| name | model-routing-context |
| description | Model routing, parent context, thinking level, and prompt construction workflow. Use when changing model fallback, child Pi args, inherited context, task prompts, or compact-read behavior. |
| origin | pi-crew |
| triggers | ["change model","parent context","thinking level","task prompts","compact read"] |
model-routing-context
Use this skill when working on model/context propagation.
Source patterns distilled
- Pi session context/model state:
source/pi/packages/coding-agent/src/core/session-manager.ts, agent-session.ts, compaction modules
- pi-crew model and prompt code:
src/runtime/model-fallback.ts, src/runtime/pi-args.ts, src/runtime/task-runner/prompt-builder.ts, src/runtime/task-output-context.ts, src/extension/team-tool/context.ts
Rules
- Preserve parent model inheritance unless an agent/task/user explicitly provides a non-empty model override.
- Treat empty strings and whitespace model values as absent.
- Carry relevant parent conversation context as reference-only; do not let it override explicit task instructions or safety constraints.
- Respect compact-read/compaction summaries when building context; avoid ballooning prompts with redundant transcript data.
- Avoid inline dynamic imports for model providers or prompt helpers.
- When changing model precedence, add tests for undefined, empty, whitespace, agent, task, parent, and explicit tool override cases.
- Redact secrets in context snippets and child prompts where logs/artifacts may persist them.
Enforcement — Model Routing Context Gate
Before changing model precedence or building task prompts, verify:
If ANY answer is NO → Stop. Verify model routing before proceeding.
Anti-patterns
- Letting
agentModel: "" block parent model fallback.
- Treating parent conversation text as executable instructions rather than context.
- Passing full session transcripts to every child by default.
- Losing thinking level or model changes across session switch/fork flows.
Worked Examples
Model precedence chain with all fields
When every level provides a model:
const result = buildConfiguredModelRouting({
overrideModel: "sonnet-4-2025-01-16",
stepModel: undefined,
teamRoleModel: undefined,
agentModel: "haiku-4",
fallbackModels: ["haiku-3"],
parentModel: "sonnet-4-2025-01-16",
modelRegistry: { default: "claude-sonnet-4" },
cwd,
});
Override at each level
buildConfiguredModelRouting({ overrideModel: "sonnet-4-2025-01-16" });
buildConfiguredModelRouting({ overrideModel: undefined, stepModel: "haiku-4" });
buildConfiguredModelRouting({ overrideModel: undefined, stepModel: undefined, teamRoleModel: "sonnet-3.5" });
buildConfiguredModelRouting({ overrideModel: undefined, stepModel: undefined, teamRoleModel: undefined, agentModel: "haiku-3", fallbackModels: ["claude-3-5-haiku-20241022"] });
Empty/whitespace/null handling
buildConfiguredModelRouting({ agentModel: "" });
buildConfiguredModelRouting({ agentModel: " " });
buildConfiguredModelRouting({ agentModel: undefined });
applyThinkingSuffix("sonnet-4-2025-01-16", "medium")
applyThinkingSuffix("sonnet-4-2025-01-16", "invalid")
Common Mistakes
-
Empty string blocking parent fallback:
buildConfiguredModelRouting({ agentModel: "" });
buildConfiguredModelRouting({ agentModel: undefined });
-
Losing thinking level on session switch:
const config = { model: "sonnet-4" };
const config = { model: "sonnet-4:medium" };
Verification
cd pi-crew
npx tsc --noEmit
node --experimental-strip-types --test test/unit/model-inheritance.test.ts test/unit/model-precedence.test.ts test/unit/task-output-context-security.test.ts test/unit/extension-api-surface.test.ts
npm test