{
  "openapi": "3.1.0",
  "info": {
    "title": "Replicas API",
    "version": "2.0.0",
    "description": "Create and control workspaces, and manage the environments, automations, and learnings they run with."
  },
  "servers": [{"url": "https://api.replicas.dev", "description": "Production API"}],
  "security": [{"apiKey": []}],
  "tags": [
    {
      "name": "Replica",
      "description": "A replica is a Replicas workspace: a cloud sandbox where a coding agent works on your repositories."
    },
    {"name": "Chats", "description": "Manage the agent chats inside a replica."},
    {"name": "Message queue", "description": "Messages waiting for the agent to finish its turn."},
    {"name": "Commands and terminals", "description": "Run commands and open shells in a replica."},
    {"name": "Pull requests", "description": "Inspect and act on pull requests a replica opened."},
    {"name": "Previews", "description": "Public URLs for ports in a replica."},
    {"name": "Canvas", "description": "Plans, reports, and other files agents produce."},
    {"name": "Sharing", "description": "Add replicas to members' Shared view."},
    {
      "name": "Environments",
      "description": "Environments define what a workspace starts with. A fork builds on the environments it was forked from."
    },
    {"name": "Environment variables", "description": "Variables injected into workspaces."},
    {"name": "Environment files", "description": "Files written into workspaces."},
    {"name": "Environment skills", "description": "Agent skills installed into workspaces."},
    {"name": "Environment MCPs", "description": "MCP servers available to workspace agents."},
    {"name": "Hooks", "description": "Scripts that run when warm pool snapshots build and when workspaces start."},
    {"name": "Warm pools", "description": "Pre-built workspaces that start faster."},
    {"name": "Automations", "description": "Run agents on schedules and events."},
    {"name": "Repositories", "description": "Repositories connected to the organization."},
    {"name": "Learnings", "description": "Organization skills every workspace agent loads."},
    {
      "name": "Agent credentials",
      "description": "API keys and endpoints that coding agents use. Connect Claude, Codex, and Muse subscriptions with the CLI."
    },
    {"name": "Plugins", "description": "Connect integrations that workspace agents can use."},
    {"name": "Organization", "description": "Who you are and who is in your organization."},
    {"name": "Media", "description": "Screenshots, recordings, and other files workspaces produce."},
    {"name": "Slack", "description": "Route Slack threads to workspaces."},
    {"name": "Workspace identity", "description": "OIDC keys for verifying workspace identity tokens."}
  ],
  "paths": {
    "/v1/organization/conversations": {
      "get": {
        "operationId": "listOrganizationConversations",
        "summary": "List organization conversations",
        "description": "Exports retained conversations from every replica without waking them. Requires an organization API key. Deleted chats and conversations outside your [data retention](/admin/data-retention) window are omitted.",
        "tags": ["Replica"],
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "description": "Opaque cursor from `next_cursor`. It preserves the initial replica and environment filters and stable artifact creation order. Filters may be omitted on later requests but cannot be changed. Chat and replica deletion and restoration remain live and require restarting the export for a consistent total.",
            "required": false,
            "schema": {"type": "string"}
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {"type": "integer", "default": 25, "minimum": 1, "maximum": 100}
          },
          {
            "name": "workspace_id",
            "in": "query",
            "description": "Return conversations from one replica.",
            "required": false,
            "schema": {"type": "string", "format": "uuid"}
          },
          {
            "name": "environment_id",
            "in": "query",
            "description": "Return conversations from replicas created with one environment.",
            "required": false,
            "schema": {"type": "string", "format": "uuid"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ListOrganizationConversationsResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "403": {"$ref": "#/components/responses/Forbidden"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      }
    },
    "/v1/replica": {
      "post": {
        "operationId": "createReplica",
        "summary": "Create replica",
        "description": "Creates a replica from an environment and sends the first message. Returns immediately with `status: \"preparing\"`; use `GET /v1/replica/{id}/wait` to wait for it. An organization can have 100 API and automation replicas active or preparing at once.",
        "tags": ["Replica"],
        "parameters": [{"$ref": "#/components/parameters/ApiVersion"}],
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"$ref": "#/components/schemas/CreateReplicaRequest"}}}
        },
        "responses": {
          "201": {
            "description": "Replica created successfully",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/CreateReplicaResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "402": {"$ref": "#/components/responses/PaymentRequired"},
          "404": {
            "description": "Repository not found",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}
          },
          "409": {"$ref": "#/components/responses/Conflict"},
          "429": {
            "description": "The organization already has 100 metered API and Automation workspaces active or preparing",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}
          },
          "500": {"$ref": "#/components/responses/InternalServerError"},
          "503": {"$ref": "#/components/responses/ServiceUnavailable"}
        }
      },
      "get": {
        "operationId": "listReplicas",
        "summary": "List replicas",
        "description": "Lists replicas, newest first. With `status=archived`, sorted by most recent activity.",
        "tags": ["Replica"],
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "description": "Page number for pagination",
            "required": false,
            "schema": {"type": "integer", "default": 1, "minimum": 1}
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Number of items per page",
            "required": false,
            "schema": {"type": "integer", "default": 10, "minimum": 1, "maximum": 100}
          },
          {
            "name": "user_id",
            "in": "query",
            "description": "Filter replicas by the user who created them",
            "required": false,
            "schema": {"type": "string"}
          },
          {
            "name": "source",
            "in": "query",
            "description": "Filter replicas by creation source",
            "required": false,
            "schema": {"type": "string", "enum": ["api", "dashboard", "slack", "linear", "github", "gitlab", "automation"]}
          },
          {
            "name": "status",
            "in": "query",
            "description": "Filter replicas by status",
            "required": false,
            "schema": {"type": "string", "enum": ["active", "sleeping", "archived", "preparing", "error"]}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ListReplicasResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      }
    },
    "/v1/replica/{id}": {
      "get": {
        "operationId": "getReplica",
        "summary": "Get replica",
        "description": "Returns the replica with its chats, repositories, and pull requests. Sleeping and archived replicas return their retained chats without waking. Use `include` for environment details and diffs.",
        "tags": ["Replica"],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The unique identifier of the replica",
            "required": true,
            "schema": {"type": "string", "format": "uuid"}
          },
          {
            "name": "include",
            "in": "query",
            "description": "Comma-separated list of additional fields to include in the response",
            "required": false,
            "schema": {"type": "string", "example": "environment,diffs"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/GetReplicaResponse"}}}
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"},
          "502": {"$ref": "#/components/responses/BadGateway"}
        }
      },
      "delete": {
        "operationId": "deleteReplica",
        "summary": "Delete replica",
        "description": "Permanently deletes the replica and its sandbox.",
        "tags": ["Replica"],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The unique identifier of the replica",
            "required": true,
            "schema": {"type": "string", "format": "uuid"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Replica deleted successfully",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/DeleteReplicaResponse"}}}
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "409": {"$ref": "#/components/responses/Conflict"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      },
      "patch": {
        "operationId": "updateReplica",
        "summary": "Rename replica",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Replica ID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {"schema": {"type": "object", "properties": {"name": {"type": "string"}}, "required": ["name"]}}
          }
        },
        "responses": {
          "200": {
            "description": "Updated workspace",
            "content": {"application/json": {"schema": {"type": "object", "properties": {"workspace": {"type": "object"}}}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Replica"]
      }
    },
    "/v1/replica/{id}/messages": {
      "post": {
        "operationId": "sendReplicaMessage",
        "summary": "Send message",
        "description": "Sends a message to a chat. Sleeping replicas wake and archived replicas restore first. Messages sent while the agent is working are queued.",
        "tags": ["Replica"],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The unique identifier of the replica",
            "required": true,
            "schema": {"type": "string", "format": "uuid"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SendReplicaMessageRequest"}}}
        },
        "responses": {
          "200": {
            "description": "Message accepted",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SendReplicaMessageResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "409": {"$ref": "#/components/responses/Conflict"},
          "500": {"$ref": "#/components/responses/InternalServerError"},
          "502": {"$ref": "#/components/responses/BadGateway"},
          "503": {"$ref": "#/components/responses/ServiceUnavailable"}
        }
      }
    },
    "/v1/replica/{id}/history": {
      "get": {
        "operationId": "readReplicaHistory",
        "summary": "Read history",
        "description": "Reads history from the newest event. Omit `limit` for everything. To page back, pass the previous `before_cursor` until it is `null`. Sleeping and archived replicas return retained history without waking. Returns `409` when a suspended replica has no retained history.",
        "tags": ["Replica"],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The unique identifier of the replica",
            "required": true,
            "schema": {"type": "string", "format": "uuid"}
          },
          {
            "name": "chat_id",
            "in": "query",
            "description": "Filter history to a specific chat",
            "required": false,
            "schema": {"type": "string"}
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Maximum number of events to return, taken from the end of the history. Omit to return the full history.",
            "required": false,
            "schema": {"type": "integer", "minimum": 1}
          },
          {
            "name": "before_event",
            "in": "query",
            "description": "Exclusive upper bound: return only events with an index below this value. Pass the previous response's `eventsStartIndex` to fetch the page before it. Indexes are stable as new events append to the end.",
            "required": false,
            "schema": {"type": "integer", "minimum": 0}
          },
          {
            "name": "before_turn",
            "in": "query",
            "description": "Exclusive upper bound for Codex transcript turns, paged with `turnsStartIndex` the same way `beforeEvent` pages events.",
            "required": false,
            "schema": {"type": "integer", "minimum": 0}
          },
          {
            "name": "before_cursor",
            "in": "query",
            "description": "Opaque cursor from the previous response's `beforeCursor`. Advances events and Codex turns together.",
            "required": false,
            "schema": {"type": "string"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ReadReplicaHistoryResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"},
          "502": {"$ref": "#/components/responses/BadGateway"}
        }
      }
    },
    "/v1/replica/{id}/hooks": {
      "get": {
        "operationId": "getReplicaHooks",
        "summary": "Get hook logs",
        "description": "Returns warm hook and start hook logs.",
        "tags": ["Replica"],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The unique identifier of the replica",
            "required": true,
            "schema": {"type": "string", "format": "uuid"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HooksResponse"}}}
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"},
          "502": {"$ref": "#/components/responses/BadGateway"}
        }
      }
    },
    "/v1/replica/{id}/events": {
      "get": {
        "operationId": "streamReplicaEvents",
        "summary": "Stream events",
        "description": "Streams replica events as server-sent events (`data: <JSON>`). Each event has `id`, `ts`, `type`, `payload`, and on current engines a `seq`; see `EngineEvent` for types. The stream opens with an `engine.stream.opened` event, and each SSE `id:` line is `<epoch>:<seq>`: reconnect with that value in `Last-Event-ID` to receive only the events you missed. A ping is sent every 15 seconds. The replica must be active, so send a message or wake it first.",
        "tags": ["Replica"],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The unique identifier of the replica",
            "required": true,
            "schema": {"type": "string", "format": "uuid"}
          },
          {
            "name": "Last-Event-ID",
            "in": "header",
            "description": "The SSE `id` of the last event received. When the engine still holds every event after it, they are replayed and `engine.stream.opened` reports `resumed: true`; otherwise it reports `resumed: false` and only live events follow.",
            "required": false,
            "schema": {"type": "string", "example": "0b6f4c1e-8d2a-4f3e-9c1b-2a7d5e6f8a90:1042"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "SSE event stream opened successfully. Each line is a JSON-encoded `EngineEvent`.",
            "content": {"text/event-stream": {"schema": {"$ref": "#/components/schemas/EngineEvent"}}}
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"},
          "502": {"$ref": "#/components/responses/BadGateway"},
          "503": {"$ref": "#/components/responses/ServiceUnavailable"}
        }
      }
    },
    "/v1/replica/{id}/wake": {
      "post": {
        "operationId": "wakeReplica",
        "summary": "Wake replica",
        "description": "Starts waking a sleeping replica and returns `202` immediately. Set `restore=true` to also restore an archived replica. Replicas in `error` are retried. Sending a message wakes or restores a replica too.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Replica ID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {
            "name": "restore",
            "in": "query",
            "description": "Restore the replica if it is archived",
            "schema": {"type": "boolean", "default": false}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "202": {
            "description": "Wake accepted",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/WakeWorkspaceResponse"}}}
          },
          "409": {"$ref": "#/components/responses/Conflict"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Replica"]
      }
    },
    "/v1/replica/{id}/sleep": {
      "post": {
        "operationId": "sleepReplica",
        "summary": "Sleep replica",
        "description": "Pauses compute. The replica keeps its files and wakes on the next message.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Replica ID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Sleep accepted",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SleepWorkspaceResponse"}}}
          },
          "409": {"$ref": "#/components/responses/Conflict"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Replica"]
      }
    },
    "/v1/replica/{id}/archive": {
      "post": {
        "operationId": "archiveReplica",
        "summary": "Archive replica",
        "description": "Archives a replica. Sending a message or waking with `restore=true` restores it.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Replica ID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Archived",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ArchiveWorkspaceResponse"}}}
          },
          "409": {"$ref": "#/components/responses/Conflict"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Replica"]
      }
    },
    "/v1/replica/{id}/media": {
      "get": {
        "operationId": "listReplicaMedia",
        "summary": "List replica media",
        "description": "Lists media the replica uploaded, newest first. Fetch a file with [Get a media download URL](/api-reference/media/get-a-media-download-url).",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Replica ID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"name": "kind", "in": "query", "schema": {"$ref": "#/components/schemas/MediaKind"}},
          {"name": "page", "in": "query", "schema": {"type": "integer", "minimum": 1, "default": 1}},
          {"name": "limit", "in": "query", "schema": {"type": "integer", "minimum": 1, "maximum": 200, "default": 50}},
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Media",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ListMediaResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Replica"]
      }
    },
    "/v1/replica/{id}/wait": {
      "get": {
        "operationId": "waitForReplica",
        "summary": "Wait for replica",
        "tags": ["Replica"],
        "description": "Waits until the replica finishes starting and its agents finish their work, including background tasks they will wake up for, then returns its chats and activity. Without `chat_id`, background tasks count as work. Returns `done: false` after `timeout_seconds` (max 50) if work is still running, or as soon as the agent waits for input; call it again to keep waiting. Use [Stream events](/api-reference/replica/stream-events) for live updates.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Replica ID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"name": "chat_id", "in": "query", "description": "Wait for only this chat", "schema": {"type": "string"}},
          {
            "name": "timeout_seconds",
            "in": "query",
            "schema": {"type": "integer", "minimum": 1, "maximum": 50, "default": 50}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "done": {"type": "boolean"},
                    "status": {"type": "string"},
                    "chats": {"type": "array", "items": {"$ref": "#/components/schemas/ReplicaChat"}},
                    "activity": {"$ref": "#/components/schemas/ReplicaActivity"},
                    "deleted": {"type": "boolean", "description": "The replica was deleted once its agents finished (`delete_when_done`)."}
                  },
                  "required": ["done", "status", "chats", "activity"]
                }
              }
            }
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "409": {"$ref": "#/components/responses/Conflict"}
        }
      }
    },
    "/v1/replica/{id}/chats": {
      "get": {
        "operationId": "listReplicaChats",
        "summary": "List chats",
        "tags": ["Chats"],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The unique identifier of the replica",
            "required": true,
            "schema": {"type": "string", "format": "uuid"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "chats": {"type": "array", "items": {"$ref": "#/components/schemas/ReplicaChat"}},
                    "waking": {
                      "type": "boolean",
                      "description": "If true, the workspace was sleeping and is now waking up. Retry after 30-90 seconds."
                    }
                  },
                  "required": ["chats"]
                }
              }
            }
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "description": "Sleeping and archived replicas return their retained chats without waking."
      },
      "post": {
        "operationId": "createReplicaChat",
        "summary": "Create chat",
        "tags": ["Chats"],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The unique identifier of the replica",
            "required": true,
            "schema": {"type": "string", "format": "uuid"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"$ref": "#/components/schemas/CreateChatRequest"}}}
        },
        "responses": {
          "201": {
            "description": "Chat created successfully",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ReplicaChat"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      }
    },
    "/v1/replica/{id}/chats/{chat_id}": {
      "delete": {
        "operationId": "deleteReplicaChat",
        "summary": "Delete chat",
        "tags": ["Chats"],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The unique identifier of the replica",
            "required": true,
            "schema": {"type": "string", "format": "uuid"}
          },
          {
            "name": "chat_id",
            "in": "path",
            "description": "The unique identifier of the chat",
            "required": true,
            "schema": {"type": "string"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Chat deleted successfully",
            "content": {
              "application/json": {"schema": {"type": "object", "properties": {"success": {"type": "boolean"}}, "required": ["success"]}}
            }
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      },
      "patch": {
        "operationId": "renameReplicaChat",
        "summary": "Rename chat",
        "description": "The replica must be active.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Replica ID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"name": "chat_id", "in": "path", "required": true, "description": "Chat ID", "schema": {"type": "string"}},
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {"display_name": {"type": "string", "minLength": 1, "maxLength": 100}},
                "required": ["display_name"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Renamed chat",
            "content": {"application/json": {"schema": {"type": "object", "properties": {"chat": {"type": "object"}}}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "409": {"$ref": "#/components/responses/Conflict"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Chats"]
      }
    },
    "/v1/replica/{id}/chats/{chat_id}/slash-commands": {
      "get": {
        "operationId": "listReplicaSlashCommands",
        "summary": "List slash commands",
        "description": "Lists Replicas and agent slash commands available in the chat.",
        "tags": ["Chats"],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The unique identifier of the replica",
            "required": true,
            "schema": {"type": "string", "format": "uuid"}
          },
          {
            "name": "chat_id",
            "in": "path",
            "description": "The unique identifier of the chat",
            "required": true,
            "schema": {"type": "string"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SlashCommandsResponse"}}}
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "409": {"$ref": "#/components/responses/Conflict"},
          "502": {"$ref": "#/components/responses/BadGateway"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      }
    },
    "/v1/replica/{id}/chats/{chat_id}/restore": {
      "post": {
        "operationId": "restoreReplicaChat",
        "summary": "Restore chat",
        "description": "Restores a deleted chat. The replica must be active.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Replica ID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"name": "chat_id", "in": "path", "required": true, "description": "Chat ID", "schema": {"type": "string"}},
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Restored chat",
            "content": {"application/json": {"schema": {"type": "object", "properties": {"chat": {"type": "object"}}}}}
          },
          "409": {"$ref": "#/components/responses/Conflict"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Chats"]
      }
    },
    "/v1/replica/{id}/chats/{chat_id}/interrupt": {
      "post": {
        "operationId": "interruptReplicaChat",
        "summary": "Interrupt chat",
        "description": "Stops the chat's current agent turn. Queued messages are discarded and returned in `removed_message_ids`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Replica ID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"name": "chat_id", "in": "path", "required": true, "description": "Chat ID", "schema": {"type": "string"}},
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Interrupted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "interrupted": {"type": "boolean"},
                    "queue": {"type": "array", "items": {"type": "string"}, "description": "Text of the queued messages that were discarded"},
                    "removed_message_ids": {"type": "array", "items": {"type": "string"}, "description": "IDs of the discarded messages"}
                  },
                  "required": ["interrupted", "queue"]
                }
              }
            }
          },
          "409": {"$ref": "#/components/responses/Conflict"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Chats"]
      }
    },
    "/v1/replica/{id}/chats/{chat_id}/goal": {
      "patch": {
        "operationId": "updateReplicaChatGoal",
        "summary": "Update chat goal",
        "description": "Sets the objective of a Codex chat, or pauses and resumes it. Other agents return `goal: null`; give them a goal by sending a message with `goal_mode: true`. The replica must be active.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Replica ID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"name": "chat_id", "in": "path", "required": true, "description": "Chat ID", "schema": {"type": "string"}},
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {"objective": {"type": "string"}, "status": {"type": "string", "enum": ["active", "paused"]}}
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated goal",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {"goal": {"oneOf": [{"$ref": "#/components/schemas/ChatGoal"}, {"type": "null"}]}}
                }
              }
            }
          },
          "409": {"$ref": "#/components/responses/Conflict"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Chats"]
      }
    },
    "/v1/replica/{id}/chats/{chat_id}/goal/clear": {
      "post": {
        "operationId": "clearReplicaChatGoal",
        "summary": "Clear chat goal",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Replica ID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"name": "chat_id", "in": "path", "required": true, "description": "Chat ID", "schema": {"type": "string"}},
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {"description": "Cleared", "content": {"application/json": {"schema": {"type": "object"}}}},
          "409": {"$ref": "#/components/responses/Conflict"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Chats"]
      }
    },
    "/v1/replica/{id}/chats/{chat_id}/tool-input": {
      "post": {
        "operationId": "answerReplicaChatToolInput",
        "summary": "Answer agent question",
        "description": "Answers a question or approval the agent is waiting on. Find pending requests in [Read history](/api-reference/replica/read-history): a tool call with `inputRequest.status` of `pending` carries the `request_id` and its option IDs.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Replica ID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"name": "chat_id", "in": "path", "required": true, "description": "Chat ID", "schema": {"type": "string"}},
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "request_id": {"type": "string"},
                  "selection_id": {"type": "string", "description": "ID of the chosen option"}
                },
                "required": ["request_id", "selection_id"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Whether the request was still pending",
            "content": {
              "application/json": {"schema": {"type": "object", "properties": {"resolved": {"type": "boolean"}}, "required": ["resolved"]}}
            }
          },
          "409": {"$ref": "#/components/responses/Conflict"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Chats"]
      }
    },
    "/v1/replica/{id}/chats/{chat_id}/fork": {
      "post": {
        "operationId": "forkReplicaChat",
        "summary": "Fork chat",
        "description": "Starts a new chat that continues from this chat's history, optionally on another coding agent and with a first message. The replica must be active.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Replica ID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"name": "chat_id", "in": "path", "required": true, "description": "Chat ID", "schema": {"type": "string"}},
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ForkChatRequest"}}}
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ForkWorkspaceChatResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "409": {"$ref": "#/components/responses/Conflict"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Chats"]
      }
    },
    "/v1/replica/{id}/chats/{chat_id}/queue": {
      "get": {
        "operationId": "getReplicaChatQueue",
        "summary": "Get queue",
        "description": "Lists messages waiting for the agent to finish its turn.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Replica ID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"name": "chat_id", "in": "path", "required": true, "description": "Chat ID", "schema": {"type": "string"}},
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ChatQueueResponse"}}}
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Message queue"]
      },
      "delete": {
        "operationId": "clearReplicaChatQueue",
        "summary": "Clear queue",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Replica ID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"name": "chat_id", "in": "path", "required": true, "description": "Chat ID", "schema": {"type": "string"}},
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/QueueMutationResponse"}}}
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Message queue"]
      }
    },
    "/v1/replica/{id}/chats/{chat_id}/queue/reorder": {
      "patch": {
        "operationId": "reorderReplicaChatQueue",
        "summary": "Reorder queued message",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Replica ID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"name": "chat_id", "in": "path", "required": true, "description": "Chat ID", "schema": {"type": "string"}},
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ReorderQueueRequest"}}}
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/QueueMutationResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Message queue"]
      }
    },
    "/v1/replica/{id}/chats/{chat_id}/queue/{message_id}": {
      "patch": {
        "operationId": "updateReplicaQueuedMessage",
        "summary": "Edit queued message",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Replica ID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"name": "chat_id", "in": "path", "required": true, "description": "Chat ID", "schema": {"type": "string"}},
          {
            "name": "message_id",
            "in": "path",
            "required": true,
            "description": "Queued message ID",
            "schema": {"type": "string"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UpdateQueuedMessageRequest"}}}
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/QueueMutationResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Message queue"]
      },
      "delete": {
        "operationId": "removeReplicaQueuedMessage",
        "summary": "Remove queued message",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Replica ID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"name": "chat_id", "in": "path", "required": true, "description": "Chat ID", "schema": {"type": "string"}},
          {
            "name": "message_id",
            "in": "path",
            "required": true,
            "description": "Queued message ID",
            "schema": {"type": "string"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/QueueMutationResponse"}}}
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Message queue"]
      }
    },
    "/v1/replica/{id}/chats/{chat_id}/queue/{message_id}/steer": {
      "post": {
        "operationId": "steerReplicaQueuedMessage",
        "summary": "Steer with queued message",
        "description": "Adds the queued message to the agent's current turn without stopping it.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Replica ID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"name": "chat_id", "in": "path", "required": true, "description": "Chat ID", "schema": {"type": "string"}},
          {
            "name": "message_id",
            "in": "path",
            "required": true,
            "description": "Queued message ID",
            "schema": {"type": "string"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/QueueMutationResponse"}}}
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Message queue"]
      }
    },
    "/v1/replica/{id}/chats/{chat_id}/queue/{message_id}/send-now": {
      "post": {
        "operationId": "sendReplicaQueuedMessageNow",
        "summary": "Send queued message now",
        "description": "Sends the queued message right away instead of waiting for the turn to finish. Running commands keep going in the background.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Replica ID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"name": "chat_id", "in": "path", "required": true, "description": "Chat ID", "schema": {"type": "string"}},
          {
            "name": "message_id",
            "in": "path",
            "required": true,
            "description": "Queued message ID",
            "schema": {"type": "string"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/QueueMutationResponse"}}}
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Message queue"]
      }
    },
    "/v1/replica/{id}/exec": {
      "post": {
        "operationId": "execReplicaCommand",
        "summary": "Run command",
        "description": "Runs a shell command and returns its output and exit code. Commands that outlast `timeout_seconds` are stopped and return `timed_out: true`. Use a terminal session for interactive or long-running work. The replica must be active.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Replica ID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ExecRequest"}}}},
        "responses": {
          "200": {
            "description": "Success",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ExecResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "409": {"$ref": "#/components/responses/Conflict"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Commands and terminals"]
      }
    },
    "/v1/replica/{id}/terminal/sessions": {
      "get": {
        "operationId": "listReplicaTerminals",
        "summary": "List terminal sessions",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Replica ID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ListTerminalSessionsResponse"}}}
          },
          "409": {"$ref": "#/components/responses/Conflict"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Commands and terminals"]
      },
      "post": {
        "operationId": "createReplicaTerminal",
        "summary": "Create terminal session",
        "description": "Opens an interactive shell. Read output from Stream terminal output and write with Send terminal input. A replica can have 8 sessions. The replica must be active.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Replica ID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"$ref": "#/components/schemas/CreateTerminalSessionRequest"}}}
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/CreateTerminalSessionResponse"}}}
          },
          "409": {"$ref": "#/components/responses/Conflict"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Commands and terminals"]
      }
    },
    "/v1/replica/{id}/terminal/sessions/{session_id}/input": {
      "post": {
        "operationId": "writeReplicaTerminal",
        "summary": "Send terminal input",
        "description": "Writes keystrokes. Number writes with an increasing `sequence` and keep `generation` fixed for the session.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Replica ID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {
            "name": "session_id",
            "in": "path",
            "required": true,
            "description": "Terminal session ID",
            "schema": {"type": "string"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"$ref": "#/components/schemas/WriteTerminalSessionRequest"}}}
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/TerminalMutationResponse"}}}
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Commands and terminals"]
      }
    },
    "/v1/replica/{id}/terminal/sessions/{session_id}/resize": {
      "post": {
        "operationId": "resizeReplicaTerminal",
        "summary": "Resize terminal",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Replica ID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {
            "name": "session_id",
            "in": "path",
            "required": true,
            "description": "Terminal session ID",
            "schema": {"type": "string"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ResizeTerminalSessionRequest"}}}
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/TerminalMutationResponse"}}}
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Commands and terminals"]
      }
    },
    "/v1/replica/{id}/terminal/sessions/{session_id}/stream": {
      "get": {
        "operationId": "streamReplicaTerminal",
        "summary": "Stream terminal output",
        "description": "Server-sent events whose `data` is a JSON string of terminal output. The first event replays recent output.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Replica ID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {
            "name": "session_id",
            "in": "path",
            "required": true,
            "description": "Terminal session ID",
            "schema": {"type": "string"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {"description": "Event stream", "content": {"text/event-stream": {"schema": {"type": "string"}}}},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Commands and terminals"]
      }
    },
    "/v1/replica/{id}/terminal/sessions/{session_id}": {
      "delete": {
        "operationId": "deleteReplicaTerminal",
        "summary": "Close terminal session",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Replica ID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {
            "name": "session_id",
            "in": "path",
            "required": true,
            "description": "Terminal session ID",
            "schema": {"type": "string"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/TerminalMutationResponse"}}}
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Commands and terminals"]
      }
    },
    "/v1/replica/{id}/ssh-token": {
      "post": {
        "operationId": "getReplicaSshToken",
        "summary": "Get SSH access",
        "description": "Returns a short-lived token and proxy command for SSH. The [CLI](/features/cli) runs this for you. The replica must be active.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Replica ID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SshTokenResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "403": {"$ref": "#/components/responses/Forbidden"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Commands and terminals"]
      }
    },
    "/v1/replica/{id}/pull-requests/details": {
      "post": {
        "operationId": "getReplicaPullRequests",
        "summary": "Get pull requests",
        "description": "Returns state, checks, reviews, and mergeability for up to 20 pull requests the replica opened. Get URLs from Get replica.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Replica ID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"$ref": "#/components/schemas/WorkspacePullRequestDetailsRequest"}}}
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/WorkspacePullRequestDetailsResponse"}}}
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Pull requests"]
      }
    },
    "/v1/replica/{id}/pull-requests/merge": {
      "post": {
        "operationId": "mergeReplicaPullRequest",
        "summary": "Merge pull request",
        "description": "Merges a GitHub pull request when it is open and mergeable, or adds it to the merge queue when its base branch requires one. With `bypass_rules`, merges a blocked pull request with your GitHub account when it can bypass the branch's rules. Returns `403` when the organization's security policy blocks agent merges.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Replica ID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MergeWorkspacePullRequestRequest"}}}
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MergeWorkspacePullRequestResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "403": {"$ref": "#/components/responses/Forbidden"},
          "409": {"$ref": "#/components/responses/Conflict"},
          "412": {"description": "Bypassing rules was requested without a personal API key"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Pull requests"]
      }
    },
    "/v1/replica/{id}/pull-requests/update": {
      "post": {
        "operationId": "updateReplicaPullRequest",
        "summary": "Update pull request",
        "description": "Closes, approves, converts to draft, or marks ready a GitHub pull request the replica opened. Approving uses your GitHub account, so it needs a personal API key with GitHub connected.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Replica ID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UpdateWorkspacePullRequestRequest"}}}
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SuccessResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "403": {"$ref": "#/components/responses/Forbidden"},
          "409": {"$ref": "#/components/responses/Conflict"},
          "412": {"description": "GitHub account not connected"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Pull requests"]
      }
    },
    "/v1/replica/{id}/previews": {
      "get": {
        "operationId": "listReplicaPreviews",
        "summary": "List previews",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Replica ID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {"previews": {"type": "array", "items": {"$ref": "#/components/schemas/Preview"}}}
                }
              }
            }
          },
          "409": {"$ref": "#/components/responses/Conflict"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Previews"]
      },
      "post": {
        "operationId": "createReplicaPreview",
        "summary": "Create preview",
        "description": "Creates a public URL for a port. Set `authenticated` to require Replicas sign-in. Port 3737 is reserved for the Replicas engine. The replica must be active.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Replica ID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "port": {"type": "integer", "minimum": 1, "maximum": 65535},
                  "authenticated": {"type": "boolean", "default": false}
                },
                "required": ["port"]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {"schema": {"type": "object", "properties": {"preview": {"$ref": "#/components/schemas/Preview"}}}}
            }
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "409": {"$ref": "#/components/responses/Conflict"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Previews"]
      }
    },
    "/v1/replica/{id}/previews/{port}": {
      "delete": {
        "operationId": "deleteReplicaPreview",
        "summary": "Delete preview",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Replica ID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"name": "port", "in": "path", "required": true, "description": "Port", "schema": {"type": "integer"}},
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/DeletePreviewResponse"}}}
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Previews"]
      }
    },
    "/v1/replica/{id}/canvas": {
      "get": {
        "operationId": "listReplicaCanvas",
        "summary": "List Canvas files",
        "description": "Lists plans, reports, and other files the agent put in the [Canvas](/features/workspaces/canvas).",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Replica ID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/CanvasListResponse"}}}
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Canvas"]
      }
    },
    "/v1/replica/{id}/canvas/{filename}": {
      "get": {
        "operationId": "getReplicaCanvasFile",
        "summary": "Read Canvas file",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Replica ID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {
            "name": "filename",
            "in": "path",
            "required": true,
            "description": "Path within the Canvas, URL-encoded",
            "schema": {"type": "string"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/CanvasContentResponse"}}}
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Canvas"]
      },
      "put": {
        "operationId": "updateReplicaCanvasFile",
        "summary": "Write Canvas file",
        "description": "Replaces a text file. Pass `expected_revision` from Read Canvas file to avoid overwriting newer changes. The replica must be active.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Replica ID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {
            "name": "filename",
            "in": "path",
            "required": true,
            "description": "Path within the Canvas, URL-encoded",
            "schema": {"type": "string"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UpdateTextFileRequest"}}}
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UpdateTextFileResponse"}}}
          },
          "409": {"$ref": "#/components/responses/Conflict"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Canvas"]
      }
    },
    "/v1/replica/{id}/shares": {
      "get": {
        "operationId": "listReplicaShares",
        "summary": "List shares",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Replica ID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {"shares": {"type": "array", "items": {"$ref": "#/components/schemas/WorkspaceShare"}}}
                }
              }
            }
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Sharing"]
      }
    },
    "/v1/replica/{id}/share": {
      "post": {
        "operationId": "shareReplica",
        "summary": "Share replica",
        "description": "Adds the replica to a member's **Shared** view. Only the owner can share a member's replica; anyone with access can share an organization-owned one.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Replica ID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {"user_id": {"type": "string", "format": "uuid"}},
                "required": ["user_id"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {"schema": {"type": "object", "properties": {"share": {"$ref": "#/components/schemas/WorkspaceShare"}}}}
            }
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "403": {"$ref": "#/components/responses/Forbidden"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Sharing"]
      }
    },
    "/v1/replica/{id}/share/{user_id}": {
      "delete": {
        "operationId": "unshareReplica",
        "summary": "Unshare replica",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Replica ID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {
            "name": "user_id",
            "in": "path",
            "required": true,
            "description": "Member user ID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SuccessResponse"}}}
          },
          "403": {"$ref": "#/components/responses/Forbidden"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Sharing"]
      }
    },
    "/v1/environments": {
      "get": {
        "operationId": "listEnvironments",
        "summary": "List environments",
        "description": "Lists environments you can use.",
        "tags": ["Environments"],
        "parameters": [
          {
            "name": "scope",
            "in": "query",
            "required": false,
            "description": "Filter by environment scope. `org` returns team environments, `user` returns your personal environments, `all` returns both. Defaults to `org`.",
            "schema": {"type": "string", "enum": ["org", "user", "all"], "default": "org"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ListEnvironmentsResponse"}}}
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      },
      "post": {
        "operationId": "createEnvironment",
        "summary": "Create environment",
        "description": "Creates an organization (`scope: \"org\"`) or personal (`scope: \"user\"`) environment. Set `source_environment_id` to create a live fork, as in Fork environment. Pass `repository_ids` to choose the repositories to clone.",
        "tags": ["Environments"],
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"$ref": "#/components/schemas/CreateEnvironmentRequest"}}}
        },
        "responses": {
          "201": {
            "description": "Environment created",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/EnvironmentResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "409": {
            "description": "An environment with this name already exists",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}
          },
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "parameters": [{"$ref": "#/components/parameters/ApiVersion"}]
      }
    },
    "/v1/environments/{id}": {
      "get": {
        "operationId": "getEnvironment",
        "summary": "Get environment",
        "tags": ["Environments"],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Environment UUID.",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/EnvironmentResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      },
      "patch": {
        "operationId": "updateEnvironment",
        "summary": "Update environment",
        "description": "Updates only the fields you send. Set `repository_ids` to `[]` to remove all repositories. `personal_preferences` can only be set on personal environments and is appended after the inherited system prompt.",
        "tags": ["Environments"],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Environment UUID.",
            "schema": {"type": "string"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UpdateEnvironmentRequest"}}}
        },
        "responses": {
          "200": {
            "description": "Environment updated",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/EnvironmentResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "403": {"$ref": "#/components/responses/Forbidden"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "409": {"$ref": "#/components/responses/Conflict"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      },
      "delete": {
        "operationId": "deleteEnvironment",
        "summary": "Delete environment",
        "description": "Also uninstalls its plugins. Forks of it, including other people's personal forks, are detached first. Returns `409` while automations use it.",
        "tags": ["Environments"],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Environment UUID.",
            "schema": {"type": "string"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Environment deleted",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SuccessResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "409": {"$ref": "#/components/responses/Conflict"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      }
    },
    "/v1/environments/{id}/fork": {
      "post": {
        "operationId": "forkEnvironment",
        "summary": "Fork environment",
        "description": "Creates a live fork that inherits everything from this environment and stores only its own overrides and exclusions. Team environments fork into shared (`scope: \"org\"`, needs Read on the parent and counts toward your environment limit) or personal (`scope: \"user\"`, needs Read) forks; your own personal environments fork only into personal ones. Other people's personal environments can't be forked. Forks nest at most 3 levels. A shared fork starts with its parent's access grants, and members also need Read on every ancestor to see it.",
        "tags": [
          "Environments"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Environment UUID.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/ApiVersion"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ForkEnvironmentRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Fork created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnvironmentResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/v1/environments/{id}/detach": {
      "post": {
        "operationId": "detachEnvironment",
        "summary": "Detach fork",
        "description": "Copies everything the fork inherits from its parents into the fork itself, then removes the link. Connected plugin accounts and MCP OAuth sign-ins can't be shared and are listed in `not_copied`.",
        "tags": [
          "Environments"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Environment UUID.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/ApiVersion"
          }
        ],
        "responses": {
          "200": {
            "description": "Detached",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DetachEnvironmentResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/v1/environments/{environment_id}/variables": {
      "get": {
        "operationId": "listEnvironmentVariables",
        "summary": "List environment variables",
        "description": "Returns variables with plaintext values.",
        "tags": ["Environment variables"],
        "parameters": [
          {
            "name": "environment_id",
            "in": "path",
            "required": true,
            "description": "Environment UUID.",
            "schema": {"type": "string"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ListEnvironmentVariablesResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      },
      "post": {
        "operationId": "createEnvironmentVariable",
        "summary": "Create environment variable",
        "description": "Keys must start with a letter or underscore and contain only letters, digits, and underscores, and are unique per environment. Values are encrypted at rest. A fork can override any inherited key that is not `locked`.",
        "tags": ["Environment variables"],
        "parameters": [
          {
            "name": "environment_id",
            "in": "path",
            "required": true,
            "description": "Environment UUID.",
            "schema": {"type": "string"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"$ref": "#/components/schemas/CreateEnvironmentVariableRequest"}}}
        },
        "responses": {
          "201": {
            "description": "Variable created",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/EnvironmentVariableResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "403": {
            "description": "Admin access required to change personal override policy",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}
          },
          "409": {"$ref": "#/components/responses/Conflict"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      }
    },
    "/v1/environments/{environment_id}/variables/bulk": {
      "post": {
        "operationId": "createEnvironmentVariables",
        "summary": "Create environment variables",
        "description": "Creates up to 200 variables at once, all or none. Counts as one change for the warm pool, so it rebuilds at most once.",
        "tags": ["Environment variables"],
        "parameters": [
          {
            "name": "environment_id",
            "in": "path",
            "required": true,
            "description": "Environment UUID.",
            "schema": {"type": "string"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"$ref": "#/components/schemas/CreateEnvironmentVariablesRequest"}}}
        },
        "responses": {
          "201": {
            "description": "Variables created",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ListEnvironmentVariablesResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "409": {"$ref": "#/components/responses/Conflict"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      }
    },
    "/v1/environments/{environment_id}/variables/{id}": {
      "patch": {
        "operationId": "updateEnvironmentVariable",
        "summary": "Update environment variable",
        "description": "Updates only the fields you send.",
        "tags": ["Environment variables"],
        "parameters": [
          {
            "name": "environment_id",
            "in": "path",
            "required": true,
            "description": "Environment UUID.",
            "schema": {"type": "string"}
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Variable UUID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UpdateEnvironmentVariableRequest"}}}
        },
        "responses": {
          "200": {
            "description": "Variable updated",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/EnvironmentVariableResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "403": {
            "description": "Admin access required to change personal override policy",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}
          },
          "404": {"$ref": "#/components/responses/NotFound"},
          "409": {"$ref": "#/components/responses/Conflict"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      },
      "delete": {
        "operationId": "deleteEnvironmentVariable",
        "summary": "Delete environment variable",
        "tags": ["Environment variables"],
        "parameters": [
          {
            "name": "environment_id",
            "in": "path",
            "required": true,
            "description": "Environment UUID.",
            "schema": {"type": "string"}
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Variable UUID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Variable deleted",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SuccessResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      }
    },
    "/v1/environments/{environment_id}/files": {
      "get": {
        "operationId": "listEnvironmentFiles",
        "summary": "List environment files",
        "description": "Files are written to their `path` when a workspace starts.",
        "tags": ["Environment files"],
        "parameters": [
          {
            "name": "environment_id",
            "in": "path",
            "required": true,
            "description": "Environment UUID.",
            "schema": {"type": "string"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ListEnvironmentFilesResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      },
      "post": {
        "operationId": "createEnvironmentFile",
        "summary": "Create environment file",
        "description": "Content is limited to 64 KB. `path` must be under the home directory.",
        "tags": ["Environment files"],
        "parameters": [
          {
            "name": "environment_id",
            "in": "path",
            "required": true,
            "description": "Environment UUID.",
            "schema": {"type": "string"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"$ref": "#/components/schemas/CreateEnvironmentFileRequest"}}}
        },
        "responses": {
          "201": {
            "description": "File created",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/EnvironmentFileResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      }
    },
    "/v1/environments/{environment_id}/files/{id}": {
      "patch": {
        "operationId": "updateEnvironmentFile",
        "summary": "Update environment file",
        "tags": ["Environment files"],
        "parameters": [
          {
            "name": "environment_id",
            "in": "path",
            "required": true,
            "description": "Environment UUID.",
            "schema": {"type": "string"}
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "File UUID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UpdateEnvironmentFileRequest"}}}
        },
        "responses": {
          "200": {
            "description": "File updated",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/EnvironmentFileResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      },
      "delete": {
        "operationId": "deleteEnvironmentFile",
        "summary": "Delete environment file",
        "tags": ["Environment files"],
        "parameters": [
          {
            "name": "environment_id",
            "in": "path",
            "required": true,
            "description": "Environment UUID.",
            "schema": {"type": "string"}
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "File UUID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "File deleted",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SuccessResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      }
    },
    "/v1/environments/{environment_id}/skills": {
      "get": {
        "operationId": "listEnvironmentSkills",
        "summary": "List environment skills",
        "description": "Lists [skills.sh](https://skills.sh) skills installed into workspaces.",
        "tags": ["Environment skills"],
        "parameters": [
          {
            "name": "environment_id",
            "in": "path",
            "required": true,
            "description": "Environment UUID.",
            "schema": {"type": "string"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ListEnvironmentSkillsResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      },
      "post": {
        "operationId": "createEnvironmentSkill",
        "summary": "Enable environment skill",
        "description": "Enables a skill found with [Search skill catalog](/api-reference/environment-skills/search-skill-catalog). Returns `409` if it is already enabled.",
        "tags": ["Environment skills"],
        "parameters": [
          {
            "name": "environment_id",
            "in": "path",
            "required": true,
            "description": "Environment UUID.",
            "schema": {"type": "string"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"$ref": "#/components/schemas/CreateEnvironmentSkillRequest"}}}
        },
        "responses": {
          "201": {
            "description": "Skill enabled",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/EnvironmentSkillResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      }
    },
    "/v1/environments/{environment_id}/skills/{id}": {
      "delete": {
        "operationId": "deleteEnvironmentSkill",
        "summary": "Disable environment skill",
        "tags": ["Environment skills"],
        "parameters": [
          {
            "name": "environment_id",
            "in": "path",
            "required": true,
            "description": "Environment UUID.",
            "schema": {"type": "string"}
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Environment skill UUID (the membership row, not the skill catalog slug).",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Skill disabled",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SuccessResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      }
    },
    "/v1/environments/{environment_id}/skills-registries": {
      "get": {
        "operationId": "listEnvironmentSkillsRegistries",
        "summary": "List skill registries",
        "description": "Lists GitHub repositories used as skill registries, with the skills found in each.",
        "tags": ["Environment skills"],
        "parameters": [
          {
            "name": "environment_id",
            "in": "path",
            "required": true,
            "description": "Environment UUID.",
            "schema": {"type": "string"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ListEnvironmentSkillsRegistriesResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      },
      "post": {
        "operationId": "createEnvironmentSkillsRegistry",
        "summary": "Add skill registry",
        "description": "Adds a GitHub repository as a skill registry. Its skills install into new workspaces.",
        "tags": ["Environment skills"],
        "parameters": [
          {
            "name": "environment_id",
            "in": "path",
            "required": true,
            "description": "Environment UUID.",
            "schema": {"type": "string"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {"type": "string", "description": "GitHub repository URL (e.g. https://github.com/org/skills-repo)."}
                },
                "required": ["url"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Registry created",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/CreateEnvironmentSkillsRegistryResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "409": {"$ref": "#/components/responses/Conflict"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      }
    },
    "/v1/environments/{environment_id}/skills-registries/{skills_registry_id}": {
      "delete": {
        "operationId": "deleteEnvironmentSkillsRegistry",
        "summary": "Remove skill registry",
        "tags": ["Environment skills"],
        "parameters": [
          {
            "name": "environment_id",
            "in": "path",
            "required": true,
            "description": "Environment UUID.",
            "schema": {"type": "string"}
          },
          {
            "name": "skills_registry_id",
            "in": "path",
            "required": true,
            "description": "Skills registry UUID.",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Registry removed",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SuccessResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      }
    },
    "/v1/environments/{environment_id}/repo-skills": {
      "get": {
        "operationId": "listRepoSkills",
        "summary": "List repository skills",
        "description": "Lists skills, agents, commands, and rules committed to the environment's repositories, read from the default branch. Returns an empty list when no repository is bound.",
        "tags": ["Environment skills"],
        "parameters": [
          {
            "name": "environment_id",
            "in": "path",
            "required": true,
            "description": "Environment UUID.",
            "schema": {"type": "string"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Successful response. `error` is populated when discovery encountered a partial failure (e.g. the repo has no GitHub App installation); the UI surfaces it inline rather than treating it as a 5xx.",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ListRepoSkillsResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      }
    },
    "/v1/environment-skills/search": {
      "get": {
        "operationId": "searchEnvironmentSkills",
        "summary": "Search skill catalog",
        "description": "Searches [skills.sh](https://skills.sh).",
        "tags": ["Environment skills"],
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Free-text query (matched against skill name and description). Empty query returns popular skills.",
            "schema": {"type": "string"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SearchEnvironmentSkillsResponse"}}}
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      }
    },
    "/v1/environments/{environment_id}/mcps": {
      "get": {
        "operationId": "listEnvironmentMcps",
        "summary": "List environment MCPs",
        "tags": ["Environment MCPs"],
        "parameters": [
          {
            "name": "environment_id",
            "in": "path",
            "required": true,
            "description": "Environment UUID.",
            "schema": {"type": "string"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ListEnvironmentMcpsResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      },
      "post": {
        "operationId": "createEnvironmentMcp",
        "summary": "Create environment MCP",
        "description": "`name` must match `^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$` and cannot start with `relay-`, `replicas-`, or `subagents`. `stdio` takes `{ command, args, env }`; `http` and `sse` take `{ url, headers }`, or `auth` for [workspace identity](/features/workspaces/workspace-identity).",
        "tags": ["Environment MCPs"],
        "parameters": [
          {
            "name": "environment_id",
            "in": "path",
            "required": true,
            "description": "Environment UUID.",
            "schema": {"type": "string"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"$ref": "#/components/schemas/CreateEnvironmentMcpRequest"}}}
        },
        "responses": {
          "201": {
            "description": "MCP created",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/EnvironmentMcpResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "409": {"$ref": "#/components/responses/Conflict"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      }
    },
    "/v1/environments/{environment_id}/mcps/{id}": {
      "patch": {
        "operationId": "updateEnvironmentMcp",
        "summary": "Update environment MCP",
        "description": "Updates only the fields you send. Changing `transport` requires a matching `config`.",
        "tags": ["Environment MCPs"],
        "parameters": [
          {
            "name": "environment_id",
            "in": "path",
            "required": true,
            "description": "Environment UUID.",
            "schema": {"type": "string"}
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "MCP UUID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UpdateEnvironmentMcpRequest"}}}
        },
        "responses": {
          "200": {
            "description": "MCP updated",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/EnvironmentMcpResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "409": {"$ref": "#/components/responses/Conflict"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      },
      "delete": {
        "operationId": "deleteEnvironmentMcp",
        "summary": "Delete environment MCP",
        "tags": ["Environment MCPs"],
        "parameters": [
          {
            "name": "environment_id",
            "in": "path",
            "required": true,
            "description": "Environment UUID.",
            "schema": {"type": "string"}
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "MCP UUID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "MCP deleted",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SuccessResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      }
    },
    "/v1/environments/{environment_id}/warm-hooks": {
      "get": {
        "operationId": "getEnvironmentWarmHooks",
        "summary": "Get warm hook",
        "description": "Returns the environment's warm hook, warm pool status, and up to 20 recent snapshots.",
        "tags": ["Hooks"],
        "parameters": [
          {
            "name": "environment_id",
            "in": "path",
            "required": true,
            "description": "Environment UUID.",
            "schema": {"type": "string"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/GetWarmHooksResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      }
    },
    "/v1/environments/{environment_id}/warm-hooks/save": {
      "post": {
        "operationId": "saveEnvironmentWarmHook",
        "summary": "Save warm hook",
        "description": "Saves and activates the warm hook without testing it. Empty content removes it.",
        "tags": ["Hooks"],
        "parameters": [
          {
            "name": "environment_id",
            "in": "path",
            "required": true,
            "description": "Environment UUID.",
            "schema": {"type": "string"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SaveWarmHookRequest"}}}
        },
        "responses": {
          "201": {
            "description": "Warm hook saved and activated, or cleared when content is empty",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SaveWarmHookResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      }
    },
    "/v1/environments/{environment_id}/warm-hooks/save-test": {
      "post": {
        "operationId": "saveAndTestEnvironmentWarmHook",
        "summary": "Save and test warm hook",
        "description": "Runs the script in a new sandbox and activates it only if it passes. Takes 30–90 seconds.",
        "tags": ["Hooks"],
        "parameters": [
          {
            "name": "environment_id",
            "in": "path",
            "required": true,
            "description": "Environment UUID.",
            "schema": {"type": "string"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SaveAndTestWarmHookRequest"}}}
        },
        "responses": {
          "201": {
            "description": "Warm hook saved (test result included in body)",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SaveAndTestWarmHookResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      }
    },
    "/v1/environments/{environment_id}/warm-hooks/test": {
      "post": {
        "operationId": "testEnvironmentWarmHook",
        "summary": "Test warm hook",
        "description": "Runs the script in a new sandbox without saving it. Takes 30–90 seconds.",
        "tags": ["Hooks"],
        "parameters": [
          {
            "name": "environment_id",
            "in": "path",
            "required": true,
            "description": "Environment UUID.",
            "schema": {"type": "string"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"$ref": "#/components/schemas/TestWarmHookRequest"}}}
        },
        "responses": {
          "200": {
            "description": "Test executed",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/TestWarmHookResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      }
    },
    "/v1/environments/{environment_id}/start-hooks": {
      "get": {
        "operationId": "getEnvironmentStartHooks",
        "summary": "Get start hook",
        "description": "Returns the environment's start hook. Start hooks run when a workspace starts, before repository hooks.",
        "tags": ["Hooks"],
        "parameters": [
          {
            "name": "environment_id",
            "in": "path",
            "required": true,
            "description": "Environment UUID.",
            "schema": {"type": "string"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/GetStartHooksResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      }
    },
    "/v1/environments/{environment_id}/start-hooks/save": {
      "post": {
        "operationId": "saveEnvironmentStartHook",
        "summary": "Save start hook",
        "description": "Saves and activates the start hook. Empty content removes it. Does not rebuild the warm pool.",
        "tags": ["Hooks"],
        "parameters": [
          {
            "name": "environment_id",
            "in": "path",
            "required": true,
            "description": "Environment UUID.",
            "schema": {"type": "string"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SaveStartHookRequest"}}}
        },
        "responses": {
          "201": {
            "description": "Start hook saved and activated, or cleared when content is empty",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SaveStartHookResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      }
    },
    "/v1/environments/{environment_id}/start-hooks/test": {
      "post": {
        "operationId": "testEnvironmentStartHook",
        "summary": "Test start hook",
        "description": "Runs the script in a new sandbox without saving it. Takes 30–90 seconds.",
        "tags": ["Hooks"],
        "parameters": [
          {
            "name": "environment_id",
            "in": "path",
            "required": true,
            "description": "Environment UUID.",
            "schema": {"type": "string"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"$ref": "#/components/schemas/TestStartHookRequest"}}}
        },
        "responses": {
          "200": {
            "description": "Test executed",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/TestStartHookResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      }
    },
    "/v1/environments/{environment_id}/start-hooks/test/stream": {
      "post": {
        "operationId": "streamTestEnvironmentStartHook",
        "summary": "Test start hook (streaming)",
        "description": "Same as [Test start hook](/api-reference/hooks/test-start-hook), streamed as server-sent events: `progress`, `output`, `complete`, and `error`.",
        "tags": ["Hooks"],
        "parameters": [
          {
            "name": "environment_id",
            "in": "path",
            "required": true,
            "description": "Environment UUID.",
            "schema": {"type": "string"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"$ref": "#/components/schemas/TestStartHookRequest"}}}
        },
        "responses": {
          "200": {
            "description": "SSE stream of start hook test events",
            "content": {
              "text/event-stream": {
                "schema": {
                  "type": "string",
                  "description": "SSE events. Each event has `type` in {`progress`, `output`, `complete`, `error`} plus an optional `message`, `output`, `exit_code`, or `timed_out` payload."
                }
              }
            }
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      }
    },
    "/v1/environments/{environment_id}/warm-pools": {
      "put": {
        "operationId": "upsertEnvironmentWarmPool",
        "summary": "Enable or disable warm pool",
        "tags": ["Warm pools"],
        "parameters": [
          {
            "name": "environment_id",
            "in": "path",
            "required": true,
            "description": "Environment UUID.",
            "schema": {"type": "string"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UpsertWarmPoolConfigRequest"}}}
        },
        "responses": {
          "200": {
            "description": "Warm pool config updated",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UpsertWarmPoolConfigResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      }
    },
    "/v1/environments/{environment_id}/warm-pools/refresh": {
      "post": {
        "operationId": "refreshEnvironmentWarmPool",
        "summary": "Refresh warm pool",
        "description": "Rebuilds the warm pool from the latest code and hooks. Limited to once every two minutes.",
        "tags": ["Warm pools"],
        "parameters": [
          {
            "name": "environment_id",
            "in": "path",
            "required": true,
            "description": "Environment UUID.",
            "schema": {"type": "string"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Warm pool refresh started",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UpsertWarmPoolConfigResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "409": {"$ref": "#/components/responses/Conflict"},
          "429": {
            "description": "A refresh already started for this environment within the last two minutes",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}
          },
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      }
    },
    "/v1/environments/{environment_id}/warm-pools/build-now": {
      "post": {
        "operationId": "buildEnvironmentWarmPoolNow",
        "summary": "Start queued warm pool build",
        "description": "Edits queue a warm pool build that starts after 45 seconds without further edits, at most 3 minutes after the first. This starts the queued build right away, or retries the current build if it failed.",
        "tags": ["Warm pools"],
        "parameters": [
          {
            "name": "environment_id",
            "in": "path",
            "required": true,
            "description": "Environment UUID.",
            "schema": {"type": "string"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Build started",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/BuildWarmPoolNowResponse"}}}
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "409": {"$ref": "#/components/responses/Conflict"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      }
    },
    "/v1/environments/{environment_id}/restore": {
      "post": {
        "operationId": "restoreEnvironmentSetup",
        "summary": "Restore an earlier setup",
        "description": "Puts the environment back to the setup a build made live: its warm hook, repositories, variables, files, and skills, and the image built from them. New workspaces get it right away. If that image was already cleaned up, the restored settings are rebuilt (`rebuilding: true`). Builds keep their setup while they are among the last 10 that stored one (`restorable`).",
        "tags": ["Environments"],
        "parameters": [
          {
            "name": "environment_id",
            "in": "path",
            "required": true,
            "description": "Environment UUID.",
            "schema": {"type": "string"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"type": "object", "properties": {"build_id": {"type": "string", "format": "uuid"}}, "required": ["build_id"]}}}
        },
        "responses": {
          "200": {
            "description": "Restored",
            "content": {"application/json": {"schema": {"type": "object", "properties": {"rebuilding": {"type": "boolean"}}, "required": ["rebuilding"]}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      }
    },
    "/v1/environments/{environment_id}/hook-runs": {
      "get": {
        "operationId": "listEnvironmentHookRuns",
        "summary": "List hook runs",
        "description": "Recent warm hook runs (one per warm pool build attempt) and start hook runs (one per workspace start), newest first. The last 20 of each kind are kept.",
        "tags": ["Environments"],
        "parameters": [
          {
            "name": "environment_id",
            "in": "path",
            "required": true,
            "description": "Environment UUID.",
            "schema": {"type": "string"}
          },
          {"name": "kind", "in": "query", "required": false, "schema": {"type": "string", "enum": ["warm", "start"]}},
          {"name": "limit", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 1, "maximum": 20, "default": 10}},
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Hook runs",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ListEnvironmentHookRunsResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      }
    },
    "/v1/environments/{environment_id}/hook-runs/{run_id}": {
      "get": {
        "operationId": "getEnvironmentHookRun",
        "summary": "Get hook run log",
        "description": "A hook run with its output. Follow a running hook by polling with `offset` set to the previous `output_length`.",
        "tags": ["Environments"],
        "parameters": [
          {
            "name": "environment_id",
            "in": "path",
            "required": true,
            "description": "Environment UUID.",
            "schema": {"type": "string"}
          },
          {"name": "run_id", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid"}},
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Hook run",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/GetEnvironmentHookRunResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      }
    },
    "/v1/environments/{environment_id}/warm-pool-snapshots/{snapshot_id}/restore": {
      "post": {
        "operationId": "restoreEnvironmentWarmPoolSnapshot",
        "summary": "Restore warm pool snapshot",
        "description": "Rebuilds the warm pool from an earlier snapshot without rerunning the warm hook. The current pool serves until the new one is ready.",
        "tags": ["Warm pools"],
        "parameters": [
          {
            "name": "environment_id",
            "in": "path",
            "required": true,
            "description": "Environment UUID.",
            "schema": {"type": "string"}
          },
          {
            "name": "snapshot_id",
            "in": "path",
            "required": true,
            "description": "Snapshot record UUID from the `snapshots` array returned by GET `/v1/environments/{environmentId}/warm-hooks`.",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Snapshot restore started",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/RestoreWarmPoolSnapshotResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "409": {"$ref": "#/components/responses/Conflict"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      }
    },
    "/v1/warm-pools/{config_id}/workspaces": {
      "get": {
        "operationId": "listWarmPoolWorkspaces",
        "summary": "List warm pool workspaces",
        "description": "Lists the 10 most recent pre-built workspaces and their status. Use it to debug a pool that is not producing ready workspaces.",
        "tags": ["Warm pools"],
        "parameters": [
          {
            "name": "config_id",
            "in": "path",
            "required": true,
            "description": "Warm pool config UUID (from the `warm_pool.id` returned by GET `/v1/environments/{environmentId}/warm-hooks` or PUT `/v1/environments/{environmentId}/warm-pools`).",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ListWarmPoolWorkspacesResponse"}}}
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      }
    },
    "/v1/warm-pool-workspaces/{workspace_id}/stream": {
      "get": {
        "operationId": "streamWarmPoolWorkspace",
        "summary": "Stream warm pool workspace updates",
        "description": "Streams warm hook output and status changes as server-sent events: `output`, `status`, `complete`, and `error`. Output is only available while the workspace is `warming`. Closes when the workspace finishes.",
        "tags": ["Warm pools"],
        "parameters": [
          {
            "name": "workspace_id",
            "in": "path",
            "required": true,
            "description": "Warm pool workspace UUID (from the `id` field returned by [GET /v1/warm-pools/{configId}/workspaces](#tag/Environments/operation/listWarmPoolWorkspaces)).",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "SSE stream of warm pool workspace updates",
            "content": {
              "text/event-stream": {
                "schema": {
                  "type": "string",
                  "description": "SSE events. Each event has `type` in {`output`, `status`, `complete`, `error`} plus an optional `output`, `status`, `workspace`, or `message` payload."
                }
              }
            }
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"}
        }
      }
    },
    "/v1/automations": {
      "get": {
        "operationId": "listAutomations",
        "summary": "List automations",
        "tags": ["Automations"],
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "description": "Page number for pagination",
            "required": false,
            "schema": {"type": "integer", "default": 1, "minimum": 1}
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Number of items per page",
            "required": false,
            "schema": {"type": "integer", "default": 20, "minimum": 1, "maximum": 100}
          },
          {
            "name": "trigger_type",
            "in": "query",
            "description": "Restrict the result set to automations that have at least one trigger of the given type. Pass `all` (or omit) to disable the filter.",
            "required": false,
            "schema": {"type": "string", "enum": ["all", "cron", "github", "gitlab", "slack", "sentry", "custom"]}
          },
          {
            "name": "enabled",
            "in": "query",
            "description": "Restrict the result set to automations matching this enabled state. Omit to include both enabled and disabled automations.",
            "required": false,
            "schema": {"type": "boolean"}
          },
          {
            "name": "search",
            "in": "query",
            "description": "Case-insensitive substring match against the automation name. Whitespace is trimmed before matching.",
            "required": false,
            "schema": {"type": "string"}
          },
          {
            "name": "scope",
            "in": "query",
            "description": "Filter by automation scope. `org` returns org-owned automations, `user` returns your personal automations, `all` returns both.",
            "required": false,
            "schema": {"type": "string", "enum": ["org", "user", "all"], "default": "org"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ListAutomationsResponse"}}}
          },
          "400": {"description": "Invalid query parameter (e.g. unknown trigger_type)"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      },
      "post": {
        "operationId": "createAutomation",
        "summary": "Create automation",
        "description": "See [Automations](/features/automations) for triggers and lifecycle policies.",
        "tags": ["Automations"],
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"$ref": "#/components/schemas/CreateAutomationRequest"}}}
        },
        "responses": {
          "201": {
            "description": "Automation created successfully",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AutomationResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "403": {
            "description": "Automation limit reached for the current plan",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}
          },
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "parameters": [{"$ref": "#/components/parameters/ApiVersion"}]
      }
    },
    "/v1/automations/executions": {
      "get": {
        "operationId": "listOrganizationAutomationExecutions",
        "summary": "List all executions",
        "description": "Lists runs across every automation you can read, newest first.",
        "tags": ["Automations"],
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "description": "Page number for pagination",
            "required": false,
            "schema": {"type": "integer", "default": 1, "minimum": 1}
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Number of items per page",
            "required": false,
            "schema": {"type": "integer", "default": 20, "minimum": 1, "maximum": 100}
          },
          {
            "name": "status",
            "in": "query",
            "description": "Only return runs with this status.",
            "required": false,
            "schema": {"$ref": "#/components/schemas/AutomationExecutionRecord/properties/status"}
          },
          {
            "name": "trigger_type",
            "in": "query",
            "description": "Only return runs of automations that have at least one trigger of this type.",
            "required": false,
            "schema": {"$ref": "#/components/schemas/AutomationTrigger/properties/type"}
          },
          {
            "name": "created_by_me",
            "in": "query",
            "description": "Only return runs of automations you created. Requires a user token.",
            "required": false,
            "schema": {"type": "boolean"}
          },
          {
            "name": "search",
            "in": "query",
            "description": "Case-insensitive substring match against the automation name.",
            "required": false,
            "schema": {"type": "string"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {"schema": {"$ref": "#/components/schemas/ListOrganizationAutomationExecutionsResponse"}}
            }
          },
          "400": {"description": "Invalid query parameter (e.g. unknown status or trigger_type)"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      }
    },
    "/v1/automations/{id}": {
      "get": {
        "operationId": "getAutomation",
        "summary": "Get automation",
        "tags": ["Automations"],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The unique identifier of the automation",
            "required": true,
            "schema": {"type": "string", "format": "uuid"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AutomationResponse"}}}
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      },
      "patch": {
        "operationId": "updateAutomation",
        "summary": "Update automation",
        "description": "Updates only the fields you send. `triggers` replaces all triggers.",
        "tags": ["Automations"],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The unique identifier of the automation",
            "required": true,
            "schema": {"type": "string", "format": "uuid"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UpdateAutomationRequest"}}}
        },
        "responses": {
          "200": {
            "description": "Automation updated successfully",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AutomationResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      },
      "delete": {
        "operationId": "deleteAutomation",
        "summary": "Delete automation",
        "description": "Also deletes its run history.",
        "tags": ["Automations"],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The unique identifier of the automation",
            "required": true,
            "schema": {"type": "string", "format": "uuid"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Automation deleted successfully",
            "content": {
              "application/json": {"schema": {"type": "object", "properties": {"success": {"type": "boolean"}}, "required": ["success"]}}
            }
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      }
    },
    "/v1/automations/{id}/trigger": {
      "post": {
        "operationId": "triggerAutomation",
        "summary": "Trigger automation",
        "description": "Runs the automation now in a new workspace. For a `pull_request.command` trigger, pass `pr` to choose the pull request.",
        "tags": ["Automations"],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The unique identifier of the automation",
            "required": true,
            "schema": {"type": "string", "format": "uuid"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "requestBody": {
          "required": false,
          "content": {"application/json": {"schema": {"$ref": "#/components/schemas/TriggerAutomationRequest"}}}
        },
        "responses": {
          "200": {
            "description": "Automation triggered successfully",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/TriggerAutomationResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      }
    },
    "/v1/automations/{id}/executions": {
      "get": {
        "operationId": "listAutomationExecutions",
        "summary": "List automation executions",
        "tags": ["Automations"],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The unique identifier of the automation",
            "required": true,
            "schema": {"type": "string", "format": "uuid"}
          },
          {
            "name": "page",
            "in": "query",
            "description": "Page number for pagination",
            "required": false,
            "schema": {"type": "integer", "default": 1, "minimum": 1}
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Number of items per page",
            "required": false,
            "schema": {"type": "integer", "default": 20, "minimum": 1, "maximum": 100}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ListAutomationExecutionsResponse"}}}
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      }
    },
    "/v1/automations/{id}/executions/{execution_id}/retry": {
      "post": {
        "operationId": "retryAutomationExecution",
        "summary": "Retry automation execution",
        "description": "Replays a failed run's trigger in a new workspace with the automation's current settings.",
        "tags": ["Automations"],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The unique identifier of the automation",
            "required": true,
            "schema": {"type": "string", "format": "uuid"}
          },
          {
            "name": "execution_id",
            "in": "path",
            "description": "The unique identifier of the failed execution",
            "required": true,
            "schema": {"type": "string", "format": "uuid"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Retry started as a new execution",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/TriggerAutomationResponse"}}}
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "403": {"$ref": "#/components/responses/Forbidden"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "409": {
            "description": "The execution has not failed, or another run is still reporting the same GitHub checks",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}
          },
          "429": {
            "description": "The automation or organization is over its hourly execution limit",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}
          },
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      }
    },
    "/v1/replica/repositories": {
      "get": {
        "operationId": "listRepositories",
        "summary": "List repositories",
        "tags": ["Repositories"],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {"repositories": {"type": "array", "items": {"$ref": "#/components/schemas/Repository"}}},
                  "required": ["repositories"]
                }
              }
            }
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "parameters": [{"$ref": "#/components/parameters/ApiVersion"}]
      }
    },
    "/v1/repositories/{id}/branches": {
      "get": {
        "operationId": "listRepositoryBranches",
        "summary": "List repository branches",
        "description": "Returns up to 100 branches. Use `q` to search by prefix.",
        "tags": ["Repositories"],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Connected repository ID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Branch name prefix",
            "schema": {"type": "string", "maxLength": 255}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Repository branches",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ListRepositoryBranchesResponse"}}}
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "409": {"$ref": "#/components/responses/Conflict"},
          "502": {"$ref": "#/components/responses/BadGateway"}
        }
      }
    },
    "/v1/github/repositories": {
      "get": {
        "operationId": "listGitHubRepositories",
        "summary": "List connectable GitHub repositories",
        "description": "Lists repositories the organization's GitHub App installations can reach, with the IDs Add repository needs.",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "repositories": {"type": "array", "items": {"$ref": "#/components/schemas/GitHubRepository"}},
                    "has_installations": {"type": "boolean"},
                    "install_url": {
                      "type": "string",
                      "format": "uri",
                      "description": "Where to install the GitHub App when there are no installations"
                    }
                  }
                }
              }
            }
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Repositories"],
        "parameters": [{"$ref": "#/components/parameters/ApiVersion"}]
      }
    },
    "/v1/repositories": {
      "post": {
        "operationId": "addRepository",
        "summary": "Add repository",
        "description": "Connects a repository. GitHub repositories must come from List connectable GitHub repositories. Requires an organization admin's personal API key.",
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AddRepositoryRequest"}}}
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {"schema": {"type": "object", "properties": {"repository": {"$ref": "#/components/schemas/Repository"}}}}
            }
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "403": {"$ref": "#/components/responses/Forbidden"},
          "409": {"$ref": "#/components/responses/Conflict"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Repositories"],
        "parameters": [{"$ref": "#/components/parameters/ApiVersion"}]
      }
    },
    "/v1/repositories/{id}": {
      "patch": {
        "operationId": "updateRepository",
        "summary": "Update repository",
        "description": "Changes the default branch. Requires an organization admin's personal API key.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Repository ID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {"type": "object", "properties": {"default_branch": {"type": "string"}}, "required": ["default_branch"]}
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {"schema": {"type": "object", "properties": {"repository": {"$ref": "#/components/schemas/Repository"}}}}
            }
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "403": {"$ref": "#/components/responses/Forbidden"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Repositories"]
      },
      "delete": {
        "operationId": "deleteRepository",
        "summary": "Remove repository",
        "description": "Disconnects a repository. Returns `409` while an environment or active workspace uses it. Requires an organization admin's personal API key.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Repository ID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SuccessResponse"}}}
          },
          "403": {"$ref": "#/components/responses/Forbidden"},
          "409": {"$ref": "#/components/responses/Conflict"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Repositories"]
      }
    },
    "/v1/learned-skills": {
      "get": {
        "operationId": "listLearnedSkills",
        "summary": "List learnings",
        "responses": {
          "200": {
            "description": "Learnings",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {"skills": {"type": "array", "items": {"$ref": "#/components/schemas/LearnedSkill"}}},
                  "required": ["skills"]
                }
              }
            }
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Learnings"],
        "parameters": [{"$ref": "#/components/parameters/ApiVersion"}]
      },
      "post": {
        "operationId": "createLearnedSkill",
        "summary": "Create learning",
        "description": "Adds a learning. Every new workspace loads it.",
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SaveLearnedSkillRequest"}}}
        },
        "responses": {
          "201": {
            "description": "Created learning",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/LearnedSkill"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Learnings"],
        "parameters": [{"$ref": "#/components/parameters/ApiVersion"}]
      }
    },
    "/v1/learned-skills/{id}": {
      "put": {
        "operationId": "updateLearnedSkill",
        "summary": "Update learning",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Learning ID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SaveLearnedSkillRequest"}}}
        },
        "responses": {
          "200": {
            "description": "Updated learning",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/LearnedSkill"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Learnings"]
      },
      "delete": {
        "operationId": "deleteLearnedSkill",
        "summary": "Delete learning",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Learning ID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SuccessResponse"}}}
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Learnings"]
      }
    },
    "/v1/agents/{agent}/models": {"get": {"operationId": "getAgentModels", "summary": "List models", "description": "Uses the workspace selection or harness credential priority. Before workspace creation, pass method and scope to preview a connected inference provider. Returns provider editability and an optional default model; null requires explicit selection.", "tags": ["Agent credentials"], "parameters": [{"name": "agent", "in": "path", "required": true, "schema": {"type": "string", "enum": ["claude", "codex", "opencode", "pi"]}}, {"name": "workspaceId", "in": "query", "schema": {"type": "string", "format": "uuid"}}, {"name": "method", "in": "query", "description": "Connected inference method; requires scope and must be supported by the agent.", "schema": {"type": "string"}}, {"name": "scope", "in": "query", "schema": {"type": "string", "enum": ["org", "user"]}}, {"name": "query", "in": "query", "schema": {"type": "string"}}, {"name": "page", "in": "query", "schema": {"type": "integer", "minimum": 1, "default": 1}}, {"name": "limit", "in": "query", "schema": {"type": "integer", "minimum": 1, "maximum": 100, "default": 100}}], "responses": {"200": {"description": "Paginated model catalog", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ModelCatalogResponse"}}}}, "401": {"$ref": "#/components/responses/Unauthorized"}, "502": {"description": "The provider catalog could not be loaded."}}}},
    "/v1/{provider}/credentials": {
      "get": {
        "operationId": "getOrgCredential",
        "summary": "Get organization credential",
        "tags": ["Agent credentials"],
        "description": "Organization credentials apply to every member. Changing them requires an admin's personal API key.",
        "parameters": [
          {
            "name": "provider",
            "in": "path",
            "required": true,
            "description": "Credential provider. `claude`, `codex`, and `muse` subscriptions also support reads and deletes; connect those with the CLI.",
            "schema": {
              "type": "string",
              "enum": [
                "anthropic",
                "openai",
                "openrouter",
                "cursor",
                "muse-api-key",
                "opencode-go",
                "aster",
                "ollama",
                "openai-compatible",
                "bedrock",
                "claude-foundry",
                "codex-foundry",
                "claude",
                "codex",
                "muse"
              ]
            }
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/CredentialStatus"}}}
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "403": {"$ref": "#/components/responses/Forbidden"}
        }
      },
      "post": {
        "operationId": "setOrgCredential",
        "summary": "Set organization credential",
        "tags": ["Agent credentials"],
        "description": "Organization credentials apply to every member. Changing them requires an admin's personal API key. The key is checked with the provider where possible. A new `opencode-go` key is added after the existing ones, up to 10, and deleting removes them all.",
        "parameters": [
          {
            "name": "provider",
            "in": "path",
            "required": true,
            "description": "Credential provider. `claude`, `codex`, and `muse` subscriptions also support reads and deletes; connect those with the CLI.",
            "schema": {
              "type": "string",
              "enum": [
                "anthropic",
                "openai",
                "openrouter",
                "cursor",
                "muse-api-key",
                "opencode-go",
                "aster",
                "ollama",
                "openai-compatible",
                "bedrock",
                "claude-foundry",
                "codex-foundry",
                "claude",
                "codex",
                "muse"
              ]
            }
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SetCredentialRequest"}}}
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {"success": {"type": "boolean"}, "credential_id": {"type": "string"}},
                  "required": ["success"]
                }
              }
            }
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "403": {"$ref": "#/components/responses/Forbidden"}
        }
      },
      "delete": {
        "operationId": "deleteOrgCredential",
        "summary": "Delete organization credential",
        "tags": ["Agent credentials"],
        "parameters": [
          {
            "name": "provider",
            "in": "path",
            "required": true,
            "description": "Credential provider. `claude`, `codex`, and `muse` subscriptions also support reads and deletes; connect those with the CLI.",
            "schema": {
              "type": "string",
              "enum": [
                "anthropic",
                "openai",
                "openrouter",
                "cursor",
                "muse-api-key",
                "opencode-go",
                "aster",
                "ollama",
                "openai-compatible",
                "bedrock",
                "claude-foundry",
                "codex-foundry",
                "claude",
                "codex",
                "muse"
              ]
            }
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SuccessResponse"}}}
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "403": {"$ref": "#/components/responses/Forbidden"}
        }
      }
    },
    "/v1/{provider}/user/credentials": {
      "get": {
        "operationId": "getPersonalCredential",
        "summary": "Get personal credential",
        "tags": ["Agent credentials"],
        "description": "Personal credentials take priority over organization ones and need a personal API key.",
        "parameters": [
          {
            "name": "provider",
            "in": "path",
            "required": true,
            "description": "Credential provider. `claude`, `codex`, and `muse` subscriptions also support reads and deletes; connect those with the CLI.",
            "schema": {
              "type": "string",
              "enum": [
                "anthropic",
                "openai",
                "openrouter",
                "cursor",
                "muse-api-key",
                "opencode-go",
                "aster",
                "ollama",
                "openai-compatible",
                "bedrock",
                "claude-foundry",
                "codex-foundry",
                "claude",
                "codex",
                "muse"
              ]
            }
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/CredentialStatus"}}}
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "403": {"$ref": "#/components/responses/Forbidden"}
        }
      },
      "post": {
        "operationId": "setPersonalCredential",
        "summary": "Set personal credential",
        "tags": ["Agent credentials"],
        "description": "Personal credentials take priority over organization ones and need a personal API key. The key is checked with the provider where possible. A new `opencode-go` key is added after the existing ones, up to 10, and deleting removes them all.",
        "parameters": [
          {
            "name": "provider",
            "in": "path",
            "required": true,
            "description": "Credential provider. `claude`, `codex`, and `muse` subscriptions also support reads and deletes; connect those with the CLI.",
            "schema": {
              "type": "string",
              "enum": [
                "anthropic",
                "openai",
                "openrouter",
                "cursor",
                "muse-api-key",
                "opencode-go",
                "aster",
                "ollama",
                "openai-compatible",
                "bedrock",
                "claude-foundry",
                "codex-foundry",
                "claude",
                "codex",
                "muse"
              ]
            }
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SetCredentialRequest"}}}
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {"success": {"type": "boolean"}, "credential_id": {"type": "string"}},
                  "required": ["success"]
                }
              }
            }
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "403": {"$ref": "#/components/responses/Forbidden"}
        }
      },
      "delete": {
        "operationId": "deletePersonalCredential",
        "summary": "Delete personal credential",
        "tags": ["Agent credentials"],
        "parameters": [
          {
            "name": "provider",
            "in": "path",
            "required": true,
            "description": "Credential provider. `claude`, `codex`, and `muse` subscriptions also support reads and deletes; connect those with the CLI.",
            "schema": {
              "type": "string",
              "enum": [
                "anthropic",
                "openai",
                "openrouter",
                "cursor",
                "muse-api-key",
                "opencode-go",
                "aster",
                "ollama",
                "openai-compatible",
                "bedrock",
                "claude-foundry",
                "codex-foundry",
                "claude",
                "codex",
                "muse"
              ]
            }
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SuccessResponse"}}}
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "403": {"$ref": "#/components/responses/Forbidden"}
        }
      }
    },
    "/v1/agents/{agent}/credentials": {
      "get": {
        "operationId": "listAgentCredentials",
        "summary": "List credentials for an agent",
        "tags": ["Agent credentials"],
        "description": "Lists the credential methods connected for a coding agent and which one workspaces use.",
        "parameters": [
          {
            "name": "agent",
            "in": "path",
            "required": true,
            "schema": {"type": "string", "enum": ["claude", "codex", "cursor", "muse", "opencode", "pi"]}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "credentials": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {"method": {"type": "string"}, "scope": {"type": "string", "enum": ["org", "user"]}}
                      }
                    },
                    "selected": {"type": ["object", "null"]}
                  }
                }
              }
            }
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "403": {"$ref": "#/components/responses/Forbidden"}
        }
      }
    },
    "/v1/agents/subscription-usage": {
      "get": {
        "operationId": "getSubscriptionUsage",
        "summary": "Get subscription usage",
        "tags": ["Agent credentials"],
        "description": "Reads live from Anthropic and OpenAI how much of each connected Claude and ChatGPT subscription's 5-hour and weekly limits is used. Muse Code and OpenCode Go do not report usage. Without `scope`, returns your personal subscriptions followed by the organization's, each in the order workspaces use them.",
        "parameters": [
          {
            "name": "scope",
            "in": "query",
            "description": "Only `user` (needs a personal API key) or only `org` subscriptions.",
            "schema": {"type": "string", "enum": ["user", "org"]}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {"accounts": {"type": "array", "items": {"$ref": "#/components/schemas/SubscriptionUsageAccount"}}},
                  "required": ["accounts"]
                }
              }
            }
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "403": {"$ref": "#/components/responses/Forbidden"}
        }
      }
    },
    "/v1/environments/{environment_id}/plugins/connections": {
      "get": {
        "operationId": "listPlugins",
        "summary": "List plugins",
        "description": "Lists every [plugin](/features/plugins) and which are connected for the environment.",
        "parameters": [
          {
            "name": "environment_id",
            "in": "path",
            "required": true,
            "description": "Environment ID",
            "schema": {"type": "string"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PluginConnectionsResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "403": {"$ref": "#/components/responses/Forbidden"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Plugins"]
      }
    },
    "/v1/environments/{environment_id}/plugins/{plugin_id}/connect": {
      "post": {
        "operationId": "connectPlugin",
        "summary": "Connect plugin",
        "description": "Connects a plugin that uses credentials, such as an API key. Credentials are verified with the provider. For OAuth plugins, use Start plugin OAuth. Requires write access to the environment.",
        "parameters": [
          {
            "name": "environment_id",
            "in": "path",
            "required": true,
            "description": "Environment ID",
            "schema": {"type": "string"}
          },
          {
            "name": "plugin_id",
            "in": "path",
            "required": true,
            "description": "Plugin ID from List plugins",
            "schema": {"type": "string"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PluginConnectRequest"}}}
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PluginConnectResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "403": {"$ref": "#/components/responses/Forbidden"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Plugins"]
      }
    },
    "/v1/environments/{environment_id}/plugins/{plugin_id}/oauth/start": {
      "post": {
        "operationId": "startPluginOAuth",
        "summary": "Start plugin OAuth",
        "description": "Returns an `authorization_url` for a person to open. The connection is saved when they approve. The authorization is tied to a person, so this needs a personal API key or the app. Requires write access to the environment.",
        "parameters": [
          {
            "name": "environment_id",
            "in": "path",
            "required": true,
            "description": "Environment ID",
            "schema": {"type": "string"}
          },
          {
            "name": "plugin_id",
            "in": "path",
            "required": true,
            "description": "Plugin ID from List plugins",
            "schema": {"type": "string"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PluginStartOAuthResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "403": {"$ref": "#/components/responses/Forbidden"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Plugins"]
      }
    },
    "/v1/environments/{environment_id}/plugins/{plugin_id}": {
      "delete": {
        "operationId": "disconnectPlugin",
        "summary": "Disconnect plugin",
        "description": "Removes the plugin's connections from the environment and revokes their authorization.",
        "parameters": [
          {
            "name": "environment_id",
            "in": "path",
            "required": true,
            "description": "Environment ID",
            "schema": {"type": "string"}
          },
          {
            "name": "plugin_id",
            "in": "path",
            "required": true,
            "description": "Plugin ID from List plugins",
            "schema": {"type": "string"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PluginConnectionDeleteResponse"}}}
          },
          "403": {"$ref": "#/components/responses/Forbidden"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Plugins"]
      }
    },
    "/v1/whoami": {
      "get": {
        "operationId": "whoami",
        "summary": "Get current identity",
        "tags": ["Organization"],
        "description": "Shows the organization and identity the request acts as, and whether it has admin rights.",
        "responses": {
          "200": {
            "description": "Identity",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Whoami"}}}
          },
          "401": {"$ref": "#/components/responses/Unauthorized"}
        },
        "parameters": [{"$ref": "#/components/parameters/ApiVersion"}]
      }
    },
    "/v1/organization/members": {
      "get": {
        "operationId": "listOrganizationMembers",
        "summary": "List members",
        "tags": ["Organization"],
        "description": "Lists members with their user IDs, for sharing workspaces and filtering by owner.",
        "responses": {
          "200": {
            "description": "Members",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {"members": {"type": "array", "items": {"$ref": "#/components/schemas/OrganizationMember"}}},
                  "required": ["members"]
                }
              }
            }
          },
          "401": {"$ref": "#/components/responses/Unauthorized"}
        },
        "parameters": [{"$ref": "#/components/parameters/ApiVersion"}]
      }
    },
    "/v1/media/{id}/url": {
      "get": {
        "operationId": "getMediaDownloadUrl",
        "summary": "Get a media download URL",
        "description": "Returns a short-lived URL that downloads the file.",
        "tags": ["Media"],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The media item identifier.",
            "required": true,
            "schema": {"type": "string", "format": "uuid"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Short-lived media download URL.",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MediaPresignedUrlResponse"}}}
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      }
    },
    "/v1/media/{id}/preview-url": {
      "get": {
        "operationId": "getMediaPreviewUrl",
        "summary": "Get a media preview URL",
        "description": "Returns a short-lived URL that renders the file inline. Sandbox HTML previews.",
        "tags": ["Media"],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The media item identifier.",
            "required": true,
            "schema": {"type": "string", "format": "uuid"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Short-lived inline media preview URL.",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MediaPresignedUrlResponse"}}}
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      }
    },
    "/v1/media/{id}/metadata": {
      "get": {
        "operationId": "getMediaMetadata",
        "summary": "Get media metadata",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Media ID",
            "schema": {"type": "string", "format": "uuid"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Media",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {"media": {"$ref": "#/components/schemas/Media"}},
                  "required": ["media"]
                }
              }
            }
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "tags": ["Media"]
      }
    },
    "/v1/slack/threads/attach": {
      "post": {
        "operationId": "attachSlackThread",
        "summary": "Attach Slack thread",
        "description": "Routes replies in a Slack thread to a workspace.",
        "tags": ["Slack"],
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SlackThreadAttachRequest"}}}
        },
        "responses": {
          "200": {
            "description": "Slack thread routed",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SlackThreadAttachResponse"}}}
          },
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "403": {
            "description": "The workspace agent cannot route this Slack thread",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}
          },
          "404": {"$ref": "#/components/responses/NotFound"},
          "409": {"$ref": "#/components/responses/Conflict"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        },
        "parameters": [{"$ref": "#/components/parameters/ApiVersion"}]
      }
    },
    "/.well-known/openid-configuration": {
      "get": {
        "operationId": "getWorkspaceIdentityDiscovery",
        "summary": "Get workspace identity discovery document",
        "description": "OIDC discovery document for [workspace identity](/features/workspaces/workspace-identity) tokens. No authentication.",
        "tags": ["Workspace identity"],
        "security": [],
        "responses": {
          "200": {
            "description": "Discovery document",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/WorkspaceIdentityDiscovery"}}}
          },
          "404": {"description": "Workspace identity is not configured on this installation"}
        }
      }
    },
    "/.well-known/jwks.json": {
      "get": {
        "operationId": "getWorkspaceIdentityJwks",
        "summary": "Get workspace identity signing keys",
        "description": "Public keys for verifying workspace identity tokens, including staged rotation keys. No authentication.",
        "tags": ["Workspace identity"],
        "security": [],
        "responses": {
          "200": {
            "description": "JSON Web Key Set",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/WorkspaceIdentityJwks"}}}
          },
          "404": {"description": "Workspace identity is not configured on this installation"}
        }
      }
    },
    "/v1/environments/{environment_id}/effective": {
      "get": {
        "operationId": "getEffectiveEnvironment",
        "summary": "Get effective environment",
        "description": "Returns the environment's configuration folded over its chain (the root, then each ancestor, then the environment itself) with provenance for every variable, file, MCP, skill, skill registry, plugin, and secret-sync connection. System prompts are listed in the order they're combined. Values from environments you can't read are blanked and flagged `masked`.",
        "tags": [
          "Environments"
        ],
        "parameters": [
          {
            "name": "environment_id",
            "in": "path",
            "required": true,
            "description": "Environment UUID.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/ApiVersion"
          }
        ],
        "responses": {
          "200": {
            "description": "Effective configuration",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EffectiveEnvironmentResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/v1/environments/{environment_id}/exclusions": {
      "post": {
        "operationId": "excludeInheritedItem",
        "summary": "Exclude inherited item",
        "description": "Hides an inherited item from this environment and its forks. `DELETE` on an inherited variable, file, MCP, skill, or registry through this environment does the same. Locked variables can't be excluded (`409`).",
        "tags": [
          "Environments"
        ],
        "parameters": [
          {
            "name": "environment_id",
            "in": "path",
            "required": true,
            "description": "Environment UUID.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/ApiVersion"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InheritanceKeyRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Excluded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          }
        }
      }
    },
    "/v1/environments/{environment_id}/reset-inherited": {
      "post": {
        "operationId": "resetInheritedItem",
        "summary": "Reset to inherited",
        "description": "Removes this environment's override and exclusion for a key so the inherited value applies again. With `kind: \"repository\"`, `\"memory\"`, or `\"default_skills\"`, a fork clears its own repository binding, memory settings, or default skills.",
        "tags": [
          "Environments"
        ],
        "parameters": [
          {
            "name": "environment_id",
            "in": "path",
            "required": true,
            "description": "Environment UUID.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/ApiVersion"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ResetInheritedRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Reset",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/v1/environments/{environment_id}/workload-identity": {
      "get": {
        "operationId": "getWorkloadIdentity",
        "summary": "Get workspace identity configuration",
        "description": "Returns the issuer, discovery, and JWKS URLs for [workspace identity](/features/workspaces/workspace-identity) tokens. Tokens are minted inside workspaces, not through the API.",
        "tags": ["Workspace identity"],
        "parameters": [
          {
            "name": "environment_id",
            "in": "path",
            "required": true,
            "description": "Environment UUID.",
            "schema": {"type": "string"}
          },
          {"$ref": "#/components/parameters/ApiVersion"}
        ],
        "responses": {
          "200": {
            "description": "Identity configuration",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/WorkloadIdentityResponse"}}}
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "403": {"$ref": "#/components/responses/Forbidden"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "500": {"$ref": "#/components/responses/InternalServerError"}
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "Organization or personal API key from **Settings → API Keys**."
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Bad request - Missing or invalid parameters",
        "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}
      },
      "Unauthorized": {
        "description": "Unauthorized - Invalid or missing API key",
        "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}
      },
      "Forbidden": {
        "description": "Forbidden - The authenticated account cannot access this resource",
        "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}
      },
      "PaymentRequired": {
        "description": "Payment Required - The organization has used up its trial or YC deal credit, reached its usage limit, or has a failed usage payment.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "error": {"type": "string", "description": "Error message"},
                "code": {
                  "type": "string",
                  "enum": ["INSUFFICIENT_MINUTES", "PAYMENT_FAILED", "USAGE_LIMIT_REACHED"],
                  "description": "Machine-readable billing block reason"
                }
              },
              "required": ["error", "code"]
            }
          }
        }
      },
      "NotFound": {
        "description": "Resource not found",
        "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}
      },
      "Conflict": {
        "description": "Conflict - Resource already exists or operation conflicts with current state",
        "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}
      },
      "InternalServerError": {
        "description": "Internal server error",
        "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}
      },
      "BadGateway": {
        "description": "Bad gateway - The workspace is unreachable or returned an invalid response",
        "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}
      },
      "ServiceUnavailable": {
        "description": "Service unavailable - The service is temporarily overloaded or under maintenance",
        "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}
      }
    },
    "parameters": {
      "ApiVersion": {
        "name": "X-Replicas-Api-Version",
        "in": "header",
        "description": "API version. `2026-10-07` returns `snake_case` responses. See [versioning](/features/api#versioning).",
        "required": false,
        "schema": {"type": "string", "enum": ["2026-10-07"]}
      }
    },
    "schemas": {
      "RepoFileEntry": {
        "type": "object",
        "required": ["repoName", "path", "displayPath", "status", "score", "indexedAt", "stale"],
        "properties": {
          "repoName": {"type": "string"},
          "path": {"type": "string", "description": "Path relative to the repository root."},
          "displayPath": {"type": "string", "description": "Repository-qualified path for multi-repository workspaces."},
          "status": {"type": "string", "enum": ["changed", "untouched"]},
          "score": {
            "type": "number",
            "description": "Search relevance score; results sort by descending score, then displayPath."
          },
          "indexedAt": {"type": "string", "format": "date-time"},
          "stale": {"type": "boolean"}
        }
      },
      "SearchRepoFilesResponse": {
        "type": "object",
        "required": ["files", "nextCursor", "indexedAt", "stale"],
        "properties": {
          "files": {"type": "array", "items": {"$ref": "#/components/schemas/RepoFileEntry"}},
          "nextCursor": {
            "type": ["string", "null"],
            "description": "Opaque cursor for the next page; null when pagination is complete."
          },
          "indexedAt": {
            "type": "string",
            "format": "date-time",
            "description": "Index version. Discard accumulated pages and restart without refresh if this value changes between pages."
          },
          "stale": {
            "type": "boolean",
            "description": "Results are cached or from a repository fallback and may not reflect the current workspace. Does not by itself mean a refresh is pending."
          },
          "refreshing": {
            "type": "boolean",
            "description": "A background workspace index refresh is pending. Poll only while true; inactive fallback results do not enable polling."
          },
          "truncated": {
            "type": "boolean",
            "description": "Index is incomplete due to provider limits, index caps, or unavailable repositories; independent of nextCursor."
          },
          "unsupported": {
            "type": "boolean",
            "description": "Optional compatibility flag indicating repository file search is unsupported."
          }
        }
      },
      "PluginId": { "type": "string", "enum": ["attio","calendly","clickhouse","cloudflare","e2b","gmail","greptile","googleads","googledocs","googledrive","googlesearch","googlesheets","linkedin","modal","posthog","planetscale","sazabi","stripe","kondo","lightfield","pangram","vercel","turbopuffer","vanta","notion","jira","confluence","googlecalendar","microsoftteams","outlook","bitbucket","datadog","pagerduty","intercom","zendesk","hubspot","supabase","figma","launchdarkly","asana","clickup","trello","todoist","airtable","coda","miro","sharepoint","onedrive","googleslides","googlemeet","circleback","granola","mercury","googletasks","dropbox","box","discord","discordbot","zoom","googlechat","newrelic","betterstack","incidentio","grafana","honeycomb","neon","glen","bugsnag","circleci","buildkite","dockerhub","digitalocean","railway","render","firebase","cloudinary","configcat","contextdev","googleanalytics","googlebigquery","amplitude","mixpanel","segment","supermemory","databricks","snowflake","algolia","elasticsearch","salesforce","pipedrive","close","apollo","gong","freshdesk","helpscout","servicenow","mailchimp","customerio","klaviyo","shopify","quickbooks","xero","brex","buffer","canva","webflow","firecrawl","browserbase","exa","youtube","twitter","instagram","facebook"], "x-generated-by": "bun run docs:generate-plugin-schemas" },
      "PluginAuthType": {"type": "string", "enum": ["oauth", "api_key", "basic", "credentials", "hosted"]},
      "HostedPluginAuthScheme": { "type": "string", "enum": ["API_KEY","BASIC","BEARER_TOKEN","DCR_OAUTH","OAUTH1","OAUTH2"], "x-generated-by": "bun run docs:generate-plugin-schemas" },
      "PluginCategory": {"type": "string", "enum": ["business", "data", "productivity"]},
      "PluginConnectionStatus": {"type": "string", "enum": ["initiated", "active", "expired", "failed"]},
      "PluginCatalogItem": {
        "type": "object",
        "properties": {
          "id": {"$ref": "#/components/schemas/PluginId"},
          "backend": {"type": "string", "enum": ["composio", "native"]},
          "toolkit": {"type": "string"},
          "auth_type": {"$ref": "#/components/schemas/PluginAuthType"},
          "auth_scheme": {
            "$ref": "#/components/schemas/HostedPluginAuthScheme",
            "description": "Authentication scheme used by a hosted Composio Connect Link. Present when authType is hosted."
          },
          "managed_auth": {
            "type": "boolean",
            "description": "Whether Composio supplies the OAuth application for this hosted plugin. Present when authType is hosted."
          },
          "category": {"$ref": "#/components/schemas/PluginCategory"},
          "name": {"type": "string"},
          "description": {"type": "string"}
        },
        "required": ["id", "backend", "toolkit", "auth_type", "category", "name", "description"]
      },
      "PluginConnectionSummary": {
        "type": "object",
        "properties": {
          "id": {"type": "string", "format": "uuid"},
          "plugin_id": {"$ref": "#/components/schemas/PluginId"},
          "environment_id": {"type": "string", "format": "uuid", "description": "Environment that owns the installation."},
          "status": {"$ref": "#/components/schemas/PluginConnectionStatus"},
          "account_label": {"type": "string"},
          "connected_at": {"type": "string", "format": "date-time"}
        },
        "required": ["id", "plugin_id", "environment_id", "status"]
      },
      "PluginConnectionsResponse": {
        "type": "object",
        "properties": {
          "plugins": {"type": "array", "items": {"$ref": "#/components/schemas/PluginCatalogItem"}},
          "environment": {
            "type": "array",
            "description": "Installations owned directly by the environment being listed.",
            "items": {"$ref": "#/components/schemas/PluginConnectionSummary"}
          }
        },
        "required": ["plugins", "environment"]
      },
      "PluginStartOAuthResponse": {
        "type": "object",
        "properties": {"authorization_url": {"type": "string", "format": "uri"}},
        "required": ["authorization_url"]
      },
      "PluginConnectPostHogRequest": {
        "type": "object",
        "properties": {
          "api_key": {"type": "string", "description": "PostHog personal API key beginning with phx_."},
          "region": {"type": "string", "enum": ["us", "eu"]}
        },
        "required": ["api_key", "region"]
      },
      "PluginConnectClickHouseRequest": {
        "type": "object",
        "properties": {
          "url": {"type": "string", "format": "uri"},
          "username": {"type": "string"},
          "password": {"type": "string"},
          "database": {"type": "string"}
        },
        "required": ["url", "username", "password"]
      },
      "PluginConnectApiKeyRequest": {
        "type": "object",
        "properties": {"api_key": {"type": "string", "description": "Provider API key or access token."}},
        "required": ["api_key"]
      },
      "PluginConnectModalRequest": {
        "type": "object",
        "properties": {
          "token_id": {"type": "string", "description": "Modal service-user token ID."},
          "token_secret": {"type": "string", "description": "Modal service-user token secret."}
        },
        "required": ["token_id", "token_secret"]
      },
      "PluginConnectVantaRequest": {
        "type": "object",
        "description": "Vanta Manage API credentials. Supported only by the environment-scoped credential endpoint.",
        "properties": {
          "client_id": {"type": "string", "description": "Vanta client ID beginning with vci_."},
          "client_secret": {"type": "string", "description": "Vanta client secret beginning with vcs_."},
          "deployment": {"type": "string", "enum": ["standard", "gov"]}
        },
        "required": ["client_id", "client_secret", "deployment"]
      },
      "PluginConnectTurbopufferRequest": {
        "type": "object",
        "properties": {
          "api_key": {"type": "string", "description": "turbopuffer API key beginning with tpuf_."},
          "region": {"type": "string", "enum": ["aws-us-east-1", "aws-us-west-2", "gcp-us-central1", "gcp-europe-west3"]}
        },
        "required": ["api_key", "region"]
      },
      "PluginConnectRequest": {
        "oneOf": [
          {"$ref": "#/components/schemas/PluginConnectPostHogRequest"},
          {"$ref": "#/components/schemas/PluginConnectClickHouseRequest"},
          {"$ref": "#/components/schemas/PluginConnectApiKeyRequest"},
          {"$ref": "#/components/schemas/PluginConnectModalRequest"},
          {"$ref": "#/components/schemas/PluginConnectVantaRequest"},
          {"$ref": "#/components/schemas/PluginConnectTurbopufferRequest"}
        ]
      },
      "PluginConnectResponse": {"type": "object", "properties": {"success": {"type": "boolean"}}, "required": ["success"]},
      "PluginConnectionDeleteResponse": {"type": "object", "properties": {"success": {"type": "boolean"}}, "required": ["success"]},
      "DesktopArchitecture": {"type": "string", "enum": ["arm64", "x64"]},
      "PresenceLocation": {
        "type": "object",
        "description": "Where a member is currently active. Both fields are optional; an empty object means the member is online but not on a specific environment or workspace.",
        "properties": {
          "environmentId": {"type": "string", "description": "ID of the environment the member is viewing."},
          "workspaceId": {"type": "string", "description": "ID of the workspace the member is viewing."}
        }
      },
      "PresenceEntry": {
        "type": "object",
        "required": ["userId", "status", "location", "ts"],
        "properties": {
          "userId": {"type": "string", "description": "ID of the member this presence entry belongs to."},
          "status": {"type": "string", "enum": ["online", "typing"], "description": "The member's current activity."},
          "location": {"$ref": "#/components/schemas/PresenceLocation"},
          "ts": {
            "type": "string",
            "format": "date-time",
            "description": "ISO 8601 timestamp of the member's last presence update."
          }
        }
      },
      "PresenceList": {
        "type": "object",
        "required": ["presence"],
        "properties": {"presence": {"type": "array", "items": {"$ref": "#/components/schemas/PresenceEntry"}}}
      },
      "UpdatePresenceRequest": {
        "type": "object",
        "required": ["status"],
        "properties": {
          "status": {
            "type": "string",
            "enum": ["online", "typing"],
            "description": "The status to report for the authenticated user."
          },
          "location": {"$ref": "#/components/schemas/PresenceLocation"}
        }
      },
      "UpdatePresenceResponse": {"type": "object", "required": ["success"], "properties": {"success": {"type": "boolean"}}},
      "OrganizationRole": {
        "type": "object",
        "properties": {
          "id": {"type": "string", "format": "uuid"},
          "name": {"type": "string"},
          "member_count": {"type": "integer"},
          "created_at": {"type": "string", "format": "date-time"},
          "updated_at": {"type": "string", "format": "date-time"}
        },
        "required": ["id", "name", "member_count", "created_at", "updated_at"]
      },
      "ListOrganizationRolesResponse": {
        "type": "object",
        "properties": {"roles": {"type": "array", "items": {"$ref": "#/components/schemas/OrganizationRole"}}},
        "required": ["roles"]
      },
      "OrganizationRoleResponse": {
        "type": "object",
        "properties": {"role": {"$ref": "#/components/schemas/OrganizationRole"}},
        "required": ["role"]
      },
      "CreateOrganizationRoleRequest": {
        "type": "object",
        "properties": {"name": {"type": "string", "minLength": 1, "maxLength": 80}},
        "required": ["name"]
      },
      "UpdateOrganizationMemberRolesRequest": {
        "type": "object",
        "properties": {"role_ids": {"type": "array", "uniqueItems": true, "items": {"type": "string", "format": "uuid"}}},
        "required": ["role_ids"]
      },
      "UpdateOrganizationMemberRolesResponse": {
        "type": "object",
        "properties": {"role_ids": {"type": "array", "items": {"type": "string", "format": "uuid"}}},
        "required": ["role_ids"]
      },
      "UserPreferences": {
        "type": "object",
        "description": "Personal preferences. Additional preference fields may be returned.",
        "properties": {"fallback_chains": {"$ref": "#/components/schemas/FallbackChains"}},
        "additionalProperties": true
      },
      "UserPreferencesResponse": {
        "type": "object",
        "properties": {"preferences": {"$ref": "#/components/schemas/UserPreferences"}},
        "required": ["preferences"]
      },
      "UpdateUserPreferencesRequest": {
        "type": "object",
        "properties": {"preferences": {"$ref": "#/components/schemas/UserPreferences"}},
        "required": ["preferences"]
      },
      "UpdateUserPreferencesResponse": {
        "type": "object",
        "properties": {"success": {"type": "boolean"}, "preferences": {"$ref": "#/components/schemas/UserPreferences"}},
        "required": ["success", "preferences"]
      },
      "FallbackStep": {
        "oneOf": [
          {
            "type": "object",
            "description": "Switch the running chat to another credential of the same harness.",
            "properties": {
              "kind": {"type": "string", "enum": ["credential"]},
              "method": {
                "type": "string",
                "enum": [
                  "oauth",
                  "api_key",
                  "openai-compatible",
                  "ollama",
                  "foundry",
                  "bedrock",
                  "opencode-go",
                  "aster",
                  "openrouter",
                  "muse-oauth"
                ]
              },
              "model": {
                "type": "string",
                "description": "Model a Claude or Codex chat switches to on an Ollama or OpenAI-compatible credential, which serve their own models. Ignored for other credentials."
              }
            },
            "required": ["kind", "method"]
          },
          {
            "type": "object",
            "description": "Fork the chat to another harness with its sanitized transcript.",
            "properties": {
              "kind": {"type": "string", "enum": ["harness"]},
              "provider": {"type": "string", "enum": ["claude", "codex", "cursor", "muse", "opencode", "pi"]},
              "model": {
                "type": "string",
                "description": "Model the fork runs on. Omit to use the saved default model; a chosen model that is no longer available skips the step."
              }
            },
            "required": ["kind", "provider"]
          }
        ]
      },
      "FallbackChains": {
        "type": "object",
        "nullable": true,
        "description": "Per-harness fallback order, keyed by coding agent provider. Steps run top to bottom and the first is always a credential, the one a chat starts on. Null uses the built-in credential order with no fork steps. Credentials left out of a chain are never fallen back to; a chain that names no credential falls back to the built-in order. A member's chain replaces the organization's for that harness.",
        "additionalProperties": {"type": "array", "items": {"$ref": "#/components/schemas/FallbackStep"}}
      },
      "OrganizationPreferences": {
        "type": "object",
        "description": "Organization-wide preferences. Additional preference fields may be returned.",
        "properties": {
          "credential_fallbacks_enabled": {
            "type": "boolean",
            "default": true,
            "description": "Whether coding agents walk their fallback chain after authentication or quota failure. When false the first configured credential is used and failures stop the turn."
          },
          "fallback_chains": {"$ref": "#/components/schemas/FallbackChains"}
        },
        "required": ["credential_fallbacks_enabled"],
        "additionalProperties": true
      },
      "OrganizationPreferencesResponse": {
        "type": "object",
        "properties": {"preferences": {"$ref": "#/components/schemas/OrganizationPreferences"}},
        "required": ["preferences"]
      },
      "UpdateOrganizationPreferencesRequest": {
        "type": "object",
        "properties": {
          "preferences": {
            "type": "object",
            "properties": {
              "credential_fallbacks_enabled": {"type": "boolean"},
              "fallback_chains": {"$ref": "#/components/schemas/FallbackChains"}
            },
            "additionalProperties": true
          }
        },
        "required": ["preferences"]
      },
      "UpdateOrganizationPreferencesResponse": {
        "type": "object",
        "properties": {"success": {"type": "boolean"}, "preferences": {"$ref": "#/components/schemas/OrganizationPreferences"}},
        "required": ["success", "preferences"]
      },
      "ApiKeyCredentialRequest": {"type": "object", "properties": {"api_key": {"type": "string", "minLength": 1}}, "required": ["api_key"]},
      "OpenAICompatibleCredentialRequest": {
        "type": "object",
        "description": "Set base_url with an API key or exact Authorization header. When models_url is omitted, model discovery uses <base_url>/models.",
        "properties": {
          "api_key": {"type": "string", "minLength": 1},
          "base_url": {"type": "string", "format": "uri", "pattern": "^https://", "minLength": 1},
          "models_url": {
            "type": "string",
            "format": "uri",
            "pattern": "^https://",
            "minLength": 1,
            "description": "Optional model catalog URL. Defaults to <base_url>/models."
          },
          "authorization_header": {"type": "string", "minLength": 1, "description": "Exact value sent in the Authorization request header."},
          "preserve_authorization_header": {
            "type": "boolean",
            "default": false,
            "description": "Reuse the stored exact Authorization header while updating other credential fields."
          }
        },
        "anyOf": [
          {"required": ["api_key", "base_url"]},
          {"required": ["authorization_header", "base_url"]},
          {"required": ["preserve_authorization_header", "base_url"]}
        ]
      },
      "OpenAICompatibleCredentialStatus": {
        "allOf": [
          {"$ref": "#/components/schemas/ApiKeyCredentialStatus"},
          {
            "type": "object",
            "properties": {
              "baseUrl": {"type": "string", "format": "uri"},
              "modelsUrl": {"type": "string", "format": "uri"},
              "hasAuthorizationHeader": {"type": "boolean"}
            }
          }
        ]
      },
      "OpenAICompatibleUserCredentialStatus": {
        "allOf": [
          {"$ref": "#/components/schemas/OpenAICompatibleCredentialStatus"},
          {"type": "object", "properties": {"authorizationHeader": {"type": "string"}}}
        ]
      },
      "ApiKeyCredentialStatus": {
        "type": "object",
        "properties": {
          "hasCredentials": {"type": "boolean"},
          "credentialId": {"type": "string", "format": "uuid"},
          "apiKey": {"type": "string"},
          "lastFetchedAt": {"type": "string", "format": "date-time"}
        },
        "required": ["hasCredentials"]
      },
      "ApiKeyCredentialUploadResponse": {
        "type": "object",
        "properties": {"success": {"type": "boolean"}, "credentialId": {"type": "string", "format": "uuid"}},
        "required": ["success", "credentialId"]
      },
      "ApiKeyCredentialDeleteResponse": {"type": "object", "properties": {"success": {"type": "boolean"}}, "required": ["success"]},
      "GitLabServiceAccountCredentialRequest": {
        "type": "object",
        "properties": {
          "personal_access_token": {
            "type": "string",
            "minLength": 1,
            "writeOnly": true,
            "description": "GitLab service account personal access token with the `api` scope."
          }
        },
        "required": ["personal_access_token"]
      },
      "GitLabServiceAccountCredentialResponse": {
        "type": "object",
        "properties": {
          "success": {"type": "boolean"},
          "credentialId": {"type": "string", "format": "uuid"},
          "login": {"type": "string"}
        },
        "required": ["success", "credentialId", "login"]
      },
      "ModelCatalogResponse": {
        "type": "object",
        "properties": {
          "source": {"type": "string", "enum": ["aster", "openrouter", "opencode-go", "static", "openai-compatible", "ollama"]},
          "models": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {"type": "string"},
                "displayName": {"type": "string"},
                "description": {"type": "string"},
                "contextWindow": {"type": "integer", "minimum": 1},
                "capabilities": {"type": "array", "items": {"type": "string"}}
              },
              "required": ["id", "displayName"]
            }
          },
          "readOnly": {"type": "boolean"},
          "defaultModel": {
            "type": ["string", "null"],
            "description": "Default model ID, or null when explicit model selection is required."
          },
          "page": {"type": "integer"},
          "total": {"type": "integer"},
          "limit": {"type": "integer"},
          "totalPages": {"type": "integer"}
        },
        "required": ["source", "models", "page", "total", "limit", "totalPages"]
      },
      "UserProfile": {
        "type": "object",
        "properties": {
          "userId": {"type": "string", "format": "uuid"},
          "email": {"type": ["string", "null"], "format": "email"},
          "displayName": {"type": "string", "minLength": 1, "maxLength": 80},
          "avatarUrl": {"type": ["string", "null"], "format": "uri"}
        },
        "required": ["userId", "email", "displayName", "avatarUrl"]
      },
      "GetUserProfileResponse": {
        "type": "object",
        "properties": {"profile": {"$ref": "#/components/schemas/UserProfile"}},
        "required": ["profile"]
      },
      "AccountDeletionRequest": {
        "type": "object",
        "properties": {
          "requestedAt": {"type": "string", "format": "date-time"},
          "deleteBy": {"type": "string", "format": "date-time"}
        },
        "required": ["requestedAt", "deleteBy"]
      },
      "GetAccountDeletionResponse": {
        "type": "object",
        "properties": {"request": {"allOf": [{"$ref": "#/components/schemas/AccountDeletionRequest"}], "nullable": true}},
        "required": ["request"]
      },
      "UpdateUserProfileRequest": {
        "type": "object",
        "properties": {
          "displayName": {"type": "string", "minLength": 1, "maxLength": 80},
          "avatarUrl": {"type": ["string", "null"], "format": "uri"}
        },
        "required": ["displayName", "avatarUrl"]
      },
      "PullRequestActivityPoint": {
        "type": "object",
        "description": "Pull request cohort counts for a single time bucket, keyed by PR open date",
        "properties": {
          "bucket": {"type": "string", "description": "Bucket start as an ISO 8601 date (e.g. 2026-07-14)"},
          "prsOpened": {"type": "integer"},
          "prsMerged": {"type": "integer"},
          "prsClosed": {"type": "integer"}
        },
        "required": ["bucket", "prsOpened", "prsMerged", "prsClosed"]
      },
      "AnalyticsTotals": {
        "type": "object",
        "description": "Counted totals for one time window. Returned twice on an overview: once for the requested range, once for all time",
        "properties": {
          "workspacesCreated": {"type": "integer"},
          "prsOpened": {"type": "integer"},
          "prsMerged": {"type": "integer"},
          "prsClosed": {"type": "integer"},
          "computeMinutes": {"type": "number", "description": "Total metered agent runtime in minutes across all workspace sources"}
        },
        "required": ["workspacesCreated", "prsOpened", "prsMerged", "prsClosed", "computeMinutes"]
      },
      "AnalyticsSourceCount": {
        "type": "object",
        "description": "Count of workspaces created from a given source",
        "properties": {
          "source": {
            "type": "string",
            "description": "Workspace source (e.g. dashboard, api, automation, slack, linear, github, gitlab)"
          },
          "count": {"type": "integer"}
        },
        "required": ["source", "count"]
      },
      "AnalyticsUsagePoint": {
        "type": "object",
        "description": "Compute minutes by workspace source and inference tokens for a single time bucket",
        "properties": {
          "bucket": {"type": "string", "description": "Bucket start as an ISO 8601 date (e.g. 2026-07-14)"},
          "bySource": {
            "type": "object",
            "description": "Map of workspace source to compute minutes in this bucket",
            "additionalProperties": {"type": "number"}
          },
          "tokens": {"type": "integer", "description": "Inference tokens used in this bucket"}
        },
        "required": ["bucket", "bySource", "tokens"]
      },
      "AnalyticsWorkspaceCreationPoint": {
        "type": "object",
        "description": "Workspaces created by workspace source for a single time bucket",
        "properties": {
          "bucket": {"type": "string", "description": "Bucket start as an ISO 8601 date (e.g. 2026-07-14)"},
          "bySource": {
            "type": "object",
            "description": "Map of workspace source to workspaces created in this bucket",
            "additionalProperties": {"type": "integer"}
          }
        },
        "required": ["bucket", "bySource"]
      },
      "AnalyticsChatTurnBreakdown": {
        "type": "object",
        "description": "Ranked inference usage for one harness, model, or credential",
        "properties": {
          "key": {"type": "string"},
          "label": {"type": "string"},
          "seconds": {"type": "number"},
          "tokens": {"type": "integer"},
          "minutes": {"type": "number"},
          "workspaces": {"type": "integer"},
          "turns": {"type": "integer"},
          "credentialOwner": {"type": "string"},
          "credentialOwnerEmail": {"type": "string", "format": "email"},
          "credentialOwnerAvatarUrl": {"type": "string", "format": "uri"}
        },
        "required": ["key", "label", "seconds", "tokens", "minutes", "workspaces", "turns"]
      },
      "AnalyticsCallBreakdown": {
        "type": "object",
        "description": "Ranked count for one skill or MCP server",
        "properties": {"name": {"type": "string"}, "calls": {"type": "integer"}},
        "required": ["name", "calls"]
      },
      "AnalyticsChatTurnActivity": {
        "type": "object",
        "description": "Inference usage for an organization over the overview's requested range",
        "properties": {
          "totalSeconds": {"type": "number"},
          "agentProviders": {"type": "array", "items": {"$ref": "#/components/schemas/AnalyticsChatTurnBreakdown"}},
          "models": {"type": "array", "items": {"$ref": "#/components/schemas/AnalyticsChatTurnBreakdown"}},
          "credentials": {"type": "array", "items": {"$ref": "#/components/schemas/AnalyticsChatTurnBreakdown"}}
        },
        "required": ["totalSeconds", "agentProviders", "models", "credentials"]
      },
      "AnalyticsTurnUsageBreakdown": {
        "type": "object",
        "description": "Turn usage ranked by a named automation or environment",
        "properties": {
          "id": {"type": "string", "format": "uuid"},
          "name": {"type": "string"},
          "tokens": {"type": "integer"},
          "minutes": {"type": "number"},
          "workspaces": {"type": "integer"},
          "turns": {"type": "integer"}
        },
        "required": ["id", "name", "tokens", "minutes", "workspaces", "turns"]
      },
      "AnalyticsTurnUsage": {
        "type": "object",
        "description": "Turn usage ranked independently by automation and environment",
        "properties": {
          "automations": {"type": "array", "items": {"$ref": "#/components/schemas/AnalyticsTurnUsageBreakdown"}},
          "environments": {"type": "array", "items": {"$ref": "#/components/schemas/AnalyticsTurnUsageBreakdown"}}
        },
        "required": ["automations", "environments"]
      },
      "AnalyticsOverview": {
        "type": "object",
        "description": "Aggregated activity and usage metrics for an organization over a time range",
        "properties": {
          "bucket": {
            "type": "string",
            "enum": ["day", "week", "month"],
            "description": "Time bucket granularity of the returned series"
          },
          "start": {
            "type": "string",
            "format": "date-time",
            "description": "Inclusive start of the range as an ISO 8601 timestamp"
          },
          "end": {
            "type": "string",
            "format": "date-time",
            "description": "Exclusive end of the range as an ISO 8601 timestamp"
          },
          "points": {"type": "array", "items": {"$ref": "#/components/schemas/PullRequestActivityPoint"}},
          "rangeTotals": {"$ref": "#/components/schemas/AnalyticsTotals", "description": "Totals over the requested range"},
          "sources": {"type": "array", "items": {"$ref": "#/components/schemas/AnalyticsSourceCount"}},
          "workspaceCreations": {"type": "array", "items": {"$ref": "#/components/schemas/AnalyticsWorkspaceCreationPoint"}},
          "usage": {"type": "array", "items": {"$ref": "#/components/schemas/AnalyticsUsagePoint"}},
          "seats": {
            "type": "array",
            "description": "Per-seat leaderboard for the range, ranked by compute minutes. Includes every billable organization seat; seats with no activity in the range report zeroes and a null top source",
            "items": {"$ref": "#/components/schemas/AnalyticsSeatUsage"}
          },
          "chatTurns": {
            "$ref": "#/components/schemas/AnalyticsChatTurnActivity",
            "description": "Inference usage over the requested range, ranked by coding harness, model, and credential; each row includes token, workspace, minute, and turn totals"
          },
          "turnUsage": {
            "$ref": "#/components/schemas/AnalyticsTurnUsage",
            "description": "Turn usage over the requested range, ranked independently by automation and environment name"
          },
          "skillCalls": {
            "type": "array",
            "description": "Skill call counts over the requested range, ranked by skill name",
            "items": {"$ref": "#/components/schemas/AnalyticsCallBreakdown"}
          },
          "mcpCalls": {
            "type": "array",
            "description": "MCP call counts over the requested range, ranked by server name",
            "items": {"$ref": "#/components/schemas/AnalyticsCallBreakdown"}
          },
          "allTimeTotals": {
            "$ref": "#/components/schemas/AnalyticsTotals",
            "description": "The same totals over the organization's whole history, ignoring the requested range"
          }
        },
        "required": [
          "bucket",
          "start",
          "end",
          "points",
          "sources",
          "workspaceCreations",
          "usage",
          "seats",
          "rangeTotals",
          "allTimeTotals",
          "chatTurns",
          "turnUsage",
          "skillCalls",
          "mcpCalls"
        ]
      },
      "AnalyticsSeatDay": {
        "type": "object",
        "description": "One seat's compute minutes on a single day. Always daily, regardless of the request's `bucket`",
        "properties": {
          "bucket": {"type": "string", "format": "date", "description": "The day as YYYY-MM-DD"},
          "minutes": {"type": "integer", "description": "Compute minutes metered to this seat that day"}
        },
        "required": ["bucket", "minutes"]
      },
      "AnalyticsSeatUsage": {
        "type": "object",
        "description": "Usage metrics for a single billable organization seat over the range",
        "properties": {
          "seatId": {"type": "string", "format": "uuid", "description": "Unique identifier for the seat"},
          "userId": {
            "type": ["string", "null"],
            "format": "uuid",
            "description": "Unique identifier for the associated user, or null for an email-only seat"
          },
          "displayName": {"type": "string", "description": "Associated user's display name, or the seat email for an email-only seat"},
          "email": {"type": "string", "description": "Seat email address"},
          "avatarUrl": {
            "type": ["string", "null"],
            "description": "URL to the associated user's avatar image, or null for an email-only seat"
          },
          "computeMinutes": {"type": "number", "description": "Compute minutes attributed to the seat"},
          "prsOpened": {"type": "integer", "description": "Pull requests opened from the seat"},
          "prsMerged": {"type": "integer", "description": "Pull requests merged from the seat"},
          "topSource": {
            "type": ["string", "null"],
            "enum": ["api", "dashboard", "slack", "linear", "github", "gitlab", "automation", null],
            "description": "Workspace source the seat creates from most"
          },
          "workspacesCreated": {
            "type": "integer",
            "description": "Workspaces this seat created in the range, including any with no recorded source"
          },
          "sources": {
            "type": "array",
            "description": "Workspaces this seat created, grouped by source, highest first. Excludes workspaces with no recorded source",
            "items": {"$ref": "#/components/schemas/AnalyticsSourceCount"}
          },
          "activity": {
            "type": "array",
            "description": "Daily compute minutes, ascending by date. Always daily regardless of `bucket`. Days with no usage are omitted",
            "items": {"$ref": "#/components/schemas/AnalyticsSeatDay"}
          }
        },
        "required": [
          "seatId",
          "userId",
          "displayName",
          "email",
          "avatarUrl",
          "computeMinutes",
          "prsOpened",
          "prsMerged",
          "topSource",
          "workspacesCreated",
          "sources",
          "activity"
        ]
      },
      "Repository": {
        "type": "object",
        "description": "A repository available to the organization",
        "properties": {
          "id": {"type": "string", "format": "uuid", "description": "Unique identifier for the repository"},
          "name": {"type": "string", "description": "Repository name"},
          "url": {"type": "string", "format": "uri", "description": "URL to the repository"},
          "default_branch": {"type": "string", "description": "Default branch name (e.g. main)"}
        },
        "required": ["id", "name", "url", "default_branch"]
      },
      "PullRequest": {
        "type": "object",
        "description": "A pull request associated with a workspace",
        "properties": {
          "repository": {"type": "string", "description": "Repository name"},
          "number": {"type": "integer", "description": "Pull request number"},
          "url": {"type": "string", "format": "uri", "description": "URL to the pull request"}
        },
        "required": ["repository", "number", "url"]
      },
      "RepositoryReference": {
        "type": "object",
        "description": "A repository reference in workspace list items",
        "properties": {
          "id": {"type": "string", "format": "uuid", "description": "Repository ID"},
          "name": {"type": "string", "description": "Repository name"},
          "url": {"type": "string", "format": "uri", "description": "Repository URL"}
        },
        "required": ["id", "name", "url"]
      },
      "GitDiff": {
        "type": "object",
        "description": "Git diff statistics",
        "properties": {
          "added": {"type": "integer", "description": "Number of lines added"},
          "removed": {"type": "integer", "description": "Number of lines removed"},
          "full_diff": {"type": "string", "description": "Full diff content"}
        },
        "required": ["added", "removed", "full_diff"]
      },
      "RepositoryStatus": {
        "type": "object",
        "description": "Status of a repository within a workspace",
        "properties": {
          "repository": {"type": "string", "description": "Repository name"},
          "branch": {"type": "string", "description": "Current git branch"},
          "default_branch": {"type": "string", "description": "Default branch of the repository"},
          "pr_urls": {
            "type": "array",
            "items": {"type": "string", "format": "uri"},
            "description": "All pull request URLs the workspace has opened in this repository."
          },
          "start_hooks_completed": {"type": "boolean", "description": "Whether start hooks have finished executing"},
          "git_diff": {
            "oneOf": [{"$ref": "#/components/schemas/GitDiff"}, {"type": "null"}],
            "description": "Git diff statistics, if available"
          }
        },
        "required": ["repository", "branch", "default_branch", "pr_urls", "start_hooks_completed", "git_diff"]
      },
      "ReplicaActivity": {
        "type": "object",
        "description": "What the replica's agent is doing, as its chat shows it. Background tasks the agent will wake up for count as working.",
        "properties": {
          "state": {"type": "string", "enum": ["working", "waiting_for_input", "idle"]},
          "chat_id": {"type": ["string", "null"], "description": "The chat described: the requested one, or the most recently active"},
          "current_step": {"type": ["string", "null"], "description": "What the agent is doing now, such as `Running npm test`, while it is working"},
          "last_agent_message": {"type": ["string", "null"], "description": "The agent's latest message, cut to 2,000 characters"}
        },
        "required": ["state", "chat_id", "current_step", "last_agent_message"]
      },
      "ReplicaChat": {
        "type": "object",
        "description": "A chat session within a workspace",
        "properties": {
          "id": {"type": "string", "description": "Unique identifier for the chat"},
          "provider": {
            "type": "string",
            "description": "Coding agent provider for this chat",
            "enum": ["claude", "codex", "cursor", "muse", "opencode", "pi"]
          },
          "title": {"type": "string", "description": "Chat title"},
          "created_at": {"type": "string", "format": "date-time", "description": "When the chat was created"},
          "updated_at": {"type": "string", "format": "date-time", "description": "When the chat was last updated"},
          "processing": {
            "type": "boolean",
            "description": "Whether the chat is currently doing work — either processing a foreground message or running background/spawned-agent tasks"
          }
        },
        "required": ["id", "provider", "title", "created_at", "updated_at", "processing"]
      },
      "SlashCommand": {
        "type": "object",
        "description": "A slash command available in a chat composer",
        "properties": {
          "command": {"type": "string", "description": "Slash command name, including the leading slash"},
          "description": {"type": "string", "description": "Short description of what the command does"},
          "argument_hint": {"type": "string", "description": "Optional argument hint for the command"},
          "providers": {
            "type": "array",
            "description": "Coding agent providers that support this command",
            "items": {"type": "string", "enum": ["claude", "codex", "cursor", "muse", "opencode", "pi"]}
          }
        },
        "required": ["command", "description", "providers"]
      },
      "SlashCommandsResponse": {
        "type": "object",
        "description": "Available slash commands for a chat",
        "properties": {"commands": {"type": "array", "items": {"$ref": "#/components/schemas/SlashCommand"}}},
        "required": ["commands"]
      },
      "ReplicaEnvironment": {
        "type": "object",
        "description": "Environment configuration and status for a workspace",
        "properties": {
          "engine_version": {"type": "string", "description": "Version of the workspace engine"},
          "files_uploaded": {"type": "array", "items": {"type": "string"}, "description": "List of uploaded file names"},
          "env_vars_set": {
            "type": "array",
            "items": {"type": "string"},
            "description": "List of environment variable names that are set"
          },
          "skills_installed": {"type": "array", "items": {"type": "string"}, "description": "List of installed skill names"},
          "integrations": {
            "type": "object",
            "properties": {
              "github": {"type": "boolean"},
              "gitlab": {"type": "boolean"},
              "linear": {"type": "boolean"},
              "slack": {"type": "boolean"}
            },
            "required": ["github", "gitlab", "linear", "slack"],
            "description": "Integration connection statuses"
          },
          "coding_agents": {
            "type": "object",
            "properties": {
              "claude": {
                "type": "object",
                "properties": {"available": {"type": "boolean"}, "auth_method": {"type": "string"}},
                "required": ["available", "auth_method"]
              },
              "codex": {
                "type": "object",
                "properties": {"available": {"type": "boolean"}, "auth_method": {"type": "string"}},
                "required": ["available", "auth_method"]
              },
              "muse": {
                "type": "object",
                "properties": {"available": {"type": "boolean"}, "auth_method": {"type": "string"}},
                "required": ["available", "auth_method"]
              },
              "opencode": {
                "type": "object",
                "properties": {"available": {"type": "boolean"}, "auth_method": {"type": "string"}},
                "required": ["available", "auth_method"]
              },
              "pi": {
                "type": "object",
                "properties": {"available": {"type": "boolean"}, "auth_method": {"type": "string"}},
                "required": ["available", "auth_method"]
              },
              "cursor": {
                "type": "object",
                "properties": {"available": {"type": "boolean"}, "auth_method": {"type": "string"}},
                "required": ["available", "auth_method"]
              }
            },
            "required": ["claude", "codex", "cursor", "muse", "opencode", "pi"],
            "description": "Available coding agents and their authentication methods"
          },
          "hooks": {
            "type": "object",
            "properties": {
              "environment_warm_hook": {
                "type": "object",
                "description": "Warm hooks of the environment and the environments it builds on, run as one step",
                "properties": {"status": {"type": "string"}, "details": {"type": ["string", "null"]}},
                "required": ["status", "details"]
              },
              "repositories": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "repository_name": {"type": "string"},
                    "warm_hook": {"type": "string"},
                    "start_hook": {"type": "string"}
                  },
                  "required": ["repository_name", "warm_hook", "start_hook"]
                }
              }
            },
            "required": ["environment_warm_hook", "repositories"],
            "description": "Hook configuration and status"
          },
          "last_updated_at": {"type": "string", "format": "date-time", "description": "When the environment was last updated"}
        },
        "required": [
          "engine_version",
          "files_uploaded",
          "env_vars_set",
          "skills_installed",
          "integrations",
          "coding_agents",
          "hooks",
          "last_updated_at"
        ]
      },
      "ReplicaListItem": {
        "type": "object",
        "description": "A workspace item in list responses",
        "properties": {
          "id": {"type": "string", "format": "uuid", "description": "Unique identifier for the workspace"},
          "name": {
            "type": "string",
            "description": "Human-readable name for the workspace. Must not contain whitespace.",
            "pattern": "^\\S+$"
          },
          "status": {
            "type": "string",
            "description": "Current status of the workspace",
            "enum": ["active", "sleeping", "archived", "preparing", "error"]
          },
          "source": {
            "type": "string",
            "description": "How the workspace was created",
            "enum": ["api", "dashboard", "slack", "linear", "github", "gitlab", "automation"]
          },
          "created_at": {"type": "string", "format": "date-time", "description": "Timestamp when the workspace was created"},
          "last_activity_at": {
            "type": ["string", "null"],
            "format": "date-time",
            "description": "Timestamp of the last activity on the workspace"
          },
          "repositories": {
            "type": "array",
            "items": {"$ref": "#/components/schemas/RepositoryReference"},
            "description": "Repositories associated with the workspace"
          },
          "pull_requests": {
            "type": "array",
            "items": {"$ref": "#/components/schemas/PullRequest"},
            "description": "Associated pull requests"
          }
        },
        "required": ["id", "name", "status", "source", "created_at", "last_activity_at", "repositories", "pull_requests"]
      },
      "WorkspaceListItem": {
        "type": "object",
        "description": "A workspace returned by the dashboard workspace list.",
        "properties": {
          "id": {"type": "string", "format": "uuid"},
          "name": {"type": "string"},
          "status": {"type": "string", "enum": ["active", "sleeping", "archived", "preparing", "error"]},
          "created_at": {"type": "string", "format": "date-time"},
          "last_activity_at": {"type": ["string", "null"], "format": "date-time"},
          "source_link": {
            "type": "object",
            "description": "Link back to the Slack thread or Linear issue that started the workspace. Omitted when the workspace was not started from Slack or Linear.",
            "properties": {
              "source": {"type": "string", "enum": ["slack", "linear"]},
              "url": {"type": "string", "format": "uri"},
              "label": {"type": "string", "description": "Display text, such as a Linear issue identifier."}
            },
            "required": ["source", "url", "label"]
          }
        },
        "required": ["id", "name", "status", "created_at", "last_activity_at"]
      },
      "CreateWorkspaceRequest": {
        "type": "object",
        "description": "Dashboard workspace creation request.",
        "properties": {
          "name": {"type": "string", "description": "Optional workspace name. A placeholder is generated when omitted."},
          "environment_id": {
            "type": "string",
            "format": "uuid",
            "description": "Environment whose repository binding and configuration the workspace uses."
          },
          "repository_branches": {
            "type": "object",
            "description": "Optional starting-branch overrides keyed by repository UUID. Every repository must belong to the selected environment. Omitted repositories use their configured default branch.",
            "propertyNames": {"type": "string", "format": "uuid"},
            "additionalProperties": {"type": "string", "minLength": 1, "maxLength": 255}
          },
          "credential": {
            "type": "object",
            "description": "Connected inference provider to use for this harness, retained on wake and credential refresh. Personal and organization credentials are validated against the authenticated user.",
            "properties": {
              "provider": {"type": "string", "enum": ["claude", "codex", "cursor", "muse", "opencode", "pi"]},
              "method": {
                "type": "string",
                "enum": [
                  "oauth",
                  "api_key",
                  "openai-compatible",
                  "ollama",
                  "foundry",
                  "bedrock",
                  "opencode-go",
                  "aster",
                  "openrouter",
                  "muse-oauth"
                ]
              },
              "scope": {"type": "string", "enum": ["org", "user"]}
            },
            "required": ["provider", "method", "scope"]
          },
          "config": {"$ref": "#/components/schemas/WorkspaceConfig"},
          "size": {"type": "string", "enum": ["small", "large", "ultra"]}
        },
        "required": ["environment_id"]
      },
      "CreateWorkspaceResponse": {
        "type": "object",
        "properties": {"workspace": {"$ref": "#/components/schemas/WorkspaceListItem"}},
        "required": ["workspace"]
      },
      "ListRepositoryBranchesResponse": {
        "type": "object",
        "properties": {
          "branches": {
            "type": "array",
            "description": "Up to 100 unique branch names matching the request.",
            "items": {"type": "string"}
          }
        },
        "required": ["branches"]
      },
      "WorkspaceRepository": {
        "type": "object",
        "description": "A repository associated with a workspace.",
        "properties": {
          "id": {"type": "string", "format": "uuid"},
          "workspace_id": {"type": "string", "format": "uuid"},
          "provider": {"type": "string", "enum": ["github", "gitlab"]},
          "name": {"type": "string"},
          "url": {"type": "string", "format": "uri"},
          "default_branch": {"type": "string"}
        },
        "required": ["id", "workspace_id", "provider", "name", "url", "default_branch"]
      },
      "WorkspacePullRequestDetailsRequest": {
        "type": "object",
        "properties": {"pr_urls": {"type": "array", "items": {"type": "string", "format": "uri"}, "maxItems": 20}},
        "required": ["pr_urls"]
      },
      "PullRequestChecksSummary": {
        "type": "object",
        "description": "Check counts across the pull request head commit, spanning both commit statuses and check runs.",
        "properties": {
          "total": {"type": "integer"},
          "passing": {"type": "integer"},
          "failing": {"type": "integer"},
          "pending": {"type": "integer"}
        },
        "required": ["total", "passing", "failing", "pending"]
      },
      "PullRequestCheck": {
        "type": "object",
        "description": "A provider-reported status or check run on the pull request head commit.",
        "properties": {
          "name": {"type": "string"},
          "status": {"type": "string", "enum": ["success", "failure", "pending"]},
          "status_label": {"type": "string"},
          "description": {"type": "string"},
          "url": {"type": "string", "format": "uri"},
          "required": {"type": "boolean", "const": true, "description": "Present when the base branch's protection or rulesets require this check."}
        },
        "required": ["name", "status"]
      },
      "PullRequestMergeRules": {
        "type": "object",
        "description": "The base branch's classic protection and rulesets combined, with the repository's merge settings.",
        "properties": {
          "required_approvals": {"type": "integer"},
          "approvals": {"type": "integer", "description": "Current approvals from people with write access."},
          "code_owner_review": {"type": "boolean"},
          "dismiss_stale_reviews": {"type": "boolean", "description": "Reported for rulesets only."},
          "merge_methods": {"type": "array", "items": {"type": "string", "enum": ["merge", "squash", "rebase"]}, "description": "Methods both the repository and the branch's rules allow."},
          "default_merge_method": {"type": "string", "enum": ["merge", "squash", "rebase"]},
          "auto_merge": {"type": "string", "enum": ["available", "enabled"], "nullable": true},
          "viewer_can_bypass": {"type": "boolean", "description": "Whether your GitHub account can merge without meeting the rules, on GitHub or with bypass_rules."}
        },
        "required": ["required_approvals", "approvals", "code_owner_review", "dismiss_stale_reviews", "merge_methods", "default_merge_method", "auto_merge", "viewer_can_bypass"]
      },
      "PullRequestStack": {
        "type": "object",
        "description": "GitHub stack metadata. Null for standalone GitHub pull requests and GitLab merge requests.",
        "properties": {
          "number": {"type": "integer"},
          "size": {"type": "integer"},
          "position": {"type": "integer", "minimum": 1, "description": "1-based order from the stack base to its top pull request."},
          "base_branch": {"type": "string"}
        },
        "required": ["number", "size", "position", "base_branch"]
      },
      "PullRequestDetails": {
        "type": "object",
        "properties": {
          "url": {"type": "string", "format": "uri"},
          "repo_name": {"type": "string"},
          "owner": {"type": "string"},
          "repo": {"type": "string"},
          "number": {"type": "integer"},
          "title": {"type": "string"},
          "state": {"type": "string", "enum": ["open", "merged", "closed", "draft"]},
          "author_login": {"type": "string", "nullable": true},
          "head_branch": {"type": "string"},
          "base_branch": {"type": "string"},
          "stack": {"allOf": [{"$ref": "#/components/schemas/PullRequestStack"}], "nullable": true},
          "mergeability": {
            "type": "string",
            "enum": ["mergeable", "blocked", "behind", "conflicts", "draft", "unknown"],
            "description": "Whether the code host will currently accept a merge. Mirrors GitHub's mergeable_state and GitLab's detailed_merge_status, so it captures branch protection outcomes that state and ciStatus cannot: blocked means a rule such as a required review is unsatisfied, behind means the branch is out of date with its base, and unknown means the host has not finished computing mergeability."
          },
          "merge_queue": {
            "type": "string",
            "enum": ["enabled", "queued"],
            "nullable": true,
            "description": "Set when the base branch merges through GitHub's merge queue; queued once this pull request is in it."
          },
          "ci_status": {"type": "string", "enum": ["success", "failure", "pending", "none"]},
          "additions": {
            "type": "integer",
            "nullable": true,
            "description": "Added lines, or null when the code host does not provide complete diff data."
          },
          "deletions": {
            "type": "integer",
            "nullable": true,
            "description": "Deleted lines, or null when the code host does not provide complete diff data."
          },
          "changed_files": {"type": "integer"},
          "comment_count": {"type": "integer"},
          "checks": {"$ref": "#/components/schemas/PullRequestChecksSummary"},
          "check_items": {
            "type": "array",
            "description": "Individual provider-reported checks and their current statuses.",
            "items": {"$ref": "#/components/schemas/PullRequestCheck"}
          },
          "merge_blockers": {
            "type": "array",
            "description": "Normalized reasons the code host currently blocks the merge.",
            "items": {
              "type": "string",
              "enum": [
                "review_required",
                "changes_requested",
                "unresolved_conversations",
                "required_checks",
                "merge_policy",
                "jira_association",
                "branch_protection"
              ]
            }
          },
          "merge_rules": {
            "allOf": [{"$ref": "#/components/schemas/PullRequestMergeRules"}],
            "description": "GitHub only. Absent when GitHub won't show Replicas the base branch's rules."
          },
          "can_approve": {
            "type": "boolean",
            "description": "Whether the requesting user's connected GitHub account can currently submit an approving review."
          },
          "updated_at": {"type": "string", "format": "date-time"}
        },
        "required": [
          "url",
          "repo_name",
          "owner",
          "repo",
          "number",
          "title",
          "state",
          "author_login",
          "head_branch",
          "base_branch",
          "stack",
          "mergeability",
          "merge_queue",
          "ci_status",
          "additions",
          "deletions",
          "changed_files",
          "comment_count",
          "checks",
          "can_approve",
          "updated_at"
        ]
      },
      "WorkspacePullRequestDetailsResponse": {
        "type": "object",
        "properties": {
          "pull_requests": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "url": {"type": "string", "format": "uri"},
                "details": {"allOf": [{"$ref": "#/components/schemas/PullRequestDetails"}], "nullable": true},
                "error": {"type": "string", "nullable": true}
              },
              "required": ["url", "details", "error"]
            }
          }
        },
        "required": ["pull_requests"]
      },
      "WorkspacePullRequestAction": {
        "type": "string",
        "enum": ["merge", "approve", "close", "convert_to_draft", "mark_ready_for_review"],
        "description": "A GitHub pull request lifecycle action."
      },
      "MergeWorkspacePullRequestRequest": {
        "type": "object",
        "properties": {
          "pr_url": {"type": "string", "format": "uri"},
          "merge_method": {
            "type": "string",
            "enum": ["merge", "squash", "rebase"],
            "description": "Defaults to merge_rules.default_merge_method. Ignored on merge queue branches, where the queue picks, unless bypassing rules."
          },
          "bypass_rules": {
            "type": "boolean",
            "description": "Merge right away, skipping any merge queue, when the pull request is blocked and merge_rules.viewer_can_bypass is true. Merges as your GitHub account, so it needs a personal API key with GitHub connected."
          }
        },
        "required": ["pr_url"]
      },
      "MergeWorkspacePullRequestResponse": {
        "type": "object",
        "properties": {
          "success": {"type": "boolean", "const": true},
          "queued": {"type": "boolean", "description": "True when the pull request joined the merge queue instead of merging right away."}
        },
        "required": ["success", "queued"]
      },
      "UpdateWorkspacePullRequestAction": {
        "type": "string",
        "enum": ["approve", "close", "convert_to_draft", "mark_ready_for_review"],
        "description": "The direct GitHub pull request action to perform."
      },
      "UpdateWorkspacePullRequestRequest": {
        "type": "object",
        "properties": {
          "pr_url": {"type": "string", "format": "uri"},
          "action": {"$ref": "#/components/schemas/UpdateWorkspacePullRequestAction"}
        },
        "required": ["pr_url", "action"]
      },
      "UpdateWorkspacePullRequestResponse": {"type": "object", "properties": {"success": {"type": "boolean", "const": true}}, "required": ["success"]},
      "WorkspacePullRequestState": {
        "type": "object",
        "description": "The latest pull request state associated with a workspace.",
        "properties": {
          "workspace_id": {"type": "string", "format": "uuid"},
          "status": {"type": "string", "enum": ["open", "closed", "merged", "draft"]},
          "url": {"type": "string", "format": "uri", "nullable": true},
          "provider_pr_number": {"type": "integer"},
          "head_branch": {"type": "string", "nullable": true}
        },
        "required": ["workspace_id", "status", "url"]
      },
      "MobileTestingInstance": {
        "type": "object",
        "properties": {
          "id": {"type": "string"},
          "platform": {"type": "string", "enum": ["ios", "android"]},
          "state": {"type": "string", "enum": ["creating", "assigned", "ready"]},
          "model": {"type": ["string", "null"]},
          "endpointWebSocketUrl": {"type": ["string", "null"], "format": "uri"},
          "signedStreamUrl": {"type": ["string", "null"], "format": "uri"},
          "token": {"type": ["string", "null"]}
        },
        "required": ["id", "platform", "state", "model", "endpointWebSocketUrl", "signedStreamUrl", "token"]
      },
      "ListMobileTestingInstancesResponse": {
        "type": "object",
        "properties": {
          "enabled": {"type": "boolean"},
          "instances": {"type": "array", "items": {"$ref": "#/components/schemas/MobileTestingInstance"}}
        },
        "required": ["enabled", "instances"]
      },
      "WorkspaceContributor": {
        "type": "object",
        "description": "A user who has sent messages in a workspace.",
        "properties": {
          "user_id": {"type": "string", "format": "uuid"},
          "email": {"type": "string"},
          "display_name": {"type": "string"},
          "avatar_url": {"type": ["string", "null"], "format": "uri"}
        },
        "required": ["user_id", "email", "display_name", "avatar_url"]
      },
      "ListWorkspacesResponse": {
        "type": "object",
        "properties": {
          "workspaces": {"type": "array", "items": {"$ref": "#/components/schemas/WorkspaceListItem"}},
          "workspace_repositories": {"type": "array", "items": {"$ref": "#/components/schemas/WorkspaceRepository"}},
          "workspace_pull_requests": {"type": "array", "items": {"$ref": "#/components/schemas/WorkspacePullRequestState"}},
          "workspace_turn_completed_at": {
            "type": "object",
            "description": "Latest completed turn timestamp by workspace ID.",
            "additionalProperties": {"type": "string", "format": "date-time"}
          },
          "creator_names": {"type": "object", "additionalProperties": {"type": "string"}},
          "creator_avatar_urls": {"type": "object", "additionalProperties": {"type": "string", "format": "uri"}},
          "shared_with": {"type": "object", "additionalProperties": {"type": "array"}},
          "viewer_share_ids": {"type": "array", "items": {"type": "string", "format": "uuid"}},
          "contributors": {
            "type": "object",
            "description": "Users who have sent messages in each workspace, keyed by workspace ID. A workspace with no messages yet is absent; clients fall back to `creator_names` and `creator_avatar_urls`.",
            "additionalProperties": {"type": "array", "items": {"$ref": "#/components/schemas/WorkspaceContributor"}}
          },
          "viewer_contributed_at": {
            "type": "object",
            "description": "When the requesting user last sent a message in each workspace, keyed by workspace ID. A workspace they never messaged is absent.",
            "additionalProperties": {"type": "string", "format": "date-time"}
          },
          "total": {"type": "integer"},
          "page": {"type": "integer"},
          "limit": {"type": "integer"},
          "totalPages": {"type": "integer"}
        },
        "required": ["workspaces", "total", "page", "limit", "totalPages"]
      },
      "ReplicaDetails": {
        "type": "object",
        "description": "Detailed workspace information including engine status and environment",
        "allOf": [
          {"$ref": "#/components/schemas/ReplicaListItem"},
          {
            "type": "object",
            "properties": {
              "coding_agent": {
                "type": ["string", "null"],
                "description": "Currently active coding agent",
                "enum": ["claude", "codex", "cursor", "muse", "opencode", "pi", null]
              },
              "repository_statuses": {
                "type": "array",
                "items": {"$ref": "#/components/schemas/RepositoryStatus"},
                "description": "Status of each repository in the workspace"
              },
              "waking": {
                "type": ["boolean", "null"],
                "description": "Whether the workspace was just woken from a sleeping state. Retry in 30-90 seconds for full details."
              },
              "chats": {
                "type": "array",
                "items": {"$ref": "#/components/schemas/ReplicaChat"},
                "description": "Chat sessions in this workspace"
              },
              "environment": {
                "oneOf": [{"$ref": "#/components/schemas/ReplicaEnvironment"}, {"type": "null"}],
                "description": "Environment configuration. Only included when requested via include=environment."
              },
              "activity": {"$ref": "#/components/schemas/ReplicaActivity"}
            }
          }
        ]
      },
      "ImageContent": {
        "type": "object",
        "description": "An image attachment for messages",
        "properties": {
          "type": {"type": "string", "const": "image", "description": "Content type, always 'image'"},
          "source": {
            "type": "object",
            "description": "Image source data",
            "oneOf": [
              {
                "type": "object",
                "properties": {
                  "type": {"type": "string", "const": "base64"},
                  "media_type": {
                    "type": "string",
                    "enum": ["image/png", "image/jpeg", "image/gif", "image/webp"],
                    "description": "MIME type of the image"
                  },
                  "data": {"type": "string", "description": "Base64-encoded image data"}
                },
                "required": ["type", "media_type", "data"]
              },
              {
                "type": "object",
                "properties": {
                  "type": {"type": "string", "const": "url"},
                  "url": {"type": "string", "format": "uri", "description": "URL to the image"}
                },
                "required": ["type", "url"]
              }
            ]
          }
        },
        "required": ["type", "source"]
      },
      "CreateReplicaRequest": {
        "type": "object",
        "description": "Request body for creating a new workspace",
        "properties": {
          "name": {
            "type": "string",
            "description": "Human-readable name for the workspace. Must not contain whitespace.",
            "pattern": "^\\S+$"
          },
          "message": {"type": "string", "description": "Initial message to send to the coding agent"},
          "environment_id": {
            "type": "string",
            "format": "uuid",
            "description": "ID of the environment to use. The server clones the environment's repositories."
          },
          "coding_agent": {
            "type": "string",
            "description": "Coding agent to use. Defaults to your default agent, which is the first agent you connected until you choose another.",
            "enum": ["claude", "codex", "cursor", "muse", "opencode", "pi"]
          },
          "model": {"type": "string", "description": "Model ID. Defaults to the organization default for the coding agent."},
          "images": {
            "type": "array",
            "items": {"$ref": "#/components/schemas/ImageContent"},
            "description": "Images to attach to the initial message"
          },
          "lifecycle_policy": {
            "type": "string",
            "description": "Lifecycle policy for the workspace. Defaults to `delete_when_done` (`default` for a Mothership), which deletes the workspace once the agent finishes; pass `default` to keep it for follow-up messages or reading history afterwards.",
            "enum": ["default", "archive_when_done", "sleep_when_done", "delete_when_done", "delete_after_inactivity"],
            "default": "delete_when_done"
          },
          "config": {"$ref": "#/components/schemas/WorkspaceConfig"},
          "plan_mode": {
            "type": "boolean",
            "description": "Whether to run the initial message in plan mode. Leading `/plan` in the message is also detected and stripped."
          },
          "goal_mode": {
            "type": "boolean",
            "description": "Whether to set the initial message as the active goal (Claude Code and Codex). Leading `/goal` in the message is also detected and stripped."
          },
          "fast_mode": {
            "type": "boolean",
            "description": "Whether to run the initial message in fast mode. Leading `/fast` in the message is also detected and stripped."
          },
          "thinking_level": {
            "type": "string",
            "description": "Reasoning effort. `ultra` is for Codex and Muse Code; `ultracode` is for Claude Code. Defaults to the agent's default.",
            "enum": ["low", "medium", "high", "xhigh", "max", "ultra", "ultracode"]
          },
          "webhook_url": {
            "description": "URL that receives `replica.ready`, `replica.turn_completed`, `replica.deleted`, and `replica.error` events.",
            "oneOf": [{"type": "string", "format": "uri"}, {"$ref": "#/components/schemas/ReplicaWebhookConfig"}]
          },
          "size": {
            "type": "string",
            "description": "Compute size for this replica. `small` (2 vCPU, 8 GB memory), `large` (4 vCPU, 16 GB memory), or `ultra` (8 vCPU, 32 GB memory); see [Billing](https://docs.replicas.dev/admin/billing#rates) for per-size rates. Defaults to `small` when omitted.",
            "enum": ["small", "large", "ultra"]
          },
          "kind": {
            "type": "string",
            "description": "`mothership` creates a [Mothership](https://docs.replicas.dev/features/workspaces/motherships). Needs a personal API key, and `lifecycle_policy` defaults to `default`.",
            "enum": ["standard", "mothership"],
            "default": "standard"
          }
        },
        "required": ["name", "message", "environment_id"]
      },
      "ReplicaWebhookConfig": {
        "type": "object",
        "properties": {
          "url": {"type": "string", "format": "uri", "description": "HTTPS endpoint the platform POSTs JSON events to."},
          "secret": {
            "type": "string",
            "description": "Optional shared secret used to compute the `X-Replicas-Signature` header (`sha256=` HMAC of the raw JSON body)."
          }
        },
        "required": ["url"]
      },
      "CreateReplicaResponse": {
        "type": "object",
        "properties": {"replica": {"$ref": "#/components/schemas/ReplicaListItem"}},
        "required": ["replica"]
      },
      "GetReplicaResponse": {
        "type": "object",
        "properties": {"replica": {"$ref": "#/components/schemas/ReplicaDetails"}},
        "required": ["replica"]
      },
      "ListReplicasResponse": {
        "type": "object",
        "properties": {
          "replicas": {
            "type": "array",
            "items": {"$ref": "#/components/schemas/ReplicaListItem"},
            "description": "Array of workspaces"
          },
          "total": {"type": "integer", "description": "Total number of workspaces matching the filters"},
          "page": {"type": "integer", "description": "Current page number"},
          "limit": {"type": "integer", "description": "Number of items per page"},
          "total_pages": {"type": "integer", "description": "Total number of pages"}
        },
        "required": ["replicas", "total", "page", "limit", "total_pages"]
      },
      "DeleteReplicaResponse": {
        "type": "object",
        "properties": {"success": {"type": "boolean", "description": "Whether the deletion was successful"}},
        "required": ["success"]
      },
      "ArchiveWorkspaceResponse": {
        "type": "object",
        "properties": {"success": {"type": "boolean", "description": "Whether the workspace was archived"}},
        "required": ["success"]
      },
      "SleepWorkspaceResponse": {
        "type": "object",
        "properties": {"success": {"type": "boolean", "description": "Whether the sleep request was accepted"}},
        "required": ["success"]
      },
      "WakeWorkspaceResponse": {
        "type": "object",
        "properties": {"success": {"type": "boolean", "description": "Whether the wake or restore request was accepted"}},
        "required": ["success"]
      },
      "SshWebSocketTransport": {
        "type": "object",
        "properties": {
          "type": {"type": "string", "const": "websocket"},
          "url": {"type": "string", "format": "uri", "description": "Secure WebSocket URL for the SSH transport."},
          "headers": {
            "type": "object",
            "additionalProperties": {"type": "string"},
            "description": "Provider credentials sent only during the WebSocket upgrade."
          }
        },
        "required": ["type", "url"]
      },
      "SshTokenResponse": {
        "type": "object",
        "properties": {
          "token": {"type": "string", "description": "Short-lived token used as the SSH username."},
          "host": {"type": "string", "description": "Workspace SSH host."},
          "proxy_command": {"type": "string", "description": "Optional OpenSSH ProxyCommand for CLI clients."},
          "transport": {"$ref": "#/components/schemas/SshWebSocketTransport"}
        },
        "required": ["token", "host"]
      },
      "TerminalSession": {
        "type": "object",
        "properties": {
          "id": {"type": "string", "format": "uuid"},
          "title": {"type": "string"},
          "created_at": {"type": "string", "format": "date-time"},
          "exited": {"type": "boolean"},
          "exit_code": {"type": "integer"}
        },
        "required": ["id", "title", "created_at", "exited"]
      },
      "ListTerminalSessionsResponse": {
        "type": "object",
        "properties": {"sessions": {"type": "array", "items": {"$ref": "#/components/schemas/TerminalSession"}}},
        "required": ["sessions"]
      },
      "CreateTerminalSessionRequest": {
        "type": "object",
        "properties": {
          "cols": {"type": "integer", "minimum": 2, "maximum": 500},
          "rows": {"type": "integer", "minimum": 1, "maximum": 200}
        },
        "required": ["cols", "rows"]
      },
      "CreateTerminalSessionResponse": {
        "type": "object",
        "properties": {"session": {"$ref": "#/components/schemas/TerminalSession"}},
        "required": ["session"]
      },
      "WriteTerminalSessionRequest": {
        "type": "object",
        "properties": {
          "data": {"type": "string", "maxLength": 65536},
          "generation": {"type": "integer", "minimum": 0, "description": "Client generation used to reset input ordering."},
          "sequence": {"type": "integer", "minimum": 0, "description": "Zero-based batch sequence within the generation."}
        },
        "required": ["data", "generation", "sequence"]
      },
      "ResizeTerminalSessionRequest": {
        "type": "object",
        "properties": {
          "cols": {"type": "integer", "minimum": 2, "maximum": 500},
          "rows": {"type": "integer", "minimum": 1, "maximum": 200}
        },
        "required": ["cols", "rows"]
      },
      "TerminalMutationResponse": {"type": "object", "properties": {"success": {"type": "boolean", "const": true}}, "required": ["success"]},
      "DeletePreviewResponse": {
        "type": "object",
        "properties": {
          "success": {"type": "boolean", "description": "Whether the preview was deleted"},
          "port": {"type": "integer", "description": "Port number that was unregistered"}
        },
        "required": ["success", "port"]
      },
      "CreateChatRequest": {
        "type": "object",
        "description": "Request body for creating a new chat",
        "properties": {
          "provider": {
            "type": "string",
            "description": "Coding agent provider for this chat",
            "enum": ["claude", "codex", "cursor", "muse", "opencode", "pi"]
          },
          "id": {"type": "string", "format": "uuid", "description": "Optional client-generated chat ID."},
          "created_at": {"type": "string", "format": "date-time", "description": "Optional client-generated creation time."},
          "title": {"type": "string", "description": "Title for the chat"},
          "parent_chat_id": {"type": "string", "format": "uuid", "description": "Optional parent chat ID."},
          "client_request_id": {
            "type": "string",
            "description": "Opaque client-chosen id echoed back in the `chat.created` event, so clients doing optimistic UI can recognize their own create"
          }
        },
        "required": ["provider"]
      },
      "WorkspaceChat": {
        "type": "object",
        "properties": {
          "id": {"type": "string", "format": "uuid"},
          "provider": {"type": "string", "enum": ["claude", "codex", "cursor", "muse", "opencode", "pi"]},
          "model": {"type": "string", "description": "Selected model retained for future messages in this chat."},
          "title": {"type": "string"},
          "created_at": {"type": "string", "format": "date-time"},
          "updated_at": {"type": "string", "format": "date-time"},
          "processing": {"type": "boolean"},
          "parent_chat_id": {"type": ["string", "null"], "format": "uuid"},
          "last_message_text": {"type": ["string", "null"]},
          "fork": {
            "description": "Fork lineage and progress, when this chat was forked from another chat in the workspace",
            "oneOf": [{"$ref": "#/components/schemas/ChatFork"}, {"type": "null"}]
          }
        },
        "required": ["id", "provider", "title", "created_at", "updated_at", "processing", "parent_chat_id"]
      },
      "WorkspaceChatListResponse": {
        "type": "object",
        "properties": {
          "chats": {"type": "array", "items": {"$ref": "#/components/schemas/WorkspaceChat"}},
          "deletedChats": {"type": "array", "items": {"$ref": "#/components/schemas/WorkspaceChat"}}
        },
        "required": ["chats"]
      },
      "ChatFork": {
        "type": "object",
        "description": "Set on a chat that was forked from another chat in the same workspace",
        "properties": {
          "source": {
            "type": "object",
            "description": "The chat this one was forked from",
            "properties": {
              "chat_id": {"type": "string", "format": "uuid"},
              "provider": {"type": "string", "enum": ["claude", "codex", "cursor", "opencode", "pi"]},
              "title": {"type": "string"}
            },
            "required": ["chat_id", "provider", "title"]
          },
          "trigger": {
            "type": "string",
            "enum": ["manual", "auto"],
            "description": "`manual` for a requested fork, `auto` when the source harness hit its usage limit and the owner opted into automatic fallback"
          },
          "reason": {"type": "string", "enum": ["rate_limit", "out_of_credits"], "description": "Why an automatic fork happened"},
          "state": {
            "type": "string",
            "enum": ["preparing", "ready", "failed"],
            "description": "`preparing` while the transcript handoff is assembled; `processing` stays true until it leaves this state"
          },
          "error": {"type": "string", "description": "Failure reason when `state` is `failed`"},
          "started_at": {"type": "string", "format": "date-time"},
          "completed_at": {"type": "string", "format": "date-time"}
        },
        "required": ["source", "trigger", "state", "started_at"]
      },
      "ForkChatRequest": {
        "type": "object",
        "description": "Request body for continuing an existing chat on another coding agent harness",
        "properties": {
          "provider": {
            "type": "string",
            "enum": ["claude", "codex", "cursor", "opencode", "pi"],
            "description": "Harness to continue the chat on. It must have credentials connected in the workspace."
          },
          "model": {"type": "string", "description": "Model for the forked chat. Defaults to the harness default."},
          "thinking_level": {
            "type": "string",
            "enum": ["low", "medium", "high", "xhigh", "max", "ultra", "ultracode"],
            "description": "Reasoning effort for the forked chat"
          },
          "title": {
            "type": "string",
            "description": "Title for the forked chat. Defaults to a title derived from the source chat."
          },
          "message": {
            "type": "string",
            "description": "Optional first instruction for the new harness, sent alongside the inherited context. Empty or whitespace-only values preserve the default continuation behavior."
          },
          "id": {"type": "string", "format": "uuid", "description": "Optional client-generated chat ID."},
          "client_request_id": {"type": "string", "description": "Opaque client-chosen id echoed back in the `chat.created` event"},
          "enable_interactive_tools": {"type": "boolean", "description": "Allow the forked chat's first turn to use interactive tools"}
        },
        "required": ["provider"]
      },
      "ForkWorkspaceChatResponse": {"type": "object", "properties": {"chat": {"$ref": "#/components/schemas/WorkspaceChat"}}, "required": ["chat"]},
      "CreateWorkspaceChatResponse": {"type": "object", "properties": {"chat": {"$ref": "#/components/schemas/WorkspaceChat"}}, "required": ["chat"]},
      "SendWorkspaceChatMessageRequest": {
        "type": "object",
        "properties": {
          "message": {"type": "string"},
          "messageId": {"type": "string"},
          "submittedAt": {"type": "string", "format": "date-time"},
          "model": {"type": "string"},
          "images": {"type": "array", "items": {"$ref": "#/components/schemas/ImageContent"}},
          "canvasUploadIds": {
            "type": "array",
            "description": "Pending Canvas upload IDs returned by the upload endpoint that must be delivered before this message.",
            "items": {"type": "string"}
          },
          "planMode": {"type": "boolean"},
          "goalMode": {"type": "boolean"},
          "fastMode": {"type": "boolean"},
          "thinkingLevel": {"type": "string", "enum": ["low", "medium", "high", "xhigh", "max", "ultra", "ultracode"]}
        },
        "required": ["message"]
      },
      "SendWorkspaceChatMessageResponse": {
        "type": "object",
        "properties": {"messageId": {"type": "string"}, "queued": {"type": "boolean"}, "position": {"type": "integer"}},
        "required": ["messageId", "queued", "position"]
      },
      "SendDeferredWorkspaceMessageRequest": {
        "allOf": [
          {"$ref": "#/components/schemas/SendWorkspaceChatMessageRequest"},
          {
            "type": "object",
            "properties": {
              "provider": {"type": "string", "enum": ["claude", "codex", "cursor", "muse", "opencode", "pi"]},
              "chatId": {"type": "string", "format": "uuid"},
              "generateName": {"type": "boolean"}
            },
            "required": ["provider"]
          }
        ]
      },
      "SendDeferredWorkspaceMessageResponse": {
        "type": "object",
        "properties": {
          "status": {"type": "string", "const": "waking"},
          "chatId": {"type": "string", "format": "uuid"},
          "messageId": {"type": "string"}
        },
        "required": ["status", "chatId", "messageId"]
      },
      "SendReplicaMessageRequest": {
        "type": "object",
        "description": "Request body for sending a message to a workspace",
        "properties": {
          "message": {"type": "string", "description": "Message to send to the coding agent"},
          "coding_agent": {
            "type": "string",
            "description": "Coding agent to use. With `chat_id`, naming another agent than the chat's continues that chat on it, with the conversation handed over.",
            "enum": ["claude", "codex", "cursor", "muse", "opencode", "pi"]
          },
          "chat_id": {"type": "string", "description": "Target a specific chat session"},
          "model": {"type": "string", "description": "Model ID. Defaults to the organization default for the coding agent."},
          "images": {
            "type": "array",
            "items": {"$ref": "#/components/schemas/ImageContent"},
            "description": "Images to attach to the message"
          },
          "plan_mode": {
            "type": "boolean",
            "description": "Whether to run in plan mode. Leading `/plan` in the message is also detected and stripped."
          },
          "goal_mode": {
            "type": "boolean",
            "description": "Whether to set the message as the active goal (Claude Code and Codex). Leading `/goal` in the message is also detected and stripped."
          },
          "fast_mode": {
            "type": "boolean",
            "description": "Whether to run in fast mode. Leading `/fast` in the message is also detected and stripped."
          },
          "thinking_level": {
            "type": "string",
            "description": "Reasoning effort. `ultra` is for Codex and Muse Code; `ultracode` is for Claude Code. Defaults to the agent's default.",
            "enum": ["low", "medium", "high", "xhigh", "max", "ultra", "ultracode"]
          },
          "sender_email": {
            "type": "string",
            "description": "Email of the user sending this message. When the request is authenticated via dashboard auth, the server overrides this with the authenticated user's email."
          }
        },
        "required": ["message"]
      },
      "SendReplicaMessageResponse": {
        "type": "object",
        "description": "Response after sending a message to a workspace",
        "properties": {
          "status": {"type": "string", "description": "Status of the message delivery", "enum": ["sent", "queued", "waking"]},
          "message_id": {"type": ["string", "null"], "description": "Unique identifier for the sent message"},
          "position": {"type": ["integer", "null"], "description": "Queue position if status is 'queued'"},
          "chat_id": {"type": ["string", "null"], "description": "ID of the chat the message was sent to"}
        },
        "required": ["status", "message_id", "position", "chat_id"]
      },
      "OrganizationConversation": {
        "type": "object",
        "description": "A retained chat and its workspace context. Fetch its transcript with `GET /v1/replica/{id}/history?chat_id={chat_id}`.",
        "properties": {
          "chat_id": {"type": "string", "format": "uuid"},
          "workspace_id": {"type": "string", "format": "uuid"},
          "workspace_name": {"type": "string"},
          "workspace_status": {"type": "string", "enum": ["active", "sleeping", "archived", "preparing", "error"]},
          "workspace_source": {"type": "string", "enum": ["api", "dashboard", "slack", "linear", "github", "gitlab", "automation"]},
          "workspace_created_at": {"type": "string", "format": "date-time"},
          "workspace_user_id": {"type": ["string", "null"], "format": "uuid"},
          "workspace_creator_email": {"type": ["string", "null"], "format": "email"},
          "environment_id": {"type": ["string", "null"], "format": "uuid"},
          "provider": {"type": ["string", "null"], "enum": ["claude", "codex", "cursor", "muse", "opencode", "pi", null]},
          "title": {"type": ["string", "null"]},
          "created_at": {"type": "string", "format": "date-time"},
          "updated_at": {"type": "string", "format": "date-time"},
          "parent_chat_id": {"type": ["string", "null"], "format": "uuid"},
          "senders": {"type": "array", "items": {"$ref": "#/components/schemas/ChatMessageSender"}}
        },
        "required": [
          "chat_id",
          "workspace_id",
          "workspace_name",
          "workspace_status",
          "workspace_source",
          "workspace_created_at",
          "workspace_user_id",
          "workspace_creator_email",
          "environment_id",
          "provider",
          "title",
          "created_at",
          "updated_at",
          "parent_chat_id",
          "senders"
        ]
      },
      "ListOrganizationConversationsResponse": {
        "type": "object",
        "properties": {
          "conversations": {"type": "array", "items": {"$ref": "#/components/schemas/OrganizationConversation"}},
          "total": {
            "type": "integer",
            "description": "Matching conversations in non-deleted workspaces at request time. Restart the export if chats or workspaces are deleted or restored while paging."
          },
          "limit": {"type": "integer"},
          "next_cursor": {"type": ["string", "null"]}
        },
        "required": ["conversations", "total", "limit", "next_cursor"]
      },
      "HistoryEvent": {
        "type": "object",
        "description": "A conversation history event",
        "properties": {
          "timestamp": {"type": "string", "format": "date-time", "description": "When the event occurred"},
          "type": {
            "type": "string",
            "description": "Type of event (e.g., 'claude-user', 'claude-assistant', 'codex-user', 'cursor-assistant')"
          },
          "payload": {
            "$ref": "#/components/schemas/AgentEvent",
            "description": "Event payload — see AgentEvent for the full discriminated schema"
          }
        },
        "required": ["timestamp", "type", "payload"]
      },
      "ReadReplicaHistoryResponse": {
        "type": "object",
        "description": "Response containing paginated conversation history",
        "properties": {
          "thread_id": {"type": ["string", "null"], "description": "Thread/session ID"},
          "events": {
            "type": "array",
            "items": {"$ref": "#/components/schemas/HistoryEvent"},
            "description": "History events (paginated from the end)"
          },
          "removed_message_ids": {
            "type": "array",
            "items": {"type": "string"},
            "description": "IDs of canceled queued messages omitted from the history"
          },
          "events_start_index": {
            "type": "integer",
            "description": "Index of the first returned event within the full history. Pass it back as `before_event` to fetch the preceding page. Absent when the full history was returned."
          },
          "turns_start_index": {
            "type": "integer",
            "description": "Index of the first returned Codex transcript turn, used with `before_turn`. Present only when the response includes `codex_asp_transcript`."
          },
          "before_cursor": {
            "type": ["string", "null"],
            "description": "Opaque cursor for the next earlier page of events and Codex turns. Null when no earlier page exists."
          },
          "total": {
            "type": "integer",
            "description": "Total number of events when known; otherwise the number of events in this page"
          },
          "has_more": {"type": "boolean", "description": "Whether earlier events exist before this page"},
          "coding_agent": {
            "type": ["string", "null"],
            "description": "Currently active coding agent",
            "enum": ["claude", "codex", "cursor", "muse", "opencode", "pi", null]
          },
          "waking": {
            "type": ["boolean", "null"],
            "description": "Whether the workspace was just woken from a sleeping state. Retry in 30-90 seconds."
          },
          "codex_asp_transcript": {"type": ["object", "null"], "description": "Native Codex ASP transcript when available"},
          "senders": {
            "type": "array",
            "items": {"$ref": "#/components/schemas/ChatMessageSender"},
            "description": "Who sent each user message, for workspaces shared by several people."
          }
        },
        "required": ["thread_id", "events", "total", "has_more"],
        "example": {
          "thread_id": "thread_123",
          "events": [],
          "eventsStartIndex": 120,
          "turnsStartIndex": 0,
          "beforeCursor": "{\"mode\":\"range\",\"events\":\"1048576\",\"turns\":\"4096\"}",
          "total": 170,
          "has_more": true,
          "codexAspTranscript": {"turns": []},
          "senders": []
        }
      },
      "ChatMessageSender": {
        "type": "object",
        "description": "Records who sent a user message in a chat. Server-recorded from the authenticated user at send time.",
        "properties": {
          "message_id": {"type": "string", "description": "Identifier of the user message associated with this sender."},
          "sender_user_id": {"type": "string", "description": "Identifier of the user who sent the message."},
          "sender_email": {"type": "string", "description": "Email of the user who sent the message."},
          "recorded_at": {"type": "string", "format": "date-time", "description": "When the sender was recorded by the engine."}
        },
        "required": ["sender_user_id", "sender_email", "recorded_at"]
      },
      "QueuedMessageInfo": {
        "type": "object",
        "description": "A message waiting in a chat queue.",
        "properties": {
          "id": {"type": "string", "description": "Unique queued message ID."},
          "message": {"type": "string", "description": "Queued message text."},
          "queued_at": {"type": "string", "format": "date-time", "description": "When the message was queued."},
          "sender_user_id": {"type": "string", "description": "Identifier of the user who queued the message."},
          "sender_email": {"type": "string", "description": "Email of the user who queued the message."},
          "sender_display_name": {"type": "string", "description": "Display name of the user who queued the message."}
        },
        "required": ["id", "message", "queued_at"]
      },
      "ChatQueueResponse": {
        "type": "object",
        "description": "Queued messages for a chat.",
        "properties": {
          "chat_id": {"type": "string", "description": "Chat session ID."},
          "processing": {
            "type": "boolean",
            "description": "Whether the chat is currently doing work — either processing a foreground message or running background/spawned-agent tasks."
          },
          "queue": {"type": "array", "items": {"$ref": "#/components/schemas/QueuedMessageInfo"}}
        },
        "required": ["chat_id", "processing", "queue"]
      },
      "ReorderQueueRequest": {
        "type": "object",
        "description": "Request to move a queued message to a new position.",
        "properties": {
          "message_id": {"type": "string", "description": "Queued message ID."},
          "position": {"type": "integer", "description": "Zero-based target position."}
        },
        "required": ["message_id", "position"]
      },
      "UpdateQueuedMessageRequest": {
        "type": "object",
        "description": "Request to replace the text of a queued message.",
        "properties": {"message": {"type": "string", "minLength": 1, "description": "New message text."}},
        "required": ["message"]
      },
      "QueueMutationResponse": {
        "type": "object",
        "description": "Result of a queue mutation.",
        "properties": {
          "success": {"type": "boolean", "description": "Whether the queue mutation changed the queue."},
          "queue": {"type": "array", "items": {"$ref": "#/components/schemas/QueuedMessageInfo"}},
          "removed_message_ids": {
            "type": "array",
            "items": {"type": "string"},
            "description": "IDs of queued messages removed by the mutation."
          }
        },
        "required": ["success", "queue"]
      },
      "CanvasItemKind": {
        "type": "string",
        "enum": ["markdown", "mermaid", "html", "text", "image", "pdf", "docx", "video", "audio", "other"],
        "description": "The kind of Canvas item, inferred from its file extension."
      },
      "UpdateTextFileRequest": {
        "type": "object",
        "properties": {
          "content": {"type": "string", "description": "Complete replacement text."},
          "expected_revision": {
            "type": "string",
            "description": "SHA-256 revision returned when the file was read.",
            "pattern": "^[a-f0-9]{64}$"
          }
        },
        "required": ["content", "expected_revision"]
      },
      "RepoFileContentResponse": {
        "type": "object",
        "description": "Repository file content and metadata. Editable text files include content and revision; supported binary previews may include base64 and mimeType.",
        "properties": {
          "repoName": {"type": "string"},
          "path": {"type": "string"},
          "content": {"type": ["string", "null"]},
          "language": {"type": ["string", "null"]},
          "sizeBytes": {"type": "integer", "minimum": 0},
          "binary": {"type": "boolean"},
          "tooLarge": {"type": "boolean"},
          "base64": {"type": "string"},
          "mimeType": {"type": "string"},
          "revision": {
            "type": "string",
            "description": "SHA-256 revision to pass as expectedRevision when saving editable text.",
            "pattern": "^[a-f0-9]{64}$"
          },
          "unsupported": {"type": "boolean"}
        },
        "required": ["repoName", "path", "content", "language", "sizeBytes", "binary", "tooLarge"]
      },
      "RepoSymbolLocation": {
        "type": "object",
        "properties": {
          "repoName": {"type": "string"},
          "path": {"type": "string", "description": "Repository-relative file path."},
          "line": {"type": "integer", "minimum": 1},
          "character": {"type": "integer", "minimum": 0},
          "endCharacter": {"type": "integer", "minimum": 0},
          "preview": {"type": "string"}
        },
        "required": ["repoName", "path", "line", "character", "endCharacter", "preview"]
      },
      "RepoSymbolResponse": {
        "type": "object",
        "properties": {
          "symbol": {"type": "string"},
          "detail": {"type": ["string", "null"]},
          "documentation": {"type": ["string", "null"]},
          "locations": {"type": "array", "items": {"$ref": "#/components/schemas/RepoSymbolLocation"}},
          "provider": {"type": "string", "enum": ["language-server", "workspace"]}
        },
        "required": ["symbol", "detail", "documentation", "locations", "provider"]
      },
      "UpdateTextFileResponse": {
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "saved": {"type": "boolean", "const": true},
              "revision": {"type": "string", "pattern": "^[a-f0-9]{64}$"},
              "size_bytes": {"type": "integer", "minimum": 0}
            },
            "required": ["saved", "revision", "size_bytes"]
          },
          {
            "type": "object",
            "properties": {
              "saved": {"type": "boolean", "const": false},
              "current": {
                "type": "object",
                "properties": {
                  "content": {"type": "string"},
                  "revision": {"type": "string", "pattern": "^[a-f0-9]{64}$"},
                  "size_bytes": {"type": "integer", "minimum": 0}
                },
                "required": ["content", "revision", "size_bytes"]
              }
            },
            "required": ["saved", "current"]
          }
        ]
      },
      "UploadWorkspaceCanvasItemResponse": {
        "type": "object",
        "description": "A Canvas upload accepted immediately or queued until the workspace is active.",
        "properties": {
          "filePath": {
            "type": "string",
            "description": "Canvas display path for the uploaded file.",
            "example": "~/.replicas/canvas/report.pdf"
          },
          "originalName": {"type": "string", "description": "Normalized Canvas-relative file name.", "example": "report.pdf"},
          "sizeBytes": {"type": "integer", "minimum": 0},
          "uploadId": {
            "type": "string",
            "description": "Present when the upload was queued. Pass it in the related message's `canvasUploadIds`."
          }
        },
        "required": ["filePath", "originalName", "sizeBytes"]
      },
      "MediaKind": {
        "type": "string",
        "enum": ["image", "video", "audio", "html"],
        "description": "The kind of uploaded workspace media. HTML media is rendered as a sandboxed page."
      },
      "MediaPresignedUrlResponse": {
        "type": "object",
        "description": "A short-lived object storage URL for downloading or previewing a media item.",
        "properties": {"url": {"type": "string", "format": "uri"}, "expires_in_seconds": {"type": "integer", "minimum": 1}},
        "required": ["url", "expires_in_seconds"]
      },
      "CanvasItem": {
        "type": "object",
        "description": "An entry returned by `list_replica_canvas_items`.",
        "properties": {
          "filename": {
            "type": "string",
            "description": "The Canvas-relative file path, including nested folders.",
            "example": "reports/q3/summary.md"
          },
          "kind": {"$ref": "#/components/schemas/CanvasItemKind"},
          "size_bytes": {"type": "integer", "description": "File size in bytes, measured at list time."}
        },
        "required": ["filename", "kind", "size_bytes"]
      },
      "CanvasListResponse": {
        "type": "object",
        "description": "List of items the agent has dropped into the Canvas.",
        "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/CanvasItem"}}},
        "required": ["items"]
      },
      "CanvasContentResponse": {
        "type": "object",
        "description": "A single Canvas item's content. Text kinds populate `content`; binary kinds populate `base64`. Items over the 5 MB preview cap return `tooLarge: true` with neither payload populated.",
        "properties": {
          "filename": {
            "type": "string",
            "description": "The Canvas-relative file path, including nested folders.",
            "example": "reports/q3/summary.md"
          },
          "kind": {"$ref": "#/components/schemas/CanvasItemKind"},
          "size_bytes": {"type": "integer"},
          "mime_type": {
            "type": "string",
            "description": "MIME type to render the content with (e.g. `text/markdown; charset=utf-8`, `image/png`)."
          },
          "content": {"type": "string", "description": "UTF-8 text for `markdown` / `mermaid` / `html` / `text` kinds."},
          "base64": {"type": "string", "description": "Base64 payload for `image` / `pdf` / `docx` / `video` / `audio` / `other` kinds."},
          "too_large": {"type": "boolean", "description": "Present and `true` when the file exceeded the engine's preview size cap."},
          "revision": {
            "type": "string",
            "description": "SHA-256 revision to pass as expectedRevision when saving editable text.",
            "pattern": "^[a-f0-9]{64}$"
          }
        },
        "required": ["filename", "kind", "size_bytes", "mime_type"]
      },
      "HooksResponse": {
        "type": "object",
        "description": "Hook execution logs for a workspace",
        "properties": {
          "warm_hooks": {
            "type": "object",
            "properties": {"logs": {"type": "array", "items": {"$ref": "#/components/schemas/WarmHookLogEntry"}}},
            "required": ["logs"]
          },
          "start_hooks": {
            "type": "object",
            "properties": {"logs": {"type": "array", "items": {"$ref": "#/components/schemas/StartHookLogEntry"}}},
            "required": ["logs"]
          }
        },
        "required": ["warm_hooks", "start_hooks"]
      },
      "WarmHookLogEntry": {
        "type": "object",
        "description": "A warm hook execution log entry. Note: fields use camelCase as they are passed through from the engine.",
        "properties": {
          "hook_type": {"type": "string", "description": "Type of hook", "enum": ["environment", "repository"]},
          "hook_name": {"type": "string", "description": "Name of the hook"},
          "hook_script": {"type": "string", "description": "Script that was executed"},
          "output": {
            "type": "string",
            "description": "Hook execution output. When `output_truncated` is true, this is a preview of up to ~100,000 characters of the full stored log; the complete log can be retrieved via the dashboard full-log endpoint."
          },
          "output_truncated": {"type": "boolean", "description": "Whether `output` has been truncated to a preview."},
          "output_total_chars": {
            "type": "integer",
            "description": "Total character length of the full stored log (regardless of whether `output` is truncated)."
          },
          "exit_code": {"type": "integer", "description": "Exit code of the hook"},
          "timed_out": {"type": "boolean", "description": "Whether the hook timed out"},
          "executed_at": {"type": "string", "format": "date-time", "description": "When the hook was executed"}
        },
        "required": [
          "hook_type",
          "hook_name",
          "hook_script",
          "output",
          "output_truncated",
          "output_total_chars",
          "exit_code",
          "timed_out",
          "executed_at"
        ]
      },
      "StartHookLogEntry": {
        "type": "object",
        "description": "A start hook execution log entry. Note: fields use camelCase as they are passed through from the engine.",
        "properties": {
          "hook_type": {
            "type": "string",
            "description": "Type of start hook. `environment` is the workspace-level start hook configured on the environment; `repository` is a per-repo start hook from replicas.json/yaml.",
            "enum": ["environment", "repository"]
          },
          "hook_name": {
            "type": "string",
            "description": "Identifier for the hook. For `repository` hooks this is the repository name; for the `environment` hook it is the literal string `environment`."
          },
          "repo_name": {
            "type": "string",
            "description": "Deprecated: use `hook_name` instead. Equals `hook_name` for repository hooks and the literal `environment` for the environment hook."
          },
          "hook_commands": {"type": "array", "items": {"type": "string"}, "description": "Commands that were executed"},
          "output": {
            "type": "string",
            "description": "Hook execution output. When `output_truncated` is true, this is a preview of up to ~100,000 characters of the full stored log; the complete log can be retrieved via the dashboard full-log endpoint."
          },
          "output_truncated": {"type": "boolean", "description": "Whether `output` has been truncated to a preview."},
          "output_total_chars": {
            "type": "integer",
            "description": "Total character length of the full stored log (regardless of whether `output` is truncated)."
          },
          "exit_code": {"type": "integer", "description": "Exit code of the hook"},
          "timed_out": {"type": "boolean", "description": "Whether the hook timed out"},
          "executed_at": {"type": "string", "format": "date-time", "description": "When the hook was executed"}
        },
        "required": [
          "hook_type",
          "hook_name",
          "repo_name",
          "hook_commands",
          "output",
          "output_truncated",
          "output_total_chars",
          "exit_code",
          "timed_out",
          "executed_at"
        ]
      },
      "EngineEvent": {
        "type": "object",
        "description": "A real-time event from the workspace engine. All events share a common envelope with `id`, `ts`, `type`, and `payload` fields, plus an optional integer `seq`: the event's position in the stream for the current engine boot. The `type` field discriminates between event variants.",
        "oneOf": [
          {
            "title": "engine.stream.opened",
            "type": "object",
            "description": "The first event on every stream. `resumed` is true when the events after the request's `Last-Event-ID` follow, and false when some may have been missed: a new engine boot, a gap older than the engine keeps, or no `Last-Event-ID`.",
            "properties": {
              "id": {"type": "string"},
              "ts": {"type": "string", "format": "date-time"},
              "type": {"type": "string", "const": "engine.stream.opened"},
              "payload": {
                "type": "object",
                "properties": {
                  "epoch": {"type": "string", "description": "Identifies the engine boot"},
                  "seq": {"type": "integer", "description": "The latest event position when the stream opened"},
                  "resumed": {"type": "boolean"}
                },
                "required": ["epoch", "seq", "resumed"]
              }
            },
            "required": ["id", "ts", "type", "payload"]
          },
          {
            "title": "engine.ready",
            "type": "object",
            "description": "Engine initialization complete.",
            "properties": {
              "id": {"type": "string", "description": "Unique event ID"},
              "ts": {"type": "string", "format": "date-time", "description": "ISO 8601 timestamp"},
              "type": {"type": "string", "const": "engine.ready"},
              "payload": {
                "type": "object",
                "properties": {"version": {"type": "string", "description": "Engine protocol version", "example": "v1"}},
                "required": ["version"]
              }
            },
            "required": ["id", "ts", "type", "payload"]
          },
          {
            "title": "engine.status.changed",
            "type": "object",
            "description": "Engine status snapshot changed (uptime, active sessions, chat counts, etc.).",
            "properties": {
              "id": {"type": "string"},
              "ts": {"type": "string", "format": "date-time"},
              "type": {"type": "string", "const": "engine.status.changed"},
              "payload": {
                "type": "object",
                "properties": {"status": {"$ref": "#/components/schemas/EngineStatusSnapshot"}},
                "required": ["status"]
              }
            },
            "required": ["id", "ts", "type", "payload"]
          },
          {
            "title": "repo.discovered",
            "type": "object",
            "description": "New repositories discovered in the workspace.",
            "properties": {
              "id": {"type": "string"},
              "ts": {"type": "string", "format": "date-time"},
              "type": {"type": "string", "const": "repo.discovered"},
              "payload": {
                "type": "object",
                "properties": {"repos": {"type": "array", "items": {"$ref": "#/components/schemas/EngineRepoState"}}},
                "required": ["repos"]
              }
            },
            "required": ["id", "ts", "type", "payload"]
          },
          {
            "title": "repo.status.changed",
            "type": "object",
            "description": "Repository status changed (branch, diff, PR URL, start hooks status).",
            "properties": {
              "id": {"type": "string"},
              "ts": {"type": "string", "format": "date-time"},
              "type": {"type": "string", "const": "repo.status.changed"},
              "payload": {
                "type": "object",
                "properties": {"repos": {"type": "array", "items": {"$ref": "#/components/schemas/EngineRepoState"}}},
                "required": ["repos"]
              }
            },
            "required": ["id", "ts", "type", "payload"]
          },
          {
            "title": "chat.created",
            "type": "object",
            "description": "A new chat session was created.",
            "properties": {
              "id": {"type": "string"},
              "ts": {"type": "string", "format": "date-time"},
              "type": {"type": "string", "const": "chat.created"},
              "payload": {
                "type": "object",
                "properties": {
                  "chat": {"$ref": "#/components/schemas/EngineChatSummary"},
                  "clientRequestId": {
                    "type": "string",
                    "description": "Echo of the `clientRequestId` from the create request, if one was provided"
                  }
                },
                "required": ["chat"]
              }
            },
            "required": ["id", "ts", "type", "payload"]
          },
          {
            "title": "chat.updated",
            "type": "object",
            "description": "A chat session was updated (e.g. title or processing state changed).",
            "properties": {
              "id": {"type": "string"},
              "ts": {"type": "string", "format": "date-time"},
              "type": {"type": "string", "const": "chat.updated"},
              "payload": {
                "type": "object",
                "properties": {"chat": {"$ref": "#/components/schemas/EngineChatSummary"}},
                "required": ["chat"]
              }
            },
            "required": ["id", "ts", "type", "payload"]
          },
          {
            "title": "chat.deleted",
            "type": "object",
            "description": "A chat session was deleted.",
            "properties": {
              "id": {"type": "string"},
              "ts": {"type": "string", "format": "date-time"},
              "type": {"type": "string", "const": "chat.deleted"},
              "payload": {
                "type": "object",
                "properties": {"chatId": {"type": "string", "description": "ID of the deleted chat"}},
                "required": ["chatId"]
              }
            },
            "required": ["id", "ts", "type", "payload"]
          },
          {
            "title": "chat.turn.accepted",
            "type": "object",
            "description": "A message was accepted and queued for processing.",
            "properties": {
              "id": {"type": "string"},
              "ts": {"type": "string", "format": "date-time"},
              "type": {"type": "string", "const": "chat.turn.accepted"},
              "payload": {
                "type": "object",
                "properties": {
                  "chatId": {"type": "string", "description": "Chat session ID"},
                  "messageId": {"type": "string", "description": "Unique message ID"},
                  "queued": {
                    "type": "boolean",
                    "description": "Whether the message was queued (true) or processing immediately (false)"
                  },
                  "position": {"type": "integer", "description": "Position in the queue (0 if processing immediately)"}
                },
                "required": ["chatId", "messageId", "queued", "position"]
              }
            },
            "required": ["id", "ts", "type", "payload"]
          },
          {
            "title": "chat.turn.started",
            "type": "object",
            "description": "The coding agent started processing a message.",
            "properties": {
              "id": {"type": "string"},
              "ts": {"type": "string", "format": "date-time"},
              "type": {"type": "string", "const": "chat.turn.started"},
              "payload": {
                "type": "object",
                "properties": {
                  "chatId": {"type": "string", "description": "Chat session ID"},
                  "messageId": {"type": "string", "description": "Message being processed"},
                  "sender": {"$ref": "#/components/schemas/ChatMessageSender"},
                  "event": {"$ref": "#/components/schemas/AgentEvent"}
                },
                "required": ["chatId", "messageId"]
              }
            },
            "required": ["id", "ts", "type", "payload"]
          },
          {
            "title": "chat.turn.delta",
            "type": "object",
            "description": "A streaming delta from the coding agent (tool calls, text output, etc.).",
            "properties": {
              "id": {"type": "string"},
              "ts": {"type": "string", "format": "date-time"},
              "type": {"type": "string", "const": "chat.turn.delta"},
              "payload": {
                "type": "object",
                "properties": {
                  "chatId": {"type": "string", "description": "Chat session ID"},
                  "messageId": {"type": "string", "description": "Message being processed"},
                  "event": {"$ref": "#/components/schemas/AgentEvent"}
                },
                "required": ["chatId", "event"]
              }
            },
            "required": ["id", "ts", "type", "payload"]
          },
          {
            "title": "chat.turn.completed",
            "type": "object",
            "description": "The coding agent finished processing a message. Check `payload.processing` to determine whether another queued message will start next.",
            "properties": {
              "id": {"type": "string"},
              "ts": {"type": "string", "format": "date-time"},
              "type": {"type": "string", "const": "chat.turn.completed"},
              "payload": {
                "type": "object",
                "properties": {
                  "chatId": {"type": "string", "description": "Chat session ID"},
                  "isComplete": {
                    "type": "boolean",
                    "description": "Whether the turn completed fully (false if interrupted or errored)"
                  },
                  "processing": {
                    "type": "boolean",
                    "description": "Whether work continues after this turn: another queued message starts next, or Claude background tasks are still running. A final chat.turn.completed with processing false follows once they finish"
                  }
                },
                "required": ["chatId", "isComplete"]
              }
            },
            "required": ["id", "ts", "type", "payload"]
          },
          {
            "title": "chat.interrupted",
            "type": "object",
            "description": "A chat turn was interrupted.",
            "properties": {
              "id": {"type": "string"},
              "ts": {"type": "string", "format": "date-time"},
              "type": {"type": "string", "const": "chat.interrupted"},
              "payload": {
                "type": "object",
                "properties": {
                  "chatId": {"type": "string", "description": "Chat session ID"},
                  "interrupted": {"type": "boolean", "description": "Whether the interruption was successful"},
                  "queue": {"type": "array", "items": {"type": "string"}, "description": "Remaining message IDs in the queue"}
                },
                "required": ["chatId", "interrupted", "queue"]
              }
            },
            "required": ["id", "ts", "type", "payload"]
          },
          {
            "title": "hooks.started",
            "type": "object",
            "description": "Hooks started executing.",
            "properties": {
              "id": {"type": "string"},
              "ts": {"type": "string", "format": "date-time"},
              "type": {"type": "string", "const": "hooks.started"},
              "payload": {
                "type": "object",
                "properties": {
                  "running": {"type": "boolean", "description": "Whether hooks are currently running"},
                  "completed": {"type": "boolean", "description": "Whether hooks have completed"}
                },
                "required": ["running", "completed"]
              }
            },
            "required": ["id", "ts", "type", "payload"]
          },
          {
            "title": "hooks.progress",
            "type": "object",
            "description": "Hooks execution progress update.",
            "properties": {
              "id": {"type": "string"},
              "ts": {"type": "string", "format": "date-time"},
              "type": {"type": "string", "const": "hooks.progress"},
              "payload": {
                "type": "object",
                "properties": {"running": {"type": "boolean"}, "completed": {"type": "boolean"}},
                "required": ["running", "completed"]
              }
            },
            "required": ["id", "ts", "type", "payload"]
          },
          {
            "title": "hooks.completed",
            "type": "object",
            "description": "Hooks completed successfully.",
            "properties": {
              "id": {"type": "string"},
              "ts": {"type": "string", "format": "date-time"},
              "type": {"type": "string", "const": "hooks.completed"},
              "payload": {
                "type": "object",
                "properties": {"running": {"type": "boolean"}, "completed": {"type": "boolean"}},
                "required": ["running", "completed"]
              }
            },
            "required": ["id", "ts", "type", "payload"]
          },
          {
            "title": "hooks.failed",
            "type": "object",
            "description": "Hooks execution failed.",
            "properties": {
              "id": {"type": "string"},
              "ts": {"type": "string", "format": "date-time"},
              "type": {"type": "string", "const": "hooks.failed"},
              "payload": {
                "type": "object",
                "properties": {"running": {"type": "boolean"}, "completed": {"type": "boolean"}},
                "required": ["running", "completed"]
              }
            },
            "required": ["id", "ts", "type", "payload"]
          },
          {
            "title": "hooks.status",
            "type": "object",
            "description": "Current hooks status snapshot.",
            "properties": {
              "id": {"type": "string"},
              "ts": {"type": "string", "format": "date-time"},
              "type": {"type": "string", "const": "hooks.status"},
              "payload": {
                "type": "object",
                "properties": {"running": {"type": "boolean"}, "completed": {"type": "boolean"}},
                "required": ["running", "completed"]
              }
            },
            "required": ["id", "ts", "type", "payload"]
          },
          {
            "title": "preview.changed",
            "type": "object",
            "description": "Available preview ports changed.",
            "properties": {
              "id": {"type": "string"},
              "ts": {"type": "string", "format": "date-time"},
              "type": {"type": "string", "const": "preview.changed"},
              "payload": {
                "type": "object",
                "properties": {"previews": {"type": "array", "items": {"$ref": "#/components/schemas/EnginePreviewPort"}}},
                "required": ["previews"]
              }
            },
            "required": ["id", "ts", "type", "payload"]
          },
          {
            "title": "error",
            "type": "object",
            "description": "An error occurred in the event stream.",
            "properties": {
              "id": {"type": "string"},
              "ts": {"type": "string", "format": "date-time"},
              "type": {"type": "string", "const": "error"},
              "payload": {
                "type": "object",
                "properties": {
                  "code": {"type": "string", "description": "Machine-readable error code"},
                  "message": {"type": "string", "description": "Human-readable error message"},
                  "details": {"type": "string", "description": "Additional error details"}
                },
                "required": ["code", "message"]
              }
            },
            "required": ["id", "ts", "type", "payload"]
          }
        ]
      },
      "EngineStatusSnapshot": {
        "type": "object",
        "description": "A snapshot of the engine's current status",
        "properties": {
          "uptimeSeconds": {"type": "number", "description": "Engine uptime in seconds"},
          "hasActiveSSHSessions": {"type": "boolean", "description": "Whether there are active SSH sessions"},
          "activeSseClients": {"type": "integer", "description": "Number of active SSE client connections"},
          "chatsTotal": {"type": "integer", "description": "Total number of chat sessions"},
          "chatsProcessing": {
            "type": "integer",
            "description": "Number of chats currently doing work, including those running background/spawned-agent tasks"
          },
          "reposTotal": {"type": "integer", "description": "Total number of repositories"},
          "hooksRunning": {"type": "boolean", "description": "Whether hooks are currently running"},
          "desktopReady": {
            "type": "boolean",
            "description": "Whether the sandbox's H.264/Opus desktop stream is accepting connections. The desktop stack boots after wake, so this can lag behind engine readiness. Absent on older engines that do not report it."
          }
        },
        "required": [
          "uptimeSeconds",
          "hasActiveSSHSessions",
          "activeSseClients",
          "chatsTotal",
          "chatsProcessing",
          "reposTotal",
          "hooksRunning"
        ]
      },
      "WorkspaceEngineHeartbeatSnapshot": {
        "type": "object",
        "description": "Latest outbound heartbeat received from the workspace engine.",
        "properties": {
          "lastSeenAt": {
            "type": ["string", "null"],
            "format": "date-time",
            "description": "When the latest heartbeat was received, or null if none has been received."
          },
          "ageMs": {
            "type": ["integer", "null"],
            "description": "Age of the latest heartbeat in milliseconds, or null if none has been received."
          },
          "fresh": {"type": "boolean", "description": "Whether the latest heartbeat is within the freshness window."},
          "staleAfterMs": {
            "type": "integer",
            "description": "Heartbeat age threshold used to decide whether the engine heartbeat is fresh."
          },
          "bootTimeMs": {"type": "integer", "description": "Engine boot timestamp in Unix epoch milliseconds, if reported."},
          "uptimeSeconds": {"type": "integer", "description": "Engine uptime in seconds, if reported."},
          "status": {"type": "string", "description": "Engine heartbeat status, if reported."}
        },
        "required": ["lastSeenAt", "ageMs", "fresh", "staleAfterMs"]
      },
      "WorkspaceStatusResponse": {
        "type": "object",
        "description": "Current workspace status and engine health context.",
        "properties": {
          "status": {
            "type": "string",
            "description": "Current workspace status.",
            "enum": ["active", "sleeping", "archived", "preparing", "error", "not_found"]
          },
          "lastChecked": {"type": "string", "format": "date-time", "description": "When the status was checked."},
          "error": {
            "type": "string",
            "description": "Status, health-check, setup/provisioning, or wake/resume error message, if present. Some workspaces in `error` can be retried with the wake endpoint; unrecoverable setup or sandbox failures may still require support."
          },
          "engineUnavailableReason": {
            "type": "string",
            "enum": ["overloaded", "unreachable"],
            "description": "Present only when an engine health probe failed. `overloaded` means sandbox metrics show memory or CPU pegged by agent workloads (the engine recovers once they finish); `unreachable` is any other probe failure."
          },
          "message": {"type": "string", "description": "Additional status message, if present."},
          "desktopReady": {
            "type": "boolean",
            "description": "Whether the sandbox's H.264/Opus desktop stream is accepting connections. The desktop stack boots after wake, so this can lag behind `active` status. Absent on older engines that do not report it."
          },
          "engineHeartbeat": {"$ref": "#/components/schemas/WorkspaceEngineHeartbeatSnapshot"},
          "repoStatuses": {
            "type": "array",
            "items": {"$ref": "#/components/schemas/RepositoryStatus"},
            "description": "Cached repository status summaries, if available."
          },
          "lastChatMessage": {
            "oneOf": [
              {
                "type": "object",
                "properties": {
                  "text": {"type": "string", "description": "Preview of the most recent input message."},
                  "provider": {
                    "type": "string",
                    "enum": ["claude", "codex", "cursor", "muse", "opencode", "pi"],
                    "description": "Agent that received the message."
                  },
                  "at": {"type": "string", "format": "date-time", "description": "When the message was sent."}
                },
                "required": ["text", "provider", "at"]
              },
              {"type": "null"}
            ],
            "description": "The most recent input message across the workspace's chats, or null if none has been sent."
          }
        },
        "required": ["status", "lastChecked"]
      },
      "EngineRepoState": {
        "type": "object",
        "description": "State of a repository within the engine",
        "properties": {
          "name": {"type": "string", "description": "Repository name"},
          "path": {"type": "string", "description": "Filesystem path to the repository"},
          "defaultBranch": {"type": "string", "description": "Default branch name (e.g. main)"},
          "currentBranch": {"type": "string", "description": "Currently checked-out branch"},
          "prUrls": {
            "type": "array",
            "items": {"type": "string", "format": "uri"},
            "description": "Pull requests the workspace opened in this repository."
          },
          "gitDiff": {
            "oneOf": [{"$ref": "#/components/schemas/EngineRepoDiff"}, {"type": "null"}],
            "description": "Git diff statistics, if available"
          },
          "startHooksCompleted": {"type": "boolean", "description": "Whether start hooks have finished executing"},
          "provider": {
            "type": "string",
            "enum": ["github", "gitlab"],
            "description": "Code host for the repository's origin remote, when resolvable"
          }
        },
        "required": ["name", "path", "defaultBranch", "currentBranch", "prUrls", "gitDiff", "startHooksCompleted"]
      },
      "EngineRepoDiff": {
        "type": "object",
        "description": "Git diff statistics for a repository",
        "properties": {
          "added": {"type": "integer", "description": "Number of lines added"},
          "removed": {"type": "integer", "description": "Number of lines removed"},
          "fullDiff": {"type": "string", "description": "Full diff content"}
        },
        "required": ["added", "removed"]
      },
      "EngineChatSummary": {
        "type": "object",
        "description": "Summary of a chat session as reported by the engine",
        "properties": {
          "id": {"type": "string", "description": "Unique chat session ID"},
          "provider": {
            "type": "string",
            "enum": ["claude", "codex", "cursor", "muse", "opencode", "pi"],
            "description": "Coding agent provider"
          },
          "model": {"type": "string", "description": "Selected model retained for future messages in this chat"},
          "title": {"type": "string", "description": "Chat title"},
          "createdAt": {"type": "string", "format": "date-time", "description": "When the chat was created"},
          "updatedAt": {"type": "string", "format": "date-time", "description": "When the chat was last updated"},
          "activityTrackingVersion": {
            "type": "integer",
            "enum": [1],
            "description": "Present when processing authoritatively tracks agent work; Claude background tasks and the follow-up turns they trigger keep the chat processing until they finish"
          },
          "processing": {
            "type": "boolean",
            "description": "Whether the chat is actively working: the main agent turn, queued messages, or Claude background tasks and the follow-up turns they trigger"
          },
          "awaitingInput": {
            "type": "boolean",
            "description": "The agent has issued an interactive tool call (e.g. ExitPlanMode, AskUserQuestion) and is paused until the user resolves it. `processing` stays true while this is true."
          },
          "parentChatId": {"type": ["string", "null"], "description": "ID of the parent chat, if this is a sub-chat"},
          "fork": {
            "description": "Fork lineage and progress, when this chat was forked from another chat in the workspace",
            "oneOf": [{"$ref": "#/components/schemas/ChatFork"}, {"type": "null"}]
          },
          "lastMessageText": {"type": ["string", "null"], "description": "Preview of the most recent input message sent to this chat."}
        },
        "required": ["id", "provider", "title", "createdAt", "updatedAt", "processing", "parentChatId"]
      },
      "EnginePreviewPort": {
        "type": "object",
        "description": "A preview port forwarded from the workspace",
        "properties": {
          "port": {"type": "integer", "description": "Local port number"},
          "publicUrl": {"type": "string", "format": "uri", "description": "Public URL for the preview"},
          "createdAt": {"type": "string", "format": "date-time", "description": "When the preview was created"}
        },
        "required": ["port", "publicUrl", "createdAt"]
      },
      "AgentEvent": {
        "description": "A raw event from the coding agent, streamed as part of `chat.turn.delta` events. The shape depends on the coding agent provider. Use the `type` field to discriminate between Claude, Codex, Cursor, Muse Server Protocol, Opencode, and Pi events.",
        "oneOf": [
          {"$ref": "#/components/schemas/ClaudeAgentEvent"},
          {"$ref": "#/components/schemas/CodexAgentEvent"},
          {"$ref": "#/components/schemas/CursorAgentEvent"},
          {"$ref": "#/components/schemas/MuseAgentEvent"},
          {"$ref": "#/components/schemas/OpencodeAgentEvent"},
          {"$ref": "#/components/schemas/PiAgentEvent"}
        ],
        "discriminator": {
          "propertyName": "type",
          "mapping": {
            "claude-assistant": "#/components/schemas/ClaudeAgentEvent",
            "claude-user": "#/components/schemas/ClaudeAgentEvent",
            "claude-result": "#/components/schemas/ClaudeAgentEvent",
            "claude-system": "#/components/schemas/ClaudeAgentEvent",
            "event_msg": "#/components/schemas/CodexAgentEvent",
            "response_item": "#/components/schemas/CodexAgentEvent",
            "cursor-assistant": "#/components/schemas/CursorAgentEvent",
            "cursor-thinking": "#/components/schemas/CursorAgentEvent",
            "cursor-tool_call": "#/components/schemas/CursorAgentEvent",
            "cursor-task": "#/components/schemas/CursorAgentEvent",
            "cursor-status": "#/components/schemas/CursorAgentEvent",
            "cursor-error": "#/components/schemas/CursorAgentEvent",
            "muse-error": "#/components/schemas/MuseAgentEvent",
            "muse-turn-completed": "#/components/schemas/MuseAgentEvent",
            "muse-item-started": "#/components/schemas/MuseAgentEvent",
            "muse-item-updated": "#/components/schemas/MuseAgentEvent",
            "muse-item-completed": "#/components/schemas/MuseAgentEvent",
            "muse-item-delta": "#/components/schemas/MuseAgentEvent",
            "muse-session-tokenUsage": "#/components/schemas/MuseAgentEvent",
            "muse-session-contextUsage": "#/components/schemas/MuseAgentEvent",
            "muse-userInput-requested": "#/components/schemas/MuseAgentEvent",
            "opencode-message.updated": "#/components/schemas/OpencodeAgentEvent",
            "opencode-session.idle": "#/components/schemas/OpencodeAgentEvent",
            "opencode-error": "#/components/schemas/OpencodeAgentEvent",
            "opencode-part-text": "#/components/schemas/OpencodeAgentEvent",
            "opencode-part-reasoning": "#/components/schemas/OpencodeAgentEvent",
            "opencode-part-tool": "#/components/schemas/OpencodeAgentEvent",
            "pi-agent_start": "#/components/schemas/PiAgentEvent",
            "pi-message_update": "#/components/schemas/PiAgentEvent",
            "pi-tool_execution_start": "#/components/schemas/PiAgentEvent",
            "pi-tool_execution_update": "#/components/schemas/PiAgentEvent",
            "pi-tool_execution_end": "#/components/schemas/PiAgentEvent",
            "pi-error": "#/components/schemas/PiAgentEvent"
          }
        }
      },
      "ClaudeAgentEvent": {
        "type": "object",
        "description": "A streaming event from the Claude Code agent. The `type` field is prefixed with `claude-` followed by the SDK message type.",
        "properties": {
          "timestamp": {"type": "string", "format": "date-time", "description": "When the event occurred"},
          "type": {
            "type": "string",
            "enum": ["claude-assistant", "claude-user", "claude-result", "claude-system"],
            "description": "Claude event type. `claude-assistant` contains model output (text, thinking, tool use). `claude-user` contains tool results. `claude-result` signals turn completion or errors. `claude-system` contains system-level messages."
          },
          "payload": {"$ref": "#/components/schemas/ClaudeEventPayload"}
        },
        "required": ["timestamp", "type", "payload"]
      },
      "AutomationTrigger": {
        "type": "object",
        "description": "A trigger that determines when an automation fires",
        "properties": {
          "type": {
            "type": "string",
            "description": "The trigger type",
            "enum": ["cron", "github", "gitlab", "slack", "sentry", "custom"]
          },
          "config": {
            "description": "Trigger configuration. Its schema depends on `type`: `CronTriggerConfig`, `GitHubTriggerConfig`, `GitLabTriggerConfig`, `SlackTriggerConfig`, `SentryTriggerConfig`, or an empty object for `custom`.",
            "anyOf": [
              {"$ref": "#/components/schemas/CronTriggerConfig"},
              {"$ref": "#/components/schemas/GitHubTriggerConfig"},
              {"$ref": "#/components/schemas/GitLabTriggerConfig"},
              {"$ref": "#/components/schemas/SlackTriggerConfig"},
              {"$ref": "#/components/schemas/SentryTriggerConfig"},
              {"$ref": "#/components/schemas/CustomTriggerConfig"}
            ]
          }
        },
        "required": ["type", "config"]
      },
      "CronTriggerConfig": {
        "type": "object",
        "description": "Configuration for a cron (scheduled) trigger",
        "properties": {
          "schedule": {
            "type": "string",
            "description": "Cron expression (e.g. \"0 9 * * 1-5\" for weekdays at 9am UTC)",
            "example": "0 9 * * 1-5"
          },
          "timezone": {
            "type": "string",
            "description": "IANA timezone for the schedule (defaults to UTC)",
            "default": "UTC",
            "example": "America/New_York"
          }
        },
        "required": ["schedule"]
      },
      "GitHubTriggerConfig": {
        "type": "object",
        "description": "Configuration for a GitHub event trigger",
        "properties": {
          "event": {
            "type": "string",
            "description": "The GitHub event to listen for",
            "enum": [
              "pull_request.opened",
              "pull_request.synchronize",
              "pull_request.ready_for_review",
              "pull_request.merged",
              "pull_request.closed",
              "pull_request.command"
            ]
          },
          "repository_ids": {
            "type": "array",
            "items": {"type": "string", "format": "uuid"},
            "description": "Optional filter: only fire for events from these repositories. If omitted, fires for all repositories."
          },
          "group_pr_events": {
            "type": "boolean",
            "description": "Send later opened, synchronize, ready for review, and command events for the same pull request to the existing workspace instead of creating a new one."
          },
          "excluded_actors": {
            "type": "array",
            "items": {"type": "string"},
            "description": "Optional exclusion list: events sent by these GitHub usernames never fire the automation (e.g. `dependabot[bot]`). Matching is case-insensitive and ignores a leading `@`."
          }
        },
        "required": ["event"]
      },
      "GitLabTriggerConfig": {
        "type": "object",
        "description": "Configuration for a GitLab merge request event trigger",
        "properties": {
          "event": {
            "type": "string",
            "description": "The GitLab event to listen for",
            "enum": ["merge_request.opened", "merge_request.updated", "merge_request.merged", "merge_request.closed"]
          },
          "repository_ids": {
            "type": "array",
            "items": {"type": "string", "format": "uuid"},
            "description": "Optional filter: only fire for events from these GitLab projects. If omitted, fires for all projects."
          },
          "group_pr_events": {
            "type": "boolean",
            "description": "Send later opened and updated events for the same merge request to the existing workspace instead of creating a new one."
          },
          "excluded_actors": {
            "type": "array",
            "items": {"type": "string"},
            "description": "Optional exclusion list: events sent by these GitLab usernames never fire the automation. Matching is case-insensitive and ignores a leading `@`."
          }
        },
        "required": ["event"]
      },
      "SlackTriggerConfig": {
        "type": "object",
        "description": "Configuration for a Slack event trigger",
        "properties": {
          "event": {"type": "string", "description": "The Slack event to listen for", "enum": ["message"]},
          "channel_ids": {
            "type": "array",
            "items": {"type": "string"},
            "description": "Optional filter: only fire for events from these Slack channels. If omitted, fires for all channels."
          },
          "group_thread_replies": {
            "type": "boolean",
            "description": "When true (default), thread replies flow to the same workspace as the root message instead of spawning new ones.",
            "default": true
          }
        },
        "required": ["event"]
      },
      "SentryTriggerConfig": {
        "type": "object",
        "description": "Configuration for a Sentry event trigger",
        "properties": {
          "event": {
            "type": "string",
            "description": "The Sentry event to listen for",
            "enum": ["event_alert.triggered", "issue.created", "error.created"]
          },
          "project_slugs": {
            "type": "array",
            "items": {"type": "string"},
            "description": "Optional filter: only fire for events from these Sentry project slugs. If omitted, fires for all projects."
          },
          "min_level": {
            "type": "string",
            "description": "Optional minimum severity level (inclusive). If omitted, fires for all levels.",
            "enum": ["debug", "info", "warning", "error", "fatal"]
          }
        },
        "required": ["event"]
      },
      "CustomTriggerConfig": {
        "type": "object",
        "description": "Configuration for a custom webhook trigger. The config is intentionally empty: the automation's generated `webhook_token` is the only thing that needs to be stored.",
        "properties": {}
      },
      "WorkspaceConfig": {
        "type": "object",
        "description": "Workspace behavior configuration. Defaults depend on the workspace source; see each setting.",
        "properties": {
          "memoryRetentionEnabled": {
            "type": "boolean",
            "description": "Whether sessions are added to session history when the workspace sleeps. Defaults to false for API and automation workspaces."
          },
          "capabilities": {
            "type": "object",
            "description": "Actions this workspace is allowed to perform. Automations snapshot this config onto each workspace they create; API-created workspaces can set it at creation time.",
            "properties": {
              "pr_followups": {
                "type": "boolean",
                "description": "Whether matching pull requests can receive Replicas follow-up actions. Only applies to workspaces created from an automation, where it defaults to false; other workspaces always receive follow-ups. When enabled, later CI and review-comment replies can route back to this workspace."
              },
              "read_only_contents": {
                "type": "boolean",
                "description": "Whether the workspace GitHub token is restricted to read-only repository contents, keeping write access for pull request comments, issues, and checks. Defaults to false, so the workspace can push branches and open pull requests."
              }
            },
            "additionalProperties": true
          },
          "preferences": {
            "type": "object",
            "description": "Workspace behavior preferences that do not grant new action permissions.",
            "properties": {
              "keep_open_on_pr_merge": {
                "type": "boolean",
                "description": "Whether the workspace should remain open after its last tracked PR is merged. Defaults to false.",
                "default": false
              },
              "keep_open_on_pr_close": {
                "type": "boolean",
                "description": "Whether the workspace should remain open after its last tracked PR is closed without merging. Defaults to false.",
                "default": false
              }
            },
            "additionalProperties": true
          },
          "provisioning_error": {
            "type": "object",
            "description": "Setup/provisioning or wake/resume failure captured when the workspace remains queryable in `error` status. Some wake/resume failures can be retried; the `error` status can also represent an unrecoverable sandbox failure.",
            "properties": {
              "message": {
                "type": "string",
                "description": "Underlying setup failure message, such as repository clone/auth errors."
              }
            },
            "additionalProperties": true
          }
        },
        "additionalProperties": true
      },
      "AutomationRecord": {
        "type": "object",
        "description": "An automation record",
        "properties": {
          "access": {
            "$ref": "#/components/schemas/EnvironmentAccess",
            "description": "The caller's effective permissions on this automation."
          },
          "my_alert_level": {
            "type": "string",
            "enum": ["muted", "normal", "every"],
            "description": "Which phone pushes the signed-in person gets from this automation: `muted` (none), `normal` (when it needs them or stops working) or `every` (each result too). Defaults to `normal` for whoever made it and `muted` for everyone else. Absent when no person is signed in, as with an organization API key."
          },
          "id": {"type": "string", "format": "uuid", "description": "Unique identifier for the automation"},
          "organization_id": {"type": "string", "format": "uuid", "description": "Organization that owns this automation"},
          "name": {"type": "string", "description": "Human-readable name for the automation"},
          "description": {"type": ["string", "null"], "description": "Optional description"},
          "triggers": {
            "type": "array",
            "items": {"$ref": "#/components/schemas/AutomationTrigger"},
            "description": "Triggers that fire this automation"
          },
          "prompt": {"type": "string", "description": "The instruction sent to the coding agent when the automation fires"},
          "debounce_seconds": {
            "type": ["integer", "null"],
            "minimum": 0,
            "maximum": 86400,
            "description": "Seconds to wait for trigger events to stop before running once with the latest payload. GitHub and GitLab events debounce per pull or merge request. `null` or `0` disables debouncing."
          },
          "github_check_names": {
            "type": "array",
            "items": {"type": "string", "maxLength": 100},
            "maxItems": 10,
            "description": "GitHub check names the automation reports a verdict on."
          },
          "environment_id": {
            "type": "string",
            "format": "uuid",
            "description": "ID of the environment this automation runs in. The environment supplies env vars / MCPs / skills layered on top of the environments it builds on and decides which repositories are cloned."
          },
          "enabled": {"type": "boolean", "description": "Whether the automation is active"},
          "auto_paused_at": {
            "type": ["string", "null"],
            "format": "date-time",
            "description": "When Replicas paused the automation after it failed every run for 7 days. Null once it's enabled again."
          },
          "failing_cause": {
            "type": ["string", "null"],
            "description": "Error from the latest failed run while every run since its last completed one has failed. Null once a run completes."
          },
          "webhook_token": {
            "type": ["string", "null"],
            "description": "Token for the `custom` trigger URL, `POST /v1/automations/webhook/{webhook_token}`. Anyone with the URL can run the automation, so keep it secret."
          },
          "cron_next_fire_at": {
            "type": ["string", "null"],
            "format": "date-time",
            "description": "Next scheduled fire time for cron automations"
          },
          "user_id": {
            "type": ["string", "null"],
            "format": "uuid",
            "description": "User ID for personal automations, null for org-owned automations"
          },
          "created_by": {"type": ["string", "null"], "format": "uuid", "description": "User who created the automation"},
          "workspace_lifecycle_policy": {
            "type": "string",
            "description": "Lifecycle policy for workspaces created by this automation",
            "enum": ["default", "archive_when_done", "sleep_when_done", "delete_when_done", "delete_after_inactivity"]
          },
          "workspace_auto_stop_minutes": {
            "type": ["integer", "null"],
            "description": "Inactivity timeout in minutes (3-1440) for the default keep-alive policy",
            "minimum": 3,
            "maximum": 1440
          },
          "workspace_size": {
            "type": ["string", "null"],
            "description": "Compute size for workspaces fired off by this automation. Defaults to `small` when omitted.",
            "enum": ["small", "large", "ultra", null]
          },
          "config": {"$ref": "#/components/schemas/WorkspaceConfig"},
          "agent_provider": {
            "type": ["string", "null"],
            "description": "Coding agent override for this automation. Null inherits the organization default.",
            "enum": ["claude", "codex", "cursor", "muse", "opencode", "pi", null]
          },
          "model": {
            "type": ["string", "null"],
            "description": "Model override for this automation. Null uses the agent default."
          },
          "thinking_level": {
            "type": ["string", "null"],
            "description": "Thinking/reasoning level override for this automation. `ultra` is available for Codex and Muse Code; `ultracode` is Claude Code-only.",
            "enum": ["low", "medium", "high", "xhigh", "max", "ultra", "ultracode", null]
          },
          "plan_mode": {"type": "boolean", "description": "Whether automation messages run in plan mode."},
          "goal_mode": {
            "type": ["boolean", "null"],
            "description": "Whether automation messages are set as goals. Null inherits the resolved agent default; false explicitly disables it. Only applies when the resolved agent is Claude Code or Codex."
          },
          "fast_mode": {
            "type": ["boolean", "null"],
            "description": "Whether automation messages run in fast mode. Null inherits the resolved agent default; false explicitly disables it."
          },
          "created_at": {"type": "string", "format": "date-time", "description": "When the automation was created"},
          "updated_at": {"type": "string", "format": "date-time", "description": "When the automation was last updated"}
        },
        "required": [
          "id",
          "organization_id",
          "name",
          "description",
          "triggers",
          "prompt",
          "debounce_seconds",
          "github_check_names",
          "environment_id",
          "enabled",
          "auto_paused_at",
          "failing_cause",
          "user_id",
          "webhook_token",
          "cron_next_fire_at",
          "created_by",
          "workspace_lifecycle_policy",
          "workspace_auto_stop_minutes",
          "workspace_size",
          "config",
          "agent_provider",
          "model",
          "thinking_level",
          "plan_mode",
          "goal_mode",
          "fast_mode",
          "created_at",
          "updated_at"
        ]
      },
      "AutomationExecutionRecord": {
        "type": "object",
        "description": "A record of a single automation execution",
        "properties": {
          "id": {"type": "string", "format": "uuid", "description": "Unique identifier for the execution"},
          "automation_id": {"type": "string", "format": "uuid", "description": "The automation that was executed"},
          "organization_id": {"type": "string", "format": "uuid", "description": "Organization that owns this execution"},
          "workspace_id": {
            "type": ["string", "null"],
            "format": "uuid",
            "description": "The workspace created for this execution (null if not yet created)"
          },
          "workspace_name": {
            "type": ["string", "null"],
            "description": "Name of the execution's workspace. Null when `workspace_id` is null or the workspace has been permanently removed."
          },
          "workspace_deleted": {"type": "boolean", "description": "Whether the run's workspace has been deleted."},
          "triggered_at": {"type": "string", "format": "date-time", "description": "When the execution was triggered"},
          "trigger_payload": {"type": "object", "description": "Event data that triggered the execution", "additionalProperties": true},
          "status": {
            "type": "string",
            "description": "Current status of the execution",
            "enum": ["pending", "creating", "running", "completed", "failed"]
          },
          "config": {"$ref": "#/components/schemas/WorkspaceConfig"},
          "error": {"type": ["string", "null"], "description": "Error message if the execution failed"},
          "completed_at": {"type": ["string", "null"], "format": "date-time", "description": "When the execution completed"},
          "can_retry": {
            "type": "boolean",
            "description": "Whether the execution failed and the caller can write to its automation, so it can be retried"
          }
        },
        "required": [
          "id",
          "automation_id",
          "organization_id",
          "workspace_id",
          "workspace_name",
          "workspace_deleted",
          "triggered_at",
          "trigger_payload",
          "status",
          "config",
          "error",
          "completed_at",
          "can_retry"
        ]
      },
      "AutomationExecutionListItem": {
        "allOf": [
          {"$ref": "#/components/schemas/AutomationExecutionRecord"},
          {
            "type": "object",
            "properties": {"automation_name": {"type": "string", "description": "Human-readable name of the automation"}},
            "required": ["automation_name"]
          }
        ]
      },
      "CreateAutomationRequest": {
        "type": "object",
        "description": "Request body for creating a new automation. The automation runs in a single environment specified by `environment_id`.",
        "properties": {
          "name": {"type": "string", "description": "Human-readable name for the automation"},
          "description": {"type": "string", "description": "Optional description"},
          "scope": {
            "type": "string",
            "description": "Automation scope. `org` (default) creates an org-owned automation visible to all members. `user` creates a personal automation scoped to the authenticated user.",
            "enum": ["org", "user"],
            "default": "org"
          },
          "triggers": {
            "type": "array",
            "items": {"$ref": "#/components/schemas/AutomationTrigger"},
            "description": "At most one cron trigger and one trigger per event.",
            "minItems": 1
          },
          "prompt": {"type": "string", "description": "The instruction sent to the coding agent when the automation fires"},
          "debounce_seconds": {
            "type": ["integer", "null"],
            "minimum": 0,
            "maximum": 86400,
            "description": "Seconds to wait for trigger events to stop before running once with the latest payload. GitHub and GitLab events debounce per pull or merge request. `null` or `0` disables debouncing."
          },
          "github_check_names": {
            "type": "array",
            "items": {"type": "string", "maxLength": 100},
            "maxItems": 10,
            "description": "GitHub check names the automation reports a verdict on. Each starts as an in-progress check on the pull request, so required checks wait for the agent. Requires a `pull_request.opened` or `pull_request.synchronize` trigger."
          },
          "environment_id": {
            "type": "string",
            "format": "uuid",
            "description": "ID of the environment this automation runs in. Required. The environment supplies resolved env vars / MCPs / skills and decides which repositories are cloned."
          },
          "enabled": {
            "type": "boolean",
            "description": "Whether the automation should be active (defaults to true)",
            "default": true
          },
          "workspace_lifecycle_policy": {
            "type": "string",
            "description": "Lifecycle policy for workspaces created by this automation. Defaults to `delete_when_done`, or `default` when `workspace_auto_stop_minutes` is set.",
            "enum": ["default", "archive_when_done", "sleep_when_done", "delete_when_done"],
            "default": "delete_when_done"
          },
          "workspace_auto_stop_minutes": {
            "type": "integer",
            "description": "Inactivity timeout in minutes for the default keep-alive policy",
            "minimum": 3,
            "maximum": 1440
          },
          "workspace_size": {
            "type": "string",
            "description": "Compute size for every workspace this automation fires off. `small` (2 vCPU, 8 GB memory), `large` (4 vCPU, 16 GB memory), or `ultra` (8 vCPU, 32 GB memory); see [Billing](https://docs.replicas.dev/admin/billing#rates) for per-size rates. Defaults to `small`.",
            "enum": ["small", "large", "ultra"],
            "default": "small"
          },
          "config": {"$ref": "#/components/schemas/WorkspaceConfig"},
          "agent_provider": {
            "type": ["string", "null"],
            "description": "Coding agent override. Null inherits the organization default.",
            "enum": ["claude", "codex", "cursor", "muse", "opencode", "pi", null]
          },
          "model": {
            "type": ["string", "null"],
            "description": "Model override. Requires `agent_provider` when set. Must be a model your organization allows for that agent; hidden models are rejected with 400."
          },
          "thinking_level": {
            "type": ["string", "null"],
            "description": "Thinking/reasoning level override. `ultra` is available for Codex and Muse Code; `ultracode` is Claude Code-only.",
            "enum": ["low", "medium", "high", "xhigh", "max", "ultra", "ultracode", null]
          },
          "plan_mode": {"type": "boolean", "description": "Run automation messages in plan mode."},
          "goal_mode": {
            "type": ["boolean", "null"],
            "description": "Set automation messages as goals. Null inherits the resolved agent default; false explicitly disables it. Only applies when the resolved agent is Claude Code or Codex."
          },
          "fast_mode": {
            "type": ["boolean", "null"],
            "description": "Run automation messages in fast mode. Null inherits the resolved agent default; false explicitly disables it."
          }
        },
        "required": ["name", "triggers", "prompt", "environment_id"]
      },
      "UpdateAutomationRequest": {
        "type": "object",
        "description": "Request body for updating an automation. Only provided fields are updated.",
        "properties": {
          "name": {"type": "string", "description": "New name"},
          "description": {"type": "string", "description": "New description"},
          "triggers": {
            "type": "array",
            "items": {"$ref": "#/components/schemas/AutomationTrigger"},
            "description": "Replaces all triggers. At most one cron trigger and one trigger per event."
          },
          "prompt": {"type": "string", "description": "New prompt"},
          "debounce_seconds": {
            "type": ["integer", "null"],
            "minimum": 0,
            "maximum": 86400,
            "description": "Seconds to wait for trigger events to stop before running once with the latest payload. GitHub and GitLab events debounce per pull or merge request. `null` or `0` disables debouncing."
          },
          "github_check_names": {
            "type": "array",
            "items": {"type": "string", "maxLength": 100},
            "maxItems": 10,
            "description": "Set or clear the GitHub check names this automation reports its verdict on. A non-empty list requires a pull_request.opened or pull_request.synchronize trigger. Pass an empty array to stop creating checks."
          },
          "environment_id": {"type": "string", "format": "uuid", "description": "Move this automation to a different environment."},
          "enabled": {"type": "boolean", "description": "Enable or disable the automation"},
          "workspace_lifecycle_policy": {
            "type": "string",
            "description": "New lifecycle policy",
            "enum": ["default", "archive_when_done", "sleep_when_done", "delete_when_done"]
          },
          "workspace_auto_stop_minutes": {
            "type": ["integer", "null"],
            "description": "New inactivity timeout in minutes for the default keep-alive policy (set to null to clear)",
            "minimum": 3,
            "maximum": 1440
          },
          "workspace_size": {
            "type": "string",
            "description": "New compute size for every workspace this automation fires off. `small` (2 vCPU, 8 GB memory), `large` (4 vCPU, 16 GB memory), or `ultra` (8 vCPU, 32 GB memory); see [Billing](https://docs.replicas.dev/admin/billing#rates) for per-size rates.",
            "enum": ["small", "large", "ultra"]
          },
          "config": {"$ref": "#/components/schemas/WorkspaceConfig"},
          "agent_provider": {
            "type": ["string", "null"],
            "description": "New coding agent override. Null inherits the organization default.",
            "enum": ["claude", "codex", "cursor", "muse", "opencode", "pi", null]
          },
          "model": {
            "type": ["string", "null"],
            "description": "New model override. Requires `agent_provider` when set. Must be a model your organization allows for that agent; hidden models are rejected with 400."
          },
          "thinking_level": {
            "type": ["string", "null"],
            "description": "New thinking/reasoning level override. `ultra` is available for Codex and Muse Code; `ultracode` is Claude Code-only.",
            "enum": ["low", "medium", "high", "xhigh", "max", "ultra", "ultracode", null]
          },
          "plan_mode": {"type": "boolean", "description": "Enable or disable plan mode for automation messages."},
          "goal_mode": {
            "type": ["boolean", "null"],
            "description": "Enable or disable goal mode for automation messages. Null inherits the resolved agent default; false explicitly disables it."
          },
          "fast_mode": {
            "type": ["boolean", "null"],
            "description": "Enable or disable fast mode for automation messages. Null inherits the resolved agent default; false explicitly disables it."
          },
          "scope": {
            "type": "string",
            "enum": ["org"],
            "description": "Set to `org` to move a personal automation to the organization so teammates can see and edit it. Requires a shared environment and Automations write access. Cannot be undone."
          }
        }
      },
      "AutomationResponse": {
        "type": "object",
        "description": "Response containing a single automation",
        "properties": {"automation": {"$ref": "#/components/schemas/AutomationRecord"}},
        "required": ["automation"]
      },
      "ListAutomationsResponse": {
        "type": "object",
        "description": "Paginated list of automations",
        "properties": {
          "automations": {"type": "array", "items": {"$ref": "#/components/schemas/AutomationRecord"}},
          "total": {"type": "integer", "description": "Total number of automations"},
          "page": {"type": "integer", "description": "Current page number"},
          "limit": {"type": "integer", "description": "Number of items per page"},
          "total_pages": {"type": "integer", "description": "Total number of pages"}
        },
        "required": ["automations", "total", "page", "limit", "total_pages"]
      },
      "TriggerAutomationRequest": {
        "type": "object",
        "description": "Request body for manually triggering an automation",
        "properties": {
          "payload": {
            "type": "object",
            "description": "Optional payload to pass to the automation execution",
            "additionalProperties": true
          },
          "pr": {
            "type": "object",
            "description": "Pull request to run against. Requires a GitHub `pull_request.command` trigger for that repository.",
            "properties": {
              "repository_id": {
                "type": "string",
                "format": "uuid",
                "description": "The Replicas repository UUID the pull request belongs to"
              },
              "number": {"type": "integer", "description": "The pull request number"}
            },
            "required": ["repository_id", "number"]
          }
        }
      },
      "TriggerAutomationResponse": {
        "type": "object",
        "description": "Response after triggering an automation",
        "properties": {
          "execution_id": {"type": "string", "format": "uuid", "description": "Unique identifier for the execution"},
          "workspace_id": {"type": ["string", "null"], "format": "uuid", "description": "The workspace created for this execution"}
        },
        "required": ["execution_id", "workspace_id"]
      },
      "ListAutomationExecutionsResponse": {
        "type": "object",
        "description": "Paginated list of automation executions",
        "properties": {
          "executions": {"type": "array", "items": {"$ref": "#/components/schemas/AutomationExecutionRecord"}},
          "total": {"type": "integer", "description": "Total number of executions"},
          "page": {"type": "integer", "description": "Current page number"},
          "limit": {"type": "integer", "description": "Number of items per page"},
          "total_pages": {"type": "integer", "description": "Total number of pages"}
        },
        "required": ["executions", "total", "page", "limit", "total_pages"]
      },
      "ListOrganizationAutomationExecutionsResponse": {
        "type": "object",
        "description": "Paginated list of executions across accessible automations",
        "properties": {
          "executions": {"type": "array", "items": {"$ref": "#/components/schemas/AutomationExecutionListItem"}},
          "total": {"type": "integer", "description": "Total number of executions"},
          "page": {"type": "integer", "description": "Current page number"},
          "limit": {"type": "integer", "description": "Number of items per page"},
          "total_pages": {"type": "integer", "description": "Total number of pages"}
        },
        "required": ["executions", "total", "page", "limit", "total_pages"]
      },
      "ClaudeEventPayload": {
        "type": "object",
        "description": "Payload of a Claude Code agent event, wrapping the Claude SDK message.",
        "properties": {
          "type": {"type": "string", "description": "Original SDK message type (e.g. `assistant`, `user`, `result`)"},
          "subtype": {
            "type": "string",
            "description": "Present on `claude-result` events; `success` indicates a clean turn completion. Any other value (e.g. `error`) signals a failed turn even when `is_error` is false."
          },
          "parent_tool_use_id": {
            "type": ["string", "null"],
            "description": "If this message is the result of a sub-agent tool call, the parent tool_use ID"
          },
          "message": {"$ref": "#/components/schemas/ClaudeMessage"},
          "is_error": {"type": "boolean", "description": "Present on `claude-result` events; true if the turn ended with an error"},
          "errors": {
            "type": "array",
            "items": {"type": "string"},
            "description": "Array of error messages, present on `claude-result` events when `is_error` is true"
          }
        },
        "additionalProperties": true
      },
      "ClaudeMessage": {
        "type": "object",
        "description": "A Claude SDK message containing an array of content blocks.",
        "properties": {
          "content": {
            "type": "array",
            "description": "Ordered list of content blocks produced or consumed by the model.",
            "items": {"$ref": "#/components/schemas/ClaudeContentBlock"}
          }
        }
      },
      "ClaudeContentBlock": {
        "type": "object",
        "description": "A single content block within a Claude message. Discriminated by `type`.",
        "oneOf": [
          {
            "type": "object",
            "title": "TextBlock",
            "description": "A text response from the model.",
            "properties": {"type": {"type": "string", "const": "text"}, "text": {"type": "string", "description": "The text content"}},
            "required": ["type", "text"]
          },
          {
            "type": "object",
            "title": "ThinkingBlock",
            "description": "An extended-thinking block showing the model's reasoning.",
            "properties": {
              "type": {"type": "string", "const": "thinking"},
              "text": {"type": "string", "description": "The thinking/reasoning content"}
            },
            "required": ["type", "text"]
          },
          {
            "type": "object",
            "title": "ToolUseBlock",
            "description": "A tool invocation by the model (e.g. Bash, Edit, Write, Grep, Glob, Read, WebSearch, TaskCreate, Skill).",
            "properties": {
              "type": {"type": "string", "const": "tool_use"},
              "id": {
                "type": "string",
                "description": "Unique ID for this tool use, referenced by subsequent tool_result blocks"
              },
              "name": {
                "type": "string",
                "description": "Tool name (e.g. `Bash`, `Edit`, `Write`, `Read`, `Grep`, `Glob`, `WebSearch`, `TaskCreate`, `Skill`)"
              },
              "input": {"type": "object", "additionalProperties": true, "description": "Tool-specific input parameters"}
            },
            "required": ["type", "id", "name", "input"]
          },
          {
            "type": "object",
            "title": "ToolResultBlock",
            "description": "The result of a tool invocation, sent back to the model in `claude-user` events.",
            "properties": {
              "type": {"type": "string", "const": "tool_result"},
              "tool_use_id": {"type": "string", "description": "ID of the tool_use block this result corresponds to"},
              "content": {
                "description": "Tool output — either a plain string or an array of text/image blocks.",
                "oneOf": [
                  {"type": "string"},
                  {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "type": {"type": "string", "enum": ["text", "image"]},
                        "text": {"type": "string"},
                        "source": {
                          "type": "object",
                          "properties": {
                            "type": {"type": "string"},
                            "media_type": {"type": "string"},
                            "data": {"type": "string", "description": "Base64-encoded image data"}
                          }
                        }
                      }
                    }
                  }
                ]
              },
              "is_error": {"type": "boolean", "description": "Whether the tool execution resulted in an error"}
            },
            "required": ["type", "tool_use_id"]
          }
        ],
        "discriminator": {"propertyName": "type"}
      },
      "CodexAgentEvent": {
        "type": "object",
        "description": "A streaming event from the Codex CLI agent. Uses either `event_msg` for high-level messages or `response_item` for structured response items.",
        "properties": {
          "timestamp": {"type": "string", "format": "date-time", "description": "When the event occurred"},
          "type": {
            "type": "string",
            "enum": ["event_msg", "response_item"],
            "description": "`event_msg` carries high-level messages (user input, reasoning). `response_item` carries structured responses (assistant messages, function calls, tool calls)."
          },
          "payload": {"$ref": "#/components/schemas/CodexEventPayload"}
        },
        "required": ["timestamp", "type", "payload"]
      },
      "CursorAgentEvent": {
        "type": "object",
        "description": "A streaming event from the Cursor agent. Cursor events are normalized with a `cursor-` prefixed type and a provider payload.",
        "properties": {
          "timestamp": {"type": "string", "format": "date-time", "description": "When the event occurred"},
          "type": {
            "type": "string",
            "enum": ["cursor-assistant", "cursor-thinking", "cursor-tool_call", "cursor-task", "cursor-status", "cursor-error"],
            "description": "Cursor event type. `cursor-assistant` contains model output, `cursor-thinking` contains reasoning text, `cursor-tool_call` contains tool progress/results, `cursor-task` contains task updates, `cursor-status` contains run status, and `cursor-error` contains failure details."
          },
          "payload": {
            "type": "object",
            "description": "Cursor event payload. Shape depends on the parent event `type`; Cursor payload sub-shapes are not yet formally specified.",
            "additionalProperties": true
          }
        },
        "required": ["timestamp", "type", "payload"]
      },
      "MuseAgentEvent": {
        "type": "object",
        "description": "A streaming event from Muse Code over Muse Server Protocol.",
        "properties": {
          "timestamp": {"type": "string", "format": "date-time", "description": "When the event occurred"},
          "type": {
            "type": "string",
            "pattern": "^muse-",
            "description": "Muse event type. Item events carry assistant, reasoning, and tool updates; session events report usage; turn completion and error events describe terminal state."
          },
          "payload": {
            "type": "object",
            "description": "Muse event payload. Shape depends on the parent event type.",
            "additionalProperties": true
          }
        },
        "required": ["timestamp", "type", "payload"]
      },
      "OpencodeAgentEvent": {
        "type": "object",
        "description": "A streaming event from the Opencode agent. Opencode events are normalized with an `opencode-` prefixed type and an open provider payload.",
        "properties": {
          "timestamp": {"type": "string", "format": "date-time", "description": "When the event occurred"},
          "type": {
            "type": "string",
            "pattern": "^opencode-",
            "description": "Opencode event type. Common values include `opencode-message.updated`, `opencode-session.idle`, `opencode-error`, and `opencode-part-*` events."
          },
          "payload": {
            "type": "object",
            "description": "Opencode event payload. Shape depends on the parent event `type`; Opencode payload sub-shapes are not yet formally specified.",
            "additionalProperties": true
          }
        },
        "required": ["timestamp", "type", "payload"]
      },
      "PiAgentEvent": {
        "type": "object",
        "description": "A streaming event from the Pi coding agent. Pi events expose session lifecycle, text and reasoning updates, tool execution, and errors.",
        "properties": {
          "timestamp": {"type": "string", "format": "date-time", "description": "When the event occurred"},
          "type": {
            "type": "string",
            "pattern": "^pi-",
            "description": "Pi event type. Common values include pi-message_update, pi-tool_execution_start, pi-tool_execution_update, pi-tool_execution_end, and pi-error."
          },
          "payload": {
            "type": "object",
            "description": "Pi event payload. Shape depends on the parent event type.",
            "additionalProperties": true
          }
        },
        "required": ["timestamp", "type", "payload"]
      },
      "CodexEventPayload": {
        "description": "Payload of a Codex CLI agent event. Shape depends on the parent event `type`.",
        "oneOf": [
          {"$ref": "#/components/schemas/CodexEventMsgPayload"},
          {"$ref": "#/components/schemas/CodexResponseItemPayload"}
        ],
        "discriminator": {
          "propertyName": "type",
          "mapping": {
            "user_message": "#/components/schemas/CodexEventMsgPayload",
            "agent_reasoning": "#/components/schemas/CodexEventMsgPayload",
            "message": "#/components/schemas/CodexResponseItemPayload",
            "function_call": "#/components/schemas/CodexResponseItemPayload",
            "function_call_output": "#/components/schemas/CodexResponseItemPayload",
            "custom_tool_call": "#/components/schemas/CodexResponseItemPayload",
            "custom_tool_call_output": "#/components/schemas/CodexResponseItemPayload"
          }
        }
      },
      "CodexEventMsgPayload": {
        "type": "object",
        "description": "Payload for `event_msg` events — high-level user or reasoning messages.",
        "properties": {
          "type": {
            "type": "string",
            "enum": ["user_message", "agent_reasoning"],
            "description": "`user_message` for user input, `agent_reasoning` for the agent's chain-of-thought"
          },
          "message": {"type": "string", "description": "User message text (present when type is `user_message`)"},
          "text": {"type": "string", "description": "Reasoning text (present when type is `agent_reasoning`)"}
        },
        "required": ["type"]
      },
      "CodexResponseItemPayload": {
        "type": "object",
        "description": "Payload for `response_item` events — structured items from the Codex response stream.",
        "oneOf": [
          {
            "type": "object",
            "title": "AssistantMessage",
            "description": "A text message from the Codex agent.",
            "properties": {
              "type": {"type": "string", "const": "message"},
              "role": {"type": "string", "const": "assistant"},
              "content": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "type": {"type": "string", "const": "output_text"},
                    "text": {"type": "string", "description": "The text content"}
                  },
                  "required": ["type", "text"]
                }
              }
            },
            "required": ["type", "role", "content"]
          },
          {
            "type": "object",
            "title": "FunctionCall",
            "description": "A function call by the Codex agent (shell commands, plan updates).",
            "properties": {
              "type": {"type": "string", "const": "function_call"},
              "call_id": {
                "type": "string",
                "description": "Unique ID for this call, referenced by the corresponding `function_call_output`"
              },
              "name": {
                "type": "string",
                "enum": ["shell", "shell_command", "exec_command", "update_plan"],
                "description": "Function name"
              },
              "arguments": {
                "type": "string",
                "description": "JSON-encoded arguments (e.g. `{\"command\": \"ls -la\"}` for shell commands, `{\"plan\": [...]}` for plan updates)"
              }
            },
            "required": ["type", "call_id", "name", "arguments"]
          },
          {
            "type": "object",
            "title": "FunctionCallOutput",
            "description": "Output from a previously invoked function call.",
            "properties": {
              "type": {"type": "string", "const": "function_call_output"},
              "call_id": {"type": "string", "description": "ID of the function_call this output corresponds to"},
              "output": {
                "type": "string",
                "description": "Raw output string. For shell commands this may include exit codes and stdout/stderr."
              }
            },
            "required": ["type", "call_id", "output"]
          },
          {
            "type": "object",
            "title": "CustomToolCall",
            "description": "A custom tool invocation (e.g. `apply_patch` for file edits).",
            "properties": {
              "type": {"type": "string", "const": "custom_tool_call"},
              "call_id": {"type": "string", "description": "Unique ID for this call"},
              "name": {"type": "string", "description": "Tool name (e.g. `apply_patch`)"},
              "input": {"type": "string", "description": "Tool input (e.g. patch content for `apply_patch`)"},
              "status": {
                "type": "string",
                "enum": ["in_progress", "completed", "failed"],
                "description": "Current execution status"
              }
            },
            "required": ["type", "call_id", "name", "input"]
          },
          {
            "type": "object",
            "title": "CustomToolCallOutput",
            "description": "Output from a custom tool call.",
            "properties": {
              "type": {"type": "string", "const": "custom_tool_call_output"},
              "call_id": {"type": "string", "description": "ID of the custom_tool_call this output corresponds to"},
              "output": {"type": "string", "description": "JSON-encoded output with optional `metadata.exit_code`"}
            },
            "required": ["type", "call_id", "output"]
          }
        ],
        "discriminator": {"propertyName": "type"}
      },
      "SuccessResponse": {
        "type": "object",
        "description": "Generic success response.",
        "properties": {"success": {"type": "boolean"}},
        "required": ["success"]
      },
      "OnboardingSteps": {
        "type": "object",
        "properties": {
          "added_repository": {"type": "boolean"},
          "skipped_repository": {"type": "boolean"},
          "connected_code_editor": {"type": "boolean"},
          "created_workspace": {"type": "boolean"},
          "connected_integration": {"type": "boolean"},
          "configured_github_triggers": {"type": "boolean"},
          "invited_member": {"type": "boolean"}
        },
        "required": [
          "added_repository",
          "skipped_repository",
          "connected_code_editor",
          "created_workspace",
          "connected_integration",
          "configured_github_triggers",
          "invited_member"
        ]
      },
      "OnboardingState": {
        "type": "object",
        "properties": {"completed": {"type": "boolean"}, "steps": {"$ref": "#/components/schemas/OnboardingSteps"}},
        "required": ["completed", "steps"]
      },
      "GetOnboardingStatusResponse": {
        "type": "object",
        "properties": {"onboarding": {"$ref": "#/components/schemas/OnboardingState"}},
        "required": ["onboarding"]
      },
      "OnboardingOrganizationMatch": {
        "type": "object",
        "properties": {
          "memberCount": {"type": "integer", "minimum": 0},
          "id": {"type": "string", "format": "uuid"},
          "name": {"type": "string"},
          "connectedAccount": {"type": "boolean"},
          "isMember": {"type": "boolean"},
          "canJoin": {"type": "boolean"}
        },
        "required": ["memberCount", "id", "name", "connectedAccount", "isMember", "canJoin"]
      },
      "GetOnboardingOrganizationsResponse": {
        "type": "object",
        "properties": {
          "organizations": {"type": "array", "items": {"$ref": "#/components/schemas/OnboardingOrganizationMatch"}},
          "membershipVerificationError": {"type": ["string", "null"]}
        },
        "required": ["organizations", "membershipVerificationError"]
      },
      "JoinOnboardingOrganizationResponse": {
        "type": "object",
        "properties": {"organization": {"$ref": "#/components/schemas/OnboardingOrganizationMatch"}},
        "required": ["organization"]
      },
      "AccessGrant": {
        "type": "object",
        "description": "A single grant. A null `resource_id` grants every resource of that type in the organization; a UUID grants only that resource. Write implies Read.",
        "properties": {
          "resource_type": {"type": "string", "enum": ["environments", "automations", "analytics"]},
          "resource_id": {
            "type": ["string", "null"],
            "format": "uuid",
            "description": "Null means every resource of this type. Always null for `analytics`."
          },
          "scope": {
            "type": "string",
            "enum": ["environments:read", "environments:write", "automations:read", "automations:write", "analytics:read"]
          }
        },
        "required": ["resource_type", "resource_id", "scope"]
      },
      "OrganizationAccessPolicy": {
        "type": "object",
        "properties": {
          "everyone": {
            "type": "array",
            "items": {"$ref": "#/components/schemas/AccessGrant"},
            "description": "Grants that apply to every member of the organization."
          },
          "roles": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "role_id": {"type": "string", "format": "uuid"},
                "grants": {"type": "array", "items": {"$ref": "#/components/schemas/AccessGrant"}}
              },
              "required": ["role_id", "grants"]
            }
          }
        },
        "required": ["everyone", "roles"]
      },
      "UpdateOrganizationAccessPolicyRequest": {
        "type": "object",
        "properties": {"grants": {"type": "array", "items": {"$ref": "#/components/schemas/AccessGrant"}}},
        "required": ["grants"]
      },
      "UpdateOrganizationAccessPolicyResponse": {
        "type": "object",
        "properties": {"grants": {"type": "array", "items": {"$ref": "#/components/schemas/AccessGrant"}}},
        "required": ["grants"]
      },
      "OrganizationMembership": {
        "type": "object",
        "properties": {
          "role": {"type": "string", "enum": ["admin", "member"]},
          "userId": {"type": "string", "format": "uuid"},
          "organizationId": {"type": "string", "format": "uuid"},
          "scopes": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": ["environments:read", "environments:write", "automations:read", "automations:write", "analytics:read"]
            },
            "description": "Organization-wide scopes in effect for the caller, from grants whose `resource_id` is null. Admins hold every scope. Per-resource grants are not listed here; they appear as `access` on each record."
          }
        },
        "required": ["role", "userId", "organizationId", "scopes"]
      },
      "EnvironmentAccess": {
        "type": "object",
        "description": "Effective permissions for the caller. Read allows discovery, full inspection, and selection for workspaces or automations. Write allows all mutations and implies Read.",
        "properties": {"can_write": {"type": "boolean"}, "can_read": {"type": "boolean"}},
        "required": ["can_read", "can_write"]
      },
      "Environment": {
        "type": "object",
        "description": "The configuration a workspace starts with. An environment builds on its `source_environment_id` chain, starting at its root. Personal environments have `user_id` set and are visible only to their owner.",
        "properties": {
          "id": {"type": "string", "format": "uuid", "description": "Unique identifier"},
          "organization_id": {"type": "string", "format": "uuid", "description": "Owning organization"},
          "user_id": {
            "type": ["string", "null"],
            "format": "uuid",
            "description": "Owning user for personal environments. Null for team environments."
          },
          "name": {"type": "string", "description": "Human-readable name"},
          "description": {"type": ["string", "null"], "description": "Optional description"},
          "repository_ids": {
            "type": "array",
            "items": {"type": "string", "format": "uuid"},
            "description": "Repositories workspaces in this environment clone, in checkout order. Inherited from the source environment when `inherit_repositories` is true. Empty = repo-less workspace."
          },
          "inherit_repositories": {
            "type": "boolean",
            "description": "True when this environment uses its source environment's repositories."
          },
          "system_prompt": {
            "type": ["string", "null"],
            "description": "Optional system prompt prepended to every workspace's coding agent."
          },
          "personal_preferences": {
            "type": ["string", "null"],
            "description": "User-authored instructions appended after the (inherited) system prompt. Only settable on personal environments, and editable even on forks."
          },
          "source_environment_id": {
            "type": ["string", "null"],
            "format": "uuid",
            "description": "Parent environment this one forks; unset fields are inherited from it. Null for environments that are not forks."
          },
          "variable_count": {"type": "integer", "description": "Number of variables attached to this environment"},
          "file_count": {"type": "integer", "description": "Number of files"},
          "skill_count": {"type": "integer", "description": "Number of enabled skills"},
          "mcp_count": {"type": "integer", "description": "Number of MCPs"},
          "access": {
            "$ref": "#/components/schemas/EnvironmentAccess",
            "description": "Effective permissions for the authenticated member. Omitted from internal workspace-authenticated responses."
          },
          "status": {
            "$ref": "#/components/schemas/EnvironmentStatus",
            "description": "What a workspace created now starts with. Returned by list and get."
          },
          "created_at": {"type": "string", "format": "date-time"},
          "updated_at": {"type": "string", "format": "date-time"}
        },
        "required": [
          "id",
          "organization_id",
          "user_id",
          "name",
          "description",
          "repository_ids",
          "inherit_repositories",
          "system_prompt",
          "personal_preferences",
          "source_environment_id",
          "created_at",
          "updated_at"
        ]
      },
      "ListEnvironmentsResponse": {
        "type": "object",
        "properties": {"environments": {"type": "array", "items": {"$ref": "#/components/schemas/Environment"}}},
        "required": ["environments"]
      },
      "EnvironmentResponse": {
        "type": "object",
        "properties": {"environment": {"$ref": "#/components/schemas/Environment"}},
        "required": ["environment"]
      },
      "CreateEnvironmentRequest": {
        "type": "object",
        "description": "Request body for creating a new environment.",
        "properties": {
          "name": {"type": "string", "description": "Human-readable name (must be unique within the selected scope)"},
          "description": {"type": ["string", "null"], "description": "Optional description"},
          "scope": {
            "type": "string",
            "enum": ["org", "user"],
            "default": "org",
            "description": "`org` creates a team environment. `user` creates a personal environment visible only to the authenticated user."
          },
          "source_environment_id": {
            "type": ["string", "null"],
            "format": "uuid",
            "description": "Optional parent. Creates a live fork, as in Fork environment; the repository binding, system prompt, and memory settings in the body are ignored."
          },
          "repository_ids": {
            "type": "array",
            "items": {"type": "string", "format": "uuid"},
            "description": "Repositories to clone, in checkout order."
          },
          "system_prompt": {"type": ["string", "null"], "description": "Optional system prompt prepended to the coding agent."}
        },
        "required": ["name"]
      },
      "UpdateEnvironmentRequest": {
        "type": "object",
        "description": "Request body for updating an environment. Only provided fields are changed.",
        "properties": {
          "name": {"type": "string"},
          "description": {"type": ["string", "null"]},
          "repository_ids": {
            "type": "array",
            "items": {"type": "string", "format": "uuid"},
            "description": "Replaces the repositories this environment clones, in checkout order. An empty array removes all. Requires write access to the environment."
          },
          "system_prompt": {"type": ["string", "null"]},
          "default_skills": {
            "$ref": "#/components/schemas/DefaultSkills",
            "description": "Sets default skills on this environment. Switches you omit keep their inherited value, and only switches that differ from the inherited value are stored."
          },
          "personal_preferences": {
            "type": ["string", "null"],
            "description": "Only settable on personal environments. Appended after the (inherited) system prompt."
          }
        }
      },
      "DefaultSkills": {
        "type": "object",
        "description": "Built-in skills installed in every workspace. Omitted abilities default to enabled.",
        "properties": {
          "replicas_agent": {
            "type": "object",
            "properties": {
              "enabled": {"type": "boolean"},
              "abilities": {
                "type": "object",
                "description": "Ability name to enabled flag.",
                "additionalProperties": {"type": "boolean"}
              }
            }
          }
        }
      },
      "WorkspaceIdentityDiscovery": {
        "type": "object",
        "properties": {
          "issuer": {"type": "string"},
          "jwks_uri": {"type": "string"},
          "subject_types_supported": {"type": "array", "items": {"type": "string"}},
          "response_types_supported": {"type": "array", "items": {"type": "string"}},
          "id_token_signing_alg_values_supported": {"type": "array", "items": {"type": "string"}},
          "claims_supported": {"type": "array", "items": {"type": "string"}},
          "scopes_supported": {"type": "array", "items": {"type": "string"}}
        },
        "required": ["issuer", "jwks_uri", "id_token_signing_alg_values_supported", "claims_supported"]
      },
      "WorkspaceIdentityJwks": {
        "type": "object",
        "properties": {
          "keys": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "kty": {"type": "string", "enum": ["RSA"]},
                "kid": {"type": "string", "description": "RFC 7638 thumbprint of the key"},
                "use": {"type": "string", "enum": ["sig"]},
                "alg": {"type": "string", "enum": ["RS256"]},
                "n": {"type": "string"},
                "e": {"type": "string"}
              },
              "required": ["kty", "kid", "n", "e"]
            }
          }
        },
        "required": ["keys"]
      },
      "WorkloadIdentityResponse": {
        "type": "object",
        "description": "Issuer configuration workspaces mint tokens against. Contains no token values.",
        "properties": {
          "configured": {"type": "boolean"},
          "issuer": {"type": "string", "nullable": true},
          "discovery_url": {"type": "string", "nullable": true},
          "jwks_url": {"type": "string", "nullable": true}
        },
        "required": ["configured", "issuer", "discovery_url", "jwks_url"]
      },
      "McpWorkloadAuth": {
        "description": "Authenticate using a short-lived workspace identity token minted for the given audience, or an OAuth account connected in the app.",
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "type": {"type": "string", "enum": ["workspace_identity"]},
              "audience": {"type": "string", "description": "Audience (`aud`) the MCP server verifies, usually its URL."}
            },
            "required": ["type", "audience"]
          },
          {
            "type": "object",
            "properties": {
              "type": {"type": "string", "enum": ["oauth"]}
            },
            "required": ["type"]
          }
        ]
      },
      "EnvironmentVariable": {
        "type": "object",
        "description": "An environment variable. Values are encrypted at rest and decrypted on read.",
        "properties": {
          "id": {"type": "string", "format": "uuid"},
          "organization_id": {"type": "string", "format": "uuid"},
          "environment_id": {"type": "string", "format": "uuid"},
          "key": {"type": "string", "description": "Variable name (e.g. `DATABASE_URL`)"},
          "value": {"type": "string", "description": "Variable value (returned in plaintext)"},
          "locked": {
            "type": "boolean",
            "description": "Whether environments that inherit this variable are blocked from overriding it"
          },
          "created_at": {"type": "string", "format": "date-time"},
          "updated_at": {"type": "string", "format": "date-time"}
        },
        "required": [
          "id",
          "organization_id",
          "environment_id",
          "key",
          "value",
          "locked",
          "created_at",
          "updated_at"
        ]
      },
      "ListEnvironmentVariablesResponse": {
        "type": "object",
        "properties": {"environment_variables": {"type": "array", "items": {"$ref": "#/components/schemas/EnvironmentVariable"}}},
        "required": ["environment_variables"]
      },
      "EnvironmentVariableResponse": {
        "type": "object",
        "properties": {"environment_variable": {"$ref": "#/components/schemas/EnvironmentVariable"}},
        "required": ["environment_variable"]
      },
      "CreateEnvironmentVariableRequest": {
        "type": "object",
        "description": "Request body for creating an environment variable.",
        "properties": {
          "key": {"type": "string", "description": "Variable name"},
          "value": {"type": "string", "description": "Variable value (encrypted at rest)"},
          "locked": {
            "type": "boolean",
            "description": "Blocks environments that inherit this variable from overriding it. Defaults to `false`. Admin only on team environments."
          }
        },
        "required": ["key", "value"]
      },
      "CreateEnvironmentVariablesRequest": {
        "type": "object",
        "properties": {
          "variables": {
            "type": "array",
            "maxItems": 200,
            "items": {
              "type": "object",
              "properties": {"key": {"type": "string"}, "value": {"type": "string"}},
              "required": ["key", "value"]
            }
          }
        },
        "required": ["variables"]
      },
      "UpdateEnvironmentVariableRequest": {
        "type": "object",
        "description": "Request body for updating an environment variable. Only provided fields are changed.",
        "properties": {
          "key": {"type": "string"},
          "value": {"type": "string"},
          "locked": {
            "type": "boolean",
            "description": "Blocks environments that inherit this variable from overriding it. Defaults to `false`. Admin only on team environments."
          }
        }
      },
      "InheritanceKeyRequest": {
        "type": "object",
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "variable",
              "file",
              "mcp",
              "skill",
              "skills_registry",
              "plugin",
              "integration"
            ]
          },
          "key": {
            "type": "string",
            "description": "Variable key, file path, MCP name, skill slug, registry URL, plugin id, or `doppler`/`infisical`."
          }
        },
        "required": [
          "kind",
          "key"
        ]
      },
      "ResetInheritedRequest": {
        "type": "object",
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "variable",
              "file",
              "mcp",
              "skill",
              "skills_registry",
              "plugin",
              "integration",
              "repository",
              "memory",
              "default_skills"
            ]
          },
          "key": {
            "type": "string",
            "description": "Required for keyed kinds."
          }
        },
        "required": [
          "kind"
        ]
      },
      "EffectiveEnvironmentItem": {
        "type": "object",
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "variable",
              "file",
              "mcp",
              "skill",
              "skills_registry",
              "plugin",
              "integration"
            ]
          },
          "key": {
            "type": "string"
          },
          "origin_environment_id": {
            "type": "string",
            "format": "uuid",
            "description": "Environment whose record is returned: the winner, or the hidden ancestor for `excluded`."
          },
          "status": {
            "type": "string",
            "enum": [
              "own",
              "inherited",
              "overridden",
              "excluded"
            ]
          },
          "inherited_from_environment_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "locked": {
            "type": "boolean",
            "description": "An ancestor locked this variable, so it can't be overridden or excluded here."
          },
          "masked": {
            "type": "boolean"
          },
          "record": {
            "type": "object",
            "description": "The variable, file, MCP, skill, registry, plugin connection, or `{environment_id, provider}` record."
          }
        },
        "required": [
          "kind",
          "key",
          "origin_environment_id",
          "status",
          "inherited_from_environment_id",
          "locked",
          "masked",
          "record"
        ]
      },
      "EffectiveEnvironmentResponse": {
        "type": "object",
        "properties": {
          "chain": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "format": "uuid"
                },
                "name": {
                  "type": "string"
                },
                "user_id": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            }
          },
          "system_prompts": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "environment_id": {
                  "type": "string",
                  "format": "uuid"
                },
                "system_prompt": {
                  "type": "string"
                }
              }
            }
          },
          "repository": {
            "type": "object",
            "properties": {
              "repository_ids": {
                "type": "array",
                "items": {"type": "string", "format": "uuid"}
              },
              "origin_environment_id": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "memory": {
            "type": "object",
            "properties": {
              "read": {
                "type": "boolean"
              },
              "read_origin_environment_id": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "write": {
                "type": "boolean"
              },
              "write_origin_environment_id": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "default_skills": {
            "type": "object",
            "properties": {
              "value": {
                "$ref": "#/components/schemas/DefaultSkills"
              },
              "origin_environment_id": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Nearest environment in the chain that sets default skills; null when the built-in defaults apply."
              }
            }
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EffectiveEnvironmentItem"
            }
          }
        },
        "required": [
          "chain",
          "system_prompts",
          "repository",
          "memory",
          "default_skills",
          "items"
        ]
      },
      "ForkEnvironmentRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "scope": {
            "type": "string",
            "enum": [
              "org",
              "user"
            ],
            "default": "org"
          }
        },
        "required": [
          "name"
        ]
      },
      "DetachEnvironmentResponse": {
        "type": "object",
        "properties": {
          "environment": {
            "$ref": "#/components/schemas/Environment"
          },
          "not_copied": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "kind": {
                  "type": "string"
                },
                "key": {
                  "type": "string"
                },
                "reason": {
                  "type": "string"
                }
              },
              "required": [
                "kind",
                "key",
                "reason"
              ]
            }
          }
        },
        "required": [
          "environment",
          "not_copied"
        ]
      },
      "EnvironmentFile": {
        "type": "object",
        "description": "A file dropped into the workspace at the configured `path` when the workspace is provisioned.",
        "properties": {
          "id": {"type": "string", "format": "uuid"},
          "organization_id": {"type": "string", "format": "uuid"},
          "environment_id": {"type": "string", "format": "uuid"},
          "name": {"type": "string", "description": "Human-readable name"},
          "path": {"type": "string", "description": "Destination path inside the workspace (typically under `~/`)"},
          "content": {"type": "string", "description": "File contents (≤ 64 KB)"},
          "created_at": {"type": "string", "format": "date-time"},
          "updated_at": {"type": "string", "format": "date-time"}
        },
        "required": ["id", "organization_id", "environment_id", "name", "path", "content", "created_at", "updated_at"]
      },
      "ListEnvironmentFilesResponse": {
        "type": "object",
        "properties": {"environment_files": {"type": "array", "items": {"$ref": "#/components/schemas/EnvironmentFile"}}},
        "required": ["environment_files"]
      },
      "EnvironmentFileResponse": {
        "type": "object",
        "properties": {"environment_file": {"$ref": "#/components/schemas/EnvironmentFile"}},
        "required": ["environment_file"]
      },
      "CreateEnvironmentFileRequest": {
        "type": "object",
        "description": "Request body for creating an environment file. Maximum content size is 64 KB (65,536 bytes).",
        "properties": {
          "name": {"type": "string"},
          "path": {"type": "string", "description": "Destination path inside the workspace, e.g. `~/AGENTS.md`"},
          "content": {"type": "string", "description": "File contents (≤ 64 KB)"}
        },
        "required": ["name", "path", "content"]
      },
      "UpdateEnvironmentFileRequest": {
        "type": "object",
        "description": "Request body for updating an environment file. Only provided fields are changed.",
        "properties": {"name": {"type": "string"}, "path": {"type": "string"}, "content": {"type": "string"}}
      },
      "EnvironmentSkill": {
        "type": "object",
        "description": "A skill enabled on an environment. The membership row, not the catalog entry.",
        "properties": {
          "id": {"type": "string", "format": "uuid"},
          "organization_id": {"type": "string", "format": "uuid"},
          "environment_id": {"type": "string", "format": "uuid"},
          "name": {"type": "string", "description": "Display name"},
          "slug": {"type": "string", "description": "Catalog slug (unique within an environment)"},
          "source": {"type": "string", "description": "Catalog URL or other source identifier"},
          "created_at": {"type": "string", "format": "date-time"},
          "updated_at": {"type": "string", "format": "date-time"}
        },
        "required": ["id", "organization_id", "environment_id", "name", "slug", "source", "created_at", "updated_at"]
      },
      "ListEnvironmentSkillsResponse": {
        "type": "object",
        "properties": {"environment_skills": {"type": "array", "items": {"$ref": "#/components/schemas/EnvironmentSkill"}}},
        "required": ["environment_skills"]
      },
      "EnvironmentSkillResponse": {
        "type": "object",
        "properties": {"environment_skill": {"$ref": "#/components/schemas/EnvironmentSkill"}},
        "required": ["environment_skill"]
      },
      "CreateEnvironmentSkillRequest": {
        "type": "object",
        "description": "Request body for enabling a skill on an environment.",
        "properties": {
          "name": {"type": "string", "description": "Display name (typically copied from the catalog result)"},
          "slug": {"type": "string", "description": "Catalog slug"},
          "source": {"type": "string", "description": "Catalog URL or other source identifier"}
        },
        "required": ["name", "slug", "source"]
      },
      "RepoSkillFramework": {
        "type": "string",
        "description": "Which AI tool owns the discovered file's on-disk convention.",
        "enum": ["claude", "codex", "cursor", "agents"]
      },
      "RepoSkill": {
        "type": "object",
        "description": "A skill/agent/command/prompt file discovered inside the environment's bound repo. Distinct from `EnvironmentSkill`: these are inferred live from the repo's git tree, are read-only, and have no DB row.",
        "properties": {
          "id": {"type": "string", "description": "Stable id, formed from the repository UUID and the in-repo path."},
          "repository_id": {"type": "string", "format": "uuid"},
          "repository_full_name": {"type": "string", "description": "Repo's `owner/name` (denormalized for the UI)."},
          "branch": {"type": "string", "description": "Default branch the file was resolved against."},
          "path": {"type": "string", "description": "Repo-relative path of the discovered file or skill directory."},
          "name": {
            "type": "string",
            "description": "Human-friendly name (from YAML frontmatter when present, otherwise the filename or directory)."
          },
          "description": {
            "type": ["string", "null"],
            "description": "Single-line description, populated from frontmatter when available."
          },
          "framework": {"$ref": "#/components/schemas/RepoSkillFramework"},
          "kind": {
            "type": "string",
            "description": "Sub-kind within the framework.",
            "enum": ["skill", "agent", "command", "prompt", "plugin"]
          },
          "html_url": {"type": "string", "format": "uri", "description": "Direct GitHub blob link."}
        },
        "required": [
          "id",
          "repository_id",
          "repository_full_name",
          "branch",
          "path",
          "name",
          "description",
          "framework",
          "kind",
          "html_url"
        ]
      },
      "ListRepoSkillsResponse": {
        "type": "object",
        "properties": {
          "repo_skills": {"type": "array", "items": {"$ref": "#/components/schemas/RepoSkill"}},
          "error": {
            "type": ["string", "null"],
            "description": "Populated when discovery couldn't run end-to-end (e.g. the bound repo has no GitHub App installation). The list may still be partially filled; the UI shows this as an inline banner rather than a 5xx."
          }
        },
        "required": ["repo_skills", "error"]
      },
      "EnvironmentSkillsRegistry": {
        "type": "object",
        "description": "A GitHub repository registered as a skill registry on an environment.",
        "properties": {
          "id": {"type": "string", "format": "uuid"},
          "organization_id": {"type": "string", "format": "uuid"},
          "environment_id": {"type": "string", "format": "uuid"},
          "name": {"type": "string"},
          "url": {"type": "string", "format": "uri"},
          "repository_full_name": {"type": "string"},
          "default_branch": {"type": "string"},
          "created_at": {"type": "string", "format": "date-time"},
          "updated_at": {"type": "string", "format": "date-time"}
        },
        "required": [
          "id",
          "organization_id",
          "environment_id",
          "name",
          "url",
          "repository_full_name",
          "default_branch",
          "created_at",
          "updated_at"
        ]
      },
      "EnvironmentSkillsRegistryWithContents": {
        "type": "object",
        "description": "A skill registry with its discovered skills.",
        "allOf": [
          {"$ref": "#/components/schemas/EnvironmentSkillsRegistry"},
          {
            "type": "object",
            "properties": {
              "repo_skills": {"type": "array", "items": {"$ref": "#/components/schemas/RepoSkill"}},
              "error": {"type": ["string", "null"]}
            },
            "required": ["repo_skills", "error"]
          }
        ]
      },
      "ListEnvironmentSkillsRegistriesResponse": {
        "type": "object",
        "properties": {
          "registries": {"type": "array", "items": {"$ref": "#/components/schemas/EnvironmentSkillsRegistryWithContents"}}
        },
        "required": ["registries"]
      },
      "CreateEnvironmentSkillsRegistryResponse": {
        "type": "object",
        "properties": {
          "registry": {"$ref": "#/components/schemas/EnvironmentSkillsRegistry"},
          "repo_skills": {"type": "array", "items": {"$ref": "#/components/schemas/RepoSkill"}},
          "error": {"type": ["string", "null"]}
        },
        "required": ["registry", "repo_skills", "error"]
      },
      "SearchSkill": {
        "type": "object",
        "description": "A skill catalog search result.",
        "properties": {
          "name": {"type": "string"},
          "slug": {"type": "string"},
          "source": {"type": "string"},
          "installs": {"type": "integer", "description": "Approximate install count from the catalog"}
        },
        "required": ["name", "slug", "source", "installs"]
      },
      "SearchEnvironmentSkillsResponse": {
        "type": "object",
        "properties": {"skills": {"type": "array", "items": {"$ref": "#/components/schemas/SearchSkill"}}},
        "required": ["skills"]
      },
      "EnvironmentMcpStdioConfig": {
        "type": "object",
        "description": "Configuration for an MCP that runs a local subprocess (`transport: stdio`).",
        "properties": {
          "command": {"type": "string", "description": "Executable to run (e.g. `npx`)"},
          "args": {"type": "array", "items": {"type": "string"}, "description": "Arguments passed to the command"},
          "env": {
            "type": "object",
            "additionalProperties": {"type": "string"},
            "description": "Environment variables for the subprocess"
          }
        },
        "required": ["command", "args", "env"]
      },
      "EnvironmentMcpHttpConfig": {
        "type": "object",
        "description": "Configuration for an MCP reached over HTTP or SSE (`transport: http` or `transport: sse`).",
        "properties": {
          "auth": {"$ref": "#/components/schemas/McpWorkloadAuth"},
          "url": {"type": "string", "format": "uri", "description": "MCP server URL"},
          "headers": {
            "type": "object",
            "additionalProperties": {"type": "string"},
            "description": "Headers attached to every request (e.g. `Authorization`)"
          }
        },
        "required": ["url", "headers"]
      },
      "EnvironmentMcpConfig": {
        "description": "MCP transport-specific configuration. Discriminate by the parent `transport` field.",
        "oneOf": [
          {"$ref": "#/components/schemas/EnvironmentMcpStdioConfig"},
          {"$ref": "#/components/schemas/EnvironmentMcpHttpConfig"}
        ]
      },
      "EnvironmentMcp": {
        "type": "object",
        "description": "An MCP (Model Context Protocol) server attached to an environment.",
        "properties": {
          "id": {"type": "string", "format": "uuid"},
          "organization_id": {"type": "string", "format": "uuid"},
          "environment_id": {"type": "string", "format": "uuid"},
          "name": {
            "type": "string",
            "description": "MCP name (1–64 chars, must match `^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$`; cannot start with reserved prefixes `relay-`, `replicas-`, or `subagents`)"
          },
          "transport": {"type": "string", "enum": ["stdio", "http", "sse"]},
          "config": {"$ref": "#/components/schemas/EnvironmentMcpConfig"},
          "oauth": {
            "type": "object",
            "description": "Connection state for MCPs using OAuth. Returned when listing MCPs.",
            "properties": {
              "status": {"type": "string", "enum": ["disconnected", "connected", "reconnect_required"]},
              "reason": {"type": "string", "nullable": true, "description": "Why a reconnect is required"}
            },
            "required": ["status", "reason"]
          },
          "created_at": {"type": "string", "format": "date-time"},
          "updated_at": {"type": "string", "format": "date-time"}
        },
        "required": ["id", "organization_id", "environment_id", "name", "transport", "config", "created_at", "updated_at"]
      },
      "ListEnvironmentMcpsResponse": {
        "type": "object",
        "properties": {"environment_mcps": {"type": "array", "items": {"$ref": "#/components/schemas/EnvironmentMcp"}}},
        "required": ["environment_mcps"]
      },
      "EnvironmentMcpResponse": {
        "type": "object",
        "properties": {"environment_mcp": {"$ref": "#/components/schemas/EnvironmentMcp"}},
        "required": ["environment_mcp"]
      },
      "CreateEnvironmentMcpRequest": {
        "type": "object",
        "description": "Request body for creating an MCP. The `config` shape must match the chosen `transport`.",
        "properties": {
          "name": {
            "type": "string",
            "description": "1–64 chars, `^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$`; reserved prefixes `relay-`, `replicas-`, and `subagents` are rejected."
          },
          "transport": {"type": "string", "enum": ["stdio", "http", "sse"]},
          "config": {"$ref": "#/components/schemas/EnvironmentMcpConfig"}
        },
        "required": ["name", "transport", "config"]
      },
      "UpdateEnvironmentMcpRequest": {
        "type": "object",
        "description": "Request body for updating an MCP. Only provided fields are changed. When `transport` is changed, `config` is required and must match the new transport's shape.",
        "properties": {
          "name": {"type": "string"},
          "transport": {"type": "string", "enum": ["stdio", "http", "sse"]},
          "config": {"$ref": "#/components/schemas/EnvironmentMcpConfig"}
        }
      },
      "WarmHookRecord": {
        "type": "object",
        "description": "A warm hook — the shell script that runs while pre-warming workspaces for an environment.",
        "properties": {
          "id": {"type": "string", "format": "uuid"},
          "organization_id": {"type": "string", "format": "uuid"},
          "environment_id": {"type": "string", "format": "uuid"},
          "version": {"type": "integer", "description": "Monotonic version (newer scripts have higher versions)"},
          "content": {"type": "string", "description": "Shell script content"},
          "is_active": {"type": "boolean", "description": "Whether this version is the active one for the environment"},
          "created_at": {"type": "string", "format": "date-time"}
        },
        "required": ["id", "organization_id", "environment_id", "version", "content", "is_active", "created_at"]
      },
      "WarmPoolConfigWithStats": {
        "type": "object",
        "description": "Warm pool configuration plus current pool counts.",
        "properties": {
          "id": {"type": "string", "format": "uuid"},
          "organization_id": {"type": "string", "format": "uuid"},
          "environment_id": {"type": "string", "format": "uuid"},
          "enabled": {"type": "boolean"},
          "target_size": {"type": "integer", "description": "Target number of pre-warmed workspaces, sized from the environment's recent demand"},
          "generation": {
            "type": "integer",
            "description": "Monotonic counter bumped on every invalidation. Workspaces and snapshots carry the generation they were built for; anything older is stale by derivation."
          },
          "error_count": {
            "type": "integer",
            "description": "Consecutive reconcile failures since the last success. Resets to 0 on success; drives exponential backoff via `next_retry_at`."
          },
          "next_retry_at": {
            "type": ["string", "null"],
            "format": "date-time",
            "description": "Earliest time the next reconcile pass may run for this config. Null when not in backoff."
          },
          "last_error_at": {
            "type": ["string", "null"],
            "format": "date-time",
            "description": "When the most recent reconcile error was recorded (null if no current error)."
          },
          "last_error_message": {"type": ["string", "null"], "description": "Most recent reconcile error message (null if no current error)."},
          "has_base_snapshot": {"type": "boolean", "description": "Whether the current generation has a base snapshot."},
          "updated_at": {"type": "string", "format": "date-time"},
          "ready_count": {
            "type": "integer",
            "description": "Number of pre-warmed workspaces at the current generation that are ready to be assigned"
          },
          "stale_count": {
            "type": "integer",
            "description": "Number of ready workspaces at older generations. Still claimable as a fallback; trimmed by reconcile when over target."
          },
          "warming_count": {
            "type": "integer",
            "description": "Number of workspaces at the current generation that are currently warming (warm hooks running)"
          },
          "snapshotting_count": {
            "type": "integer",
            "description": "Number of seed workspaces currently capturing a base snapshot (E2B only). Always 0 on providers without live snapshots."
          },
          "last_failure_at": {
            "type": ["string", "null"],
            "format": "date-time",
            "description": "When the most recent warm-up failure occurred (null if never)"
          },
          "last_failure_reason": {"type": ["string", "null"], "description": "Reason for the most recent warm-up failure"}
        },
        "required": [
          "id",
          "organization_id",
          "environment_id",
          "enabled",
          "target_size",
          "generation",
          "error_count",
          "next_retry_at",
          "last_error_at",
          "last_error_message",
          "has_base_snapshot",
          "updated_at",
          "ready_count",
          "stale_count",
          "warming_count",
          "snapshotting_count",
          "last_failure_at",
          "last_failure_reason"
        ]
      },
      "WarmPoolSnapshotRecord": {
        "type": "object",
        "description": "A retained provider snapshot for one successful warm-pool generation.",
        "properties": {
          "id": {"type": "string", "format": "uuid", "description": "Snapshot record UUID used by the restore endpoint"},
          "warm_pool_config_id": {"type": "string", "format": "uuid"},
          "generation": {"type": "integer", "description": "Warm-pool generation that captured this snapshot"},
          "is_current": {
            "type": "boolean",
            "description": "Whether the config is currently installed on this snapshot. Restoring an older version moves this flag back onto that version."
          },
          "is_fallback": {
            "type": "boolean",
            "description": "Whether this snapshot is serving while the current generation warms or recovers"
          },
          "created_at": {"type": "string", "format": "date-time"}
        },
        "required": ["id", "warm_pool_config_id", "generation", "is_current", "is_fallback", "created_at"]
      },
      "EnvironmentHookRunSummary": {
        "type": "object",
        "properties": {
          "id": {"type": "string", "format": "uuid"},
          "environment_id": {"type": "string", "format": "uuid"},
          "kind": {"type": "string", "enum": ["warm", "start"]},
          "status": {"type": "string", "enum": ["running", "succeeded", "failed", "cancelled"]},
          "exit_code": {"type": ["integer", "null"]},
          "timed_out": {"type": "boolean"},
          "warm_pool_build_id": {"type": ["string", "null"], "format": "uuid", "description": "Set on warm hook runs"},
          "workspace_id": {"type": ["string", "null"], "format": "uuid", "description": "Set on start hook runs"},
          "workspace_name": {"type": ["string", "null"]},
          "builder_workspace_id": {"type": ["string", "null"], "format": "uuid", "description": "While a warm hook runs, the warm pool workspace whose output stream shows it live"},
          "started_at": {"type": "string", "format": "date-time"},
          "finished_at": {"type": ["string", "null"], "format": "date-time"}
        },
        "required": ["id", "environment_id", "kind", "status", "exit_code", "timed_out", "warm_pool_build_id", "workspace_id", "workspace_name", "builder_workspace_id", "started_at", "finished_at"]
      },
      "EnvironmentHookRun": {
        "allOf": [
          {"$ref": "#/components/schemas/EnvironmentHookRunSummary"},
          {
            "type": "object",
            "properties": {
              "output": {"type": "string", "description": "The log, stored once the run finishes; empty while it runs"},
              "output_length": {"type": "integer", "description": "Characters the hook printed"},
              "output_truncated": {"type": "boolean", "description": "True when only the last 5 MB were kept"}
            },
            "required": ["output", "output_length", "output_truncated"]
          }
        ]
      },
      "ListEnvironmentHookRunsResponse": {
        "type": "object",
        "properties": {"runs": {"type": "array", "items": {"$ref": "#/components/schemas/EnvironmentHookRunSummary"}}},
        "required": ["runs"]
      },
      "GetEnvironmentHookRunResponse": {
        "type": "object",
        "properties": {"run": {"$ref": "#/components/schemas/EnvironmentHookRun"}},
        "required": ["run"]
      },
      "EnvironmentChange": {
        "type": "object",
        "description": "One edit waiting to reach new workspaces.",
        "properties": {
          "kind": {"type": "string", "enum": ["repositories", "warm_hook", "variable", "file", "skill", "skills_registry", "default_skills", "agent_auth", "workspace_size", "agent_setup", "restore", "system"]},
          "key": {"type": ["string", "null"], "description": "The edited row: variable key, file path, skill slug, registry, or provider"},
          "op": {"type": "string", "enum": ["created", "updated", "deleted"]},
          "user_id": {"type": ["string", "null"], "format": "uuid", "description": "Who made the edit"}
        },
        "required": ["kind", "key", "op", "user_id"]
      },
      "EnvironmentStatus": {
        "type": "object",
        "description": "`ready`: new workspaces start with the current setup. `applying`: `changes` reach new workspaces after `apply_after` (`waiting`) or once the warm hook finishes (`running`); until then they start with the previous setup. `needs_attention`: the latest changes failed to apply, so new workspaces start with the setup that went live at `live_since`.",
        "properties": {
          "state": {"type": "string", "enum": ["ready", "applying", "needs_attention"]},
          "phase": {"type": ["string", "null"], "enum": ["waiting", "running", "idle", null], "description": "`idle`: the environment is unused, so its saved changes build the next time someone starts or selects it"},
          "apply_after": {"type": ["string", "null"], "format": "date-time"},
          "live_since": {"type": ["string", "null"], "format": "date-time", "description": "When the setup new workspaces start with went live"},
          "first_setup": {"type": "boolean", "description": "True while applying an environment that has never been set up"},
          "changes": {"type": "array", "items": {"$ref": "#/components/schemas/EnvironmentChange"}},
          "failure": {
            "type": ["object", "null"],
            "properties": {
              "build_id": {"type": "string", "format": "uuid"},
              "kind": {"type": "string", "enum": ["hook", "infra"], "description": "`hook`: a warm hook failed; it is not retried until the next change or an explicit retry"},
              "message": {"type": ["string", "null"]},
              "failed_at": {"type": ["string", "null"], "format": "date-time"},
              "run_id": {"type": ["string", "null"], "format": "uuid", "description": "The failed warm hook run; its full log is at `/v1/environments/{environment_id}/hook-runs/{run_id}`"},
              "exit_code": {"type": ["integer", "null"]},
              "cause": {
                "type": ["object", "null"],
                "description": "Likely cause, read from the log tail and exit code. Null for infrastructure failures.",
                "properties": {
                  "kind": {"type": "string", "enum": ["timeout", "out_of_memory", "disk_full", "lockfile_mismatch", "missing_secret", "command_not_found", "network", "missing_file", "exit_code"]},
                  "summary": {"type": "string"},
                  "fix": {"type": "string"},
                  "line": {"type": ["string", "null"], "description": "The log line the cause was read from"}
                },
                "required": ["kind", "summary", "fix", "line"]
              },
              "log_tail": {"type": "array", "items": {"type": "string"}, "description": "Last lines of the log"}
            },
            "required": ["build_id", "kind", "message", "failed_at", "run_id", "exit_code", "cause", "log_tail"]
          }
        },
        "required": ["state", "phase", "apply_after", "live_since", "first_setup", "changes", "failure"]
      },
      "WarmPoolBuildRecord": {
        "type": "object",
        "description": "One warm pool generation that was asked to build.",
        "properties": {
          "id": {"type": "string", "format": "uuid"},
          "generation": {"type": "integer"},
          "status": {"type": "string", "enum": ["queued", "building", "succeeded", "failed", "superseded", "cancelled"]},
          "reasons": {"type": "array", "items": {"type": "string"}, "description": "Every change folded into this build while it was queued"},
          "attempts": {"type": "integer"},
          "queued_at": {"type": "string", "format": "date-time"},
          "build_after": {"type": "string", "format": "date-time", "description": "When a queued build starts unless more edits push it back"},
          "started_at": {"type": ["string", "null"], "format": "date-time"},
          "finished_at": {"type": ["string", "null"], "format": "date-time"},
          "superseded_by": {"type": ["string", "null"], "format": "uuid"},
          "error_message": {"type": ["string", "null"]},
          "builder_warm_pool_workspace_id": {"type": ["string", "null"], "format": "uuid", "description": "Warm pool workspace that ran the build; stream its output from `/v1/warm-pool-workspaces/{id}/stream`"},
          "changes": {"type": "array", "items": {"$ref": "#/components/schemas/EnvironmentChange"}, "description": "Edits this build applies, including those of earlier builds that never went live"},
          "failure_kind": {"type": ["string", "null"], "enum": ["hook", "infra", null]},
          "restorable": {"type": "boolean", "description": "The setup this build made live is stored and can be restored with `POST /v1/environments/{environment_id}/restore`"}
        },
        "required": ["id", "generation", "status", "reasons", "attempts", "queued_at", "build_after", "started_at", "finished_at", "superseded_by", "error_message", "builder_warm_pool_workspace_id", "changes", "failure_kind", "restorable"]
      },
      "WarmPoolServingState": {
        "type": "object",
        "properties": {
          "serving_build": {"oneOf": [{"$ref": "#/components/schemas/WarmPoolBuildRecord"}, {"type": "null"}], "description": "Build a workspace created now would be claimed from; null means it would start cold"},
          "serving_generation": {"type": ["integer", "null"]},
          "serving_is_current": {"type": "boolean"},
          "ready_count": {"type": "integer"},
          "current_ready_count": {"type": "integer"},
          "pending_build": {"oneOf": [{"$ref": "#/components/schemas/WarmPoolBuildRecord"}, {"type": "null"}], "description": "Queued or running build for the current generation"}
        },
        "required": ["serving_build", "serving_generation", "serving_is_current", "ready_count", "current_ready_count", "pending_build"]
      },
      "BuildWarmPoolNowResponse": {
        "type": "object",
        "properties": {"build": {"$ref": "#/components/schemas/WarmPoolBuildRecord"}},
        "required": ["build"]
      },
      "GetWarmHooksResponse": {
        "type": "object",
        "properties": {
          "warm_hook": {
            "oneOf": [{"$ref": "#/components/schemas/WarmHookRecord"}, {"type": "null"}],
            "description": "The active warm hook for the environment (null if none has ever been saved)."
          },
          "warm_pool": {
            "oneOf": [{"$ref": "#/components/schemas/WarmPoolConfigWithStats"}, {"type": "null"}],
            "description": "The warm pool config and current counts (null if no pool has been configured)."
          },
          "snapshots": {
            "type": "array",
            "description": "Up to 20 retained snapshots ordered newest first.",
            "items": {"$ref": "#/components/schemas/WarmPoolSnapshotRecord"}
          },
          "builds": {
            "type": "array",
            "description": "Up to 20 builds ordered newest first.",
            "items": {"$ref": "#/components/schemas/WarmPoolBuildRecord"}
          },
          "serving": {
            "oneOf": [{"$ref": "#/components/schemas/WarmPoolServingState"}, {"type": "null"}],
            "description": "Which build new workspaces come from now, and the build in progress (null if no pool has been configured)."
          }
        },
        "required": ["warm_hook", "warm_pool", "snapshots", "builds", "serving"]
      },
      "WarmHookTestResult": {
        "type": "object",
        "description": "Result of running a warm hook script in an isolated sandbox.",
        "properties": {
          "exit_code": {"type": "integer", "description": "Process exit code (0 = success)"},
          "output": {"type": "string", "description": "Captured stdout + stderr"},
          "timed_out": {"type": "boolean", "description": "Whether execution was killed for taking too long"}
        },
        "required": ["exit_code", "output", "timed_out"]
      },
      "SaveWarmHookRequest": {
        "type": "object",
        "properties": {
          "content": {
            "type": "string",
            "description": "Shell script to persist and activate. Empty content clears the active warm hook."
          }
        },
        "required": ["content"]
      },
      "SaveWarmHookResponse": {
        "type": "object",
        "properties": {
          "warm_hook": {
            "oneOf": [{"$ref": "#/components/schemas/WarmHookRecord"}, {"type": "null"}],
            "description": "The saved active warm hook, or null when the request cleared the active warm hook."
          }
        },
        "required": ["warm_hook"]
      },
      "SaveAndTestWarmHookRequest": {
        "type": "object",
        "properties": {"content": {"type": "string", "description": "Shell script to save and execute"}},
        "required": ["content"]
      },
      "SaveAndTestWarmHookResponse": {
        "type": "object",
        "properties": {
          "warm_hook": {"$ref": "#/components/schemas/WarmHookRecord"},
          "test": {"$ref": "#/components/schemas/WarmHookTestResult"}
        },
        "required": ["warm_hook", "test"]
      },
      "TestWarmHookRequest": {
        "type": "object",
        "properties": {"content": {"type": "string", "description": "Shell script to execute (not persisted)"}},
        "required": ["content"]
      },
      "TestWarmHookResponse": {
        "type": "object",
        "properties": {"test": {"$ref": "#/components/schemas/WarmHookTestResult"}},
        "required": ["test"]
      },
      "StartHookRecord": {
        "type": "object",
        "description": "A start hook — the shell script that runs at workspace boot (after the warm sandbox is claimed) for an environment.",
        "properties": {
          "id": {"type": "string", "format": "uuid"},
          "organization_id": {"type": "string", "format": "uuid"},
          "environment_id": {"type": "string", "format": "uuid"},
          "version": {"type": "integer", "description": "Monotonic version (newer scripts have higher versions)"},
          "content": {"type": "string", "description": "Shell script content"},
          "is_active": {"type": "boolean", "description": "Whether this version is the active one for the environment"},
          "created_at": {"type": "string", "format": "date-time"}
        },
        "required": ["id", "organization_id", "environment_id", "version", "content", "is_active", "created_at"]
      },
      "GetStartHooksResponse": {
        "type": "object",
        "properties": {
          "start_hook": {
            "oneOf": [{"$ref": "#/components/schemas/StartHookRecord"}, {"type": "null"}],
            "description": "The active start hook for the environment (null if none has ever been saved)."
          }
        },
        "required": ["start_hook"]
      },
      "SaveStartHookRequest": {
        "type": "object",
        "properties": {
          "content": {
            "type": "string",
            "description": "Shell script to persist and activate. Empty content clears the active start hook."
          }
        },
        "required": ["content"]
      },
      "SaveStartHookResponse": {
        "type": "object",
        "properties": {
          "start_hook": {
            "oneOf": [{"$ref": "#/components/schemas/StartHookRecord"}, {"type": "null"}],
            "description": "The saved active start hook, or null when the request cleared the active start hook."
          }
        },
        "required": ["start_hook"]
      },
      "StartHookTestResult": {
        "type": "object",
        "description": "Result of running a start hook script in an isolated sandbox.",
        "properties": {
          "exit_code": {"type": "integer", "description": "Process exit code (0 = success)"},
          "output": {"type": "string", "description": "Captured stdout + stderr"},
          "timed_out": {"type": "boolean", "description": "Whether execution was killed for taking too long"}
        },
        "required": ["exit_code", "output", "timed_out"]
      },
      "TestStartHookRequest": {
        "type": "object",
        "properties": {"content": {"type": "string", "description": "Shell script to execute (not persisted)"}},
        "required": ["content"]
      },
      "TestStartHookResponse": {
        "type": "object",
        "properties": {"test": {"$ref": "#/components/schemas/StartHookTestResult"}},
        "required": ["test"]
      },
      "UpsertWarmPoolConfigRequest": {
        "type": "object",
        "properties": {"enabled": {"type": "boolean", "description": "Whether the warm pool should be active"}},
        "required": ["enabled"]
      },
      "UpsertWarmPoolConfigResponse": {
        "type": "object",
        "properties": {"warm_pool": {"$ref": "#/components/schemas/WarmPoolConfigWithStats"}},
        "required": ["warm_pool"]
      },
      "RestoreWarmPoolSnapshotResponse": {
        "type": "object",
        "properties": {
          "warm_pool": {"$ref": "#/components/schemas/WarmPoolConfigWithStats"},
          "restored_generation": {"type": "integer", "description": "Generation of the snapshot that was restored and is now installed"}
        },
        "required": ["warm_pool", "restored_generation"]
      },
      "WarmPoolWorkspaceRecord": {
        "type": "object",
        "description": "A single pre-warmed workspace within a warm pool.",
        "properties": {
          "id": {"type": "string", "format": "uuid"},
          "organization_id": {"type": "string", "format": "uuid"},
          "warm_pool_config_id": {"type": "string", "format": "uuid"},
          "sandbox_id": {"type": "string", "description": "Underlying sandbox/VM identifier"},
          "status": {"type": "string", "enum": ["warming", "snapshotting", "ready", "assigned", "expired", "failed"]},
          "generation": {
            "type": "integer",
            "description": "Config generation this workspace was built for. Less than the parent config's `generation` means stale by derivation."
          },
          "error_message": {"type": ["string", "null"], "description": "Error message if `status` is `failed`"},
          "created_at": {"type": "string", "format": "date-time"}
        },
        "required": [
          "id",
          "organization_id",
          "warm_pool_config_id",
          "sandbox_id",
          "status",
          "generation",
          "error_message",
          "created_at"
        ]
      },
      "ListWarmPoolWorkspacesResponse": {
        "type": "object",
        "properties": {"workspaces": {"type": "array", "items": {"$ref": "#/components/schemas/WarmPoolWorkspaceRecord"}}},
        "required": ["workspaces"]
      },
      "SlackUserConnectionStatusResponse": {
        "type": "object",
        "properties": {
          "hasConnection": {"type": "boolean"},
          "displayName": {"type": "string"},
          "teamName": {"type": "string"},
          "lastConnectedAt": {"type": "string", "format": "date-time"}
        },
        "required": ["hasConnection"]
      },
      "SlackUserStartOAuthResponse": {
        "type": "object",
        "properties": {"authorizationUrl": {"type": "string", "format": "uri"}},
        "required": ["authorizationUrl"]
      },
      "SlackUserConnectionDeleteResponse": {"type": "object", "properties": {"success": {"type": "boolean"}}, "required": ["success"]},
      "LinearUserConnectionStatusResponse": {
        "type": "object",
        "properties": {
          "hasConnection": {"type": "boolean"},
          "displayName": {"type": "string"},
          "workspaceName": {"type": "string"},
          "lastConnectedAt": {"type": "string", "format": "date-time"}
        },
        "required": ["hasConnection"]
      },
      "LinearUserStartOAuthResponse": {
        "type": "object",
        "properties": {"authorizationUrl": {"type": "string", "format": "uri"}},
        "required": ["authorizationUrl"]
      },
      "LinearUserConnectionDeleteResponse": {"type": "object", "properties": {"success": {"type": "boolean"}}, "required": ["success"]},
      "SlackThreadAttachRequest": {
        "type": "object",
        "properties": {
          "channel_id": {"type": "string", "description": "Slack channel ID containing the thread."},
          "thread_ts": {"type": "string", "description": "Slack thread timestamp."},
          "workspace_id": {"type": "string", "format": "uuid", "description": "Target workspace ID. Required outside agent mode."}
        },
        "required": ["channel_id", "thread_ts"]
      },
      "SlackThreadAttachResponse": {
        "type": "object",
        "properties": {
          "thread": {"$ref": "#/components/schemas/SlackThreadRecord"},
          "workspace": {
            "type": "object",
            "properties": {"id": {"type": "string", "format": "uuid"}, "name": {"type": "string"}},
            "required": ["id", "name"]
          }
        },
        "required": ["thread", "workspace"]
      },
      "SlackThreadRecord": {
        "type": "object",
        "properties": {
          "id": {"type": "string", "format": "uuid"},
          "organization_id": {"type": "string", "format": "uuid"},
          "slack_team_id": {"type": "string"},
          "channel_id": {"type": "string"},
          "thread_ts": {"type": "string"},
          "workspace_id": {"type": ["string", "null"], "format": "uuid"},
          "status": {"type": "string"},
          "metadata": {"$ref": "#/components/schemas/SlackThreadMetadata"},
          "last_processed_message_ts": {"type": ["string", "null"]},
          "created_at": {"type": "string", "format": "date-time"},
          "updated_at": {"type": "string", "format": "date-time"}
        },
        "required": [
          "id",
          "organization_id",
          "slack_team_id",
          "channel_id",
          "thread_ts",
          "workspace_id",
          "status",
          "metadata",
          "last_processed_message_ts",
          "created_at",
          "updated_at"
        ]
      },
      "SlackThreadMetadata": {
        "type": "object",
        "properties": {
          "channel_id": {"type": "string"},
          "channel_name": {"type": "string"},
          "thread_ts": {"type": "string"},
          "message_ts": {"type": "string"},
          "routed_message_timestamps": {"type": "array", "items": {"type": "string"}},
          "original_message": {"type": "string"},
          "user_id": {"type": "string"},
          "user_name": {"type": "string"},
          "images": {"type": "array", "items": {"type": "object", "additionalProperties": true}},
          "workspace_target": {"type": "object", "properties": {"label": {"type": "string"}}, "required": ["label"]},
          "workspace": {
            "type": "object",
            "properties": {
              "id": {"type": "string", "format": "uuid"},
              "coding_agent": {"type": "string"},
              "task_description": {"type": "string"},
              "created_at": {"type": "string", "format": "date-time"}
            },
            "required": ["id", "task_description", "created_at"]
          }
        },
        "required": ["channel_id", "thread_ts", "original_message", "user_id"]
      },
      "GetDefaultAgentResponse": {
        "type": "object",
        "properties": {
          "default_agent": {"type": "string", "enum": ["claude", "codex", "cursor", "muse", "opencode", "pi"]},
          "default_model": {"type": ["string", "null"]}
        },
        "required": ["default_agent", "default_model"]
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {"type": "string", "description": "Error message"},
          "details": {"type": ["string", "null"], "description": "Additional error details"},
          "code": {"type": "string", "description": "Machine-readable error code when available"}
        },
        "required": ["error"]
      },
      "Media": {
        "type": "object",
        "properties": {
          "id": {"type": "string", "format": "uuid"},
          "workspace_id": {"type": "string", "format": "uuid"},
          "kind": {"$ref": "#/components/schemas/MediaKind"},
          "size": {"type": "integer", "description": "Size in bytes"},
          "display_name": {"type": ["string", "null"]},
          "created_at": {"type": "string", "format": "date-time"}
        },
        "required": ["id", "workspace_id", "kind", "size", "created_at"]
      },
      "ListMediaResponse": {
        "type": "object",
        "properties": {
          "media": {"type": "array", "items": {"$ref": "#/components/schemas/Media"}},
          "total": {"type": "integer"},
          "page": {"type": "integer"},
          "limit": {"type": "integer"},
          "total_pages": {"type": "integer"}
        },
        "required": ["media", "total", "page", "limit", "total_pages"]
      },
      "LearnedSkill": {
        "type": "object",
        "properties": {
          "id": {"type": "string", "format": "uuid"},
          "name": {"type": "string", "description": "Skill name from the SKILL.md frontmatter"},
          "title": {"type": "string"},
          "description": {"type": "string", "description": "When agents should use the skill"},
          "content": {"type": "string", "description": "Full SKILL.md"},
          "created_at": {"type": "string", "format": "date-time"},
          "updated_at": {"type": "string", "format": "date-time"}
        },
        "required": ["id", "name", "title", "description", "content", "created_at", "updated_at"]
      },
      "SaveLearnedSkillRequest": {
        "type": "object",
        "properties": {
          "content": {
            "type": "string",
            "description": "SKILL.md with `name` and `description` frontmatter. `description` should start with \"Use when\"."
          },
          "title": {"type": "string", "description": "Short title, like \"Always use Conventional Commits\""}
        },
        "required": ["title", "content"]
      },
      "ChatGoal": {
        "type": "object",
        "properties": {
          "objective": {"type": "string"},
          "status": {"type": "string", "enum": ["active", "paused", "blocked", "usageLimited", "budgetLimited", "complete"]},
          "token_budget": {"type": ["integer", "null"]},
          "tokens_used": {"type": "integer"},
          "time_used_seconds": {"type": "integer"}
        }
      },
      "ExecRequest": {
        "type": "object",
        "properties": {
          "command": {"type": "string", "description": "Shell command, run in the workspace root"},
          "timeout_seconds": {"type": "integer", "minimum": 1, "maximum": 50, "default": 30}
        },
        "required": ["command"]
      },
      "ExecResponse": {
        "type": "object",
        "properties": {
          "output": {"type": "string", "description": "Combined stdout and stderr, last 64 KB"},
          "exit_code": {"type": ["integer", "null"], "description": "`null` when the command timed out"},
          "timed_out": {"type": "boolean"},
          "truncated": {"type": "boolean"}
        },
        "required": ["output", "exit_code", "timed_out", "truncated"]
      },
      "Preview": {
        "type": "object",
        "properties": {
          "port": {"type": "integer"},
          "public_url": {"type": "string", "format": "uri"},
          "created_at": {"type": "string", "format": "date-time"},
          "system": {
            "type": "string",
            "enum": ["desktop"],
            "description": "Set on previews Replicas creates, like the live desktop stream on port 6080"
          }
        },
        "required": ["port", "public_url"]
      },
      "WorkspaceShare": {
        "type": "object",
        "properties": {
          "id": {"type": "string", "format": "uuid"},
          "workspace_id": {"type": "string", "format": "uuid"},
          "shared_with_user_id": {"type": "string", "format": "uuid"},
          "shared_by_user_id": {"type": ["string", "null"], "format": "uuid"},
          "created_at": {"type": "string", "format": "date-time"}
        }
      },
      "GitHubRepository": {
        "type": "object",
        "properties": {
          "id": {"type": "integer", "description": "Use as `github_repository_id`"},
          "installation_id": {"type": "integer", "description": "Use as `github_installation_id`"},
          "name": {"type": "string"},
          "full_name": {"type": "string"},
          "clone_url": {"type": "string", "format": "uri"},
          "default_branch": {"type": "string"},
          "owner_login": {"type": "string"}
        }
      },
      "AddRepositoryRequest": {
        "type": "object",
        "properties": {
          "name": {"type": "string", "description": "`owner/repo`"},
          "url": {"type": "string", "format": "uri"},
          "provider": {"type": "string", "enum": ["github", "gitlab"], "default": "github"},
          "default_branch": {"type": "string"},
          "github_installation_id": {"type": "integer"},
          "github_repository_id": {"type": "integer"},
          "gitlab_project_id": {"type": "integer"},
          "gitlab_path_with_namespace": {"type": "string"}
        },
        "required": ["name", "url"]
      },
      "Whoami": {
        "type": "object",
        "properties": {
          "organization": {"type": "object", "properties": {"id": {"type": "string", "format": "uuid"}, "name": {"type": "string"}}},
          "caller": {"type": "string", "enum": ["user", "organization_api_key", "personal_api_key", "workspace"]},
          "user": {
            "type": ["object", "null"],
            "properties": {
              "id": {"type": "string", "format": "uuid"},
              "email": {"type": ["string", "null"]},
              "display_name": {"type": "string"}
            }
          },
          "workspace_id": {"type": ["string", "null"], "format": "uuid"},
          "is_admin": {"type": "boolean"}
        },
        "required": ["organization", "caller", "user", "workspace_id", "is_admin"]
      },
      "OrganizationMember": {
        "type": "object",
        "properties": {
          "user_id": {"type": "string", "format": "uuid"},
          "email": {"type": "string"},
          "display_name": {"type": "string"},
          "role": {"type": "string", "enum": ["admin", "member"]},
          "created_at": {"type": ["string", "null"], "format": "date-time"}
        }
      },
      "CredentialStatus": {
        "type": "object",
        "description": "Secrets are masked for API keys.",
        "properties": {
          "has_credentials": {"type": "boolean"},
          "credential_id": {"type": "string"},
          "last_fetched_at": {"type": ["string", "null"], "format": "date-time"},
          "api_key": {"type": "string", "description": "Masked, e.g. `••••abcd`"},
          "base_url": {"type": "string"},
          "models": {"type": "array", "items": {"type": "string"}},
          "aws_region": {"type": "string"}
        },
        "required": ["has_credentials"]
      },
      "SubscriptionUsageAccount": {
        "type": "object",
        "properties": {
          "provider": {"type": "string", "enum": ["claude", "codex"]},
          "scope": {"type": "string", "enum": ["user", "org"]},
          "credential_id": {"type": "string", "format": "uuid"},
          "email": {"type": "string"},
          "plan_type": {"type": "string", "description": "Plan name as the provider reports it, e.g. `max` or `pro`"},
          "exhausted_until": {"type": ["string", "null"], "format": "date-time", "description": "Workspaces skip the account until then because it last hit a usage limit."},
          "windows": {
            "type": ["array", "null"],
            "description": "Null when the provider did not report usage. Empty when the plan has no limits.",
            "items": {
              "type": "object",
              "properties": {
                "kind": {"type": "string", "enum": ["session", "weekly"], "description": "`session` is the 5-hour limit."},
                "model": {"type": ["string", "null"], "description": "Set when the limit covers one model family, e.g. `Opus`."},
                "used_percent": {"type": "number"},
                "resets_at": {"type": ["string", "null"], "format": "date-time", "description": "Null until usage starts the window."}
              },
              "required": ["kind", "model", "used_percent", "resets_at"]
            }
          },
          "reconnect_required": {"type": "boolean", "description": "The provider rejected the saved login, so workspaces cannot use the account until it is reconnected."}
        },
        "required": ["provider", "scope", "credential_id", "exhausted_until", "windows", "reconnect_required"]
      },
      "SetCredentialRequest": {
        "type": "object",
        "description": "Most providers take `api_key`. `ollama`: `api_key`, `base_url`, `models`. `openai-compatible`: `base_url`, `api_key`, `models_url`, `authorization_header`. `bedrock`: `aws_access_key_id`, `aws_secret_access_key`, `aws_region`, `small_fast_model_region`. `claude-foundry`: `api_key`, `resource`, `sonnet_model`, `haiku_model`, `opus_model`. `codex-foundry`: `api_key`, `base_url`, `model`.",
        "properties": {
          "api_key": {"type": "string"},
          "base_url": {"type": "string"},
          "models_url": {"type": "string"},
          "authorization_header": {"type": "string"},
          "aws_access_key_id": {"type": "string"},
          "aws_secret_access_key": {"type": "string"},
          "aws_region": {"type": "string"},
          "small_fast_model_region": {"type": "string"},
          "resource": {"type": "string"},
          "sonnet_model": {"type": "string"},
          "haiku_model": {"type": "string"},
          "opus_model": {"type": "string"},
          "model": {"type": "string"},
          "models": {"type": "array", "items": {"type": "string"}}
        }
      }
    }
  }
}
