Tasks model discrete steps within a run. They appear as a timeline in the run detail view and make it easy to see where time was spent or where a failure occurred.
Use tasks when your agent has identifiable phases — fetching data, running a model, writing output. Without tasks, a run is just a flat stream of events. With tasks, you get a structured breakdown.
const run = await client.startRun({ input: { file: "report.pdf" } });
const parseTask = await run.startTask("parse-pdf", { file: "report.pdf" });
const pages = await parsePDF("report.pdf");
await parseTask.complete({ output: { pages: pages.length } });
const summariseTask = await run.startTask("summarise", { pages: pages.length });
const summary = await summarise(pages);
await summariseTask.complete({ output: { summary } });
await run.complete({ output: { summary } });
startTask() → running
↓
complete() → completed
fail() → failed
skip() → skipped
run.startTask(name, input?)Creates a task in running state. Flushes any pending events first so the task appears after them in the timeline.
const task = await run.startTask("fetch-data", { url: "https://api.example.com" });
task.complete(options?)await task.complete({ output: { rows: 142 } });
task.fail(options)await task.fail({ errorMessage: "Connection refused" });
task.skip()Mark a task as intentionally skipped (e.g. a cache hit made it unnecessary).
await task.skip();
Tasks are independent — you can start multiple tasks and complete them in any order.
const [taskA, taskB] = await Promise.all([
run.startTask("fetch-users"),
run.startTask("fetch-products"),
]);
const [users, products] = await Promise.all([fetchUsers(), fetchProducts()]);
await taskA.complete({ output: { count: users.length } });
await taskB.complete({ output: { count: products.length } });
run = client.start_run(input={"file": "report.pdf"})
task = run.start_task("parse-pdf", input={"file": "report.pdf"})
pages = parse_pdf("report.pdf")
task.complete(output={"pages": len(pages)})
run.complete(output={"pages": len(pages)})