The Universal Harness API
The Universal Harness API is a managed agents API for every harness. One call describes an agent — any harness, any configuration — and starts it running in an isolated sandbox. No provisioning, no setup step: your first agent is running in a few seconds.
Every coding agent harness has its own installation, configuration format, authentication, and runtime quirks. Running one in production is real work; running several means maintaining several integrations. This API abstracts all of that behind one endpoint: the same payload, the same response shape, and the same thread endpoints for every harness.
$BRAINBASE_API_KEY. See Authentication for details.Quickstart
/v2/threadsDescribe the agent inline and pass its first input. Brainbase creates the agent, boots a sandbox, and starts the first turn — one request, nothing to set up beforehand.
agentobjectoptionalThe whole agent, inline: harness, instructions, model, tools. See the whole agent in one payload for every field.
agent_iduuidoptionalAlready have an agent? Pass its id instead of agent and skip the spec entirely.
inputstringoptionalThe first user message. The turn starts immediately.
The body also accepts title, metadata, group_id, and a messages array in place of input — see the full Create Thread reference.
The response is a handle to a running thread. Threads title themselves from the conversation, so you don't need to name anything.
curl https://api.brainbaselabs.com/v2/threads \
-H "Authorization: Bearer $BRAINBASE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"agent": {
"harness": "claude_code",
"instructions": "You are a concise research assistant. Answer briefly and precisely.",
"model": "claude-sonnet-5"
},
"input": "In two sentences, what is the Model Context Protocol (MCP)?"
}'
{
"thread_id": "a4fe9c41-7fea-4b93-91e4-081329e35865",
"agent_id": "54850f1a-e68f-46ac-a85c-01f977101f91",
"status": "running"
}
Any harness
Change one line and the same request runs a different harness. Same payload, same response, same thread endpoints — the model, instructions, and tools carry over unchanged.
"agent": {
"harness": "codex",
"instructions": "You are a concise research assistant. Answer briefly and precisely.",
"model": "claude-sonnet-5"
}
Eight harnesses are supported today. The harness values below come straight from the live runtime registry — the same source that generates the accepted values in the API reference.
| Harness | Harness value |
|---|---|
| Claude Code | claude_code |
| Codex | codex |
| Cursor | cursor |
| Factory Droid | factory |
| Kafka — Brainbase's flagship runtime for knowledge work | kafka_cloud |
| OpenCode | opencode |
| Qoder | qoder |
| Qwen Code | qwen |
The whole agent in one payload
If you've used a serverless inference API, the shape is familiar: pass a spec, get a handle. The difference is what the spec describes. Instead of a model, you pass an agent — a harness, instructions, and whatever tools it needs, all inline.
"agent": {
"harness": "claude_code",
"instructions": "You are a research assistant.",
"model": "claude-opus-4-8",
"mcp_servers": [{ "name": "search", "url": "https://mcp.example.com/sse" }],
"skills": [{ "source": "registry:brainbase/deep-research" }],
"secrets": { "TAVILY_API_KEY": "tvly-..." },
"entrypoint": "pip install -r requirements.txt"
}
harnessstringoptionalWhich harness executes the agent's turns. Defaults to claude_code. See Any harness for the accepted values.
instructionsstringoptionalThe agent's system instructions — who it is and how it should work.
modelstringoptionalModel the harness runs, e.g. claude-sonnet-5 or claude-opus-4-8. Omit to use the harness default.
mcp_serversarrayoptionalMCP servers the agent can call. Each entry names a server and points at a url (remote) or command (local to the sandbox).
skillsarrayoptionalSkill declarations from the Brainbase registry, as registry:creator/slug with an optional @version pin.
secretsobjectoptionalKey–value secrets planted into the sandbox as plain environment variables, available to the harness and to your entrypoint.
entrypointstringoptionalBash that runs inside the sandbox before the agent launches — install dependencies, clone a repo, whatever your agent needs waiting for it when it wakes up. Runs with cwd=/workspace; failures are logged but don't block the agent from starting.
machine_kindstringoptionalSandbox provider the agent runs on. See Sandboxes.
titlestringoptionalOptional display title for the agent. Omit it and one is derived for you.
Same spec, same agent
Send the same agent spec twice and you get the same agent_id back, with a new thread each time. Brainbase hashes the spec and reuses the match, so you aren't minting a new agent on every call — describe the agent inline on every request and let the API dedupe. Change anything in the spec and you get a new agent.
// First call
{ "thread_id": "a4fe9c41-7fea-4b93-91e4-081329e35865",
"agent_id": "54850f1a-e68f-46ac-a85c-01f977101f91", "status": "running" }
// Identical spec, called again — same agent, new thread
{ "thread_id": "194c86d9-6b57-4128-83b8-a31fb8a7370e",
"agent_id": "54850f1a-e68f-46ac-a85c-01f977101f91", "status": "running" }
Already have an agent? Pass agent_id directly and skip the spec entirely.
{
"agent_id": "54850f1a-e68f-46ac-a85c-01f977101f91",
"input": "Same agent, new conversation."
}
Watch it run
A thread reports running while a turn is executing, then settles: success or fail for a finished turn, need_more_info when the agent is waiting on your answer, or idle when the turn ended without reporting an outcome. Watch it however you like.
/v2/threads/{thread_id}Poll the thread's status.{
"id": "a4fe9c41-7fea-4b93-91e4-081329e35865",
"agent_id": "54850f1a-e68f-46ac-a85c-01f977101f91",
"title": "Explain Model Context Protocol",
"status": "success",
"created_at": "2026-07-15T19:07:43.910211"
}
/v2/threads/{thread_id}/messagesFetch the transcript. Messages arrive in an `items` array.{
"items": [
{
"role": "user",
"content": "In two sentences, what is the Model Context Protocol (MCP)?"
},
{
"role": "assistant",
"content": "The Model Context Protocol (MCP) is an open standard (introduced by Anthropic) that defines how AI applications connect to external data sources, tools, and systems through a uniform client-server interface. ...",
"metadata": { "model": "claude-sonnet-5" }
}
]
}
/v2/threads/{thread_id}/events/streamA live server-sent events feed of everything the agent does.The stream carries the full activity of the thread as typed events — user.message, assistant.message.chunk (streaming text), assistant.message, tool_call.start, mcp.status, and idle (the turn's outcome and a summary) are the ones you'll see most, with comment keepalives in between. The connection stays open across turns, so follow-up messages and their replies arrive on the same stream.
curl -N "https://api.brainbaselabs.com/v2/threads/$THREAD_ID/events/stream" \
-H "Authorization: Bearer $BRAINBASE_API_KEY"
event: assistant.message.chunk
data: {"type":"assistant.message.chunk","thread_id":"a4fe9c41-…","data":{"content":[{"type":"text","content":"The Model Context Protocol (MCP) is an open standard…"}]}}
event: idle
data: {"type":"idle","thread_id":"a4fe9c41-…","data":{"status":"success","summary":"Answered a factual question about MCP in two sentences; no tools needed."}}
/v2/threads/{thread_id}/eventsThe same events as a paginated history (an `items` array) instead of a live stream./v2/threads/{thread_id}/interruptStop the current turn.Keep the conversation going
/v2/threads/{thread_id}/messagesThreads are conversations, not one-shot jobs. Append a message with run: true and the agent picks the thread back up — same sandbox, full context.
messagesarrayrequiredMessages to append. Each needs content; role defaults to user.
runbooleanoptionalIf true, kick off the runtime after appending the messages. Defaults to false — append without running.
The response confirms the append with run_started: true; the reply shows up in the transcript (and on the event stream) when the turn settles.
curl "https://api.brainbaselabs.com/v2/threads/$THREAD_ID/messages" \
-H "Authorization: Bearer $BRAINBASE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"messages": [
{ "role": "user", "content": "Now name three popular MCP servers, one line each." }
],
"run": true
}'
{
"messages": [
{
"id": "bc85731e-7966-441f-ab57-3c92070e1438",
"role": "user",
"content": "Now name three popular MCP servers, one line each."
}
],
"run_started": true
}
{
"items": [
{
"role": "assistant",
"content": "- **Filesystem** — read/write access to local files and directories for an AI client.\n- **GitHub** — manage repos, issues, and PRs directly from an MCP-enabled assistant.\n- **Slack** — send messages and read channel history through Slack's API via MCP."
}
]
}
Sandboxes
Every agent runs in an isolated sandbox, and you choose the ground it runs on with machine_kind in the agent spec: daytona (the default) or e2b, with more providers on the way. The provider is fixed when the agent is created.
"agent": {
"harness": "claude_code",
"instructions": "You are a research assistant.",
"machine_kind": "daytona"
}
See it on the platform
Everything you create through the API also shows up on the Brainbase platform — open app.brainbaselabs.com and the agent and its threads are right there, with the full conversation streaming live.