{
  "openapi": "3.1.0",
  "info": {
    "title": "OpenComputer Management API",
    "description": "HTTP API for running OpenComputer serverless agents from trusted server code: create sessions on deployed agents, send turns, read each session's durable event log, and manage projects, agents, deployments, webhooks, event subscriptions, Linear connections and document memory. Request and response bodies are JSON. Every request carries an organization API key in the `x-api-key` header; keep it on the server. Errors are `{ error: { code, message } }`, except a missing key or unknown route, which return `{ error: string }`. Full reference: https://docs.opencomputer.dev/agents/api",
    "version": "1.0.0",
    "contact": {
      "name": "OpenComputer",
      "url": "https://opencomputer.dev/contact"
    }
  },
  "externalDocs": {
    "description": "Management API reference",
    "url": "https://docs.opencomputer.dev/agents/api"
  },
  "servers": [
    {
      "url": "https://app.opencomputer.dev/api/managed-agents",
      "description": "Production"
    }
  ],
  "security": [
    {
      "apiKey": []
    }
  ],
  "tags": [
    {
      "name": "Sessions",
      "description": "Durable conversations with one deployed agent."
    },
    {
      "name": "Turns",
      "description": "Send user input to a session."
    },
    {
      "name": "Events",
      "description": "The durable per-session event log."
    },
    {
      "name": "Memory",
      "description": "Document memory per project and environment."
    },
    {
      "name": "Webhooks",
      "description": "Agent webhook configuration."
    },
    {
      "name": "Event subscriptions",
      "description": "Deliver turn outcomes to another session."
    },
    {
      "name": "Linear connections",
      "description": "Bind a Linear app to an agent."
    },
    {
      "name": "Projects",
      "description": "Projects."
    },
    {
      "name": "Agents",
      "description": "Agents."
    },
    {
      "name": "Deployments",
      "description": "Agent deployments."
    },
    {
      "name": "GitHub",
      "description": "GitHub App installation repositories."
    }
  ],
  "paths": {
    "/sessions": {
      "post": {
        "operationId": "createSession",
        "tags": [
          "Sessions"
        ],
        "summary": "Create a session",
        "description": "Creates a durable session on a deployed agent, addressed by `agentId` alias or a pinned `deploymentId`. The session starts without a turn; send one with the turns route. Error codes include `invalid_environment`, `invalid_memory_binding`, `invalid_labels`, `invalid_external_reference`, `deployment_not_found`, `deployment_not_promoted`, `idempotency_conflict`, `memory_admission_unconfirmed` and `session_publication_unconfirmed`.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "At most 256 characters. Identifies the session within your organization: the same key with the same request returns the existing session with `200`; anything else under the key is `409 idempotency_conflict`.",
            "schema": {
              "type": "string",
              "maxLength": 256
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateSessionRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The key had already created this session; returns it with the deployment it pinned.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateSessionResponse"
                }
              }
            }
          },
          "201": {
            "description": "Session created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateSessionResponse"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_environment`, `invalid_memory_binding`, `invalid_labels` or `invalid_external_reference`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`deployment_not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_conflict` (different request under the same key) or `deployment_not_promoted` (pinned deployment not active in the named environment).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "description": "`memory_admission_unconfirmed` or `session_publication_unconfirmed` (with `error.sessionId`); retry with the same key and body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "get": {
        "operationId": "listSessions",
        "tags": [
          "Sessions"
        ],
        "summary": "List sessions",
        "description": "Returns one page of session rows, newest first, filtered by exact-match query parameters combined with AND. Label filters are sent as `label.<key>=<value>` query parameters (at most three), which cannot be expressed as fixed parameters here. Unknown parameters, both spellings of one filter, or malformed values are `400 invalid_query`.",
        "parameters": [
          {
            "name": "project",
            "in": "query",
            "required": false,
            "description": "A project ID or slug. Do not combine with `projectId`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "projectId",
            "in": "query",
            "required": false,
            "description": "A project ID or slug; same filter as `project`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "environment",
            "in": "query",
            "required": false,
            "description": "`development` or `production`.",
            "schema": {
              "$ref": "#/components/schemas/EnvironmentName"
            }
          },
          {
            "name": "agent",
            "in": "query",
            "required": false,
            "description": "An agent ID. Do not combine with `agentId`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "agentId",
            "in": "query",
            "required": false,
            "description": "An agent ID; same filter as `agent`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "One session status.",
            "schema": {
              "$ref": "#/components/schemas/SessionStatus"
            }
          },
          {
            "name": "deploymentId",
            "in": "query",
            "required": false,
            "description": "A deployment ID.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "externalReference",
            "in": "query",
            "required": false,
            "description": "Sessions created with exactly this external reference.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 256
            }
          },
          {
            "name": "createdAfter",
            "in": "query",
            "required": false,
            "description": "RFC 3339 timestamp: sessions with `createdAt >= createdAfter`.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "createdBefore",
            "in": "query",
            "required": false,
            "description": "RFC 3339 timestamp: sessions with `createdAt < createdBefore`.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "updatedAfter",
            "in": "query",
            "required": false,
            "description": "RFC 3339 timestamp: sessions with `updatedAt >= updatedAfter`.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Rows per page, 1 to 100; default 50.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The `nextCursor` of the previous page; valid only with the same filters, else `400 invalid_cursor`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "One page of rows.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SessionPage"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_query` or `invalid_cursor`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "`project_scope_violation`: a filter names a project outside the key's scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "5XX": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/sessions/{sessionId}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/SessionId"
        }
      ],
      "get": {
        "operationId": "getSession",
        "tags": [
          "Sessions"
        ],
        "summary": "Get a session",
        "description": "Returns the session with its status, turns, labels, memory bindings, latest result and open question.",
        "responses": {
          "200": {
            "description": "The session.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Session"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "5XX": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/sessions/{sessionId}/labels": {
      "parameters": [
        {
          "$ref": "#/components/parameters/SessionId"
        }
      ],
      "patch": {
        "operationId": "updateSessionLabels",
        "tags": [
          "Sessions"
        ],
        "summary": "Change session labels",
        "description": "Removes the `unset` keys, then writes the `set` keys, and returns the session. Labels can be changed on an ended session; repeating a patch is safe.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateLabelsRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The session; the list reflects the change.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Session"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_labels`: the patch exceeds the bounds; nothing changed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "description": "`session_publication_unconfirmed` (with `error.sessionId`): labels recorded but the list row was not confirmed; retry the same patch.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/sessions/{sessionId}/end": {
      "parameters": [
        {
          "$ref": "#/components/parameters/SessionId"
        }
      ],
      "post": {
        "operationId": "endSession",
        "tags": [
          "Sessions"
        ],
        "summary": "End a session",
        "description": "Ends the session: queued and running turns are cancelled with reason `session_ended` and no further turns are accepted. A `200` confirms memory write access is revoked; repeating end confirms pending revocation.",
        "responses": {
          "200": {
            "description": "The ended session.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Session"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "description": "`session_end_unconfirmed`: the session ended but memory revocation was not acknowledged; retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/sessions/{sessionId}/interrupt": {
      "parameters": [
        {
          "$ref": "#/components/parameters/SessionId"
        }
      ],
      "post": {
        "operationId": "interruptSession",
        "tags": [
          "Sessions"
        ],
        "summary": "Interrupt the running turn",
        "description": "Requests that the running turn stop without spending a model turn; the response does not wait for completion. The turn then becomes `cancelled` with reason `interrupted` and queued turns remain; an idle session is returned unchanged.",
        "responses": {
          "200": {
            "description": "The session.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Session"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "5XX": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/sessions/{sessionId}/questions/{questionId}/dismiss": {
      "parameters": [
        {
          "$ref": "#/components/parameters/SessionId"
        },
        {
          "name": "questionId",
          "in": "path",
          "required": true,
          "description": "The open question's ID.",
          "schema": {
            "type": "string"
          }
        }
      ],
      "post": {
        "operationId": "dismissSessionQuestion",
        "tags": [
          "Sessions"
        ],
        "summary": "Dismiss the open question",
        "description": "Closes the session's open question with reason `dismissed`; inputs held behind it run as ordinary turns, in order.",
        "responses": {
          "200": {
            "description": "The question was dismissed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QuestionDismissResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "5XX": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/sessions/{sessionId}/turns": {
      "parameters": [
        {
          "$ref": "#/components/parameters/SessionId"
        }
      ],
      "post": {
        "operationId": "sendTurn",
        "tags": [
          "Turns"
        ],
        "summary": "Send a turn",
        "description": "Admits a turn with user text and an optional JSON payload; follow its progress in the event log. While a question is open, a turn without `answers` is held and delivered with the answer.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Identifies this request: a repeat with the same `input`, `payload` and `mode` returns the existing turn with `200`; the same key with anything else is `409 idempotency_conflict`. Without one every request starts a turn.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SendTurnRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Repeated idempotency key: the existing turn (or held input), with `duplicate: true`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SendTurnResponse"
                }
              }
            }
          },
          "202": {
            "description": "New turn admitted, or input held behind the open question.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SendTurnResponse"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_turn` or `invalid_payload` (payload over 32 KB).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "`idempotency_conflict`, `question_stale`, `memory_admission_pending` (retry the session creation with its key first) or `memory_admission_rejected` (the session is ended).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "5XX": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/sessions/{sessionId}/events": {
      "parameters": [
        {
          "$ref": "#/components/parameters/SessionId"
        }
      ],
      "get": {
        "operationId": "listSessionEvents",
        "tags": [
          "Events"
        ],
        "summary": "Read the session event log",
        "description": "Returns up to 500 events with `seq` greater than `after`, in ascending order. Start at `after=0` and repeat with the last `seq` received until a page is empty; keep polling to follow a live session.",
        "parameters": [
          {
            "name": "after",
            "in": "query",
            "required": false,
            "description": "Return events with `seq` greater than this; start at 0.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of events.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EventPage"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "5XX": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/projects/{projectId}/memory": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ProjectId"
        }
      ],
      "get": {
        "operationId": "listMemoryResources",
        "tags": [
          "Memory"
        ],
        "summary": "List memory resources",
        "description": "Returns the environment's document-memory resource inventory, including retired resources no active deployment declares.",
        "parameters": [
          {
            "$ref": "#/components/parameters/MemoryEnvironment"
          }
        ],
        "responses": {
          "200": {
            "description": "The resource inventory.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MemoryResourceInventory"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`: invalid input, environment or conditions.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`not_found` or `project_not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "5XX": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/projects/{projectId}/memory/{resourceId}/documents": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ProjectId"
        },
        {
          "$ref": "#/components/parameters/ResourceId"
        }
      ],
      "get": {
        "operationId": "listMemoryDocuments",
        "tags": [
          "Memory"
        ],
        "summary": "List memory documents",
        "description": "Returns one page of document metadata without `text`, by descending update time then ascending ID. Pagination is live; re-list for a complete inventory.",
        "parameters": [
          {
            "$ref": "#/components/parameters/MemoryEnvironment"
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The `nextCursor` of the previous page.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "One page of documents.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MemoryDocumentPage"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`: invalid input, environment or conditions.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`not_found` or `project_not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "5XX": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/projects/{projectId}/memory/{resourceId}/documents/{documentId}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ProjectId"
        },
        {
          "$ref": "#/components/parameters/ResourceId"
        },
        {
          "$ref": "#/components/parameters/DocumentId"
        }
      ],
      "get": {
        "operationId": "getMemoryDocument",
        "tags": [
          "Memory"
        ],
        "summary": "Read a memory document",
        "description": "Returns the document and its quoted `ETag`, which is the value to send in `If-Match`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/MemoryEnvironment"
          }
        ],
        "responses": {
          "200": {
            "description": "The document.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MemoryDocument"
                }
              }
            },
            "headers": {
              "ETag": {
                "description": "Quoted document revision.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`: invalid input, environment or conditions.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`not_found` or `project_not_found`: missing or deleted target.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "5XX": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "put": {
        "operationId": "putMemoryDocument",
        "tags": [
          "Memory"
        ],
        "summary": "Create or replace a memory document",
        "description": "With `If-None-Match: *`, creates a document under a never-used ID (body requires `title`) and returns `201`. With `If-Match`, replaces the text and optionally the summary (body requires `text`) and returns `200`; checks and writes happen together.",
        "parameters": [
          {
            "$ref": "#/components/parameters/MemoryEnvironment"
          },
          {
            "name": "If-None-Match",
            "in": "header",
            "required": false,
            "description": "Send `*` to create. Exactly one of `If-None-Match` or `If-Match` is required; missing both is `428 precondition_required`.",
            "schema": {
              "type": "string",
              "enum": [
                "*"
              ]
            }
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": false,
            "description": "Send the current quoted `ETag` to replace text or summary.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PutMemoryDocumentRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Text replaced.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MemoryDocument"
                }
              }
            },
            "headers": {
              "ETag": {
                "description": "Quoted new revision.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "201": {
            "description": "Document created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MemoryDocument"
                }
              }
            },
            "headers": {
              "ETag": {
                "description": "Quoted new revision.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`: invalid input, environment or conditions.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`not_found` or `project_not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "412": {
            "description": "`precondition_failed`: stale revision or an already-used create ID. Read the latest document and reconcile.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "`memory_limit_exceeded`: a field is above its size limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "428": {
            "description": "`precondition_required`: missing condition header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "5XX": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "patch": {
        "operationId": "updateMemoryDocument",
        "tags": [
          "Memory"
        ],
        "summary": "Change document title or policy",
        "description": "Changes the title, `agentWrites` policy, or both; omitted fields stay unchanged. Setting `agentWrites: \"disabled\"` freezes the document against agent saves.",
        "parameters": [
          {
            "$ref": "#/components/parameters/MemoryEnvironment"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PatchMemoryDocumentRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated document.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MemoryDocument"
                }
              }
            },
            "headers": {
              "ETag": {
                "description": "Quoted new revision.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`: invalid input, environment or conditions.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`not_found` or `project_not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "412": {
            "description": "`precondition_failed`: stale revision.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "`memory_limit_exceeded`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "428": {
            "description": "`precondition_required`: missing `If-Match`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "5XX": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "delete": {
        "operationId": "deleteMemoryDocument",
        "tags": [
          "Memory"
        ],
        "summary": "Delete a memory document",
        "description": "Removes the document's title, text and summary and reserves its ID against recreation. Existing document bindings fail their next recall.",
        "parameters": [
          {
            "$ref": "#/components/parameters/MemoryEnvironment"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted; empty body and no new ETag."
          },
          "400": {
            "description": "`invalid_request`: invalid input, environment or conditions.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`not_found` or `project_not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "412": {
            "description": "`precondition_failed`: stale revision.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "428": {
            "description": "`precondition_required`: missing `If-Match`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "5XX": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/projects/{projectId}/webhooks": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ProjectId"
        }
      ],
      "get": {
        "operationId": "listWebhooks",
        "tags": [
          "Webhooks"
        ],
        "summary": "List webhooks",
        "description": "Lists the project's agent webhooks, with invocation URLs without tokens.",
        "parameters": [
          {
            "name": "environment",
            "in": "query",
            "required": false,
            "description": "Only webhooks of this environment.",
            "schema": {
              "$ref": "#/components/schemas/Environment"
            }
          },
          {
            "name": "agentId",
            "in": "query",
            "required": false,
            "description": "Only webhooks targeting this agent.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The webhooks.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "5XX": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "post": {
        "operationId": "createWebhook",
        "tags": [
          "Webhooks"
        ],
        "summary": "Create a webhook",
        "description": "Creates an agent webhook for one agent and environment. The `token` and full `invocationUrl` appear only in this response; store them as a credential.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateWebhookRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Webhook created; carries `token` and the full `invocationUrl` once.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEnvelope"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "`webhook_target_unavailable`: the agent is not deployed in the environment.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "5XX": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/projects/{projectId}/webhooks/{webhookId}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ProjectId"
        },
        {
          "$ref": "#/components/parameters/WebhookId"
        }
      ],
      "patch": {
        "operationId": "updateWebhook",
        "tags": [
          "Webhooks"
        ],
        "summary": "Update a webhook",
        "description": "Changes any of `name`, `enabled` and `identity`; `identity: null` removes the identity source.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateWebhookRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated webhook.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEnvelope"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "5XX": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "delete": {
        "operationId": "deleteWebhook",
        "tags": [
          "Webhooks"
        ],
        "summary": "Delete a webhook",
        "description": "Removes the webhook so its caller can no longer start sessions.",
        "responses": {
          "204": {
            "description": "Deleted."
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "5XX": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/projects/{projectId}/webhooks/{webhookId}/rotate-token": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ProjectId"
        },
        {
          "$ref": "#/components/parameters/WebhookId"
        }
      ],
      "post": {
        "operationId": "rotateWebhookToken",
        "tags": [
          "Webhooks"
        ],
        "summary": "Rotate a webhook token",
        "description": "Issues a new token; the previous URL stops working immediately. The response carries the new token once.",
        "responses": {
          "200": {
            "description": "The webhook with its new token.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEnvelope"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "5XX": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/projects/{projectId}/webhooks/{webhookId}/requests": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ProjectId"
        },
        {
          "$ref": "#/components/parameters/WebhookId"
        }
      ],
      "get": {
        "operationId": "listWebhookRequests",
        "tags": [
          "Webhooks"
        ],
        "summary": "Read the webhook request ledger",
        "description": "Returns the webhook's recorded invocation requests and their outcomes. The session ID in the ledger is authoritative.",
        "responses": {
          "200": {
            "description": "The request ledger.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookRequestList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "5XX": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/projects/{projectId}/event-subscriptions": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ProjectId"
        }
      ],
      "post": {
        "operationId": "createEventSubscription",
        "tags": [
          "Event subscriptions"
        ],
        "summary": "Create an event subscription",
        "description": "Delivers recorded turn outcomes of agents in the project to a session in the same project, as new turns of that session. Subscriptions are immutable.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateEventSubscriptionRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Subscription created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EventSubscriptionEnvelope"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_event_subscription`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "`project_scope_violation`: the agent is outside the project.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`destination_session_not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "`destination_session_ended`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "5XX": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "get": {
        "operationId": "listEventSubscriptions",
        "tags": [
          "Event subscriptions"
        ],
        "summary": "List event subscriptions",
        "description": "Lists the project's event subscriptions.",
        "responses": {
          "200": {
            "description": "The subscriptions.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EventSubscriptionList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "5XX": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/projects/{projectId}/event-subscriptions/{subscriptionId}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ProjectId"
        },
        {
          "$ref": "#/components/parameters/SubscriptionId"
        }
      ],
      "get": {
        "operationId": "getEventSubscription",
        "tags": [
          "Event subscriptions"
        ],
        "summary": "Get an event subscription",
        "description": "Returns one event subscription.",
        "responses": {
          "200": {
            "description": "The subscription.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EventSubscriptionEnvelope"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`event_subscription_not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "5XX": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "delete": {
        "operationId": "deleteEventSubscription",
        "tags": [
          "Event subscriptions"
        ],
        "summary": "Delete an event subscription",
        "description": "Deletes the subscription; its pending deliveries stop.",
        "responses": {
          "204": {
            "description": "Deleted; pending deliveries stop."
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`event_subscription_not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "5XX": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/projects/{projectId}/linear/connections": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ProjectId"
        }
      ],
      "post": {
        "operationId": "createLinearConnection",
        "tags": [
          "Linear connections"
        ],
        "summary": "Create a Linear connection",
        "description": "Creates a pending connection binding a Linear app to one agent in one environment, returning `webhookUrl` and a prefilled `createAppUrl`. Creating again for a pending binding resets it with the new name and a new `webhookUrl`. Requires an organization API key.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateLinearConnectionRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "A pending connection for that binding already existed and was reset.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateLinearConnectionResponse"
                }
              }
            }
          },
          "201": {
            "description": "Connection created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateLinearConnectionResponse"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_environment`, `invalid_agent`, `invalid_linear_app_name` or `linear_app_name_reserved`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "`forbidden`: a project-scoped key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`project_not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "`project_archived`, `linear_already_connected` (with `error.connectionId`) or `linear_connection_changed` (with `error.connectionId`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "description": "`linear_connector_unavailable`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "get": {
        "operationId": "listLinearConnections",
        "tags": [
          "Linear connections"
        ],
        "summary": "List Linear connections",
        "description": "Lists the project's Linear connections. A project-scoped key may list its own project's connections.",
        "parameters": [
          {
            "name": "environment",
            "in": "query",
            "required": false,
            "description": "Only connections of this environment.",
            "schema": {
              "$ref": "#/components/schemas/EnvironmentName"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The connections.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LinearConnectionList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`project_not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "description": "`linear_connector_unavailable`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/linear/connections/{connectionId}/credentials": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ConnectionId"
        }
      ],
      "put": {
        "operationId": "setLinearConnectionCredentials",
        "tags": [
          "Linear connections"
        ],
        "summary": "Set Linear app credentials",
        "description": "Stores the client ID, client secret and webhook signing secret copied from the Linear app. Requires an organization API key.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LinearCredentialsRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The connection.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LinearConnectionEnvelope"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_linear_credentials`: all three fields are required.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "`forbidden`: a project-scoped key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`linear_connection_not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "`linear_app_already_connected`, `linear_connection_connected` or `linear_connection_changed`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "description": "`linear_connector_unavailable`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/linear/connections/{connectionId}/authorize": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ConnectionId"
        }
      ],
      "post": {
        "operationId": "authorizeLinearConnection",
        "tags": [
          "Linear connections"
        ],
        "summary": "Start Linear authorization",
        "description": "Returns Linear's consent page for the app; a workspace admin completes it and Linear returns to OpenComputer's callback. Requires an organization API key.",
        "responses": {
          "200": {
            "description": "The authorize URL.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LinearAuthorizeResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "`forbidden`: a project-scoped key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`linear_connection_not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "`linear_credentials_required`: set the credentials first.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "description": "`linear_connector_unavailable`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/linear/connections/{connectionId}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ConnectionId"
        }
      ],
      "delete": {
        "operationId": "deleteLinearConnection",
        "tags": [
          "Linear connections"
        ],
        "summary": "Disconnect a Linear connection",
        "description": "Disconnects the connection; `revoked` says whether Linear confirmed the token revocation. Requires an organization API key.",
        "responses": {
          "200": {
            "description": "Disconnected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LinearDisconnectResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "`forbidden`: a project-scoped key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`linear_connection_not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "description": "`linear_connector_unavailable`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/projects": {
      "get": {
        "operationId": "listProjects",
        "tags": [
          "Projects"
        ],
        "summary": "List projects",
        "description": "Lists the projects the API key can see.",
        "responses": {
          "200": {
            "description": "The projects.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "5XX": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "post": {
        "operationId": "createProject",
        "tags": [
          "Projects"
        ],
        "summary": "Create a project",
        "description": "Creates a project. `environmentMode` is `single` (one `default` environment) or `legacy` (Development and Production).",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateProjectRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The project.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Project"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "5XX": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/projects/{projectId}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ProjectId"
        }
      ],
      "get": {
        "operationId": "getProject",
        "tags": [
          "Projects"
        ],
        "summary": "Get a project",
        "description": "Returns the project with its deployments, sessions, connections and schedules.",
        "responses": {
          "200": {
            "description": "The project and related records.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectDetail"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "5XX": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/agents": {
      "get": {
        "operationId": "listAgents",
        "tags": [
          "Agents"
        ],
        "summary": "List agents",
        "description": "Lists agents with their active alias, active deployment and deployment count.",
        "responses": {
          "200": {
            "description": "The agents.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AgentList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "5XX": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/deployments": {
      "get": {
        "operationId": "listDeployments",
        "tags": [
          "Deployments"
        ],
        "summary": "List deployments of an agent",
        "description": "Lists the deployments of one agent.",
        "parameters": [
          {
            "name": "agentId",
            "in": "query",
            "required": true,
            "description": "The agent whose deployments to list.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The deployments.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeploymentList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "5XX": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/deployments/{deploymentId}": {
      "parameters": [
        {
          "name": "deploymentId",
          "in": "path",
          "required": true,
          "description": "Deployment ID.",
          "schema": {
            "type": "string"
          }
        }
      ],
      "get": {
        "operationId": "getDeployment",
        "tags": [
          "Deployments"
        ],
        "summary": "Get a deployment",
        "description": "Returns one deployment with its alias and memory declarations.",
        "responses": {
          "200": {
            "description": "The deployment.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deployment"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "5XX": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/projects/{projectId}/github/repositories": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ProjectId"
        }
      ],
      "get": {
        "operationId": "listGithubRepositories",
        "tags": [
          "GitHub"
        ],
        "summary": "List reachable GitHub repositories",
        "description": "Lists the repositories the environment's GitHub App installation covers, read live from GitHub each time. Call it from your server with an organization API key.",
        "parameters": [
          {
            "name": "environment",
            "in": "query",
            "required": true,
            "description": "`development` or `production`. Required.",
            "schema": {
              "$ref": "#/components/schemas/EnvironmentName"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size, at most 100 (the default).",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The `nextCursor` of the previous page.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "One page of repositories.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GithubRepositoryPage"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_environment`, `invalid_limit` or `invalid_cursor`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`github_connection_not_found`: the environment has no GitHub installation attached.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "`installation_suspended`: GitHub reports the installation suspended.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "502": {
            "description": "`github_unavailable`: GitHub could not be read; retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key",
        "description": "Organization (or project-scoped) API key."
      }
    },
    "parameters": {
      "SessionId": {
        "name": "sessionId",
        "in": "path",
        "required": true,
        "description": "Session ID.",
        "schema": {
          "type": "string"
        }
      },
      "ProjectId": {
        "name": "projectId",
        "in": "path",
        "required": true,
        "description": "Project ID.",
        "schema": {
          "type": "string"
        }
      },
      "ResourceId": {
        "name": "resourceId",
        "in": "path",
        "required": true,
        "description": "Memory resource ID: 1-128 lowercase letters or digits with single hyphen separators.",
        "schema": {
          "type": "string"
        }
      },
      "DocumentId": {
        "name": "documentId",
        "in": "path",
        "required": true,
        "description": "Document ID: 1-128 ASCII letters, digits, `-`, `_`.",
        "schema": {
          "type": "string"
        }
      },
      "WebhookId": {
        "name": "webhookId",
        "in": "path",
        "required": true,
        "description": "Webhook ID.",
        "schema": {
          "type": "string"
        }
      },
      "SubscriptionId": {
        "name": "subscriptionId",
        "in": "path",
        "required": true,
        "description": "Event subscription ID.",
        "schema": {
          "type": "string"
        }
      },
      "ConnectionId": {
        "name": "connectionId",
        "in": "path",
        "required": true,
        "description": "Linear connection ID.",
        "schema": {
          "type": "string"
        }
      },
      "MemoryEnvironment": {
        "name": "environment",
        "in": "query",
        "required": true,
        "description": "Required on every memory route: `development` or `production`.",
        "schema": {
          "$ref": "#/components/schemas/EnvironmentName"
        }
      },
      "IfMatch": {
        "name": "If-Match",
        "in": "header",
        "required": true,
        "description": "The document's current `ETag` (quoted revision), retained verbatim from a read or write. A stale value is `412 precondition_failed`.",
        "schema": {
          "type": "string"
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Invalid body, query or header.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Missing or invalid API key. A missing key returns `{ error: string }` without a code.",
        "content": {
          "application/json": {
            "schema": {
              "oneOf": [
                {
                  "$ref": "#/components/schemas/Error"
                },
                {
                  "$ref": "#/components/schemas/PlainError"
                }
              ],
              "description": "Coded error, or plain error for a missing key."
            }
          }
        }
      },
      "PaymentRequired": {
        "description": "`insufficient_credits`: prepaid credits are exhausted.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Forbidden": {
        "description": "The key may not perform this operation.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "NotFound": {
        "description": "The route or the target does not exist. An unknown route returns `{ error: string }` without a code.",
        "content": {
          "application/json": {
            "schema": {
              "oneOf": [
                {
                  "$ref": "#/components/schemas/Error"
                },
                {
                  "$ref": "#/components/schemas/PlainError"
                }
              ],
              "description": "Coded error, or plain error for an unknown route."
            }
          }
        }
      },
      "TooManyRequests": {
        "description": "Too many requests; retry after `Retry-After`.",
        "headers": {
          "Retry-After": {
            "description": "Seconds to wait before retrying.",
            "schema": {
              "type": "integer"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "ServerError": {
        "description": "Temporary failure; retry with the same idempotency key.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "description": "Standard error body. Branch on `error.code`; `error.message` is short and safe to show.",
        "properties": {
          "error": {
            "type": "object",
            "description": "The error.",
            "properties": {
              "code": {
                "type": "string",
                "description": "Stable machine-readable error code, for example `invalid_turn`, `idempotency_conflict` or `insufficient_credits`."
              },
              "message": {
                "type": "string",
                "description": "Short human-readable message that is safe to show."
              },
              "sessionId": {
                "type": "string",
                "description": "Present on `503 session_publication_unconfirmed`: the session that exists but whose list row was not confirmed in time."
              },
              "connectionId": {
                "type": "string",
                "description": "Present on `409 linear_already_connected` and `409 linear_connection_changed`: the Linear connection concerned."
              }
            },
            "required": [
              "code",
              "message"
            ]
          }
        },
        "required": [
          "error"
        ]
      },
      "PlainError": {
        "type": "object",
        "description": "Error body without a code, returned for a missing API key and for an unknown route.",
        "properties": {
          "error": {
            "type": "string",
            "description": "Human-readable error text."
          }
        },
        "required": [
          "error"
        ]
      },
      "Environment": {
        "type": "string",
        "description": "Environment scope. `development` or `production` for legacy (two-environment) projects; `default` for single-environment projects, where requests naming `development` resolve to `default` and requests naming `production` fail with `409 single_environment_project`.",
        "enum": [
          "development",
          "production",
          "default"
        ]
      },
      "EnvironmentName": {
        "type": "string",
        "description": "`development` or `production`. On a single-environment project, `development` resolves to its `default` environment.",
        "enum": [
          "development",
          "production"
        ]
      },
      "SessionStatus": {
        "type": "string",
        "description": "Session status.",
        "enum": [
          "new",
          "connecting",
          "idle",
          "running",
          "stopping",
          "waiting_runtime",
          "suspending",
          "suspended",
          "resuming",
          "failed",
          "ended"
        ]
      },
      "TurnMode": {
        "type": "string",
        "description": "How a turn is admitted. `queue` (default): run after earlier turns. `steer`: deliver into the running turn when the runtime supports it, otherwise queue. `interrupt`: interrupt running turns and run next.",
        "enum": [
          "queue",
          "steer",
          "interrupt"
        ]
      },
      "TurnStatus": {
        "type": "string",
        "description": "Turn status.",
        "enum": [
          "queued",
          "running",
          "completed",
          "failed",
          "cancelled"
        ]
      },
      "Labels": {
        "type": "object",
        "description": "Your own metadata on a session: at most 16 keys, each matching `^[a-z][a-z0-9_.-]{0,63}$`, each value at most 256 characters, 4 KB in all. Not permissions and never shown to the agent.",
        "maxProperties": 16,
        "propertyNames": {
          "type": "string",
          "pattern": "^[a-z][a-z0-9_.-]{0,63}$",
          "description": "Label key."
        },
        "additionalProperties": {
          "type": "string",
          "maxLength": 256,
          "description": "Label value."
        }
      },
      "ExternalReference": {
        "type": "string",
        "description": "Your own opaque reference for the session (for example the id of the record it works for): 1 to 256 bytes of UTF-8 without control characters. Stored as given, never shown to the agent, grants nothing, and cannot be changed after creation.",
        "minLength": 1,
        "maxLength": 256
      },
      "MemoryBinding": {
        "type": "object",
        "description": "A session's binding to a document-memory resource. Use `scope: \"document\"` with `id` to bind one document, or `scope: \"collection\"` without `id` to read the resource's documents (collections are read-only).",
        "properties": {
          "scope": {
            "type": "string",
            "description": "`document` binds one document; `collection` gives read access to the resource's documents.",
            "enum": [
              "document",
              "collection"
            ]
          },
          "id": {
            "type": "string",
            "description": "Document ID; required for `document` scope and omitted for `collection` scope. 1-128 ASCII letters, digits, `-`, `_`.",
            "minLength": 1,
            "maxLength": 128,
            "pattern": "^[A-Za-z0-9_-]{1,128}$"
          },
          "access": {
            "type": "string",
            "description": "`read` (default) or `read-write`. Collection writes are unsupported.",
            "enum": [
              "read",
              "read-write"
            ]
          }
        },
        "required": [
          "scope"
        ]
      },
      "MemoryBindings": {
        "type": "object",
        "description": "Memory bindings keyed by resource ID, at most eight. Needs a deployed agent that declares the resources and an environment; bound documents must exist.",
        "maxProperties": 8,
        "additionalProperties": {
          "$ref": "#/components/schemas/MemoryBinding"
        }
      },
      "SessionMemoryBinding": {
        "type": "object",
        "description": "A memory binding as returned on a session.",
        "properties": {
          "resource": {
            "type": "string",
            "description": "Memory resource ID."
          },
          "scope": {
            "type": "string",
            "description": "Binding scope.",
            "enum": [
              "document",
              "collection"
            ]
          },
          "id": {
            "type": "string",
            "description": "Document ID; present for document bindings."
          },
          "access": {
            "type": "string",
            "description": "Access granted by the binding.",
            "enum": [
              "read",
              "read-write"
            ]
          },
          "writable": {
            "type": "boolean",
            "description": "Whether the agent can currently save. False for read-only bindings, frozen or deleted documents and ended sessions."
          }
        }
      },
      "QuestionOption": {
        "type": "object",
        "description": "One choice of a question.",
        "properties": {
          "label": {
            "type": "string",
            "description": "Text shown for the choice."
          },
          "value": {
            "type": "string",
            "description": "Value sent back when the choice is selected."
          }
        }
      },
      "SessionQuestion": {
        "type": "object",
        "description": "The open question the agent asked with `ask`.",
        "properties": {
          "id": {
            "type": "string",
            "description": "Question ID; pass it as `answers` on a turn to answer it."
          },
          "text": {
            "type": "string",
            "description": "The question text."
          },
          "options": {
            "type": "array",
            "description": "Choices; empty for a free-text question.",
            "items": {
              "$ref": "#/components/schemas/QuestionOption"
            }
          },
          "askedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the question was asked."
          }
        }
      },
      "SessionResult": {
        "type": "object",
        "description": "The latest committed output of the agent's result tool.",
        "properties": {
          "turnId": {
            "type": "string",
            "description": "The turn whose tool call reported the data."
          },
          "callId": {
            "type": "string",
            "description": "The tool call that reported the data."
          },
          "reportedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the result was reported."
          },
          "data": {
            "description": "The result tool's committed output, any JSON value."
          }
        }
      },
      "SessionDestination": {
        "type": "object",
        "description": "An event subscription destination: a session of an agent in the same project that can still take turns.",
        "properties": {
          "type": {
            "type": "string",
            "description": "Destination type; sessions are the only destination.",
            "enum": [
              "session"
            ]
          },
          "sessionId": {
            "type": "string",
            "description": "The destination session ID."
          }
        },
        "required": [
          "type",
          "sessionId"
        ]
      },
      "OutcomeEventType": {
        "type": "string",
        "description": "A turn outcome an event subscription can select.",
        "enum": [
          "turn.completed",
          "turn.failed",
          "turn.cancelled"
        ]
      },
      "TurnDelivery": {
        "type": "object",
        "description": "One delivery of a turn's outcome to an event subscription.",
        "properties": {
          "id": {
            "type": "string",
            "description": "`<subscription-id>:<event-id>`; also the idempotency key of the destination turn."
          },
          "subscriptionId": {
            "type": "string",
            "description": "The subscription the outcome was delivered to."
          },
          "eventId": {
            "type": "string",
            "description": "The delivered event's ID."
          },
          "eventType": {
            "$ref": "#/components/schemas/OutcomeEventType",
            "description": "A turn outcome an event subscription can select."
          },
          "destination": {
            "$ref": "#/components/schemas/SessionDestination",
            "description": "An event subscription destination: a session of an agent in the same project that can still take turns."
          },
          "status": {
            "type": "string",
            "description": "Delivery status.",
            "enum": [
              "pending",
              "delivered",
              "failed"
            ]
          },
          "attempt": {
            "type": "integer",
            "description": "Delivery attempts so far."
          },
          "receipt": {
            "type": "object",
            "description": "The turn the destination admitted, once delivered.",
            "properties": {
              "sessionId": {
                "type": "string",
                "description": "Destination session ID."
              },
              "turnId": {
                "type": "string",
                "description": "Turn admitted on the destination session."
              }
            }
          },
          "nextAttemptAt": {
            "type": "string",
            "format": "date-time",
            "description": "When a pending delivery is retried."
          },
          "error": {
            "type": "string",
            "description": "Why delivery failed.",
            "enum": [
              "subscription_unavailable",
              "target_missing",
              "target_ended",
              "delivery_failed"
            ]
          }
        }
      },
      "Turn": {
        "type": "object",
        "description": "One turn of a session.",
        "properties": {
          "id": {
            "type": "string",
            "description": "Turn ID."
          },
          "input": {
            "type": "string",
            "description": "The user text of the turn."
          },
          "mode": {
            "$ref": "#/components/schemas/TurnMode",
            "description": "How a turn is admitted. `queue` (default): run after earlier turns. `steer`: deliver into the running turn when the runtime supports it, otherwise queue. `interrupt`: interrupt running turns and run next."
          },
          "status": {
            "$ref": "#/components/schemas/TurnStatus",
            "description": "Turn status."
          },
          "outcome": {
            "type": "string",
            "description": "`question` on a completed turn that ended by asking a question.",
            "enum": [
              "question"
            ]
          },
          "deliveries": {
            "type": "array",
            "description": "Present when an event subscription selected the turn's outcome.",
            "items": {
              "$ref": "#/components/schemas/TurnDelivery"
            }
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the turn was created."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the turn last changed."
          }
        }
      },
      "Session": {
        "type": "object",
        "description": "A session as returned by `GET /sessions/{sessionId}` and the routes that return the session.",
        "properties": {
          "id": {
            "type": "string",
            "description": "Session ID."
          },
          "agentId": {
            "type": "string",
            "description": "The agent the session runs."
          },
          "deploymentId": {
            "type": "string",
            "description": "The deployment the session runs on, chosen when it was created."
          },
          "projectId": {
            "type": "string",
            "description": "The project the agent belongs to."
          },
          "environment": {
            "$ref": "#/components/schemas/Environment",
            "description": "The session's environment, when the create request named one."
          },
          "status": {
            "$ref": "#/components/schemas/SessionStatus",
            "description": "Session status."
          },
          "source": {
            "type": "string",
            "description": "The `source` given at creation, for example `api`, `playground` or `webhook`."
          },
          "executionMode": {
            "type": "string",
            "description": "How the session is hosted. Sessions with `microvm` cancel immediately on interrupt without waiting for commands to stop."
          },
          "labels": {
            "$ref": "#/components/schemas/Labels",
            "description": "Your own metadata on a session: at most 16 keys, each matching `^[a-z][a-z0-9_.-]{0,63}$`, each value at most 256 characters, 4 KB in all. Not permissions and never shown to the agent."
          },
          "labelsUpdatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the labels last changed."
          },
          "externalReference": {
            "type": "string",
            "description": "The reference given at creation; absent when none was given."
          },
          "memory": {
            "type": "array",
            "description": "Memory bindings; present when the session was created with bindings.",
            "items": {
              "$ref": "#/components/schemas/SessionMemoryBinding"
            }
          },
          "turns": {
            "type": "array",
            "description": "Every turn of the session.",
            "items": {
              "$ref": "#/components/schemas/Turn"
            }
          },
          "result": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/SessionResult"
              },
              {
                "type": "null",
                "description": "No result has been committed."
              }
            ],
            "description": "The latest committed output of the agent's result tool, or null. A failed or cancelled turn never clears it."
          },
          "question": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/SessionQuestion"
              },
              {
                "type": "null",
                "description": "No open question."
              }
            ],
            "description": "The open question the agent asked with `ask`, or null. Independent of `result`."
          },
          "revision": {
            "type": "integer",
            "description": "Counter that increases with every change to the session's status, turns, labels or result."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the session was created."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the session last changed."
          }
        }
      },
      "SessionActivity": {
        "type": "object",
        "description": "Activity summary on a session list row.",
        "properties": {
          "activeTurnId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The running turn's ID, or null."
          },
          "queued": {
            "type": "integer",
            "description": "How many turns wait behind the running one."
          },
          "lastSettledTurn": {
            "oneOf": [
              {
                "type": "object",
                "description": "The most recently finished turn.",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "Turn ID."
                  },
                  "status": {
                    "$ref": "#/components/schemas/TurnStatus",
                    "description": "Turn status."
                  },
                  "at": {
                    "type": "string",
                    "format": "date-time",
                    "description": "When the turn settled."
                  }
                }
              },
              {
                "type": "null",
                "description": "No turn has settled."
              }
            ],
            "description": "The most recently finished turn, or null."
          }
        }
      },
      "SessionRow": {
        "type": "object",
        "description": "A row of `GET /sessions`. Rows carry no `turns`, no `memory` and no prompt or message text.",
        "properties": {
          "id": {
            "type": "string",
            "description": "Session ID."
          },
          "projectId": {
            "type": "string",
            "description": "The project the agent belongs to."
          },
          "agentId": {
            "type": "string",
            "description": "The agent the session runs."
          },
          "deploymentId": {
            "type": "string",
            "description": "The deployment the session runs on."
          },
          "environment": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Environment"
              },
              {
                "type": "null",
                "description": "The session has no environment."
              }
            ],
            "description": "The session's environment, or null when it has none."
          },
          "source": {
            "type": "string",
            "description": "The `source` given at creation."
          },
          "status": {
            "$ref": "#/components/schemas/SessionStatus",
            "description": "Session status."
          },
          "labels": {
            "$ref": "#/components/schemas/Labels",
            "description": "Your own metadata on a session: at most 16 keys, each matching `^[a-z][a-z0-9_.-]{0,63}$`, each value at most 256 characters, 4 KB in all. Not permissions and never shown to the agent."
          },
          "externalReference": {
            "type": "string",
            "description": "The reference given at creation; present when one was given."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the session was created."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the session last changed."
          },
          "revision": {
            "type": "integer",
            "description": "Counter that increases with every change to the session."
          },
          "activity": {
            "$ref": "#/components/schemas/SessionActivity",
            "description": "Activity summary on a session list row."
          },
          "result": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/SessionResult"
              },
              {
                "type": "null",
                "description": "No result has been committed."
              }
            ],
            "description": "The latest committed result, or null."
          }
        }
      },
      "SessionPage": {
        "type": "object",
        "description": "One page of session rows.",
        "properties": {
          "sessions": {
            "type": "array",
            "description": "Session rows, newest `createdAt` first, then by `id`.",
            "items": {
              "$ref": "#/components/schemas/SessionRow"
            }
          },
          "nextCursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Opaque cursor for the next page, valid only with the same filters; null when there are no more matches."
          }
        },
        "required": [
          "sessions",
          "nextCursor"
        ]
      },
      "CreateSessionRequest": {
        "type": "object",
        "description": "Body of `POST /sessions`. Address the agent with `agentId` (an alias), or pin a deployment with `deploymentId` plus `environment`.",
        "properties": {
          "agentId": {
            "type": "string",
            "description": "`<agent-id>@development` or `<agent-id>@production`. The alias selects the environment and the deployment active in it; a bare agent ID means `production`."
          },
          "deploymentId": {
            "type": "string",
            "description": "Advanced: pin one deployment instead of resolving an alias. Send `environment` with it; it may be omitted only when the deployment is promoted to exactly one environment."
          },
          "environment": {
            "$ref": "#/components/schemas/Environment",
            "description": "`development` or `production` for legacy projects; `default` for single-environment projects. Optional with `agentId`; it must agree with the alias."
          },
          "memory": {
            "$ref": "#/components/schemas/MemoryBindings",
            "description": "Memory bindings keyed by resource ID, at most eight. Needs a deployed agent that declares the resources and an environment; bound documents must exist."
          },
          "source": {
            "type": "string",
            "description": "Session source; the dashboard groups sessions by it. Defaults to `api`.",
            "enum": [
              "api",
              "playground",
              "webhook"
            ],
            "default": "api"
          },
          "labels": {
            "$ref": "#/components/schemas/Labels",
            "description": "Your own metadata on a session: at most 16 keys, each matching `^[a-z][a-z0-9_.-]{0,63}$`, each value at most 256 characters, 4 KB in all. Not permissions and never shown to the agent."
          },
          "externalReference": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/ExternalReference"
              },
              {
                "type": "null",
                "description": "No reference."
              }
            ],
            "description": "Your own reference for the session; omitted or null creates a session without one."
          }
        }
      },
      "CreatedSession": {
        "type": "object",
        "description": "The session returned by `POST /sessions`.",
        "properties": {
          "id": {
            "type": "string",
            "description": "Session ID."
          },
          "executionMode": {
            "type": "string",
            "description": "How the session is hosted, for example `microvm`. Check it when interrupt settlement guarantees matter."
          },
          "status": {
            "$ref": "#/components/schemas/SessionStatus",
            "description": "Session status."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the session was created."
          },
          "externalReference": {
            "type": "string",
            "description": "The reference given at creation, when one was given."
          }
        }
      },
      "CreateSessionResponse": {
        "type": "object",
        "description": "Response of `POST /sessions`.",
        "properties": {
          "session": {
            "$ref": "#/components/schemas/CreatedSession",
            "description": "The session returned by `POST /sessions`."
          },
          "deployment": {
            "$ref": "#/components/schemas/Deployment",
            "description": "A deployment of an agent."
          }
        }
      },
      "UpdateLabelsRequest": {
        "type": "object",
        "description": "Body of `PATCH /sessions/{sessionId}/labels`. `unset` removes keys, then `set` writes keys.",
        "properties": {
          "set": {
            "$ref": "#/components/schemas/Labels",
            "description": "Your own metadata on a session: at most 16 keys, each matching `^[a-z][a-z0-9_.-]{0,63}$`, each value at most 256 characters, 4 KB in all. Not permissions and never shown to the agent."
          },
          "unset": {
            "type": "array",
            "description": "Label keys to remove.",
            "items": {
              "type": "string",
              "description": "A label key."
            }
          }
        }
      },
      "SendTurnRequest": {
        "type": "object",
        "description": "Body of `POST /sessions/{sessionId}/turns`.",
        "properties": {
          "input": {
            "type": "string",
            "description": "The user text for this turn. Required, not empty.",
            "minLength": 1
          },
          "idempotencyKey": {
            "type": "string",
            "description": "The idempotency key in body form, for a browser send proxied through your server. Must equal the `Idempotency-Key` header when both are present, else `400 invalid_turn`."
          },
          "mode": {
            "$ref": "#/components/schemas/TurnMode",
            "description": "How a turn is admitted. `queue` (default): run after earlier turns. `steer`: deliver into the running turn when the runtime supports it, otherwise queue. `interrupt`: interrupt running turns and run next."
          },
          "payload": {
            "description": "Optional JSON value for the agent, at most 32 KB encoded. The agent reads it as `useInput().payload`; it is recorded on the turn's `message.received` event."
          },
          "answers": {
            "type": "string",
            "description": "The ID of the session's open question; the input answers it and the agent reads it as `useInput().answer`. Naming a question that is not open is `409 question_stale`."
          }
        },
        "required": [
          "input"
        ]
      },
      "TurnReceipt": {
        "type": "object",
        "description": "Receipt for an admitted turn.",
        "properties": {
          "turnId": {
            "type": "string",
            "description": "The turn ID."
          },
          "status": {
            "$ref": "#/components/schemas/TurnStatus",
            "description": "`queued` or `running` for a new turn; for a repeated key, whatever the existing turn has reached."
          },
          "duplicate": {
            "type": "boolean",
            "description": "True when the idempotency key had already created the turn."
          }
        },
        "required": [
          "turnId",
          "status",
          "duplicate"
        ]
      },
      "HeldTurnReceipt": {
        "type": "object",
        "description": "Receipt for an input held behind the session's open question; it carries no `turnId`.",
        "properties": {
          "status": {
            "type": "string",
            "description": "`held` while waiting on the question; `discarded` on a repeated key after a Linear stop discarded the input.",
            "enum": [
              "held",
              "discarded"
            ]
          },
          "questionId": {
            "type": "string",
            "description": "The open question the input waits on."
          },
          "duplicate": {
            "type": "boolean",
            "description": "True when the idempotency key had already been received."
          }
        },
        "required": [
          "status",
          "duplicate"
        ]
      },
      "SendTurnResponse": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/TurnReceipt"
          },
          {
            "$ref": "#/components/schemas/HeldTurnReceipt"
          }
        ],
        "description": "An admitted-turn receipt, or a held-input receipt when the session has an open question and the turn was sent without `answers`."
      },
      "Event": {
        "type": "object",
        "description": "One entry of the session's durable event log.",
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique event ID."
          },
          "seq": {
            "type": "integer",
            "minimum": 1,
            "description": "Position in the log, starting at 1 and increasing with every event. Use it as the `after` cursor."
          },
          "timestamp": {
            "type": "string",
            "format": "date-time",
            "description": "When the event was recorded."
          },
          "sessionId": {
            "type": "string",
            "description": "The session."
          },
          "turnId": {
            "type": "string",
            "description": "The turn the event belongs to; absent on session-level events."
          },
          "type": {
            "type": "string",
            "description": "Event type, for example `session.created`, `session.status_changed`, `session.ended`, `session.failed`, `message.received`, `turn.queued`, `turn.started`, `turn.completed`, `turn.failed`, `turn.cancelled`, `question.asked`, `message.delta`, `message.completed`, `tool.started`, `tool.completed`, `tool.failed`, `memory.saved`, `usage.recorded`, `runtime.log` or `agent.rendered`. New types can appear; treat unknown types as informational. See https://docs.opencomputer.dev/agents/events."
          },
          "data": {
            "type": "object",
            "description": "Fields specific to the event type, as listed on https://docs.opencomputer.dev/agents/events. Every `session.*` event's data carries `externalReference` when the session has one.",
            "additionalProperties": true
          }
        },
        "required": [
          "id",
          "seq",
          "timestamp",
          "sessionId",
          "type",
          "data"
        ]
      },
      "EventPage": {
        "type": "object",
        "description": "A page of events.",
        "properties": {
          "events": {
            "type": "array",
            "description": "Up to 500 events with `seq` greater than `after`, in ascending order. An empty page means the log has been read to its end.",
            "items": {
              "$ref": "#/components/schemas/Event"
            },
            "maxItems": 500
          }
        },
        "required": [
          "events"
        ]
      },
      "MemoryResource": {
        "type": "object",
        "description": "A document-memory resource in an environment.",
        "properties": {
          "id": {
            "type": "string",
            "description": "Resource ID."
          },
          "provider": {
            "type": "object",
            "description": "Stored provider kind and current limit.",
            "properties": {
              "kind": {
                "type": "string",
                "description": "Provider kind, for example `document`."
              },
              "maxBytes": {
                "type": "integer",
                "description": "Current document text limit in UTF-8 bytes."
              }
            }
          },
          "declared": {
            "type": "boolean",
            "description": "Whether any active deployment in the environment declares the resource."
          },
          "documents": {
            "type": "integer",
            "description": "Count of non-deleted documents."
          }
        }
      },
      "MemoryResourceInventory": {
        "type": "object",
        "description": "The environment's memory resources.",
        "properties": {
          "resources": {
            "type": "array",
            "description": "Resources, including retired ones that are no longer declared.",
            "items": {
              "$ref": "#/components/schemas/MemoryResource"
            }
          }
        },
        "required": [
          "resources"
        ]
      },
      "MemoryWriter": {
        "type": "object",
        "description": "Who last wrote the document, set by the platform.",
        "properties": {
          "kind": {
            "type": "string",
            "description": "`owner` for an owner edit, `agent` for an agent save.",
            "enum": [
              "owner",
              "agent"
            ]
          },
          "sessionId": {
            "type": "string",
            "description": "The session that saved; present when `kind` is `agent`."
          }
        },
        "required": [
          "kind"
        ]
      },
      "AgentWrites": {
        "type": "string",
        "description": "Whether agent saves may commit to the document; `disabled` freezes it.",
        "enum": [
          "enabled",
          "disabled"
        ]
      },
      "MemoryDocumentSummary": {
        "type": "object",
        "description": "Document metadata as the list returns it (no `text`).",
        "properties": {
          "id": {
            "type": "string",
            "description": "Document ID."
          },
          "title": {
            "type": "string",
            "description": "Document title."
          },
          "summary": {
            "type": "string",
            "description": "Document summary."
          },
          "agentWrites": {
            "$ref": "#/components/schemas/AgentWrites",
            "description": "Whether agent saves may commit to the document; `disabled` freezes it."
          },
          "revision": {
            "type": "string",
            "description": "Opaque revision; also returned quoted as the `ETag` header. Use it verbatim in `If-Match`."
          },
          "bytes": {
            "type": "integer",
            "description": "UTF-8 byte size of the text."
          },
          "maxBytes": {
            "type": "integer",
            "description": "The resource's current text limit."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the document last changed."
          },
          "writer": {
            "$ref": "#/components/schemas/MemoryWriter",
            "description": "Who last wrote the document, set by the platform."
          }
        }
      },
      "MemoryDocument": {
        "type": "object",
        "description": "A full document.",
        "properties": {
          "id": {
            "type": "string",
            "description": "Document ID."
          },
          "title": {
            "type": "string",
            "description": "Document title."
          },
          "summary": {
            "type": "string",
            "description": "Document summary."
          },
          "agentWrites": {
            "$ref": "#/components/schemas/AgentWrites",
            "description": "Whether agent saves may commit to the document; `disabled` freezes it."
          },
          "revision": {
            "type": "string",
            "description": "Opaque revision; also returned quoted as the `ETag` header. Use it verbatim in `If-Match`."
          },
          "bytes": {
            "type": "integer",
            "description": "UTF-8 byte size of the text."
          },
          "maxBytes": {
            "type": "integer",
            "description": "The resource's current text limit."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the document last changed."
          },
          "writer": {
            "$ref": "#/components/schemas/MemoryWriter",
            "description": "Who last wrote the document, set by the platform."
          },
          "text": {
            "type": "string",
            "description": "Document text."
          }
        }
      },
      "MemoryDocumentPage": {
        "type": "object",
        "description": "One page of document metadata.",
        "properties": {
          "documents": {
            "type": "array",
            "description": "Documents without `text`, by descending update time then ascending ID; at most 50 per page.",
            "items": {
              "$ref": "#/components/schemas/MemoryDocumentSummary"
            }
          },
          "nextCursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` for the next page; null on the last page."
          }
        },
        "required": [
          "documents",
          "nextCursor"
        ]
      },
      "PutMemoryDocumentRequest": {
        "description": "Create body (with `If-None-Match: *`) or replace body (with `If-Match`). Unknown fields are rejected. Mutation bodies are at most 64 KiB.",
        "oneOf": [
          {
            "type": "object",
            "description": "Create a document. Requires `If-None-Match: *` and a never-used ID.",
            "properties": {
              "title": {
                "type": "string",
                "description": "Document title, 1-240 UTF-8 bytes.",
                "minLength": 1
              },
              "text": {
                "type": "string",
                "description": "Document text, at most the resource's `maxBytes`. Defaults to an empty string."
              },
              "summary": {
                "type": "string",
                "description": "Summary, 0-240 UTF-8 bytes. Defaults to an empty string."
              },
              "agentWrites": {
                "$ref": "#/components/schemas/AgentWrites",
                "description": "Defaults to `enabled`."
              }
            },
            "required": [
              "title"
            ],
            "additionalProperties": false
          },
          {
            "type": "object",
            "description": "Replace text and optionally the summary. Requires `If-Match`.",
            "properties": {
              "text": {
                "type": "string",
                "description": "New document text, at most the resource's `maxBytes`."
              },
              "summary": {
                "type": "string",
                "description": "New summary, 0-240 UTF-8 bytes. Omitted means preserved."
              }
            },
            "required": [
              "text"
            ],
            "additionalProperties": false
          }
        ]
      },
      "PatchMemoryDocumentRequest": {
        "type": "object",
        "description": "Change title, agent-write policy, or both. Omitted fields stay unchanged; unknown fields are rejected.",
        "properties": {
          "title": {
            "type": "string",
            "description": "New title, 1-240 UTF-8 bytes.",
            "minLength": 1
          },
          "agentWrites": {
            "$ref": "#/components/schemas/AgentWrites",
            "description": "Whether agent saves may commit to the document; `disabled` freezes it."
          }
        },
        "additionalProperties": false,
        "minProperties": 1
      },
      "Webhook": {
        "type": "object",
        "description": "An agent webhook targeting one agent in one environment. The docs name the fields below; other fields may be present.",
        "properties": {
          "id": {
            "type": "string",
            "description": "Webhook ID."
          },
          "name": {
            "type": "string",
            "description": "Webhook name."
          },
          "agentId": {
            "type": "string",
            "description": "Target agent."
          },
          "environment": {
            "$ref": "#/components/schemas/Environment",
            "description": "Environment scope. `development` or `production` for legacy (two-environment) projects; `default` for single-environment projects, where requests naming `development` resolve to `default` and requests naming `production` fail with `409 single_environment_project`."
          },
          "enabled": {
            "type": "boolean",
            "description": "Whether invocations start sessions."
          },
          "identity": {
            "type": "string",
            "description": "Identity source for deduplicating deliveries: `header:<name>` or `body:<json-pointer>`."
          },
          "invocationUrl": {
            "type": "string",
            "description": "The URL to POST to. Contains the token only in create and rotate-token responses; listed without the token otherwise."
          },
          "token": {
            "type": "string",
            "description": "The webhook credential. Present only once, in create and rotate-token responses."
          }
        },
        "additionalProperties": true
      },
      "WebhookEnvelope": {
        "type": "object",
        "description": "A single webhook.",
        "properties": {
          "webhook": {
            "$ref": "#/components/schemas/Webhook",
            "description": "An agent webhook targeting one agent in one environment. The docs name the fields below; other fields may be present."
          }
        },
        "required": [
          "webhook"
        ]
      },
      "WebhookList": {
        "type": "object",
        "description": "Webhooks of the project.",
        "properties": {
          "webhooks": {
            "type": "array",
            "description": "Webhooks, with URLs without tokens.",
            "items": {
              "$ref": "#/components/schemas/Webhook"
            }
          }
        },
        "required": [
          "webhooks"
        ]
      },
      "CreateWebhookRequest": {
        "type": "object",
        "description": "Body of webhook creation.",
        "properties": {
          "name": {
            "type": "string",
            "description": "Webhook name."
          },
          "agentId": {
            "type": "string",
            "description": "The agent the webhook starts sessions on; it must be deployed in the environment."
          },
          "environment": {
            "$ref": "#/components/schemas/Environment",
            "description": "Environment scope. `development` or `production` for legacy (two-environment) projects; `default` for single-environment projects, where requests naming `development` resolve to `default` and requests naming `production` fail with `409 single_environment_project`."
          },
          "identity": {
            "type": "string",
            "description": "Optional identity source: `header:<name>` or `body:<json-pointer>`, for senders that cannot set `Idempotency-Key`."
          }
        },
        "required": [
          "name",
          "agentId",
          "environment"
        ]
      },
      "UpdateWebhookRequest": {
        "type": "object",
        "description": "Body of webhook update; send any of the fields.",
        "properties": {
          "name": {
            "type": "string",
            "description": "New name."
          },
          "enabled": {
            "type": "boolean",
            "description": "Enable or disable the webhook."
          },
          "identity": {
            "type": [
              "string",
              "null"
            ],
            "description": "`header:<name>` or `body:<json-pointer>`; null removes the identity source."
          }
        }
      },
      "WebhookRequest": {
        "type": "object",
        "description": "One entry of a webhook's request ledger. The docs describe the request's outcome and session ID; other fields are open. The session ID here is authoritative.",
        "properties": {
          "outcome": {
            "type": "string",
            "description": "`pending` until the session holds the turn, then `accepted`; `failed` after five start attempts or when no retry would help.",
            "enum": [
              "pending",
              "accepted",
              "failed"
            ]
          },
          "terminal": {
            "type": "boolean",
            "description": "True on a failed request that the platform determined no retry would help."
          }
        },
        "additionalProperties": true
      },
      "WebhookRequestList": {
        "type": "object",
        "description": "A webhook's request ledger.",
        "properties": {
          "requests": {
            "type": "array",
            "description": "Recorded invocation requests.",
            "items": {
              "$ref": "#/components/schemas/WebhookRequest"
            }
          }
        },
        "required": [
          "requests"
        ]
      },
      "CreateEventSubscriptionRequest": {
        "type": "object",
        "description": "Body of event subscription creation.",
        "properties": {
          "agentId": {
            "type": "string",
            "description": "Optional. Deliver outcomes of this agent only; omitted means every agent in the project."
          },
          "events": {
            "type": "array",
            "description": "One or more turn outcomes to deliver.",
            "items": {
              "$ref": "#/components/schemas/OutcomeEventType"
            },
            "minItems": 1,
            "uniqueItems": true
          },
          "destination": {
            "$ref": "#/components/schemas/SessionDestination",
            "description": "An event subscription destination: a session of an agent in the same project that can still take turns."
          },
          "environment": {
            "$ref": "#/components/schemas/EnvironmentName",
            "description": "The environment whose outcomes are delivered; the destination session runs there."
          }
        },
        "required": [
          "events",
          "destination"
        ]
      },
      "EventSubscription": {
        "type": "object",
        "description": "An immutable event subscription.",
        "properties": {
          "id": {
            "type": "string",
            "description": "Subscription ID."
          },
          "projectId": {
            "type": "string",
            "description": "The project."
          },
          "agentId": {
            "type": "string",
            "description": "Source agent; absent when every agent in the project is selected."
          },
          "events": {
            "type": "array",
            "description": "Selected turn outcomes.",
            "items": {
              "$ref": "#/components/schemas/OutcomeEventType"
            }
          },
          "destination": {
            "$ref": "#/components/schemas/SessionDestination",
            "description": "An event subscription destination: a session of an agent in the same project that can still take turns."
          },
          "environment": {
            "$ref": "#/components/schemas/EnvironmentName",
            "description": "`development` or `production`. On a single-environment project, `development` resolves to its `default` environment."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the subscription was created."
          }
        }
      },
      "EventSubscriptionEnvelope": {
        "type": "object",
        "description": "A single subscription.",
        "properties": {
          "subscription": {
            "$ref": "#/components/schemas/EventSubscription",
            "description": "An immutable event subscription."
          }
        },
        "required": [
          "subscription"
        ]
      },
      "EventSubscriptionList": {
        "type": "object",
        "description": "The project's subscriptions.",
        "properties": {
          "subscriptions": {
            "type": "array",
            "description": "Subscriptions.",
            "items": {
              "$ref": "#/components/schemas/EventSubscription"
            }
          }
        },
        "required": [
          "subscriptions"
        ]
      },
      "LinearConnection": {
        "type": "object",
        "description": "A Linear connection binding a Linear app to one agent in one environment. Never carries a secret or token.",
        "properties": {
          "id": {
            "type": "string",
            "description": "Connection ID."
          },
          "projectId": {
            "type": "string",
            "description": "The project."
          },
          "environment": {
            "$ref": "#/components/schemas/EnvironmentName",
            "description": "`development` or `production`. On a single-environment project, `development` resolves to its `default` environment."
          },
          "agentId": {
            "type": "string",
            "description": "The connected agent."
          },
          "name": {
            "type": "string",
            "description": "Linear app name."
          },
          "status": {
            "type": "string",
            "description": "Connection status.",
            "enum": [
              "pending",
              "connected",
              "disconnected",
              "revoked"
            ]
          },
          "clientId": {
            "type": "string",
            "description": "The Linear app's client ID."
          },
          "appUserId": {
            "type": "string",
            "description": "The Linear app user's ID."
          },
          "organizationId": {
            "type": "string",
            "description": "The Linear organization ID."
          },
          "webhookUrl": {
            "type": "string",
            "description": "Webhook URL to configure on the Linear app. Contains the connection's secret; treat it as a credential."
          },
          "createAppUrl": {
            "type": "string",
            "description": "Linear's create-app page prefilled with the name, callback URL and `webhookUrl`."
          },
          "verifiedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the connection was verified."
          },
          "verificationError": {
            "type": "string",
            "description": "The verification error, if any."
          },
          "lastEventAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the last Linear event was received."
          },
          "teams": {
            "type": "object",
            "description": "The Linear teams the app can see.",
            "properties": {
              "allPublic": {
                "type": "boolean",
                "description": "Whether the app sees all public teams."
              },
              "teamIds": {
                "type": "array",
                "description": "Team IDs the app can see.",
                "items": {
                  "type": "string",
                  "description": "A Linear team ID."
                }
              }
            }
          },
          "health": {
            "type": "object",
            "description": "Connection health.",
            "properties": {
              "state": {
                "type": "string",
                "description": "Health state.",
                "enum": [
                  "awaiting_credentials",
                  "awaiting_authorization",
                  "waiting_for_first_delegation",
                  "receiving",
                  "revoked"
                ]
              },
              "message": {
                "type": "string",
                "description": "Human-readable health message."
              },
              "lastEventAt": {
                "type": "string",
                "format": "date-time",
                "description": "When the last event was received, when there was one."
              }
            }
          },
          "revision": {
            "type": "integer",
            "description": "Connection revision."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the connection was created."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the connection last changed."
          }
        }
      },
      "CreateLinearConnectionRequest": {
        "type": "object",
        "description": "Body of Linear connection creation.",
        "properties": {
          "name": {
            "type": "string",
            "description": "Linear app name, 1 to 64 characters; must not contain \"Linear\".",
            "minLength": 1,
            "maxLength": 64
          },
          "environment": {
            "$ref": "#/components/schemas/EnvironmentName",
            "description": "`development` or `production`. On a single-environment project, `development` resolves to its `default` environment."
          },
          "agentId": {
            "type": "string",
            "description": "An agent of the project."
          }
        },
        "required": [
          "name",
          "environment",
          "agentId"
        ]
      },
      "CreateLinearConnectionResponse": {
        "type": "object",
        "description": "A created (or reset pending) Linear connection.",
        "properties": {
          "connectionId": {
            "type": "string",
            "description": "Connection ID."
          },
          "webhookUrl": {
            "type": "string",
            "description": "Webhook URL for the Linear app; contains the connection's secret."
          },
          "createAppUrl": {
            "type": "string",
            "description": "Linear's prefilled create-app page."
          },
          "connection": {
            "$ref": "#/components/schemas/LinearConnection",
            "description": "A Linear connection binding a Linear app to one agent in one environment. Never carries a secret or token."
          }
        }
      },
      "LinearConnectionList": {
        "type": "object",
        "description": "The project's Linear connections.",
        "properties": {
          "connections": {
            "type": "array",
            "description": "Connections.",
            "items": {
              "$ref": "#/components/schemas/LinearConnection"
            }
          }
        },
        "required": [
          "connections"
        ]
      },
      "LinearCredentialsRequest": {
        "type": "object",
        "description": "Credentials copied from the Linear app; all three are required.",
        "properties": {
          "clientId": {
            "type": "string",
            "description": "The Linear app's client ID."
          },
          "clientSecret": {
            "type": "string",
            "description": "The Linear app's client secret."
          },
          "signingSecret": {
            "type": "string",
            "description": "The Linear app's webhook signing secret."
          }
        },
        "required": [
          "clientId",
          "clientSecret",
          "signingSecret"
        ]
      },
      "LinearConnectionEnvelope": {
        "type": "object",
        "description": "A single connection.",
        "properties": {
          "connection": {
            "$ref": "#/components/schemas/LinearConnection",
            "description": "A Linear connection binding a Linear app to one agent in one environment. Never carries a secret or token."
          }
        },
        "required": [
          "connection"
        ]
      },
      "LinearAuthorizeResponse": {
        "type": "object",
        "description": "Linear consent page for the app; a workspace admin completes it.",
        "properties": {
          "authorizeUrl": {
            "type": "string",
            "description": "Linear's consent page URL."
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the authorize URL expires."
          }
        }
      },
      "LinearDisconnectResponse": {
        "type": "object",
        "description": "Result of disconnecting.",
        "properties": {
          "connection": {
            "$ref": "#/components/schemas/LinearConnection",
            "description": "A Linear connection binding a Linear app to one agent in one environment. Never carries a secret or token."
          },
          "revoked": {
            "type": "boolean",
            "description": "Whether Linear confirmed the token revocation."
          }
        }
      },
      "ProjectAgent": {
        "type": "object",
        "description": "An agent of a project.",
        "properties": {
          "id": {
            "type": "string",
            "description": "Agent ID."
          },
          "name": {
            "type": "string",
            "description": "Agent name."
          }
        }
      },
      "Project": {
        "type": "object",
        "description": "A project.",
        "properties": {
          "id": {
            "type": "string",
            "description": "Project ID."
          },
          "slug": {
            "type": "string",
            "description": "Project slug."
          },
          "name": {
            "type": "string",
            "description": "Project name."
          },
          "environmentMode": {
            "type": "string",
            "description": "`single` (one `default` environment) or `legacy` (Development and Production).",
            "enum": [
              "single",
              "legacy"
            ]
          },
          "environments": {
            "type": "array",
            "description": "The project's environments.",
            "items": {
              "type": "object",
              "description": "An environment of the project; the docs do not specify its fields.",
              "additionalProperties": true
            }
          },
          "agents": {
            "type": "array",
            "description": "The project's agents.",
            "items": {
              "$ref": "#/components/schemas/ProjectAgent"
            }
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the project was created."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the project last changed."
          }
        }
      },
      "ProjectList": {
        "type": "object",
        "description": "Projects visible to the key.",
        "properties": {
          "projects": {
            "type": "array",
            "description": "Projects.",
            "items": {
              "$ref": "#/components/schemas/Project"
            }
          }
        },
        "required": [
          "projects"
        ]
      },
      "CreateProjectRequest": {
        "type": "object",
        "description": "Body of project creation.",
        "properties": {
          "name": {
            "type": "string",
            "description": "Project name."
          },
          "slug": {
            "type": "string",
            "description": "Optional project slug."
          },
          "environmentMode": {
            "type": "string",
            "description": "`single` (one `default` environment) or `legacy` (Development and Production).",
            "enum": [
              "single",
              "legacy"
            ]
          }
        },
        "required": [
          "name"
        ]
      },
      "ProjectDetail": {
        "type": "object",
        "description": "A project with related records.",
        "properties": {
          "project": {
            "$ref": "#/components/schemas/Project",
            "description": "A project."
          },
          "deployments": {
            "type": "array",
            "description": "The project's deployments.",
            "items": {
              "$ref": "#/components/schemas/Deployment"
            }
          },
          "sessions": {
            "type": "array",
            "description": "The project's sessions.",
            "items": {
              "$ref": "#/components/schemas/SessionRow"
            }
          },
          "connections": {
            "type": "array",
            "description": "The project's connections.",
            "items": {
              "type": "object",
              "description": "A connection; the docs do not specify its fields.",
              "additionalProperties": true
            }
          },
          "schedules": {
            "type": "array",
            "description": "The project's schedules.",
            "items": {
              "type": "object",
              "description": "A schedule; the docs do not specify its fields.",
              "additionalProperties": true
            }
          }
        }
      },
      "Agent": {
        "type": "object",
        "description": "An agent.",
        "properties": {
          "id": {
            "type": "string",
            "description": "Agent ID."
          },
          "name": {
            "type": "string",
            "description": "Agent name."
          },
          "activeAlias": {
            "type": [
              "string",
              "null"
            ],
            "description": "Alias of the active deployment; null while the agent has no active deployment."
          },
          "activeDeploymentId": {
            "type": [
              "string",
              "null"
            ],
            "description": "Active deployment ID; null while the agent has no active deployment."
          },
          "deploymentCount": {
            "type": "integer",
            "description": "Number of deployments."
          }
        }
      },
      "AgentList": {
        "type": "object",
        "description": "Agents visible to the key.",
        "properties": {
          "agents": {
            "type": "array",
            "description": "Agents.",
            "items": {
              "$ref": "#/components/schemas/Agent"
            }
          }
        },
        "required": [
          "agents"
        ]
      },
      "Deployment": {
        "type": "object",
        "description": "A deployment of an agent.",
        "properties": {
          "id": {
            "type": "string",
            "description": "Deployment ID."
          },
          "agentId": {
            "type": "string",
            "description": "The agent."
          },
          "alias": {
            "type": "string",
            "description": "The deployment's alias."
          },
          "memory": {
            "type": "array",
            "description": "Memory resources the deployment declares.",
            "items": {
              "type": "object",
              "description": "A memory declaration; the API page does not specify its fields.",
              "additionalProperties": true
            }
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the deployment was created."
          }
        }
      },
      "DeploymentList": {
        "type": "object",
        "description": "Deployments of an agent.",
        "properties": {
          "deployments": {
            "type": "array",
            "description": "Deployments.",
            "items": {
              "$ref": "#/components/schemas/Deployment"
            }
          }
        },
        "required": [
          "deployments"
        ]
      },
      "GithubRepository": {
        "type": "object",
        "description": "A repository the environment's GitHub installation covers.",
        "properties": {
          "id": {
            "type": "integer",
            "description": "GitHub repository ID."
          },
          "fullName": {
            "type": "string",
            "description": "`owner/name`."
          },
          "private": {
            "type": "boolean",
            "description": "Whether the repository is private."
          },
          "defaultBranch": {
            "type": "string",
            "description": "Default branch name."
          },
          "archived": {
            "type": "boolean",
            "description": "Whether the repository is archived."
          }
        }
      },
      "GithubRepositoryPage": {
        "type": "object",
        "description": "One page of repositories, read live from GitHub.",
        "properties": {
          "repositories": {
            "type": "array",
            "description": "Repositories.",
            "items": {
              "$ref": "#/components/schemas/GithubRepository"
            }
          },
          "nextCursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` for the next page; null on the last page."
          }
        },
        "required": [
          "repositories",
          "nextCursor"
        ]
      },
      "QuestionDismissResponse": {
        "type": "object",
        "description": "Acknowledgement of the dismissal. The docs state only the `200` status, not the body.",
        "additionalProperties": true
      }
    }
  }
}
