> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mesh.texturehq.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Run scratch storage

> Keep large tool results and temporary working data in bounded run-scoped storage.

The scratch store holds temporary working data within a run. Large tool results
can spill into it automatically, and the agent can write explicit notes with
`scratch_*` tools. These entries expire; use [durable memory](/versioned-state)
for information that must survive across work.

## Why it exists

Context is the only data bus between tool calls in a text turn. Every byte a
tool returns is serialized back into the prompt for the next model call. A
code-execution turn hides its intermediate state in the sandbox — files,
variables, a 40k-line DOM parsed down to the one number the agent wanted — and
returns only a summary. A browser, query, or workspace-read turn has nowhere to
put a large result but the prompt. So the blob floods context, the model
re-summarizes and truncates it, loses the thread it was following, and the turn
fails.

The scratch store is the missing out-of-context scratch space. It backs two
surfaces over the **same rows**, distinguished by a `kind` column:

* **Auto output-handles.** When a tool result exceeds a byte
  threshold (`spillThresholdBytes`, \~8 KiB), the full content is spilled to the
  store under a generated handle id and only a compact stub —
  `{handle, preview, size, note}` — enters context. A `read_handle` verb slices
  the stored blob by byte range or returns the windows that match a substring,
  so a large result is read back in pieces instead of re-entering context whole.
* **Explicit scratchpad.** `scratch_write` / `scratch_read` /
  `scratch_list` / `scratch_delete`: a deliberate per-run key/value the agent
  writes interim notes to, over the same store.

## What it is NOT

It is not durable memory. Versioned-state is what an agent *chose to remember*:
curated, durable, retrieved across conversations, auditable forever. This is
what an agent is *holding right now*: cheap, TTL-bounded, garbage after the run.
The two never share a table, a retention policy, or a reader. `internal/scratch`
touches `scratch_entries` and nothing else; it never reads or writes the
versioned-state tables.

## Scoping is multiplayer-first

A row belongs to one `(run_id, agent_id)` pair. The run has one owning agent.
Every read and write is scoped by both IDs and enforced in SQL. Deleting a run
or agent cascades to its scratch entries. Completing a run does not itself
delete its row; live entries otherwise remain until expiry or explicit deletion.

## Retention

Entries carry an `expires_at` (default one hour, `scratch.DefaultTTL`). Reads
filter on live expiry, so an expired row is invisible before it is collected.
`runScratchSweeps` deletes expired rows every few minutes as a backstop; the
primary GC is the `ON DELETE CASCADE` from the run row.

## The spill decision

`shouldSpill` is deliberately conservative — when in doubt, do not spill, because
a wrongly-spilled result some downstream contract expected verbatim is a bug,
and a result left in context is merely large. It never spills when the
observation carries structured out-of-band meaning the stub would strip:
`ArtifactID`, `MutationComplete`, `Metadata`, or a memory-write receipt
(`MemoryEntryID`/`Persisted`). It skips the always-on internal verbs by name
(`report_progress`, the memory and scratch verbs, `tool_search`). It spills only
the result classes that actually flood context — `query`, `workspace`,
`browser` — and leaves `effect`-class results alone. A spill failure is never a
turn failure: the full result is returned to context as if the layer were not
there, with a loud log.

## Relationship to compaction

This is complementary to `internal/turn/compaction.go`, not a replacement.
Compaction trims the whole conversation window once it is already too big;
output-handles keeps one oversized result out of the window to begin with.
Compaction still runs over everything that does enter.

## Inspection limits

There is no scratch HTTP endpoint or dedicated dashboard inspector. The store's
`ListScratchEntriesForRun` query returns live-entry metadata (keys, sizes,
previews and source tool). The previously proposed
`GET /api/agents/{slug}/runs/{run}/scratch` route is not implemented.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.