Skip to content

feat(cache): per-agent params for cacheRetention control (#17112)#17470

Closed
rrenamed wants to merge 1 commit intoopenclaw:mainfrom
rrenamed:feat/per-agent-cache-retention
Closed

feat(cache): per-agent params for cacheRetention control (#17112)#17470
rrenamed wants to merge 1 commit intoopenclaw:mainfrom
rrenamed:feat/per-agent-cache-retention

Conversation

@rrenamed
Copy link
Contributor

@rrenamed rrenamed commented Feb 15, 2026

Summary

Fixes #17112. No way to set cacheRetention per-agent. Low-traffic agents (e.g., cron jobs running every 30 min) waste money on cache writes ($1.25/MTok) that expire before the next request.

Root Cause

resolveExtraParams() only reads from global model defaults (agents.defaults.models["provider/model"].params). There is no per-agent override — all agents sharing the same model get identical cache settings.

Fix

Add optional params field to AgentConfig and resolve it in resolveExtraParams():

// types.agents.ts
export type AgentConfig = {
  // ...existing fields...
  params?: Record<string, unknown>;
};
// extra-params.ts — resolveExtraParams now accepts agentId
const agentConfig = cfg?.agents?.list?.find((a) => a.id === params.agentId);
return Object.assign({}, globalParams, agentConfig?.params);

Agent params merge on top of global model defaults. Three files changed, no new dependencies.

Config example:

{
  "agents": {
    "list": [{
      "id": "risk-reviewer",
      "params": { "cacheRetention": "none" }
    }]
  }
}

Test plan

  • Per-agent params returned when agentId matches
  • Agent params merge over global model defaults (agent wins)
  • Unmatched agentId returns undefined (no side effects)

Local Validation

  • pnpm build
  • pnpm check (format + tsgo + lint) ✅
  • Relevant test suites pass ✅

Contribution Checklist

  • Focused scope — single feature per PR
  • Clear "what" + "why" in description
  • AI-assisted (Claude) — reviewed and tested by human
  • Local validation run (pnpm build && pnpm check)

AI-assisted (Claude). Reviewed and tested by human.

Greptile Summary

Adds per-agent params override support to resolveExtraParams, allowing individual agents to customize stream parameters (e.g., cacheRetention, temperature) that previously could only be set globally per model. Agent-level params merge on top of global model defaults, with agent values winning on conflict.

  • Adds optional params?: Record<string, unknown> field to AgentConfig type
  • Extends resolveExtraParams and applyExtraParamsToAgent with optional agentId parameter
  • Passes sessionAgentId through at the call site in attempt.ts
  • Three new tests cover match, merge, and no-match scenarios
  • Backward-compatible: all new parameters are optional, existing behavior unchanged when agentId is not provided

Confidence Score: 5/5

  • This PR is safe to merge — it's a small, well-scoped additive feature with proper tests and no breaking changes.
  • The change is minimal (4 files, ~50 lines of logic), fully backward-compatible (all new parameters are optional), and well-tested. The merge semantics (Object.assign with agent overriding global) are correct and straightforward. The integration point in attempt.ts correctly passes the already-resolved sessionAgentId. No security concerns, no mutation of config objects, and existing call sites don't need updating.
  • No files require special attention.

Last reviewed commit: 8c13172

(4/5) You can add custom instructions or style guidelines for the agent here!

Add optional `params` field to AgentConfig so individual agents can
override stream params like cacheRetention. Agent params merge on top
of global model defaults, allowing low-traffic agents (e.g., cron jobs)
to disable caching and avoid wasted cache write costs.

Fixes openclaw#17112
@openclaw-barnacle openclaw-barnacle bot added agents Agent runtime and tooling size: S labels Feb 15, 2026
@rrenamed rrenamed changed the title feat(cache): per-agent params for cacheRetention control feat(cache): per-agent params for cacheRetention control (#17112) Feb 15, 2026
@steipete steipete closed this Feb 16, 2026
@steipete steipete reopened this Feb 17, 2026
@openclaw-barnacle
Copy link

This pull request has been automatically marked as stale due to inactivity.
Please add updates or it will be closed.

@openclaw-barnacle openclaw-barnacle bot added stale Marked as stale due to inactivity and removed stale Marked as stale due to inactivity labels Feb 22, 2026
@steipete
Copy link
Contributor

Closing as covered by landed equivalent changes.

Implemented and landed:

  • 8e37c7021 — add per-agent params overrides merged on top of model defaults in resolveExtraParams.
  • Pass sessionAgentId through applyExtraParamsToAgent from run/attempt.ts.
  • Add schema support for agents.list[].params in src/config/types.agents.ts.
  • Add regression tests covering match / merge-precedence / no-match behavior.

This delivers per-agent cache tuning (e.g. cacheRetention) without affecting agents that rely only on model defaults.

@steipete steipete closed this Feb 23, 2026
iamjulio pushed a commit to NeuroGym-Dev/openclaw that referenced this pull request Feb 23, 2026
* upstream/main: (1467 commits)
  fix(doctor): use gateway health status for memory search key check (openclaw#22327)
  refactor: harden reset notice + cron delivery target flow
  refactor(exec): simplify env-prefixed wrapper modifier check
  fix(skills): support multiline frontmatter fallback without PyYAML
  fix(skills): make quick_validate work without PyYAML
  fix(exec): bind env-prefixed shell wrappers to full approval text
  fix(browser): derive relay auth token from gateway token in Chrome extension
  Browser relay: accept raw gateway token in extension auth
  fix(gateway): include platform and reason in node command rejection error
  CLI: fix gateway restart health ownership for child listener pids (openclaw#24696)
  docs: detail per-agent prompt caching configuration
  fix(config): tighten bedrock cache-retention type narrowing
  feat(agents): add per-agent stream params overrides for cache tuning (openclaw#17470) (thanks @rrenamed)
  fix(providers): support Bedrock Anthropic cacheRetention defaults/pass-through (openclaw#22303) (thanks @snese)
  fix(providers): disable Bedrock prompt caching for non-Anthropic models (openclaw#20866) (thanks @pierreeurope)
  docs(changelog): note /new and /reset auth-label removal (openclaw#24409)
  fix(reply): omit auth labels in /new and /reset
  docs(changelog): correct kimi issue references
  test(tools): fix kimi web_search mock typing
  feat(media): add moonshot video provider and wiring
  ...

# Conflicts:
#	ui/src/ui/app-render.ts
#	ui/src/ui/controllers/agents.ts
carlosrivera pushed a commit to myascendai/meshiclaw that referenced this pull request Feb 23, 2026
mreedr pushed a commit to mreedr/openclaw-custom that referenced this pull request Feb 24, 2026
@BillChirico
Copy link
Contributor

BillChirico commented Feb 24, 2026

Are the available params documented anywhere? And how would you set it for cron jobs specifically?

@rrenamed
Copy link
Contributor Author

rrenamed commented Feb 24, 2026

@BillChirico Docs are here: https://docs.openclaw.ai/reference/prompt-caching and the config reference covers the schema too.

For cron jobs, they inherit params from whichever agent they run on. So you'd set it on the agent in agents.list[], not on the cron itself:

{
 "agents": {
   "list": [{
     "id": "my-cron-agent",
     "params": { "cacheRetention": "none" }
   }]
 }
}

If your crons don't target a specific agent you can also set it per-model under agents.defaults.models["<MODEL>"].params. Per-agent wins over model defaults when both are set.

@BillChirico
Copy link
Contributor

Ah, so I'd make a specific cron agent @rrenamed, thank you! Do you have any other recommendations on how to use this to save tokens or anything else? Different types of agents or something.

@rrenamed
Copy link
Contributor Author

Depends on your setup but the main win is disabling cache on anything low-traffic. We have a couple of cron agents that fire every 30min to 1h with small prompts, setting cacheRetention: "none" on those saved us roughly 25% on daily API spend since the cache writes were just expiring unused.

For high-traffic agents (main orchestrator, anything getting frequent messages) keep the default caching, that's where it actually pays off.

@rrenamed
Copy link
Contributor Author

rrenamed commented Feb 24, 2026

Other than that, model routing helps more than cache tuning honestly. We run Haiku for simple cron jobs (daily reports, health checks) and only use Opus/Sonnet for the agents that need it. That alone cut our costs way more than the cache stuff did. We went from like $8/day to around $2-3/day just from routing the right models to the right jobs.

@BillChirico Hope this helps:)

@rrenamed rrenamed deleted the feat/per-agent-cache-retention branch February 24, 2026 10:55
@BillChirico
Copy link
Contributor

Other than that, model routing helps more than cache tuning honestly. We run Haiku for simple cron jobs (daily reports, health checks) and only use Opus/Sonnet for the agents that need it. That alone cut our costs way more than the cache stuff did. We went from like $8/day to around $2-3/day just from routing the right models to the right jobs.

@BillChirico Hope this helps:)

Thank does a ton thank you! You're able to route models that low level?

@rrenamed
Copy link
Contributor Author

rrenamed commented Feb 24, 2026

Thank does a ton thank you! You're able to route models that low level?

Yeah, each agent and cron can have its own model. In your config:

{
  "agents": {
    "list": [
      {
        "id": "main",
        "model": "openrouter/openai/gpt-5.2"
      },
      {
        "id": "daily-report",
        "model": "ollama/llama3:8b"
      }
    ]
  }
}

For crons you set the model directly when you create it:
npx openclaw cron add --name "daily-report" --model "<MODEL>" ...

So you can mix and match however you want. Heavy reasoning on Opus or GPT-5.2, coding on Sonnet or Codex, lightweight crons on Haiku or a local Ollama model. Each one gets its own model + params independently.

One thing that's worked well for us is having a second agent validate the first one's output. Like our main agent runs on one model and a separate tester agent on a cheaper one double-checks its work. Catches a lot of stuff the primary misses.

plgs2005 pushed a commit to plgs2005/openclaw that referenced this pull request Feb 24, 2026
@BillChirico
Copy link
Contributor

@rrenamed Can I contact you on Discord? This is a huge help and just have a couple more questions. My Discord is Bapes

@BillChirico
Copy link
Contributor

@rrenamed I accidentally ignored your Discord invitation. Just sent you another one!

moliendocode added a commit to moliendocode/openclaw that referenced this pull request Feb 25, 2026
PR openclaw#17470 added per-agent `params` overrides to the TypeScript type
(`AgentConfig`) and runtime logic (`extra-params.ts`) but missed adding
the field to the Zod validation schema.  Because `AgentEntrySchema` uses
`.strict()`, any `params` key in the agent config is silently rejected
at parse time, making the feature unusable.

Add `params: z.record(z.string(), z.unknown()).optional()` to
`AgentEntrySchema` to match the existing type definition.

Closes openclaw#25903

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
margulans pushed a commit to margulans/Neiron-AI-assistant that referenced this pull request Feb 25, 2026
brianleach pushed a commit to brianleach/openclaw that referenced this pull request Feb 26, 2026
mylukin pushed a commit to mylukin/openclaw that referenced this pull request Feb 26, 2026
r4jiv007 pushed a commit to r4jiv007/openclaw that referenced this pull request Feb 28, 2026
darcuri pushed a commit to darcuri/openclaw that referenced this pull request Feb 28, 2026
darcuri pushed a commit to darcuri/openclaw that referenced this pull request Feb 28, 2026
moliendocode added a commit to moliendocode/openclaw that referenced this pull request Mar 3, 2026
PR openclaw#17470 added per-agent `params` overrides to the TypeScript type
(`AgentConfig`) and runtime logic (`extra-params.ts`) but missed adding
the field to the Zod validation schema.  Because `AgentEntrySchema` uses
`.strict()`, any `params` key in the agent config is silently rejected
at parse time, making the feature unusable.

Add `params: z.record(z.string(), z.unknown()).optional()` to
`AgentEntrySchema` to match the existing type definition.

Closes openclaw#25903

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Per-agent prompt cache control (cacheRetention config key)

3 participants