Skip to content

Attach artifact

A session is more than a list of messages. The agents package treats four kinds of attached state as first-class:

  1. Messagessession_messages table. Already covered in create-session.
  2. Target snapshot — the introspect tree of the target actor at session start.
  3. REPL state — the omega-lisp REPL's serialized environment, when $eval has been used.
  4. Activity frames — the per-request trace log.

Target snapshot

Stored under session_state(session_id, key='snapshot'). The value is the JSON-serialized tree from a $introspect call on the target actor: its accepts, state, declared children, and so on.

The oracle prompt builder uses the snapshot to give the model structured awareness of what the target IS. A resume restores the snapshot from disk so the model sees the same target shape across turns.

ts
// Session-store interface (IAgentSessionStore.ts:74-76)
saveSnapshot(sessionId: string, tree: OracleTreeNode): Promise<void>;
loadSnapshot(sessionId: string): Promise<OracleTreeNode | null>;

REPL state

Stored under session_state(session_id, key='repl_state'). The value is SerializedReplState:

ts
type SerializedReplState = {
  env?: Record<string, unknown>;  // bindings
  history?: string[];             // recent expressions
};

The REPL is hydrated at the start of an $eval turn from loadSessionState(sessionId, 'repl_state') and re-serialized after the turn. This is the mechanism behind "state persists across sessions" — it's just JSON in a SQLite row.

Activity frames

Stored via the IAgentSessionStore.appendActivityFrames interface, not in the SQLite session store. Two backends:

BackendStorage
FileAgentSessionStore<host-home>/sessions/<sessionId>/activity-<requestId>.jsonl
RecordBackedSessionStorerows in the observability record store

Frames are append-only per request id. loadActivityFrames(sessionId, requestId?) returns a single request's frames or all frames for the session.

What CANNOT be attached

  • File uploads. The agent platform does not have an artifact-upload op. If a workflow needs files, those files live somewhere else (the package's own storage) and the session references them by path.
  • Inference responses themselves. Only the rendered text/tool calls are stored as messages. Provider-specific raw payloads stay in observability.
  • Credentials. Ever.

Target state

A first-class "attach repository" or "attach repo worktree" affordance is implied by the repo-coding tool context (ToolContextSpec.ts:69-94) and the WorkerRef.host.repoRoots field (runtime/WorkerRef.ts), but there is no session.attachArtifact op today. Attaching a repo is currently done by configuring the agency profile to use a propose profile with a repo-coding skill — the worker's environment carries the repo root, not the session.

See also

Source: projects/matrix-3/packages/agents/src/AgentsStore.ts:535-545 (session_state CRUD), projects/matrix-3/packages/agents/src/IAgentSessionStore.ts:65-80 (snapshot/REPL/activity surface).