> ## Documentation Index
> Fetch the complete documentation index at: https://docs.stefanbrain.com/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Follow the content contract in AGENTS.md.
> Treat text as the canonical explanation; video and screenshots enhance it.
> Do not publish unverified product behavior or duplicate an existing canonical article.

# Parallel agent sessions

> Run concurrent StefanBrain workstreams with one shared project and a separate session-labeled chat for each agent fork.

Use parallel sessions when several agents or workstreams need the same project context without competing for one chat.

The pattern has two parts:

* Put shared instructions, briefs, and reference files in one StefanBrain Project.
* Give every fork its own `session` label. StefanBrain routes that label to a dedicated chat named `Developer API — <label>` inside the project.

Calls that reuse a label continue the same chat. Different labels use different chats and can run concurrently.

## Address every call consistently

`ask_stefanbrain`, asynchronous submit tools, and the job status, result, and cancel tools accept `project` and `session` arguments. Repeat the same `project` and `session` when polling a job or retrying a keyed submission.

Lookups for submit-tool jobs are chat-scoped, so a different address cannot find the job. Idempotency keys are chat-scoped too, so a keyed retry at a different address starts new work. Parked asks (`mcp_ask`) resolve by account, but keep the same address anyway. An MCP poll with a wrong or unused `session` label also creates an empty `Developer API — <label>` chat.

Session labels must contain 1–128 characters from `A–Z`, `a–z`, `0–9`, `_`, `.`, `:`, or `-`. An invalid label returns `invalid_session`.

<Warning>
  A session is a tool argument; there is no session header. An MCP connection can use `x-stefanbrain-project` as its fallback project scope, but each fork must still pass its own `session` argument.
</Warning>

## Run forks with the SDK

```ts theme={"system"}
import StefanBrain from "@stefanbrain/sdk";

const client = new StefanBrain();
const project = "proj_your_project";

await Promise.all(
  ["research", "hooks", "landing-page"].map((session) =>
    client.ask("Complete your assigned task from the project brief.", {
      project,
      session,
    }),
  ),
);
```

Use the same label for a follow-up in one fork:

```ts theme={"system"}
await client.ask("Revise the strongest option using the same brief.", {
  project,
  session: "hooks",
});
```

## Run forks with the CLI

```bash theme={"system"}
sb ask "Research customer objections." \
  --project proj_your_project \
  --session research

sb ask "Draft five hooks from the project brief." \
  --project proj_your_project \
  --session hooks
```

For a project-pinned Claude Code workspace, `sb init --project proj_your_project` writes or merges the MCP configuration. It does not write a session header. Tell each fork to pass its label on every StefanBrain call.

## Handle busy chats deliberately

A chat runs one turn at a time. Only `on_busy: "reject"` is supported. By default, an `ask_stefanbrain` call into a busy labeled chat does not start a turn. It returns a successful tool result with `status: "chat_busy"`, the blocking `active_run_id`, and a `hint`. The SDK raises that result as `ChatBusyError`.

When calls depend on earlier conversation state, wait for the active run to finish before submitting the next ask.

Use separate labels for independent work. In one chat, submit dependent work after the earlier ask finishes.

## Resolve older sessions safely

The SDK and CLI resolve a session label with one exact, case-sensitive chat-name lookup and use the oldest-created match, which is where the server routes work for that label. A label that was never used fails with `chat_not_found` instead of polling another chat. Pass the `chat` returned at submit time to skip the lookup.

Next, read [TypeScript SDK](/developers/sdk) or [CLI](/developers/cli) for the full client contract.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.