Skip to content

fix(tools): Agent.model — treat empty/whitespace as omitted + clearer…#11

Merged
wusijian007 merged 1 commit into
mainfrom
fix/agent-tool-model-field
May 15, 2026
Merged

fix(tools): Agent.model — treat empty/whitespace as omitted + clearer…#11
wusijian007 merged 1 commit into
mainfrom
fix/agent-tool-model-field

Conversation

@wusijian007

Copy link
Copy Markdown
Owner

… schema doc

Observed today on real runs: both haiku and sonnet repeatedly emit junk values in the Agent tool's model field — "", "default", "sonnet", "claude" — because the JSON schema only said "Optional model name override. Uses the same provider client." with no hint about valid values or that omission is the correct default.

The empty-string case was the worst because zod rejected it with "String must contain at least 1 character", surfaced as a tool error and the model burned 2-3 tool-call retries before falling through to direct grep/read.

Two fixes:

  1. Zod schema: empty / whitespace-only strings normalize to undefined via .transform(). The sub-agent then inherits the parent's model, which is what the LLM meant 100% of the time. Non-empty bogus values like "default" still pass schema and fail loudly at the provider (model_not_found), which is the correct blast radius — the parent agent observes the failure and can pick a real ID or omit.

  2. JSON schema description: explicit "OMIT this field unless you explicitly need a different model" + valid example (claude-sonnet-4-6, claude-haiku-4-5-20251001) + enumerated anti-examples ("default", "sonnet", "claude", empty string). Strongly nudges LLMs to skip the field instead of guessing.

Tests added in agent-tools.test.ts (4 cases): empty / whitespace / tabs+newlines all parse as omitted, real model id still passes.

Local: 175 tests, 3/3 green.

… schema doc

Observed today on real runs: both haiku and sonnet repeatedly emit
junk values in the Agent tool's `model` field — "", "default",
"sonnet", "claude" — because the JSON schema only said
"Optional model name override. Uses the same provider client." with
no hint about valid values or that omission is the correct default.

The empty-string case was the worst because zod rejected it with
"String must contain at least 1 character", surfaced as a tool error
and the model burned 2-3 tool-call retries before falling through to
direct grep/read.

Two fixes:

1. Zod schema: empty / whitespace-only strings normalize to
   undefined via .transform(). The sub-agent then inherits the
   parent's model, which is what the LLM meant 100% of the time.
   Non-empty bogus values like "default" still pass schema and fail
   loudly at the provider (model_not_found), which is the correct
   blast radius — the parent agent observes the failure and can
   pick a real ID or omit.

2. JSON schema description: explicit "OMIT this field unless you
   explicitly need a different model" + valid example
   (claude-sonnet-4-6, claude-haiku-4-5-20251001) + enumerated
   anti-examples ("default", "sonnet", "claude", empty string).
   Strongly nudges LLMs to skip the field instead of guessing.

Tests added in agent-tools.test.ts (4 cases): empty / whitespace /
tabs+newlines all parse as omitted, real model id still passes.

Local: 175 tests, 3/3 green.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@wusijian007 wusijian007 merged commit fc6399c into main May 15, 2026
3 checks passed
@wusijian007 wusijian007 deleted the fix/agent-tool-model-field branch May 15, 2026 02:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant