weiqingy opened a new pull request, #1046: URL: https://github.com/apache/flink-agents/pull/1046
Linked issue: #985 ### Purpose of change An output schema that cannot be rendered as JSON Schema fails opaquely. Python leaks a raw `PydanticInvalidForJsonSchema` naming a pydantic-internal type, never the caller's model. Java throws past a catch clause too narrow to see it. Per the decision on the issue, such a schema is now refused with a clear, cause-chained error naming the schema. `RowTypeInfo` stays a fallback and is documented as one on the public `chat` contract, which previously said nothing about how a connection treats each kind of schema. A schema that renders but constrains nothing is refused only on the ReAct path, where the rendered document is pasted verbatim into the prompt, so an empty one tells the model to match nothing. At a connection it is a wire format the provider may accept, and it is passed through as before. **Observable changes:** | Where | Change | |---|---| | Python, all 4 sites | unrenderable schema raises `TypeError`, cause chained | | Java ReAct | catch widened to what Jackson actually throws; rethrown as `IllegalArgumentException`, cause chained | | Java ReAct | refuses a POJO rendering no properties. Includes a `@JsonTypeInfo` base with no fields of its own; one shared field renders and is accepted | | Anthropic (py) | a model pydantic renders but Anthropic refuses now raises `TypeError`, not `ValueError`. Only site where the new type is not a subtype of the old | | Anthropic (py) | no render at all when the caller supplies `output_config`, so a discarded schema can no longer fail the call | | Azure (py) | the caller `response_format` conflict is reported before the render | **The Java connections are deliberately untouched.** Validating them with Jackson would refuse schemas the providers accept: a `@JsonTypeInfo` member renders empty under Jackson while the SDK ships a full `anyOf` union, and Jackson throws on field-less, colliding-property and self-referential POJOs that the SDKs send today. Validating the SDK's own schema is no better, since it renders a map member and an unrenderable member identically. Probed with 15 hostile classes, the SDKs never failed to render, so there is no failure there to report. That leaves one asymmetry, imposed by the libraries rather than chosen: pydantic raises where the Java SDKs do not. Not in scope: no change to `RowTypeInfo` handling, no new dependency, no payload change for a schema that renders, and `output_schema` still is not threaded from the runtime to a connection in either language. ### Tests `ReActAgentTest` and `test_react_agent.py` are the first unit coverage of `ReActAgent` in either language. Per site: an unrenderable schema raises with the cause chained, a `dict`/`Map` member is accepted and still sent whole, and a normal schema produces the payload it produced before. Two assertions are load-bearing: - Java asserts the **absence of a cause chain**, not message text. The schema check throws the same type the catch handles, and a wrapper that interpolates `getMessage()` still shows the path even when the error has been buried. - Python parametrizes over **nested and map-reached** field-less models, because a check that stopped below the root would otherwise pass unnoticed. The map-member tests pin the distinction the check rests on: `properties` present and empty constrains nothing, `properties` absent is a free-form map and is valid. Inverting that rejects ordinary models. Verified: Python 985 passed, no non-e2e failures. Java `api` 387, openai 104, anthropic 61, zero failures. `spotless:check` and `check-license.sh` clean. The 27 e2e failures here are pre-existing, from jars never built in this worktree. `tools/lint.sh` could not run locally (its Python step needs an editable install this pip is too old to perform). `ruff check` and `ruff format --check` were run directly on the changed files and are clean. ### API Yes. Two helpers in `flink_agents.api.agents.types`: `render_provider_output_schema` for connections, `render_constraining_output_schema` for the prompt path. Two names rather than a flag, so the call site states which behaviour it wants, and neither takes the bare name `render_output_schema` so a future prompt path cannot silently skip the check. `OutputSchema.rejectUnconstrainedSchema` is package-private, its only caller being `ReActAgent`. No existing signature changes. Exception types change as listed above. ### Documentation - [x] `doc-included` ### Was this patch authored or co-authored using generative AI tooling? - [x] Yes Generated-by: Claude Code v2.1.53 (claude-opus-5[1m]) -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
