← Back to PRs

#14640: feat(agents): support per-agent temperature and maxTokens in agents.list[].model (#14494)

by lailoo open 2026-02-12 12:45 View on GitHub →
agents stale size: S trusted-contributor
## 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