Agent loop
Agent loop
The agent loop lives in Bolt. Sending a message persists one conversation message and its directive, and a durable answer task admits the run into one isolated invocation. Awaiting inference or a host tool yields while the host performs I/O, then resumes that invocation. The loop remains bounded by the acting subject’s workspace policies.
The loop
Every run starts from the platform baseline, the workspace prompt in src/+agents.md, plus an envoy’s task and the active plan when applicable, then alternates complete provider messages and tool calls. Bolt fences the complete assistant and tool-call batch before executing side effects, runs the batch’s calls together, and stores each canonical tool-result message in call order before the next provider iteration. Token deltas are temporary display state, never durable history. A provider failure ends that run; continuing it requires an explicit resume.
conversations.send ─► conversation + user message + directive
│
▼
durable admission ─► one run
│
┌─────────────────────────┼──────────────────────┐
▼ ▼ ▼
assistant batch await host I/O provider failure
fences first same invocation terminal run
│ resumes │
▼ ▼
tool effects run together explicit resume
│
▼
tool results in call order ─► next provider iteration Two doors into the loop
The same loop serves two entry points. Web chat and envoy inbound atomically persist the canonical user message and inbox receipt before notifying the scheduler:
- web chat — a signed-in user, acting on their own account
- envoys — the envoy principal under its declared policies
Permission bounds
The rule is permission bounds the agent, not its tool list : data operations run unelevated under the acting principal’s policy, whatever tools the loop can name.
Budget
Colony’s host policy is a 2,000 ms uninterrupted guest-thread CPU span between yields (COLONY_EXECUTION_COMPUTE_MS), not a wall timeout. Each model, database, or tool facility reply starts a fresh span; the wait retains the slot and context but consumes neither the CPU span nor the compute meter. There is no token budget to declare in source: a turn ends on stop, provider failure, exhausted retries, or the model finishing, and the invocation budget bounds how deep enqueued work — automations and child tasks — may nest. Context growth is handled by an automatic checkpoint at the model window, and a host tool call that outlasts its inline bound becomes a background job collected with wait.
Subagents
For narrow subtasks the root loop delegates through one subagent tool with actions spawn, read, message, await, stop, and resume. A child is its own durable task: spawn returns its conversation id while it runs in the background, several run side by side, and a settled child reports into the parent and wakes it if idle. Only the root delegates — a child cannot spawn — and every child inherits the same permission boundary.
Transcripts
The whole run — complete messages, tool calls, and results — is written to the canonical chat collections. A conversation has one durable inbox and one active lane. Input claimed by a run stays fixed; later messages wait for the next compatible run. Every committed message reaches the client through the same live findMany path as other collection data.
Related guides
The authoring surface is Norbius .