Files
open-multi-agent/docs/model-routing.md
T
Jack Chen 1d37ce6026 refactor(repo): monorepo groundwork for an easier first run (#303)
* refactor(repo): monorepo groundwork for an easier first run

Trying OMA for the first time costs more than it should: a lot to read before anything runs, and no one-command way to watch a team actually work. The plan is to fix that with a `npm create oma` scaffold (a multi-agent demo that runs on the first try) and an npm README that leads with getting started. Neither lands cleanly until core lives in its own package, so this PR does that part first.

This is groundwork, not the payoff: nothing changes for anyone installing `@open-multi-agent/core` today. It turns the repo into an npm-workspaces monorepo with core in `packages/core/`, and splits the README into a GitHub landing page (root) and the npm package page (`packages/core/`). Doing it now, while the repo is small, avoids migrating twice.

The published package is byte-identical: same name, same three runtime dependencies, same entry points, guarded by an isolated-install smoke test. `npm ci` + lint + test (1060) + build pass; the tarball still ships only `dist/`, `README.md`, `LICENSE`, and `package.json`.

* build: restore cross-platform optional deps in package-lock.json

Regenerating the lockfile on macOS pruned the non-host rollup/esbuild optional binaries (npm/cli#4828), so Linux CI could not load @rollup/rollup-linux-x64-gnu and vitest failed to start. Rebuild the lock from the pre-migration base so every platform variant is present again. Verified with npm ci + lint + build + test (1060).

* fix(examples,docs): correct monorepo paths and anchors after the packages/core move

with-vercel-ai-sdk example (pre-existing, surfaced by the move):
- package.json: the @open-multi-agent/core file: link was file:../../, which
  resolves to packages/core/examples (no manifest). Corrected to file:../../..
  (packages/core); predev cd updated to match.
- package-lock.json regenerated: was linking ../.. and pinning a stale core
  1.4.0; now links ../../.. at 1.7.0.
- README: setup paths and the file: note updated.

docs missed by the move:
- docs/cli.md: repo-clone build output is now packages/core/dist/cli/oma.js;
  the quick-start anchor now lives in the package README.
- CONTRIBUTING.md: the architecture anchor and src/ entry-point paths now live
  under packages/core/.
2026-06-18 17:31:52 +08:00

4.0 KiB

Model routing

modelRouting is an opt-in, deterministic policy that sends different orchestration calls to different models without touching your team or agent configuration. The usual shape is "flagship model plans, a cheap model runs the leaf work":

import type { ModelRoutingPolicy } from '@open-multi-agent/core'

const modelRouting: ModelRoutingPolicy = {
  rules: [
    // Flagship model decomposes the goal and synthesizes the final answer.
    { match: { phase: 'coordinator' }, route: { model: 'claude-opus-4-7' } },
    { match: { phase: 'synthesis' },   route: { model: 'claude-opus-4-7' } },
    // Everything that has no dependents runs on a cheap model.
    { match: { leaf: true }, route: { model: 'claude-haiku-4-5' } },
  ],
}

const result = await orchestrator.runTeam(team, goal, { modelRouting })

runTasks takes the same option:

const result = await orchestrator.runTasks(team, tasks, { modelRouting })

A rule is { match, route }. Rules are evaluated in array order and the first match wins, so put your most specific rules first. A call that matches no rule keeps the model it would have used anyway.

Match dimensions

A rule matches only when every field set in match agrees with the call. An empty match: {} matches everything (useful as a final catch-all).

Field Matches when Available on
phase the call is for this orchestration phase (coordinator, synthesis, short-circuit, worker, delegated) every call
agent the running agent's name equals this every call
taskRole the task's role equals this worker / delegated calls (role comes from an explicit task or the coordinator's JSON)
taskPriority the task's priority equals this (low | normal | high | critical) worker / delegated calls
leaf the task has no dependents in the execution graph worker / delegated calls
hasDependencies the task's dependsOn is non-empty worker / delegated calls

taskRole, taskPriority, leaf, and hasDependencies are task-scoped, so they only ever match worker and delegated calls. The coordinator, synthesis, and short-circuit phases have no task attached, and a rule that sets a task field will simply never match them.

Route config

The route is the override applied when the rule matches. Only model is required; the rest fall back to the agent's config, then the orchestrator defaults.

Field Meaning
model Model for the matched call. Required.
provider Provider override (anthropic, openai, gemini, …). Defaults to the agent's or default provider.
baseURL Base URL for OpenAI-compatible or self-hosted endpoints.
apiKey API key for the matched call.
region AWS region, for Bedrock routes.

Which calls are routed

A single policy covers all five orchestration phases:

  • coordinator — the goal-decomposition call in runTeam.
  • synthesis — the final answer-assembly call in runTeam.
  • worker — a task agent running an assigned task (runTeam and runTasks).
  • delegated — an agent reached through delegate_to_agent.
  • short-circuit — the single-agent path runTeam takes when a goal is simple enough to skip decomposition.

Opt-in and non-mutation

Two guarantees keep routing safe to leave configured:

  • Opt-in. Omit modelRouting and model selection is byte-identical to before, on both runTeam and runTasks.
  • No mutation. A matched route builds an ephemeral effective config for that one call. Your Team, its AgentConfigs, and the orchestrator defaults are never modified, so the same team can run with different policies across calls.

Cost-tiered example

examples/patterns/cost-tiered-pipeline.ts runs the same four-stage pipeline twice (all-flagship vs. a tiered mix) and prints the per-model token and USD breakdown, so you can see what a routing policy saves before adopting one.