Docs navigation
Reference

Agent manifest

brainbase.agent.yaml is the committed, declarative source of truth for an agent. Edit it by hand, then run brainbase agent push. Cached cloud metadata (slug, URL, org/team, tracking config) lives separately in a gitignored .brainbase/state.json — never in this file.

Legacy filename
The older filename brainbase.yaml is still read if present, but writes always go to brainbase.agent.yaml.

Creating this file

Three commands produce a manifest, depending on where you're starting from. None of them requires the web app.

CommandUse it when
`agent init`You're starting a new agent. Writes an unclaimed manifest and stops — no login, no network, no cloud writes.
`agent create`You want the file and the cloud agent in one step. Scaffolds a manifest if the folder has none, then claims it.
`agent pull <id>`The agent already exists in the cloud. Writes a manifest for it into an empty folder.
bash
brainbase agent init            # starter manifest, offline
brainbase agent init --full     # commented template covering every block

agent init writes the file below. Only schema and agent.name are required; the harness, tagline and instructions are starter values to edit or delete, and every other field in this reference is optional.

brainbase.agent.yamlyaml
schema: 1
harness: claude-code
agent:
  name: hello-world
  tagline: A starter agent.
instructions:
  text: You are a helpful Claude Code agent.

From there, edit by hand and run brainbase agent create to create the cloud agent, or brainbase agent push if the manifest is already claimed.

Full example

brainbase.agent.yamlyaml
schema: 1
id: 5ad59580-8028-4c52-9a31-574607a2aacb  # present once claimed
harness: claude-code
machine_kind: daytona       # selected when the agent is created
default_model: openai/gpt-5.6-terra
agent:
  name: Repo Assistant
  tagline: Reviews PRs and keeps the changelog tidy
instructions:
  file: ./.brainbase/instructions.md
entrypoint:
  commands:
    - npm install
    - npm run build
playbooks:
  - title: Release checklist
    description: Steps to cut a release
    content:
      file: ./playbooks/release.md
capabilities:
  memory: true
  browser: true
  slack: false
  meeting: false
skills:
  - source: registry:brainbase/changelog@1.0.0
  - source: ./skills/local-linter
mcp:
  - name: github
    url: https://api.githubcopilot.com/mcp/
    is_enabled: true
evals:
  - slug: cites-the-diff
    criteria: Pass when the review quotes the lines it is commenting on.

Top-level fields

schemainteger · 1required

Manifest schema version. Must be 1.

idUUIDoptional

Cloud agent id. Absent on an "unclaimed" manifest; brainbase agent create writes it once the cloud agent exists. Its presence is what makes the manifest "claimed".

harnessstringoptional

Harness this agent targets locally: claude-code, codex, or kafka.

machine_kindstringoptional

Sandbox provider selected when agent create claims the manifest. Omit it to leave provider selection to the platform. Once the agent exists, the field is immutable: changing it is reported as drift and rejected before cloud writes. Create a new agent to use another provider.

default_modelstring | nulloptional

Agent-level model override managed by the manifest. Omit the field to leave the cloud value unmanaged, set a model id to update it, or set null to explicitly clear the override. Model ids may contain letters, digits, ., _, -, :, and /, up to 128 characters.

agentobjectrequired

Agent metadata. See below.

agent.namestringrequired

Display name. Must be non-empty.

agent.taglinestringoptional

Short one-line description.

Keep secrets out of the manifest
brainbase.agent.yaml is committed source. Never put API keys, tokens, or other secret values in it, including under MCP env or headers. Agent secrets belong in the gitignored .brainbase/secrets.env; agent pull writes that file and agent push syncs it to the cloud. MCP config may reference those values with placeholders such as ${GITHUB_TOKEN}.

instructions

The agent's standing instructions. Set exactly one of file or textpush rejects a block that sets both or neither.

instructions.filestringoptional

Path (relative to the manifest) to a markdown file holding the instructions.

instructions.textstringoptional

Inline instructions, as an alternative to file.

entrypoint

Bash that runs inside the sandbox after secrets are loaded and agent pull completes, before the in-VM runner launches. Set exactly one of file, commands, or text.

entrypoint.filestringoptional

Path to a local script; its contents are used verbatim.

entrypoint.commandsarray<string>optional

A list of shell commands. Joined with newlines and prefixed with set -euo pipefail so a failing command fails the boot.

entrypoint.textstringoptional

An inline script body, used as-is (no fail-fast preamble added).

playbooks

