Repository navigation
Python: fix(core): serialize Pydantic tool results in JSON mode - #9036
Anish Mehta (anishmehta24) wants to merge 8 commits into
Conversation
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
/review |
There was a problem hiding this comment.
MAF Automated Review — Iteration 1
Result: Findings reported
Scope: full PR (1 commit(s)): 4ba0a5cfbd3d
Model: gpt-5.6-sol
Overview
The PR correctly targets Pydantic's JSON-mode conversions and adds a focused regression test for enums and datetimes, while retaining the existing paths for strings, Content, and non-Pydantic values. However, JSON mode can reject otherwise valid Pydantic models, and the normal invocation fallback then exposes the model's raw string representation, including excluded fields. This creates a concrete credential-disclosure path and breaks direct serialization callers.
Reviewed the supplied pull-request change set across correctness, security/reliability, architecture, and failure behavior.
1 verified finding remained after source verification (1 high) across 1 file. Details are attached to the affected lines below.
Affected areas: python/packages/core/agent_framework/_tools.py
|
Anish Mehta (@anishmehta24) Could you add the related issue this fixes, or briefly document why this qualifies for the trivial-change exception? The current body does not answer that required template field. |
|
There is no issue for this one. I filled in the trivial-change exception under Related Issue (one-line fix with a repro and a regression test), and added the AI Assistance section. |
…s fallback where Pydantic supports it
Eduard van Valkenburg (eavanvalkenburg)
left a comment
There was a problem hiding this comment.
Anish Mehta (@anishmehta24) I found two remaining blocking serialization gaps on the current head:
python/packages/core/agent_framework/_tools.py:1285: on supported Pydantic 2.0.x,type(model).model_computed_fieldsis a class property rather than an iterable. If JSON dumping enters this fallback, it raisesTypeError;FunctionTool.invokecan then fall back tostr(result), which can include values from fields markedexclude=True.python/packages/core/agent_framework/_tools.py:1291-1295: the fallback recurses only when the field itself is aBaseModel. Alist[BaseModel]ordict[str, BaseModel]falls back in Python mode as a whole, bypassing nested JSON-only serializers and potentially emitting raw values.
Please make computed-field enumeration version-safe and recursively preserve JSON-mode serializers and exclusions inside model containers, with regressions for Pydantic 2.0.x and nested model lists/maps.
… models in lists and dicts
|
Eduard van Valkenburg (@eavanvalkenburg) both fixed in 4295bcd.
Added tests for a computed field on the fallback path and for |
|
please resolve the comments Anish Mehta (@anishmehta24) |
…antic-json-mode # Conflicts: # python/packages/core/agent_framework/_tools.py
…s invalid UTF-8 bytes
Motivation & Context
A tool that returns a Pydantic model is serialized with
model_dump()and thenjson.dumps(default=str), so enum and datetime fields come out as their Pythonstr():The model gets
Status.OPENback from a tool whose own input schema uses"open".Description & Review Guide
_make_dumpabledumpsBaseModelvalues in JSON mode (model_dump(mode="json"), withfallback=stron Pydantic versions that have it, like_mcp.py). If JSON mode fails for a model (bytes that aren't valid UTF-8, or an arbitrary type on Pydantic < 2.11), each field is dumped in JSON mode on its own and only the failing field falls back, so JSON-only serializers andexclude=Truestill apply to the rest. A failing field with its own serializer is retried with its invalid UTF-8 bytes escaped, and left out if it still can't be encoded.FunctionTool._dump_model. Models that JSON mode can encode never reach it.Related Issue
N/A - trivial change: a bug fix in
_make_dumpable(Pydantic tool results dumped in JSON mode). The repro is above and the PR adds a regression test that fails on main.AI Assistance
AI assistance details: implementation, tests and this description.
Contribution Checklist
breaking changelabel (or add "[BREAKING]" to the title prefix, before or after any language prefix) — a workflow keeps the label and title prefix in sync automatically.Test:
test_parse_result_pydantic_model_uses_json_modeinpackages/core/tests/core/test_types.py; it fails on main. Theparse_resulttests pass (22 passed) on pydantic 2.0.3, 2.10.6 and 2.14.1. In the core suite the only failures locally are MCP tests (nomcppackage in my env),test_declared_feature_indexes_match_registryand the aiohttp invocation tests, which fail the same way on main here. ruff check/format clean.