#14640: feat(agents): support per-agent temperature and maxTokens in agents.list[].model (#14494)
agents
stale
size: S
trusted-contributor
Cluster:
Compaction Enhancements and Features
## Summary
Fixes #14494
## Problem
The `agents.list[].model` schema only accepts `primary` and `fallbacks` fields. Adding `temperature` or `maxTokens` causes config validation to fail with `Invalid input`. This forces all agents to share the same inference parameters, which undermines the value of having specialized agents with different roles (e.g., a low-temperature code generator vs. a high-temperature creative writer).
**Before:**
```json
{
"agents": {
"list": [{
"id": "developer",
"model": {
"primary": "anthropic/claude-opus-4",
"temperature": 0.2,
"maxTokens": 8192
}
}]
}
}
```
Result: `Invalid input` — Zod schema rejects unknown fields due to `.strict()`.
## Fix
1. **Zod schema** (`src/config/zod-schema.agent-runtime.ts`): Add `temperature` (number, 0–2) and `maxTokens` (positive integer) to `AgentModelSchema` object variant.
2. **TypeScript type** (`src/config/types.agents.ts`): Add `temperature?: number` and `maxTokens?: number` to `AgentModelConfig`.
3. **Agent config resolver** (`src/agents/agent-scope.ts`): Add `resolveAgentModelParams()` to extract per-agent temperature/maxTokens from agent config.
4. **Attempt runner** (`src/agents/pi-embedded-runner/run/attempt.ts`): Merge per-agent model params into the `extraParamsOverride` passed to `applyExtraParamsToAgent`, which wraps the agent's `streamFn` with the configured temperature/maxTokens.
**After:**
```json
{
"agents": {
"list": [{
"id": "developer",
"model": {
"primary": "anthropic/claude-opus-4",
"temperature": 0.2,
"maxTokens": 8192
}
}]
}
}
```
Result: Config validates successfully. The developer agent uses temperature=0.2 and maxTokens=8192 for all API calls.
### Priority chain
Per-agent params slot into the existing priority chain:
```
global model params (agents.defaults.models[key].params)
← per-agent model params (agents.list[].model.temperature/maxTokens) [NEW]
← per-request stream params (streamParams from caller)
```
Per-agent overrides global; per-request overrides per-agent.
## Testing
- ✅ 14 tests pass (`pnpm vitest run src/agents/agent-scope.test.ts`) — including 4 new tests for `resolveAgentModelParams`
- ✅ 362 config tests pass (`pnpm vitest run src/config/`)
- ✅ Lint passes (`pnpm lint`)
## Effect on User Experience
**Before:** Multi-agent setups forced all agents to use the same temperature and maxTokens, or required workarounds via `agents.defaults.models` keyed by provider/model (which doesn't work when multiple agents share the same model but need different parameters).
**After:** Each agent can have its own inference parameters, enabling specialized agent configurations like low-temperature code generators and high-temperature creative writers.
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
This PR extends the per-agent `agents.list[].model` configuration to support `temperature` and `maxTokens`.
Key changes:
- Updates the runtime Zod schema so `agents.list[].model` object entries can include `temperature` (0–2) and `maxTokens` (positive int) without failing strict validation.
- Extends the TypeScript `AgentModelConfig` type accordingly.
- Adds `resolveAgentModelParams()` in `src/agents/agent-scope.ts` to extract these per-agent parameters.
- Wires the resolved per-agent params into the embedded attempt runner by merging them into `applyExtraParamsToAgent(...)` overrides, preserving the intended precedence where per-request stream params override per-agent params.
Overall, this fits the existing model-param plumbing (global defaults via `agents.defaults.models[provider/model].params` and request-level `streamParams`) by inserting a per-agent layer in between without changing unrelated agent resolution logic.
<h3>Confidence Score: 5/5</h3>
- This PR is safe to merge with minimal risk.
- Changes are narrowly scoped: schema/type expansion plus a small, well-contained plumbing change to pass per-agent params into the existing extra-params wrapper with correct precedence (per-request overrides win). No incompatible API changes were found in the affected call sites, and the new resolver is defensive when model config is a string or unset.
- No files require special attention
<!-- greptile_other_comments_section -->
<!-- /greptile_comment -->
Most Similar PRs
#10197: fix: add missing allowAgents to agent defaults subagents schema
by Yida-Dev · 2026-02-06
80.9%
#20954: feat: per-agent model allowlist
by coletebou · 2026-02-19
80.8%
#19329: feat: add per-agent compaction and context pruning overrides
by curtismercier · 2026-02-17
79.5%
#17470: feat(cache): per-agent params for cacheRetention control (#17112)
by rrenamed · 2026-02-15
78.5%
#11562: Fix #10883: Enforce subagent model configuration
by divol89 · 2026-02-08
77.7%
#13376: fix: pass model directly to agent for sub-agent runs
by jrbobbyhansen-pixel · 2026-02-10
77.6%
#20968: fix(ui): enable save button when editing default agent models
by Gitjay11 · 2026-02-19
77.5%
#16899: feat(config): per-agent and per-model thinking defaults
by jh280722 · 2026-02-15
77.3%
#10943: fix(config): resolve Control UI "Unsupported schema node" for confi...
by kraftbj · 2026-02-07
77.3%
#20712: fix(subagents): prioritize agent runtime default model over global ...
by sourcesavant · 2026-02-19
76.5%