fix(kernel): resolve team/delegate model pins through the config accessor - #5405
Conversation
Checkpoint of work in progress, touching src/openhuman/config/schema/agent.rs. Co-authored-by: Medulla <medulla@tinyhumans.ai>
Checkpoint of work in progress, touching src/openhuman/agent/tinyagents/config.rs. Co-authored-by: Medulla <medulla@tinyhumans.ai>
Checkpoint of work in progress, touching src/openhuman/agent/tinyagents/config.rs. Co-authored-by: Medulla <medulla@tinyhumans.ai>
Checkpoint of work in progress, touching src/openhuman/agent/tinyagents/config.rs. Co-authored-by: Medulla <medulla@tinyhumans.ai>
Checkpoint of work in progress, touching src/openhuman/agent/tinyagents/config.rs. Co-authored-by: Medulla <medulla@tinyhumans.ai>
Checkpoint of work in progress, touching src/openhuman/agent/tinyagents/config.rs. Co-authored-by: Medulla <medulla@tinyhumans.ai>
Checkpoint of work in progress, touching 2 files: docs/specs/kernel.md,docs/specs/plan-agents.md. Co-authored-by: Medulla <medulla@tinyhumans.ai>
Checkpoint of work in progress, touching docs/specs/plan-agents.md. Co-authored-by: Medulla <medulla@tinyhumans.ai>
There was a problem hiding this comment.
senamakel has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.
📝 WalkthroughWalkthroughThe changes update team and delegate model-pin handling, expand related tests, revise agent migration planning, label a Markdown code fence, and document ChangesModel pin resolution
Agent planning updates
Documentation clarifications
Estimated code review effort: 2 (Simple) | ~10 minutes Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/openhuman/agent/tinyagents/config.rs`:
- Around line 151-162: Add verbose, grep-friendly diagnostics in
src/openhuman/agent/tinyagents/config.rs:151-162 around the model_for_role-based
team-pin resolution, logging the resolution result and whether lead and subagent
pins were applied after fallback without model values; in
src/openhuman/agent/tinyagents/config.rs:173-186, log entry and successful
completion of the non-blank delegate model override, also excluding model
values.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: e51b4e5d-702b-4a2b-9daa-ab9c2e806776
📒 Files selected for processing (4)
docs/specs/kernel.mddocs/specs/plan-agents.mdsrc/openhuman/agent/tinyagents/config.rssrc/openhuman/config/schema/agent.rs
| // Resolve through `model_for_role` rather than copying the raw options. | ||
| // That helper owns three behaviours this mapper must not re-derive: it | ||
| // trims, it drops empty strings (so a blank pin cannot displace a valid | ||
| // default), and it falls back across the pair — a team that sets only | ||
| // `lead_model` means that model for *both* tiers. Copying the fields | ||
| // directly left the unset tier on the global default, which is a different | ||
| // model from the one the user configured. | ||
| if let Some(lead) = pins.model_for_role(true) { | ||
| session.lead_model = Some(lead.to_string()); | ||
| } | ||
| if let Some(agent) = pins.agent_model.as_ref() { | ||
| session.subagent_model = Some(agent.clone()); | ||
| if let Some(agent) = pins.model_for_role(false) { | ||
| session.subagent_model = Some(agent.to_string()); |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
Add diagnostics for the changed model-pin flows.
Both flows change session model state but do not provide complete branch diagnostics.
src/openhuman/agent/tinyagents/config.rs#L151-L162: log the team-pin resolution result and whether lead and subagent pins were applied after fallback.src/openhuman/agent/tinyagents/config.rs#L173-L186: log entry and successful completion of a non-blank delegate model override.
Do not log model values.
As per coding guidelines, “Add verbose, grep-friendly diagnostics for new or changed flows, including entry/exit, branches, external calls, retries, state transitions, and errors; never log secrets or full PII.”
📍 Affects 1 file
src/openhuman/agent/tinyagents/config.rs#L151-L162(this comment)src/openhuman/agent/tinyagents/config.rs#L173-L186
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/openhuman/agent/tinyagents/config.rs` around lines 151 - 162, Add
verbose, grep-friendly diagnostics in
src/openhuman/agent/tinyagents/config.rs:151-162 around the model_for_role-based
team-pin resolution, logging the resolution result and whether lead and subagent
pins were applied after fallback without model values; in
src/openhuman/agent/tinyagents/config.rs:173-186, log entry and successful
completion of the non-blank delegate model override, also excluding model
values.
Source: Coding guidelines
Summary
TeamModelConfig::model_for_role— a team pinning only one tier applied it to that tier only, leaving the other on the global default instead of the team's model.model = "", and both the team and delegate paths assigned it unchecked.Problem
#5396 merged with 18 unresolved threads. Four were real defects in the config seam; the rest were documentation drift and lint.
The two model-pin bugs share a shape: the mapper copied raw
Option<String>fields instead of going through the accessor that owns the semantics.TeamModelConfig::model_for_roletrims, drops empty strings, and falls back across thelead_model/agent_modelpair — its own doc says "callers fall back across the pair so configs can specify only one tier without breaking routing".apply_team_modelsdid none of that, so a team pinning onlylead_modelran its subagents on the global default rather than the model the user chose for that team.DelegateAgentConfig::modelis a bareString.apply_delegateassigned it unchecked, somodel = ""replaced a working session model with the empty string and failed at dispatch rather than at config load.The coverage gap was pointed out with unusual precision and is worth restating:
compact_contextandtool_result_budget_byteswere mapped but unfalsifiable.default_config_maps_to_the_crate_defaultscompares againstTurnConfig::default(), so a field left at the crate default still passes;per_section_mappers_agree_with_the_composed_oneassertss.turn == turn_config_from(&c.agent), which compares the mapper against itself. A dropped assignment for either field would have stayed green.Solution
apply_team_modelsresolves both roles throughmodel_for_role(true/false).apply_delegatetrims and ignores a blank pin, warning rather than silently substituting.turn_limits_come_from_the_agent_sectionsets both previously-uncovered fields away from their defaults, with a comment naming why the other two tests cannot catch them.AgentConfig::session_shadow_reads' doc now listsdisabledand notes case-insensitivity, matchingenv_kill_switch_engaged, which accepts0|false|no|off|disable|disabled. The implementation was right and the config doc was incomplete — the reviewer offered "or remove an unsupported value", but the value is supported.plan-agents.md§Phase 4:integration_runtime_config: Option<Config>→runtime_config: Option<Arc<Config>>landed in feat(kernel): host capability adapters, config seam, and the Phase 2 transcript soak #5396, so the plan was describing completed work as a future blocker. Rewritten, and the two crate-side blockers found during that review are now linked.Behaviour change worth flagging:
a_team_pinning_only_one_tier_leaves_the_other_on_the_defaultasserted the buggy behaviour and has been replaced bya_team_pinning_only_one_tier_applies_it_to_both. If the old semantics were intentional, this is the test to argue about — butTeamModelConfig's own doc says otherwise.Submission Checklist
a_team_pinning_only_one_tier_applies_it_to_both,a_blank_team_pin_does_not_displace_the_default,a_blank_delegate_model_keeps_the_session_default, plus the extended turn-limits assertions.N/A: no feature rows added, removed, or renamed.## Related—N/A: no matrix rows touched.N/A: no network code.N/A: no release-cut surface touched.Closes #NNN—N/A: follow-up to a merged PR, no tracking issue.Impact
Config mapping only, and the adapters remain unwired (Phase 4 repointing is still blocked), so nothing changes at runtime today. The team-pin fix changes which model a team's subagents would resolve to once the seam goes live.
cargo fmt --check,cargo clippy --lib -D warnings, and the full lib suite (12820 / 0) are clean.One caveat I would rather state than omit: the first full-suite run in this fresh worktree reported 3 failures whose names I did not capture, and four subsequent runs were clean. It looks like first-run state initialisation rather than these changes — they touch only config mapping and docs — but I could not reproduce it to confirm, so I am not claiming it away.
Related
Follow-up to #5396. Two crate-side blockers surfaced by that review are filed upstream:
ProgressEventhas no tool-completion milestoneModelResolveRequestcarries no model pinSummary by CodeRabbit
Bug Fixes
Documentation
disabled, as well as other falsy values, disables them.