State & artifacts
Introspection separates task inputs, durable outputs, and personal memory. That makes it clear what the agent may change, what survives sandbox replacement, and what can return in a later task.
The task workspace
Most of the sandbox filesystem is ephemeral. The agent should do routine work there and use the three managed workspace directories only for resources that need their specific persistence behavior:
| Directory | Purpose | Lifetime |
|---|---|---|
/workspace/files | User-uploaded resources and files supplied by the recipe | Read-only inputs for the current task |
/workspace/outputs | Intentional artifacts the agent wants to return from the task | Task-scoped; restored if the sandbox is replaced and surfaced as task outputs |
/workspace/memories | Durable context the agent learns about the current owner | Owner-scoped; available to later tasks for the same owner in the same project and environment |
Repository checkouts also land in the workspace: a task that clones
recipe-declared repositories gets each one at
/workspace/repos/<name> at boot.
Introspection mounts these directories, but with one exception it does not
automatically inject workspace usage instructions into the agent’s prompt. A
recipe that expects its agent to use them must add that guidance to
SYSTEM.md or the agent’s
system_instructions, including the relevant paths,
access rules, and persistence behavior.
The exception is uploads attached to a task: their paths are announced to the agent on the turn they arrive, so it knows a file was handed to it. See Input files.
Input files
/workspace/files contains resources supplied to the task, including user
uploads and files packaged by the recipe. The agent can read them but should
not modify them. Local changes to this directory are not persisted.
Uploads are attached by id through the files field on task and run creation —
see the CLI, JavaScript,
or Python docs. A file attached
partway through a conversation lands before that turn runs, without restarting
the sandbox.
Their paths, and only their paths, are announced to the agent on the turn the file arrives:
<uploaded_files>
<file path="/workspace/files/spec.md" />
</uploaded_files>Contents are never injected — the agent reads the file itself, so a large
attachment costs nothing until it does. A file the platform cannot serve is
reported as status="unavailable" with a reason rather than failing the task,
so the agent can say the attachment did not arrive instead of inventing its
contents. Because rehydration re-fetches the original bytes, an agent’s local
edits under this directory do not survive a sandbox replacement.
Outputs
/workspace/outputs is for deliberate, lightweight deliverables such as a
report, research notes, or structured results. Files written there survive a
sandbox replacement during the task and appear as the task’s output files.
Dependencies, caches, build products, logs, and routine intermediate work
belong in the ephemeral workspace rather than in outputs.
The one size limit
Every file a task reads or writes through these managed workspace directories is limited to 25 MB per file — applied per file, with no aggregate total. The one exception sits outside the workspace: files created directly through the Files API may be up to 50 MB per file.
That bound governs what a task reads and writes. Files a recipe ships in its own
files/ directory are bounded separately, at package time, by the limits in
Packaging a recipe.
Files, shares, and forks
A file is a durable, versioned project artifact. When a task writes new
content to a file, it creates a new version rather than overwriting history.
Use files for generated reports, uploaded inputs, datasets, and other durable
artifacts. Inside a task, uploaded inputs appear in /workspace/files, while
artifacts written to /workspace/outputs are saved as output files. The rest
of the sandbox filesystem is temporary.
There is no restore verb: recovering an earlier version means reading it and writing it back, which lands as a new version rather than rewinding the history.
A share is a read-only grant for one file or conversation. It can be shared with a project, one member, or one end-user identity. It never grants write access or changes ownership. Tasks themselves are not shareable. Share a conversation when someone else needs to reproduce or investigate work; they can then fork a new, independent task from that immutable record.
A fork tries to seed the new task with the shared conversation. If that source can no longer be loaded, the new task can still be created without the copied history. Keep the share available until the forked task has started if the earlier context is required.
A share reaches one member and grants read only; to give a group read and write over a growing set of files, use a tag instead — see Choosing between tags and shares.
Use runner.files for files and versions, and runner.shares for read-only
grants. Both are Data Plane namespaces, so in the Node and Python SDKs they hang
off the runner rather than the top-level client. The browser client talks only
to the Data Plane, so it carries files and shares directly. The
JS SDK shows the runner API, and
Browser applications covers the browser
client’s equivalent namespaces.
Memory
Memory is durable, file-backed context that an agent can carry from one task
to another for the same owner. It is mounted at /workspace/memories, where the
agent reads and writes ordinary files. The platform mounts and synchronizes
those files, but it does not create a default memory file, summarize the files,
or add any memory index or contents to the agent’s prompt. Each Recipe chooses
its own filenames and loading strategy.
Memory is always private to one owner. Use it for stable preferences, decisions,
notes, and small useful facts—not task artifacts, transient notes, credentials,
or instructions that override the current task. Large artifacts belong in
files, and credentials belong in bindings, never memory.
The runtime synchronizes .md, .txt, and .json memory files; it ignores
other file types.
For skill-like progressive disclosure, build a recipe
extension that scans Markdown files under
/workspace/memories, parses lightweight YAML frontmatter, and adds only a
catalog of paths and descriptions during before_agent_start. The agent can
then open the relevant memory file when needed, just as it chooses a skill
from skill metadata without loading every skill body up front.
Fields such as name and description are a convention owned by that
extension, not a platform memory schema. Treat the files as owner-provided
data, validate their paths and metadata, and do not inject their full bodies
into the prompt.
How memory carries forward
The lifecycle is:
- A task starts with the current versions of the owner’s memory files mounted.
- The agent changes those files with its normal file tools.
- Checkpoints and successful task completion save changed files as new versions.
- A later task for the same owner mounts the current versions.
Memory is scoped by project, environment lane, identity kind, and identity value—not by Runtime. It can therefore remain across sandbox replacement and Runtime versions, but never crosses into another owner, lane, or project.
Owner eligibility
| Task context | Memory owner |
|---|---|
| SDK task using an API key or service account with runner identity | First available of user_id, anonymous_id, then conversation_id |
| SDK task using a federated customer session | The authenticated customer |
| Task without an eligible identity | None; /workspace/memories is absent |
For application traffic performed on behalf of a subject, open the task through a server-side SDK. Authenticate the calling application with an API key or service-account credential, and provide a stable runner identity for the subject to whom the task should be attributed. The credential identifies the calling application; the runner identity identifies the subject on whose behalf it runs:
const runner = await client.runtimes("support-agent").run({
identity: { user_id: "customer-123" },
});The ID is an opaque string of at most 255 characters. Reuse the exact value and
do not add a user: prefix; the platform namespaces it. anonymous_id and
conversation_id create separate owner scopes. If several kinds are supplied,
selection uses user_id, then anonymous_id, then conversation_id.
Memories are only available when using the SDK with a valid subject. They are not available when tasks are invoked through:
- Dashboard Runtime chat
- Runtime Preview or its chat opened by
introspection dev introspection devintrospection local- A browser-authenticated CLI member session
For ineligible tasks, /workspace/memories is not created. Passing CLI
--subject provides a routing identity, but does not make a
browser-authenticated member session eligible for memories.
Concurrent updates
Concurrent tasks may start from the same memory version. The platform currently specifies no merge, compare-and-swap, or last-writer rule for conflicting updates. Serialize tasks that can write the same owner’s memory until conflict semantics are defined.
What belongs where
| Need | Use |
|---|---|
| Give the agent an uploaded or recipe-provided input | /workspace/files |
| Keep a generated report, dataset, or other output | /workspace/outputs |
| Let someone read a file or conversation | A read-only share |
| Let a group read and write a growing set of files and tasks | A tag carried by both the rows and the group’s members |
| Reproduce work from someone else’s conversation | A fork created from a shared conversation |
| Carry an owner’s stable preferences into later tasks | /workspace/memories |
As a concrete example: a research agent may save its final report as a file, share the source conversation with a reviewer, and let that reviewer fork a new task to challenge one conclusion. The agent can remember the original user’s preferred output format for next time, while that personal memory remains unavailable to the reviewer.
Related
- Tasks & runs: execution sessions, replayable records, and conversation forks.
- Tags: grouping files and tasks, and sharing them with a cohort of members.
- Authentication & identity: how identity scopes memory.