Skip to content

StructuredOutput tool fails when agent wraps output in {"output": {...}} #571

@SukulMohanrajTR

Description

@SukulMohanrajTR

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)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions