ThreadState
Unified runtime API for tools, hooks, and endpoints
What Is ThreadState?
ThreadState is the runtime interface passed to tools, hooks, and thread endpoints.
It provides:
- thread identity
- message operations
- model/prompt/agent loaders
- tool and effect scheduling helpers
- filesystem access
- sandboxed JavaScript/TypeScript execution through Dynamic Workers
- subagent hierarchy and lifecycle surfaces
- thread invocation arguments and per-execution scratch context
Core Surfaces
Identity
threadIdagentIduserIdcreatedAt
Messaging
getMessages()getMessage()injectMessage()updateMessage()queueMessage()
Subagent Hierarchy
getChildThread(referenceId)getParentThread()children(child registry)
Lifecycle
terminate()terminatedstatus()(the authoritative run status)stopSession()(ends a session)
Arguments and Context
arguments: read-only invocation or creation arguments for the threadcontext: mutable scratch data shared only during the current execution
For subagents, subagent_create.arguments is persisted with the child thread and restored as state.arguments for both child sides on every run. Top-level argument keys are also available to prompt variable interpolation, including included prompts.
Use state.context for derived values that should be shared among tools, hooks, and runtime code during one execution. Do not use it for durable thread state or subagent creation arguments; use state.arguments, state.getValue() / state.setValue(), or files depending on the data.
Resource Loading
loadModel()loadPrompt()loadAgent()
Environment
env(propertyName)envType(propertyName)instanceEnv(propertyName)(optional in the specification)setEnv(propertyName, value, options?)
env() resolves values in this order: thread environment, agent definition defaults, prompt definition defaults, user-account environment, then runtime-instance environment. envType() returns secret by default; text values may be shown in tool output and errors, while secret values should be redacted. setEnv() writes a thread-scoped env value and propagates it to active descendant threads. Pass { type: 'text' } or { type: 'secret' } to choose the display/redaction type; omitting type preserves the existing type or defaults new keys to secret.
instanceEnv() reads only the runtime instance. Use it for trusted service
configuration that thread or user values must not override. Check that the
method exists before you call it on another runtime.
Utilities
queueTool()/invokeTool()scheduleEffect()/getScheduledEffects()/removeScheduledEffect()(see Effects)runtimeStreams(see Runtime streams)- file APIs (
readFile,writeFile,readdirFile,findFiles, etc.) runCode(source, options?)
Code Execution
runCode() executes JavaScript or TypeScript in a Cloudflare Dynamic Worker sandbox loaded by stable content ID when possible. The sandbox does not receive thread state, filesystem, network access, timers, or host globals automatically. Bridge exact capabilities through options.imports and options.globals, use options.modules for local relative ES modules, and use options.execute to choose which export to run with which arguments. By default, Standard Agents Builder executes the default export with no args. Sandbox code can call and await a bridged function at the top level of a module as well as inside an exported function.
const run = state.runCode(
`
const text = await readText('/notes.txt');
report({ length: text.length });
export function summarize(limit: number) {
return text.slice(0, limit);
}
`,
{
execute: { fn: 'summarize', args: [120] },
globals: {
readText: async (path: string) => {
const data = await state.readFile(path);
return data ? new TextDecoder().decode(data) : '';
},
},
report: (value) => console.log(value),
},
);
const result = await run;The returned handle is promise-like and supports run.terminate(reason). Standard Agents Builder uses the AGENT_BUILDER_CODE_LOADER Worker Loader binding; missing configuration returns a link_error result naming that binding.
The memory limit of a sandbox is 134,217,728 bytes (128 MB). Cloudflare fixes this ceiling for each Workers isolate. The Worker Loader accepts limits for CPU time and subrequests only, and the isolate exposes no heap measurement. For these reasons Standard Agents Builder handles memoryLimitBytes as follows:
- A value below the ceiling is accepted and has no effect. The 128 MB ceiling applies.
- A value above the ceiling is clamped to the ceiling. The run is not rejected.
- When
memoryLimitBytesis omitted, the ceiling is the default limit. - A value that is not a positive finite number returns
status: 'link_error'.
A memory failure that the platform or the engine reports returns status: 'memory'. Its error.message names the effective limit, and it states whether a requested value was clamped or was not applied. memoryUsedBytes is not reported.
ThreadState in Tools
import { defineTool } from '@standardagents/spec';
import { z } from 'zod';
export default defineTool({
description: 'Inspect subagent status',
args: z.object({ referenceId: z.string() }),
execute: async (state, args) => {
const child = await state.getChildThread(args.referenceId);
if (!child) {
return { status: 'error', error: 'Child thread not found.' };
}
return {
status: 'success',
result: `Child terminated: ${child.terminated ? 'yes' : 'no'}`,
};
},
});Queue Semantics
queueMessage() is durable and ordered:
- active thread: injected before next model step
- idle thread: queue triggers execution
- queue survives eviction
- 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
- message APIs expose
sendMessage()andqueueMessage()queued entries as pending messages withmetadata.queued: true
Cross-Thread Attachment Safety
When parent/child communication includes attachments, runtimes copy files across thread filesystems and rewrite attachment paths to destination-local values.
Notes
executionmay benullwhen thread is at rest.argumentsis the place for thread invocation and subagent creation arguments.contextis ephemeral execution scratch state, not durable storage._notPackableRuntimeContextis runtime-specific and not portable.