A list of playbooks. Each is shipped as one markdown file with title / description assembled into YAML frontmatter at push time. Defaults to an empty list.

playbooks[].idstringoptional

Cloud playbook id. Round-tripped: written by pull and sent back on push so an existing cloud playbook is updated rather than recreated.

playbooks[].titlestringrequired

Playbook title. Must be non-empty.

playbooks[].descriptionstringoptional

Short description, included in the playbook table.

playbooks[].iconstringoptional

Cloud icon for the playbook. Round-tripped between pull and push.

playbooks[].contentobjectrequired

The body — set exactly one of file or text (same shape as instructions).

skills

A list of skill sources, resolved at agent pull time. Defaults to an empty list. Each entry is { source: <string> }, where source is one of:

FormMeaning
registry:creator/slugLatest version from the registry.
registry:creator/slug@1.4.0A pinned version (exact MAJOR.MINOR.PATCH).
registry:slugLegacy / unscoped (no creator namespace).
./relative/pathA local skill directory.
Version ranges are not supported
Ranges such as @^2.0 are not supported. Versions are matched exactly, so a range resolves to nothing. Validation happens when the manifest is read, so every command that reads it — agent push, agent pull, agent create, agent unpack, and sync — rejects the range with an error telling you to pin an exact version, and exits non-zero. Omit the version to track the latest instead.

mcp

A list of MCP servers. Defaults to an empty list. Either url (remote) or command (stdio) must be set; push validates and emits a clear error otherwise.

mcp[].namestringrequired

Server name. Must be non-empty.

mcp[].urlstringoptional

Remote MCP endpoint URL.

mcp[].commandstringoptional

Command to launch a stdio MCP server.

mcp[].argsarray<string>optional

Arguments passed to command.

mcp[].envobjectoptional

Environment variables (string → string) for a stdio server.

mcp[].headersobjectoptional

HTTP headers (string → string) for a remote server.

mcp[].is_enabledbooleanoptional

Whether the server is active.

evals

A list of evals — natural-language criteria a judge scores each finished turn against. Defaults to an empty list. Evals are the agent's test suite, so keeping them here puts a behaviour change and the check that guards it in the same commit and the same review.

Definitions are declarative: edit this block and run agent push. Verdicts are results, never config — they are read with brainbase agent eval runs and never written to this file.

evals[].slugstringrequired

Identity within the agent. Kebab-case (a-z, 0-9, hyphens) and unique across the agent's evals. Renaming a slug on an entry that carries an id renames that cloud eval; renaming one without an id creates a new eval and archives the old one.

evals[].idstringoptional

Cloud eval id. Round-tripped: written by pull, and by push for evals it creates, then sent back on later pushes so an existing eval is updated rather than recreated. Do not write it by hand.

evals[].criteriastringrequired

What the judge scores against, in plain language. 1–4000 characters. Inline only — there is no file form.

evals[].iconstringoptional

Lucide icon name shown beside the eval in the web app, e.g. CircleCheck. Max 64 characters.

evals[].enabledbooleanoptional

Whether the judge scores turns against this eval. Defaults to true. Setting it to false keeps the definition and its past verdicts while stopping new ones.

evals[].judge_modelstringoptional

Model that renders the verdict. Defaults to claude-sonnet-4-6. Ignored when judge_type is agent.

evals[].judge_type"model" | "agent"optional

Who judges: a model directly, or another agent. Defaults to model.

evals[].judge_agentstringoptional

The judging agent, as an agent id or a name that slugifies to one. Required when judge_type is agent, and rejected otherwise. It must be an agent you can access that shares a project with this one — or, for personal agents, one you own — and it cannot be the agent being judged. A name is resolved on push and rewritten in place as the resolved id; see the callout below.

evals[].output_shape"binary" | "rating" | "classification"optional

The shape of the verdict: pass/fail, a 1–5 rating, or one of a fixed set of categories. Defaults to binary.

evals[].classification_valuesarray<string>optional

The allowed categories. Required, non-empty, and free of duplicates when output_shape is classification; rejected for any other shape.

brainbase.agent.yamlyaml
evals:
  - slug: asks-for-missing-info
    criteria: >-
      Pass when the agent asks for a required field it was not given,
      instead of guessing a value.
    icon: CircleCheck

  - slug: answer-quality
    criteria: Rate how completely the answer addressed the question.
    output_shape: rating

  - slug: refusal-reason
    criteria: When the agent declined, which reason applied?
    output_shape: classification
    classification_values: [policy, missing-data, out-of-scope]

  - slug: follows-escalation-policy
    criteria: Pass when the agent escalated according to the policy playbook.
    judge_type: agent
    judge_agent: policy-reviewer
