#19329: feat: add per-agent compaction and context pruning overrides
gateway
agents
size: XL
Cluster:
Compaction Enhancements and Features
# PR: Per-agent compaction and context pruning overrides
## Title
feat: add per-agent compaction and context pruning overrides
## Body
### Summary
Adds per-agent `compaction` and `contextPruning` configuration to `agents.list[]` entries, allowing different agents to use different compaction behavior. Currently, all agents share the same global `agents.defaults.compaction` settings — this is a significant gap when running agents on models with different context windows or when agents have fundamentally different session lifetimes.
### Motivation
A multi-agent setup might include:
- A **coding agent** on a large-context model that should compact aggressively to stay fast
- A **companion agent** that should never compact (managed by a plugin or external process)
- A **research agent** with a higher `reserveTokensFloor` to preserve more working context
Today, all of these agents share identical compaction behavior. This PR lets each agent override:
- `compaction.mode` — `"default"`, `"safeguard"`, or `"off"` (new)
- `compaction.reserveTokensFloor` — per-agent token reserve
- `compaction.maxHistoryShare` — per-agent history share limit
- `compaction.memoryFlush` — per-agent flush prompt, system prompt, threshold, and enabled flag
- `contextPruning` — per-agent pruning mode, TTL, and keepLastAssistants
### Example config
```json5
{
agents: {
defaults: {
compaction: {
mode: "safeguard",
reserveTokensFloor: 20000,
memoryFlush: { enabled: true }
}
},
list: [
{
id: "researcher",
compaction: {
reserveTokensFloor: 80000 // higher floor, inherits mode + memoryFlush from defaults
}
},
{
id: "plugin-managed",
compaction: {
mode: "off" // compaction handled externally
}
},
{
id: "companion",
compaction: {
memoryFlush: {
prompt: "Save emotional context, personal stories, and relationship details."
}
}
}
]
}
}
```
### What changed
**Schema & types** (commit 1):
- Extracted `CompactionSchema` from `zod-schema.agent-defaults.ts` into `zod-schema.agent-runtime.ts` for reuse
- Added `compaction` and `contextPruning` fields to `AgentEntrySchema`
- Added `"off"` to `AgentCompactionMode` type
**Resolvers** (commit 2):
- `resolveAgentCompaction(cfg, agentId?)` — deep merges per-agent overrides with global defaults; `memoryFlush` sub-object is shallow-merged one level deeper so partial overrides don't wipe sibling fields
- `resolveAgentContextPruning(cfg, agentId?)` — merges per-agent context pruning with global defaults
- `isCompactionEnabled(cfg, agentId?)` — guard helper that encapsulates the `mode !== "off"` check
**Callsite wiring** (commit 3, 6 files):
- `compact.ts` — skips `ensurePiCompactionReserveTokens` when mode is `"off"`
- `attempt.ts` — same skip logic for run attempts
- `extensions.ts` — uses resolved per-agent config for both compaction mode and context pruning
- `pi-settings.ts` — `resolveCompactionReserveTokensFloor` now takes optional `agentId`
- `memory-flush.ts` — `resolveMemoryFlushSettings` uses per-agent compaction config; returns `null` when mode is `"off"`
- `agent-runner-memory.ts` — extracts `agentId` from session key and passes it through
**Tests** (commit 4):
- 38 tests covering all resolver functions, merge semantics, mode combinations, edge cases (missing agent, empty overrides, partial memoryFlush, undefined spread safety)
**Review feedback** (commit 5):
- Removed dead code in `buildContextPruningExtension`
- Widened per-agent `contextPruning` type to include `ttl` and `keepLastAssistants`
- Used named `AgentContextPruningConfig` type instead of inline return type
### Integration tested
Tested on a live gateway with a dedicated test agent (`claude-haiku-4-5`, 200k context):
| Test | Config | Result |
|------|--------|--------|
| Custom floor | `reserveTokensFloor: 80000` | Compacted at ~120k used (98k → 17k) ✅ |
| Mode off | `mode: "off"` | No compaction at 222k+ tokens ✅ |
### Breaking changes
None. All new fields are optional. Agents without per-agent overrides behave exactly as before (global defaults apply).
### Checklist
- [x] Schema extraction (no duplication between defaults and per-agent)
- [x] Deep merge with memoryFlush sub-object handling
- [x] `mode: "off"` support with guard helper
- [x] All callsites wired
- [x] 38 unit tests passing
- [x] Type check clean
- [x] Integration tested on live gateway
- [x] No unrelated changes in diff
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
Adds per-agent `compaction` and `contextPruning` configuration overrides to `agents.list[]` entries, enabling different agents to use different compaction behaviors. The implementation introduces a new `"off"` mode for compaction, along with resolver functions that deep-merge per-agent settings with global defaults.
**Key changes:**
- Extracted `CompactionSchema` for reuse between `AgentDefaultsSchema` and `AgentEntrySchema`
- Added `resolveAgentCompaction()`, `resolveAgentContextPruning()`, and `isCompactionEnabled()` helpers with proper deep-merge semantics for `memoryFlush` sub-object
- Wired per-agent config through all callsites (`compact.ts`, `attempt.ts`, `extensions.ts`, `pi-settings.ts`, `memory-flush.ts`, `agent-runner-memory.ts`)
- Added comprehensive test coverage (38 tests covering merge semantics, edge cases, `mode: "off"` behavior)
- Migrated existing e2e tests to unit tests in `agent-scope.test.ts`
The implementation follows the existing pattern for per-agent model overrides and maintains backward compatibility - all new fields are optional and default to global settings when not specified.
<h3>Confidence Score: 5/5</h3>
- This PR is safe to merge with minimal risk.
- The implementation is well-architected with proper deep-merge semantics for nested config objects, comprehensive test coverage (38 tests), clean extraction of shared schema components, and systematic wiring through all callsites. The `mode: "off"` feature is correctly guarded at every integration point. All changes maintain backward compatibility.
- No files require special attention
<sub>Last reviewed commit: 0a2dce7</sub>
<!-- greptile_other_comments_section -->
<sub>(3/5) Reply to the agent's comments like "Can you suggest a fix for this @greptileai?" or ask follow-up questions!</sub>
<!-- /greptile_comment -->
Closes #13736
Closes #17735
Relates to #16546 (this PR adds per-agent compaction; contextTokens override is a separate concern)
Most Similar PRs
#8313: feat: auto-compaction support for spawned subagent sessions
by vishaltandale00 · 2026-02-03
83.5%
#11089: feat(compaction): support customInstructions and model override for...
by p697 · 2026-02-07
82.4%
#14487: feat(config): support per-agent compaction overrides (#14446)
by lailoo · 2026-02-12
82.1%
#21547: feat: add compaction.announce config to notify users of compaction ...
by jlwestsr · 2026-02-20
81.2%
#15927: feat: add compaction.model override config option
by Shuai-DaiDai · 2026-02-14
81.1%
#10505: feat(compaction): add timeout, model override, and diagnostic logging
by thebtf · 2026-02-06
80.7%
#10214: feat(compaction): Add Anthropic server-side compaction API support
by GodsBoy · 2026-02-06
80.5%
#14887: feat(compaction): configurable auto-compaction notifications with o...
by seilk · 2026-02-12
79.6%
#14640: feat(agents): support per-agent temperature and maxTokens in agents...
by lailoo · 2026-02-12
79.5%
#17470: feat(cache): per-agent params for cacheRetention control (#17112)
by rrenamed · 2026-02-15
79.4%