mirror of
https://github.com/himanshudongre/smriti.git
synced 2026-08-28 05:14:59 +00:00
Skill pack (template.md -> AGENTS.md, .claude/skills/smriti/SKILL.md):
- §3.2 Repo reconciliation: lead with `## Repo state`'s automated drift
signals; keep the manual git log checks as the documented fallback
for checkpoints without recorded git state.
- §3.5 Backend reachability: lead with `smriti doctor` as the
structured health check; keep `curl /health` as the raw fallback.
- Bump skill pack version 2.4 -> 2.5; re-render AGENTS.md (the
.claude/skills/smriti/SKILL.md install is local-only and untracked).
- test_skill_pack: bump the expected version; add four single-line
required phrases proving the new content shipped (`Repo state`,
`smriti doctor`, "ahead of the last checkpoint", "checkpoint taken
on a different branch").
docs/API.md:
- POST /api/v4/chat/commit: add `repo_state` to the request body
example and a paragraph explaining its purpose (drift detection),
persistence (`context_blob`), and read-back path (V4 state endpoint).
- DELETE /api/v2/repos/{repo_id}: add the missing section with the
`force` query param, 204/404/409 responses, and the structured
detail shape for the 409 refusal.
CLI suite: 253 passed. AGENTS.md and SKILL.md verified byte-identical
to fresh render(target) output.
952 lines
23 KiB
Markdown
952 lines
23 KiB
Markdown
# Smriti API Reference
|
||
|
||
This document covers the V4 (chat) and V5 (checkpoint) APIs — the current primary
|
||
interfaces. V1 and V2 endpoints are legacy and not documented here; see
|
||
[docs/legacy/](legacy/) for historical context.
|
||
|
||
Base URL: `http://localhost:8000`
|
||
|
||
All request and response bodies are JSON. All IDs are UUIDs.
|
||
|
||
---
|
||
|
||
## V4 — Chat API
|
||
|
||
Prefix: `/api/v4/chat`
|
||
|
||
The V4 API manages Sessions, Turns, and message sending. It is the primary runtime
|
||
API for the Smriti workspace.
|
||
|
||
---
|
||
|
||
### Sessions
|
||
|
||
#### Create a session
|
||
|
||
```
|
||
POST /api/v4/chat/sessions
|
||
```
|
||
|
||
Creates a new Session, optionally attached to a Space and seeded from a Checkpoint.
|
||
|
||
**Request body:**
|
||
|
||
```json
|
||
{
|
||
"repo_id": "<space-uuid>",
|
||
"title": "Optional title",
|
||
"provider": "openrouter",
|
||
"model": "anthropic/claude-3.5-sonnet",
|
||
"seed_from": "head"
|
||
}
|
||
```
|
||
|
||
| Field | Type | Required | Description |
|
||
|---|---|---|---|
|
||
| `repo_id` | UUID string | No | Attach to a Space. Omit for a FRESH session. |
|
||
| `title` | string | No | Defaults to `"Session MMM DD HH:MM"` |
|
||
| `provider` | string | No | Defaults to `chat.default_provider` from config |
|
||
| `model` | string | No | Model identifier for this provider |
|
||
| `seed_from` | string | No | `"head"` (default) seeds from latest Checkpoint; `"none"` starts fresh; a Checkpoint UUID seeds from that specific Checkpoint |
|
||
|
||
**Response:** Session object
|
||
|
||
```json
|
||
{
|
||
"id": "uuid",
|
||
"repo_id": "uuid or null",
|
||
"title": "Session Mar 21 14:30",
|
||
"active_provider": "openrouter",
|
||
"active_model": "anthropic/claude-3.5-sonnet",
|
||
"seeded_commit_id": "uuid or null",
|
||
"created_at": "2026-03-21T14:30:00Z",
|
||
"updated_at": "2026-03-21T14:30:00Z"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
#### List recent sessions
|
||
|
||
```
|
||
GET /api/v4/chat/sessions
|
||
```
|
||
|
||
Returns the 50 most recently updated Sessions, ordered by `updated_at` descending.
|
||
|
||
**Response:** Array of Session objects
|
||
|
||
---
|
||
|
||
#### Get a session
|
||
|
||
```
|
||
GET /api/v4/chat/sessions/{session_id}
|
||
```
|
||
|
||
**Response:** Session object
|
||
|
||
---
|
||
|
||
#### Generate a session title
|
||
|
||
```
|
||
POST /api/v4/chat/sessions/{session_id}/title
|
||
```
|
||
|
||
Uses the background intelligence model to generate a concise 3–5 word title from
|
||
the first four Turns of the Session. Updates `session.title` in place.
|
||
|
||
Called automatically by the frontend after the first assistant reply (if a background
|
||
provider is configured).
|
||
|
||
**Response:** Updated Session object
|
||
|
||
---
|
||
|
||
#### List session turns
|
||
|
||
```
|
||
GET /api/v4/chat/sessions/{session_id}/turns
|
||
```
|
||
|
||
Returns all Turns for a Session, ordered by `sequence_number` ascending.
|
||
|
||
**Response:** Array of Turn objects
|
||
|
||
```json
|
||
[
|
||
{
|
||
"id": "uuid",
|
||
"session_id": "uuid",
|
||
"role": "user",
|
||
"content": "What countries should I visit?",
|
||
"provider": "openrouter",
|
||
"model": "anthropic/claude-3.5-sonnet",
|
||
"sequence_number": 0,
|
||
"created_at": "2026-03-21T14:31:00Z"
|
||
},
|
||
{
|
||
"id": "uuid",
|
||
"session_id": "uuid",
|
||
"role": "assistant",
|
||
"content": "...",
|
||
"provider": "openrouter",
|
||
"model": "anthropic/claude-3.5-sonnet",
|
||
"sequence_number": 1,
|
||
"created_at": "2026-03-21T14:31:05Z"
|
||
}
|
||
]
|
||
```
|
||
|
||
---
|
||
|
||
#### Attach a session to a space
|
||
|
||
```
|
||
PUT /api/v4/chat/sessions/{session_id}/attach
|
||
```
|
||
|
||
Attaches an existing Session to a Space. Updates `session.repo_id` and sets
|
||
`repo_id` on all existing Turns in the Session.
|
||
|
||
**Request body:**
|
||
|
||
```json
|
||
{
|
||
"repo_id": "<space-uuid>"
|
||
}
|
||
```
|
||
|
||
**Response:** Updated Session object
|
||
|
||
---
|
||
|
||
### Sending messages
|
||
|
||
#### Send a message
|
||
|
||
```
|
||
POST /api/v4/chat/send
|
||
```
|
||
|
||
The core endpoint. Sends a user message, resolves the context based on the active
|
||
mode, calls the provider, and stores both the user Turn and assistant Turn.
|
||
|
||
**Request body:**
|
||
|
||
```json
|
||
{
|
||
"session_id": "<session-uuid>",
|
||
"repo_id": "<space-uuid>",
|
||
"provider": "openai",
|
||
"model": "gpt-4o",
|
||
"message": "What should I do first?",
|
||
"use_mock": false,
|
||
"memory_scope": "latest_1",
|
||
"mounted_checkpoint_id": null,
|
||
"history_base_seq": null
|
||
}
|
||
```
|
||
|
||
| Field | Type | Required | Description |
|
||
|---|---|---|---|
|
||
| `session_id` | UUID string | Yes | The active Session |
|
||
| `repo_id` | UUID string | No | The attached Space. Must match `session.repo_id`. |
|
||
| `provider` | string | Yes | Provider to use for this Turn |
|
||
| `model` | string | Yes | Model identifier |
|
||
| `message` | string | Yes | The user's message |
|
||
| `use_mock` | boolean | No | Use the deterministic mock adapter (no API key required) |
|
||
| `memory_scope` | string | No | `"latest_1"` (default) or `"latest_3"` |
|
||
| `mounted_checkpoint_id` | UUID string | No | If set, anchors context to this specific Checkpoint |
|
||
| `history_base_seq` | integer | No | Required when `mounted_checkpoint_id` is set. The sequence number of the last Turn before mounting. Only Turns with `sequence_number > history_base_seq` are included in context. |
|
||
|
||
**Context resolution logic:**
|
||
|
||
1. If `mounted_checkpoint_id` is set: use that Checkpoint (plus ancestors if
|
||
`memory_scope` is `"latest_3"`). Turn history: `sequence_number > history_base_seq`.
|
||
2. If `repo_id` is set (HEAD mode): use the N most recent Checkpoints from the Space.
|
||
Turn history: `created_at >= latest_checkpoint.created_at`.
|
||
3. Otherwise (FRESH): no Checkpoint context. No Turn history filter.
|
||
|
||
**Response:**
|
||
|
||
```json
|
||
{
|
||
"reply": "Here is what I recommend...",
|
||
"session_id": "uuid",
|
||
"turn_count": 4,
|
||
"provider": "openai",
|
||
"model": "gpt-4o"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### Spaces
|
||
|
||
#### List spaces
|
||
|
||
```
|
||
GET /api/v2/repos
|
||
```
|
||
|
||
Note: Spaces use the V2 prefix. The user-facing name is "Space"; the internal
|
||
model is `RepoModel`.
|
||
|
||
**Response:** Array of Space objects
|
||
|
||
```json
|
||
[
|
||
{
|
||
"id": "uuid",
|
||
"name": "Australia Trip",
|
||
"description": "Planning for the 2026 trip",
|
||
"created_at": "2026-03-01T10:00:00Z",
|
||
"updated_at": "2026-03-21T14:30:00Z"
|
||
}
|
||
]
|
||
```
|
||
|
||
#### Create a space
|
||
|
||
```
|
||
POST /api/v2/repos
|
||
```
|
||
|
||
**Request body:**
|
||
|
||
```json
|
||
{
|
||
"name": "Australia Trip",
|
||
"description": "Planning for the 2026 trip"
|
||
}
|
||
```
|
||
|
||
**Response:** Space object
|
||
|
||
#### Get a space
|
||
|
||
```
|
||
GET /api/v2/repos/{repo_id}
|
||
```
|
||
|
||
**Response:** Space object
|
||
|
||
#### Delete a space
|
||
|
||
```
|
||
DELETE /api/v2/repos/{repo_id}
|
||
```
|
||
|
||
Deletes a Space and cascades to every Checkpoint, Session, and Turn under it. Irreversible.
|
||
|
||
**Query parameters:**
|
||
|
||
- `force` (boolean, default `false`) — required to delete a Space that still holds checkpoints.
|
||
|
||
**Responses:**
|
||
|
||
- `204 No Content` — Space deleted (empty Space, or `force=true` on a populated Space).
|
||
- `404 Not Found` — Space does not exist (or belongs to a different user).
|
||
- `409 Conflict` — Space holds checkpoints and `force=true` was not passed. The response body carries a structured detail explaining the refusal:
|
||
|
||
```json
|
||
{
|
||
"detail": {
|
||
"message": "Cannot delete space 'Australia Trip': it still holds 12 checkpoint(s). Deletion cascades to every checkpoint, session, and turn under it and cannot be undone. Re-send with ?force=true to delete the space and all its contents.",
|
||
"checkpoint_count": 12,
|
||
"requires_force": true
|
||
}
|
||
}
|
||
```
|
||
|
||
The 409 guard is one of three deletion-safety layers — the CLI's `--force` flag and the MCP `smriti_delete_space` tool's `confirm_space` argument are the other two. Every client (direct `curl`, the web UI, a future client) goes through this server-side rule.
|
||
|
||
#### Get space head state (main-only)
|
||
|
||
```
|
||
GET /api/v4/chat/spaces/{repo_id}/head
|
||
```
|
||
|
||
Returns the latest main-branch Checkpoint and latest Session for a Space. This is the legacy single-HEAD endpoint — for multi-agent workflows, prefer `/state` below.
|
||
|
||
**Response:**
|
||
|
||
```json
|
||
{
|
||
"repo_id": "uuid",
|
||
"commit_hash": "abc1234...",
|
||
"commit_id": "uuid",
|
||
"summary": "Decided to focus on east coast cities",
|
||
"objective": "Plan a 3-week Australia itinerary",
|
||
"latest_session_id": "uuid",
|
||
"latest_session_title": "Australia Trip Planning"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
#### Get space state (multi-branch, default)
|
||
|
||
```
|
||
GET /api/v4/chat/spaces/{repo_id}/state
|
||
```
|
||
|
||
The agent-facing default. Returns the main-branch continuation brief plus active non-main branches, active work claims, and a divergence signal when any branch disagrees with main on decisions. One round trip, atomic snapshot.
|
||
|
||
**Response:**
|
||
|
||
```json
|
||
{
|
||
"space": {
|
||
"id": "uuid",
|
||
"name": "my-project",
|
||
"description": "..."
|
||
},
|
||
"head": { "...same shape as /head..." },
|
||
"commit": { "...full main-branch HEAD checkpoint..." },
|
||
"active_branches": [
|
||
{
|
||
"branch_name": "experiment-a",
|
||
"commit_id": "uuid",
|
||
"commit_hash": "abc1234...",
|
||
"message": "Trying alternative approach",
|
||
"author_agent": "codex-local",
|
||
"created_at": "...",
|
||
"summary": "..."
|
||
}
|
||
],
|
||
"active_claims": [
|
||
{
|
||
"id": "uuid",
|
||
"agent": "claude-code",
|
||
"branch_name": "main",
|
||
"scope": "Adding lineage test",
|
||
"intent_type": "implement",
|
||
"claimed_at": "...",
|
||
"expires_at": "...",
|
||
"base_commit_hash": "abc1234"
|
||
}
|
||
],
|
||
"divergence": {
|
||
"pairs": [
|
||
{
|
||
"branch_name": "experiment-a",
|
||
"branch_commit_hash": "def5678",
|
||
"main_only_decisions": ["Use Pydantic"],
|
||
"branch_only_decisions": ["Use dataclasses"]
|
||
}
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
`active_branches` is capped at 5 (most recent by `created_at`). `divergence.pairs` is capped at 2. Per-branch divergence is capped at 3 decisions per side. `active_claims` shows only active, non-expired claims. All three sections are omitted from the response when empty.
|
||
|
||
---
|
||
|
||
### Provider status
|
||
|
||
#### List provider status
|
||
|
||
```
|
||
GET /api/v4/chat/providers
|
||
```
|
||
|
||
Returns the configuration status of all providers. Never returns API keys.
|
||
|
||
**Response:**
|
||
|
||
```json
|
||
{
|
||
"openai": {
|
||
"enabled": true,
|
||
"has_key": true,
|
||
"missing_package": false,
|
||
"configured": true,
|
||
"status_label": "Ready",
|
||
"default_model": "gpt-4o"
|
||
},
|
||
"anthropic": {
|
||
"enabled": false,
|
||
"has_key": false,
|
||
"missing_package": false,
|
||
"configured": false,
|
||
"status_label": "Disabled",
|
||
"default_model": ""
|
||
},
|
||
"openrouter": {
|
||
"enabled": true,
|
||
"has_key": true,
|
||
"missing_package": false,
|
||
"configured": true,
|
||
"status_label": "Ready",
|
||
"default_model": ""
|
||
},
|
||
"background_intelligence": {
|
||
"provider": "openai",
|
||
"model": "gpt-4o-mini",
|
||
"enabled": true,
|
||
"has_key": true,
|
||
"configured": true,
|
||
"status_label": "Ready"
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## V5 — Checkpoint API
|
||
|
||
Prefix: `/api/v5/checkpoint`
|
||
|
||
The V5 API handles checkpoint drafting — the AI-assisted extraction of structured
|
||
state from a conversation.
|
||
|
||
---
|
||
|
||
### Draft a checkpoint
|
||
|
||
```
|
||
POST /api/v5/checkpoint/draft
|
||
```
|
||
|
||
Uses the background intelligence model to extract structured metadata from the
|
||
active conversation. Returns a draft that the user can review, edit, and save.
|
||
|
||
**Important:** This endpoint respects the same context isolation as `send_message`.
|
||
If `mounted_checkpoint_id` and `history_base_seq` are provided, the draft is
|
||
extracted only from Turns after the isolation boundary — the same Turns the model
|
||
saw during the session.
|
||
|
||
**Request body:**
|
||
|
||
```json
|
||
{
|
||
"session_id": "<session-uuid>",
|
||
"num_turns": 15,
|
||
"mounted_checkpoint_id": null,
|
||
"history_base_seq": null
|
||
}
|
||
```
|
||
|
||
| Field | Type | Required | Description |
|
||
|---|---|---|---|
|
||
| `session_id` | UUID string | Yes | The Session to draft from |
|
||
| `num_turns` | integer | No | Maximum number of recent Turns to include (default 15, max 100) |
|
||
| `mounted_checkpoint_id` | UUID string | No | If set, applies isolation boundary |
|
||
| `history_base_seq` | integer | No | Required when `mounted_checkpoint_id` is set |
|
||
|
||
**Turn selection:**
|
||
|
||
- If `mounted_checkpoint_id` and `history_base_seq` are both provided:
|
||
`sequence_number > history_base_seq`, limited to `num_turns` most recent
|
||
- Otherwise: all Turns in the Session, limited to `num_turns` most recent
|
||
|
||
No previous Checkpoint context is injected into the extraction prompt. The draft
|
||
reflects only what is present in the selected Turns.
|
||
|
||
**Response:**
|
||
|
||
```json
|
||
{
|
||
"title": "Australia East Coast Plan",
|
||
"objective": "Decide on a 3-week itinerary for Australia focusing on the east coast",
|
||
"summary": "The user is planning a trip to Australia and has narrowed focus to Sydney, Melbourne, and the Great Barrier Reef. Budget and timing constraints have been discussed.",
|
||
"decisions": [
|
||
"Focus on east coast cities only",
|
||
"Avoid peak season (December–January)"
|
||
],
|
||
"tasks": [
|
||
"Research visa requirements",
|
||
"Compare flight options from London"
|
||
],
|
||
"open_questions": [
|
||
"Whether to include Tasmania",
|
||
"How many nights to allocate to each city"
|
||
],
|
||
"entities": [
|
||
"Sydney",
|
||
"Melbourne",
|
||
"Great Barrier Reef",
|
||
"Qantas"
|
||
],
|
||
"assumptions": [
|
||
"Budget is flexible",
|
||
"Traveling from London"
|
||
]
|
||
}
|
||
```
|
||
|
||
All array fields may be empty if nothing relevant was found in the conversation.
|
||
`objective` may be an empty string if the goal is not stated clearly enough to extract.
|
||
`assumptions` captures things the conversation takes for granted that were not explicitly
|
||
debated or decided.
|
||
|
||
---
|
||
|
||
### Review a checkpoint
|
||
|
||
```
|
||
POST /api/v5/checkpoint/{checkpoint_id}/review
|
||
```
|
||
|
||
Uses the background intelligence model to review a checkpoint for reasoning
|
||
consistency. Returns a list of issues and suggestions.
|
||
|
||
**Issue types (V1):**
|
||
|
||
| Type | Description |
|
||
|---|---|
|
||
| `contradiction` | Two decisions or an assumption and a decision that appear to conflict |
|
||
| `hidden_assumption` | Something the reasoning relies on that is not listed as an assumption or decision |
|
||
| `resolved_question` | An open question that appears already answered by a decision or the summary |
|
||
| `unused_entity` | An entity not referenced in the summary, decisions, tasks, or objective |
|
||
|
||
**Response:**
|
||
|
||
```json
|
||
{
|
||
"checkpoint_id": "uuid",
|
||
"issues": [
|
||
{
|
||
"type": "hidden_assumption",
|
||
"description": "The itinerary assumes travel logistics between cities can be easily managed within the 10-day timeframe"
|
||
}
|
||
],
|
||
"suggestions": [
|
||
"Consider adding travel logistics as an explicit assumption"
|
||
]
|
||
}
|
||
```
|
||
|
||
Issues are capped at 5 per review. The review is conservative and prefers precision
|
||
over recall.
|
||
|
||
---
|
||
|
||
### Saving a checkpoint
|
||
|
||
Checkpoints are saved via the V4 commit endpoint, not V5.
|
||
|
||
```
|
||
POST /api/v4/chat/commit
|
||
```
|
||
|
||
**Request body:**
|
||
|
||
```json
|
||
{
|
||
"repo_id": "<space-uuid>",
|
||
"session_id": "<session-uuid>",
|
||
"message": "Australia East Coast Plan",
|
||
"summary": "Decided to focus on east coast...",
|
||
"objective": "Plan a 3-week itinerary...",
|
||
"decisions": ["Focus on east coast cities only"],
|
||
"assumptions": ["Budget is flexible"],
|
||
"tasks": ["Research visa requirements"],
|
||
"open_questions": ["Whether to include Tasmania"],
|
||
"entities": ["Sydney", "Melbourne"],
|
||
"artifacts": [
|
||
{
|
||
"id": "a1b2c3d4",
|
||
"type": "text",
|
||
"label": "Draft itinerary",
|
||
"content": "Day 1: Arrive in Sydney..."
|
||
}
|
||
],
|
||
"repo_state": {
|
||
"head": "abc123def456...",
|
||
"head_short": "abc123d",
|
||
"branch": "main"
|
||
}
|
||
}
|
||
```
|
||
|
||
**Response:**
|
||
|
||
```json
|
||
{
|
||
"id": "uuid",
|
||
"commit_hash": "abc1234def5678...",
|
||
"message": "Australia East Coast Plan",
|
||
"created_at": "2026-03-21T15:00:00Z"
|
||
}
|
||
```
|
||
|
||
**Repo-state drift detection (`repo_state`).** The optional `repo_state` field
|
||
records the git HEAD and branch of the repo the checkpoint was created from.
|
||
It is persisted under the commit's `context_blob` and returned by `GET
|
||
/api/v4/chat/spaces/{repo_id}/state` as `commit.context_blob.repo_state`. The
|
||
CLI uses it on subsequent `smriti state` calls to detect drift — N commits
|
||
ahead of the recorded checkpoint, a different branch, or diverged history —
|
||
and surfaces those signals in the rendered state brief's `## Repo state`
|
||
section. The field is optional: clients that cannot inspect a repo (e.g. the
|
||
MCP server, which runs in the host's arbitrary working directory) may omit
|
||
it, and the backend stores an empty `context_blob`.
|
||
|
||
---
|
||
|
||
### Checkpoint history
|
||
|
||
#### List checkpoints for a space
|
||
|
||
```
|
||
GET /api/v2/repos/{repo_id}/commits
|
||
```
|
||
|
||
Returns all Checkpoints for a Space, ordered by creation time.
|
||
|
||
**Response:** Array of Checkpoint objects
|
||
|
||
```json
|
||
[
|
||
{
|
||
"id": "uuid",
|
||
"commit_hash": "abc1234...",
|
||
"parent_commit_id": "uuid or null",
|
||
"message": "Australia East Coast Plan",
|
||
"objective": "Plan a 3-week itinerary...",
|
||
"summary": "Decided to focus on east coast...",
|
||
"decisions": ["Focus on east coast cities only"],
|
||
"assumptions": ["Budget is flexible"],
|
||
"tasks": ["Research visa requirements"],
|
||
"open_questions": ["Whether to include Tasmania"],
|
||
"entities": ["Sydney", "Melbourne"],
|
||
"artifacts": [],
|
||
"created_at": "2026-03-21T15:00:00Z"
|
||
}
|
||
]
|
||
```
|
||
|
||
#### Get a specific checkpoint
|
||
|
||
```
|
||
GET /api/v2/commits/{commit_id}
|
||
```
|
||
|
||
**Response:** Checkpoint object (full fields as above)
|
||
|
||
---
|
||
|
||
---
|
||
|
||
## V5 — Lineage API
|
||
|
||
Prefix: `/api/v5/lineage`
|
||
|
||
The Lineage API handles session forking, branch tree visualization, and checkpoint
|
||
comparison across branches.
|
||
|
||
---
|
||
|
||
### Fork a session
|
||
|
||
```
|
||
POST /api/v5/lineage/sessions/fork
|
||
```
|
||
|
||
Creates a new Session branching from a specific Checkpoint. The forked session starts
|
||
with a clean Turn history; its context comes from the checkpoint state snapshot.
|
||
|
||
**Request body:**
|
||
|
||
```json
|
||
{
|
||
"space_id": "<space-uuid>",
|
||
"checkpoint_id": "<checkpoint-uuid>",
|
||
"branch_name": "my-branch",
|
||
"provider": "openai",
|
||
"model": "gpt-4o"
|
||
}
|
||
```
|
||
|
||
| Field | Type | Required | Description |
|
||
|---|---|---|---|
|
||
| `space_id` | UUID string | Yes | The Space to fork within |
|
||
| `checkpoint_id` | UUID string | Yes | The Checkpoint to fork from |
|
||
| `branch_name` | string | No | Branch name. Defaults to `"branch-YYYY-MM-DD"` |
|
||
| `provider` | string | No | Defaults to config default |
|
||
| `model` | string | No | Model for the new session |
|
||
|
||
**Response:**
|
||
|
||
```json
|
||
{
|
||
"session_id": "uuid",
|
||
"branch_name": "my-branch",
|
||
"forked_from_checkpoint_id": "uuid",
|
||
"history_base_seq": 0
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### Get branch tree
|
||
|
||
```
|
||
GET /api/v5/lineage/spaces/{space_id}
|
||
```
|
||
|
||
Returns all Checkpoints and Sessions for a Space, structured for branch tree
|
||
rendering. Checkpoints carry `parent_checkpoint_id` for the commit ancestry chain;
|
||
Sessions carry `forked_from_checkpoint_id` to locate where each branch began.
|
||
|
||
**Response:**
|
||
|
||
```json
|
||
{
|
||
"space_id": "uuid",
|
||
"checkpoints": [
|
||
{
|
||
"id": "uuid",
|
||
"commit_hash": "abc1234...",
|
||
"message": "Australia East Coast Plan",
|
||
"branch_name": "main",
|
||
"parent_checkpoint_id": "uuid or null",
|
||
"created_at": "...",
|
||
"summary": "...",
|
||
"objective": "..."
|
||
}
|
||
],
|
||
"sessions": [
|
||
{
|
||
"id": "uuid",
|
||
"title": "Session Mar 21",
|
||
"branch_name": "main",
|
||
"forked_from_checkpoint_id": "uuid or null",
|
||
"seeded_commit_id": "uuid or null",
|
||
"created_at": "..."
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### Compare two checkpoints
|
||
|
||
```
|
||
GET /api/v5/lineage/checkpoints/{a_id}/compare/{b_id}
|
||
```
|
||
|
||
Returns a structured diff of two Checkpoint state snapshots. Works across any two
|
||
Checkpoints regardless of branch origin.
|
||
|
||
**Response:**
|
||
|
||
```json
|
||
{
|
||
"checkpoint_a": {
|
||
"id": "uuid",
|
||
"commit_hash": "abc1234...",
|
||
"message": "...",
|
||
"branch_name": "main",
|
||
"summary": "...",
|
||
"objective": "...",
|
||
"decisions": ["..."],
|
||
"tasks": ["..."],
|
||
"open_questions": ["..."]
|
||
},
|
||
"checkpoint_b": { ... },
|
||
"diff": {
|
||
"summary_a": "...",
|
||
"summary_b": "...",
|
||
"objective_a": "...",
|
||
"objective_b": "...",
|
||
"decisions_only_a": ["..."],
|
||
"decisions_only_b": ["..."],
|
||
"decisions_shared": ["..."],
|
||
"tasks_only_a": ["..."],
|
||
"tasks_only_b": ["..."],
|
||
"tasks_shared": ["..."]
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### Get reachable checkpoints for a session
|
||
|
||
```
|
||
GET /api/v5/lineage/sessions/{session_id}/checkpoints
|
||
```
|
||
|
||
Returns the Checkpoint set reachable from a given Session. This is the authoritative
|
||
query for populating the checkpoint history panel and mount-candidate list.
|
||
|
||
Reachability rules:
|
||
|
||
- **Main-branch session** — all Checkpoints where `branch_name == "main"`, newest first.
|
||
- **Forked session** — fork-local Checkpoints (same branch) plus the fork-source
|
||
Checkpoint and all its ancestors. Downstream main Checkpoints created after the fork
|
||
point are explicitly excluded.
|
||
|
||
**Response:** Array of full Checkpoint objects (same schema as `GET /api/v2/commits/{id}`)
|
||
|
||
---
|
||
|
||
## V5 — Work Claims API
|
||
|
||
Prefix: `/api/v5/claims`
|
||
|
||
Work claims are lightweight, time-bounded declarations that an agent is actively
|
||
working on something in a space. They make pre-work intent visible to other agents
|
||
before work produces a checkpoint. Claims are advisory — not locks.
|
||
|
||
---
|
||
|
||
### Create a work claim
|
||
|
||
```
|
||
POST /api/v5/claims
|
||
```
|
||
|
||
**Request body:**
|
||
|
||
```json
|
||
{
|
||
"space_id": "<space-uuid>",
|
||
"agent": "claude-code",
|
||
"scope": "Adding lineage test for author_agent",
|
||
"branch_name": "main",
|
||
"base_commit_id": "<checkpoint-uuid>",
|
||
"intent_type": "implement",
|
||
"ttl_hours": 4.0
|
||
}
|
||
```
|
||
|
||
| Field | Type | Required | Description |
|
||
|---|---|---|---|
|
||
| `space_id` | UUID string | Yes | The Space to claim work in |
|
||
| `agent` | string | Yes | Agent identifier (e.g. `claude-code`, `codex-local`) |
|
||
| `scope` | string | Yes | One sentence describing the work |
|
||
| `branch_name` | string | No | Branch the work targets. Default `"main"` |
|
||
| `base_commit_id` | UUID string | No | The Checkpoint the agent read as HEAD |
|
||
| `intent_type` | string | No | One of: `implement`, `review`, `investigate`, `docs`, `test`. Default `"implement"` |
|
||
| `ttl_hours` | float | No | Hours until the claim expires. Default `4.0` |
|
||
|
||
**Response:** Claim object (status `"active"`, `claimed_at` and `expires_at` set)
|
||
|
||
---
|
||
|
||
### Update a claim
|
||
|
||
```
|
||
PATCH /api/v5/claims/{claim_id}
|
||
```
|
||
|
||
Marks a claim as `done` or `abandoned`. Only active claims can be updated.
|
||
|
||
**Request body:**
|
||
|
||
```json
|
||
{
|
||
"status": "done"
|
||
}
|
||
```
|
||
|
||
| Value | Meaning |
|
||
|---|---|
|
||
| `done` | Work completed successfully |
|
||
| `abandoned` | Work intentionally stopped |
|
||
|
||
**Response:** Updated Claim object
|
||
|
||
Returns `409` if the claim is already `done` or `abandoned`.
|
||
|
||
---
|
||
|
||
### List claims
|
||
|
||
```
|
||
GET /api/v5/claims?space_id=<uuid>
|
||
```
|
||
|
||
Returns active, non-expired claims for a space. Pass `include_expired=true` to
|
||
include done, abandoned, and expired claims.
|
||
|
||
**Response:** Array of Claim objects
|
||
|
||
---
|
||
|
||
## Error responses
|
||
|
||
All endpoints return errors in this format:
|
||
|
||
```json
|
||
{
|
||
"detail": "Session not found"
|
||
}
|
||
```
|
||
|
||
| Status | Meaning |
|
||
|---|---|
|
||
| 400 | Bad request — missing required field or invalid input |
|
||
| 404 | Resource not found |
|
||
| 422 | Validation error — request body did not match schema |
|
||
| 500 | Server error — typically a misconfigured or missing background provider |
|
||
| 502 | Provider error — the upstream LLM returned an error or invalid response |
|
||
|
||
---
|
||
|
||
## Notes on V1, V2, V4, V5
|
||
|
||
`/api/v1` — Transcript paste ingestion. Accepts raw text, extracts memories,
|
||
generates context packs. Not used by the current UI or CLI. Retained for
|
||
compatibility but no new development happens here. Do not build new integrations
|
||
against V1.
|
||
|
||
`/api/v2` — Space CRUD and Checkpoint read endpoints. The CLI reads full
|
||
checkpoints via `GET /api/v2/commits/{commit_id}` and lists per-space checkpoints
|
||
via `GET /api/v2/repos/{repo_id}/commits`. The `CommitResponse` schema returns
|
||
the complete checkpoint shape including `assumptions` and `artifacts`. New
|
||
programmatic clients are welcome to use V2 read endpoints; for writes, use V4
|
||
(`POST /api/v4/chat/commit`) which accepts the full schema.
|
||
|
||
`/api/v4` — Chat sessions, message sending, and the canonical checkpoint write
|
||
path. The chat UI's primary interaction surface and the CLI's write surface.
|
||
|
||
`/api/v5` — Checkpoint drafting, review, fork, compare, lineage, and work claims.
|
||
Used by both the chat UI and the CLI/MCP server.
|