perf(prompts): trim tool schema descriptions to reduce prompt token count

Removes verbose redundant text from tool descriptions and system prompt
guidance: multi-line recurrence_rule JSON examples, CAPS warnings that
duplicate system prompt instructions, and wordy descriptions that don't
add model understanding.

Saves ~990 tokens per request (~17% reduction, 5,639 → ~4,650 tokens),
reducing prefill time on cache misses and lowering KV memory pressure.
No functional changes — parameter names, types, enums, and required
fields are unchanged.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-03 11:01:05 -04:00
parent c9065c4481
commit a6888953dc
2 changed files with 19 additions and 72 deletions
+4 -11
View File
@@ -508,17 +508,10 @@ async def build_context(
"next line. Never describe images as text or list their URLs — always render them as markdown images."
)
tool_lines.append(
"Use update_note to edit/expand an existing note OR to update a task's status/priority/due_date. "
"Use create_note ONLY for genuinely new notes with a different title. "
"Use list_tasks to find tasks by status, priority, or due date (e.g. overdue, high priority, in progress). "
"If a note was created earlier in the conversation and the user provides more content for it, use update_note. "
"Use get_note to read the full content of a specific note. "
"Use list_notes to browse notes by recency or tag. "
"Use search_notes for conceptual/semantic queries — e.g. 'what notes do I have about X' or "
"'find notes related to Y' — it uses semantic understanding to find thematically related content "
"even when exact words don't match. Pass project= to scope the search to a specific project. "
"Use delete_note / delete_task only when explicitly asked to delete — these require confirmation. "
"Never proactively search notes or comment on the absence of notes/context unless the user explicitly asks about their notes."
"Use update_note for existing notes/tasks; use create_note only for new content. "
"Use search_notes for semantic/conceptual queries. "
"Delete tools require an explicit user request. "
"Never proactively search notes or comment on absent context."
)
tool_guidance = "\n".join(tool_lines)
+15 -61
View File
@@ -107,16 +107,7 @@ _CORE_TOOLS = [
},
"recurrence_rule": {
"type": "object",
"description": (
"Optional recurrence schedule so the task repeats automatically. Two forms:\n"
" Interval — repeat every N units from the due date:\n"
' {"type": "interval", "every": 3, "unit": "month"}\n'
" unit options: day | week | month | year\n"
" Calendar/monthly — specific day each month:\n"
' {"type": "calendar", "unit": "month", "day_of_month": 1}\n'
" Calendar/annual — specific day each year:\n"
' {"type": "calendar", "unit": "year", "day_of_month": 15, "month": 6}'
),
"description": 'Optional recurrence. Interval form: {"type":"interval","every":3,"unit":"month"} (units: day/week/month/year). Calendar form: {"type":"calendar","unit":"month","day_of_month":1}. Annual: add "month":6.',
},
},
"required": ["title"],
@@ -161,12 +152,7 @@ _CORE_TOOLS = [
"type": "function",
"function": {
"name": "update_note",
"description": (
"Update an existing note or task — content, title, status, priority, or due date. "
"Use this when the user asks to add to, edit, expand, or modify a note, "
"OR to mark a task done/in-progress, change its priority, or set a due date. "
"NEVER use create_note when updating an existing note — always use update_note."
),
"description": "Update an existing note or task — content, title, status, priority, or due date. Use for edits, marking tasks done, changing priority. Never use create_note for existing notes.",
"parameters": {
"type": "object",
"properties": {
@@ -220,10 +206,7 @@ _CORE_TOOLS = [
},
"recurrence_rule": {
"type": "object",
"description": (
"Set or update the recurrence schedule. Pass null to remove recurrence. "
"Same format as create_task recurrence_rule."
),
"description": "Set or update recurrence (same format as create_task). Pass null to remove.",
},
},
"required": ["query"],
@@ -234,13 +217,7 @@ _CORE_TOOLS = [
"type": "function",
"function": {
"name": "search_notes",
"description": (
"Search notes and tasks using semantic understanding. Finds content related to a concept, "
"theme, or topic — even when exact keywords don't appear in the title or body. "
"Use this when the user asks what notes they have about a topic, wants to explore related "
"content, or is looking for something they've written. Falls back to keyword search "
"automatically if semantic search is unavailable."
),
"description": "Search notes and tasks by semantic meaning — finds content by concept or theme even when exact keywords don't appear.",
"parameters": {
"type": "object",
"properties": {
@@ -363,12 +340,7 @@ _CORE_TOOLS = [
"type": "function",
"function": {
"name": "list_tasks",
"description": (
"List the user's tasks with optional filters. Use this when the user asks about their tasks "
"by status (e.g. 'what's in progress'), priority (e.g. 'high priority tasks'), "
"or due date (e.g. 'overdue tasks', 'due this week'). "
"For 'overdue', set due_before to today's date. For 'due today', set due_after to today and due_before to tomorrow."
),
"description": "List tasks with optional filters. For overdue tasks, set due_before to today's date.",
"parameters": {
"type": "object",
"properties": {
@@ -378,11 +350,7 @@ _CORE_TOOLS = [
"type": "string",
"enum": ["todo", "in_progress", "done", "cancelled"],
},
"description": (
"Filter by one or more task statuses. "
'Example: ["todo", "in_progress"] to list all active tasks. '
"Omit to return tasks of any status."
),
"description": "Filter by one or more statuses. Omit for all.",
},
"priority": {
"type": "string",
@@ -417,7 +385,7 @@ _CORE_TOOLS = [
"type": "function",
"function": {
"name": "create_project",
"description": "Create a brand-new project. IMPORTANT: NEVER call this because a project name was not found — always use list_projects first to confirm no similar project exists. Only call this when the user has explicitly asked to create a new project AND confirmed it. Call with confirmed=true only after the user has explicitly approved. The system will block creation if any project with a similar name already exists.",
"description": "Create a new project. Use list_projects first to check for duplicates. Only call after user has explicitly confirmed.",
"parameters": {
"type": "object",
"properties": {
@@ -482,7 +450,7 @@ _CORE_TOOLS = [
"type": "function",
"function": {
"name": "create_milestone",
"description": "Create a new milestone inside a project. IMPORTANT: You MUST ask the user to confirm the milestone name and which project it belongs to before calling this tool. Only call with confirmed=true after the user has explicitly approved creation.",
"description": "Create a milestone inside a project. Confirm name and project with user before calling.",
"parameters": {
"type": "object",
"properties": {
@@ -569,10 +537,7 @@ _CORE_TOOLS = [
"properties": {
"location": {
"type": "string",
"description": (
"City, region, or country to look up — e.g. 'Portland, Oregon', 'Tokyo', 'home', 'work'. "
"Use 'home' or 'work' to get the user's saved locations. Omit for all saved locations."
),
"description": "City/region to look up, or 'home'/'work' for saved locations. Omit for all saved.",
},
"days": {
"type": "integer",
@@ -614,11 +579,7 @@ _CORE_TOOLS = [
"type": "function",
"function": {
"name": "add_rss_feed",
"description": (
"Add a new RSS feed to the user's briefing. Use this when the user asks to "
"subscribe to, follow, add, or track a feed, blog, news source, subreddit, or podcast URL. "
"The feed will be fetched immediately after adding."
),
"description": "Add an RSS/Atom feed. Use when user asks to subscribe to or track a feed, blog, subreddit, or podcast.",
"parameters": {
"type": "object",
"properties": {
@@ -645,15 +606,15 @@ _CORE_TOOLS = [
"properties": {
"title": {
"type": "string",
"description": "A descriptive event title (e.g. 'John's Birthday' not just 'Birthday')",
"description": "A descriptive event title",
},
"start": {
"type": "string",
"description": "Start date (YYYY-MM-DD for all-day) or datetime (ISO 8601, e.g. 2025-01-15T14:00:00)",
"description": "Start date (YYYY-MM-DD) or datetime (ISO 8601 with timezone offset)",
},
"end": {
"type": "string",
"description": "Optional end date or datetime in same format as start",
"description": "Optional end date or datetime",
},
"duration": {
"type": "integer",
@@ -673,7 +634,7 @@ _CORE_TOOLS = [
},
"all_day": {
"type": "boolean",
"description": "Set to true for all-day events like birthdays, holidays, deadlines (default false)",
"description": "True for all-day events (birthdays, holidays, deadlines)",
},
"recurrence": {
"type": "string",
@@ -874,14 +835,7 @@ _IMAGE_TOOLS = [
"type": "function",
"function": {
"name": "search_images",
"description": (
"Search the web for images and display them inline in the response. "
"ONLY use this when the user explicitly asks to SEE, SHOW, VIEW, or DISPLAY "
"an image or photo — e.g. 'show me a picture of X', 'what does X look like', "
"'find a photo of X', 'display an image of X'. "
"Do NOT use for general descriptions, factual questions, or when the user just "
"wants information without visual content. Returns at most 2 images."
),
"description": "Search and display images inline. Use ONLY when user explicitly asks to see or show an image or photo. Not for factual questions.",
"parameters": {
"type": "object",
"properties": {