Skip to content

fix(cli): let Agent Manager tool fields be null so strict providers can omit them - #13206

Merged
marius-kilocode merged 3 commits into
mainfrom
fix-agent-manager-nullable-wire-fields
Aug 19, 2026
Merged

fix(cli): let Agent Manager tool fields be null so strict providers can omit them#13206
marius-kilocode merged 3 commits into
mainfrom
fix-agent-manager-nullable-wire-fields

Conversation

@marius-kilocode

Copy link
Copy Markdown
Collaborator

Fixes #13029.

The agent_manager tool advertises one flat object covering both starting sessions and managing existing ones. That flat shape is required: Anthropic rejects a tool whose input_schema has a top-level anyOf, oneOf, or allOf, and since the tool sorts to tools[0] whenever KILO_CLIENT=vscode, a rejected schema fails the entire request rather than just that tool call. #13197 tried a discriminated union and had to be reverted in #13203 for exactly this reason.

The cost of flattening is that providers enforcing strict structured outputs, notably the OpenAI Responses API, must supply a value for every advertised property. None of the fields accepted null, so a model starting a worktree session had no way to decline action and was forced to invent a value. The invented action then took precedence over mode and tasks, so the tool returned an overview of existing sessions and no session was created. Reproduced on gpt-5.6-sol, which sends:

{"mode":"worktree","versions":false,"tasks":[{"prompt":"write a haiku","name":"probe","branchName":"probe-branch","model":"","variant":""}],
 "action":"list","filter":null,"sessionID":"","prompt":"write a haiku","sectionID":null}

Every advertised field is now nullable, so null is how a model states that a field is not part of the operation it chose, and the per-field descriptions say when to use it. The runtime already resolved action: null to a start request, so only the advertised schema changes here. The five-branch Params union remains the authoritative validator and its behavior is unchanged.

Two incidental cleanups in the same schema: versions and filter were double-wrapped in Schema.optional, which emitted a redundant nested anyOf. Both are now flat. The tasks bounds of 1 to 20 are preserved through the nullable wrapper.

This does not reintroduce strict rejection of mixed payloads. A model that still sends a populated action alongside mode and tasks continues to be routed by action. Turning that case into an explicit error is worthwhile but is a separate behavior change, tracked in #13205 along with the systemic Anthropic normalization in ProviderTransform.schema from #12905.

Also adds test/kilocode/tool-schema-provider-compat.test.ts, which walks every advertised tool and asserts an object root with no top-level combinator. It lives outside any single tool's test file and is phrased as a cross-tool invariant on purpose: this break shipped twice, and the second time the per-tool assertion protecting it was rewritten in the same diff that broke the shape, so CI stayed green. Confirmed the guard fails against the reverted-away schema before relying on it.

@marius-kilocode
marius-kilocode merged commit 20e14cf into main Aug 19, 2026
31 checks passed
@marius-kilocode
marius-kilocode deleted the fix-agent-manager-nullable-wire-fields branch August 19, 2026 10:14
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.

agent_manager start becomes list under strict Responses API tool calling

2 participants