feat: per-call model + reasoning override with list_models discovery#5446
Open
harshav167 wants to merge 4 commits into
Open
feat: per-call model + reasoning override with list_models discovery#5446harshav167 wants to merge 4 commits into
harshav167 wants to merge 4 commits into
Conversation
…discovery Let the orchestrator pin a model (and reasoning/variant) per delegation — on task(subagent_type|category), call_omo_agent, and team members — gated to connected/available models, with the configured default preserved when omitted. Adds a list_models tool so the agent can discover connected models and the valid reasoning vocabulary before overriding. - delegate-core: resolveRequestedModelOverride() pure helper (parse "provider/model[ variant]", gate via fuzzyMatchModel, reasoning_effort precedence over embedded variant, cold-cache passthrough) - task() + call_omo_agent: optional model/reasoning_effort args; override replaces the resolved model and preserves the agent/category fallback chain - team-core: optional model/reasoning_effort on the member spec (strict kept) - list_models: always-on tool listing connected provider/model ids grouped by provider plus the reasoning vocabulary; seeded into the model arg descriptions - docs: features.md (per-call override + list_models), team-mode.md (per-member) Tests: delegate-core helper (8), tool-boundary integration (5), team member schema (4), list_models formatting (5); typecheck clean (tsgo, 0 errors).
The team_create tool's advertised inline-member schema omitted the model/reasoning_effort fields added to the team-core member spec, so the tool framework stripped them and agents saw additionalProperties:false. Per-member model override therefore only worked via a config.json team file or a JSON-string inline_spec — not the structured inline member object agents naturally use. Add model/reasoning_effort to TeamCreateInlineMemberToolSchema. The inline-spec normalizer already preserves both fields and team-core MemberSchema already accepts them, so the full structured path (tool args -> normalize -> TeamSpec -> resolveMember) now applies the gated per-member override. Test: lifecycle-inline-member-model.test.ts (object form, category variant string, JSON-string path, default-preserved).
The new always-on list_models tool was missing from the AGENTS.md tool catalog. Bump "Always on (18)" to (19) and add list_models so the doc matches the registered tool set.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
task(bothsubagent_typeandcategory),call_omo_agent, and team members — gated to connected/available models, with the configured default and fallback chain preserved when omitted.list_modelstool so the agent can discover connectedprovider/modelids and the valid reasoning vocabulary before overriding.team_createinline members to actually acceptmodel/reasoning_effort(the tool schema previously stripped them).Changes
@oh-my-opencode/delegate-core— new pure, dependency-injected helperresolveRequestedModelOverride(): parsesprovider/model[ variant], letsreasoning_effortoverride the embedded variant, gates viafuzzyMatchModel, with cold-cache passthrough so the first call isn't blocked.task+call_omo_agent— new optionalmodel/reasoning_effortargs; the override replaces the resolved model at top precedence while preserving the agent/categoryfallbackChain.team-coreMemberBaseSchema— optionalmodel/reasoning_effort(schema stays.strict()); andteam_create's inline-member tool schema now advertises both fields so the framework no longer strips them.list_models— new always-on tool: connectedprovider/modelids grouped by provider plus the reasoning vocabulary; pointer seeded into themodelarg descriptions. Registered via the standard factory →tool-registry-factories→createCoreTools()→tools/index.tspath.docs/reference/features.md(per-call override +list_models) anddocs/guide/team-mode.md(per-member override).Testing
delegate-corehelper — 8 (parse / gate / variant / reasoning precedence / cold cache)session.prompt/launchbody carries model, reasoning, gate-reject + no-spawn, default-preserved, category)team_createinline-member model — 4;list_modelsformatting — 5list_modelsreturns the connected set;task(model="openai/gpt-5.5", reasoning_effort="high")andtask(model="xai/grok-composer-2.5-fast")each launch on exactly that model/provider; an invalid id (openai/ghost-999) fails at the gate/provider and the preserved fallback chain recovers it. Plugin load verified in an isolated XDG sandbox (Built tool registry … totalTools 26, teamModeEnabled true, 25→26 =list_modelsregistered).Related Issues
None — standalone feature. Three design questions for maintainers:
delegate_task.allow_runtime_modelconfig flag if you'd prefer it gated, given the caution indocs/guide/agent-model-matching.md.requested-model.tsis the one gate relaxation (first-call safety); stricter behavior is a one-liner.reasoning_effortaccepts any string (normalized downstream per model); could be enum-validated.