{
  "openapi": "3.1.0",
  "info": {
    "title": "Cody API",
    "version": "1.1.0",
    "description": "Start and control Cody agent runs, consume incremental progress events, and coordinate delegated work. Each API key belongs to one account; requests are routed to that account's dedicated Cody instance.",
    "contact": { "name": "Cody", "url": "https://agentcody.ai/docs", "email": "cody@heycody.ink" }
  },
  "servers": [{ "url": "https://api.agentcody.ai", "description": "Production" }],
  "security": [{ "bearerAuth": [] }],
  "tags": [{ "name": "Runs", "description": "Start, observe, steer, cancel, and organize agent runs." }],
  "paths": {
    "/codyapi": {
      "post": {
        "tags": ["Runs"],
        "operationId": "controlRun",
        "summary": "Start, steer, or cancel a run",
        "description": "Omit `action` (or use `agent`) to start a run. Use `action=steer` to replace its active turn or `action=cancel` to stop it.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  { "$ref": "#/components/schemas/SendEventRequest" },
                  { "$ref": "#/components/schemas/SteerRunRequest" },
                  { "$ref": "#/components/schemas/CancelRunRequest" }
                ]
              },
              "example": { "agentId": "n1774177363529", "message": "Summarize today's new leads" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Run accepted.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    { "$ref": "#/components/schemas/SendEventResponse" },
                    { "$ref": "#/components/schemas/SteerRunResponse" },
                    { "$ref": "#/components/schemas/CancelRunResponse" }
                  ]
                },
                "example": { "ok": true, "runId": "2cb88653-7005-4062-9232-d0982ed2c1e3", "agentId": "n1774177363529", "status": "in_flight" }
              }
            }
          },
          "400": { "$ref": "#/components/responses/Error" },
          "401": { "$ref": "#/components/responses/Error" },
          "409": { "$ref": "#/components/responses/Error" },
          "502": { "$ref": "#/components/responses/Error" },
          "504": { "$ref": "#/components/responses/Error" }
        }
      },
      "get": {
        "tags": ["Runs"],
        "operationId": "getAgentsOrStatus",
        "summary": "List agents / Run status",
        "description": "Two read actions selected by the `action` query parameter:\n\n- `action=agents` — list your agent ids and names.\n- `action=status` — poll a run (requires `runId`).",
        "parameters": [
          {
            "name": "action",
            "in": "query",
            "required": true,
            "description": "Which read action to perform.",
            "schema": { "type": "string", "enum": ["agents", "status"] }
          },
          {
            "name": "runId",
            "in": "query",
            "required": false,
            "description": "Required when `action=status`. The runId returned by POST /codyapi.",
            "schema": { "type": "string" }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "For `action=status`, return events after this non-negative cursor. Retain `nextCursor` from the previous response.",
            "schema": { "type": "integer", "minimum": 0, "default": 0 }
          }
        ],
        "responses": {
          "200": {
            "description": "Agents list (action=agents) or run status (action=status).",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    { "$ref": "#/components/schemas/AgentsResponse" },
                    { "$ref": "#/components/schemas/RunStatusResponse" }
                  ]
                },
                "examples": {
                  "agents": {
                    "summary": "action=agents",
                    "value": { "ok": true, "agents": [{ "id": "main", "name": "Cody" }, { "id": "n1774177363529", "name": "Coby" }] }
                  },
                  "status": {
                    "summary": "action=status",
                    "value": {
                      "ok": true,
                      "run": { "runId": "2cb88653-…", "status": "succeeded", "durationMs": 5013, "rootRunId": "2cb88653-…", "childRunIds": [] },
                      "events": [{ "id": "event_1", "type": "assistant.message", "text": "There were 14 new leads today." }],
                      "nextCursor": "1",
                      "result": { "text": "There were 14 new leads today." }
                    }
                  }
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/Error" },
          "401": { "$ref": "#/components/responses/Error" },
          "409": { "$ref": "#/components/responses/Error" }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "A secret API key (cody_sk_…) generated in the dashboard under Tools → Cody API. Send it as `Authorization: Bearer <key>`."
      }
    },
    "responses": {
      "Error": {
        "description": "Error. Non-2xx status with a JSON body.",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/Error" },
            "example": { "ok": false, "error": "Missing or malformed API key." }
          }
        }
      }
    },
    "schemas": {
      "SendEventRequest": {
        "type": "object",
        "required": ["message"],
        "properties": {
          "message": { "type": "string", "description": "The task or message for the agent." },
          "agentId": { "type": "string", "description": "Target a specific agent. Omit to use your default agent. Get valid ids from `GET /codyapi?action=agents`." },
          "name": { "type": "string", "description": "A label for the run, shown in your event log." },
          "deliver": { "type": "boolean", "default": false, "description": "If true, the agent also delivers its reply to its configured channel." },
          "timeoutSeconds": { "type": "number", "description": "Maximum seconds the run may take before timing out." }
          ,
          "parentRunId": { "type": "string", "description": "Optional parent run. The new run is attached as its child and shares its rootRunId." }
        }
      },
      "SteerRunRequest": {
        "type": "object",
        "required": ["action", "runId", "message"],
        "properties": {
          "action": { "type": "string", "const": "steer" },
          "runId": { "type": "string", "description": "The stable public run identifier." },
          "message": { "type": "string", "description": "Replacement instruction for the active turn." }
        }
      },
      "CancelRunRequest": {
        "type": "object",
        "required": ["action", "runId"],
        "properties": {
          "action": { "type": "string", "const": "cancel" },
          "runId": { "type": "string", "description": "The active run to cancel." }
        }
      },
      "SendEventResponse": {
        "type": "object",
        "properties": {
          "ok": { "type": "boolean" },
          "runId": { "type": "string", "description": "Poll this with `GET /codyapi?action=status&runId=…`." },
          "agentId": { "type": "string" },
          "status": { "type": "string", "enum": ["in_flight"] },
          "parentRunId": { "type": "string" },
          "rootRunId": { "type": "string" }
        }
      },
      "SteerRunResponse": {
        "type": "object",
        "properties": {
          "ok": { "type": "boolean" },
          "runId": { "type": "string" },
          "gatewayRunId": { "type": "string", "description": "Internal replacement turn identifier. Continue polling with runId." },
          "status": { "type": "string", "enum": ["in_flight"] },
          "interruptedActiveRun": { "type": "boolean" },
          "run": { "$ref": "#/components/schemas/RunStatus" }
        }
      },
      "CancelRunResponse": {
        "type": "object",
        "properties": {
          "ok": { "type": "boolean" },
          "cancelled": { "type": "boolean" },
          "run": { "$ref": "#/components/schemas/RunStatus" }
        }
      },
      "Agent": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "name": { "type": "string" }
        }
      },
      "AgentsResponse": {
        "type": "object",
        "properties": {
          "ok": { "type": "boolean" },
          "agents": { "type": "array", "items": { "$ref": "#/components/schemas/Agent" } }
        }
      },
      "RunStatus": {
        "type": "object",
        "properties": {
          "runId": { "type": "string" },
          "gatewayRunId": { "type": "string" },
          "agentId": { "type": "string" },
          "status": { "type": "string", "enum": ["in_flight", "succeeded", "failed", "cancelled", "unknown"] },
          "parentRunId": { "type": "string" },
          "rootRunId": { "type": "string" },
          "childRunIds": { "type": "array", "items": { "type": "string" } },
          "steerCount": { "type": "integer", "minimum": 0 },
          "durationMs": { "type": "integer" },
          "endedAtMs": { "type": "integer" },
          "error": { "type": "string" }
        }
      },
      "RunStatusResponse": {
        "type": "object",
        "properties": {
          "ok": { "type": "boolean" },
          "run": { "$ref": "#/components/schemas/RunStatus" },
          "sessionId": { "type": "string" },
          "events": { "type": "array", "items": { "$ref": "#/components/schemas/RunEvent" } },
          "nextCursor": { "type": "string", "description": "Pass this value as cursor on the next poll." },
          "result": {
            "type": "object",
            "properties": { "text": { "type": "string", "description": "Latest final assistant-visible answer for this run." } }
          }
        }
      },
      "RunEvent": {
        "oneOf": [
          { "$ref": "#/components/schemas/ModelChangedEvent" },
          { "$ref": "#/components/schemas/ThinkingEvent" },
          { "$ref": "#/components/schemas/AssistantMessageEvent" },
          { "$ref": "#/components/schemas/ToolStartedEvent" },
          { "$ref": "#/components/schemas/ToolCompletedEvent" }
        ],
        "discriminator": { "propertyName": "type" }
      },
      "EventBase": {
        "type": "object",
        "required": ["id", "type"],
        "properties": {
          "id": { "type": "string" },
          "type": { "type": "string" },
          "timestamp": { "type": "string", "format": "date-time" }
        }
      },
      "ModelChangedEvent": {
        "allOf": [
          { "$ref": "#/components/schemas/EventBase" },
          { "type": "object", "properties": { "type": { "const": "model.changed" }, "provider": {}, "modelId": {} } }
        ]
      },
      "ThinkingEvent": {
        "description": "Lifecycle marker only. Hidden model reasoning is never exposed.",
        "allOf": [
          { "$ref": "#/components/schemas/EventBase" },
          { "type": "object", "properties": { "type": { "const": "agent.thinking" } } }
        ]
      },
      "AssistantMessageEvent": {
        "allOf": [
          { "$ref": "#/components/schemas/EventBase" },
          { "type": "object", "required": ["text"], "properties": { "type": { "const": "assistant.message" }, "text": { "type": "string" } } }
        ]
      },
      "ToolStartedEvent": {
        "allOf": [
          { "$ref": "#/components/schemas/EventBase" },
          {
            "type": "object",
            "required": ["toolCallId", "tool", "arguments"],
            "properties": {
              "type": { "const": "tool.started" },
              "toolCallId": { "type": "string" },
              "tool": { "type": "string" },
              "arguments": { "description": "Redacted and truncated tool arguments." }
            }
          }
        ]
      },
      "ToolCompletedEvent": {
        "allOf": [
          { "$ref": "#/components/schemas/EventBase" },
          {
            "type": "object",
            "required": ["toolCallId", "output", "isError"],
            "properties": {
              "type": { "const": "tool.completed" },
              "toolCallId": { "type": "string" },
              "output": { "type": "string", "description": "Redacted and truncated tool output." },
              "isError": { "type": "boolean" }
            }
          }
        ]
      },
      "Error": {
        "type": "object",
        "properties": {
          "ok": { "type": "boolean", "enum": [false] },
          "error": { "type": "string" }
        }
      }
    }
  }
}
