Existing Issue - #532
Summary
When using output_format with the Claude Agent SDK, the agent sometimes wraps its JSON output in
{"output": {...}} instead of providing the data directly. This causes schema validation to fail because
the CLI validates at the root level, finding only an output key instead of the expected schema
properties.
Environment
- claude-agent-sdk version: 0.1.35
- Claude CLI version: 2.1.41
- Python version: 3.11
Description
When configuring structured output via ClaudeAgentOptions.output_format, the agent calls the
StructuredOutput tool to provide validated JSON. However, the agent inconsistently wraps its output:
Failing case :
{
"output": {
"as": 4,
"xs": "xzy",
...
}
}
Error returned:
Output does not match required schema: root: must have required property 'as',
root: must have required property 'xs', ...
Succeeding case :
{
"as": 2,
"xs": "zxa",
...
}
Result: Structured output provided successfully
Observed Behavior
1. Agent calls StructuredOutput tool with wrapped JSON {"output": {...}}
2. CLI validates against schema at root level
3. Validation fails because root has only output key, not schema-required properties
4. Tool returns is_error=True with validation error message
5. Agent retries multiple times, eventually hitting error_max_structured_output_retries
6. ResultMessage.structured_output is None
Expected Behavior
Either:
1. CLI should unwrap the {"output": {...}} wrapper before validation (if this is a known pattern), OR
2. Agent should be instructed by the CLI/SDK to never use wrapper keys, OR
3. SDK should handle the unwrapping on the client side before returning structured_output
Related Issues
- PR #532 addressed wrapper key issues and stringified JSON in structured output
- The fix in PR #532 may not fully cover this case where the agent itself generates the wrapper
Reproduction
from claude_agent_sdk import ClaudeAgentOptions, ClaudeSDKClient
from pydantic import BaseModel, Field
class MyOutput(BaseModel):
change_number: int = Field(description="as")
form_name: str = Field(description="xs")
options = ClaudeAgentOptions(
output_format={
"type": "json_schema",
"schema": MyOutput.model_json_schema()
}
)
async with ClaudeSDKClient(options) as client:
await client.send_query("Analyze this form change and provide structured output")
async for message in client.receive_response():
if isinstance(message, ResultMessage):
# structured_output may be None if agent wrapped in {"output": {...}}
print(message.structured_output)
Existing Issue - #532
Summary
When using
output_formatwith the Claude Agent SDK, the agent sometimes wraps its JSON output in{"output": {...}}instead of providing the data directly. This causes schema validation to fail becausethe CLI validates at the root level, finding only an
outputkey instead of the expected schemaproperties.
Environment
Description
When configuring structured output via
ClaudeAgentOptions.output_format, the agent calls theStructuredOutputtool to provide validated JSON. However, the agent inconsistently wraps its output:Failing case :
{ "output": { "as": 4, "xs": "xzy", ... } } Error returned: Output does not match required schema: root: must have required property 'as', root: must have required property 'xs', ... Succeeding case : { "as": 2, "xs": "zxa", ... } Result: Structured output provided successfully Observed Behavior 1. Agent calls StructuredOutput tool with wrapped JSON {"output": {...}} 2. CLI validates against schema at root level 3. Validation fails because root has only output key, not schema-required properties 4. Tool returns is_error=True with validation error message 5. Agent retries multiple times, eventually hitting error_max_structured_output_retries 6. ResultMessage.structured_output is None Expected Behavior Either: 1. CLI should unwrap the {"output": {...}} wrapper before validation (if this is a known pattern), OR 2. Agent should be instructed by the CLI/SDK to never use wrapper keys, OR 3. SDK should handle the unwrapping on the client side before returning structured_output Related Issues - PR #532 addressed wrapper key issues and stringified JSON in structured output - The fix in PR #532 may not fully cover this case where the agent itself generates the wrapper Reproduction from claude_agent_sdk import ClaudeAgentOptions, ClaudeSDKClient from pydantic import BaseModel, Field class MyOutput(BaseModel): change_number: int = Field(description="as") form_name: str = Field(description="xs") options = ClaudeAgentOptions( output_format={ "type": "json_schema", "schema": MyOutput.model_json_schema() } ) async with ClaudeSDKClient(options) as client: await client.send_query("Analyze this form change and provide structured output") async for message in client.receive_response(): if isinstance(message, ResultMessage): # structured_output may be None if agent wrapped in {"output": {...}} print(message.structured_output)