A judge named by name is rewritten as an id
judge_agent: policy-reviewer is resolved on push and written back into the manifest as that agent's id, because agent names are not stable identity. The rewrite happens once, on the first push; until then agent status reports the eval as locally modified, which is expected. Commit the rewritten file.
The evals list is authoritative, and omissions archive
agent push sends the whole list, so an eval you delete from this file is archived in the cloud — it stops scoring turns and disappears from the web app. Archived is not deleted: past verdicts are kept, and re-adding the same slug restores the same eval with its history. agent push names every eval it is about to archive and, when run interactively, asks first; agent status shows the same list before you push. The same rule applies to playbooks.
Push refuses rather than archive an eval you have never pulled
A deletion and a folder that has never seen the cloud's evals both look like an empty list, so push distinguishes them using the last-synced state in .brainbase/. If the cloud holds an eval your checkout has not pulled — one a teammate created in the web app, say — push stops with a non-zero exit and tells you to agent pull first, rather than archiving it. The same applies to an eval edited in the cloud since your last pull. agent push --force overrides both and makes your local list authoritative.
A manifest that declares no evals makes no claim
Declaring no evals is not the same as declaring that the agent has none. A manifest with no evals — whether the block is absent or written as evals: [], which are indistinguishable once parsed — asserts nothing, so cloud evals are left untouched and the rest of the push proceeds. That also holds under --force, which means "my edits beat the cloud's edits" and never "this agent has no evals". Deleting your last eval still works: that is a change against your last-synced state, which is a claim about that specific eval.

capabilities

Which built-in MCP servers unpack lays into the harness. Omit the block to accept the defaults below.

The five fields look alike but are not the same kind of thing, and only the first two are settable:

FieldsKindChanged by
memory, browserA settingEditing them here, then agent push
slack, meetingReported connection stateagent connect / disconnect
githubReported connection stateThe web app — GitHub renders its own App-manifest confirmation page, which a terminal cannot complete

The second group is not a toggle: it reports whether an active install exists, and no value written here can conjure one. agent pull refreshes them, and agent push refuses if what you have on disk disagrees with the live connection — the same "you're behind, pull first" rule it applies to a stale revision. They stay in the file because unpack runs offline inside a sandbox and has no control plane to ask.

capabilities.memorybooleanoptional

Writable. Built-in memory MCP server. Defaults to on when absent; only an explicit false turns it off.

capabilities.browserbooleanoptional

Writable. Built-in browser MCP server. Defaults to on when absent; only an explicit false turns it off.

capabilities.slackbooleanoptional

Read-only. True while an active Slack install exists. Defaults to off. Change it with brainbase agent connect slack.

capabilities.meetingbooleanoptional

Read-only. True while an active meeting install exists. Defaults to off. Change it with brainbase agent connect meeting.

capabilities.githubbooleanoptional

Read-only. True while an active GitHub install exists. Defaults to off. GitHub renders its own App-manifest confirmation page, so it is connected in the web app rather than from the terminal.

Reserved fields

commands, hooks, and files parse but are not synced. They are accepted so a manifest written for a newer control plane still loads on an older CLI — accepting them is not the same as applying them. Nothing in the CLI transmits these blocks, and no harness installs them.

Because they cannot be applied, declaring one is treated as an error rather than ignored quietly. If any of the three is present and non-empty, agent push and agent create refuse the command, name the block, and exit non-zero without contacting the control plane. An empty block (hooks: []) declares nothing and is a no-op.

agent status reports declared blocks as ignored — in the human report and under the ignored key of agent status --json — so you can see the discrepancy without running a command that writes.

Older CLI versions dropped these blocks silently
Before this refusal existed, a manifest declaring commands, hooks, or files pushed successfully and exited 0 while discarding the block — so an agent could be missing configuration its own manifest declared, with nothing on either side recording it. If your CLI does not refuse a manifest declaring one of these blocks, it is an older build that drops them: upgrade, then run agent status to see what is being ignored.

Whether these blocks become real features or are removed from the schema is still open. There is no target release; treat them as unsupported until this page says otherwise.

Schedules are orchestration-level
Agent manifests do not accept schedule triggers. To schedule one agent, create an orchestration with that agent as its only member and define the schedule in brainbase-orchestration.yaml.