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

# Agent branches

> A second draft of an agent, rebased and merged onto its main draft.

A branch is a second working draft of an agent, cut from its main draft (what the App calls Development), so a change can be prepared apart and landed in one step. Merging is a fast-forward only: a branch lands while main has not moved since the branch was cut or last rebased, and otherwise it must be rebased first. Nothing here publishes; after a merge, main's draft is published the usual way ([Agents](https://docs.sempera.org/agents.md)).

These are `/v2` compatibility routes ([API overview](https://docs.sempera.org/api-overview.md)). `{agent_id}` is the Sempera agent id, and a branch id is a UUID.

| Route | Scope | Notes |
| - | - | - |
| `GET /v2/agents/{agent_id}/branches` | `agents:read` | The agent's open branches, oldest first |
| `POST /v2/agents/{agent_id}/branches` | `agents:write` | `{"name"}`. Cuts a branch from main's draft as it stands. `201` |
| `POST /v2/agents/{agent_id}/branches/{branch_id}/rebase-preview` | `agents:write` | What rebasing onto main's current head would do. Writes nothing |
| `POST /v2/agents/{agent_id}/branches/{branch_id}/rebase` | `agents:write` | Rebase onto the head the preview named, settling each conflict |
| `POST /v2/agents/{agent_id}/branches/{branch_id}/merge` | `agents:write` | Land the branch on main and close it |
| `DELETE /v2/agents/{agent_id}/branches/{branch_id}` | `agents:write` | Close the branch without landing it: `{"deleted": true}` |

Writes need the `operator` or `owner` role. A branch reads `id`, `agent_id`, `name`, `base_version_id`, `created_by`, `created_at` and `behind`, which is true once main has moved past the point the branch was cut from or last rebased onto.

A branch `name` is 1 to 64 letters, digits, dots, underscores or dashes, unique among the agent's open branches. `dev`, `latest`, `staging`, `production` and version-like names such as `1.2.3` are reserved.

## Rebase and merge

Branches are compared one draft setting at a time, with the instructions document counting as one setting. The preview answers `{"dev_head_version_id", "up_to_date", "auto_merged", "changes", "conflicts"}`: `changes` are settings only main changed, taken automatically; `conflicts` are settings both sides changed differently. Each item carries `id` (`setting:<key>`), `key`, `label`, `base` and `theirs` (main's value); a conflict adds `ours` (the branch's value).

```http theme={null}
POST /v2/agents/northwind-barbers/branches/{branch_id}/rebase
{"dev_head_version_id": "<from the preview>", "resolutions": {"setting:greeting": "ours"}}
```

Every conflict needs a resolution: `"ours"`, `"theirs"` or `{"value": ...}`, a new value that passes the same checks a draft edit does. The merged result becomes the branch's draft and its base moves to main's head. The answer is `{"version", "auto_merged", "resolved"}`. If main moved since the preview, the rebase is refused and you preview again.

A merge takes no body and answers `{"version", "merged_fields"}`, the settings the branch changed.

## Refusals

Answers use the compatibility envelope `{"data": ..., "errors": null}`; a refusal these routes make is `{"data": null, "errors": [{"error", "message"}]}`. A missing credential, scope or role, and a request body that is not a JSON object, get the standard error envelope ([Errors and limits](https://docs.sempera.org/errors-and-limits.md)).

| Status | `error` | When |
| - | - | - |
| `400` | `INVALID_NAME` | The name breaks the rule above |
| `400` | `INVALID_RESOLUTIONS`, `UNRESOLVED_CONFLICTS` | A resolution is malformed or its value is refused, or a conflict has none |
| `400` | `NO_CHANGES` | Merging a branch with no changes of its own |
| `404` | `NOT_FOUND` | No such agent, or no such open branch of it in this workspace. Deleting a branch that is not there answers `BRANCH_NOT_FOUND` |
| `409` | `BRANCH_EXISTS` | An open branch already has this name |
| `409` | `REBASE_STALE` | Main changed since the preview, or `dev_head_version_id` is missing or does not match main's head |
| `409` | `BRANCH_BEHIND` | Main moved past the branch's base; preview, rebase, then merge again. Nothing is written |
| `503` | `UNAVAILABLE` | The deployment has no database to keep branches in |

Editing a branch's own draft is done in the Sempera App today; `PATCH /v1/agents/{id}/draft` edits main.


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