agent re-fetched the same ticket 40 times: per-run cache
A guide to stopping agents from re-fetching the same ticket repeatedly, in the business-apis-integrations category: per-run caching, fetch dedup, and request budgeting. Use when agents hammer the API with duplicate reads, runs are slow from redundant fetches, or when optimizing agent API usage. Not for long-term caching strategy, CDN design, or API rate limit tiers.
TL;DR
An agent that fetches the same ticket 40 times has no memory of its own reads: every step re-reads what an earlier step already knew. Add a per-run cache: the first fetch stores the ticket, later reads hit the cache, and the run makes exactly one API call per ticket. Duplicate reads are pure waste; the cache deletes them.
The query
agent re-fetched the same ticket 40 times: per-run cacheUse this when
- Agents make duplicate API reads
- Runs are slow from redundant fetches
- API usage is higher than ticket count explains
- You are optimizing agent efficiency
Not for
- Cross-run caching architecture
- CDN or edge caching
- Choosing API rate limit plans
- Webhook design
Steps
1. Count the duplicate reads first
Log API reads per ticket per run. The count justifies the fix and shows where reads cluster: usually a "get ticket, decide, get ticket again" pattern in the agent loop. Measure before optimizing.
Expected output: duplicate-read counts per run.
2. Add a per-run ticket cache
A simple in-memory map: ticket id to fetched ticket, living for the duration of the run. Every read checks the map first. One map, one lookup, forty fetches become one.
Expected output: a run-scoped cache on the read path.
3. Invalidate on write within the run
If the agent updates a ticket mid-run, the cached copy is stale. Invalidate or update the cache entry on every write the agent makes. A cache that serves pre-write data creates subtle wrong-decision bugs.
Expected output: write-through or invalidate-on-write.
4. Scope the cache to the run, not globally
A per-run cache dies with the run: no cross-run staleness, no invalidation protocol, no shared-state bugs. Resist promoting it to a persistent cache; the simplicity is the point.
Expected output: run-scoped lifetime, no persistence.
5. Budget API reads per run and alert on excess
Set an expected reads-per-ticket ratio (near 1.0) and alert when a run exceeds it. The budget catches future regressions: a new agent step that re-fetches shows up immediately as a budget breach.
Expected output: per-run read budgeting with alerts.
Template: the checklist
Per-run fetch dedup:
[ ] Duplicate reads counted per run
[ ] Run-scoped ticket cache on the read path
[ ] Cache invalidated on mid-run writes
[ ] Cache lifetime tied to the run only
[ ] Read budget per run with alertsVariant phrasings
agent fetching same ticket repeatedly
Steps 1 and 2. Count, then cache.
duplicate api reads agent loop
Steps 2 and 3. Cache plus write invalidation.
reduce zendesk api calls agent
Steps 2 and 5. Cache plus budgeting.
Why it happens
Agent frameworks encourage "fetch fresh" as the safe default: each tool call reads the ticket to avoid stale data. Across a 40-step run, "safe" becomes 40 identical reads. Nobody notices because each read succeeds; the waste is visible only in aggregate API usage. The per-run cache restores the obvious truth: the ticket did not change between step 3 and step 4.
Edge cases
- Long runs where tickets genuinely change: for multi-hour runs, add a TTL or re-fetch on explicit "refresh" actions. Match staleness tolerance to reality.
- Memory growth on huge runs: a run touching 100k tickets should not cache them all. Bound the cache with eviction.
- Concurrent agents on the same tickets: per-run caches do not coordinate. That is fine; coordination is a different problem.
- Reads for side effects (auditing): if the read itself must hit the API (audit logging), bypass the cache deliberately and document why.
Provenance
Resolved from the public thread: https://vectle.com/posts/pst_LQjlf4hrjMuEaVnw64H5zg