openapi: 3.0.3 info: title: byre version: 0.0.0 paths: /api/me: get: operationId: getMe responses: "200": description: The calling user. content: application/json: schema: { $ref: "#/components/schemas/User" } put: operationId: updateMe requestBody: required: true content: application/json: schema: { $ref: "#/components/schemas/UserUpdate" } responses: "200": description: The updated user. content: application/json: schema: { $ref: "#/components/schemas/User" } "400": { $ref: "#/components/responses/Error" } /api/me/notifications: put: operationId: updateNotificationPrefs description: Sets which inbox items the calling user is sent push notifications for. requestBody: required: true content: application/json: schema: { $ref: "#/components/schemas/NotificationPrefs" } responses: "200": description: The updated user. content: application/json: schema: { $ref: "#/components/schemas/User" } "400": { $ref: "#/components/responses/Error" } /api/me/push-subscriptions: post: operationId: addPushSubscription description: Registers a browser's push subscription for the calling user. Registering an endpoint again replaces it. requestBody: required: true content: application/json: schema: { $ref: "#/components/schemas/PushSubscription" } responses: "204": description: Registered. "400": { $ref: "#/components/responses/Error" } delete: operationId: removePushSubscription parameters: - { name: endpoint, in: query, required: true, schema: { type: string } } responses: "204": description: Removed, or was not registered. /api/push/key: get: operationId: getPushKey responses: "200": description: The server's VAPID public key, the applicationServerKey for PushManager.subscribe. content: application/json: schema: { $ref: "#/components/schemas/PushKey" } /api/projects: get: operationId: listProjects responses: "200": description: All projects. content: application/json: schema: type: array items: { $ref: "#/components/schemas/Project" } post: operationId: createProject requestBody: required: true content: application/json: schema: { $ref: "#/components/schemas/ProjectCreate" } responses: "201": description: The new project. content: application/json: schema: { $ref: "#/components/schemas/Project" } "400": { $ref: "#/components/responses/Error" } /api/projects/{projectId}: parameters: - { name: projectId, in: path, required: true, schema: { type: string } } get: operationId: getProject responses: "200": description: The project. content: application/json: schema: { $ref: "#/components/schemas/Project" } "404": { $ref: "#/components/responses/Error" } /api/projects/{projectId}/tasks: parameters: - { name: projectId, in: path, required: true, schema: { type: string } } get: operationId: listTasks responses: "200": description: The project's tasks, newest first. content: application/json: schema: type: array items: { $ref: "#/components/schemas/Task" } "404": { $ref: "#/components/responses/Error" } post: operationId: createTask description: Creates the task's branch and worktree from the project's default branch. requestBody: required: true content: application/json: schema: { $ref: "#/components/schemas/TaskCreate" } responses: "201": description: The new task. content: application/json: schema: { $ref: "#/components/schemas/Task" } "400": { $ref: "#/components/responses/Error" } "404": { $ref: "#/components/responses/Error" } /api/projects/{projectId}/todo: parameters: - { name: projectId, in: path, required: true, schema: { type: string } } get: operationId: getTodo description: The items of TODO.md at the root of the project's default branch, in file order. responses: "200": description: The items; exists is false when the default branch has no TODO.md. content: application/json: schema: { $ref: "#/components/schemas/Todo" } "404": { $ref: "#/components/responses/Error" } /api/projects/{projectId}/todo/tasks: parameters: - { name: projectId, in: path, required: true, schema: { type: string } } post: operationId: startTodoItem description: > Creates a task for a TODO.md item, recording the item as its todo_item, and starts its agent with the item as the first message. Refused while another active task has the same item. requestBody: required: true content: application/json: schema: { $ref: "#/components/schemas/TodoStart" } responses: "201": description: The new task. content: application/json: schema: { $ref: "#/components/schemas/Task" } "400": { $ref: "#/components/responses/Error" } "404": { $ref: "#/components/responses/Error" } "409": { $ref: "#/components/responses/Error" } /api/tasks/{taskId}: parameters: - { name: taskId, in: path, required: true, schema: { type: string } } get: operationId: getTask responses: "200": description: The task. content: application/json: schema: { $ref: "#/components/schemas/Task" } "404": { $ref: "#/components/responses/Error" } /api/tasks/{taskId}/unmerged: parameters: - { name: taskId, in: path, required: true, schema: { type: string } } get: operationId: getUnmerged description: What the task's worktree holds that its project's default branch doesn't. responses: "200": description: The unmerged changes. content: application/json: schema: { $ref: "#/components/schemas/Unmerged" } "404": { $ref: "#/components/responses/Error" } "409": { $ref: "#/components/responses/Error" } /api/tasks/{taskId}/co-authors: parameters: - { name: taskId, in: path, required: true, schema: { type: string } } get: operationId: getCoAuthors description: > The humans other than the caller with a message in the task's transcript (sent its agent a message, or had an inbox answer delivered under their name), in order of their first message. A merge by the caller gives each one with a git identity a Co-authored-by trailer. responses: "200": description: The co-authors. content: application/json: schema: type: array items: { $ref: "#/components/schemas/Participant" } "404": { $ref: "#/components/responses/Error" } /api/tasks/{taskId}/merge: parameters: - { name: taskId, in: path, required: true, schema: { type: string } } post: operationId: mergeTask description: > Starts the same agent turn as merge-in. When that turn ends normally, byre squashes the task's worktree into one commit titled with the task's merge_title on the project's default branch, authored by the caller with a Co-authored-by trailer for each of the task's co-authors, pushes it to origin, fast-forwards the project's checkout to it, then removes the worktree and branch and marks the task merged. Refused while a turn is running or queued. responses: "202": description: The merge turn was started or queued. content: application/json: schema: { $ref: "#/components/schemas/AgentSession" } "400": { $ref: "#/components/responses/Error" } "404": { $ref: "#/components/responses/Error" } "409": { $ref: "#/components/responses/Error" } /api/tasks/{taskId}/merge-in: parameters: - { name: taskId, in: path, required: true, schema: { type: string } } post: operationId: mergeIn description: > Asks the task's agent to merge the project's default branch into the task branch, resolving any conflicts and regenerating generated files. Sent to the task's idle session, or starts a session when it has none. Refused while a turn is running or queued. responses: "202": description: The merge turn was started or queued. content: application/json: schema: { $ref: "#/components/schemas/AgentSession" } "400": { $ref: "#/components/responses/Error" } "404": { $ref: "#/components/responses/Error" } "409": { $ref: "#/components/responses/Error" } /api/tasks/{taskId}/discard: parameters: - { name: taskId, in: path, required: true, schema: { type: string } } post: operationId: discardTask description: Removes the task's worktree and branch without merging. The task's record and events remain. responses: "200": description: The discarded task. content: application/json: schema: { $ref: "#/components/schemas/Task" } "404": { $ref: "#/components/responses/Error" } "409": { $ref: "#/components/responses/Error" } /api/tasks/{taskId}/events: parameters: - { name: taskId, in: path, required: true, schema: { type: string } } get: operationId: listTaskEvents description: The task's events after a seq, oldest first. Page by passing the last seq back as after. parameters: - { name: after, in: query, required: false, schema: { type: integer, format: int64 } } - { name: limit, in: query, required: false, schema: { type: integer, minimum: 1, maximum: 1000 } } responses: "200": description: Up to limit events (default 500). content: application/json: schema: type: array items: { $ref: "#/components/schemas/Event" } "404": { $ref: "#/components/responses/Error" } /api/tasks/{taskId}/changes: parameters: - { name: taskId, in: path, required: true, schema: { type: string } } get: operationId: getTaskChanges description: > Everything in the task's worktree (committed, staged, unstaged and untracked, respecting .gitignore) as a tree, compared with the merge-base of the task branch and the project's default branch, or with since when given. The worktree's own index is not touched. With snapshot, the tree is that snapshot's instead, compared with the merge-base of its commit and the default branch, or with the previous snapshot's tree when step is true. parameters: - { name: since, in: query, required: false, schema: { type: string }, description: "A commit to compare with instead of the merge-base, such as a user.message event's head. Not allowed with snapshot." } - { name: snapshot, in: query, required: false, schema: { type: integer }, description: "A snapshot's n: show the task as it was in that snapshot rather than the live worktree." } - { name: step, in: query, required: false, schema: { type: boolean }, description: "With snapshot: compare with the previous snapshot (the snapshot commit's parent for the first one)." } responses: "200": description: Per-file stats. content: application/json: schema: { $ref: "#/components/schemas/TaskChanges" } "400": { $ref: "#/components/responses/Error" } "404": { $ref: "#/components/responses/Error" } "409": { $ref: "#/components/responses/Error" } /api/tasks/{taskId}/diff: parameters: - { name: taskId, in: path, required: true, schema: { type: string } } get: operationId: getTaskDiff description: The unified diff of one file between a base and tree from getTaskChanges. parameters: - { name: base, in: query, required: true, schema: { type: string } } - { name: tree, in: query, required: true, schema: { type: string } } - { name: path, in: query, required: true, schema: { type: string } } - { name: old_path, in: query, required: false, schema: { type: string } } responses: "200": description: The patch. content: application/json: schema: { $ref: "#/components/schemas/FileDiff" } "400": { $ref: "#/components/responses/Error" } "404": { $ref: "#/components/responses/Error" } "409": { $ref: "#/components/responses/Error" } /api/tasks/{taskId}/snapshots: parameters: - { name: taskId, in: path, required: true, schema: { type: string } } get: operationId: listSnapshots description: > The task's snapshots, oldest first. Each is a commit of the worktree as if everything were staged, kept at refs/byre/tasks/{taskId}/snap/{n} until the task is merged or discarded; the rows remain after that. responses: "200": description: The snapshots. content: application/json: schema: type: array items: { $ref: "#/components/schemas/Snapshot" } "404": { $ref: "#/components/responses/Error" } /api/tasks/{taskId}/sessions: parameters: - { name: taskId, in: path, required: true, schema: { type: string } } get: operationId: listSessions responses: "200": description: The task's agent sessions, oldest first. content: application/json: schema: type: array items: { $ref: "#/components/schemas/AgentSession" } "404": { $ref: "#/components/responses/Error" } post: operationId: createSession description: Starts an agent session in the task's worktree and sends it the prompt as its first turn. requestBody: required: true content: application/json: schema: { $ref: "#/components/schemas/SessionCreate" } responses: "201": description: The new session. content: application/json: schema: { $ref: "#/components/schemas/AgentSession" } "400": { $ref: "#/components/responses/Error" } "404": { $ref: "#/components/responses/Error" } "409": { $ref: "#/components/responses/Error" } /api/sessions/{sessionId}: parameters: - { name: sessionId, in: path, required: true, schema: { type: string } } get: operationId: getSession responses: "200": description: The session. content: application/json: schema: { $ref: "#/components/schemas/AgentSession" } "404": { $ref: "#/components/responses/Error" } /api/sessions/{sessionId}/messages: parameters: - { name: sessionId, in: path, required: true, schema: { type: string } } post: operationId: sendMessage description: Starts a new turn with this message. The session must be idle. requestBody: required: true content: application/json: schema: { $ref: "#/components/schemas/MessageCreate" } responses: "202": description: The turn has started. content: application/json: schema: { $ref: "#/components/schemas/AgentSession" } "400": { $ref: "#/components/responses/Error" } "404": { $ref: "#/components/responses/Error" } "409": { $ref: "#/components/responses/Error" } /api/sessions/{sessionId}/compact: parameters: - { name: sessionId, in: path, required: true, schema: { type: string } } post: operationId: compactSession description: > Asks the idle session's agent for a handoff (goal, decisions, state, dead ends, open questions, files). When that turn ends, the session is completed and a new session on the same task and model starts with the handoff as its first message. responses: "202": description: The handoff turn was started or queued. content: application/json: schema: { $ref: "#/components/schemas/AgentSession" } "404": { $ref: "#/components/responses/Error" } "409": { $ref: "#/components/responses/Error" } /api/sessions/{sessionId}/interrupt: parameters: - { name: sessionId, in: path, required: true, schema: { type: string } } post: operationId: interruptSession description: Ends the current turn. responses: "202": description: The interrupt was delivered. content: application/json: schema: { $ref: "#/components/schemas/AgentSession" } "404": { $ref: "#/components/responses/Error" } "409": { $ref: "#/components/responses/Error" } /api/blobs: post: operationId: uploadBlob description: > Stores an image for use in a message. The body is the raw image; its type is detected from the bytes and must be PNG, JPEG, GIF or WebP. At most 5 MiB. requestBody: required: true content: image/png: { schema: { type: string, format: binary } } image/jpeg: { schema: { type: string, format: binary } } image/gif: { schema: { type: string, format: binary } } image/webp: { schema: { type: string, format: binary } } responses: "201": description: The stored blob. content: application/json: schema: { $ref: "#/components/schemas/Blob" } "400": { $ref: "#/components/responses/Error" } "413": { $ref: "#/components/responses/Error" } /api/blobs/{blobId}: parameters: - { name: blobId, in: path, required: true, schema: { type: string } } get: operationId: getBlob responses: "200": description: The blob's bytes, with its content type. content: image/png: { schema: { type: string, format: binary } } image/jpeg: { schema: { type: string, format: binary } } image/gif: { schema: { type: string, format: binary } } image/webp: { schema: { type: string, format: binary } } "404": { $ref: "#/components/responses/Error" } /api/inbox: get: operationId: listInbox description: > Inbox items, highest priority first (blocked, gate, review, fyi), then oldest first. Filters narrow the one query to a project's or a task's view. parameters: - { name: project_id, in: query, required: false, schema: { type: string } } - { name: task_id, in: query, required: false, schema: { type: string } } - { name: state, in: query, required: false, schema: { $ref: "#/components/schemas/InboxState" } } responses: "200": description: Matching items with their responses. Defaults to open items. content: application/json: schema: type: array items: { $ref: "#/components/schemas/InboxItem" } /api/inbox/{itemId}: parameters: - { name: itemId, in: path, required: true, schema: { type: string } } get: operationId: getInboxItem responses: "200": description: The item with its responses. content: application/json: schema: { $ref: "#/components/schemas/InboxItem" } "404": { $ref: "#/components/responses/Error" } /api/inbox/responses: post: operationId: respondInbox description: > Answers one or more items in one submission. Answers reach the agent as one message once it is idle and none of its blocking questions are unanswered. requestBody: required: true content: application/json: schema: { $ref: "#/components/schemas/InboxRespond" } responses: "200": description: The updated items. content: application/json: schema: type: array items: { $ref: "#/components/schemas/InboxItem" } "400": { $ref: "#/components/responses/Error" } "404": { $ref: "#/components/responses/Error" } "409": { $ref: "#/components/responses/Error" } /api/events: get: operationId: streamEvents description: > Server-sent events. Each event's id is its seq; data is the Event as JSON. Events after Last-Event-ID (or the after query parameter) are replayed before live events. With task_id, only that task's events are sent. parameters: - { name: Last-Event-ID, in: header, required: false, schema: { type: integer, format: int64 } } - { name: after, in: query, required: false, schema: { type: integer, format: int64 } } - { name: task_id, in: query, required: false, schema: { type: string } } responses: "200": description: Event stream. content: text/event-stream: schema: { type: string } "404": { $ref: "#/components/responses/Error" } /api/admin/status: get: operationId: getStatus responses: "200": description: Server health and usage. content: application/json: schema: { $ref: "#/components/schemas/Status" } components: responses: Error: description: Error. content: application/json: schema: { $ref: "#/components/schemas/Error" } schemas: Error: type: object required: [message] properties: message: { type: string } User: type: object required: [login, display_name, git_name, git_email, notification_prefs] properties: login: { type: string } display_name: { type: string } git_name: { type: string } git_email: { type: string } notification_prefs: { $ref: "#/components/schemas/NotificationPrefs" } NotificationPrefs: type: object description: Which new inbox items send this user a push notification. required: [blocking_questions, questions, reports, errors, rate_limits] properties: blocking_questions: { type: boolean, description: "Questions asked with blocking: true. On by default." } questions: { type: boolean, description: Non-blocking questions. } reports: { type: boolean, description: Turn summaries. } errors: { type: boolean, description: session_error items. } rate_limits: { type: boolean, description: rate_limited items. } PushSubscription: type: object required: [endpoint, p256dh, auth] properties: endpoint: { type: string } p256dh: { type: string, description: The subscription's p256dh key, base64url. } auth: { type: string, description: The subscription's auth secret, base64url. } PushKey: type: object required: [public_key] properties: public_key: { type: string, description: Base64url, uncompressed P-256 point. } UserUpdate: type: object required: [git_name, git_email] properties: git_name: { type: string } git_email: { type: string } Project: type: object required: [id, name, repo_path, default_branch, remote, created_by, created_at] properties: id: { type: string } name: { type: string } repo_path: { type: string } default_branch: { type: string } remote: { type: string } created_by: { type: string } created_at: { type: string, format: date-time } ProjectCreate: type: object required: [name, repo_path] properties: name: { type: string } repo_path: { type: string } Task: type: object required: [id, project_id, title, merge_title, branch, worktree_path, base_ref, status, created_by, created_at] properties: id: { type: string } project_id: { type: string } title: { type: string } merge_title: { type: string, description: "The title of the squash commit Merge makes: the task title until the agent sets another with set_merge_title." } branch: { type: string } worktree_path: { type: string } base_ref: { type: string } status: type: string enum: [active, merged, discarded] x-enum-varnames: [TaskStatusActive, TaskStatusMerged, TaskStatusDiscarded] created_by: { type: string } created_at: { type: string, format: date-time } closed_at: { type: string, format: date-time, description: When the task was merged or discarded. } merge_commit: { type: string, description: "merged: the squash commit on the default branch; empty when there was nothing to merge." } todo_item: { type: string, description: "The title of the TODO.md item the task was started from; absent for other tasks." } Todo: type: object required: [exists, items] properties: exists: { type: boolean, description: Whether the default branch has a TODO.md at its root. } items: type: array items: { $ref: "#/components/schemas/TodoItem" } TodoItem: type: object required: [title, body, section] properties: title: { type: string, description: "The item's first line, without its list marker: the item's identity." } body: { type: string, description: The item's further lines, as Markdown with the item's indentation removed. } section: { type: string, description: The text of the nearest heading above the item; empty when there is none. } TodoStart: type: object required: [title] properties: title: { type: string, description: The title of the item to start. } model: { type: string } Unmerged: type: object required: [commits, files, insertions, deletions, uncommitted] properties: commits: { type: integer, description: Commits on the task branch that aren't on the default branch. } files: { type: integer, description: Files that differ from the merge base, uncommitted changes included. } insertions: { type: integer } deletions: { type: integer } uncommitted: { type: integer, description: Paths with uncommitted changes in the worktree. } Participant: type: object required: [login, display_name, git_name, git_email] properties: login: { type: string } display_name: { type: string } git_name: { type: string, description: Empty when the user hasn't set a git identity; they then get no trailer. } git_email: { type: string } TaskCreate: type: object required: [title] properties: title: { type: string } TaskChanges: type: object required: [base, tree, files] properties: base: { type: string, description: "The commit or tree compared with: the merge-base of the task branch and the default branch, since, or the previous snapshot's tree." } tree: { type: string, description: "Tree of the worktree as if everything were staged, or the snapshot's tree." } files: type: array items: { $ref: "#/components/schemas/FileChange" } FileChange: type: object required: [path, status, additions, deletions, binary] properties: path: { type: string } old_path: { type: string, description: "renamed: the path before the rename." } status: { type: string, enum: [added, modified, deleted, renamed, type_changed] } additions: { type: integer } deletions: { type: integer } binary: { type: boolean } FileDiff: type: object required: [path, patch] properties: path: { type: string } patch: { type: string } Snapshot: type: object required: [id, task_id, agent_session_id, n, commit_sha, tree_sha, event_seq, trigger, created_at] properties: id: { type: string } task_id: { type: string } agent_session_id: { type: string } n: { type: integer, description: "Position in the task's snapshots, from 1; the ref is refs/byre/tasks/{task_id}/snap/{n}." } commit_sha: { type: string, description: A commit of tree_sha whose parent is the worktree's HEAD when it was taken. } tree_sha: { type: string } event_seq: { type: integer, format: int64, description: "The task's latest event when the snapshot was started: the tree holds at least the work up to it." } trigger: type: string enum: [tool_call, turn_end, ask_human, timer] x-enum-varnames: [SnapshotTriggerToolCall, SnapshotTriggerTurnEnd, SnapshotTriggerAskHuman, SnapshotTriggerTimer] created_at: { type: string, format: date-time } AgentSession: type: object required: [id, task_id, vendor, model, vendor_session_id, state, role, created_by, created_at] properties: id: { type: string } task_id: { type: string } vendor: { type: string, enum: [claude] } model: { type: string, description: Requested model; empty means the vendor's default. } vendor_session_id: { type: string } state: type: string enum: [idle, queued, running, completed] x-enum-varnames: [AgentSessionStateIdle, AgentSessionStateQueued, AgentSessionStateRunning, AgentSessionStateCompleted] description: queued means a turn is waiting for a free slot under the concurrency caps. role: { type: string, enum: [implementer] } created_by: { type: string } created_at: { type: string, format: date-time } SessionCreate: type: object required: [prompt] properties: prompt: { type: string } model: { type: string } images: type: array items: { type: string } description: Blob ids from uploadBlob, sent to the agent as images alongside the prompt. MessageCreate: type: object required: [text] properties: text: { type: string, description: May be empty when images are given. } images: type: array items: { type: string } description: Blob ids from uploadBlob, sent to the agent as images alongside the text. model: type: string description: Model for this turn and later ones. When it differs from the session's model, the session switches before the message is sent. Blob: type: object required: [id, content_type, created_by, created_at] properties: id: { type: string } content_type: { type: string } created_by: { type: string } created_at: { type: string, format: date-time } Attachment: type: object required: [kind] properties: kind: { type: string, enum: [file, diff, image, diagram, task, snapshot, url] } path: { type: string, description: "file: repo-relative path." } start_line: { type: integer } end_line: { type: integer } ref: { type: string, description: "diff: git revision range." } url: { type: string } mermaid: { type: string, description: "diagram: Mermaid source." } image: { type: string, description: "image: data URL." } task_id: { type: string } snapshot_id: { type: string } caption: { type: string } InboxState: type: string enum: [open, answered, dismissed, superseded] InboxItem: type: object required: [id, project_id, task_id, agent_session_id, thread_id, kind, priority, blocking, payload, state, created_at, responses] properties: id: { type: string } project_id: { type: string } task_id: { type: string } agent_session_id: { type: string } thread_id: { type: string } kind: { type: string, enum: [question, report, session_error, rate_limited] } priority: { type: string, enum: [blocked, gate, review, fyi] } blocking: { type: boolean } payload: type: object description: > question: context (Markdown with the choices inline as `- ( ) text` / `- (*) text` pick-one or `- [ ] text` / `- [x] text` pick-any list items), question, why_blocked, options (each choice's text, in order), multiple (true for pick-any), recommended (the marked choices' text), attachments. report: text (the final message of a turn that ended normally). session_error: error. rate_limited: vendor, rate_limit (the vendor's rate-limit status), error. state: { $ref: "#/components/schemas/InboxState" } created_at: { type: string, format: date-time } resolved_by: { type: string } resolved_at: { type: string, format: date-time } responses: type: array items: { $ref: "#/components/schemas/InboxResponse" } InboxResponseType: type: string enum: [option, other, dismiss] InboxResponse: type: object required: [id, item_id, user, type, attachments, created_at] properties: id: { type: string } item_id: { type: string } user: { type: string } type: { $ref: "#/components/schemas/InboxResponseType" } options: type: array items: { type: string } text: { type: string } attachments: type: array items: { $ref: "#/components/schemas/Attachment" } created_at: { type: string, format: date-time } delivered_at: { type: string, format: date-time } InboxResponseCreate: type: object required: [item_id, type] properties: item_id: { type: string } type: { $ref: "#/components/schemas/InboxResponseType" } options: type: array items: { type: string } description: "option: the chosen options; exactly one for a pick-one question, one or more for a pick-any question." text: { type: string, description: "other: the text sent to the agent. option on a pick-any question: optional text sent along with the checked options." } attachments: type: array items: { $ref: "#/components/schemas/Attachment" } InboxRespond: type: object required: [responses] properties: responses: type: array minItems: 1 items: { $ref: "#/components/schemas/InboxResponseCreate" } Event: type: object required: [seq, kind, actor, payload, created_at] properties: seq: { type: integer, format: int64 } kind: { type: string } project_id: { type: string } task_id: { type: string } agent_session_id: { type: string } actor: { type: string } payload: { type: object } created_at: { type: string, format: date-time } Status: type: object required: [started_at, db_bytes, last_event_seq, projects, active_tasks, sse_clients, live_agents, running_turns, queued_turns, caps, rate_limits, agent_processes, zombies, stuck_after_seconds, protocol_errors] properties: live_agents: { type: integer, description: Agent processes currently running. } agent_processes: type: array description: Every agent process byre is tracking, idle sessions included. items: { $ref: "#/components/schemas/AgentProcess" } zombies: type: array description: Sessions marked running with no live process, and agent processes byre has no session for. items: { $ref: "#/components/schemas/Zombie" } stuck_after_seconds: { type: integer, description: How long a running turn may go without a stream event before it counts as stuck. } protocol_errors: { $ref: "#/components/schemas/ProtocolErrors" } running_turns: type: array description: Turns running now, oldest session first. items: { $ref: "#/components/schemas/TurnRef" } queued_turns: type: array description: Turns waiting for room under the caps, in the order they will start. items: { $ref: "#/components/schemas/TurnRef" } caps: { $ref: "#/components/schemas/Caps" } rate_limits: type: object description: The latest rate-limit status each vendor reported, keyed by vendor. additionalProperties: { type: object } started_at: { type: string, format: date-time } db_bytes: { type: integer, format: int64 } last_event_seq: { type: integer, format: int64 } projects: { type: integer } active_tasks: { type: integer } sse_clients: { type: integer } Caps: type: object required: [global, per_vendor] properties: global: { type: integer, description: Most turns running at once across all vendors. } per_vendor: type: object description: Most turns running at once per vendor, keyed by vendor. additionalProperties: { type: integer } TurnRef: type: object required: [session_id, task_id, vendor] properties: session_id: { type: string } task_id: { type: string } vendor: { type: string } AgentProcess: type: object required: [session_id, task_id, vendor, pid, state, last_event_at, health] properties: session_id: { type: string } task_id: { type: string } vendor: { type: string } pid: { type: integer } state: { type: string, description: The session's state, as on AgentSession. } last_event_at: { type: string, format: date-time, description: When the process last wrote a line to its stream, or when it started. } health: type: string enum: [ok, stuck, exited] x-enum-varnames: [HealthOk, HealthStuck, HealthExited] description: stuck means a turn is running and no stream event has arrived for stuck_after_seconds; exited means the process is gone. Zombie: type: object required: [kind, detail] properties: kind: type: string enum: [running_without_process, process_without_session] detail: { type: string } session_id: { type: string } task_id: { type: string } pid: { type: integer } ProtocolErrors: type: object required: [counts, recent] properties: counts: type: object description: Stream lines the adapter couldn't parse or didn't recognise since byre started, keyed by vendor. additionalProperties: { type: integer } recent: type: array description: The most recent ones, newest first. items: { $ref: "#/components/schemas/ProtocolError" } ProtocolError: type: object required: [vendor, session_id, at, reason, raw, size] properties: vendor: { type: string } session_id: { type: string } at: { type: string, format: date-time } reason: { type: string } raw: { type: string, description: The line as received, cut to its first 4 KiB. } size: { type: integer, description: The line's full length in bytes. }