Skip to main content
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.
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.

Run forks with the SDK

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

Run forks with the CLI

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 or CLI for the full client contract.