sangkyoonnam opened a new issue, #1150:
URL: https://github.com/apache/flink-agents/issues/1150

   ### Search before asking
   
   - [x] I searched in the 
[issues](https://github.com/apache/flink-agents/issues) and found nothing 
similar.
   
   ### Description
   
   `ModelRouter.Builder#build()` checks that every rule key names a candidate, 
but not the candidate declaration itself. A duplicate candidate, an empty 
candidate name, an empty candidate list, or a `defaultModel(...)` that is not 
one of the candidates all pass `build()`.
   
   `AgentPlan#validateRoutingStrategies` (`plan/.../AgentPlan.java:749-810`) 
has the same gap for descriptor-built plans: it validates the strategy type 
tag, the `candidates` shape, rule keys and the judge model, but not the 
candidate names or `default_model`. Its comment leaves a missing `candidates` 
argument "to the constructor's own message".
   
   The checks exist only in the `ModelRouter` constructor 
(`api/.../ModelRouter.java:75-95`). That constructor runs on the TaskManager 
when the router resource is first resolved, inside the durable `route:<router>` 
call, per routed request (`ModelRoutingResolver#resolve` -> `ctx.getResource`). 
Under the default `FAIL` policy the job dies on the first routed record instead 
of at submission; under `IGNORE` every routed record is dropped while the job 
stays RUNNING. The same static-constraint reasoning already moved the 
judge-model and rule-key checks to plan construction in #1042.
   
   The docs table for `defaultModel(String)` already says "Must be a candidate."
   
   Expected:
   
   - `build()` rejects a duplicate or empty candidate, an empty candidate list, 
and a default model that is not a candidate, with the constructor's messages.
   - Plan construction rejects the same declarations for descriptors that never 
went through the builder, naming the router as the other plan-time router 
checks do.
   - One validation path shared by the constructor, the builder and plan 
construction, so the diagnostics cannot drift.
   
   Java side only: Python cannot register routers yet 
(`check_registrable_from_python`).
   
   ### How to reproduce
   
   ```java
   // Each of these passes build() today and throws only on the TaskManager per 
routed request.
   ModelRouter.of("small", "big")
           .strategy(Strategies.rules(Map.of()))
           .defaultModel("huge")
           .build();
   
   ModelRouter.of("small", 
"small").strategy(Strategies.rules(Map.of())).build();
   ModelRouter.of("small", "").strategy(Strategies.rules(Map.of())).build();
   ModelRouter.of().strategy(Strategies.rules(Map.of())).build();
   ```
   
   A hand-built descriptor with `"default_model": "huge"` or `"candidates": 
["small", "small"]` likewise passes `new AgentPlan(...)`; a regression test can 
be added next to 
`AgentPlanLlmJudgeValidationTest#ruleKeyNamingNonCandidateFailsAtPlanConstruction`.
   
   ### Version and environment
   
   Current `main` (`0.4-SNAPSHOT`, e8f79d51). Java 21, macOS ARM64; not 
platform specific.
   
   ### Are you willing to submit a PR?
   
   - [x] I'm willing to submit a PR!
   


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