Summary
When a cron job runs against an OpenAI responses-API model (e.g. openai/gpt-5.5), OpenClaw sets prompt_cache_key = options.sessionId (provider-stream-CiQISJm-.js:1376). Cron runs are spawned with isolated session ids of the form agent:<agent>:cron:<jobId>:run:<runId>, where <runId> is unique per execution. Result: every cron run gets a fresh prompt_cache_key, OpenAI's prompt cache (24h TTL) never matches across runs, and the same recurring prompt is billed at full input price every time.
By contrast, Anthropic's automatic prefix caching IS hit across runs (because it works on prefix hash, not session id), so the same cron costs ~10% as much on Anthropic vs paid OpenAI.
Concrete impact
In one user's environment, 2 high-frequency crons (*/15 * * * * with lightContext: true) were observed at:
- Anthropic Opus 4.7: ~9 to 11 input tokens billed per run (rest cached).
- OpenAI GPT-5.5 (responses API): ~104K to 125K input tokens billed per run, 0% cache reuse.
That is roughly a 10,000x billable-input ratio for the same prompt. Combined with reasoning tokens billed at output rate, this drove ~$70 of unintended OpenAI spend across 2 days from cron jobs that the user expected to be cheap.
Workarounds (each has drawbacks)
sessionTarget: "session:<stable-id>" to keep the sessionId stable across runs. Side effect: conversation history accumulates inside that session over time, defeating the clean-state intent of cron jobs.
- Pin every cron to a non-OpenAI provider. Works, but loses the option of using OpenAI for crons that genuinely benefit from it.
- Avoid making OpenAI the agent defaults primary while any cron uses it.
Proposed feature
Allow cron payloads (and ideally any agentTurn payload) to set an explicit promptCacheKey (or cacheKey) value that overrides the default sessionId-based key. The intended pattern: a cron job sets promptCacheKey: "cron:<jobId>" once, and every run of that job hits the same OpenAI cache entry as long as the prompt prefix is stable.
This should compose with the existing cacheRetention controls and respect provider compatibility (compat.supportsPromptCacheKey).
Optional second improvement
Consider warning at config-validation time when a cron payload pins a model id that isn't in the registered model catalog. Today such pins silently fall back to agent defaults ([cron] payload.model 'X' not allowed, falling back to agent defaults only appears in gateway.err.log at runtime), which made the cost incident much harder to predict and diagnose.
Environment
- OpenClaw 2026.4.25
- macOS 25.3.0 arm64
- Models involved:
openai/gpt-5.5 (responses API), anthropic/claude-opus-4-7, anthropic/claude-sonnet-4-6
Summary
When a cron job runs against an OpenAI responses-API model (e.g.
openai/gpt-5.5), OpenClaw setsprompt_cache_key = options.sessionId(provider-stream-CiQISJm-.js:1376). Cron runs are spawned with isolated session ids of the formagent:<agent>:cron:<jobId>:run:<runId>, where<runId>is unique per execution. Result: every cron run gets a freshprompt_cache_key, OpenAI's prompt cache (24h TTL) never matches across runs, and the same recurring prompt is billed at full input price every time.By contrast, Anthropic's automatic prefix caching IS hit across runs (because it works on prefix hash, not session id), so the same cron costs ~10% as much on Anthropic vs paid OpenAI.
Concrete impact
In one user's environment, 2 high-frequency crons (
*/15 * * * *withlightContext: true) were observed at:That is roughly a 10,000x billable-input ratio for the same prompt. Combined with reasoning tokens billed at output rate, this drove ~$70 of unintended OpenAI spend across 2 days from cron jobs that the user expected to be cheap.
Workarounds (each has drawbacks)
sessionTarget: "session:<stable-id>"to keep the sessionId stable across runs. Side effect: conversation history accumulates inside that session over time, defeating the clean-state intent of cron jobs.Proposed feature
Allow cron payloads (and ideally any
agentTurnpayload) to set an explicitpromptCacheKey(orcacheKey) value that overrides the defaultsessionId-based key. The intended pattern: a cron job setspromptCacheKey: "cron:<jobId>"once, and every run of that job hits the same OpenAI cache entry as long as the prompt prefix is stable.This should compose with the existing
cacheRetentioncontrols and respect provider compatibility (compat.supportsPromptCacheKey).Optional second improvement
Consider warning at config-validation time when a cron payload pins a model id that isn't in the registered model catalog. Today such pins silently fall back to agent defaults (
[cron] payload.model 'X' not allowed, falling back to agent defaultsonly appears in gateway.err.log at runtime), which made the cost incident much harder to predict and diagnose.Environment
openai/gpt-5.5(responses API),anthropic/claude-opus-4-7,anthropic/claude-sonnet-4-6