[codex] fix nested MCP schema conversion#130
Open
117503445 wants to merge 1 commit into
Open
Conversation
21e59b7 to
84dfaf2
Compare
f1b5947 to
dbda29b
Compare
Signed-off-by: 黑曜 <haotian.qht@alibaba-inc.com>
dbda29b to
5e62dbd
Compare
Contributor
There was a problem hiding this comment.
Pull request overview
This PR fixes JSON Schema → Pydantic conversion issues in the LangChain adapter path so that nested MCP object schemas (especially anyOf/$ref wrappers) remain objects after the second conversion, and recursive $ref graphs no longer crash during model construction.
Changes:
- Thread the root schema and add
$ref-tracking/caching to_json_schema_to_pydantic/_json_type_to_pythonto correctly resolve deep$defsreferences and avoid exponential expansion. - Add
$ref-cycle protection so self-referential schemas degrade gracefully instead of raising recursion errors. - Add regression tests covering nested optional objects,
anyOf + $refwrappers, recursive and shared$reftopologies, and reachable-ref caching.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
agentrun/integration/utils/tool.py |
Threads root schema + adds ref-cycle guard and caching to preserve nested object typing across conversions. |
tests/unittests/integration/test_tool_utils.py |
Adds regression coverage for nested object round-trips and multiple $ref recursion/caching scenarios. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+2035
to
+2043
| if root_schema is not None and ( | ||
| "anyOf" in field_schema | ||
| or "oneOf" in field_schema | ||
| or "allOf" in field_schema | ||
| or "$ref" in field_schema | ||
| ): | ||
| core_schema, _ = _extract_core_schema(field_schema, root_schema) | ||
| if core_schema: | ||
| field_schema = core_schema |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
_json_schema_to_pydantic/_json_type_to_pythonso deepanyOf/$refwrappers can resolve$defs.anyOf+$refschemas, and recursive$refschemas that should not crash.Root Cause
Optional nested object fields are represented by Pydantic as
anyOf: [{"$ref": ...}, {"type": "null"}]. The second JSON Schema to Pydantic conversion in the LangChain adapter previously passed those nested field schemas into_json_type_to_pythonwithout the root schema, and_json_type_to_pythondefaulted schemas without a top-leveltypetostring. That downgraded nested MCP objects intostring | null.The fix resolves wrapped schema fragments against the root schema and tracks active
$refentries while recursively constructing Pydantic models, so self-referential schemas degrade todictat the recursive edge instead of raisingRecursionError.Validation
.venv/bin/python -m pytest tests/unittests/integration/test_tool_utils.py::TestNestedObjectRoundTrip -q.venv/bin/python -m pytest tests/unittests/integration/test_tool_utils.py -q