weiqingy opened a new pull request, #1129:
URL: https://github.com/apache/flink-agents/pull/1129

   Linked issue: #912
   
   Stacked on #1128, which adds the effective-model hook this builds beside. 
Review that one first; the diff here shows its two commits until it merges.
   
   ### Purpose of change
   
   Nothing changes for a caller yet: no production code asks what this adds. It 
is the second step of wiring an agent `output_schema` through to the providers 
that can enforce it, and it removes a drift hazard the first step exposed.
   
   Whether a native schema reaches a provider depends on more than the model. 
The schema form decides it, and so do conditions that differ per provider: an 
api version floor on Azure, a caller supplied output config on Anthropic, bound 
tools on Gemini. Each connection already made that decision inside its own 
request path, where a caller cannot see it. Asking a connection to answer the 
same question separately would mean writing those conditions twice, and two 
copies drift silently, because a caller only ever sees the answer.
   
   #### Runtime flow
   
   Both connection bases gain a feasibility query: can this connection apply 
this schema, to a request built from these tools and parameters, with the 
effective model's capability set aside. The default is `false`, which suits a 
connection that translates no schema at all.
   
   Every connection with a native branch implements it, and each branch now 
calls the query instead of restating its conditions, so the branch and the 
answer cannot disagree. Capability stays a separate conjunct of each branch. 
The query is asked with the parameters the caller supplied, before a request 
path strips its own keys, because two connections read keys that a stripped 
copy no longer holds.
   
   #### Key decisions
   
   **Feasibility is asked separately from capability, and neither bounds the 
other.** A schema form a connection cannot translate is infeasible on a model 
it calls capable; a translatable form is feasible on a model it calls 
incapable. Merging them would have hidden one behind the other.
   
   **Each override answers from its own request path rather than from a copy of 
its conditions.** That is what the tests pin, and it is why the query is asked 
with the unstripped parameters.
   
   **Anthropic's JSON prefill keeps reading the live parameters** rather than 
sharing the query's snapshot, because prefill has to see the output config the 
branch derives, which the caller never supplied.
   
   ### Behavioral Semantics
   
   #### Interaction decisions
   
   | Connection | Conditions the query answers | Kept in the branch |
   |---|---|---|
   | OpenAI, Ollama, Bedrock, watsonx, Tongyi | schema form | capability |
   | Azure | schema form, api version floor | capability |
   | Anthropic | schema form, no caller supplied output config | capability |
   | Gemini | schema form, no bound tools | capability |
   
   #### Behavioral contracts
   
   1. The query answers whether the connection could apply that schema to such 
a request, with the effective model's capability excluded.
   2. It accepts a missing schema, missing tools and missing parameters without 
raising, so a caller can ask speculatively, and it reads the parameters without 
consuming them.
   3. A `false` answer is not an error: the caller keeps the prompt fallback.
   4. A `true` answer is not a promise the call succeeds. A connection may 
still raise once its branch has decided to apply, where the caller supplied a 
conflicting format, or where the schema cannot be rendered.
   5. An override answers from the same logic its own request path uses.
   
   #### Failure behavior
   
   No new failure path, and one narrow change on invalid input. A branch 
consults the query before the capability predicate, so a request the query 
reports infeasible no longer evaluates that predicate. Where the model is not a 
string, four Python connections raised there and now send the request without a 
schema: OpenAI, Anthropic, Tongyi and Azure. Anthropic reaches that path with a 
translatable schema when the caller supplied an output config, and Azure when 
the api version is below its floor, since both conditions moved into the query. 
Ollama and watsonx are unaffected. Measured by driving every connection across 
1032 request shapes on both trees: 70 cells differ, none of them carrying a 
valid or absent model, and all 696 that do are byte-identical.
   
   ### Tests
   
   | Contract | Tests |
   |---|---|
   | 1, 2, 3 | the base-class tests in both languages: default, missing inputs 
accepted, parameters not consumed |
   | 4 | each connection's contract states it; the conflicting-format raises 
are pinned by existing tests |
   | 5 | a binding test per connection, capturing what the branch actually does 
and comparing it with the answer |
   | the exclusion | a dedicated test per connection that capability is not 
folded into the answer |
   | the unstripped parameters | a test per stripping connection that the query 
sees keys the request path later removes |
   
   Coverage by risk. The failure that matters is an answer that stops matching 
the branch, which no assertion against a literal can catch. The binding tests 
capture the model or the request the branch produced and compare it with the 
query, so a branch that stops agreeing fails. The exclusion tests exist because 
a binding test is structurally blind to capability being folded into an 
override: it moves both sides together, which was measured on both languages.
   
   Suite results: Java api 428, chat-models common 6, openai 131, anthropic 
103, bedrock 90, gemini 71, ollama 18, watsonx 51. Python 797 passed, 12 
skipped.
   
   Not verified. No live provider was called.
   
   ### API
   
   New method on each chat-model connection base, `protected` in Java and 
public in Python, plus overrides. No user-facing API changes, and no behavior 
change for an existing caller beyond the invalid-model case above.
   
   ### Documentation
   
   - [ ] `doc-needed`
   - [x] `doc-not-needed`
   - [ ] `doc-included`
   
   ### Was this patch authored or co-authored using generative AI tooling?
   
   - [x] Yes
   - [ ] No
   
   Generated-by: Claude Code 2.1.272 (Claude Opus 5)
   


-- 
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]

Reply via email to