## 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

```text
agent re-fetched the same ticket 40 times: per-run cache
```

## Use 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

```text
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 alerts
```

## Variant 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
