[{"data":1,"prerenderedAt":61},["ShallowReactive",2],{"docs:core-concepts/thread":3},{"title":4,"navTitle":4,"description":5,"api":6,"html":7,"toc":8,"path":50,"tab":51,"group":52,"prev":53,"next":56,"markdownUrl":59,"sourceUrl":60,"lastModified":6},"Thread","Durable thread runtime, queueing, and parent/child subagent state",null,"\u003Ch2 id=\"what-is-a-thread\">\u003Ca class=\"docs-anchor\" href=\"#what-is-a-thread\" aria-label=\"Link to this section\">\u003C/a>What Is a Thread?\u003C/h2>\n\u003Cp>A thread is a conversation instance backed by a Cloudflare Durable Object and SQLite state.\u003C/p>\n\u003Cp>Each thread has isolated:\u003C/p>\n\u003Cul>\n\u003Cli>messages\u003C/li>\n\u003Cli>execution state\u003C/li>\n\u003Cli>logs\u003C/li>\n\u003Cli>filesystem\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"durable-runtime\">\u003Ca class=\"docs-anchor\" href=\"#durable-runtime\" aria-label=\"Link to this section\">\u003C/a>Durable Runtime\u003C/h2>\n\u003Cp>New projects do not create local Durable Object subclass files. The \u003Ccode>builder()\u003C/code>\nVite plugin generates the Worker entry and exports the built-in thread and\nbuilder Durable Objects with the required Cloudflare bindings and migrations.\u003C/p>\n\u003Ch2 id=\"threadstate-apis\">\u003Ca class=\"docs-anchor\" href=\"#threadstate-apis\" aria-label=\"Link to this section\">\u003C/a>ThreadState APIs\u003C/h2>\n\u003Cp>Tools/hooks/endpoints receive \u003Ccode>ThreadState\u003C/code>.\u003C/p>\n\u003Cp>Key methods:\u003C/p>\n\u003Cul>\n\u003Cli>\u003Ccode>getMessages()\u003C/code> / \u003Ccode>injectMessage()\u003C/code> / \u003Ccode>updateMessage()\u003C/code>\u003C/li>\n\u003Cli>\u003Ccode>queueMessage()\u003C/code>\u003C/li>\n\u003Cli>\u003Ccode>getParentThread()\u003C/code> / \u003Ccode>getChildThread(referenceId)\u003C/code>\u003C/li>\n\u003Cli>\u003Ccode>terminate()\u003C/code>\u003C/li>\n\u003Cli>filesystem methods (\u003Ccode>readFile\u003C/code>, \u003Ccode>writeFile\u003C/code>, etc.)\u003C/li>\n\u003Cli>\u003Ccode>status()\u003C/code> — the thread's authoritative run status (see below)\u003C/li>\n\u003Cli>\u003Ccode>log(entry)\u003C/code> — record an application log entry (see below)\u003C/li>\n\u003C/ul>\n\u003Cp>Key properties:\u003C/p>\n\u003Cul>\n\u003Cli>\u003Ccode>children\u003C/code> (child registry)\u003C/li>\n\u003Cli>\u003Ccode>terminated\u003C/code>\u003C/li>\n\u003Cli>\u003Ccode>arguments\u003C/code> (read-only invocation or creation arguments)\u003C/li>\n\u003Cli>\u003Ccode>context\u003C/code> (mutable scratch data for the current execution only)\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"run-status\">\u003Ca class=\"docs-anchor\" href=\"#run-status\" aria-label=\"Link to this section\">\u003C/a>Run Status\u003C/h2>\n\u003Cp>\u003Ccode>await state.status()\u003C/code> returns the thread's \u003Ccode>ThreadStatus\u003C/code>:\n\u003Ccode>{ state: 'idle' | 'running' | 'failed', since, reason }\u003C/code>. \u003Ccode>since\u003C/code> is in\nmicroseconds; \u003Ccode>reason\u003C/code> is the raw stop reason code of the last transition out\nof \u003Ccode>running\u003C/code> (\u003Ccode>stop_on_response\u003C/code>, \u003Ccode>stop_tool\u003C/code>, \u003Ccode>awaiting_human\u003C/code>,\n\u003Ccode>hook_blocked\u003C/code>, \u003Ccode>aborted_by_user\u003C/code>, \u003Ccode>step_error\u003C/code>, \u003Ccode>execution_lost\u003C/code>, …). A run\nthat hands the turn to a human side settles as \u003Ccode>idle\u003C/code> with reason\n\u003Ccode>awaiting_human\u003C/code> (or the code that ended the turn); the status describes\nexecution, not whose turn it is.\u003C/p>\n\u003Cp>The status is persisted with the thread, so it survives restarts, and a run\nthe runtime lost settles to \u003Ccode>failed\u003C/code> (\u003Ccode>execution_lost\u003C/code>) instead of staying\n\u003Ccode>running\u003C/code>. Clients receive it without polling: \u003Ccode>GET /api/threads/:id\u003C/code> includes\n\u003Ccode>status\u003C/code>, and the \u003Ca href=\"/docs/api-reference/websocket/stream\">message stream\u003C/a> sends a\n\u003Ccode>thread_status\u003C/code> snapshot on connect and a frame on every change.\u003C/p>\n\u003Cp>\u003Ccode>status()\u003C/code> is unrelated to \u003Ccode>setStatus(label)\u003C/code>, which writes a free-form label\ninto this thread's entry in its parent's subagent registry.\u003C/p>\n\u003Ch2 id=\"application-logs\">\u003Ca class=\"docs-anchor\" href=\"#application-logs\" aria-label=\"Link to this section\">\u003C/a>Application Logs\u003C/h2>\n\u003Cp>\u003Ccode>log()\u003C/code> is a Standard Agents Builder extension. Import the Builder SDK to load\nits TypeScript declaration:\u003C/p>\n\u003Cfigure class=\"docs-code\" data-docs=\"code\" data-lang=\"typescript\">\u003Cpre class=\"shiki shiki-themes one-light github-dark\" style=\"--shiki-light:#383A42;--shiki-dark:#e1e4e8;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#A626A4;--shiki-dark:#F97583\">import\u003C/span>\u003Cspan style=\"--shiki-light:#A626A4;--shiki-dark:#F97583\"> type\u003C/span>\u003Cspan style=\"--shiki-light:#383A42;--shiki-dark:#E1E4E8\"> { \u003C/span>\u003Cspan style=\"--shiki-light:#E45649;--shiki-dark:#E1E4E8\">ThreadLogEntry\u003C/span>\u003Cspan style=\"--shiki-light:#383A42;--shiki-dark:#E1E4E8\"> } \u003C/span>\u003Cspan style=\"--shiki-light:#A626A4;--shiki-dark:#F97583\">from\u003C/span>\u003Cspan style=\"--shiki-light:#50A14F;--shiki-dark:#9ECBFF\"> '@standardagents/builder'\u003C/span>\u003Cspan style=\"--shiki-light:#383A42;--shiki-dark:#E1E4E8\">;\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\u003C/figure>\n\u003Cp>\u003Ccode>await state.log(entry)\u003C/code> records an application entry in the thread's logs,\nnext to the runtime's own LLM request, tool, and handler rows. Any code with a\n\u003Ccode>ThreadState\u003C/code> can write one; only \u003Ccode>name\u003C/code> is required.\u003C/p>\n\u003Cp>A plain event is a name and a message:\u003C/p>\n\u003Cfigure class=\"docs-code\" data-docs=\"code\" data-lang=\"typescript\">\u003Cpre class=\"shiki shiki-themes one-light github-dark\" style=\"--shiki-light:#383A42;--shiki-dark:#e1e4e8;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#A626A4;--shiki-dark:#F97583\">await\u003C/span>\u003Cspan style=\"--shiki-light:#383A42;--shiki-dark:#E1E4E8\"> state.\u003C/span>\u003Cspan style=\"--shiki-light:#4078F2;--shiki-dark:#B392F0\">log\u003C/span>\u003Cspan style=\"--shiki-light:#383A42;--shiki-dark:#E1E4E8\">({ \u003C/span>\u003Cspan style=\"--shiki-light:#E45649;--shiki-dark:#E1E4E8\">name\u003C/span>\u003Cspan style=\"--shiki-light:#0184BC;--shiki-dark:#E1E4E8\">:\u003C/span>\u003Cspan style=\"--shiki-light:#50A14F;--shiki-dark:#9ECBFF\"> 'cache.miss'\u003C/span>\u003Cspan style=\"--shiki-light:#383A42;--shiki-dark:#E1E4E8\">, \u003C/span>\u003Cspan style=\"--shiki-light:#E45649;--shiki-dark:#E1E4E8\">level\u003C/span>\u003Cspan style=\"--shiki-light:#0184BC;--shiki-dark:#E1E4E8\">:\u003C/span>\u003Cspan style=\"--shiki-light:#50A14F;--shiki-dark:#9ECBFF\"> 'debug'\u003C/span>\u003Cspan style=\"--shiki-light:#383A42;--shiki-dark:#E1E4E8\">, \u003C/span>\u003Cspan style=\"--shiki-light:#E45649;--shiki-dark:#E1E4E8\">message\u003C/span>\u003Cspan style=\"--shiki-light:#0184BC;--shiki-dark:#E1E4E8\">:\u003C/span>\u003Cspan style=\"--shiki-light:#50A14F;--shiki-dark:#9ECBFF\"> 'cold start'\u003C/span>\u003Cspan style=\"--shiki-light:#383A42;--shiki-dark:#E1E4E8\"> });\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\u003C/figure>\n\u003Cp>An entry that records an operation (a call to another service, a decision, a\nbackground job) also says what caused it, what was sent, what came back, how\nlong it took, and what it cost:\u003C/p>\n\u003Cfigure class=\"docs-code\" data-docs=\"code\" data-lang=\"typescript\">\u003Cpre class=\"shiki shiki-themes one-light github-dark\" style=\"--shiki-light:#383A42;--shiki-dark:#e1e4e8;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#A626A4;--shiki-dark:#F97583\">await\u003C/span>\u003Cspan style=\"--shiki-light:#383A42;--shiki-dark:#E1E4E8\"> state.\u003C/span>\u003Cspan style=\"--shiki-light:#4078F2;--shiki-dark:#B392F0\">log\u003C/span>\u003Cspan style=\"--shiki-light:#383A42;--shiki-dark:#E1E4E8\">({\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#E45649;--shiki-dark:#E1E4E8\">  name\u003C/span>\u003Cspan style=\"--shiki-light:#0184BC;--shiki-dark:#E1E4E8\">:\u003C/span>\u003Cspan style=\"--shiki-light:#50A14F;--shiki-dark:#9ECBFF\"> 'search.query'\u003C/span>\u003Cspan style=\"--shiki-light:#383A42;--shiki-dark:#E1E4E8\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#E45649;--shiki-dark:#E1E4E8\">  status\u003C/span>\u003Cspan style=\"--shiki-light:#0184BC;--shiki-dark:#E1E4E8\">:\u003C/span>\u003Cspan style=\"--shiki-light:#50A14F;--shiki-dark:#9ECBFF\"> 'success'\u003C/span>\u003Cspan style=\"--shiki-light:#383A42;--shiki-dark:#E1E4E8\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#E45649;--shiki-dark:#E1E4E8\">  message\u003C/span>\u003Cspan style=\"--shiki-light:#0184BC;--shiki-dark:#E1E4E8\">:\u003C/span>\u003Cspan style=\"--shiki-light:#50A14F;--shiki-dark:#9ECBFF\"> 'Found 12 flights'\u003C/span>\u003Cspan style=\"--shiki-light:#383A42;--shiki-dark:#E1E4E8\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#E45649;--shiki-dark:#E1E4E8\">  trigger\u003C/span>\u003Cspan style=\"--shiki-light:#0184BC;--shiki-dark:#E1E4E8\">:\u003C/span>\u003Cspan style=\"--shiki-light:#383A42;--shiki-dark:#E1E4E8\"> { \u003C/span>\u003Cspan style=\"--shiki-light:#E45649;--shiki-dark:#E1E4E8\">kind\u003C/span>\u003Cspan style=\"--shiki-light:#0184BC;--shiki-dark:#E1E4E8\">:\u003C/span>\u003Cspan style=\"--shiki-light:#50A14F;--shiki-dark:#9ECBFF\"> 'message'\u003C/span>\u003Cspan style=\"--shiki-light:#383A42;--shiki-dark:#E1E4E8\">, \u003C/span>\u003Cspan style=\"--shiki-light:#E45649;--shiki-dark:#E1E4E8\">id\u003C/span>\u003Cspan style=\"--shiki-light:#0184BC;--shiki-dark:#E1E4E8\">:\u003C/span>\u003Cspan style=\"--shiki-light:#383A42;--shiki-dark:#E1E4E8\"> messageId, \u003C/span>\u003Cspan style=\"--shiki-light:#E45649;--shiki-dark:#E1E4E8\">summary\u003C/span>\u003Cspan style=\"--shiki-light:#0184BC;--shiki-dark:#E1E4E8\">:\u003C/span>\u003Cspan style=\"--shiki-light:#50A14F;--shiki-dark:#9ECBFF\"> 'User asked for flights'\u003C/span>\u003Cspan style=\"--shiki-light:#383A42;--shiki-dark:#E1E4E8\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#E45649;--shiki-dark:#E1E4E8\">  request\u003C/span>\u003Cspan style=\"--shiki-light:#0184BC;--shiki-dark:#E1E4E8\">:\u003C/span>\u003Cspan style=\"--shiki-light:#383A42;--shiki-dark:#E1E4E8\"> { \u003C/span>\u003Cspan style=\"--shiki-light:#E45649;--shiki-dark:#E1E4E8\">q\u003C/span>\u003Cspan style=\"--shiki-light:#0184BC;--shiki-dark:#E1E4E8\">:\u003C/span>\u003Cspan style=\"--shiki-light:#50A14F;--shiki-dark:#9ECBFF\"> 'flights to Lisbon'\u003C/span>\u003Cspan style=\"--shiki-light:#383A42;--shiki-dark:#E1E4E8\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#E45649;--shiki-dark:#E1E4E8\">  response\u003C/span>\u003Cspan style=\"--shiki-light:#0184BC;--shiki-dark:#E1E4E8\">:\u003C/span>\u003Cspan style=\"--shiki-light:#383A42;--shiki-dark:#E1E4E8\"> { \u003C/span>\u003Cspan style=\"--shiki-light:#E45649;--shiki-dark:#E1E4E8\">results\u003C/span>\u003Cspan style=\"--shiki-light:#0184BC;--shiki-dark:#E1E4E8\">:\u003C/span>\u003Cspan style=\"--shiki-light:#986801;--shiki-dark:#79B8FF\"> 12\u003C/span>\u003Cspan style=\"--shiki-light:#383A42;--shiki-dark:#E1E4E8\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#E45649;--shiki-dark:#E1E4E8\">  duration_ms\u003C/span>\u003Cspan style=\"--shiki-light:#0184BC;--shiki-dark:#E1E4E8\">:\u003C/span>\u003Cspan style=\"--shiki-light:#986801;--shiki-dark:#79B8FF\"> 182\u003C/span>\u003Cspan style=\"--shiki-light:#383A42;--shiki-dark:#E1E4E8\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#E45649;--shiki-dark:#E1E4E8\">  cost\u003C/span>\u003Cspan style=\"--shiki-light:#0184BC;--shiki-dark:#E1E4E8\">:\u003C/span>\u003Cspan style=\"--shiki-light:#986801;--shiki-dark:#79B8FF\"> 0.0004\u003C/span>\u003Cspan style=\"--shiki-light:#383A42;--shiki-dark:#E1E4E8\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#383A42;--shiki-dark:#E1E4E8\">});\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\u003C/figure>\n\u003Cdiv class=\"docs-table\">\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>Field\u003C/th>\n\u003Cth>Meaning\u003C/th>\n\u003C/tr>\n\u003C/thead>\n\u003Ctbody>\n\u003Ctr>\n\u003Ctd>\u003Ccode>name\u003C/code>\u003C/td>\n\u003Ctd>Short event name, e.g. \u003Ccode>cache.miss\u003C/code>. Required.\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>message\u003C/code>\u003C/td>\n\u003Ctd>One human-readable line.\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>level\u003C/code>\u003C/td>\n\u003Ctd>\u003Ccode>debug\u003C/code>, \u003Ccode>info\u003C/code>, \u003Ccode>warn\u003C/code>, or \u003Ccode>error\u003C/code>. Defaults to \u003Ccode>error\u003C/code> when \u003Ccode>status\u003C/code> is \u003Ccode>error\u003C/code>, otherwise \u003Ccode>info\u003C/code>.\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>status\u003C/code>\u003C/td>\n\u003Ctd>Outcome of the operation: \u003Ccode>success\u003C/code>, \u003Ccode>error\u003C/code>, or \u003Ccode>skipped\u003C/code>.\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>trigger\u003C/code>\u003C/td>\n\u003Ctd>The event that caused the entry: \u003Ccode>{ kind, id?, summary? }\u003C/code>.\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>request\u003C/code>\u003C/td>\n\u003Ctd>What was sent, or the input that triggered the work. Any JSON value; strings stay text.\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>response\u003C/code>\u003C/td>\n\u003Ctd>What came back. Any JSON value; strings stay text.\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>error\u003C/code>\u003C/td>\n\u003Ctd>Failure reason.\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>duration_ms\u003C/code>\u003C/td>\n\u003Ctd>Duration in milliseconds.\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>cost\u003C/code>\u003C/td>\n\u003Ctd>Cost in USD, when the operation cost money. Counts toward the thread's cost totals alongside its LLM request costs.\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>data\u003C/code>\u003C/td>\n\u003Ctd>Any other structured detail.\u003C/td>\n\u003C/tr>\n\u003C/tbody>\n\u003C/table>\u003C/div>\n\u003Cp>Entries are delivered to live log subscribers and returned by\n\u003Ccode>GET /api/threads/:id/logs\u003C/code> as rows with \u003Ccode>kind: 'app'\u003C/code>: \u003Ccode>model\u003C/code> holds the\nname, and the other fields are \u003Ccode>app_level\u003C/code>, \u003Ccode>app_message\u003C/code>, \u003Ccode>app_status\u003C/code>,\n\u003Ccode>app_error\u003C/code>, \u003Ccode>app_duration_ms\u003C/code>, \u003Ccode>app_cost\u003C/code>, plus JSON text in \u003Ccode>app_request\u003C/code>,\n\u003Ccode>app_response\u003C/code>, \u003Ccode>app_trigger\u003C/code>, and \u003Ccode>app_data\u003C/code>. The builder UI opens these rows\nin the log detail pane with the trigger, duration, cost, and Request and\nResponse tabs, and show the cost in the logs table's Cost column.\u003C/p>\n\u003Cp>An entry's \u003Ccode>cost\u003C/code> is part of what the thread cost: \u003Ccode>GET /api/threads/:id/cost\u003C/code>\nadds it to \u003Ccode>totalCost\u003C/code> (and to the thread's row in the per-thread\nbreakdown), and reports the application share apart as \u003Ccode>appCost\u003C/code>. The\nper-model breakdown and \u003Ccode>requestCount\u003C/code> cover LLM requests only. The row's own\n\u003Ccode>cost_total\u003C/code> stays null; it is the LLM request cost.\u003C/p>\n\u003Cp>Logging never creates a message and never starts or wakes an execution, so it\nis safe from hooks, tools, effects, and endpoints. It never throws because of\nan entry's content: fields of the wrong type are dropped, values that cannot be\nJSON-encoded are replaced by a marker object, and oversized fields are\ntruncated with a marker (\u003Ccode>name\u003C/code> to 120 characters, \u003Ccode>message\u003C/code> and \u003Ccode>error\u003C/code> to\n4 KiB, the JSON of \u003Ccode>data\u003C/code> to 16 KiB, and the JSON of \u003Ccode>request\u003C/code> and \u003Ccode>response\u003C/code>\nto 64 KiB each). Entries attach to the newest top-level message when one exists. Before the first\nmessage, entries persist without a message anchor and reach live log subscribers.\u003C/p>\n\u003Ch2 id=\"user-identity-and-application-roles\">\u003Ca class=\"docs-anchor\" href=\"#user-identity-and-application-roles\" aria-label=\"Link to this section\">\u003C/a>User Identity and Application Roles\u003C/h2>\n\u003Cp>\u003Ccode>await state.user()\u003C/code> returns the thread owner's identity and user handle, or\n\u003Ccode>null\u003C/code> for a thread without a user. Its optional \u003Ccode>roles\u003C/code> array carries\napplication-defined strings from the runtime's identity authority. Hosted\nStandard Agents Builder instances receive them from Platform through signed updates.\nCheck roles in each protected request or execution and treat absent roles as\nan empty assignment. \u003Ccode>ThreadState.user()\u003C/code> reads identity on each call.\n\u003Ccode>UserState.identity()\u003C/code> caches identity within one user-scope execution. These strings do not change built-in instance access levels\nor permissions. See \u003Ca href=\"/docs/core-concepts/api#guarding-user-endpoints-with-application-roles\">application role checks\u003C/a>\nfor a server-side endpoint example. See \u003Ca href=\"/docs/core-concepts/users\">Users\u003C/a> for user endpoints, \u003Ccode>call()\u003C/code>, and the user event stream.\u003C/p>\n\u003Ch2 id=\"queue-semantics\">\u003Ca class=\"docs-anchor\" href=\"#queue-semantics\" aria-label=\"Link to this section\">\u003C/a>Queue Semantics\u003C/h2>\n\u003Cp>\u003Ccode>queueMessage()\u003C/code> is durable and ordered:\u003C/p>\n\u003Cul>\n\u003Cli>if thread is active, queued messages are injected before the next model step\u003C/li>\n\u003Cli>if thread is idle, queueing forces execution\u003C/li>\n\u003Cli>queue entries survive eviction\u003C/li>\n\u003Cli>a message sent through the HTTP API while the thread is active is delivered the same way: it joins the running execution in the order it was sent\u003C/li>\n\u003Cli>message APIs expose \u003Ccode>sendMessage()\u003C/code> and \u003Ccode>queueMessage()\u003C/code> queued entries as pending messages with \u003Ccode>metadata.queued: true\u003C/code>\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"parent/child-communication\">\u003Ca class=\"docs-anchor\" href=\"#parent/child-communication\" aria-label=\"Link to this section\">\u003C/a>Parent/Child Communication\u003C/h2>\n\u003Cp>Subagent communication is message + filesystem aware:\u003C/p>\n\u003Ch3 id=\"parent->-child\">\u003Ca class=\"docs-anchor\" href=\"#parent->-child\" aria-label=\"Link to this section\">\u003C/a>Parent -> Child\u003C/h3>\n\u003Cul>\n\u003Cli>initial invocation mapping and later \u003Ccode>subagent_message\u003C/code> calls\u003C/li>\n\u003Cli>\u003Ccode>subagent_create.arguments\u003C/code> persists with the child thread as \u003Ccode>ThreadState.arguments\u003C/code> and renders as prompt variables for both child sides\u003C/li>\n\u003Cli>any referenced attachments are copied parent -> child\u003C/li>\n\u003C/ul>\n\u003Ch3 id=\"child->-parent\">\u003Ca class=\"docs-anchor\" href=\"#child->-parent\" aria-label=\"Link to this section\">\u003C/a>Child -> Parent\u003C/h3>\n\u003Cul>\n\u003Cli>with \u003Ccode>parentCommunication: 'implicit'\u003C/code>, completion/failure payloads are queued as silent messages for the relationship's owning side\u003C/li>\n\u003Cli>with \u003Ccode>parentCommunication: 'explicit'\u003C/code>, completion does not queue a parent message; child code can escalate through \u003Ccode>state.notifyParent()\u003C/code>\u003C/li>\n\u003Cli>returned attachments are copied child -> parent\u003C/li>\n\u003Cli>copied attachment paths are rewritten for the destination thread\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"termination\">\u003Ca class=\"docs-anchor\" href=\"#termination\" aria-label=\"Link to this section\">\u003C/a>Termination\u003C/h2>\n\u003Cp>\u003Ccode>terminate()\u003C/code> performs soft shutdown:\u003C/p>\n\u003Cul>\n\u003Cli>sets \u003Ccode>terminated\u003C/code> timestamp\u003C/li>\n\u003Cli>aborts in-flight execution\u003C/li>\n\u003Cli>rejects new execution/queue operations; \u003Ccode>POST /api/threads/{threadId}/messages\u003C/code> and the debug \u003Ccode>POST /api/threads/{threadId}/continue\u003C/code> return \u003Ccode>423\u003C/code> and store nothing\u003C/li>\n\u003Cli>keeps the non-execution thread routes working: reading, listing, updating, reading and deleting messages, files, stop, the stream, and deleting the thread\u003C/li>\n\u003Cli>propagates child termination status to parent registry when linked\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"registry-and-message-projection\">\u003Ca class=\"docs-anchor\" href=\"#registry-and-message-projection\" aria-label=\"Link to this section\">\u003C/a>Registry and Message Projection\u003C/h2>\n\u003Cp>Parent threads maintain a registry of their child instances.\u003C/p>\n\u003Cp>Messages may carry projected subagent fields (for UI/client grouping), including:\u003C/p>\n\u003Cul>\n\u003Cli>\u003Ccode>subagent_id\u003C/code>\u003C/li>\n\u003Cli>\u003Ccode>subagent_name\u003C/code>\u003C/li>\n\u003Cli>\u003Ccode>subagent_title\u003C/code>\u003C/li>\n\u003Cli>\u003Ccode>subagent_status\u003C/code>\u003C/li>\n\u003Cli>\u003Ccode>subagent_relationship\u003C/code>\u003C/li>\n\u003Cli>\u003Ccode>subagent_blocking\u003C/code>\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"related-docs\">\u003Ca class=\"docs-anchor\" href=\"#related-docs\" aria-label=\"Link to this section\">\u003C/a>Related Docs\u003C/h2>\n\u003Cul>\n\u003Cli>\u003Ca href=\"/docs/core-concepts/subagents\">Subagents\u003C/a>\u003C/li>\n\u003Cli>\u003Ca href=\"/docs/core-concepts/tools\">Tools\u003C/a>\u003C/li>\n\u003Cli>\u003Ca href=\"/docs/api-reference/rest/get-messages\">API: get messages\u003C/a>\u003C/li>\n\u003C/ul>",[9,13,16,19,22,25,28,31,34,38,41,44,47],{"id":10,"text":11,"depth":12},"what-is-a-thread","What Is a Thread?",2,{"id":14,"text":15,"depth":12},"durable-runtime","Durable Runtime",{"id":17,"text":18,"depth":12},"threadstate-apis","ThreadState APIs",{"id":20,"text":21,"depth":12},"run-status","Run Status",{"id":23,"text":24,"depth":12},"application-logs","Application Logs",{"id":26,"text":27,"depth":12},"user-identity-and-application-roles","User Identity and Application Roles",{"id":29,"text":30,"depth":12},"queue-semantics","Queue Semantics",{"id":32,"text":33,"depth":12},"parent/child-communication","Parent/Child Communication",{"id":35,"text":36,"depth":37},"parent->-child","Parent -> Child",3,{"id":39,"text":40,"depth":37},"child->-parent","Child -> Parent",{"id":42,"text":43,"depth":12},"termination","Termination",{"id":45,"text":46,"depth":12},"registry-and-message-projection","Registry and Message Projection",{"id":48,"text":49,"depth":12},"related-docs","Related Docs","core-concepts/thread","docs","Core Concepts",{"path":54,"title":55,"navTitle":55},"core-concepts/credential-grants","Credential grants",{"path":57,"title":58,"navTitle":58},"core-concepts/hooks","Hooks","/docs/core-concepts/thread.md","https://github.com/standardagents/agentbuilder/blob/main/docs/core-concepts/thread.mdx",1794580509245]