Trim all tool docstrings to reduce token count per request

Removed verbose "Use this tool when the user asks about" bullet lists
from all 31 tools. Each tool now has a 1-2 line description plus compact
arg docs. Saves ~3-5k tokens per request on a 32k context budget.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-09-18 07:04:26 -04:00
parent 6fb9bade08
commit 64b20754a1
+85 -368
View File
@@ -96,17 +96,7 @@ except (ValueError, FileNotFoundError, Exception) as e:
@tool
def get_current_date() -> str:
"""Get today's date in a human-readable format.
Use this tool when you need to:
- Reference today's date in your response
- Answer questions like "what is today's date"
- Format dates in messages or documents
- Calculate time periods relative to today
Returns:
Today's date in YYYY-MM-DD format
"""
"""Return today's date (YYYY-MM-DD). Use whenever the current date is needed."""
from datetime import datetime
from zoneinfo import ZoneInfo
@@ -115,19 +105,10 @@ def get_current_date() -> str:
@tool
async def web_search(query: str) -> str:
"""Search the web for current information using Tavily.
Use this tool when you need to:
- Find current information not in the knowledge base
- Look up recent events, news, or updates
- Verify facts or get additional context
- Search for information outside of Simba's documents
"""Search the web for current information not in the knowledge base.
Args:
query: The search query to look up on the web
Returns:
Search results from the web with titles, content, and source URLs
query: Search query
"""
response = await client.search(query=query, search_depth="basic")
results = response.get("results", [])
@@ -146,21 +127,10 @@ async def web_search(query: str) -> str:
@tool(response_format="content_and_artifact")
async def simba_search(query: str):
"""Search through Simba's medical records, veterinary documents, and personal information.
Use this tool whenever the user asks questions about:
- Simba's health history, medical records, or veterinary visits
- Medications, treatments, or diagnoses
- Weight, diet, or physical characteristics over time
- Veterinary recommendations or advice
- Ryan's (the owner's) information related to Simba
- Any factual information that would be found in documents
"""Search Simba's medical records, vet documents, and household documents.
Args:
query: The user's question or information need about Simba
Returns:
Relevant information from Simba's documents
query: Question or information need
"""
print(f"[SIMBA SEARCH] Tool called with query: {query}")
serialized, docs = await query_vector_store(query=query, source="paperless")
@@ -172,18 +142,7 @@ async def simba_search(query: str):
@tool
def ynab_budget_summary() -> str:
"""Get overall budget summary and health status from YNAB.
Use this tool when the user asks about:
- Overall budget health or status
- How much money is to be budgeted
- Total budget amounts or spending
- General budget overview questions
Returns:
Summary of budget health, to-be-budgeted amount, total budgeted,
total activity, and available amounts.
"""
"""Get overall YNAB budget health: to-be-budgeted, total budgeted, and available amounts."""
if not ynab_enabled:
return "YNAB integration is not configured. Please set YNAB_ACCESS_TOKEN environment variable."
@@ -203,20 +162,11 @@ def ynab_search_transactions(
) -> str:
"""Search YNAB transactions by date range, category, or payee.
Use this tool when the user asks about:
- Specific transactions or purchases
- Spending at a particular store or payee
- Transactions in a specific category
- What was spent during a time period
Args:
start_date: Start date in YYYY-MM-DD format (optional, defaults to 30 days ago)
end_date: End date in YYYY-MM-DD format (optional, defaults to today)
category_name: Filter by category name (optional, partial match)
payee_name: Filter by payee/store name (optional, partial match)
Returns:
List of matching transactions with dates, amounts, categories, and payees.
start_date: YYYY-MM-DD (default: 30 days ago)
end_date: YYYY-MM-DD (default: today)
category_name: Partial match on category name
payee_name: Partial match on payee/store name
"""
if not ynab_enabled:
return "YNAB integration is not configured. Please set YNAB_ACCESS_TOKEN environment variable."
@@ -255,19 +205,10 @@ def ynab_search_transactions(
@tool
def ynab_category_spending(month: str = "") -> str:
"""Get spending breakdown by category for a specific month.
Use this tool when the user asks about:
- Spending by category
- What categories were overspent
- Monthly spending breakdown
- Budget vs actual spending for a month
"""Get YNAB spending breakdown by category, including overspent categories.
Args:
month: Month in YYYY-MM format (optional, defaults to current month)
Returns:
Spending breakdown by category with budgeted, spent, and available amounts.
month: YYYY-MM (default: current month)
"""
if not ynab_enabled:
return "YNAB integration is not configured. Please set YNAB_ACCESS_TOKEN environment variable."
@@ -303,19 +244,10 @@ def ynab_category_spending(month: str = "") -> str:
@tool
def ynab_category_allocations(month: str = "") -> str:
"""Get all category allocations showing how much is assigned and available in each category.
Use this tool when the user asks about:
- How much is budgeted or assigned to each category
- How much money is left (available) in each category
- Full category breakdown by group with balances
- Which categories are funded, empty, or overspent
"""Get all YNAB category allocations grouped by group, with assigned and available amounts.
Args:
month: Month in YYYY-MM format (optional, defaults to current month)
Returns:
All categories grouped by category group, with assigned and available amounts.
month: YYYY-MM (default: current month)
"""
if not ynab_enabled:
return "YNAB integration is not configured. Please set YNAB_ACCESS_TOKEN environment variable."
@@ -358,21 +290,10 @@ def ynab_category_allocations(month: str = "") -> str:
@tool
def ynab_insights(months_back: int = 3) -> str:
"""Generate insights about spending patterns and budget health over time.
Use this tool when the user asks about:
- Spending trends or patterns
- Budget recommendations
- Which categories are frequently overspent
- How current spending compares to past months
- Overall budget health analysis
"""Get YNAB spending trends, frequently overspent categories, and budget recommendations.
Args:
months_back: Number of months to analyze (default 3, max 6)
Returns:
Insights about spending trends, frequently overspent categories,
and personalized recommendations.
months_back: Months to analyze (default 3, max 6)
"""
if not ynab_enabled:
return "YNAB integration is not configured. Please set YNAB_ACCESS_TOKEN environment variable."
@@ -409,16 +330,7 @@ def ynab_insights(months_back: int = 3) -> str:
@tool
async def mealie_todays_meals() -> str:
"""Get today's meal plan from Mealie.
Use this tool when the user asks about:
- What's for dinner/lunch/breakfast today
- Today's meal plan
- What meals are planned for today
Returns:
Today's planned meals with recipe names and meal types.
"""
"""Get today's planned meals from Mealie."""
if not mealie_enabled:
return "Mealie integration is not configured. Please set MEALIE_BASE_URL and MEALIE_API_TOKEN environment variables."
@@ -441,19 +353,11 @@ async def mealie_todays_meals() -> str:
@tool
async def mealie_meal_plans(start_date: str = "", end_date: str = "") -> str:
"""Get meal plans for a date range from Mealie.
Use this tool when the user asks about:
- Meal plans for this week or a specific date range
- What's planned for upcoming meals
- Weekly meal schedule
"""Get Mealie meal plans for a date range.
Args:
start_date: Start date in YYYY-MM-DD format (optional, defaults to today)
end_date: End date in YYYY-MM-DD format (optional, defaults to 7 days from start)
Returns:
Meal plans organized by date.
start_date: YYYY-MM-DD (default: today)
end_date: YYYY-MM-DD (default: 7 days out)
"""
if not mealie_enabled:
return "Mealie integration is not configured. Please set MEALIE_BASE_URL and MEALIE_API_TOKEN environment variables."
@@ -484,18 +388,10 @@ async def mealie_meal_plans(start_date: str = "", end_date: str = "") -> str:
@tool
async def mealie_get_recipe(recipe_slug: str) -> str:
"""Get full recipe details from Mealie including ingredients and instructions.
Use this tool when the user asks about:
- Recipe details, ingredients, or instructions
- How to make a specific recipe
- What ingredients are needed for a meal
"""Get full recipe details (ingredients, instructions, times) from Mealie.
Args:
recipe_slug: The recipe's slug identifier (from meal plan data)
Returns:
Full recipe with ingredients, instructions, prep/cook times, and servings.
recipe_slug: Recipe slug from meal plan data
"""
if not mealie_enabled:
return "Mealie integration is not configured. Please set MEALIE_BASE_URL and MEALIE_API_TOKEN environment variables."
@@ -541,16 +437,7 @@ async def mealie_get_recipe(recipe_slug: str) -> str:
@tool
async def mealie_shopping_lists() -> str:
"""Get shopping lists and their items from Mealie.
Use this tool when the user asks about:
- What's on the shopping list
- What groceries are needed
- Shopping list items
Returns:
Shopping lists with unchecked (needed) and checked (done) items.
"""
"""Get Mealie shopping lists with needed and checked-off items."""
if not mealie_enabled:
return "Mealie integration is not configured. Please set MEALIE_BASE_URL and MEALIE_API_TOKEN environment variables."
@@ -590,22 +477,14 @@ async def mealie_create_meal_plan(
title: str = "",
note: str = "",
) -> str:
"""Create a new meal plan entry in Mealie.
Use this tool when the user wants to:
- Add a meal to the meal plan
- Plan dinner/lunch/breakfast for a specific day
- Schedule a recipe for a date
"""Add a meal to the Mealie meal plan.
Args:
date: Date in YYYY-MM-DD format
entry_type: Type of meal - breakfast, lunch, dinner, or side (default: dinner)
recipe_slug: Recipe slug to add (optional)
date: YYYY-MM-DD
entry_type: breakfast, lunch, dinner, or side (default: dinner)
recipe_slug: Recipe slug (optional)
title: Custom title if no recipe (optional)
note: Additional notes (optional)
Returns:
Confirmation of the created meal plan entry.
note: Notes (optional)
"""
if not mealie_enabled:
return "Mealie integration is not configured. Please set MEALIE_BASE_URL and MEALIE_API_TOKEN environment variables."
@@ -626,19 +505,10 @@ async def mealie_create_meal_plan(
@tool
async def obsidian_search_notes(query: str) -> str:
"""Search through Obsidian vault notes for information.
Use this tool when you need to:
- Find information in personal notes
- Research past ideas or thoughts from your vault
- Look up information stored in markdown files
- Search for content that would be in your notes
"""Search personal Obsidian vault notes.
Args:
query: The search query to look up in your Obsidian vault
Returns:
Relevant notes with their content and metadata
query: Search query
"""
if not obsidian_enabled:
return "Obsidian integration is not configured. Please set OBSIDIAN_VAULT_PATH environment variable."
@@ -654,18 +524,10 @@ async def obsidian_search_notes(query: str) -> str:
@tool
async def obsidian_read_note(relative_path: str) -> str:
"""Read a specific note from your Obsidian vault.
Use this tool when you want to:
- Read the full content of a specific note
- Get detailed information from a particular markdown file
- Access content from a known note path
"""Read the full content of a specific Obsidian note by path.
Args:
relative_path: Path to note relative to vault root (e.g., "notes/my-note.md")
Returns:
Full content and metadata of the requested note
relative_path: Path relative to vault root (e.g., "notes/my-note.md")
"""
if not obsidian_enabled:
return "Obsidian integration is not configured. Please set OBSIDIAN_VAULT_PATH environment variable."
@@ -695,21 +557,13 @@ async def obsidian_create_note(
folder: str = "notes",
tags: str = "",
) -> str:
"""Create a new note in your Obsidian vault.
Use this tool when you want to:
- Save research findings or ideas to your vault
- Create a new document with a specific title
- Write notes for future reference
"""Create a new note in the Obsidian vault.
Args:
title: The title of the note (will be used as filename)
content: The body content of the note
folder: The folder where to create the note (default: "notes")
tags: Comma-separated list of tags to add (default: "")
Returns:
Path to the created note
title: Note title (used as filename)
content: Body content
folder: Target folder (default: "notes")
tags: Comma-separated tags (optional)
"""
if not obsidian_enabled:
return "Obsidian integration is not configured. Please set OBSIDIAN_VAULT_PATH environment variable."
@@ -733,17 +587,7 @@ async def obsidian_create_note(
@tool
def journal_get_today() -> str:
"""Get today's daily journal note, including all tasks and log entries.
Use this tool when the user asks about:
- What's on their plate today
- Today's tasks or to-do list
- Today's journal entry
- What they've logged today
Returns:
The full content of today's daily note, or a message if it doesn't exist.
"""
"""Get today's full daily journal note including tasks and log entries."""
if not obsidian_enabled:
return "Obsidian integration is not configured."
@@ -758,18 +602,10 @@ def journal_get_today() -> str:
@tool
def journal_get_tasks(date: str = "") -> str:
"""Get tasks from a daily journal note.
Use this tool when the user asks about:
- Open or pending tasks for a day
- What tasks are done or not done
- Task status for today or a specific date
"""Get tasks and their completion status from a daily journal note.
Args:
date: Date in YYYY-MM-DD format (optional, defaults to today)
Returns:
List of tasks with their completion status.
date: YYYY-MM-DD (default: today)
"""
if not obsidian_enabled:
return "Obsidian integration is not configured."
@@ -799,17 +635,9 @@ def journal_get_tasks(date: str = "") -> str:
def journal_add_task(task: str, date: str = "") -> str:
"""Add a task to a daily journal note.
Use this tool when the user wants to:
- Add a task or to-do to today's note
- Remind themselves to do something
- Track a new item in their daily note
Args:
task: The task description to add
date: Date in YYYY-MM-DD format (optional, defaults to today)
Returns:
Confirmation of the added task.
task: Task description
date: YYYY-MM-DD (default: today)
"""
if not obsidian_enabled:
return "Obsidian integration is not configured."
@@ -833,17 +661,9 @@ def journal_add_task(task: str, date: str = "") -> str:
def journal_complete_task(task: str, date: str = "") -> str:
"""Mark a task as complete in a daily journal note.
Use this tool when the user wants to:
- Check off a task as done
- Mark something as completed
- Update task status in their daily note
Args:
task: The task text to mark complete (exact or partial match)
date: Date in YYYY-MM-DD format (optional, defaults to today)
Returns:
Confirmation that the task was marked complete.
task: Task text to match (exact or partial)
date: YYYY-MM-DD (default: today)
"""
if not obsidian_enabled:
return "Obsidian integration is not configured."
@@ -869,22 +689,14 @@ async def obsidian_create_task(
due_date: str = "",
tags: str = "",
) -> str:
"""Create a new task note in your Obsidian vault.
Use this tool when you want to:
- Create a task to remember to do something
- Add a task with a due date
- Track tasks in your vault
"""Create a task note in the Obsidian vault.
Args:
title: The title of the task
content: The description of the task (optional)
folder: The folder to place the task (default: "tasks")
due_date: Due date in YYYY-MM-DD format (optional)
tags: Comma-separated list of tags to add (optional)
Returns:
Path to the created task note
title: Task title
content: Description (optional)
folder: Target folder (default: "tasks")
due_date: YYYY-MM-DD (optional)
tags: Comma-separated tags (optional)
"""
if not obsidian_enabled:
return "Obsidian integration is not configured. Please set OBSIDIAN_VAULT_PATH environment variable."
@@ -909,26 +721,10 @@ async def obsidian_create_task(
@tool
async def save_user_memory(content: str, config: RunnableConfig) -> str:
"""Save a fact or preference about the user for future conversations.
Use this tool when the user:
- Explicitly asks you to remember something ("remember that...", "keep in mind...")
- Shares a personal preference that would be useful in future conversations
(e.g., "I prefer metric units", "my cat's name is Luna")
- Tells you a meaningful personal fact (e.g., "I'm allergic to peanuts")
Do NOT save:
- Trivial or ephemeral info (e.g., "I'm tired today")
- Information already in the system prompt or documents
- Conversation-specific context that won't matter later
"""Save a persistent fact or preference about the user for future conversations. Only use when user explicitly asks to remember something or shares a durable preference.
Args:
content: A concise statement of the fact or preference to remember.
Write it as a standalone sentence (e.g., "User prefers dark mode"
rather than "likes dark mode").
Returns:
Confirmation that the memory was saved.
content: Standalone statement to remember (e.g., "User prefers metric units")
"""
user_id = config["configurable"]["user_id"]
return await save_memory(user_id=user_id, content=content)
@@ -942,21 +738,12 @@ async def get_calendar_events(
*,
config: RunnableConfig,
) -> str:
"""Get upcoming Google Calendar events including all-day events.
Use this tool when the user asks about:
- What's on their calendar today or this week
- Upcoming meetings or events
- Scheduling or availability questions
"""Get Google Calendar events.
Args:
time_range: One of "today", "tomorrow", or "week" (default: "today")
days: If set to a positive number, show events for this many upcoming days
(overrides time_range)
calendar_id: Calendar ID to query (default: "primary")
Returns:
Formatted list of calendar events with times, titles, and locations.
time_range: "today", "tomorrow", or "week" (default: "today")
days: Number of upcoming days to show (overrides time_range if > 0)
calendar_id: Calendar ID (default: "primary")
"""
if not config["configurable"].get("is_admin"):
return "Calendar access is restricted to admin users."
@@ -1021,23 +808,15 @@ async def create_calendar_event(
*,
config: RunnableConfig,
) -> str:
"""Create a new Google Calendar event.
Use this tool when the user wants to:
- Schedule a meeting or appointment
- Add an event to their calendar
- Block time on their calendar
"""Create a Google Calendar event.
Args:
summary: Event title
start_time: Start time in RFC3339 format (e.g. "2026-09-16T14:00:00-04:00")
end_time: End time in RFC3339 format
description: Event description (optional)
location: Event location (optional)
calendar_id: Calendar to add event to (default: "primary")
Returns:
Confirmation with the event link.
start_time: RFC3339 start time (e.g. "2026-09-16T14:00:00-04:00")
end_time: RFC3339 end time
description: Description (optional)
location: Location (optional)
calendar_id: Calendar ID (default: "primary")
"""
if not config["configurable"].get("is_admin"):
return "Calendar access is restricted to admin users."
@@ -1064,19 +843,11 @@ async def gmail_search_emails(
*,
config: RunnableConfig,
) -> str:
"""Search Gmail messages using Gmail search syntax.
Use this tool when the user asks about:
- Finding emails from a specific sender or about a topic
- Recent emails, unread messages, or emails in a label
- Whether they received an email about something
"""Search Gmail using Gmail search syntax.
Args:
query: Gmail search query (e.g. "from:bank unread", "subject:invoice", "after:2026/09/01")
max_results: Maximum number of results to return (default: 10)
Returns:
List of matching emails with sender, subject, date, and snippet.
query: Gmail search query (e.g. "from:bank unread", "subject:invoice")
max_results: Max results (default: 10)
"""
if not config["configurable"].get("is_admin"):
return "Gmail access is restricted to admin users."
@@ -1102,17 +873,10 @@ async def gmail_get_email(
*,
config: RunnableConfig,
) -> str:
"""Get the full content of a Gmail message by ID.
Use this tool when the user wants to:
- Read a specific email
- Get full details of an email found by gmail_search_emails
"""Get the full content of a Gmail message by ID (from gmail_search_emails results).
Args:
message_id: The message ID from gmail_search_emails results
Returns:
Full email content including headers and body.
message_id: Message ID
"""
if not config["configurable"].get("is_admin"):
return "Gmail access is restricted to admin users."
@@ -1130,17 +894,7 @@ async def gmail_get_email(
@tool
async def simbakit_device_status() -> str:
"""Get the status of all PetKit smart devices and any active alerts.
Use this tool when the user asks about:
- PetKit device statuses or health
- Whether any pet devices have issues or alerts
- Litter box, water fountain, or feeder device status
- Any device errors or warnings
Returns:
Device statuses and active alerts from all PetKit devices.
"""
"""Get PetKit smart device statuses and active alerts (litter box, fountain, feeder)."""
if not simbakit_enabled:
return "SimbaKit integration is not configured. Please set SIMBAKIT_URL environment variable."
@@ -1154,19 +908,11 @@ async def simbakit_device_status() -> str:
@tool
async def simbakit_weight_history(pet_name: str = "", days: int = 30) -> str:
"""Get pet weight history and trends from PetKit smart litter box.
Use this tool when the user asks about:
- How much Simba weighs or pet weight
- Weight trends or changes over time
- Recent weight measurements
"""Get pet weight history and trends from the PetKit litter box.
Args:
pet_name: Name of the pet to filter by (optional, defaults to all pets)
days: Number of days of history to retrieve (default 30)
Returns:
Weight records, averages, and trends.
pet_name: Pet name filter (optional)
days: Days of history (default 30)
"""
if not simbakit_enabled:
return "SimbaKit integration is not configured. Please set SIMBAKIT_URL environment variable."
@@ -1182,20 +928,11 @@ async def simbakit_weight_history(pet_name: str = "", days: int = 30) -> str:
@tool
async def simbakit_litter_activity(pet_name: str = "", days: int = 7) -> str:
"""Get litter box activity (bathroom visits) from PetKit smart litter box.
Use this tool when the user asks about:
- Simba's litter box usage or bathroom habits
- How often the cat poops or pees
- Litter box visit statistics
- Recent litter box events
"""Get litter box visit statistics and recent events from PetKit.
Args:
pet_name: Name of the pet to filter by (optional, defaults to all pets)
days: Number of days of history to retrieve (default 7)
Returns:
Litter box visit statistics and recent events.
pet_name: Pet name filter (optional)
days: Days of history (default 7)
"""
if not simbakit_enabled:
return "SimbaKit integration is not configured. Please set SIMBAKIT_URL environment variable."
@@ -1211,20 +948,11 @@ async def simbakit_litter_activity(pet_name: str = "", days: int = 7) -> str:
@tool
async def simbakit_drinking_activity(pet_name: str = "", days: int = 7) -> str:
"""Get water fountain drinking activity from the PetKit smart water fountain.
Use this tool when the user asks about:
- How much water Simba is drinking or hydration
- Water fountain usage or visits
- Drinking habits, frequency, or trends
- Recent drinking sessions
"""Get water fountain drinking activity and session stats from PetKit.
Args:
pet_name: Name of the pet to filter by (optional, defaults to all pets)
days: Number of days of history to retrieve (default 7)
Returns:
Drinking session statistics and recent fountain events.
pet_name: Pet name filter (optional)
days: Days of history (default 7)
"""
if not simbakit_enabled:
return "SimbaKit integration is not configured. Please set SIMBAKIT_URL environment variable."
@@ -1321,27 +1049,16 @@ async def beli_search_restaurants(
category: str = "",
friends_only: bool = False,
) -> str:
"""Search restaurant, bar, cafe, and bakery recommendations from Beli profiles.
Use this tool when the user asks about:
- Restaurant, bar, cafe, or bakery recommendations
- Places they've been to or want to try
- Dining or drinks recommendations in a specific city or cuisine
- What places their friends have rated on Beli
"""Search Beli restaurant, bar, cafe, and bakery rankings.
Args:
status: Filter by status — 'been' (ranked places) or 'want_to_try' (bookmarks). Leave blank for all.
city: Filter by city name (partial match). Leave blank for all cities.
cuisine: Filter by cuisine type (partial match). Leave blank for all cuisines.
name: Filter by place name (partial match). Leave blank for all.
category: Filter by type — 'restaurant', 'bar', 'cafe', 'bakery', 'dessert'. Leave blank for all.
IMPORTANT: When the user asks for "restaurants", "top restaurants", or "places to eat",
always pass category='restaurant'. Only leave blank when the user explicitly wants all types.
friends_only: Set True when the user specifically asks what their friends like or recommend.
False (default) returns the user's own rankings only.
Returns:
Formatted list of matching places with ratings, type, location, and attribution.
status: 'been' or 'want_to_try' (default: all)
city: City filter (partial match)
cuisine: Cuisine filter (partial match)
name: Name filter (partial match)
category: 'restaurant', 'bar', 'cafe', 'bakery', or 'dessert'. IMPORTANT: pass
category='restaurant' when user asks for restaurants or places to eat.
friends_only: True when user asks what friends like/recommend; False for own rankings.
"""
from blueprints.beli.models import BeliRestaurant, BeliStatus