Skip to content

Python: fix(claude): preserve $defs in JSON schema for nested Pydantic models - #3655

Merged
Evan Mattson (moonbox3) merged 3 commits into
microsoft:mainfrom
droideronline:fix/claude-agent-preserve-schema-defs
Feb 4, 2026
Merged

Python: fix(claude): preserve $defs in JSON schema for nested Pydantic models#3655
Evan Mattson (moonbox3) merged 3 commits into
microsoft:mainfrom
droideronline:fix/claude-agent-preserve-schema-defs

Conversation

@droideronline

Copy link
Copy Markdown
Contributor

Summary

This PR fixes a bug where _function_tool_to_sdk_mcp_tool() dropped the $defs section from Pydantic JSON schemas, breaking any tool that uses nested Pydantic models.

Problem

When converting a FunctionTool to an SDK MCP tool, the code was only extracting properties and required from the Pydantic model's JSON schema, but dropping the $defs section which contains definitions for nested types:

input_schema: dict[str, Any] = {
    "type": "object",
    "properties": schema.get("properties", {}),
    "required": schema.get("required", []),
}
# $defs was not being preserved!

This caused tools with nested Pydantic models to produce invalid/unresolvable JSON schemas. The schema would contain $ref references like "$ref": "#/$defs/SomeNestedType" but the $defs section was missing, so Claude could not resolve the type and refused to call the tool.

Changes

_agent.py

  • Preserve $defs section from Pydantic JSON schema when present:
    if "$defs" in schema:
        input_schema["$defs"] = schema["$defs"]

test_claude_agent.py

  • Added test_function_tool_to_sdk_mcp_tool_preserves_defs_for_nested_types - verifies that nested Pydantic models generate schemas with $defs preserved

Testing

All 45 tests pass:

pytest tests/test_claude_agent.py -v
============================== 45 passed in 0.31s ==============================

Fixes #3654

Copilot AI review requested due to automatic review settings February 3, 2026 20:28
@markwallace-microsoft Mark Wallace (markwallace-microsoft) added the python Usage: [Issues, PRs], Target: Python label Feb 3, 2026
@github-actions github-actions Bot changed the title fix(claude): preserve $defs in JSON schema for nested Pydantic models Python: fix(claude): preserve $defs in JSON schema for nested Pydantic models Feb 3, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes the Claude agent’s FunctionTool → SDK MCP conversion so that Pydantic nested models produce valid JSON schemas by preserving the $defs section, and adds a regression test to prevent regressions for nested types.

Changes:

  • Updated _function_tool_to_sdk_mcp_tool to carry over the $defs section from the Pydantic model’s model_json_schema() into the MCP tool input schema.
  • Added a dedicated test ensuring that tools with nested Pydantic models have $defs preserved and that the top-level property referencing the nested model is present.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
python/packages/claude/agent_framework_claude/_agent.py Extends the generated MCP input schema to include $defs from the underlying Pydantic schema so nested $ref types resolve correctly.
python/packages/claude/tests/test_claude_agent.py Adds a regression test using nested Pydantic models to verify that $defs is preserved and that the nested model reference appears in properties.

@markwallace-microsoft

Mark Wallace (markwallace-microsoft) commented Feb 4, 2026

Copy link
Copy Markdown
Contributor

Python Test Coverage

Python Test Coverage Report •
FileStmtsMissCoverMissing
packages/core/agent_framework
   _tools.py7697690%226, 272, 323, 325, 353, 523, 558–559, 661, 663, 683, 701, 715, 727, 732, 734, 741, 774, 845–847, 888, 913–922, 928–937, 973, 981, 1222, 1559, 1646–1650, 1672–1673, 1789, 1791, 1857, 1949, 1955, 1997–1998, 2011–2012, 2055, 2139, 2177–2178, 2217–2219, 2257–2258, 2268, 2325–2326, 2333–2334
TOTAL16338198287% 

Python Unit Test Overview

Tests Skipped Failures Errors Time
3822 221 💤 0 ❌ 0 🔥 1m 9s ⏱️

@droideronline

Copy link
Copy Markdown
Contributor Author

Evan Mattson (@moonbox3) - Can we have please have a look at this ?

- Preserve $defs section from Pydantic JSON schema when converting FunctionTool to SDK MCP tool
- This fixes tools with nested Pydantic models that use $ref references
- Add test for nested type schema preservation

Fixes microsoft#3654
@moonbox3

Copy link
Copy Markdown
Contributor

I need to get another PR merged that fixes a bug, and thus allows the failing unit test to pass.

@droideronline
Dineshsuriya D (droideronline) force-pushed the fix/claude-agent-preserve-schema-defs branch from b33d823 to e8d3930 Compare February 4, 2026 05:46
@droideronline

Copy link
Copy Markdown
Contributor Author

I need to get another PR merged that fixes a bug, and thus allows the failing unit test to pass.

sure, I just cherry-picked your test failure fixes here

@moonbox3
Evan Mattson (moonbox3) added this pull request to the merge queue Feb 4, 2026
Merged via the queue into microsoft:main with commit 5c6cf4f Feb 4, 2026
23 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

python Usage: [Issues, PRs], Target: Python

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Python: [Bug]: _function_tool_to_sdk_mcp_tool drops $defs from Pydantic JSON schemas, breaking tools with nested types

5 participants