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

   Linked issue: #1334
   
   Closes #1334
   
   ### Purpose of change
   
   #### Outcome
   
   YAML can declare model routers under `model_routers`, on an agent or as 
shared resources. Both loaders register them as `MODEL_ROUTER` descriptors, and 
a chat request that names the router uses the existing routing execution.
   
   #### Intent
   
   Router configuration was programmatic only. YAML needs the same descriptor 
arguments — candidates, descriptions, strategy, default model, and fallback — 
checked by the existing plan validation.
   
   #### Runtime flow
   
   The parser accepts `model_routers` as a list of `DescriptorSpec`. The loader 
resolves `clazz`, including the `model_router` alias, copies every other field 
into a resource descriptor, and registers it as `MODEL_ROUTER` on the agent or 
the execution environment. Shared routers join the agent with the existing 
environment-then-agent merge when the plan is built. Plan construction runs the 
existing routing checks. The existing resource provider then constructs 
`ModelRouter`, and the existing resolver runs the declared strategy.
   
   #### Key decisions
   
   The section reuses `DescriptorSpec`, so strategy settings stay the 
descriptor keys the builder already emits. The alias is `model_router` in both 
languages. Cross-language declarations are rejected by the loaders' existing 
language allow-lists: Java YAML sets `type: java`, and Python YAML keeps the 
default Python implementation. An unsupported strategy fails inside the plan 
check used for the same programmatic descriptor.
   
   ### Behavioral Semantics
   
   #### Interaction decisions
   
   | Scope | Language | Strategy supported by that runtime | Result |
   |---|---|---|---|
   | Agent-local or shared | Loader's own language | Yes | Registered; plan 
checks and routing execution proceed |
   | Agent-local or shared | The other language | Either | Load fails before 
registration |
   | Same name as a chat model | Either | Either | Existing name-collision 
error |
   | Loader's own language | Unsupported or invalid | Plan build fails with the 
same exception and message as that descriptor registered programmatically |
   
   A shared router and an agent-local router with different names are both 
visible after the merge. An agent-local resource of the same type and name 
still wins.
   
   #### Behavioral contracts
   
   1. Agent-local and shared `model_routers` become `MODEL_ROUTER` descriptors 
for `ModelRouter`, preserving candidates, descriptions, strategy type, strategy 
arguments, executor class, default model, and fallback.
   2. `clazz: model_router` resolves to the Java or Python `ModelRouter` class 
for the selected language. A fully qualified class name is kept.
   3. Omitting `model_routers` leaves that map empty, so existing YAML 
documents still load.
   4. A YAML router and the same descriptor registered programmatically fail 
plan construction with the same exception type and message.
   5. A loaded rule router selects the matching candidate, abstains to 
`default_model` otherwise, and a custom router runs `strategy_executor_class`.
   6. Fallback and candidate order on the resolved route follow the declaration.
   
   #### Failure behavior
   
   Missing `name` or `clazz`, or an unknown document key, fails while the file 
is parsed. The other implementation language raises `IllegalArgumentException` 
(Java) or `ValueError` (Python) from the existing `type` check, and the router 
is not registered. A router name that is already a chat model raises the 
existing registration error. A missing strategy, unknown strategy tag, rule 
target outside the candidates, Python `llm_judge` or `decision_model`, or a 
missing custom executor raises during plan construction and is not retried or 
replaced with another strategy. A candidate that is not declared in the file 
still fails when a request resolves that model.
   
   ### Tests
   
   | Contract | Tests |
   |---|---|
   | 1. Arguments at both scopes | 
`YamlModelRouterLoaderTest.declaresAgentLocalAndSharedRouters`, 
`test_model_router_declarations_keep_descriptor_arguments`, 
`test_load_yaml_registers_shared_model_router` |
   | 2. Alias and class name | 
`AliasesTest.clazzAliasCoversModelRouterInBothLanguages`, 
`test_resolve_clazz_covers_model_router_in_both_languages`, and the loader 
tests above |
   | 3. Omitted section | `SchemaParityTest`, 
`test_checked_in_schema_matches_pydantic_models`, existing fixture loads |
   | 4. Same plan failure as a programmatic descriptor | 
`YamlModelRouterDeclarationTest.invalidYamlFailsLikeTheSameProgrammaticDescriptor`,
 `test_invalid_yaml_fails_like_the_same_programmatic_descriptor`, 
name-collision tests |
   | 5 and 6. Selection, abstention, custom execution, fallback order | 
`yamlRoutersExecuteRulesAndCustomStrategies`, 
`test_yaml_routers_execute_rules_and_custom_strategies` |
   
   Covered: loader, plan check, and route resolution for rule and custom 
strategies, including an invalid tag, a bad rule target, unsupported Python 
strategies, and a missing executor. Not verified: a live chat-model call after 
selection, LLM-judge and decision-model execution, Java annotations, and 
recovery replay. Those paths are unchanged.
   
   <details>
   <summary>Implementation invariants</summary>
   
   The loader does not interpret strategy arguments. `DescriptorSpec` extras 
are copied into the descriptor, and `JavaResourceProvider` or 
`PythonResourceProvider` constructs `ModelRouter`. Shared entries merge through 
`Agent.addResourcesIfAbsent` in Java and the same environment-then-agent map 
merge in Python. Python plan validation still requires a Python descriptor; 
Java `type: java` produces a Java descriptor. Schema copies: 
`docs/yaml-schema.json` and 
`dev/agent-skills/flink-agents-dev/assets/yaml-schema.json`.
   
   </details>
   
   ### API
   
   #### Compatibility impact
   
   Existing YAML is unchanged: `model_routers` is optional and defaults to an 
empty list. Programmatic registration, plan validation, and routing execution 
are unchanged. Declaring the section in the other implementation language fails 
at load. Java annotations and Python decorators remain unavailable.
   
   ### Documentation
   
   - [x] `doc-included`
   - [ ] `doc-needed`
   - [ ] `doc-not-needed`
   
   ### Was this patch authored or co-authored using generative AI tooling?
   
   - [x] Yes
   - [ ] No
   
   Generated-by: Cursor Grok 4.7 (Grok 4.7)
   


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