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

# Thread

> Durable thread runtime, queueing, and parent/child subagent state

## What Is a Thread?

A thread is a conversation instance backed by a Cloudflare Durable Object and SQLite state.

Each thread has isolated:

* messages
* execution state
* logs
* filesystem

## Durable Runtime

New projects do not create local Durable Object subclass files. The `builder()`
Vite plugin generates the Worker entry and exports the built-in thread and
builder Durable Objects with the required Cloudflare bindings and migrations.

## ThreadState APIs

Tools/hooks/endpoints receive `ThreadState`.

Key methods:

* `getMessages()` / `injectMessage()` / `updateMessage()`
* `queueMessage()`
* `getParentThread()` / `getChildThread(referenceId)`
* `terminate()`
* filesystem methods (`readFile`, `writeFile`, etc.)
* `status()` — the thread's authoritative run status (see below)
* `log(entry)` — record an application log entry (see below)

Key properties:

* `children` (resumable child registry)
* `terminated`
* `arguments` (read-only invocation or creation arguments)
* `context` (mutable scratch data for the current execution only)

## Run Status

`await state.status()` returns the thread's `ThreadStatus`:
`{ state: 'idle' | 'running' | 'failed', since, reason }`. `since` is in
microseconds; `reason` is the raw stop reason code of the last transition out
of `running` (`stop_on_response`, `stop_tool`, `awaiting_human`,
`hook_blocked`, `aborted_by_user`, `step_error`, `execution_lost`, …). A run
that hands the turn to a human side settles as `idle` with reason
`awaiting_human` (or the code that ended the turn); the status describes
execution, not whose turn it is.

The status is persisted with the thread, so it survives restarts, and a run
the runtime lost settles to `failed` (`execution_lost`) instead of staying
`running`. Clients receive it without polling: `GET /api/threads/:id` includes
`status`, and the [message stream](https://docs.standardagents.ai/api-reference/websocket/stream.md) sends a
`thread_status` snapshot on connect and a frame on every change.

`status()` is unrelated to `setStatus(label)`, which writes a free-form label
into this thread's entry in its parent's subagent registry.

## Application Logs

`await state.log(entry)` records an application entry in the thread's logs,
next to the runtime's own LLM request, tool, and handler rows. Any code with a
`ThreadState` can write one; only `name` is required.

A plain event is a name and a message:

```typescript theme={null}
await state.log({ name: 'cache.miss', level: 'debug', message: 'cold start' });
```

An entry that records an operation (a call to another service, a decision, a
background job) also says what caused it, what was sent, what came back, how
long it took, and what it cost:

```typescript theme={null}
await state.log({
  name: 'search.query',
  status: 'success',
  message: 'Found 12 flights',
  trigger: { kind: 'message', id: messageId, summary: 'User asked for flights' },
  request: { q: 'flights to Lisbon' },
  response: { results: 12 },
  duration_ms: 182,
  cost: 0.0004,
});
```

| Field | Meaning |
| - | - |
| `name` | Short event name, e.g. `cache.miss`. Required. |
| `message` | One human-readable line. |
| `level` | `debug`, `info`, `warn`, or `error`. Defaults to `error` when `status` is `error`, otherwise `info`. |
| `status` | Outcome of the operation: `success`, `error`, or `skipped`. |
| `trigger` | The event that caused the entry: `{ kind, id?, summary? }`. |
| `request` | What was sent, or the input that triggered the work. Any JSON value; strings stay text. |
| `response` | What came back. Any JSON value; strings stay text. |
| `error` | Failure reason. |
| `duration_ms` | Duration in milliseconds. |
| `cost` | Cost in USD, when the operation cost money. Counts toward the thread's cost totals alongside its LLM request costs. |
| `data` | Any other structured detail. |

Entries are delivered to live log subscribers and returned by
`GET /api/threads/:id/logs` as rows with `kind: 'app'`: `model` holds the
name, and the other fields are `app_level`, `app_message`, `app_status`,
`app_error`, `app_duration_ms`, `app_cost`, plus JSON text in `app_request`,
`app_response`, `app_trigger`, and `app_data`. The builder UI opens these rows
in the log detail pane with the trigger, duration, cost, and Request and
Response tabs, and show the cost in the logs table's Cost column.

An entry's `cost` is part of what the thread cost: `GET /api/threads/:id/cost`
adds it to `totalCost` (and to the thread's row in the per-thread
breakdown), and reports the application share apart as `appCost`. The
per-model breakdown and `requestCount` cover LLM requests only. The row's own
`cost_total` stays null; it is the LLM request cost.

Logging never creates a message and never starts or wakes an execution, so it
is safe from hooks, tools, effects, and endpoints. It never throws because of
an entry's content: fields of the wrong type are dropped, values that cannot be
JSON-encoded are replaced by a marker object, and oversized fields are
truncated with a marker (`name` to 120 characters, `message` and `error` to
4 KiB, the JSON of `data` to 16 KiB, and the JSON of `request` and `response`
to 64 KiB each). Entries attach to the thread's newest message; on a thread
with no messages yet the entry is written to the Worker console only.

## User Identity and Application Roles

`await state.user()` returns the thread owner's identity and user handle, or
`null` for a thread without a user. Its optional `roles` array carries
application-defined strings from the runtime's identity authority. Hosted
Standard Agents Builder instances receive them from Platform through signed updates.
Check roles in each protected request or execution and treat absent roles as
an empty assignment. Identity is memoized within an execution; pushed changes
are visible on the next request or execution. These strings do not change built-in instance access levels
or permissions. See [application role checks](https://docs.standardagents.ai/core-concepts/api.md#guarding-user-endpoints-with-application-roles)
for a server-side endpoint example.

## Queue Semantics

`queueMessage()` is durable and ordered:

* if thread is active, queued messages are injected before the next model step
* if thread is idle, queueing forces execution
* queue entries survive eviction
* message APIs expose `sendMessage()` and `queueMessage()` queued entries as pending messages with `metadata.queued: true`

## Parent/Child Communication

Subagent communication is message + filesystem aware:

### Parent -> Child

* initial invocation mapping and resumable `subagent_message`
* `subagent_create.arguments` persists with the child thread as `ThreadState.arguments` and renders as prompt variables for both child sides
* any referenced attachments are copied parent -> child

### Child -> Parent

* completion/failure payloads are queued as silent parent messages
* returned attachments are copied child -> parent
* copied attachment paths are rewritten for the destination thread

## Termination

`terminate()` performs soft shutdown:

* sets `terminated` timestamp
* aborts in-flight execution
* rejects new execution/queue operations; `POST /api/threads/{threadId}/messages` and the debug `POST /api/threads/{threadId}/continue` return `423` and store nothing
* keeps the non-execution thread routes working: reading, listing, updating, reading and deleting messages, files, stop, the stream, and deleting the thread
* propagates child termination status to parent registry when linked

## Registry and Message Projection

Parent threads maintain a child registry for resumable instances.

Messages may carry projected subagent fields (for UI/client grouping), including:

* `subagent_id`
* `subagent_name`
* `subagent_title`
* `subagent_status`
* `subagent_resumable`
* `subagent_blocking`

## Related Docs

* [Subagents](https://docs.standardagents.ai/core-concepts/subagents.md)
* [Tools](https://docs.standardagents.ai/core-concepts/tools.md)
* [API: get messages](https://docs.standardagents.ai/api-reference/rest/get-messages.md)


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