Worker
A generic, sandboxed subagent type. Workers are spawned by other agents (typically Horton) via the spawn_worker tool — the spawner provides a system prompt and picks the subset of tools the worker should have access to.
Source: packages/ts-darix-server/src/darix-agents/agents/worker.ts
Spawn args
interface WorkerArgs {
systemPrompt: string
tools: Array<WorkerToolName>
}| Field | Required | Description |
|---|---|---|
systemPrompt | Yes | The worker's system prompt. Brief it like a colleague: file paths, line numbers, deliverable. |
tools | Yes | Non-empty subset of valid tool names (see below). Unknown names throw at parse time. |
registerWorker(registry, { workingDirectory, streamFn? }) is called by the dev server during bootstrap; you don't usually call it yourself.
Valid tool names
type WorkerToolName =
| "bash"
| "read"
| "write"
| "edit"
| "brave_search"
| "fetch_url"
| "spawn_worker"These are the same primitives Horton uses. Pick the smallest subset the worker needs — tools are the worker's permission set.
Spawning a worker
The canonical way to spawn a worker is the spawn_worker tool, which Horton calls from inside its agent loop:
spawn_worker({
systemPrompt:
"You are a focused researcher. Find the three most-cited papers on X and return their titles, authors, and DOIs as a markdown table.",
tools: ["brave_search", "fetch_url"],
initialMessage: "Begin research now.",
})| Field | Required | Notes |
|---|---|---|
systemPrompt | Yes | Sets persona and constraints. |
tools | Yes | Subset of WorkerToolName. Must contain at least one entry. |
initialMessage | Yes | First user message. Without this the worker idles — nothing kicks it off. |
The spawn uses wake: { on: 'runFinished', includeResponse: true }, so the spawner wakes when the worker finishes its run and receives the worker's response in the wake message.
What the handler does
- Parses
ctx.argsintoWorkerArgs. Throws ifsystemPromptis empty ortoolscontains an unknown name. - Builds the requested tool instances against the worker's
workingDirectory(and a fresh per-wakereadSetfor the read-first-then-edit guard). - Configures the agent with
HORTON_MODEL(claude-sonnet-4-5-20250929), the provided system prompt (with a brief reporting-back footer appended), and the assembled tool list. - Runs the agent until the LLM stops.
Least-privilege sandbox
Workers deliberately do not receive ctx.darixTools. The spawner already picked the worker's tool subset; granting entity-runtime primitives (cron, schedule, send-to-arbitrary-entity) would let a worker escape that scope. If a worker needs those primitives, it must spawn its own subagent or report back to the spawner. This invariant is asserted by worker-least-privilege.test.ts.
Reporting footer
The runtime appends this to every worker's system prompt:
# Reporting back
When you finish, respond with a concise report covering what was done and any key findings. The caller will relay this to the user, so it only needs the essentials.Details
| Property | Value |
|---|---|
| Type name | worker |
| Model | HORTON_MODEL (claude-sonnet-4-5-20250929) |
| Tools | Subset of 7 primitives chosen at spawn time. No ctx.darixTools. |
| Working directory | Provided to registerWorker at bootstrap |
| Description | Internal — generic worker spawned by other agents |