Crux
GuidesPlans & Tasks

Server Usage

Use plan and task handles from server functions, route handlers, and durable workers.

You created a plan in one request and need it in another process: a route handler, a queue worker, a cron job. Because plans and task ledgers persist through the configured RecordStore, the pattern is simple: pass the ID across the process boundary and rebind a handle with plan.ref() or tasks.ref() where the work runs.

import { plan } from "@use-crux/core/plan";
import { tasks } from "@use-crux/core/tasks";

export async function createWork(request: string) {
  const roadmap = await plan({
    title: "User request",
    content: request,
  });

  const work = await tasks({
    plan: roadmap,
    title: "Request tasks",
  });

  return { planId: roadmap.id, taskListId: work.id };
}

Rebind In Handlers

export async function POST(req: Request) {
  const { planId, taskListId, taskId } = await req.json();

  const roadmap = plan.ref(planId);
  const work = tasks.ref(taskListId);
  const worker = work.worker(taskId);

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

  return Response.json({ ok: true });
}

Creation Tools

Creation tools work on the server as normal prompt tools. Read their result with created() after the model uses the tool.

const makePlan = plan.tool();

await generate(
  prompt({
    system: "Create a short plan.",
    tools: { makePlan },
  }),
  { model, input: { request } },
);

const roadmap = makePlan.created();
const work = await tasks({ plan: roadmap, title: "Execution" });

Observability

Core emits canonical plan and task operation spans with JSON artifacts. Local devtools uses those artifacts to build the Plans views even when the backing store lives behind a server boundary.

On this page