Skip to content

Proposal: model aliases so one agent works in every tool #830

Closed

Description

@SaulMoro

Today. An agent names one model, and TeamAI copies it into every tool as is.

agents/implementer.md    model: opus

Claude Code    opus    works
Codex          opus    breaks, unknown model
OpenCode       opus    breaks, unknown model

Proposal. The agent says what kind of model it wants. The team says which model that is in each tool.

agents/implementer.md    model: strong

team repo                strong:
                           claude:   opus
                           codex:    gpt-5.6
                           opencode: ...

Claude Code    opus       works
Codex          gpt-5.6    works
OpenCode       ...        works
  • A member can change a mapping on their own machine, the way model profiles use team: and local:.
  • A tool with no mapping gets its default model, and pull and doctor warn about it.
  • model: opus keeps working as it does today.
  • An alias could also carry reasoning effort, which most agent tools expose.

Every team that deploys agents to more than one tool needs this, and it is on the roadmap in #647 (Team Execution: "Improve and expand support for different Agents"). Workflows (#818) need it too, since each member runs agents in their own tool.

Open question. Should the team name its aliases, or should TeamAI ship a fixed set such as strong and fast? I lean toward team names.

Activity

  1. changed the title [-]Proposal: tool-independent model aliases for agents[/-] [+]Proposal: model aliases so one agent works in every tool[/+] on Sep 25, 2026
  2. jeff-r2026 commented on Sep 25, 2026

    @jeff-r2026
    Collaborator

    I think strong and fast are enough as the initial aliases. It would be useful to allow multiple model options within each tier, though, so teams can choose among them based on availability or preference. The default choice should be explicit, with local overrides when needed.

  3. SaulMoro commented on Sep 26, 2026

    @SaulMoro
    CollaboratorAuthor

    Starting with strong and fast makes sense to me, and so do several options per alias, an explicit default and local overrides. Below is a shape that tries to fit those together, as a starting point for discussion rather than a settled design. The main thing I'd add is team names on top of the two, so a team that wants a reviewer model doesn't have to bend strong to get it.

    Goal. One agent file runs in every tool a member uses, on the model the team chose for that tool. This works with or without an AI gateway.

    Terms. A model alias names a kind of model, such as strong. A mapping says which model that is in one tool, and optionally which reasoning effort to use.

    flowchart LR
      A["agents/implementer.yaml<br/>model: strong"] --> R{{resolve per tool}}
      T["models/aliases.yaml<br/>team mapping"] --> R
      L["~/.teamai/models/aliases.yaml<br/>local override"] --> R
      R --> C["Claude Code<br/>model: opus<br/>effort: high"]
      R --> X["Codex<br/>model = gpt-6-sol<br/>model_reasoning_effort = high"]
      R --> O["OpenCode<br/>model: anthropic/..."]
      R --> G["Codex on the team gateway<br/>model = glm-5.3"]
      R --> U["tool with no mapping<br/>no model field, warning"]
    
    Loading

    The agent says what kind of model it wants. model stays optional. An agent without it runs on each member's default model, which is effectively the middle option between strong and fast.

    # agents/implementer.yaml
    name: implementer
    description: Implements a planned change
    model: strong        # an alias, or a concrete model as today
    instructions: ...

    The team says what each alias means in each tool, in that tool's own format. Each tool gets an ordered list: the first entry is the default, and the rest are options the team supports.

    # models/aliases.yaml, example 1: members on their own accounts (IDs are illustrative)
    strong:
      claude:   [{ model: opus, effort: high }, { model: fable }]
      codex:    [{ model: gpt-6-sol, effort: high }, { model: gpt-6-astra }]
      opencode: [{ model: anthropic/claude-opus-5-5 }]
    fast:
      claude:   haiku                      # a single model, no effort
      codex:    { model: gpt-6-luna, effort: low }
    reviewer:                              # a team alias
      claude:   [{ model: opus, effort: max }]

    With a gateway. A team whose gateway serves the same models to several tools maps each alias once per gateway, keyed by the model profile. It applies to every tool a member has switched to that profile, and TeamAI writes the model in each tool's form, since it set up that tool's provider. Tools not on the gateway keep using their own entries.

    # models/aliases.yaml, example 2: with a gateway (IDs are illustrative)
    strong:
      gateways:
        team:tokenhub: glm-5.3             # Claude, Codex, OpenCode, CodeBuddy on this profile
      claude: [{ model: opus, effort: high }]      # members on their own accounts
      codex:  [{ model: gpt-6-sol, effort: high }]
    fast:
      gateways:
        team:tokenhub: deepseek-v4-flash
    team:tokenhub, glm-5.3
      claude     model: glm-5.3
      codex      model = "glm-5.3"
      opencode   model: teamai-chat/glm-5.3
      codebuddy  model: glm-5.3
    

    A member can use another model on their own machine. The override can name any model, not only the team's options. This follows the same team/personal split that model profiles use.

    # ~/.teamai/models/aliases.yaml
    strong:
      codex: { model: gpt-6-astra, effort: xhigh }
      gateways:
        local:my-gateway: qwen-4-coder     # a personal model profile

    Resolution, per agent and tool:

    tool_extras.<tool>.model      explicit in the agent, skips aliases
    > local override
    > gateways.<profile the tool is switched to>
    > <tool> entry (first option)
    > no model field: the tool's default, and pull and doctor warn
    

    No gateway needed. A mapping holds each tool's native value (opus, gpt-6-sol, provider/model), which works with the member's own account. Model profiles come in only when a member has run teamai models switch for that tool. In that case, the alias's gateways entry for that profile applies, and pull and doctor warn if a model isn't in the gateway's catalog.

    No built-in mappings. I'd have TeamAI reserve the names strong and fast but ship no models for them. A tool's own alias like opus doesn't go stale, but the judgement that opus is strong does: Fable already sits above it. I think that judgement belongs in the team repo, where a team can change it without waiting for a TeamAI release. An agent that says strong still works as-is in any team that maps strong once.

    What I'd put in v1.

    • model: <alias> in agents, with the reserved strong and fast plus team aliases.
    • models/aliases.yaml and models/<ns>/aliases.yaml, activated by resources.models like model profiles. A namespace alias replaces the root alias of the same name, whole.
    • ~/.teamai/models/aliases.yaml for local overrides.
    • Optional effort per mapping, written in the tool's own field and values.
    • gateways entries keyed by model profile, team or personal, for every tool switched to that profile.
    • Checks in pull and doctor: an alias with no mapping for a deployed tool, a mapping that doesn't fit the tool's format, and a resolved model missing from an active gateway.
    • push writes the alias back when the deployed value matches what it resolved to.

    What could wait.

    • An effort on the agent that overrides the alias's effort, on a scale TeamAI translates per tool.
    • Per-tool exceptions inside a gateways entry, such as another model or an effort for Claude on the same gateway.

    Acceptance check. Alice uses Claude Code and Codex with her own accounts. Bob uses Codex through the team gateway. Both deploy the same agents/implementer.yaml with model: strong, and nobody edits it. Alice gets opus with high and gpt-6-sol with high. Bob gets glm-5.3 in Codex from the gateway entry, without the team writing a Codex mapping for the gateway. Carol switches her strong in Codex to gpt-6-astra locally. Nothing changes for anyone else, and her next push doesn't propose an edit.

    Design notes: proposed details and open questions

    Proposed:

    • Alias or model. A model value that matches a reserved or team alias is an alias. Any other value is written as-is, as today. A team alias named after a tool's own alias (opus, sonnet, haiku, inherit, ...) is rejected.
    • New reserved names. If TeamAI reserves another name later, a team alias with that name keeps winning, and doctor notes it.
    • Keys. A mapping is keyed by tool id. Only variants that share a model catalog inherit: claude-internal and tclaude from claude, and codex-internal and tcodex from codex. Qoder, for example, doesn't inherit opus.
    • Format. Each tool's mapping uses that tool's native values and fields: effort for Claude and CodeBuddy, model_reasoning_effort for Codex, and variant for OpenCode. The output only carries fields the tool knows, since Gemini CLI's schema rejects unknown keys. Tools handle a bad model ID differently (silent fallback, a warning, a hard error), so TeamAI checks the mapping at deploy time instead of relying on the tool.
    • Shorthand. A single string or object stands for a one-entry list.
    • Push. If the deployed value equals what the alias resolved to, push writes the alias back. Any other value counts as an edit to model, with today's conflict rules. A local override is resolved the same way, so it never shows up as an edit.
    • Legacy agents. Aliases apply to YAML agents. A legacy agents/<name>.md is copied as-is, so it should keep a concrete model; pull could warn when its model is an alias.
    • Gateways. A gateways entry wins over the tool's own entry only when that tool is switched to the profile, since it describes the member's real provider. It is an ordered list like the others, and carries no effort in v1, because effort levels depend on the model. A model missing from the profile's catalog is skipped with a warning, then the next option, then the tool's entry. A profile that isn't active for the member is ignored without a warning. push doesn't check the catalog, since a namespace override can change it per member. Only the tools model profiles support (Claude, Codex, OpenCode, CodeBuddy, WorkBuddy) use these entries.
    • Claude on a gateway. Claude Code 2.1.283 sends an unknown subagent model to the API unchanged. It logs unrecognized_model and doesn't fall back to the inherited model, so a gateway ID like glm-5.3 reaches the gateway. This was tested against the Anthropic API, which returns 404 for that ID, and not yet against a gateway that serves it.
    • Separate file. models/models.yaml is parsed strictly, so an aliases key there would break model profiles for members on older CLIs. A separate file doesn't.
    • Naming. Local config already has a modelAliases key, used only to price gateway models. It could get a clearer name in its own change first, to avoid two meanings for one word.
    • Older CLIs. They ignore models/aliases.yaml, but write model: strong into the tool as-is. Auto-update is on by default, so most members get a CLI that resolves aliases without doing anything. The release notes tell teams with autoUpdate: false to update before their agents use an alias. There is no minimum-version check.

    Open questions:

    • Cursor now receives model as-is (fix(agents): carry the agent's model into the Cursor render (#830) #856). Should an alias's effort map into Cursor's model[effort=...] form?
    • Copilot accepts an ordered list of models natively. Render the team's list there, or only the first entry?
    • An explicit inherit entry, so a team can say "this tool uses its default" and silence the warning.

    Feedback from anyone who deploys agents to more than one tool would help:

    • Do strong and fast cover how you pick models today, or do you need a third name?
    • Would you want reasoning effort in the alias, on the agent, or both?
    • If your team uses a gateway, does one entry per gateway fit how you work?
    • Is anything here more than a first version needs?
  4. deleted a comment from hsuchifeng on Sep 26, 2026
  5. jeff-r2026 commented on Sep 26, 2026

    @jeff-r2026
    Collaborator

    Agreed. Keep the mappings team-defined. strong and fast are enough as the reserved default tiers, and a team should be able to add its own aliases, such as reviewer.

    TeamAI can reserve those two names, but it should not ship model IDs for them. What counts as strong changes over time, and that choice belongs in the team repo.

    For v1, put reasoning effort on the alias only. An effort on the agent that overrides it can wait.

    Gateway mappings can wait too. v1 only resolves the per-tool entries, for members on their own accounts. A tool already switched to a model profile keeps its current model.

  6. ydflow commented on Sep 27, 2026

    @ydflow
    Contributor

    The Cursor half of that open question is now a separate PR: #856 writes the agent's model verbatim into the Cursor frontmatter (which reverseFromCursor already read back), so a Cursor agent stops silently losing the team-declared model. The model[effort=...] form stays with the alias proposal here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions