Skip to main content

Task and stream tools

Task and stream tools coordinate parallel work. A stream is the shared integration branch for an area, such as stream/os-skills. A task is an isolated branch, worktree, metadata bundle, and draft PR for one focused change. This page describes the tool surface. It does not replace the Task Workflow skill, which owns the required lifecycle, workpad rules, validation order, conflict handling, PR promotion, and cleanup policy. Start with stream.context when the stream area is known. It reports the stream branch, open task PRs, recent commits, current worktrees, and recent workpads. That gives the agent enough situational awareness to avoid colliding with other agents:
await workspace.call({
  tool: "stream.context",
  input: { area: "os-skills" },
  timeout: 120,
})
Use stream.list only when the correct area is unknown. It lists stream branches so the agent can ask for or confirm the right target instead of silently choosing one. stream.sync is the mutating stream maintenance tool. It syncs a stream branch with main. Because it changes shared integration state, it should be used deliberately, usually when a stream PR has drifted from main or the task workflow calls for stream repair. In a parallel-agent stream, read context first and treat conflicts involving source docs, code, tests, config, or generated files as real conflicts. Once the stream is known, task.start creates the isolated task branch and worktree. It returns the taskSession, which is the durable handle for subsequent task-scoped calls:
const started = await workspace.call({
  tool: "task.start",
  input: {
    area: "os-skills",
    title: "author tool family docs b",
    startFrom: "stream",
  },
  timeout: 180,
})

const taskSession = started.data.taskSession
After task.start, pass taskSession at the top level of task-scoped calls. Do not rely on the current branch, root .task/current.json, or ambient task selection:
await workspace.call({
  tool: "fs.read",
  taskSession,
  input: { path: "packages/os/TOOLS.md", from: 1, to: 80 },
  timeout: 120,
})
The task workflow then moves through scoped workpad updates, research, focused testing or a no-test waiver, implementation, validation, and review. The task tools only make the transitions; the skill decides when each transition is justified. task.push publishes the task branch update. It usually sends changed task files with a commit message:
await workspace.call({
  tool: "task.push",
  taskSession,
  input: {
    message: "docs(os): author tool family docs b",
    changed: true,
  },
  timeout: 300,
})
A successful push is not the final review surface. It updates the task branch and task PR. task.pr promotes the task into the stream and creates or refreshes the stream review PR. By default, the review path is task/<area>/<slug> into stream/<area>, then stream/<area> into main:
await workspace.call({
  tool: "task.pr",
  taskSession,
  input: { ready: true },
  timeout: 300,
})
The review link that matters to Ko is the stream review PR, not only the intermediate task PR. taskOnly: true is an explicit stop mode, not the default. task.finish cleans up the task worktree and local task state after merge proof exists and cleanup is safe. It is intentionally last:
await workspace.call({
  tool: "task.finish",
  taskSession,
  input: {},
  timeout: 300,
})
The stream model lets many agents work in the same area without sharing one mutable checkout. The safety comes from explicit stream context, a task-scoped worktree, top-level taskSession, validation evidence, and stream PR promotion rather than from local branch assumptions.