Crux
GuidesPlans & Tasks

Workers

Bind an agent to one task with scoped context and lifecycle tools.

When you hand a subagent a task, you want it to work on exactly that task, with tools that cannot touch the rest of the ledger. A worker handle gives you that binding, created from a task ledger:

const worker = work.worker("research");

The worker is scoped to one task ID. Its context describes the assignment, and its tools mutate only that task.

await generate(
  prompt({
    use: [launchPlan.asContext(), worker.asContext()],
    tools: worker.asTools(),
    system: "Complete the assigned task and report progress.",
  }),
  { model, input: {} },
);

Guidelines

Pass task-specific guidance when the worker is created:

const writer = work.worker("draft", {
  guidelines: "Write markdown. Include source links. Keep the tone direct.",
});

Custom Context

Use renderContext when the default assignment summary is not enough:

const reviewer = work.worker("review", {
  renderContext: (task, allTasks) => {
    const completed = allTasks.filter(
      (item) => item.status === "completed",
    ).length;
    return `Task: ${task.label}\nStatus: ${task.status}\nCompleted nearby tasks: ${completed}`;
  },
});

Bounded Worker Pool

Workers are handles, not a scheduler. You can run a small pool in user code:

const active = (await work.list()).filter((item) => item.status === "pending");
const poolSize = 3;

for (let index = 0; index < active.length; index += poolSize) {
  const batch = active.slice(index, index + poolSize);

  await Promise.all(
    batch.map((item) => {
      const worker = work.worker(item.id);
      return generate(
        prompt({
          use: [launchPlan.asContext(), worker.asContext()],
          tools: worker.asTools(),
          system: "Complete this task.",
        }),
        { model, input: {} },
      );
    }),
  );
}

Use a durable runner when you need retries, scheduling, backpressure, or cross-process queue semantics.

On this page