{
  "components": {
    "schemas": {
      "AddCommentRequest": {
        "description": "Request body for `POST /sessions/{id}/comments`.",
        "properties": {
          "anchor_content": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Plain-text snapshot of the selected range, used to re-anchor the comment after file edits. `None` if not provided.",
            "title": "Anchor Content"
          },
          "body": {
            "description": "The comment text.",
            "title": "Body",
            "type": "string"
          },
          "end_index": {
            "description": "0-based absolute character offset (exclusive) within the file where the anchor range ends.",
            "format": "int64",
            "title": "End Index",
            "type": "integer"
          },
          "path": {
            "description": "File path relative to workspace root, e.g. `\"src/App.tsx\"`.",
            "title": "Path",
            "type": "string"
          },
          "start_index": {
            "description": "0-based absolute character offset (inclusive) within the file where the anchor range begins.",
            "format": "int64",
            "title": "Start Index",
            "type": "integer"
          }
        },
        "required": [
          "path",
          "body",
          "start_index",
          "end_index"
        ],
        "title": "AddCommentRequest",
        "type": "object"
      },
      "AgentObject": {
        "description": "API representation of a registered agent.",
        "properties": {
          "builtin": {
            "default": false,
            "description": "Whether this is a server-*seeded* built-in agent (deterministic, name-derived id) as opposed to an operator/user-registered template (random id, e.g. via `omnigent server --agent`) or a session-scoped upload. The Web UI's new-session picker uses this to decide whether a same-named `omnigent run` upload may shadow the catalog entry: seeded built-ins are protected, while a user-registered template is superseded by a newer same-named upload. Always `False` for session-scoped agents.",
            "title": "Builtin",
            "type": "boolean"
          },
          "created_at": {
            "description": "Unix epoch timestamp of creation.",
            "format": "int64",
            "title": "Created At",
            "type": "integer"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional free-text description of the agent's purpose.",
            "title": "Description"
          },
          "harness": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "The agent's harness/kind, e.g. `\"codex\"`, `\"codex-native\"`, or `\"claude-native\"` for `executor.type: omnigent` agents, otherwise the executor type (`\"claude_sdk\"`, `\"agents_sdk\"`). `None` when the bundle cannot be loaded. Lets the Web UI Add Agent picker recognise an agent's kind (Codex vs Claude) without hardcoding by name slug.",
            "title": "Harness"
          },
          "id": {
            "description": "Unique agent identifier, e.g. `\"ag_abc123\"`.",
            "title": "Id",
            "type": "string"
          },
          "mcp_servers": {
            "description": "MCP servers the agent is connected to (secret fields omitted). Empty list when the spec declares no MCP servers or when the bundle cannot be loaded.",
            "items": {
              "$ref": "#/components/schemas/MCPServerSummary"
            },
            "title": "Mcp Servers",
            "type": "array"
          },
          "mcp_servers_editable": {
            "default": false,
            "description": "Whether the MCP list can be edited through the session UI by the authenticated caller. This requires ownership of both the effective session and its session-scoped agent; built-in template and native agents are read-only.",
            "title": "Mcp Servers Editable",
            "type": "boolean"
          },
          "name": {
            "description": "Human-readable agent name, e.g. `\"research-agent\"`.",
            "title": "Name",
            "type": "string"
          },
          "object": {
            "default": "agent",
            "description": "Fixed resource type, always `\"agent\"`.",
            "title": "Object",
            "type": "string"
          },
          "policies": {
            "description": "Guardrails policies declared on the agent. Each entry summarises the policy name, type, and phases. Empty list when the spec declares no policies or when the bundle cannot be loaded.",
            "items": {
              "$ref": "#/components/schemas/PolicySummary"
            },
            "title": "Policies",
            "type": "array"
          },
          "skills": {
            "description": "Skills bundled in the agent spec (`skills/<dir>/SKILL.md`). Lets the Web UI's new-session composer offer a slash-command menu before a session exists. `GET /skills` discovers host skills and, when given `session_id`, merges the session's bundled skills. Empty list when the spec bundles no skills or when the bundle cannot be loaded.",
            "items": {
              "$ref": "#/components/schemas/SkillSummary"
            },
            "title": "Skills",
            "type": "array"
          },
          "terminals": {
            "description": "Terminal names declared in the spec's `terminals:` block, in declaration order, e.g. `[\"shell\"]`. The Web UI gates its \"new terminal\" affordance on this list (creation is only offered for agents with terminal access) and offers these names as the launchable choices. Empty list when the spec declares no terminals or when the bundle cannot be loaded.",
            "items": {
              "type": "string"
            },
            "title": "Terminals",
            "type": "array"
          },
          "updated_at": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "Unix epoch timestamp of the last update, or `None` if never updated.",
            "title": "Updated At"
          },
          "version": {
            "default": 1,
            "description": "Monotonic version counter. Starts at 1, incremented on each update.",
            "format": "int64",
            "title": "Version",
            "type": "integer"
          }
        },
        "required": [
          "id",
          "name",
          "created_at"
        ],
        "title": "AgentObject",
        "type": "object"
      },
      "AutomaticSessionRenameRequest": {
        "additionalProperties": false,
        "description": "Proposed title for a framework or agent-initiated rename.",
        "properties": {
          "title": {
            "maxLength": 100,
            "minLength": 2,
            "title": "Title",
            "type": "string"
          }
        },
        "required": [
          "title"
        ],
        "title": "AutomaticSessionRenameRequest",
        "type": "object"
      },
      "AutomaticSessionRenameResponse": {
        "description": "Result of a conditional automatic session rename.",
        "properties": {
          "reason": {
            "anyOf": [
              {
                "enum": [
                  "not_top_level",
                  "no_seed",
                  "title_changed",
                  "generation_failed"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Reason"
          },
          "renamed": {
            "title": "Renamed",
            "type": "boolean"
          },
          "title": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Title"
          }
        },
        "required": [
          "renamed"
        ],
        "title": "AutomaticSessionRenameResponse",
        "type": "object"
      },
      "BackgroundTaskInfo": {
        "description": "One still-running background shell from the claude-native `Stop` hook.\n\nClaude Code leaves finished shells in the hook's `background_tasks`\narray, so the list surfaced here is filtered to the non-terminal ones \u2014\nits length matches the `background_task_count` tally. Every field is\nbest-effort: the hook shape is external, so an entry missing one field\nstill yields a usable row (e.g. a `description` with no `command`).",
        "properties": {
          "command": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Command the shell is running, e.g. `\"sleep 120\"`.",
            "title": "Command"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Human-readable label, e.g. `\"Wait for CI\"`.",
            "title": "Description"
          },
          "id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Opaque per-shell identifier, e.g. `\"abc123\"`.",
            "title": "Id"
          },
          "status": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Per-task status, e.g. `\"running\"`.",
            "title": "Status"
          },
          "type": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Task kind, e.g. `\"shell\"`.",
            "title": "Type"
          }
        },
        "title": "BackgroundTaskInfo",
        "type": "object"
      },
      "Body_update_session_agent_v1_sessions__session_id__agent_put": {
        "properties": {
          "bundle": {
            "contentMediaType": "application/octet-stream",
            "title": "Bundle",
            "type": "string"
          }
        },
        "required": [
          "bundle"
        ],
        "title": "Body_update_session_agent_v1_sessions__session_id__agent_put",
        "type": "object"
      },
      "Body_upload_session_file_v1_sessions__session_id__resources_files_post": {
        "properties": {
          "file": {
            "contentMediaType": "application/octet-stream",
            "title": "File",
            "type": "string"
          }
        },
        "required": [
          "file"
        ],
        "title": "Body_upload_session_file_v1_sessions__session_id__resources_files_post",
        "type": "object"
      },
      "BrandingInfo": {
        "properties": {
          "app_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "App Name"
          },
          "heading": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Heading"
          },
          "logos": {
            "$ref": "#/components/schemas/BrandingLogosInfo"
          },
          "powered_by": {
            "title": "Powered By",
            "type": "boolean"
          }
        },
        "required": [
          "app_name",
          "heading",
          "logos",
          "powered_by"
        ],
        "title": "BrandingInfo",
        "type": "object"
      },
      "BrandingLogosInfo": {
        "properties": {
          "favicon": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Favicon"
          },
          "loading": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Loading"
          },
          "main": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Main"
          }
        },
        "required": [
          "main",
          "loading",
          "favicon"
        ],
        "title": "BrandingLogosInfo",
        "type": "object"
      },
      "BrowserActionRequestEvent": {
        "description": "Request that the desktop renderer perform one browser action.\n\nEmitted by the server `POST /v1/sessions/{id}/browser/action_request`\nroute when a runner-side `browser_*` tool dispatch needs the\nOmnigent desktop app's embedded browser to act. The event fans out\non the session stream to every subscribed renderer; each renderer\nfirst POSTs `/browser/action_claim/{action_id}` and only the\nwinning claimant executes the action and POSTs the result back to\n`/browser/action_result/{action_id}`. The claim lease prevents\ndouble execution when more than one renderer is subscribed.",
        "properties": {
          "action": {
            "description": "The browser action to perform \u2014 the `browser_` tool name with the prefix stripped, e.g. `\"navigate\"`, `\"snapshot\"`, `\"click\"`, `\"type\"`, `\"screenshot\"`.",
            "title": "Action",
            "type": "string"
          },
          "action_id": {
            "description": "Unique correlation id for this request, e.g. `\"baction_abc123\"`. Echoed on the claim and result routes.",
            "title": "Action Id",
            "type": "string"
          },
          "args": {
            "additionalProperties": true,
            "description": "Action arguments forwarded from the tool call, e.g. `{\"url\": \"https://example.com\"}`.",
            "title": "Args",
            "type": "object"
          },
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "type": {
            "const": "browser.action_request",
            "description": "Always `\"browser.action_request\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "action_id",
          "action",
          "args"
        ],
        "title": "BrowserActionRequestEvent",
        "type": "object"
      },
      "CancelledEvent": {
        "description": "Terminal event for a turn cancelled before completion.",
        "properties": {
          "response": {
            "$ref": "#/components/schemas/ResponseObject",
            "description": "The final response object with `status=\"cancelled\"`."
          },
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "type": {
            "const": "response.cancelled",
            "description": "Always `\"response.cancelled\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "response"
        ],
        "title": "CancelledEvent",
        "type": "object"
      },
      "ChildSessionList": {
        "description": "Paginated list of child sessions; `data` is a page of `ChildSessionSummary`.",
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/ChildSessionSummary"
            },
            "title": "Data",
            "type": "array"
          },
          "first_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "First Id"
          },
          "has_more": {
            "default": false,
            "title": "Has More",
            "type": "boolean"
          },
          "last_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Id"
          },
          "object": {
            "const": "list",
            "default": "list",
            "title": "Object",
            "type": "string"
          }
        },
        "title": "ChildSessionList",
        "type": "object"
      },
      "ChildSessionSummary": {
        "description": "Summary of a sub-agent (child) session under a parent session.\n\nPowers `GET /v1/sessions/{id}/child_sessions`. Lets the web /\nREPL debug surface enumerate sub-agent calls spawned from a\nparent session without parsing parent `function_call_output`\nJSON handles (the legacy TUI Ctrl+O path). The endpoint is the\ncanonical \"historical truth\" source; the existing transient\n`session.created` SSE event handles live incremental updates.\n\nFields are derived from the child `Conversation` plus its\nlatest `Task` (newest by `created_at`).",
        "properties": {
          "agent_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Agent id recorded on the latest task, e.g. `\"ag_abc123\"`. `None` if the child has no tasks yet (rare \u2014 `_spawn_one` creates a task atomically with the conversation).",
            "title": "Agent Id"
          },
          "agent_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Agent type recorded on the latest task, e.g. `\"researcher\"`. Mirrors the `tool` prefix in `title` and is provided alongside it because the title is a denormalized string while `agent_name` is the durable per-task value.",
            "title": "Agent Name"
          },
          "busy": {
            "default": false,
            "description": "`True` when the child's session loop is live. Mirrors the algorithm used by `GET /v1/sessions/{id}` to compute `status`: read the live in-memory cache first (`\"running\"`/`\"waiting\"` \u2192 busy), and fall back to the latest task's status on cache miss (`\"queued\"` / `\"in_progress\"` \u2192 busy). For NO_DBOS sessions the tasks table is not populated during active runs, so the cache consult is what keeps the rail's \"Working\" badge correct.",
            "title": "Busy",
            "type": "boolean"
          },
          "created_at": {
            "description": "Unix epoch timestamp of child creation.",
            "format": "int64",
            "title": "Created At",
            "type": "integer"
          },
          "current_task_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Latest task id for the child (newest by `created_at`), e.g. `\"task_abc123\"`. `None` if no tasks exist.",
            "title": "Current Task Id"
          },
          "current_task_status": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Status of the latest task, e.g. `\"completed\"`, `\"in_progress\"`, `\"failed\"`. `None` if no tasks exist.",
            "title": "Current Task Status"
          },
          "id": {
            "description": "Child conversation/session identifier, e.g. `\"conv_child123\"`.",
            "title": "Id",
            "type": "string"
          },
          "kind": {
            "default": "sub_agent",
            "description": "Conversation kind discriminator, always `\"sub_agent\"` for rows surfaced by this endpoint.",
            "title": "Kind",
            "type": "string"
          },
          "labels": {
            "additionalProperties": {
              "type": "string"
            },
            "description": "Session-scoped guardrails labels on the child conversation (mirrors `ConversationObject.labels`).",
            "title": "Labels",
            "type": "object"
          },
          "last_message_preview": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Single-line preview of the most recent message item in the child's conversation, truncated to ~150 chars with a trailing ellipsis when longer. `None` when the child has no message items yet (rare \u2014 the spawn tool immediately commits a user message). Lets the UI render a real-time \"what's the sub-agent saying right now\" line without fetching the child's full item history.",
            "title": "Last Message Preview"
          },
          "last_task_error": {
            "anyOf": [
              {
                "additionalProperties": {
                  "type": "string"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Error details from the child's most recent failed run, e.g. `{\"code\": \"required_terminal_exited\", \"message\": \"...\"}`. `None` when the child has no durable failure detail. This is the typed projection of runner-owned failure labels; clients should not parse those labels directly.",
            "title": "Last Task Error"
          },
          "object": {
            "default": "child_session",
            "description": "Fixed resource type, always `\"child_session\"`.",
            "title": "Object",
            "type": "string"
          },
          "parent_session_id": {
            "description": "Parent conversation id (echo of the route's `session_id` path parameter), e.g. `\"conv_parent987\"`. Stable join key for clients that cache child rows across multiple parents.",
            "title": "Parent Session Id",
            "type": "string"
          },
          "pending_elicitations_count": {
            "default": 0,
            "description": "Number of approval / input prompts the child is currently blocked on, read from the server's `omnigent.runtime.pending_elicitations` index. `> 0` means the sub-agent is parked awaiting user input \u2014 the Agents rail renders an \"awaiting input\" badge so a fanned-out sub-agent that needs attention is visible without opening its chat. Mirrors `SessionListItem.pending_elicitations_count`.",
            "format": "int64",
            "title": "Pending Elicitations Count",
            "type": "integer"
          },
          "routed_model": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Model this sub-agent runs on when one was pinned for it, e.g. `\"databricks-claude-opus-4-8\"`. Read from the child's `model_override` \u2014 the field intelligent routing writes when it picks a model for a spawned child. `None` when the child inherits the parent/spec model.",
            "title": "Routed Model"
          },
          "routing_decision_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Identifier of the routing decision that produced `routed_model`, mirroring `RoutingDecisionData.decision_id`. Read from the child's `omnigent.routing.decision_id` label, stamped when routing pins the model. `None` when the child was not routed.",
            "title": "Routing Decision Id"
          },
          "session_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Sub-agent instance name, the suffix of `title` after the first `\":\"`, e.g. `\"auth\"`. `None` if `title` is `None` or missing a colon.",
            "title": "Session Name"
          },
          "task_summary": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Task Summary"
          },
          "title": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Sub-agent title, `\"{agent_type}:{session_name}\"` as written by `omnigent.tools.builtins.spawn._spawn_one`, e.g. `\"researcher:auth\"`. `None` only for legacy / malformed rows; the spawn path always sets it.",
            "title": "Title"
          },
          "tool": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "UI-facing sub-agent label. For Omnigent-spawned children this is derived from the prefix of `title` before the first `\":\"`, e.g. `\"researcher\"`. For Codex-native children this is the Codex-assigned `agent_nickname` when available, then `agent_role`, then `\"Codex\"`. Falls back to the raw title for legacy / malformed rows; `None` only when `title` itself is `None` or empty.",
            "title": "Tool"
          },
          "updated_at": {
            "description": "Unix epoch timestamp of the child's most recent update.",
            "format": "int64",
            "title": "Updated At",
            "type": "integer"
          }
        },
        "required": [
          "id",
          "parent_session_id",
          "created_at",
          "updated_at"
        ],
        "title": "ChildSessionSummary",
        "type": "object"
      },
      "ClearCodexGoalResponse": {
        "description": "Response body for `DELETE /v1/sessions/{id}/codex_goal`.",
        "properties": {
          "cleared": {
            "description": "`True` when Codex removed an existing goal; `False` when no goal was present.",
            "title": "Cleared",
            "type": "boolean"
          }
        },
        "required": [
          "cleared"
        ],
        "title": "ClearCodexGoalResponse",
        "type": "object"
      },
      "ClientTaskCancelEvent": {
        "description": "Server-side request that the client cancel a tunneled tool call.\n\nEmitted by `omnigent/runtime/workflow.py` when a parent\ncancellation needs to propagate to a long-running async client\ntool. Wire shape matches `workflow.py:4258-4266`.",
        "properties": {
          "call_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Synthetic `call_id` the SDK uses to reconcile the local task; `None` when no pending tool call row exists for the task.",
            "title": "Call Id"
          },
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "task_id": {
            "description": "Identifier of the client-side task being cancelled, e.g. `\"resp_async_abc\"`.",
            "title": "Task Id",
            "type": "string"
          },
          "type": {
            "const": "response.client_task.cancel",
            "description": "Always `\"response.client_task.cancel\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "task_id"
        ],
        "title": "ClientTaskCancelEvent",
        "type": "object"
      },
      "CodexGoalObject": {
        "description": "Current Codex goal state for a Codex-native session.\n\nMirrors Codex app-server's `ThreadGoal` shape using Omnigent's\nsnake-case API convention. `created_at` and `updated_at` are optional\nbecause older app-server documentation examples omit them even though the\ncurrent protocol includes them.",
        "properties": {
          "created_at": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "Unix timestamp when the goal was created, e.g. `1776272400`. `None` when not provided by Codex.",
            "title": "Created At"
          },
          "objective": {
            "description": "Goal objective text, e.g. `\"Finish the migration and keep tests green\"`.",
            "title": "Objective",
            "type": "string"
          },
          "status": {
            "description": "Raw Codex goal lifecycle status, e.g. `\"active\"`.",
            "title": "Status",
            "type": "string"
          },
          "thread_id": {
            "description": "Codex app-server thread id, e.g. `\"thr_123\"`.",
            "title": "Thread Id",
            "type": "string"
          },
          "time_used_seconds": {
            "description": "Wall-clock seconds spent on this goal, e.g. `60`.",
            "format": "int64",
            "minimum": 0.0,
            "title": "Time Used Seconds",
            "type": "integer"
          },
          "token_budget": {
            "anyOf": [
              {
                "exclusiveMinimum": 0.0,
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional token budget, e.g. `40000`. `None` means no explicit budget is set.",
            "title": "Token Budget"
          },
          "tokens_used": {
            "description": "Tokens spent while pursuing this goal, e.g. `1024`.",
            "format": "int64",
            "minimum": 0.0,
            "title": "Tokens Used",
            "type": "integer"
          },
          "updated_at": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "Unix timestamp when the goal was last updated, e.g. `1776272460`. `None` when not provided by Codex.",
            "title": "Updated At"
          }
        },
        "required": [
          "thread_id",
          "objective",
          "status",
          "tokens_used",
          "time_used_seconds"
        ],
        "title": "CodexGoalObject",
        "type": "object"
      },
      "CodexGoalResponse": {
        "description": "Response body for reading or setting a Codex-native session goal.",
        "properties": {
          "goal": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/CodexGoalObject"
              },
              {
                "type": "null"
              }
            ],
            "description": "Current goal state, or `None` when the session has no persisted Codex goal."
          }
        },
        "required": [
          "goal"
        ],
        "title": "CodexGoalResponse",
        "type": "object"
      },
      "CompactionCompletedEvent": {
        "description": "Conversation history compaction has finished.\n\nEmitted after compaction completes \u2014 either by the server after\n`compact_conversation_now()` (explicit `/compact`), or by a\nharness that compacted its own internal context. Clients that\nrendered a \"Compacting\u2026\" spinner on\n`CompactionInProgressEvent` should upgrade it to the\npermanent \"Conversation compacted\" marker on this event.\n\nWhen emitted by a harness, `summary` and `summary_model`\nare populated so the runner can persist a compaction item for\nsession resume. When emitted by the server's explicit\n`/compact` path, those fields are `None`.",
        "properties": {
          "compacted_messages": {
            "anyOf": [
              {
                "items": {
                  "additionalProperties": true,
                  "type": "object"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Compacted Messages"
          },
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "summary": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Text summary of the compacted conversation, or `None` for server-side compaction (already persisted).",
            "title": "Summary"
          },
          "summary_model": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Model used for summarization, or `None` if truncation-based or server-side.",
            "title": "Summary Model"
          },
          "total_tokens": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Tiktoken estimate of the post-compaction message context size, e.g. `8421`. Used by clients to update the context-ring immediately without waiting for the next `response.completed` usage report. `None` when token counting is unavailable.",
            "title": "Total Tokens"
          },
          "type": {
            "const": "response.compaction.completed",
            "description": "Always `\"response.compaction.completed\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type"
        ],
        "title": "CompactionCompletedEvent",
        "type": "object"
      },
      "CompactionData": {
        "description": "Data payload for a compaction summary item.\n\nStored as a conversation item of `type=\"compaction\"`.\nThe summary covers all items from the start of the\nconversation (or the previous compaction item) through\nthe item identified by `last_item_id`.",
        "properties": {
          "compacted_messages": {
            "anyOf": [
              {
                "items": {
                  "additionalProperties": true,
                  "type": "object"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Compacted Messages"
          },
          "last_item_id": {
            "description": "The item ID (inclusive) of the last conversation item covered by this summary, e.g. `\"msg_abc123\"`. Items at positions <= this item are summarized and do not need to be loaded for prompt construction.",
            "title": "Last Item Id",
            "type": "string"
          },
          "model": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "The model used to generate the summary, e.g. `\"openai/gpt-4o\"`.",
            "title": "Model"
          },
          "summary": {
            "description": "The LLM-generated summary text covering all conversation items up through `last_item_id`, e.g. `\"User asked to analyze a dataset. Agent loaded data.csv and computed statistics.\"`.",
            "title": "Summary",
            "type": "string"
          },
          "token_count": {
            "description": "Approximate token count of the summary text, for budget tracking, e.g. `342`.",
            "format": "int64",
            "title": "Token Count",
            "type": "integer"
          },
          "window_id": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Opaque vendor compaction-window identifier. Current Codex writes a UUID string to `payload.window_id` on its `type == \"compacted\"` rollout JSONL record; older Codex rollouts used integer counters there.",
            "title": "Window Id"
          }
        },
        "required": [
          "summary",
          "last_item_id",
          "token_count"
        ],
        "title": "CompactionData",
        "type": "object"
      },
      "CompactionFailedEvent": {
        "description": "Conversation history compaction failed.\n\nEmitted by `omnigent/server/routes/sessions.py` when\n`compact_conversation_now()` raises. Clients that rendered a\n\"Compacting\u2026\" spinner on `CompactionInProgressEvent`\nshould dismiss it without leaving a permanent marker, since the\nconversation history was not modified.",
        "properties": {
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "type": {
            "const": "response.compaction.failed",
            "description": "Always `\"response.compaction.failed\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type"
        ],
        "title": "CompactionFailedEvent",
        "type": "object"
      },
      "CompactionInProgressEvent": {
        "description": "Conversation history is being compacted.\n\nEmitted by `omnigent/runtime/compaction.py` while a\ncompaction step runs so clients can render a \"summarizing\nhistory\u2026\" indicator. Wire shape matches `compaction.py:765`.\n\nA long compaction is announced repeatedly (once per status poll), so\nclients must treat every event carrying the same `started_at` as one\ncompaction \u2014 refreshing their indicator rather than stacking another.",
        "properties": {
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "started_at": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Unix epoch timestamp (seconds) when this compaction was first reported in progress. Stable across repeated progress events for the same compaction, so clients can anchor an elapsed counter to the true start \u2014 including after a page reload. `None` when the emitter does not track it.",
            "title": "Started At"
          },
          "type": {
            "const": "response.compaction.in_progress",
            "description": "Always `\"response.compaction.in_progress\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type"
        ],
        "title": "CompactionInProgressEvent",
        "type": "object"
      },
      "CompletedEvent": {
        "description": "Terminal event for a successfully completed turn.\n\nCarries the final\n`omnigent.server.schemas.ResponseObject`.",
        "properties": {
          "response": {
            "$ref": "#/components/schemas/ResponseObject",
            "description": "The final response object with `status=\"completed\"`."
          },
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "type": {
            "const": "response.completed",
            "description": "Always `\"response.completed\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "response"
        ],
        "title": "CompletedEvent",
        "type": "object"
      },
      "ConversationDeleted": {
        "description": "Confirmation payload returned after deleting a conversation.",
        "properties": {
          "deleted": {
            "default": true,
            "description": "Always `True`.",
            "title": "Deleted",
            "type": "boolean"
          },
          "id": {
            "description": "ID of the deleted conversation, e.g. `\"conv_abc123\"`.",
            "title": "Id",
            "type": "string"
          },
          "object": {
            "default": "conversation.deleted",
            "description": "Fixed resource type, always `\"conversation.deleted\"`.",
            "title": "Object",
            "type": "string"
          }
        },
        "required": [
          "id"
        ],
        "title": "ConversationDeleted",
        "type": "object"
      },
      "ConversationItem": {
        "description": "A persisted item with a store-assigned ID.",
        "properties": {
          "created_at": {
            "description": "Unix epoch timestamp of creation.",
            "format": "int64",
            "title": "Created At",
            "type": "integer"
          },
          "created_by": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Identity of the human actor who authored this item, or `None` for agent/tool/system items and single-user mode. Lets owner and collaborator messages be distinguished.",
            "title": "Created By"
          },
          "data": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/MessageData"
              },
              {
                "$ref": "#/components/schemas/FunctionCallData"
              },
              {
                "$ref": "#/components/schemas/FunctionCallOutputData"
              },
              {
                "$ref": "#/components/schemas/ErrorData"
              },
              {
                "$ref": "#/components/schemas/ReasoningData"
              },
              {
                "$ref": "#/components/schemas/CompactionData"
              },
              {
                "$ref": "#/components/schemas/NativeToolData"
              },
              {
                "$ref": "#/components/schemas/ResourceEventData"
              },
              {
                "$ref": "#/components/schemas/RoutingDecisionData"
              },
              {
                "$ref": "#/components/schemas/SlashCommandData"
              },
              {
                "$ref": "#/components/schemas/TerminalCommandData"
              }
            ],
            "description": "The typed data payload (MessageData, etc.).",
            "title": "Data"
          },
          "id": {
            "description": "Store-assigned item ID, e.g. `\"msg_abc123\"`.",
            "title": "Id",
            "type": "string"
          },
          "response_id": {
            "description": "The task/response ID this item belongs to.",
            "title": "Response Id",
            "type": "string"
          },
          "status": {
            "description": "Item status, e.g. `\"completed\"`.",
            "title": "Status",
            "type": "string"
          },
          "type": {
            "description": "Item type, e.g. `\"message\"`, `\"function_call\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "id",
          "type",
          "status",
          "response_id",
          "created_at",
          "data"
        ],
        "title": "ConversationItem",
        "type": "object"
      },
      "ConversationRef": {
        "description": "Lightweight reference to a conversation, used in request and\nresponse bodies where only the conversation ID is needed.",
        "properties": {
          "id": {
            "description": "Conversation identifier, e.g. `\"conv_abc123\"`.",
            "title": "Id",
            "type": "string"
          }
        },
        "required": [
          "id"
        ],
        "title": "ConversationRef",
        "type": "object"
      },
      "CopyFilesRequest": {
        "description": "Request to copy files from a lineage ancestor into a session.\n\nThe destination session is the path parameter; `source_session_id`\nmust be a STRICT ancestor of the destination up its\n`parent_conversation_id` chain (spawn lineage) \u2014 the destination may\nnot name itself as the source. The copy creates new child-scoped rows \u2014\nit does not grant cross-session read access.",
        "properties": {
          "file_ids": {
            "description": "Non-empty, unique ids of the source-owned files to copy, e.g. `[\"file_abc123\"]`.",
            "items": {
              "minLength": 1,
              "type": "string"
            },
            "minItems": 1,
            "title": "File Ids",
            "type": "array",
            "uniqueItems": true
          },
          "source_session_id": {
            "description": "Session that owns the source files, e.g. `\"conv_parent\"`. Must be a strict ancestor of the destination.",
            "title": "Source Session Id",
            "type": "string"
          }
        },
        "required": [
          "source_session_id",
          "file_ids"
        ],
        "title": "CopyFilesRequest",
        "type": "object"
      },
      "CreateDefaultPolicyRequest": {
        "description": "Request body for `POST /v1/policies`.",
        "properties": {
          "factory_params": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional dict of kwargs passed to the handler when it is a factory function. Only valid for `type=\"python\"`, e.g. `{\"limit\": 10}`.",
            "title": "Factory Params"
          },
          "handler": {
            "description": "Dotted import path (python) or HTTPS URL (url), e.g. `\"github_mcp_policy.block_non_misc_push\"` or `\"https://example.com/policies/eval\"`.",
            "title": "Handler",
            "type": "string"
          },
          "name": {
            "description": "Human-readable policy name. Must be globally unique, e.g. `\"block_non_feature_branch_push\"`.",
            "title": "Name",
            "type": "string"
          },
          "type": {
            "description": "Handler discriminator: `\"python\"`, `\"url\"`,",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "name",
          "type",
          "handler"
        ],
        "title": "CreateDefaultPolicyRequest",
        "type": "object"
      },
      "CreateDirectoryRequest": {
        "description": "Request body for `POST /v1/hosts/{host_id}/directories`.",
        "properties": {
          "path": {
            "description": "Absolute path of the directory to create on the host machine, e.g. `\"/Users/corey/projects/new-app\"`, or a tilde-prefixed path (`\"~/scratch\"`) the host expands against its own process owner. Missing parents are created.",
            "title": "Path",
            "type": "string"
          }
        },
        "required": [
          "path"
        ],
        "title": "CreateDirectoryRequest",
        "type": "object"
      },
      "CreateProjectRequest": {
        "additionalProperties": false,
        "description": "Request body for `POST /v1/projects`.",
        "properties": {
          "config": {
            "additionalProperties": true,
            "description": "Optional default session settings (opaque JSON object). Omitted / empty stores no defaults.",
            "title": "Config",
            "type": "object"
          },
          "name": {
            "description": "Human-readable project name. Trimmed; must be non-empty and at most 100 characters; unique among the caller's projects.",
            "title": "Name",
            "type": "string"
          }
        },
        "required": [
          "name"
        ],
        "title": "CreateProjectRequest",
        "type": "object"
      },
      "CreateSessionPolicyRequest": {
        "description": "Request body for `POST /v1/sessions/{session_id}/policies`.",
        "properties": {
          "factory_params": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional dict of kwargs passed to the handler when it is a factory function. Only valid for `type=\"python\"`, e.g. `{\"limit\": 10}`.",
            "title": "Factory Params"
          },
          "handler": {
            "description": "Dotted import path (python) or HTTPS URL (url), e.g. `\"github_mcp_policy.block_non_misc_push\"` or `\"https://example.com/policies/eval\"`.",
            "title": "Handler",
            "type": "string"
          },
          "name": {
            "description": "Human-readable policy name. Must be unique within the session, e.g. `\"block_non_feature_branch_push\"`.",
            "title": "Name",
            "type": "string"
          },
          "type": {
            "description": "Handler discriminator: `\"python\"` or `\"url\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "name",
          "type",
          "handler"
        ],
        "title": "CreateSessionPolicyRequest",
        "type": "object"
      },
      "CreatedEvent": {
        "description": "Initial event emitted at the start of every streaming response.\n\nCarries the freshly-allocated\n`omnigent.server.schemas.ResponseObject` (status will\nbe `\"queued\"` or `\"in_progress\"` depending on whether the\ntask started immediately).",
        "properties": {
          "response": {
            "$ref": "#/components/schemas/ResponseObject",
            "description": "The newly-allocated response object."
          },
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "type": {
            "const": "response.created",
            "description": "Always `\"response.created\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "response"
        ],
        "title": "CreatedEvent",
        "type": "object"
      },
      "DailyCost": {
        "description": "One day's LLM spend for the daily timeline chart.",
        "properties": {
          "cost_usd": {
            "default": 0.0,
            "format": "double",
            "title": "Cost Usd",
            "type": "number"
          },
          "day": {
            "title": "Day",
            "type": "string"
          }
        },
        "required": [
          "day"
        ],
        "title": "DailyCost",
        "type": "object"
      },
      "ElicitationRequestEvent": {
        "description": "Synchronous request for a decision from upstream.\n\nEmitted by Omnigent (or, under the new contract, by a harness)\nwhen the LLM / a tool / a policy needs a verdict before\nproceeding. The consumer replies via\n`POST /v1/sessions/{session_id}/events` with\n`type == \"approval\"` and\n`omnigent.server.schemas.ElicitationResult` fields in\n`data`. This preserves MCP request/reply correlation by id\nwithout threading elicitations through PATCH.\n\nWire shape matches the existing emit at\n`omnigent/runtime/policies/approval.py:175`.",
        "properties": {
          "elicitation_id": {
            "description": "Unique correlation id for this request \u2014 appears in the consumer's approval event payload, e.g. `\"elicit_abc123\"`.",
            "title": "Elicitation Id",
            "type": "string"
          },
          "method": {
            "const": "elicitation/create",
            "default": "elicitation/create",
            "description": "MCP method literal \u2014 always `\"elicitation/create\"` (the value of `_MCP_ELICITATION_METHOD` in `omnigent/runtime/policies/approval.py`).",
            "title": "Method",
            "type": "string"
          },
          "params": {
            "$ref": "#/components/schemas/ElicitationRequestParams",
            "description": "The MCP-shaped params block carrying the prompt and (form-mode only) the requested schema."
          },
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "type": {
            "const": "response.elicitation_request",
            "description": "Always `\"response.elicitation_request\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "elicitation_id",
          "params"
        ],
        "title": "ElicitationRequestEvent",
        "type": "object"
      },
      "ElicitationRequestParams": {
        "additionalProperties": true,
        "description": "Inner `params` block of a `ElicitationRequestEvent`.\n\nThe standard fields (`mode`, `message`, `requestedSchema`,\n`url`) mirror MCP's `ElicitRequestFormParams` /\n`ElicitRequestUrlParams` byte-for-byte (Principle 8 \u2014 adopt\nMCP's wire shape verbatim where it overlaps). The\nAP-specific extensions (`phase`, `policy_name`,\n`content_preview`, `target_session_id`) carry policy-engine\ncontext and mirrored-child routing for the consumer's renderer;\nMCP's `extra=\"allow\"` config permits them under the same params\nblock. Wire shape matches\n`omnigent/runtime/policies/approval.py:175`.",
        "properties": {
          "content_preview": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Truncated preview of the underlying request payload (\u22641024 chars in current AP), for the consumer's renderer.",
            "title": "Content Preview"
          },
          "message": {
            "description": "Human-readable prompt the consumer renders, e.g. `\"Approve running 'rm -rf /tmp/cache'?\"`.",
            "title": "Message",
            "type": "string"
          },
          "mode": {
            "default": "form",
            "description": "MCP-standard discriminator. `\"form\"` collects structured input via `requestedSchema`; `\"url\"` directs upstream to an external URL for OAuth / out-of-band interaction.",
            "enum": [
              "form",
              "url"
            ],
            "title": "Mode",
            "type": "string"
          },
          "phase": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Omnigent policy-engine phase the elicitation belongs to, e.g. `\"pre_tool_use\"`.",
            "title": "Phase"
          },
          "policy_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Omnigent policy that triggered the elicitation, e.g. `\"approve_shell_commands\"`.",
            "title": "Policy Name"
          },
          "requestedSchema": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "JSON-Schema dict for form mode (or `None` for url mode). camelCase preserved per MCP spec, e.g. `{\"type\": \"object\", \"properties\": {\"approve\": {\"type\": \"boolean\"}}}`.",
            "title": "Requestedschema"
          },
          "target_session_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "AP session whose resolve endpoint owns this elicitation, e.g. `\"conv_child123\"`. Present when a child/sub-agent prompt is mirrored into an ancestor stream; `None` means resolve against the current session.",
            "title": "Target Session Id"
          },
          "url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "External URL for url mode (or `None` for form mode), e.g. `\"https://oauth.example.com/authorize?...\"`.",
            "title": "Url"
          }
        },
        "required": [
          "message"
        ],
        "title": "ElicitationRequestParams",
        "type": "object"
      },
      "ElicitationResolvedEvent": {
        "description": "Signal that a previously-published elicitation is no longer\noutstanding, even though no UI `approval` verdict was\ndelivered through `POST /v1/sessions/{id}/events`.\n\nEmitted by the runner when its own `_pending_approvals`\nFuture is popped without a verdict (the runner's wait timed\nout, the turn was cancelled, the harness exited) so the AP\nserver's `omnigent.runtime.pending_elicitations`\nindex can decrement the sidebar badge in lockstep with the\nunderlying awaiter's lifecycle. Without this signal, the AP\nserver has no way to learn that the prompt is dead and the\nbadge stays stuck.\n\nIdempotent on the consumer side: the Omnigent server's index\ndecrement is a no-op when the id isn't tracked, so the\nrunner can fire-and-forget on every Future cleanup.",
        "properties": {
          "action": {
            "anyOf": [
              {
                "enum": [
                  "accept",
                  "decline",
                  "cancel"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional MCP verdict recorded when the resolution carried a human decision (`\"accept\"` / `\"decline\"` / `\"cancel\"`). `None` for resolutions without a verdict \u2014 timeout, severed wait, or a runner that predates verdict carriage \u2014 so consumers can say \"no verdict was recorded\" rather than guessing one.",
            "title": "Action"
          },
          "elicitation_id": {
            "description": "Correlation id of the elicitation being cleared, e.g. `\"elicit_abc123\"`. Must match the id of a prior `ElicitationRequestEvent`.",
            "title": "Elicitation Id",
            "type": "string"
          },
          "reason": {
            "anyOf": [
              {
                "const": "unanswered",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Why a verdict-less resolution happened, when known. `\"unanswered\"`: the hook stopped waiting (a severed poll never re-parked, the ask timed out) before anyone answered, so the prompt is gone rather than decided and the UI can say so instead of implying it was resolved elsewhere. `None` when a verdict is present or the reason is unknown.",
            "title": "Reason"
          },
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "type": {
            "const": "response.elicitation_resolved",
            "description": "Always `\"response.elicitation_resolved\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "elicitation_id"
        ],
        "title": "ElicitationResolvedEvent",
        "type": "object"
      },
      "ErrorData": {
        "description": "Data for a persisted error banner item.\n\nThese items mirror `response.error` events so clients can render\nthe same error banner after reconnect / refresh. They are listed in\n`NON_CONTENT_ITEM_TYPES` because they are operator-visible\ntranscript metadata, not content the next agent turn should receive.",
        "properties": {
          "cause": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional one or two sentences explaining why it failed.",
            "title": "Cause"
          },
          "code": {
            "description": "Stable error classifier, e.g. `\"native_terminal_start_failed\"`.",
            "title": "Code",
            "type": "string"
          },
          "level": {
            "anyOf": [
              {
                "enum": [
                  "error",
                  "info"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Rendering level. `\"info\"` renders the banner as a neutral notice (e.g. codex started a fresh thread) rather than a failure; `None` / `\"error\"` is the destructive default and is omitted from the wire so existing error items are unchanged.",
            "title": "Level"
          },
          "message": {
            "description": "Human-readable error message, e.g. `\"Native Codex requires the 'codex' CLI on PATH.\"`.",
            "title": "Message",
            "type": "string"
          },
          "remediation": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional concrete next step, e.g. the sign-in link and code; the card offers it as an action.",
            "title": "Remediation"
          },
          "source": {
            "description": "Error source, e.g. `\"execution\"`.",
            "enum": [
              "llm",
              "execution",
              "tool",
              "harness"
            ],
            "title": "Source",
            "type": "string"
          },
          "title": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional short headline naming the failure, e.g. `\"Codex can't start until you sign in to Databricks\"`. Kept so the card reads the same after a reload as it did live.",
            "title": "Title"
          }
        },
        "required": [
          "source",
          "code",
          "message"
        ],
        "title": "ErrorData",
        "type": "object"
      },
      "ErrorDetail": {
        "description": "Machine-readable error information attached to a failed response.",
        "properties": {
          "cause": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional one/two-sentence explanation of why it failed. Paired with `title`.",
            "title": "Cause"
          },
          "code": {
            "description": "Error code string, e.g. `\"server_error\"`, `\"invalid_input\"`.",
            "title": "Code",
            "type": "string"
          },
          "message": {
            "description": "Human-readable error description. Always populated; older clients render this verbatim.",
            "title": "Message",
            "type": "string"
          },
          "remediation": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional concrete next step to fix it, e.g. a command to run. `None` when there is no single clear fix.",
            "title": "Remediation"
          },
          "title": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional short headline naming what went wrong, e.g. `\"Claude Code can't run as root\"`. Present when the runner recognized the failure (see `omnigent.runner.launch_failure`); lets the UI show a clear card title instead of the raw `code`.",
            "title": "Title"
          },
          "undelivered": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "description": "`True` when the harness reports it never received the message this turn carried (it failed before delivery), so the sender's queued copy is the only record of it; absent otherwise.",
            "title": "Undelivered"
          }
        },
        "required": [
          "code",
          "message"
        ],
        "title": "ErrorDetail",
        "type": "object"
      },
      "ErrorEvent": {
        "description": "Non-recoverable error reported during the turn.\n\nEmitted from multiple sites in\n`omnigent/runtime/workflow.py` \u2014 terminal LLM failures\n(`_emit_llm_error_event`), execution timeouts\n(`_handle_execution_timeout`), and the agent-loop catch-all\n(`except Exception`). Wire shape matches those emits.",
        "properties": {
          "error": {
            "$ref": "#/components/schemas/RetryErrorDetail",
            "description": "Classified error description."
          },
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "source": {
            "description": "Origin of the error -- `\"llm\"` for LLM-call failures, `\"execution\"` for timeouts, `\"tool\"` for tool failures, `\"harness\"` for harness process failures.",
            "enum": [
              "llm",
              "execution",
              "tool",
              "harness"
            ],
            "title": "Source",
            "type": "string"
          },
          "tool_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Tool identifier when `source == \"tool\"`; `None` for the other sources.",
            "title": "Tool Name"
          },
          "type": {
            "const": "response.error",
            "description": "Always `\"response.error\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "source",
          "error"
        ],
        "title": "ErrorEvent",
        "type": "object"
      },
      "ErrorResponse": {
        "description": "The body every failed request carries: a single `error` object.\n\nMirrors what the FastAPI exception handler emits for an\n`~omnigent.errors.OmnigentError`, so documented error responses\nand the runtime envelope stay the same shape.",
        "properties": {
          "error": {
            "$ref": "#/components/schemas/ErrorDetail",
            "description": "Machine-readable detail about the failure."
          }
        },
        "required": [
          "error"
        ],
        "title": "ErrorResponse",
        "type": "object"
      },
      "ExtensionAssetErrorResponse": {
        "description": "Concise diagnostic for one unresolved browser bundle.",
        "properties": {
          "error": {
            "title": "Error",
            "type": "string"
          },
          "extension_id": {
            "title": "Extension Id",
            "type": "string"
          },
          "status": {
            "const": "unresolved",
            "default": "unresolved",
            "title": "Status",
            "type": "string"
          }
        },
        "required": [
          "extension_id",
          "error"
        ],
        "title": "ExtensionAssetErrorResponse",
        "type": "object"
      },
      "ExtensionBrowserBundleResponse": {
        "description": "Opaque browser-bundle availability and content-addressed asset URLs.",
        "properties": {
          "declared": {
            "title": "Declared",
            "type": "boolean"
          },
          "digest": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Digest"
          },
          "has_styles": {
            "title": "Has Styles",
            "type": "boolean"
          },
          "script_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Script Url"
          },
          "style_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Style Url"
          }
        },
        "required": [
          "declared",
          "has_styles"
        ],
        "title": "ExtensionBrowserBundleResponse",
        "type": "object"
      },
      "ExtensionDiagnosticsResponse": {
        "description": "Administrator view of accepted and rejected extensions.",
        "properties": {
          "asset_errors": {
            "items": {
              "$ref": "#/components/schemas/ExtensionAssetErrorResponse"
            },
            "title": "Asset Errors",
            "type": "array"
          },
          "extensions": {
            "items": {
              "$ref": "#/components/schemas/ExtensionResponse"
            },
            "title": "Extensions",
            "type": "array"
          },
          "load_errors": {
            "items": {
              "$ref": "#/components/schemas/ExtensionLoadErrorResponse"
            },
            "title": "Load Errors",
            "type": "array"
          },
          "object": {
            "const": "extension_diagnostics",
            "default": "extension_diagnostics",
            "title": "Object",
            "type": "string"
          }
        },
        "required": [
          "extensions",
          "load_errors",
          "asset_errors"
        ],
        "title": "ExtensionDiagnosticsResponse",
        "type": "object"
      },
      "ExtensionListResponse": {
        "description": "Public catalog of accepted extensions.",
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/ExtensionResponse"
            },
            "title": "Data",
            "type": "array"
          },
          "object": {
            "const": "list",
            "default": "list",
            "title": "Object",
            "type": "string"
          }
        },
        "required": [
          "data"
        ],
        "title": "ExtensionListResponse",
        "type": "object"
      },
      "ExtensionLoadErrorResponse": {
        "description": "Concise diagnostic for one rejected entry point.",
        "properties": {
          "entry_point": {
            "title": "Entry Point",
            "type": "string"
          },
          "error": {
            "title": "Error",
            "type": "string"
          },
          "status": {
            "const": "rejected",
            "default": "rejected",
            "title": "Status",
            "type": "string"
          }
        },
        "required": [
          "entry_point",
          "error"
        ],
        "title": "ExtensionLoadErrorResponse",
        "type": "object"
      },
      "ExtensionPageResponse": {
        "description": "One namespaced page contribution.",
        "properties": {
          "id": {
            "title": "Id",
            "type": "string"
          },
          "route": {
            "title": "Route",
            "type": "string"
          },
          "title": {
            "title": "Title",
            "type": "string"
          },
          "view": {
            "title": "View",
            "type": "string"
          }
        },
        "required": [
          "id",
          "title",
          "route",
          "view"
        ],
        "title": "ExtensionPageResponse",
        "type": "object"
      },
      "ExtensionPrimaryNavigationResponse": {
        "description": "One primary-sidebar navigation contribution.",
        "properties": {
          "icon": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Icon"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "label": {
            "title": "Label",
            "type": "string"
          },
          "order": {
            "format": "int64",
            "title": "Order",
            "type": "integer"
          },
          "page": {
            "title": "Page",
            "type": "string"
          },
          "when": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "When"
          }
        },
        "required": [
          "id",
          "label",
          "page",
          "icon",
          "order",
          "when"
        ],
        "title": "ExtensionPrimaryNavigationResponse",
        "type": "object"
      },
      "ExtensionResponse": {
        "description": "Public metadata for one accepted extension.",
        "properties": {
          "browser": {
            "$ref": "#/components/schemas/ExtensionBrowserBundleResponse"
          },
          "display_name": {
            "title": "Display Name",
            "type": "string"
          },
          "distribution": {
            "title": "Distribution",
            "type": "string"
          },
          "extension_api": {
            "format": "int64",
            "title": "Extension Api",
            "type": "integer"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "object": {
            "const": "extension",
            "default": "extension",
            "title": "Object",
            "type": "string"
          },
          "pages": {
            "items": {
              "$ref": "#/components/schemas/ExtensionPageResponse"
            },
            "title": "Pages",
            "type": "array"
          },
          "permissions": {
            "items": {
              "type": "string"
            },
            "title": "Permissions",
            "type": "array"
          },
          "primary_navigation": {
            "items": {
              "$ref": "#/components/schemas/ExtensionPrimaryNavigationResponse"
            },
            "title": "Primary Navigation",
            "type": "array"
          },
          "status": {
            "enum": [
              "enabled",
              "unavailable"
            ],
            "title": "Status",
            "type": "string"
          },
          "version": {
            "title": "Version",
            "type": "string"
          }
        },
        "required": [
          "id",
          "display_name",
          "distribution",
          "version",
          "extension_api",
          "status",
          "permissions",
          "pages",
          "primary_navigation",
          "browser"
        ],
        "title": "ExtensionResponse",
        "type": "object"
      },
      "FailedEvent": {
        "description": "Terminal event for a turn that ended with an error.\n\nCarries a `omnigent.server.schemas.FailedResponseObject`\nwhose `error` field describes the failure. Response metadata may\nbe absent when the failure occurs before response allocation.",
        "properties": {
          "response": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ResponseObject"
              },
              {
                "$ref": "#/components/schemas/FailedResponseObject"
              }
            ],
            "description": "The failure response object with `status=\"failed\"` and `error` populated.",
            "title": "Response"
          },
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "source": {
            "default": "execution",
            "description": "Where the fault originated -- `\"llm\"` for inference/context errors, `\"harness\"` for Claude Code/harness process failures, `\"execution\"` for runner configuration or infrastructure failures.",
            "enum": [
              "llm",
              "execution",
              "tool",
              "harness"
            ],
            "title": "Source",
            "type": "string"
          },
          "type": {
            "const": "response.failed",
            "description": "Always `\"response.failed\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "response"
        ],
        "title": "FailedEvent",
        "type": "object"
      },
      "FailedResponseObject": {
        "description": "Response payload for failures raised before response allocation.\n\nTransport and setup failures can terminate a turn before the harness has\nassigned the metadata required by `ResponseObject`. The remaining\nfields mirror that model so fully allocated failures retain their complete\nwire representation.",
        "properties": {
          "background": {
            "default": false,
            "description": "Whether the response was created as a background task.",
            "title": "Background",
            "type": "boolean"
          },
          "completed_at": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Unix epoch timestamp of completion, or `None`.",
            "title": "Completed At"
          },
          "conversation": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ConversationRef"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Reference to the owning conversation, or `None`."
          },
          "created_at": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Unix epoch timestamp of creation, or `None` when the response failed before creation.",
            "title": "Created At"
          },
          "error": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ErrorDetail"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Error details describing the failure, or `None`."
          },
          "id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Unique response identifier, e.g. `\"resp_abc123\"`, or `None` when allocation did not complete.",
            "title": "Id"
          },
          "incomplete_details": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/IncompleteDetails"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Incomplete-response details, or `None`."
          },
          "instructions": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Per-request instructions override, or `None`.",
            "title": "Instructions"
          },
          "model": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Agent name that produced the response, e.g. `\"research-agent\"`, or `None` when resolution did not complete.",
            "title": "Model"
          },
          "object": {
            "default": "response",
            "description": "Fixed resource type, always `\"response\"`.",
            "title": "Object",
            "type": "string"
          },
          "output": {
            "description": "Heterogeneous serialized output items accumulated before failure.",
            "items": {
              "additionalProperties": true,
              "type": "object"
            },
            "title": "Output",
            "type": "array"
          },
          "previous_response_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "ID of the prior response, or `None`.",
            "title": "Previous Response Id"
          },
          "reasoning": {
            "anyOf": [
              {
                "additionalProperties": {
                  "type": "string"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Reasoning configuration, or `None`.",
            "title": "Reasoning"
          },
          "status": {
            "description": "Lifecycle status, normally `\"failed\"`.",
            "title": "Status",
            "type": "string"
          },
          "store": {
            "default": true,
            "description": "Whether the response is persisted.",
            "title": "Store",
            "type": "boolean"
          },
          "usage": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Usage"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Token usage statistics, or `None` when unavailable."
          }
        },
        "required": [
          "status"
        ],
        "title": "FailedResponseObject",
        "type": "object"
      },
      "FunctionCallData": {
        "description": "Data for a function_call item.\n\n**Parameters**\n\n- `agent` \u2014 Agent name. Serialized as `\"model\"` in JSON.",
        "properties": {
          "arguments": {
            "description": "JSON-encoded arguments string.",
            "title": "Arguments",
            "type": "string"
          },
          "call_id": {
            "description": "Unique call identifier from the LLM, e.g. `\"call_abc123\"`.",
            "title": "Call Id",
            "type": "string"
          },
          "model": {
            "title": "Model",
            "type": "string"
          },
          "name": {
            "description": "Tool function name, e.g. `\"search.web\"`.",
            "title": "Name",
            "type": "string"
          }
        },
        "required": [
          "model",
          "name",
          "arguments",
          "call_id"
        ],
        "title": "FunctionCallData",
        "type": "object"
      },
      "FunctionCallOutputData": {
        "description": "Data for a function_call_output item.",
        "properties": {
          "call_id": {
            "description": "The call_id this output corresponds to, e.g. `\"call_abc123\"`.",
            "title": "Call Id",
            "type": "string"
          },
          "output": {
            "description": "The tool's string result.",
            "title": "Output",
            "type": "string"
          },
          "subagent_return_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Native task id of an explicitly completed child.",
            "title": "Subagent Return Id"
          }
        },
        "required": [
          "call_id",
          "output"
        ],
        "title": "FunctionCallOutputData",
        "type": "object"
      },
      "GrantPermissionRequest": {
        "description": "Request body for `PUT /v1/sessions/{id}/permissions`.",
        "properties": {
          "level": {
            "description": "Numeric permission level: `1` = read, `2` = edit, `3` = manage.",
            "format": "int64",
            "maximum": 3.0,
            "minimum": 1.0,
            "title": "Level",
            "type": "integer"
          },
          "user_id": {
            "description": "The user to grant access to, e.g. `\"alice@example.com\"` or `\"__public__\"` for public read access.",
            "title": "User Id",
            "type": "string"
          }
        },
        "required": [
          "user_id",
          "level"
        ],
        "title": "GrantPermissionRequest",
        "type": "object"
      },
      "HTTPValidationError": {
        "properties": {
          "detail": {
            "items": {
              "$ref": "#/components/schemas/ValidationError"
            },
            "title": "Detail",
            "type": "array"
          }
        },
        "title": "HTTPValidationError",
        "type": "object"
      },
      "HarnessStartup": {
        "description": "The only launch metadata allowed across the host tunnel and HTTP API.",
        "properties": {
          "arg_count": {
            "format": "int64",
            "minimum": 0.0,
            "title": "Arg Count",
            "type": "integer"
          },
          "command": {
            "title": "Command",
            "type": "string"
          },
          "command_source": {
            "enum": [
              "env",
              "config",
              "default"
            ],
            "title": "Command Source",
            "type": "string"
          },
          "resolved_path": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Resolved Path"
          }
        },
        "required": [
          "command",
          "resolved_path",
          "command_source",
          "arg_count"
        ],
        "title": "HarnessStartup",
        "type": "object"
      },
      "HeartbeatEvent": {
        "description": "Keepalive event emitted on a fixed cadence during streaming.\n\nLets consumers detect stalled producers via missed-interval\ntiming. Cadence is set by `_HEARTBEAT_INTERVAL_S` in\n`omnigent/runtime/workflow.py` (15 seconds at the time of\nwriting). Wire shape matches the existing emit at\n`omnigent/runtime/workflow.py:4636-4639`.\n\nPer `designs/SERVER_HARNESS_CONTRACT.md` \u00a7Heartbeats, the\nevent MAY carry timing metadata so consumers can do richer\ndead-detection than \"did anything arrive\":\n\n- `server_time` is the producer's wall-clock at emission,\n  letting consumers detect clock drift between producer and\n  consumer.\n- `last_event_seq` is the `sequence_number` of the most\n  recent NON-heartbeat event (or `None` when this is the\n  first heartbeat before any user-visible event), letting\n  consumers detect dropped events on reconnect.\n\nBoth fields are optional on the wire (`None` round-trips as\nomitted) so older AP\u2192harness pairs that pre-date the field\naddition still parse cleanly.",
        "properties": {
          "last_event_seq": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Sequence number of the last non- heartbeat event seen on the same stream, e.g. `42`. `None` before any user-visible event has fired (first heartbeat of the turn, before deltas land), or when the producer chose not to populate it.",
            "title": "Last Event Seq"
          },
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "server_time": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "ISO 8601 UTC timestamp at emission, e.g. `\"2026-04-27T15:30:00Z\"`. `None` when the producer chose not to populate it (legacy emitters).",
            "title": "Server Time"
          },
          "type": {
            "const": "response.heartbeat",
            "description": "Always `\"response.heartbeat\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type"
        ],
        "title": "HeartbeatEvent",
        "type": "object"
      },
      "HostModelOptionsResponse": {
        "description": "Pre-launch model choices resolved by a host harness.\n\n`error` carries the host's reason for an empty catalog \u2014 a probe that\nfailed on the host is not a transport failure, so the request still\nsucceeds and the picker can say WHY it is empty instead of a generic\n\"Models unavailable\".",
        "properties": {
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error"
          },
          "models": {
            "items": {
              "additionalProperties": true,
              "type": "object"
            },
            "title": "Models",
            "type": "array"
          },
          "routable_models": {
            "items": {
              "type": "string"
            },
            "title": "Routable Models",
            "type": "array"
          }
        },
        "required": [
          "models",
          "routable_models"
        ],
        "title": "HostModelOptionsResponse",
        "type": "object"
      },
      "ImportFailureRef": {
        "description": "One session that could not be imported, with a user-facing reason.\n\n`external_session_id` / `source` name the source session when known (a\nhost that reports only a count leaves them `None`); `reason` explains the\nfailure so the UI can show it instead of an anonymous \"N failed\". Also the\nshape of each `{\"event\": \"failed\", ...}` line on the stream endpoint.",
        "properties": {
          "external_session_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "External Session Id"
          },
          "reason": {
            "title": "Reason",
            "type": "string"
          },
          "source": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Source"
          }
        },
        "required": [
          "reason"
        ],
        "title": "ImportFailureRef",
        "type": "object"
      },
      "ImportItemInput": {
        "description": "One normalized existing Omnigent item received from the CLI.",
        "properties": {
          "data": {
            "additionalProperties": true,
            "title": "Data",
            "type": "object"
          },
          "response_id": {
            "maxLength": 64,
            "minLength": 1,
            "title": "Response Id",
            "type": "string"
          },
          "type": {
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "response_id",
          "data"
        ],
        "title": "ImportItemInput",
        "type": "object"
      },
      "ImportSessionRequest": {
        "description": "Request body for importing one local harness session.\n\n`project_id` files the imported session into a first-class project the\ncaller owns, with the same ownership, default-fill, and mismatch-warning\nsemantics as `POST /v1/sessions`.",
        "properties": {
          "external_session_id": {
            "maxLength": 128,
            "minLength": 1,
            "title": "External Session Id",
            "type": "string"
          },
          "force": {
            "default": false,
            "title": "Force",
            "type": "boolean"
          },
          "host_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Host Id"
          },
          "items": {
            "items": {
              "$ref": "#/components/schemas/ImportItemInput"
            },
            "maxItems": 100000,
            "minItems": 1,
            "title": "Items",
            "type": "array"
          },
          "project_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Project Id"
          },
          "source": {
            "enum": [
              "claude",
              "codex",
              "kimi",
              "kiro",
              "opencode",
              "pi",
              "qwen"
            ],
            "title": "Source",
            "type": "string"
          },
          "title": {
            "anyOf": [
              {
                "maxLength": 512,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Title"
          },
          "workspace": {
            "anyOf": [
              {
                "maxLength": 2048,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Workspace"
          }
        },
        "required": [
          "source",
          "external_session_id",
          "items"
        ],
        "title": "ImportSessionRequest",
        "type": "object"
      },
      "ImportSessionResponse": {
        "description": "Result of importing or locating one source session.",
        "properties": {
          "item_count": {
            "format": "int64",
            "title": "Item Count",
            "type": "integer"
          },
          "session_id": {
            "title": "Session Id",
            "type": "string"
          },
          "status": {
            "const": "imported",
            "title": "Status",
            "type": "string"
          }
        },
        "required": [
          "session_id",
          "status",
          "item_count"
        ],
        "title": "ImportSessionResponse",
        "type": "object"
      },
      "ImportedSessionRef": {
        "description": "One freshly imported session: its new id plus display title.\n\n`title` is `None` when the session has no native title and no first user\nmessage to synthesize from; the UI falls back to a placeholder. Also the\nshape of each `{\"event\": \"session\", ...}` line the\n`/imports/local/stream` endpoint emits.",
        "properties": {
          "session_id": {
            "title": "Session Id",
            "type": "string"
          },
          "title": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Title"
          }
        },
        "required": [
          "session_id"
        ],
        "title": "ImportedSessionRef",
        "type": "object"
      },
      "InProgressEvent": {
        "description": "Event emitted once the task transitions to in-progress.\n\nAlways follows `response.created` (and `response.queued`\nfor background tasks).",
        "properties": {
          "response": {
            "$ref": "#/components/schemas/ResponseObject",
            "description": "The response object with `status=\"in_progress\"`."
          },
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "type": {
            "const": "response.in_progress",
            "description": "Always `\"response.in_progress\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "response"
        ],
        "title": "InProgressEvent",
        "type": "object"
      },
      "IncompleteDetails": {
        "description": "Details explaining why a response is incomplete.",
        "properties": {
          "reason": {
            "description": "Reason the response stopped early, e.g. `\"max_output_tokens\"`, `\"max_tool_calls\"`.",
            "title": "Reason",
            "type": "string"
          }
        },
        "required": [
          "reason"
        ],
        "title": "IncompleteDetails",
        "type": "object"
      },
      "IncompleteEvent": {
        "description": "Terminal event for a turn that ended without completing\n(e.g. hit the iteration cap or token budget).",
        "properties": {
          "response": {
            "$ref": "#/components/schemas/ResponseObject",
            "description": "The final response object with `status=\"incomplete\"` and `incomplete_details` populated describing the reason."
          },
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "type": {
            "const": "response.incomplete",
            "description": "Always `\"response.incomplete\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "response"
        ],
        "title": "IncompleteEvent",
        "type": "object"
      },
      "LaunchRunnerRequest": {
        "description": "Request body for `POST /v1/hosts/{host_id}/runners`.",
        "properties": {
          "git": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SessionGitOptions"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional git worktree options. In create mode the server creates a worktree for a new branch off `workspace` on the host and binds the runner to it (the fork-resume path; mirrors `POST /v1/sessions`). In bind mode (`existing_worktree=True`) `workspace` already IS a worktree \u2014 no worktree is created; `branch_name` is recorded as the session's `git_branch` for display and opt-in cleanup. `None` binds `workspace` directly. `host_id` is always present (it is in the path), so no host check is needed here."
          },
          "session_id": {
            "description": "Session to bind the new runner to, e.g. `\"conv_abc123\"`.",
            "title": "Session Id",
            "type": "string"
          },
          "workspace": {
            "description": "Absolute path on the host machine to use as the runner's working directory, e.g. `\"/Users/corey/projects/frontend\"`. When `git` is set, this is interpreted as the source repository directory and the runner starts in the created worktree instead.",
            "title": "Workspace",
            "type": "string"
          }
        },
        "required": [
          "session_id",
          "workspace"
        ],
        "title": "LaunchRunnerRequest",
        "type": "object"
      },
      "LocalImportRequest": {
        "description": "Request to import local harness sessions from a host.\n\nUnlike `/imports` (the CLI posts already-normalized items), the server\nasks the chosen host to read + normalize its own transcripts over the\ntunnel \u2014 the transcripts live on the caller's machine, not the server. A\nsupplied `session_id` loads that exact session without enumerating local\nhistory.",
        "properties": {
          "host_id": {
            "title": "Host Id",
            "type": "string"
          },
          "limit": {
            "default": 10,
            "format": "int64",
            "maximum": 100.0,
            "minimum": 1.0,
            "title": "Limit",
            "type": "integer"
          },
          "session_id": {
            "anyOf": [
              {
                "maxLength": 128,
                "minLength": 1,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Session Id"
          },
          "source": {
            "anyOf": [
              {
                "enum": [
                  "claude",
                  "codex",
                  "kimi",
                  "kiro",
                  "opencode",
                  "pi",
                  "qwen"
                ],
                "type": "string"
              },
              {
                "const": "all",
                "type": "string"
              }
            ],
            "title": "Source"
          }
        },
        "required": [
          "host_id",
          "source"
        ],
        "title": "LocalImportRequest",
        "type": "object"
      },
      "LocalImportResponse": {
        "description": "Buffered batch result for `POST /v1/imports/local`.\n\nThe streaming `/imports/local/stream` endpoint carries the same tally on\nits terminal `{\"event\": \"done\", ...}` line instead.",
        "properties": {
          "already_imported": {
            "format": "int64",
            "title": "Already Imported",
            "type": "integer"
          },
          "failed": {
            "format": "int64",
            "title": "Failed",
            "type": "integer"
          },
          "failures": {
            "items": {
              "$ref": "#/components/schemas/ImportFailureRef"
            },
            "title": "Failures",
            "type": "array"
          },
          "imported": {
            "format": "int64",
            "title": "Imported",
            "type": "integer"
          },
          "sessions": {
            "items": {
              "$ref": "#/components/schemas/ImportedSessionRef"
            },
            "title": "Sessions",
            "type": "array"
          }
        },
        "required": [
          "imported",
          "already_imported",
          "failed",
          "sessions"
        ],
        "title": "LocalImportResponse",
        "type": "object"
      },
      "MCPServerSummary": {
        "description": "Safe subset of an MCP server's configuration for API exposure.\n\nHeader values are redacted (`\"[REDACTED]\"`) so callers can see\nwhich headers are configured without leaking the actual secrets.\n`env` is still fully excluded.",
        "properties": {
          "args": {
            "description": "Command-line arguments for `transport=\"stdio\"` servers, e.g. `[\"mcp-server-github\"]`. Empty list when unset.",
            "items": {
              "type": "string"
            },
            "title": "Args",
            "type": "array"
          },
          "command": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Executable path for `transport=\"stdio\"` servers, e.g. `\"uvx\"`. `None` for http servers.",
            "title": "Command"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional free-text description from the spec, e.g. `\"GitHub MCP server\"`. `None` when unset.",
            "title": "Description"
          },
          "headers": {
            "additionalProperties": {
              "type": "string"
            },
            "description": "HTTP headers for `transport=\"http\"` servers. Values are always `\"[REDACTED]\"`; only the key names are exposed.",
            "title": "Headers",
            "type": "object"
          },
          "name": {
            "description": "Server name as declared in the agent spec, e.g. `\"github\"`.",
            "title": "Name",
            "type": "string"
          },
          "transport": {
            "description": "Transport type \u2014 `\"stdio\"` or `\"http\"`.",
            "title": "Transport",
            "type": "string"
          },
          "url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "HTTP(S) endpoint URL for `transport=\"http\"` servers, e.g. `\"https://mcp.example.com/sse\"`. `None` for stdio servers.",
            "title": "Url"
          }
        },
        "required": [
          "name",
          "transport"
        ],
        "title": "MCPServerSummary",
        "type": "object"
      },
      "McpServerStartup": {
        "description": "One MCP server's startup state within a `session.mcp_startup` event.",
        "properties": {
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Failure detail when `status == \"failed\"`, e.g. `\"handshaking with MCP server failed\"`. `None` otherwise.",
            "title": "Error"
          },
          "status": {
            "description": "Latest startup state reported by the harness, mirroring Codex's `McpServerStartupState` enum.",
            "enum": [
              "starting",
              "ready",
              "failed",
              "cancelled"
            ],
            "title": "Status",
            "type": "string"
          }
        },
        "required": [
          "status"
        ],
        "title": "McpServerStartup",
        "type": "object"
      },
      "McpServerSummary": {
        "description": "An MCP server a harness loads on the host, without secrets.",
        "properties": {
          "harness": {
            "description": "Harness family that loads it: `claude`, `codex`, or `cursor`.",
            "title": "Harness",
            "type": "string"
          },
          "name": {
            "description": "Server name as configured, e.g. `\"github\"`.",
            "title": "Name",
            "type": "string"
          },
          "plugin": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Plugin that bundles the server, e.g. `\"figma\"`.",
            "title": "Plugin"
          },
          "scope": {
            "const": "user",
            "description": "Config scope; always `user` today.",
            "title": "Scope",
            "type": "string"
          },
          "source_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Source Id"
          },
          "transport": {
            "description": "`stdio` for a local process, `http` for a remote server.",
            "enum": [
              "stdio",
              "http"
            ],
            "title": "Transport",
            "type": "string"
          },
          "url_host": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Hostname of a remote server, e.g. `\"mcp.linear.app\"`.",
            "title": "Url Host"
          }
        },
        "required": [
          "name",
          "harness",
          "transport",
          "scope"
        ],
        "title": "McpServerSummary",
        "type": "object"
      },
      "McpServersResponse": {
        "description": "User-level MCP servers discovered on a host.",
        "properties": {
          "mcp_servers": {
            "items": {
              "$ref": "#/components/schemas/McpServerSummary"
            },
            "title": "Mcp Servers",
            "type": "array"
          }
        },
        "required": [
          "mcp_servers"
        ],
        "title": "McpServersResponse",
        "type": "object"
      },
      "McpToolSummary": {
        "properties": {
          "description": {
            "anyOf": [
              {
                "maxLength": 300,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "name": {
            "maxLength": 256,
            "title": "Name",
            "type": "string"
          }
        },
        "required": [
          "name"
        ],
        "title": "McpToolSummary",
        "type": "object"
      },
      "McpToolsRequest": {
        "properties": {
          "harness": {
            "enum": [
              "claude",
              "codex",
              "cursor"
            ],
            "title": "Harness",
            "type": "string"
          },
          "plugin": {
            "anyOf": [
              {
                "maxLength": 1024,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Plugin"
          },
          "server": {
            "maxLength": 1024,
            "minLength": 1,
            "title": "Server",
            "type": "string"
          },
          "source_id": {
            "anyOf": [
              {
                "pattern": "^[0-9a-f]{64}$",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Source Id"
          }
        },
        "required": [
          "harness",
          "server"
        ],
        "title": "McpToolsRequest",
        "type": "object"
      },
      "McpToolsResponse": {
        "properties": {
          "connection": {
            "enum": [
              "connected",
              "needs_auth",
              "unreachable",
              "timeout",
              "unsupported"
            ],
            "title": "Connection",
            "type": "string"
          },
          "tools": {
            "items": {
              "$ref": "#/components/schemas/McpToolSummary"
            },
            "maxItems": 500,
            "title": "Tools",
            "type": "array"
          },
          "truncated": {
            "title": "Truncated",
            "type": "boolean"
          }
        },
        "required": [
          "tools",
          "connection",
          "truncated"
        ],
        "title": "McpToolsResponse",
        "type": "object"
      },
      "MessageData": {
        "description": "Data for a message item (user or assistant).\n\n**Parameters**\n\n- `agent` \u2014 Agent name (required for assistant messages, absent for user). Serialized as `\"model\"` in JSON.",
        "properties": {
          "content": {
            "description": "Heterogeneous content blocks, e.g. `[{\"type\": \"input_text\", \"text\": \"Hello\"}]`.",
            "items": {
              "additionalProperties": true,
              "type": "object"
            },
            "title": "Content",
            "type": "array"
          },
          "interrupted": {
            "default": false,
            "description": "`True` when an assistant message is a durable partial response from an interrupted external-native turn, e.g. Codex `turn/completed` with status `\"interrupted\"`. Defaults to `False` and is omitted from serialized payloads in that case.",
            "title": "Interrupted",
            "type": "boolean"
          },
          "is_meta": {
            "default": false,
            "description": "`True` for durable context that must be replayed to agents but hidden from user-facing transcripts, e.g. injected skill instructions. Defaults to `False` and is omitted from serialized payloads in that case.",
            "title": "Is Meta",
            "type": "boolean"
          },
          "model": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Model"
          },
          "role": {
            "description": "`\"user\"` or `\"assistant\"`.",
            "enum": [
              "user",
              "assistant"
            ],
            "title": "Role",
            "type": "string"
          },
          "stream_message_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Native live-preview stream finalized by this assistant message. Persisted so reconnect snapshots can suppress delayed preview chunks after the authoritative item.",
            "title": "Stream Message Id"
          },
          "subagent_return_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Native task id of an explicitly completed child.",
            "title": "Subagent Return Id"
          },
          "user_authored": {
            "default": false,
            "description": "Confirmed or conservatively preserved user input; prevents legacy content cleanup from hiding literal agent markup.",
            "title": "User Authored",
            "type": "boolean"
          }
        },
        "required": [
          "role",
          "content"
        ],
        "title": "MessageData",
        "type": "object"
      },
      "ModelUsage": {
        "description": "Cumulative token/cost usage attributed to a single LLM model.\n\nOne value in the `usage_by_model` map on `SessionResponse` /\n`SessionUsageEvent`, keyed by the raw harness-reported model id\n(e.g. `\"claude-sonnet-4-6\"`, `\"databricks-gpt-5-5\"`). Counts are\nsummed over the session's subtree (itself + sub-agent descendants), so a\nparent folds in sub-agents that ran a different model. Token buckets\nmirror the flat per-session breakdown.",
        "properties": {
          "cache_creation_input_tokens": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "Cumulative tokens written to the prompt cache, e.g. `2000`. `None` when not recorded.",
            "title": "Cache Creation Input Tokens"
          },
          "cache_read_input_tokens": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "Cumulative tokens read from the prompt cache, e.g. `8000`. `None` when not recorded.",
            "title": "Cache Read Input Tokens"
          },
          "input_tokens": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "Cumulative non-cached input (prompt) tokens for this model over the subtree, e.g. `12000`. `None` when not recorded.",
            "title": "Input Tokens"
          },
          "output_tokens": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "Cumulative output (completion) tokens, e.g. `3400`. `None` when not recorded.",
            "title": "Output Tokens"
          },
          "total_cost_usd": {
            "anyOf": [
              {
                "format": "double",
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Cumulative USD spend attributed to this model, e.g. `0.42`. Present **only when this model's turns were priced** (same \"priced \u27fa key present\" contract as the session total); `None` when the model is unpriced, so the sum of priced per-model costs equals the session `total_cost_usd`.",
            "title": "Total Cost Usd"
          },
          "total_tokens": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "Cumulative total tokens (counts cache buckets too, as the harness reports), e.g. `15400`. `None` when not recorded.",
            "title": "Total Tokens"
          }
        },
        "title": "ModelUsage",
        "type": "object"
      },
      "NativeModelOption": {
        "additionalProperties": true,
        "description": "One runner-owned native model-picker row.",
        "properties": {
          "defaultReasoningEffort": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Defaultreasoningeffort"
          },
          "displayName": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Displayname"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "isDefault": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Isdefault"
          },
          "model": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Model"
          },
          "supportedReasoningEfforts": {
            "items": {
              "$ref": "#/components/schemas/NativeReasoningEffortOption"
            },
            "title": "Supportedreasoningefforts",
            "type": "array"
          }
        },
        "required": [
          "id"
        ],
        "title": "NativeModelOption",
        "type": "object"
      },
      "NativeReasoningEffortOption": {
        "additionalProperties": true,
        "description": "Reasoning-effort metadata advertised by a native model catalog.",
        "properties": {
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "reasoningEffort": {
            "title": "Reasoningeffort",
            "type": "string"
          }
        },
        "required": [
          "reasoningEffort"
        ],
        "title": "NativeReasoningEffortOption",
        "type": "object"
      },
      "NativeToolData": {
        "description": "A provider-native tool output item (e.g. `web_search_call`).\n\nThese are executed server-side by the LLM provider and returned\nas opaque dicts. Agent-plane persists and replays them so the\nLLM sees its own tool results on subsequent iterations.",
        "properties": {
          "item": {
            "additionalProperties": true,
            "description": "The raw dict from the Responses API output, e.g. `{\"type\": \"web_search_call\", \"id\": \"ws_abc\", \"status\": \"completed\", \"action\": {...}}`.",
            "title": "Item",
            "type": "object"
          }
        },
        "required": [
          "item"
        ],
        "title": "NativeToolData",
        "type": "object"
      },
      "OutputFileDoneEvent": {
        "description": "A streamed file output completed materializing.\n\nEmitted by `_emit_file_annotation_events` in\n`omnigent/runtime/workflow.py` once per file annotation in\nthe assistant's output. `filename` and `content_type` are\nonly populated when the originating annotation carried them.",
        "properties": {
          "content_type": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "MIME content type if the annotation supplied one, e.g. `\"application/pdf\"`. `None` otherwise.",
            "title": "Content Type"
          },
          "file_id": {
            "description": "Identifier of the materialized file, e.g. `\"file_abc123\"`.",
            "title": "File Id",
            "type": "string"
          },
          "filename": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Original filename if the annotation supplied one, e.g. `\"report.pdf\"`. `None` otherwise.",
            "title": "Filename"
          },
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "type": {
            "const": "response.output_file.done",
            "description": "Always `\"response.output_file.done\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "file_id"
        ],
        "title": "OutputFileDoneEvent",
        "type": "object"
      },
      "OutputItemDoneEvent": {
        "description": "A conversation output item completed during the turn.\n\nCarries any item type the conversation persists (message,\nfunction_call, function_call_output, reasoning, compaction,\nnative_tool, \u2026). The `item` payload's wire shape merges\ncommon fields (`id`, `type`, `status`) with the\ntype-specific data fields \u2014 it is NOT nested as\n`{type, data}`.",
        "properties": {
          "item": {
            "additionalProperties": true,
            "description": "The completed item dict. Heterogeneous and item-type-specific; see `omnigent/entities/conversation.py` for the per-type `*Data` shapes that drive serialization. Example for a function_call item: `{\"id\": \"fc_abc123\", \"type\": \"function_call\", \"status\": \"action_required\", \"name\": \"search.web\", \"arguments\": \"{\\\"q\\\": \\\"foo\\\"}\", \"call_id\": \"call_xyz\"}`.",
            "title": "Item",
            "type": "object"
          },
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "type": {
            "const": "response.output_item.done",
            "description": "Always `\"response.output_item.done\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "item"
        ],
        "title": "OutputItemDoneEvent",
        "type": "object"
      },
      "OutputTextDeltaEvent": {
        "description": "Incremental assistant-text token emitted during streaming.\n\nWire shape matches the existing raw-dict emit at\n`omnigent/runtime/workflow.py:1352-1356`.",
        "properties": {
          "delta": {
            "description": "The text fragment for this chunk, e.g. `\"Hello\"`.",
            "title": "Delta",
            "type": "string"
          },
          "final": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional provider completion marker for the message.",
            "title": "Final"
          },
          "index": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "0-based chunk order within the message, e.g. `3`. Used to suppress repeated chunks; `None` for in-process streaming.",
            "title": "Index"
          },
          "message_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "For native terminal streaming, the provider's stable per-message id, e.g. `\"2ca51d97-2f0f-493a-aed7-85a5b56c5747\"`. `None` for ordinary in-process task streaming, where deltas group by the active response.",
            "title": "Message Id"
          },
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "type": {
            "const": "response.output_text.delta",
            "description": "Always `\"response.output_text.delta\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "delta"
        ],
        "title": "OutputTextDeltaEvent",
        "type": "object"
      },
      "PaginatedList": {
        "description": "A paginated list response following cursor-based pagination.",
        "properties": {
          "data": {
            "description": "Page of results. Items are heterogeneous (`ResponseObject`, `ConversationObject`, `FileObject`, or dicts) and list is invariant, so no single concrete type satisfies all callers.",
            "items": {},
            "title": "Data",
            "type": "array"
          },
          "first_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "ID of the first item in the page, or `None` if the page is empty, e.g. `\"resp_abc123\"`.",
            "title": "First Id"
          },
          "has_more": {
            "default": false,
            "description": "Whether more items exist beyond this page.",
            "title": "Has More",
            "type": "boolean"
          },
          "last_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "ID of the last item in the page, or `None` if the page is empty, e.g. `\"resp_xyz789\"`.",
            "title": "Last Id"
          },
          "object": {
            "default": "list",
            "description": "Fixed resource type, always `\"list\"`.",
            "title": "Object",
            "type": "string"
          }
        },
        "title": "PaginatedList",
        "type": "object"
      },
      "PermissionObject": {
        "description": "API representation of a session permission grant.",
        "properties": {
          "conversation_id": {
            "description": "The session, e.g. `\"conv_abc123\"`.",
            "title": "Conversation Id",
            "type": "string"
          },
          "level": {
            "description": "Numeric permission level (1=read, 2=edit, 3=manage).",
            "format": "int64",
            "title": "Level",
            "type": "integer"
          },
          "user_id": {
            "description": "The grantee, e.g. `\"alice@example.com\"`.",
            "title": "User Id",
            "type": "string"
          }
        },
        "required": [
          "user_id",
          "conversation_id",
          "level"
        ],
        "title": "PermissionObject",
        "type": "object"
      },
      "PluginAsset": {
        "properties": {
          "id": {
            "pattern": "^[0-9a-f]{64}$",
            "title": "Id",
            "type": "string"
          },
          "name": {
            "maxLength": 256,
            "title": "Name",
            "type": "string"
          }
        },
        "required": [
          "id",
          "name"
        ],
        "title": "PluginAsset",
        "type": "object"
      },
      "PluginSummary": {
        "description": "Installed Claude plugin metadata, without paths or executable configuration.",
        "properties": {
          "description": {
            "anyOf": [
              {
                "maxLength": 1000,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "enabled": {
            "title": "Enabled",
            "type": "boolean"
          },
          "harness": {
            "const": "claude",
            "title": "Harness",
            "type": "string"
          },
          "has_commands": {
            "title": "Has Commands",
            "type": "boolean"
          },
          "has_hooks": {
            "title": "Has Hooks",
            "type": "boolean"
          },
          "id": {
            "anyOf": [
              {
                "pattern": "^[0-9a-f]{64}$",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Id"
          },
          "marketplace": {
            "maxLength": 256,
            "title": "Marketplace",
            "type": "string"
          },
          "mcp_entries": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/PluginAsset"
                },
                "maxItems": 128,
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Mcp Entries"
          },
          "mcp_servers": {
            "items": {
              "maxLength": 256,
              "type": "string"
            },
            "maxItems": 128,
            "title": "Mcp Servers",
            "type": "array"
          },
          "name": {
            "maxLength": 256,
            "minLength": 1,
            "title": "Name",
            "type": "string"
          },
          "skill_entries": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/PluginAsset"
                },
                "maxItems": 128,
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Skill Entries"
          },
          "skills": {
            "items": {
              "maxLength": 256,
              "type": "string"
            },
            "maxItems": 128,
            "title": "Skills",
            "type": "array"
          },
          "version": {
            "anyOf": [
              {
                "maxLength": 256,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Version"
          }
        },
        "required": [
          "harness",
          "name",
          "marketplace",
          "enabled",
          "skills",
          "mcp_servers",
          "has_hooks",
          "has_commands"
        ],
        "title": "PluginSummary",
        "type": "object"
      },
      "PluginsResponse": {
        "description": "Installed plugins reported by the host (Claude only).",
        "properties": {
          "plugins": {
            "items": {
              "$ref": "#/components/schemas/PluginSummary"
            },
            "maxItems": 128,
            "title": "Plugins",
            "type": "array"
          }
        },
        "required": [
          "plugins"
        ],
        "title": "PluginsResponse",
        "type": "object"
      },
      "PolicyDeniedEvent": {
        "description": "Signal that a policy DENY was enforced on a native harness turn.\n\nA native harness (Claude Code, Codex, ...) routes each tool call and\nprompt through Omnigent's policy engine via the vendor command-hook\n(`POST /v1/sessions/{id}/policies/evaluate`). The DENY verdict is\nreturned synchronously to that hook, so unlike the SDK/wrap path there is\nno stream-visible signal that a native action was blocked \u2014 only the\n*effect* (the blocked tool never runs). This event surfaces the decision\nitself on the session stream so observers (the web UI, the capability\nbench) can see a native DENY as a positive signal rather than infer it\nfrom an absence.\n\nFire-and-forget and observational: it does not gate the turn (the hook\nresponse already did that) and carries no correlation id.",
        "properties": {
          "conversation_id": {
            "description": "Session/conversation id the DENY applies to, e.g. `\"conv_abc123\"`.",
            "title": "Conversation Id",
            "type": "string"
          },
          "phase": {
            "default": "",
            "description": "The policy phase the DENY landed on, e.g. `\"tool_call\"`.",
            "title": "Phase",
            "type": "string"
          },
          "reason": {
            "default": "",
            "description": "Human-readable deny reason from the deciding policy, e.g. `\"Blocked by policy.\"`.",
            "title": "Reason",
            "type": "string"
          },
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "type": {
            "const": "response.policy_denied",
            "description": "Always `\"response.policy_denied\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "conversation_id"
        ],
        "title": "PolicyDeniedEvent",
        "type": "object"
      },
      "PolicySummary": {
        "description": "Safe subset of a policy's spec for API exposure.\n\nExposes the policy name, type, and phases so the UI can\ndisplay which guardrails are active on an agent. The full\npolicy body (prompt text, callable path, label conditions)\nis intentionally excluded \u2014 this is a summary for display,\nnot a full spec.",
        "properties": {
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Short detail string about the policy implementation. For function policies: the callable dotted path. For prompt policies: the first line of the prompt. `None` when not available.",
            "title": "Description"
          },
          "name": {
            "description": "Policy name as declared in the agent spec, e.g. `\"block_long_sleep\"`.",
            "title": "Name",
            "type": "string"
          },
          "on": {
            "description": "List of phase selectors the policy fires on, e.g. `[\"tool_call\"]` or `[\"request\", \"response\"]`.",
            "items": {
              "type": "string"
            },
            "title": "On",
            "type": "array"
          },
          "type": {
            "description": "Policy type discriminator \u2014 `\"function\"` or `\"prompt\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "name",
          "type",
          "on"
        ],
        "title": "PolicySummary",
        "type": "object"
      },
      "PresenceViewer": {
        "description": "One user currently viewing a session (holding its SSE stream open).",
        "properties": {
          "idle": {
            "default": false,
            "description": "Whether every stream the user holds reports an idle (backgrounded) tab. The web greys idle viewers' avatars.",
            "title": "Idle",
            "type": "boolean"
          },
          "joined_at": {
            "description": "ISO 8601 UTC timestamp of when the user joined, e.g. `\"2026-06-10T17:00:00Z\"`. Stable across reconnects within the server's leave-grace window.",
            "title": "Joined At",
            "type": "string"
          },
          "user_id": {
            "description": "The viewer's authenticated identity, e.g. `\"alice@example.com\"`. Never the reserved single-user `\"local\"` sentinel \u2014 presence only tracks distinct human actors (see `attribution_user`).",
            "title": "User Id",
            "type": "string"
          }
        },
        "required": [
          "user_id",
          "joined_at"
        ],
        "title": "PresenceViewer",
        "type": "object"
      },
      "ProjectOrderRequest": {
        "description": "Rank owned project IDs; unranked projects append in discovery order.\n\nNull selects alphabetical mode without erasing the remembered manual IDs.\nThe serialized preference must fit in 65,535 bytes after compression and\nframing; lists below the 10,000-ID limit can still exceed this byte limit.",
        "properties": {
          "ordered_project_ids": {
            "anyOf": [
              {
                "items": {
                  "maxLength": 32,
                  "minLength": 32,
                  "pattern": "^[0-9a-f]{32}$",
                  "type": "string"
                },
                "maxItems": 10000,
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Ordered Project Ids"
          }
        },
        "required": [
          "ordered_project_ids"
        ],
        "title": "ProjectOrderRequest",
        "type": "object"
      },
      "ProjectOrderResponse": {
        "description": "Current sorting mode and the manual order retained in either mode.",
        "properties": {
          "ordered_project_ids": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Ordered Project Ids"
          },
          "sort_mode": {
            "enum": [
              "alphabetical",
              "manual"
            ],
            "title": "Sort Mode",
            "type": "string"
          }
        },
        "required": [
          "sort_mode",
          "ordered_project_ids"
        ],
        "title": "ProjectOrderResponse",
        "type": "object"
      },
      "QueuedEvent": {
        "description": "Optional event emitted between `created` and `in_progress`\nfor background tasks that are queued before they start.\n\nForeground streaming responses skip this event.",
        "properties": {
          "response": {
            "$ref": "#/components/schemas/ResponseObject",
            "description": "The response object with `status=\"queued\"`."
          },
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "type": {
            "const": "response.queued",
            "description": "Always `\"response.queued\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "response"
        ],
        "title": "QueuedEvent",
        "type": "object"
      },
      "ReadStatePutRequest": {
        "additionalProperties": false,
        "description": "Request body for `PUT /v1/sessions/{session_id}/read-state`.\n\nSets the *calling user's* read tracking for one session. Mirrors the\ntwo values the web client keeps per session: a \"last seen\" wall-clock\nbaseline (seconds since epoch) and an explicit \"marked unread\"\noverride. The unread dot shows when `updated_at > last_seen` and the\nsession is finished; `unread` separately pins the override so the\nthread the user is *viewing* (or a running one) still surfaces the dot\nwhere the automatic \"seen\" logic would otherwise suppress it.",
        "properties": {
          "last_seen": {
            "description": "Wall-clock baseline in seconds, e.g. `1717000000`. Marking seen sets this to \"now\"; marking unread pins it to `updated_at - 1` so the row reads unseen.",
            "format": "int64",
            "title": "Last Seen",
            "type": "integer"
          },
          "unread": {
            "description": "Whether this session is explicitly flagged unread for the caller.",
            "title": "Unread",
            "type": "boolean"
          }
        },
        "required": [
          "last_seen",
          "unread"
        ],
        "title": "ReadStatePutRequest",
        "type": "object"
      },
      "ReasoningData": {
        "description": "Data for a reasoning item.\n\n**Parameters**\n\n- `agent` \u2014 Agent name. Serialized as `\"model\"` in JSON.",
        "properties": {
          "content": {
            "anyOf": [
              {
                "items": {
                  "additionalProperties": {
                    "type": "string"
                  },
                  "type": "object"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Raw reasoning content blocks, or `None` if redacted.",
            "title": "Content"
          },
          "encrypted_content": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Encrypted reasoning content, or `None`.",
            "title": "Encrypted Content"
          },
          "model": {
            "title": "Model",
            "type": "string"
          },
          "summary": {
            "description": "Summary text blocks, e.g. `[{\"type\": \"summary_text\", \"text\": \"...\"}]`.",
            "items": {
              "additionalProperties": {
                "type": "string"
              },
              "type": "object"
            },
            "title": "Summary",
            "type": "array"
          }
        },
        "required": [
          "model",
          "summary"
        ],
        "title": "ReasoningData",
        "type": "object"
      },
      "ReasoningStartedEvent": {
        "description": "Marker emitted once when a reasoning block begins.\n\nFired even when the reasoning content itself is encrypted /\nredacted (so no delta events follow), letting clients render\na \"thinking\u2026\" indicator regardless of provider verification\nstatus. Wire shape matches `omnigent/runtime/workflow.py:1350`.",
        "properties": {
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "type": {
            "const": "response.reasoning.started",
            "description": "Always `\"response.reasoning.started\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type"
        ],
        "title": "ReasoningStartedEvent",
        "type": "object"
      },
      "ReasoningSummaryTextDeltaEvent": {
        "description": "Incremental reasoning-summary token.\n\nEmitted when `reasoning.summary` is configured on the\nrequest. Wire shape matches\n`omnigent/runtime/workflow.py:1370-1373`.",
        "properties": {
          "delta": {
            "description": "The summary text fragment, e.g. `\"Will use the search tool to gather context.\"`.",
            "title": "Delta",
            "type": "string"
          },
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "type": {
            "const": "response.reasoning_summary_text.delta",
            "description": "Always `\"response.reasoning_summary_text.delta\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "delta"
        ],
        "title": "ReasoningSummaryTextDeltaEvent",
        "type": "object"
      },
      "ReasoningTextDeltaEvent": {
        "description": "Incremental reasoning-text token (full chain-of-thought).\n\nOnly emitted by providers that surface reasoning content\n(e.g. OpenAI o-series with appropriate verification). Wire\nshape matches `omnigent/runtime/workflow.py:1358-1364`.",
        "properties": {
          "delta": {
            "description": "The reasoning text fragment, e.g. `\"Considering the user's intent...\"`.",
            "title": "Delta",
            "type": "string"
          },
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "type": {
            "const": "response.reasoning_text.delta",
            "description": "Always `\"response.reasoning_text.delta\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "delta"
        ],
        "title": "ReasoningTextDeltaEvent",
        "type": "object"
      },
      "ResetSessionModelOverrideRequest": {
        "additionalProperties": false,
        "description": "Reset a launch-time model selection only while that selection is current.",
        "properties": {
          "expected_model_override": {
            "minLength": 1,
            "title": "Expected Model Override",
            "type": "string"
          }
        },
        "required": [
          "expected_model_override"
        ],
        "title": "ResetSessionModelOverrideRequest",
        "type": "object"
      },
      "ResetSessionModelOverrideResponse": {
        "description": "Whether the launch-time selection was still current and was cleared.",
        "properties": {
          "reset": {
            "title": "Reset",
            "type": "boolean"
          }
        },
        "required": [
          "reset"
        ],
        "title": "ResetSessionModelOverrideResponse",
        "type": "object"
      },
      "ResourceEventData": {
        "description": "Data payload for a persisted resource lifecycle event.\n\nThese items are written to the conversation store when a\nsession resource is created or deleted, so reconnecting\nclients can discover resource history without replaying the\nlive SSE stream.  The agent loop filters them out of the\nLLM's message context (they are metadata, not conversation\ncontent).",
        "properties": {
          "event_type": {
            "description": "The SSE event type literal, e.g. `\"session.resource.created\"` or `\"session.resource.deleted\"`.",
            "title": "Event Type",
            "type": "string"
          },
          "resource": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Full resource object dict for `created` events. `None` for `deleted` events.",
            "title": "Resource"
          },
          "resource_id": {
            "description": "Opaque id of the affected resource, e.g. `\"terminal_bash_s1\"` or `\"file_abc123\"`.",
            "title": "Resource Id",
            "type": "string"
          },
          "resource_type": {
            "description": "Kind of resource, e.g. `\"terminal\"`, `\"file\"`, `\"environment\"`.",
            "title": "Resource Type",
            "type": "string"
          }
        },
        "required": [
          "event_type",
          "resource_id",
          "resource_type"
        ],
        "title": "ResourceEventData",
        "type": "object"
      },
      "ResponseObject": {
        "description": "API representation of a response (task execution result).",
        "properties": {
          "background": {
            "default": false,
            "description": "Whether this response was created as a background task.",
            "title": "Background",
            "type": "boolean"
          },
          "completed_at": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Unix epoch timestamp of completion, or `None` if not yet complete.",
            "title": "Completed At"
          },
          "conversation": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ConversationRef"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Reference to the owning conversation."
          },
          "created_at": {
            "description": "Unix epoch timestamp of creation.",
            "format": "int64",
            "title": "Created At",
            "type": "integer"
          },
          "error": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ErrorDetail"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Error details if the response failed."
          },
          "id": {
            "description": "Unique response identifier, e.g. `\"resp_abc123\"`.",
            "title": "Id",
            "type": "string"
          },
          "incomplete_details": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/IncompleteDetails"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Details if the response is incomplete (e.g. hit token limit)."
          },
          "instructions": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Per-request system instructions composed additively with the agent's own, or `None`.",
            "title": "Instructions"
          },
          "model": {
            "description": "Agent name that produced this response, e.g. `\"research-agent\"`.",
            "title": "Model",
            "type": "string"
          },
          "object": {
            "default": "response",
            "description": "Fixed resource type, always `\"response\"`.",
            "title": "Object",
            "type": "string"
          },
          "output": {
            "description": "Heterogeneous output items (messages, reasoning, function_calls) serialized as dicts; shape varies by item type. Empty for non-completed responses.",
            "items": {
              "additionalProperties": true,
              "type": "object"
            },
            "title": "Output",
            "type": "array"
          },
          "previous_response_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "ID of the prior response in the conversation thread, or `None` for the first turn.",
            "title": "Previous Response Id"
          },
          "reasoning": {
            "anyOf": [
              {
                "additionalProperties": {
                  "type": "string"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Reasoning configuration, e.g. `{\"effort\": \"medium\"}`.",
            "title": "Reasoning"
          },
          "status": {
            "description": "Lifecycle status, one of `\"queued\"`, `\"in_progress\"`, `\"completed\"`, `\"failed\"`, `\"incomplete\"`, `\"cancelled\"`.",
            "title": "Status",
            "type": "string"
          },
          "store": {
            "default": true,
            "description": "Whether this response is persisted. Always `True`.",
            "title": "Store",
            "type": "boolean"
          },
          "usage": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Usage"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Token usage statistics, or `None` if not yet available."
          }
        },
        "required": [
          "id",
          "status",
          "model",
          "created_at"
        ],
        "title": "ResponseObject",
        "type": "object"
      },
      "RetryErrorDetail": {
        "description": "Error block carried by `RetryEvent` and `ErrorEvent`.\n\nMirrors the shape that `llm_retry.py` and `tool_retry.py`\nemit today \u2014 flat `code` / `message` plus an optional\n`detail` for provider-specific structured fields.",
        "properties": {
          "code": {
            "description": "Stable error classifier, e.g. `\"timeout\"`, `\"rate_limit\"`.",
            "title": "Code",
            "type": "string"
          },
          "detail": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional provider-specific structured fields (e.g. `{\"status_code\": 429, \"retry_after\": 5}`); `None` when the classifier had no extra context.",
            "title": "Detail"
          },
          "message": {
            "description": "Human-readable summary, e.g. `\"Connection timed out after 30s\"`.",
            "title": "Message",
            "type": "string"
          }
        },
        "required": [
          "code",
          "message"
        ],
        "title": "RetryErrorDetail",
        "type": "object"
      },
      "RetryEvent": {
        "description": "A retryable failure was caught and a retry is scheduled.\n\nEmitted by `omnigent/runtime/llm_retry.py` (LLM calls)\nand `omnigent/runtime/tool_retry.py` (tool calls) before\nsleeping for the backoff delay. Wire shape matches\n`llm_retry.py:329-340` and `tool_retry.py:168-180`.",
        "properties": {
          "attempt": {
            "description": "1-based count of the upcoming attempt (i.e. attempt that will run AFTER this delay), e.g. `2` for the first retry.",
            "format": "int64",
            "title": "Attempt",
            "type": "integer"
          },
          "delay_seconds": {
            "description": "Seconds the producer will sleep before retrying, rounded to two decimals, e.g. `1.5`.",
            "format": "double",
            "title": "Delay Seconds",
            "type": "number"
          },
          "error": {
            "$ref": "#/components/schemas/RetryErrorDetail",
            "description": "Classified error description for the failure being retried."
          },
          "max_attempts": {
            "description": "Total tries allowed by the retry policy, e.g. `3`. Lets clients render \"attempt 2 of 3\".",
            "format": "int64",
            "title": "Max Attempts",
            "type": "integer"
          },
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "source": {
            "description": "Origin of the retried failure \u2014 `\"llm\"` for LLM-call retries, `\"tool\"` for tool-call retries.",
            "enum": [
              "llm",
              "tool"
            ],
            "title": "Source",
            "type": "string"
          },
          "tool_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Tool identifier when `source == \"tool\"`, e.g. `\"search.web\"`. `None` for LLM retries.",
            "title": "Tool Name"
          },
          "type": {
            "const": "response.retry",
            "description": "Always `\"response.retry\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "source",
          "attempt",
          "max_attempts",
          "delay_seconds",
          "error"
        ],
        "title": "RetryEvent",
        "type": "object"
      },
      "RoutingDecisionData": {
        "description": "Data payload for an intelligent model-router decision item.\n\nEmitted by the server-side smart routing path at the START of an\nadvised turn and persisted\nas a display-only transcript item so the model the router chose shows\nin the conversation flow the moment the turn begins. Listed in\n`NON_CONTENT_ITEM_TYPES` so the agent loop's history filter\nskips it \u2014 the brain never sees (or answers) its own router note. The\nrunner's harness-input builder also drops every non\nmessage/function_call type, a second guarantee it stays out of the\nmodel's context.",
        "properties": {
          "agent": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Agent"
          },
          "applied": {
            "description": "`True` when the brain actually ran on `model` this turn (optimize mode, no user pin); `False` when the router only WOULD have picked it (advise/shadow mode, or a user model pin won) \u2014 the UI renders \"would have picked\".",
            "title": "Applied",
            "type": "boolean"
          },
          "attempted_override": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Model the spawning agent asked for and the router overrode, e.g. `\"databricks-gpt-5-5\"` \u2014 an LLM-supplied `args.model` on a child session, or a native spawn's own `requested_model`. `None` when nothing was asked for, or when the router's pick names the same arm as the ask.",
            "title": "Attempted Override"
          },
          "decision_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Router decision identifier, e.g. `\"3f1c\u2026\"`. Correlates the transcript item with the routing telemetry event and the child-sessions API row. `None` for decisions made before decision ids existed.",
            "title": "Decision Id"
          },
          "harness": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Harness the decision applies to, e.g. `\"claude-native\"` or `\"codex\"`. `None` when the decision picked a model only (no harness dimension).",
            "title": "Harness"
          },
          "model": {
            "description": "The concrete brain model the router chose, e.g. `\"databricks-claude-opus-4-8\"`.",
            "title": "Model",
            "type": "string"
          },
          "rationale": {
            "description": "The router's one-line explanation, shown as muted secondary text, e.g. `\"Multi-file refactor needs deep reasoning.\"`.",
            "title": "Rationale",
            "type": "string"
          },
          "raw_model": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "The router-vocabulary pick before resolution to a servable catalog id, e.g. `\"gpt-5-6-sol\"`. `None` when the pick needed no resolution.",
            "title": "Raw Model"
          },
          "router_source": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Which router produced the decision \u2014 `\"databricks-aigw\"` for the external AI-Gateway `task_v1` service, `\"oss-llm\"` for the built-in judge. Deliberately a plain `str` rather than a `Literal`: a source added later must still round-trip through stored rows and the wire instead of failing validation. `None` on rows written before the field existed.",
            "title": "Router Source"
          },
          "scope": {
            "default": "turn",
            "description": "What the decision governs \u2014 `\"session\"` (auto-harness session routing), `\"turn\"` (per-turn routing), `\"child_session\"` (an Omnigent-spawned sub-agent) or `\"native_subagent\"` (a Task / `spawn_agent` spawn routed inside the harness). Defaults to `\"turn\"` so rows persisted before this field deserialize.",
            "enum": [
              "session",
              "turn",
              "child_session",
              "native_subagent"
            ],
            "title": "Scope",
            "type": "string"
          },
          "task_description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Human label of the task/spawn this decision governed, e.g. `\"Research auth flows\"` \u2014 what ties a fan-out's decision to its sub-agent when every spawn shares one `agent` type. `None` when the spawn carried none, and on rows written before the field existed.",
            "title": "Task Description"
          }
        },
        "required": [
          "model",
          "applied",
          "rationale"
        ],
        "title": "RoutingDecisionData",
        "type": "object"
      },
      "SandboxStatus": {
        "description": "Managed-sandbox launch progress for a `host_type=\"managed\"` session.\n\nCarried on the session snapshot only while the session's\nbackground sandbox launch is in flight or has failed; `None`\nfor sessions without a managed launch and once the launch\nsucceeds (the session then looks like any host-bound session).",
        "properties": {
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Failure detail when `stage == \"failed\"`, e.g. `\"managed sandbox launch failed: spend limit reached\"`. `None` otherwise.",
            "title": "Error"
          },
          "stage": {
            "description": "Current launch stage, e.g. `\"provisioning\"` \u2014 one of `SandboxLaunchStage`, in pipeline order: `provisioning` (creating the sandbox) \u2192 `cloning` (cloning the repository workspace; skipped when the session has none) \u2192 `starting` (starting the in-sandbox host) \u2192 `connecting` (launching the agent runner) \u2192 `ready` / `failed`.",
            "enum": [
              "provisioning",
              "cloning",
              "starting",
              "connecting",
              "ready",
              "failed"
            ],
            "title": "Stage",
            "type": "string"
          }
        },
        "required": [
          "stage"
        ],
        "title": "SandboxStatus",
        "type": "object"
      },
      "SendCommentsRequest": {
        "description": "Request body for `POST .../comments/send`.",
        "properties": {
          "comment_ids": {
            "description": "IDs of comments to send.",
            "items": {
              "type": "string"
            },
            "title": "Comment Ids",
            "type": "array"
          },
          "instruction": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional custom instruction prefix; defaults to the standard \"Please address the following file review comments.\" header.",
            "title": "Instruction"
          }
        },
        "required": [
          "comment_ids"
        ],
        "title": "SendCommentsRequest",
        "type": "object"
      },
      "ServerInfoResponse": {
        "properties": {
          "accounts_enabled": {
            "title": "Accounts Enabled",
            "type": "boolean"
          },
          "archive_worktree_cleanup": {
            "default": true,
            "title": "Archive Worktree Cleanup",
            "type": "boolean"
          },
          "branding": {
            "$ref": "#/components/schemas/BrandingInfo"
          },
          "databricks_features": {
            "title": "Databricks Features",
            "type": "boolean"
          },
          "dictation_available": {
            "title": "Dictation Available",
            "type": "boolean"
          },
          "enabled_connections": {
            "items": {
              "type": "string"
            },
            "title": "Enabled Connections",
            "type": "array"
          },
          "features": {
            "additionalProperties": {
              "type": "boolean"
            },
            "title": "Features",
            "type": "object"
          },
          "harness_install_enabled": {
            "title": "Harness Install Enabled",
            "type": "boolean"
          },
          "installable_harnesses": {
            "items": {
              "type": "string"
            },
            "title": "Installable Harnesses",
            "type": "array"
          },
          "login_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Login Url"
          },
          "managed_sandboxes_enabled": {
            "title": "Managed Sandboxes Enabled",
            "type": "boolean"
          },
          "needs_setup": {
            "title": "Needs Setup",
            "type": "boolean"
          },
          "public_sharing_enabled": {
            "title": "Public Sharing Enabled",
            "type": "boolean"
          },
          "sandbox_provider": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Sandbox Provider"
          },
          "sandbox_provider_capabilities": {
            "additionalProperties": {
              "additionalProperties": {
                "type": "boolean"
              },
              "type": "object"
            },
            "default": {},
            "title": "Sandbox Provider Capabilities",
            "type": "object"
          },
          "sandbox_providers": {
            "items": {
              "type": "string"
            },
            "title": "Sandbox Providers",
            "type": "array"
          },
          "server_version": {
            "title": "Server Version",
            "type": "string"
          },
          "sharing_mode": {
            "enum": [
              "on",
              "read_only",
              "restricted_read_only",
              "off"
            ],
            "title": "Sharing Mode",
            "type": "string"
          },
          "single_user": {
            "title": "Single User",
            "type": "boolean"
          },
          "smart_routing_enabled": {
            "title": "Smart Routing Enabled",
            "type": "boolean"
          },
          "smart_routing_sources": {
            "$ref": "#/components/schemas/SmartRoutingSourcesInfo"
          }
        },
        "required": [
          "accounts_enabled",
          "single_user",
          "login_url",
          "needs_setup",
          "databricks_features",
          "managed_sandboxes_enabled",
          "sandbox_provider",
          "sandbox_providers",
          "enabled_connections",
          "sharing_mode",
          "public_sharing_enabled",
          "server_version",
          "smart_routing_enabled",
          "smart_routing_sources",
          "features",
          "harness_install_enabled",
          "installable_harnesses",
          "dictation_available",
          "branding"
        ],
        "title": "ServerInfoResponse",
        "type": "object"
      },
      "ServerStreamEvent": {
        "discriminator": {
          "mapping": {
            "browser.action_request": "#/components/schemas/BrowserActionRequestEvent",
            "response.cancelled": "#/components/schemas/CancelledEvent",
            "response.client_task.cancel": "#/components/schemas/ClientTaskCancelEvent",
            "response.compaction.completed": "#/components/schemas/CompactionCompletedEvent",
            "response.compaction.failed": "#/components/schemas/CompactionFailedEvent",
            "response.compaction.in_progress": "#/components/schemas/CompactionInProgressEvent",
            "response.completed": "#/components/schemas/CompletedEvent",
            "response.created": "#/components/schemas/CreatedEvent",
            "response.elicitation_request": "#/components/schemas/ElicitationRequestEvent",
            "response.elicitation_resolved": "#/components/schemas/ElicitationResolvedEvent",
            "response.error": "#/components/schemas/ErrorEvent",
            "response.failed": "#/components/schemas/FailedEvent",
            "response.function_call_output.delta": "#/components/schemas/ToolOutputDeltaEvent",
            "response.heartbeat": "#/components/schemas/HeartbeatEvent",
            "response.in_progress": "#/components/schemas/InProgressEvent",
            "response.incomplete": "#/components/schemas/IncompleteEvent",
            "response.output_file.done": "#/components/schemas/OutputFileDoneEvent",
            "response.output_item.done": "#/components/schemas/OutputItemDoneEvent",
            "response.output_text.delta": "#/components/schemas/OutputTextDeltaEvent",
            "response.policy_denied": "#/components/schemas/PolicyDeniedEvent",
            "response.queued": "#/components/schemas/QueuedEvent",
            "response.reasoning.started": "#/components/schemas/ReasoningStartedEvent",
            "response.reasoning_summary_text.delta": "#/components/schemas/ReasoningSummaryTextDeltaEvent",
            "response.reasoning_text.delta": "#/components/schemas/ReasoningTextDeltaEvent",
            "response.retry": "#/components/schemas/RetryEvent",
            "session.agent_changed": "#/components/schemas/SessionAgentChangedEvent",
            "session.btw_sidechat": "#/components/schemas/SessionBtwSidechatEvent",
            "session.changed_files.invalidated": "#/components/schemas/SessionChangedFilesInvalidatedEvent",
            "session.child_session.updated": "#/components/schemas/SessionChildSessionUpdatedEvent",
            "session.codex_approval_mode": "#/components/schemas/SessionCodexApprovalModeEvent",
            "session.collaboration_mode": "#/components/schemas/SessionCollaborationModeEvent",
            "session.created": "#/components/schemas/SessionCreatedEvent",
            "session.heartbeat": "#/components/schemas/SessionHeartbeatEvent",
            "session.input.consumed": "#/components/schemas/SessionInputConsumedEvent",
            "session.interrupted": "#/components/schemas/SessionInterruptedEvent",
            "session.mcp_startup": "#/components/schemas/SessionMcpStartupEvent",
            "session.model": "#/components/schemas/SessionModelEvent",
            "session.model_options": "#/components/schemas/SessionModelOptionsEvent",
            "session.permission_mode": "#/components/schemas/SessionPermissionModeEvent",
            "session.presence": "#/components/schemas/SessionPresenceEvent",
            "session.reasoning_effort": "#/components/schemas/SessionReasoningEffortEvent",
            "session.resource.created": "#/components/schemas/SessionResourceCreatedEvent",
            "session.resource.deleted": "#/components/schemas/SessionResourceDeletedEvent",
            "session.sandbox_status": "#/components/schemas/SessionSandboxStatusEvent",
            "session.status": "#/components/schemas/SessionStatusEvent",
            "session.superseded": "#/components/schemas/SessionSupersededEvent",
            "session.terminal.activity": "#/components/schemas/SessionTerminalActivityEvent",
            "session.terminal_pending": "#/components/schemas/SessionTerminalPendingEvent",
            "session.title": "#/components/schemas/SessionTitleEvent",
            "session.todos": "#/components/schemas/SessionTodosEvent",
            "session.usage": "#/components/schemas/SessionUsageEvent",
            "turn.cancelled": "#/components/schemas/TurnCancelledEvent",
            "turn.completed": "#/components/schemas/TurnCompletedEvent",
            "turn.failed": "#/components/schemas/TurnFailedEvent",
            "turn.started": "#/components/schemas/TurnStartedEvent"
          },
          "propertyName": "type"
        },
        "oneOf": [
          {
            "$ref": "#/components/schemas/SessionStatusEvent"
          },
          {
            "$ref": "#/components/schemas/SessionUsageEvent"
          },
          {
            "$ref": "#/components/schemas/SessionModelEvent"
          },
          {
            "$ref": "#/components/schemas/SessionTitleEvent"
          },
          {
            "$ref": "#/components/schemas/SessionReasoningEffortEvent"
          },
          {
            "$ref": "#/components/schemas/SessionCollaborationModeEvent"
          },
          {
            "$ref": "#/components/schemas/SessionPermissionModeEvent"
          },
          {
            "$ref": "#/components/schemas/SessionCodexApprovalModeEvent"
          },
          {
            "$ref": "#/components/schemas/SessionAgentChangedEvent"
          },
          {
            "$ref": "#/components/schemas/SessionTodosEvent"
          },
          {
            "$ref": "#/components/schemas/SessionTerminalPendingEvent"
          },
          {
            "$ref": "#/components/schemas/SessionSandboxStatusEvent"
          },
          {
            "$ref": "#/components/schemas/SessionMcpStartupEvent"
          },
          {
            "$ref": "#/components/schemas/SessionModelOptionsEvent"
          },
          {
            "$ref": "#/components/schemas/SessionInputConsumedEvent"
          },
          {
            "$ref": "#/components/schemas/SessionInterruptedEvent"
          },
          {
            "$ref": "#/components/schemas/SessionCreatedEvent"
          },
          {
            "$ref": "#/components/schemas/SessionSupersededEvent"
          },
          {
            "$ref": "#/components/schemas/SessionBtwSidechatEvent"
          },
          {
            "$ref": "#/components/schemas/SessionPresenceEvent"
          },
          {
            "$ref": "#/components/schemas/SessionResourceCreatedEvent"
          },
          {
            "$ref": "#/components/schemas/SessionResourceDeletedEvent"
          },
          {
            "$ref": "#/components/schemas/SessionChildSessionUpdatedEvent"
          },
          {
            "$ref": "#/components/schemas/SessionChangedFilesInvalidatedEvent"
          },
          {
            "$ref": "#/components/schemas/SessionTerminalActivityEvent"
          },
          {
            "$ref": "#/components/schemas/OutputTextDeltaEvent"
          },
          {
            "$ref": "#/components/schemas/ToolOutputDeltaEvent"
          },
          {
            "$ref": "#/components/schemas/ReasoningStartedEvent"
          },
          {
            "$ref": "#/components/schemas/ReasoningTextDeltaEvent"
          },
          {
            "$ref": "#/components/schemas/ReasoningSummaryTextDeltaEvent"
          },
          {
            "$ref": "#/components/schemas/OutputItemDoneEvent"
          },
          {
            "$ref": "#/components/schemas/OutputFileDoneEvent"
          },
          {
            "$ref": "#/components/schemas/HeartbeatEvent"
          },
          {
            "$ref": "#/components/schemas/SessionHeartbeatEvent"
          },
          {
            "$ref": "#/components/schemas/ElicitationRequestEvent"
          },
          {
            "$ref": "#/components/schemas/ElicitationResolvedEvent"
          },
          {
            "$ref": "#/components/schemas/BrowserActionRequestEvent"
          },
          {
            "$ref": "#/components/schemas/PolicyDeniedEvent"
          },
          {
            "$ref": "#/components/schemas/CreatedEvent"
          },
          {
            "$ref": "#/components/schemas/QueuedEvent"
          },
          {
            "$ref": "#/components/schemas/InProgressEvent"
          },
          {
            "$ref": "#/components/schemas/CompletedEvent"
          },
          {
            "$ref": "#/components/schemas/FailedEvent"
          },
          {
            "$ref": "#/components/schemas/CancelledEvent"
          },
          {
            "$ref": "#/components/schemas/IncompleteEvent"
          },
          {
            "$ref": "#/components/schemas/RetryEvent"
          },
          {
            "$ref": "#/components/schemas/ErrorEvent"
          },
          {
            "$ref": "#/components/schemas/CompactionInProgressEvent"
          },
          {
            "$ref": "#/components/schemas/CompactionCompletedEvent"
          },
          {
            "$ref": "#/components/schemas/CompactionFailedEvent"
          },
          {
            "$ref": "#/components/schemas/ClientTaskCancelEvent"
          },
          {
            "$ref": "#/components/schemas/TurnStartedEvent"
          },
          {
            "$ref": "#/components/schemas/TurnCompletedEvent"
          },
          {
            "$ref": "#/components/schemas/TurnFailedEvent"
          },
          {
            "$ref": "#/components/schemas/TurnCancelledEvent"
          }
        ]
      },
      "SessionAgentChangedEvent": {
        "description": "The session's bound agent changed.\n\nEmitted after a session's MCP servers are edited (the agent's bundle\nis rewritten). Connected clients re-derive their cached session state\n(bound agent, harness presentation labels) from a fresh snapshot.",
        "properties": {
          "agent_id": {
            "description": "The agent bound to the session, e.g. `\"ag_abc123\"`.",
            "title": "Agent Id",
            "type": "string"
          },
          "agent_name": {
            "description": "Display name of that agent, e.g. `\"claude-native-ui\"`. Category: **transient** (SSE-only). The change is persisted, so on reconnect clients read it from the session snapshot.",
            "title": "Agent Name",
            "type": "string"
          },
          "conversation_id": {
            "description": "Session identifier, e.g. `\"conv_abc123\"`.",
            "title": "Conversation Id",
            "type": "string"
          },
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "type": {
            "const": "session.agent_changed",
            "description": "Always `\"session.agent_changed\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "conversation_id",
          "agent_id",
          "agent_name"
        ],
        "title": "SessionAgentChangedEvent",
        "type": "object"
      },
      "SessionBtwSidechatEvent": {
        "description": "A Claude Code `/btw` side-chat exchange to show transiently.\n\n`/btw` opens an ephemeral side conversation whose answer Claude Code\nkeeps only in its in-TUI overlay \u2014 it is never written to the session\ntranscript. The claude-native forwarder scrapes the settled overlay\nfrom the pane and emits this event so the managed web UI can show the\nsame ephemeral overlay (dismissed with Escape), WITHOUT adding a\npersisted side-chat turn to the main conversation.\n\nCategory: **transient** (SSE-only), live-only by design. Nothing is\npersisted and there is no SSE replay, so a reload drops the overlay \u2014\nmatching the terminal, where Escape closes it and leaves no history.\n\nThe wire shape is FLAT (not enveloped):\n`{\"type\": \"session.btw_sidechat\", \"conversation_id\": <id>, \"question\": <str>, \"answer\": <str>, \"truncated\": <bool>}`.",
        "properties": {
          "answer": {
            "description": "The side-chat answer text.",
            "title": "Answer",
            "type": "string"
          },
          "conversation_id": {
            "description": "The conversation whose stream this rides.",
            "title": "Conversation Id",
            "type": "string"
          },
          "question": {
            "description": "The `/btw` request line as typed, e.g. `\"/btw is this backward compatible?\"`.",
            "title": "Question",
            "type": "string"
          },
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "truncated": {
            "default": false,
            "description": "True when the pane clipped a longer answer; the web overlay notes it and points at the terminal for the full text.",
            "title": "Truncated",
            "type": "boolean"
          },
          "type": {
            "const": "session.btw_sidechat",
            "description": "Always `\"session.btw_sidechat\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "conversation_id",
          "question",
          "answer"
        ],
        "title": "SessionBtwSidechatEvent",
        "type": "object"
      },
      "SessionChangedFilesInvalidatedEvent": {
        "description": "The session's changed-files list may have changed \u2014 refetch it.\n\nA coarse \"something changed\" signal (per-file events aren't available\nfor git-mode workspaces) emitted by the runner after a file-mutating\ntool. The web treats it as a refetch trigger for the changed-files\npanel; transient (not persisted \u2014 the REST list is source of truth).",
        "properties": {
          "environment_id": {
            "default": "default",
            "description": "Environment whose changes were invalidated, e.g. `\"default\"`.",
            "title": "Environment Id",
            "type": "string"
          },
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "session_id": {
            "description": "Owning session/conversation id.",
            "title": "Session Id",
            "type": "string"
          },
          "type": {
            "const": "session.changed_files.invalidated",
            "description": "Always `\"session.changed_files.invalidated\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "session_id"
        ],
        "title": "SessionChangedFilesInvalidatedEvent",
        "type": "object"
      },
      "SessionChildSessionUpdatedEvent": {
        "description": "A child (sub-agent) session's status changed \u2014 pushed to the PARENT.\n\nLets the parent's resource rail update a child's status without\npolling `GET \u2026/child_sessions`. Carries the full\n`ChildSessionSummary` so the web patches its cache directly.",
        "properties": {
          "child": {
            "additionalProperties": true,
            "description": "A PARTIAL `ChildSessionSummary` \u2014 the snapshot-on-connect sends the full summary, while live runner deltas carry only the fields that changed (a status delta omits `last_message_preview`; a preview delta carries only it). The web merges present fields over the cached row, so the payload is an open dict rather than the strict model.",
            "title": "Child",
            "type": "object"
          },
          "child_session_id": {
            "description": "The child session id, e.g. `\"conv_child_abc123\"`.",
            "title": "Child Session Id",
            "type": "string"
          },
          "conversation_id": {
            "description": "The PARENT (carrier) session id.",
            "title": "Conversation Id",
            "type": "string"
          },
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "type": {
            "const": "session.child_session.updated",
            "description": "Always `\"session.child_session.updated\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "conversation_id",
          "child_session_id",
          "child"
        ],
        "title": "SessionChildSessionUpdatedEvent",
        "type": "object"
      },
      "SessionCodexApprovalModeEvent": {
        "description": "Active approval/sandbox-mode update from a codex-native session.\n\nEmitted after the web UI switches the mode, and after the Codex forwarder\nobserves a `thread/settings/updated` notification \u2014 an approval change the\nuser made inside Codex's `/permissions` popup, which Omnigent has no other\nway to see. Lets the composer's approval picker track the thread without a\nreload.",
        "properties": {
          "approval_mode": {
            "description": "The active mode, one of `\"ask-for-approval\"`, `\"approve-for-me\"`, `\"full-access\"`, `\"read-only\"`. Category: **transient** (SSE-only). The server also writes `omnigent.codex_native.approval_mode` on the conversation labels (and `terminal_launch_args`), so reconnecting clients restore the same state from the session snapshot.",
            "title": "Approval Mode",
            "type": "string"
          },
          "conversation_id": {
            "description": "Session identifier, e.g. `\"conv_abc123\"`.",
            "title": "Conversation Id",
            "type": "string"
          },
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "type": {
            "const": "session.codex_approval_mode",
            "description": "Always `\"session.codex_approval_mode\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "conversation_id",
          "approval_mode"
        ],
        "title": "SessionCodexApprovalModeEvent",
        "type": "object"
      },
      "SessionCollaborationModeEvent": {
        "description": "Active collaboration-mode update from a Codex-native session.\n\nEmitted after the web UI toggles Codex collaboration mode, and after the\nCodex forwarder observes a `thread/settings/updated` notification from\nthe native Codex TUI. Lets connected clients show a clear Plan-mode\nindicator without a reload.",
        "properties": {
          "conversation_id": {
            "description": "Session identifier, e.g. `\"conv_abc123\"`.",
            "title": "Conversation Id",
            "type": "string"
          },
          "mode": {
            "description": "The active collaboration mode string, e.g. `\"plan\"` or `\"default\"`. Category: **transient** (SSE-only). The server also writes `omnigent.codex_native.collaboration_mode` on the conversation labels, so reconnect clients restore the same state from the session snapshot.",
            "title": "Mode",
            "type": "string"
          },
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "type": {
            "const": "session.collaboration_mode",
            "description": "Always `\"session.collaboration_mode\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "conversation_id",
          "mode"
        ],
        "title": "SessionCollaborationModeEvent",
        "type": "object"
      },
      "SessionCreatedEvent": {
        "description": "A child (sub-agent) session was spawned from this session.\n\nEmitted by `omnigent/tools/builtins/spawn.py:_spawn_one`\nonto the **parent** session's conversation stream after the\nchild conversation row is created and the child task has been\nstarted. Per the session-rearchitecture spec \u00a73 (\"Event types\nand direction\") and \u00a77 (\"Flow: client interacts with\nsub-agent\"), this lets clients watching the parent session's\nSSE subscribe directly to the child's stream without polling\nhistory for the tunneled `function_call` item.\n\nThe wire shape is FLAT (not enveloped):\n`{\"type\": \"session.created\", \"conversation_id\": <parent>, \"child_session_id\": <child>, \"agent_id\": <agent or None>, \"parent_session_id\": <parent>, \"sequence_number\": null}`.\n\nThe existing tunneled `function_call` ConversationItem\n(carried inside `OutputItemDoneEvent`) is retained\nfor compatibility \u2014 clients that don't yet implement the\n\"subscribe to child stream\" pattern can keep rendering sub-\nagent calls from the parent's persistent history.",
        "properties": {
          "agent_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Registered agent id the child runs as, e.g. `\"agent_xyz\"`. `None` is permitted only for legacy spawn paths that did not record an agent id; new code MUST set it.",
            "title": "Agent Id"
          },
          "child_session_id": {
            "description": "The newly-created child session id, e.g. `\"conv_child456\"`. Same as `conversation_id` on the child's own stream when consumers pivot to it.",
            "title": "Child Session Id",
            "type": "string"
          },
          "conversation_id": {
            "description": "The PARENT session/conversation id \u2014 this event rides the parent's stream, e.g. `\"conv_parent123\"`.",
            "title": "Conversation Id",
            "type": "string"
          },
          "parent_session_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Echo of `conversation_id` for consumers that key on a dedicated \"parent\" field rather than the carrier `conversation_id`. Always equal to `conversation_id`; included for forward-compat with clients that may relay these events across stream boundaries. Category: **transient** (SSE-only). The corresponding durable record of \"a child session exists\" lives in the conversation store as the child conversation row itself (`parent_conversation_id` foreign key) and the parent's tunneled `function_call` item \u2014 reconnecting clients discover children by walking the parent's persisted history, not by replaying this event.",
            "title": "Parent Session Id"
          },
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "type": {
            "const": "session.created",
            "description": "Always `\"session.created\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "conversation_id",
          "child_session_id"
        ],
        "title": "SessionCreatedEvent",
        "type": "object"
      },
      "SessionForkRequest": {
        "additionalProperties": false,
        "description": "Request body for `POST /v1/sessions/{source_id}/fork`.\n\nCreates a deep copy of an existing session's items into a new\nsession. All fields are optional.",
        "properties": {
          "agent_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Built-in agent to bind the fork to, switching it away from the source's agent/harness (e.g. fork a Claude session into a Codex one, or a Claude-SDK session into Claude Code). When `None`, the fork keeps the source's agent. Must be a built-in agent (one listed by `GET /v1/agents`).",
            "title": "Agent Id"
          },
          "codex_bypass_sandbox": {
            "default": false,
            "description": "Opt-in for the DANGEROUS codex-native full-bypass (`--dangerously-bypass-approvals-and-sandbox`) on the fork. The source's bypass label is ALWAYS dropped on a fork (a bypass-armed source can never silently re-arm its clone), so this is the only way a fork enables it \u2014 an explicit, banner-gated opt-in from the dialog, mirroring the new-session approval selector. `True` stamps `omnigent.codex_native.bypass_sandbox` on the fork; `False` / omitted leaves the fork in Codex's normal approval/sandbox stance. Only meaningful for a codex-native target; ignored otherwise.",
            "title": "Codex Bypass Sandbox",
            "type": "boolean"
          },
          "host_type": {
            "default": "external",
            "description": "How the fork's host is obtained \u2014 `\"external\"` (the default: the caller binds one afterwards, via `POST /v1/hosts/{host_id}/runners` from the web dialog or `PATCH /v1/sessions/{id}` from the REPL) or `\"managed\"` (the server provisions a sandbox host for the fork, the same background launch a `host_type: \"managed\"` create schedules).",
            "enum": [
              "external",
              "managed"
            ],
            "title": "Host Type",
            "type": "string"
          },
          "model_override": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Per-session LLM model override to apply to the fork, e.g. `\"claude-opus-4-7\"`. **Omitting** the field inherits the source's model (same as today, within the same provider family); an explicit value overrides it, and a clear alias (`\"default\"`, `\"off\"`, `\"reset\"`) resets the fork to the bound agent's default. Validated against a conservative model-id charset. Set by the web fork dialog's model picker.",
            "title": "Model Override"
          },
          "reasoning_effort": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Per-session reasoning-effort override to apply to the fork, e.g. `\"high\"`. **Omitting** the field inherits the source's effort; an explicit value overrides it, and a clear alias (`\"default\"`, `\"off\"`, `\"reset\"`) resets it. Validated against the shared effort vocabulary; provider support is enforced at launch. Set by the web fork dialog's effort picker.",
            "title": "Reasoning Effort"
          },
          "sandbox_provider": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Which configured sandbox provider to provision on `host_type: \"managed\"` (one of the server's `sandbox_providers`); `None` takes the server's first. Only valid with `host_type: \"managed\"`.",
            "title": "Sandbox Provider"
          },
          "side_chat": {
            "default": false,
            "title": "Side Chat",
            "type": "boolean"
          },
          "terminal_launch_args": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Per-session native-terminal pass-through args to apply to the fork, e.g. `[\"--permission-mode\", \"auto\"]` (the fork dialog's permission-/approval-mode selector). **Omitting** the field keeps today's behavior \u2014 the source's args are carried on a same-agent fork and dropped on an agent switch. A list (including `[]`, which clears them) replaces them wholesale. Bounds (count / length) are validated server-side.",
            "title": "Terminal Launch Args"
          },
          "title": {
            "anyOf": [
              {
                "maxLength": 200,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Title for the forked session. When `None`, the server derives `\"Fork of <source_title>\"`.",
            "title": "Title"
          },
          "up_to_response_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Truncation point for the copied history, e.g. `\"resp_abc123\"`. When set, only items up to and including the last item of that response are copied \u2014 items after it are dropped from the fork. When `None` (default), the full history is copied.",
            "title": "Up To Response Id"
          },
          "workspace": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Git repository URL (optionally `#<branch>`) the server clones into the fork's sandbox as its working directory, e.g. `\"https://github.com/org/repo#release-1.2\"`. **Omitting** the field inherits the repository the source session recorded, so cloning a sandbox session lands the fork in the same checkout; an explicit value overrides it and an explicit `null` gives the fork an empty sandbox. Only valid with `host_type: \"managed\"` \u2014 an external fork's directory is chosen when it binds a host.",
            "title": "Workspace"
          }
        },
        "title": "SessionForkRequest",
        "type": "object"
      },
      "SessionGitOptions": {
        "description": "Git worktree options for `POST /v1/sessions`.\n\nRequires `host_id` to be set (and therefore `workspace`, which\nis interpreted as the source repository directory). Two modes,\nselected by `existing_worktree`:\n\n- **create** (default): the server creates a git worktree on the\n  host for a new branch and starts the runner in that worktree\n  instead of the picked directory.\n- **bind** (`existing_worktree=True`): `workspace` already IS a\n  pre-existing worktree; no worktree is created. `branch_name` is\n  recorded as the session's `git_branch` for display and opt-in\n  cleanup, and `base_branch` must not be set.\n\nSee designs/SESSION_GIT_WORKTREE.md.",
        "properties": {
          "base_branch": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional base ref to branch from, e.g. `\"main\"` or `\"origin/main\"`. `None` branches from the source repository's current `HEAD`. Create mode only \u2014 invalid with `existing_worktree`.",
            "title": "Base Branch"
          },
          "branch_name": {
            "description": "In create mode, the new branch to create and check out, e.g. `\"feature/login\"`. In bind mode, the branch already checked out in the existing worktree. Validated against git ref-format rules; invalid names fail with `invalid_input`.",
            "title": "Branch Name",
            "type": "string"
          },
          "existing_branch": {
            "default": false,
            "description": "When `True`, `branch_name` already exists and the host checks it out into a fresh worktree (the deleted-worktree recreate path) instead of creating a new branch. Create mode only; invalid with `existing_worktree` and with `base_branch` (an existing branch has no base to fork).",
            "title": "Existing Branch",
            "type": "boolean"
          },
          "existing_worktree": {
            "default": false,
            "description": "When `True`, bind to the pre-existing worktree at `workspace` instead of creating one (see above).",
            "title": "Existing Worktree",
            "type": "boolean"
          }
        },
        "required": [
          "branch_name"
        ],
        "title": "SessionGitOptions",
        "type": "object"
      },
      "SessionHeartbeatEvent": {
        "description": "Idle-stream keepalive on `GET /v1/sessions/{id}/stream`.\n\nEmitted by the session-stream route on a fixed cadence whenever\nthe underlying publish queue has been quiet (no turn in flight,\nno resource events). Distinct from `HeartbeatEvent`\n(`response.heartbeat`), which is per-turn and is driven by\nthe runtime workflow while a response is producing output.\n\nWhy this exists: the session stream stays open across many turns\nand through idle periods (waiting for the user to type). Without\na periodic emit, intermediate proxies, OS-level sockets, and the\nclient's SSE read-timeout can leave a half-open stream\nundetected for minutes after a network event (laptop sleep,\nWi-Fi handoff). The heartbeat puts a regular byte on the wire\nso the client's read-timeout and the server's\n`request.is_disconnected()` check both fire promptly.\n\nConsumers MAY ignore the payload entirely (the bytes crossing\nthe wire are sufficient). The optional `server_time` mirrors\n`HeartbeatEvent` for symmetry and debugging.",
        "properties": {
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "server_time": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "ISO 8601 UTC timestamp at emission, e.g. `\"2026-05-25T10:30:00Z\"`. `None` when the producer chose not to populate it.",
            "title": "Server Time"
          },
          "type": {
            "const": "session.heartbeat",
            "description": "Always `\"session.heartbeat\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type"
        ],
        "title": "SessionHeartbeatEvent",
        "type": "object"
      },
      "SessionInputConsumedEvent": {
        "description": "A queued input item was materialized into conversation history.\n\nEmitted by `POST /v1/sessions/{id}/events` once per accepted\ninput item at the moment it is persisted into conversation\nhistory (either onto a steered active turn or as the seed item\nof a freshly-started one). Wire shape uses the NESTED envelope:\n`{\"type\": \"session.input.consumed\", \"data\": <SessionInputConsumedPayload>, \"sequence_number\": null}`.\n\nThe event name is **provisional** \u2014 it may be renamed in a\nfuture revision. Consumers should reference\n`SessionInputConsumedEvent` (or its `type` literal)\nrather than hardcoding the wire string.",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/SessionInputConsumedPayload",
            "description": "The decoded queued-item payload \u2014 see `SessionInputConsumedPayload`."
          },
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "type": {
            "const": "session.input.consumed",
            "description": "Always `\"session.input.consumed\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "data"
        ],
        "title": "SessionInputConsumedEvent",
        "type": "object"
      },
      "SessionInputConsumedPayload": {
        "description": "Inner payload of a `SessionInputConsumedEvent`.\n\nEmitted by the sessions route handler at the moment a client\ninput is persisted into `conversation_items`. Carries the\npersisted-item shape so clients can render the input (e.g.\nthe user's message bubble) at the moment of acceptance.",
        "properties": {
          "cleared_pending_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "When this consumed message drains a `omnigent.runtime.pending_inputs` entry (a native- terminal web message round-tripping back from the transcript), the drained entry's id, e.g. `\"pending_a1b2c3\"`. Lets a client drop the matching optimistic bubble by id instead of by position. `None` for non-native messages and for messages that matched no pending entry (e.g. typed directly in the TUI).",
            "title": "Cleared Pending Id"
          },
          "created_by": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Email of the human actor who posted the item, e.g. `\"alice@example.com\"`. `None` for agent/tool/system items and single-user mode. Mirrors `ConversationItem.to_api_dict` for live attribution.",
            "title": "Created By"
          },
          "data": {
            "additionalProperties": true,
            "description": "Decoded item payload, e.g. `{\"role\": \"user\", \"content\": [{\"type\": \"input_text\", \"text\": \"Hello\"}]}`. Heterogeneous and `type`-specific.",
            "title": "Data",
            "type": "object"
          },
          "item_id": {
            "description": "Stable identifier of the conversation item just persisted, e.g. `\"item_abc123\"`.",
            "title": "Item Id",
            "type": "string"
          },
          "type": {
            "description": "The item type discriminator \u2014 `\"message\"` for user messages, `\"function_call_output\"` for tool results, etc. Mirrors `omnigent.server.schemas.SessionEventInput`'s `type` field.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "item_id",
          "type",
          "data"
        ],
        "title": "SessionInputConsumedPayload",
        "type": "object"
      },
      "SessionInterruptedEvent": {
        "description": "User-triggered cancel reached the loop.\n\nEmitted by `_publish_interrupted` in\n`omnigent/server/routes/sessions.py` when a client posts\na `{\"type\": \"interrupt\"}` to `POST /v1/sessions/{id}/events`. Co-emitted with\n`IncompleteEvent` (with the underlying response carrying\n`incomplete_details.reason == \"user_interrupt\"`) so off-the-\nshelf Responses parsers still close cleanly. Wire shape uses\nthe NESTED envelope verbatim from the existing emit site.",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/SessionInterruptedPayload",
            "description": "The interrupt metadata \u2014 see `SessionInterruptedPayload`."
          },
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "type": {
            "const": "session.interrupted",
            "description": "Always `\"session.interrupted\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "data"
        ],
        "title": "SessionInterruptedEvent",
        "type": "object"
      },
      "SessionInterruptedPayload": {
        "description": "Inner payload of a `SessionInterruptedEvent`.\n\nBuilt by `_publish_interrupted` in\n`omnigent/server/routes/sessions.py`.",
        "properties": {
          "requested_at": {
            "description": "Unix epoch seconds when the interrupt request reached the server, e.g. `1704067200`.",
            "format": "int64",
            "title": "Requested At",
            "type": "integer"
          },
          "response_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional active response id for terminal-backed integrations, e.g. `\"codex_turn_abc123\"`.",
            "title": "Response Id"
          }
        },
        "required": [
          "requested_at"
        ],
        "title": "SessionInterruptedPayload",
        "type": "object"
      },
      "SessionLabelsResponse": {
        "description": "Lightweight response body for `GET /v1/sessions/{id}/labels`.",
        "properties": {
          "id": {
            "description": "Session identifier, e.g. `\"conv_abc123\"`.",
            "title": "Id",
            "type": "string"
          },
          "labels": {
            "additionalProperties": {
              "type": "string"
            },
            "description": "Session-scoped guardrails labels. Empty dict when no labels have been written.",
            "title": "Labels",
            "type": "object"
          }
        },
        "required": [
          "id"
        ],
        "title": "SessionLabelsResponse",
        "type": "object"
      },
      "SessionList": {
        "description": "Paginated list of sessions; `data` is a page of `SessionListItem`.",
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/SessionListItem"
            },
            "title": "Data",
            "type": "array"
          },
          "first_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "First Id"
          },
          "has_more": {
            "default": false,
            "title": "Has More",
            "type": "boolean"
          },
          "last_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Id"
          },
          "object": {
            "const": "list",
            "default": "list",
            "title": "Object",
            "type": "string"
          }
        },
        "title": "SessionList",
        "type": "object"
      },
      "SessionListItem": {
        "description": "Lightweight session summary for `GET /v1/sessions` list responses.\n\nSame shape as `SessionResponse` minus `items`.",
        "properties": {
          "agent_id": {
            "description": "Durable identifier of the bound agent.",
            "title": "Agent Id",
            "type": "string"
          },
          "agent_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Human-readable name of the bound agent, e.g. `\"research-agent\"`. `None` when the agent row cannot be found.",
            "title": "Agent Name"
          },
          "archived": {
            "default": false,
            "description": "Whether the session is archived. Archived sessions are returned by `GET /v1/sessions` only when the request passes `include_archived=true`; the sidebar groups them into a dedicated \"Archived\" section. `False` for normal sessions.",
            "title": "Archived",
            "type": "boolean"
          },
          "comments_count": {
            "default": 0,
            "description": "Total number of review comments (any status) on this session. Together with `comments_updated_at` it forms a change fingerprint: an add or edit bumps the timestamp, a delete changes the count, so the web client can invalidate its cached comment list when either field changes in a `WS /v1/sessions/updates` frame. `0` when the session has no comments or the server has no comment store wired.",
            "format": "int64",
            "title": "Comments Count",
            "type": "integer"
          },
          "comments_updated_at": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "Unix epoch **microseconds** of the most recently mutated comment on this session (max `updated_at` across its comments). Microsecond precision keeps back-to-back mutations within one second distinguishable while staying an exact integer in JavaScript; clients only compare it for change. `None` when the session has no comments or the server has no comment store wired.",
            "title": "Comments Updated At"
          },
          "created_at": {
            "description": "Unix epoch seconds of creation.",
            "format": "int64",
            "title": "Created At",
            "type": "integer"
          },
          "external_session_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Runtime-native session id this conversation wraps, e.g. a Claude Code session uuid for `omnigent claude` sessions. `None` for regular AP-only conversations. Lets the sidebar / picker render a runtime badge without a follow-up GET.",
            "title": "External Session Id"
          },
          "git_branch": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Git branch checked out in the session's worktree, e.g. `\"feature/login\"`. Set only when the session was created with a server-created git worktree; `None` otherwise. The Web UI uses a non-`None` value to offer the \"delete local branch\" cleanup checkbox on session delete. See designs/SESSION_GIT_WORKTREE.md.",
            "title": "Git Branch"
          },
          "host_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Host that launched the runner for this session.",
            "title": "Host Id"
          },
          "host_online": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "description": "Whether the session's host tunnel is live (status online and fresh within the host liveness TTL). `None` when the session has no `host_id` (CLI/local). Distinguishes \"runner down but host can relaunch\" from \"host offline\" for the open-session view; not used by the sidebar.",
            "title": "Host Online"
          },
          "id": {
            "description": "Session/conversation identifier, e.g. `\"conv_abc123\"`.",
            "title": "Id",
            "type": "string"
          },
          "labels": {
            "additionalProperties": {
              "type": "string"
            },
            "description": "Session-scoped guardrails labels.",
            "title": "Labels",
            "type": "object"
          },
          "owner": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "The user_id of the session owner, or `None` when permissions are disabled. Included so the sidebar can display the owner without a separate API call.",
            "title": "Owner"
          },
          "parent_session_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Parent Session Id"
          },
          "pending_elicitations_count": {
            "default": 0,
            "description": "Number of approval prompts currently waiting on this session. Powers the sidebar's \"needs attention\" badge so a user with several sessions running can tell which ones are blocked on them without opening each chat. Sourced from the Omnigent server's in-memory `omnigent.runtime.pending_elicitations` index, which mirrors every `response.elicitation_request` event passing through `session_stream` and decrements when a verdict is dispatched. `0` when the session has no outstanding elicitations.",
            "format": "int64",
            "title": "Pending Elicitations Count",
            "type": "integer"
          },
          "permission_level": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "The requesting user's numeric permission level on this session: `1` = read, `2` = edit, `3` = manage. `None` when permissions are disabled.",
            "title": "Permission Level"
          },
          "project_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Project Id"
          },
          "reasoning_effort": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Per-session reasoning-effort hint.",
            "title": "Reasoning Effort"
          },
          "runner_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Runner currently bound to the session.",
            "title": "Runner Id"
          },
          "runner_online": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "description": "Strict runner liveness \u2014 `True` iff a runner tunnel is currently registered for this session. Matches `GET /health`'s `runner_online` value. Strict: a dead runner on a live host reads `False` here (no host-relaunch optimism folded in), unlike the legacy conflated value. `None` when the server has no runner liveness lookup wired.",
            "title": "Runner Online"
          },
          "search_snippet": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Excerpt of the chat content that matched the request's `search_query`, centered on the match with `\u2026` marking elided ends, so the search UI can show *where* a session matched in its body. Present whenever the query hit an item body (even if the title also matched); `None` on non-search reads and when only the title matched.",
            "title": "Search Snippet"
          },
          "status": {
            "description": "Derived session lifecycle status.",
            "enum": [
              "idle",
              "running",
              "waiting",
              "failed"
            ],
            "title": "Status",
            "type": "string"
          },
          "title": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional human-readable title.",
            "title": "Title"
          },
          "updated_at": {
            "description": "Unix epoch seconds of last update.",
            "format": "int64",
            "title": "Updated At",
            "type": "integer"
          },
          "viewer_last_seen": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "The *requesting user's* \"last seen\" wall-clock baseline in seconds for this session, or `None` when they have never seen it. Per-viewer (built from the server's in-memory per-user read-state, written by `PUT /v1/sessions/{id}/read-state`); the unread dot shows when `updated_at > viewer_last_seen` and the session is finished. In-memory only \u2014 resets on a server restart.",
            "title": "Viewer Last Seen"
          },
          "viewer_unread": {
            "default": false,
            "description": "Whether the *requesting user* explicitly marked this session unread. Per-viewer; lifts the active-row dot suppression on the client. `False` by default.",
            "title": "Viewer Unread",
            "type": "boolean"
          },
          "workspace": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Absolute path on disk where the runner cd's, e.g. `\"/Users/corey/universe/src/foo\"`. `None` for sessions that haven't been bound to a host workspace.",
            "title": "Workspace"
          }
        },
        "required": [
          "id",
          "agent_id",
          "status",
          "created_at",
          "updated_at"
        ],
        "title": "SessionListItem",
        "type": "object"
      },
      "SessionMcpStartupEvent": {
        "description": "Per-MCP-server startup progress for a native harness session.\n\nA codex-native session brings up its configured MCP servers when its\nCodex thread starts; slow or failing servers previously left the web\nsession looking hung with no signal. The native forwarder mirrors\nCodex's `mcpServer/startupStatus/updated` notifications as\n`external_mcp_startup` posts, republished here so the web UI can\nshow which servers are still starting and which failed or were\ncancelled.",
        "properties": {
          "conversation_id": {
            "description": "Session identifier, e.g. `\"conv_abc123\"`.",
            "title": "Conversation Id",
            "type": "string"
          },
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "servers": {
            "additionalProperties": {
              "$ref": "#/components/schemas/McpServerStartup"
            },
            "description": "Latest per-server startup map, e.g. `{\"safe\": {\"status\": \"starting\", \"error\": None}}`. Category: **transient** (SSE + snapshot cache). Not persisted; a client connecting mid-startup seeds from the session snapshot's `mcp_startup` field and updates live off this event.",
            "title": "Servers",
            "type": "object"
          },
          "type": {
            "const": "session.mcp_startup",
            "description": "Always `\"session.mcp_startup\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "conversation_id",
          "servers"
        ],
        "title": "SessionMcpStartupEvent",
        "type": "object"
      },
      "SessionModelEvent": {
        "description": "Active-model report from a harness integration.\n\nEmitted after an `external_model_change` POST from a native\nforwarder or when an SDK relay reports its concrete model in terminal\nresponse usage. Every surface re-renders its model display from this.",
        "properties": {
          "conversation_id": {
            "description": "Session identifier, e.g. `\"conv_abc123\"`.",
            "title": "Conversation Id",
            "type": "string"
          },
          "model": {
            "description": "The model the harness reports the session is on, VERBATIM in the harness's own spelling, e.g. `\"claude-opus-4-8[1m]\"` or `\"gpt-5.6-luna\"` \u2014 never collapsed to a picker alias. Category: **transient** (SSE-only). The server also writes `reported_model` on the conversation (served on the snapshot's `llm_model`), so on reconnect clients restore the display from the snapshot rather than from a replayed event.",
            "title": "Model",
            "type": "string"
          },
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "type": {
            "const": "session.model",
            "description": "Always `\"session.model\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "conversation_id",
          "model"
        ],
        "title": "SessionModelEvent",
        "type": "object"
      },
      "SessionModelOptionsEvent": {
        "description": "Signal that a native session's model catalog has resolved.\n\nModel options are fetched from the bound runner and cached on the session\nsnapshot. The initial snapshot can return an empty list while this\nbackground fetch is in flight; this event tells connected clients to\nre-read the snapshot and apply its now-populated `model_options`.\n\nCarries no payload beyond the conversation id. The snapshot's\n`model_options` field remains the source of truth.",
        "properties": {
          "conversation_id": {
            "description": "Session identifier, e.g. `\"conv_abc123\"`. Category: **transient** (SSE-only). On reconnect, clients seed Native model / effort controls from the session snapshot.",
            "title": "Conversation Id",
            "type": "string"
          },
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "type": {
            "const": "session.model_options",
            "description": "Always `\"session.model_options\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "conversation_id"
        ],
        "title": "SessionModelOptionsEvent",
        "type": "object"
      },
      "SessionPermissionModeEvent": {
        "description": "Active permission-mode update from a claude-native session.\n\nEmitted after the web UI switches the mode, and after the Claude forwarder\nobserves a different mode in the pane footer \u2014 a shift+tab pressed inside\nthe TUI, which Omnigent has no other way to see. Lets the composer's mode\npicker track the pane without a reload.",
        "properties": {
          "conversation_id": {
            "description": "Session identifier, e.g. `\"conv_abc123\"`.",
            "title": "Conversation Id",
            "type": "string"
          },
          "permission_mode": {
            "description": "The active mode, e.g. `\"auto\"` or `\"plan\"`. Category: **transient** (SSE-only). The server also writes `omnigent.claude_native.permission_mode` on the conversation labels, so reconnecting clients restore the same state from the session snapshot.",
            "title": "Permission Mode",
            "type": "string"
          },
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "type": {
            "const": "session.permission_mode",
            "description": "Always `\"session.permission_mode\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "conversation_id",
          "permission_mode"
        ],
        "title": "SessionPermissionModeEvent",
        "type": "object"
      },
      "SessionPresenceEvent": {
        "description": "The session's viewer list changed \u2014 full state, not a delta.\n\nEmitted on `GET /v1/sessions/{id}/stream` whenever a user\njoins, leaves (after the server-side grace window absorbs\nreconnect churn), or flips their idle aggregate, and once to\neach newly-connected stream as a snapshot-on-connect. Every\nevent carries the COMPLETE viewer list so clients replace their\nstate wholesale \u2014 missed events self-heal on the next event or\nreconnect. Viewers are scoped to the session *tree* (the root\nconversation and every sub-agent conversation under it), so a\nuser on a sub-agent page and a user on the root page appear in\neach other's lists. See `omnigent/server/presence.py` and\n`designs/UI/PRESENCE.md`.",
        "properties": {
          "conversation_id": {
            "description": "The conversation whose stream delivered this event \u2014 the root or a sub-agent conversation, e.g. `\"conv_abc123\"`. Matches the streamed conversation (not necessarily the tree's root) so clients can guard events by the conversation they are viewing.",
            "title": "Conversation Id",
            "type": "string"
          },
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "type": {
            "const": "session.presence",
            "description": "Always `\"session.presence\"`.",
            "title": "Type",
            "type": "string"
          },
          "viewers": {
            "description": "All users currently viewing any conversation in the session tree (including the receiving user \u2014 the web filters self out for display), ordered by join time.",
            "items": {
              "$ref": "#/components/schemas/PresenceViewer"
            },
            "title": "Viewers",
            "type": "array"
          }
        },
        "required": [
          "type",
          "conversation_id",
          "viewers"
        ],
        "title": "SessionPresenceEvent",
        "type": "object"
      },
      "SessionProjectSummary": {
        "description": "One entry of `GET /v1/sessions/projects` \u2014 a sidebar project folder.\n\nDual-read union of first-class projects and legacy `omni_project`\nlabel-projects, keyed by name.",
        "properties": {
          "icon": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "The project's chosen emoji icon (a unicode grapheme), read from its `config`; `None` when unset or for a label-only folder, so the sidebar falls back to the default folder glyph.",
            "title": "Icon"
          },
          "id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "First-class project id when one exists, or `None` for a label-only project not yet promoted to the `projects` table.",
            "title": "Id"
          },
          "name": {
            "description": "Project name (the folder's display name and union key).",
            "title": "Name",
            "type": "string"
          }
        },
        "required": [
          "name"
        ],
        "title": "SessionProjectSummary",
        "type": "object"
      },
      "SessionReasoningEffortEvent": {
        "description": "Active reasoning-effort update from a terminal-backed integration.\n\nEmitted after an `external_reasoning_effort_change` POST from a native\nterminal forwarder when the user changes the thinking level inside the\nterminal UI. Lets the web effort picker reflect a TUI-side switch without\na reload.",
        "properties": {
          "conversation_id": {
            "description": "Session identifier, e.g. `\"conv_abc123\"`.",
            "title": "Conversation Id",
            "type": "string"
          },
          "reasoning_effort": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Reasoning effort now active for the session, e.g. `\"medium\"`, or `None` when Codex cleared to its default. Category: **transient** (SSE-only). The server also writes `reasoning_effort` on the conversation, so on reconnect clients restore the selection from the session snapshot rather than from a replayed event.",
            "title": "Reasoning Effort"
          },
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "type": {
            "const": "session.reasoning_effort",
            "description": "Always `\"session.reasoning_effort\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "conversation_id"
        ],
        "title": "SessionReasoningEffortEvent",
        "type": "object"
      },
      "SessionResourceCreatedEvent": {
        "description": "A session resource was created.\n\nEmitted when a terminal is launched, a file is uploaded, or\nany other resource is materialized under a session. Wire shape\nis FLAT: `{\"type\": \"session.resource.created\", \"resource\": <SessionResourceObject-like dict>}`.",
        "properties": {
          "resource": {
            "additionalProperties": true,
            "description": "The newly created resource object.",
            "title": "Resource",
            "type": "object"
          },
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "type": {
            "const": "session.resource.created",
            "description": "Always `\"session.resource.created\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "resource"
        ],
        "title": "SessionResourceCreatedEvent",
        "type": "object"
      },
      "SessionResourceDeletedEvent": {
        "description": "A session resource was deleted.\n\nEmitted when a terminal is closed, a file is deleted, or\nany other resource is removed from a session.",
        "properties": {
          "resource_id": {
            "description": "Opaque id of the deleted resource.",
            "title": "Resource Id",
            "type": "string"
          },
          "resource_type": {
            "description": "Type of the deleted resource, e.g. `\"terminal\"`, `\"file\"`.",
            "title": "Resource Type",
            "type": "string"
          },
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "session_id": {
            "description": "Owning session/conversation id.",
            "title": "Session Id",
            "type": "string"
          },
          "type": {
            "const": "session.resource.deleted",
            "description": "Always `\"session.resource.deleted\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "resource_id",
          "resource_type",
          "session_id"
        ],
        "title": "SessionResourceDeletedEvent",
        "type": "object"
      },
      "SessionResourceObject": {
        "additionalProperties": false,
        "description": "API representation of a session-scoped resource handle.",
        "properties": {
          "environment": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "For terminal resources, the environment id the terminal actually runs in. Omitted for non-terminal resources.",
            "title": "Environment"
          },
          "id": {
            "description": "Opaque resource identifier, e.g. `\"default\"` or `\"terminal_bash_s1\"`.",
            "title": "Id",
            "type": "string"
          },
          "metadata": {
            "additionalProperties": true,
            "description": "Resource-type-specific metadata.",
            "title": "Metadata",
            "type": "object"
          },
          "name": {
            "description": "Human-readable display name. Not required to be globally unique.",
            "title": "Name",
            "type": "string"
          },
          "object": {
            "const": "session.resource",
            "description": "Fixed resource type, always `\"session.resource\"`.",
            "title": "Object",
            "type": "string"
          },
          "session_id": {
            "description": "Owning session/conversation id.",
            "title": "Session Id",
            "type": "string"
          },
          "type": {
            "description": "Resource kind, initially `\"environment\"`, `\"terminal\"`, or `\"file\"`.",
            "enum": [
              "environment",
              "terminal",
              "file"
            ],
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "id",
          "object",
          "type",
          "session_id",
          "name"
        ],
        "title": "SessionResourceObject",
        "type": "object"
      },
      "SessionResourcePaginatedList": {
        "description": "Public paginated list of session resources.",
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/SessionResourceObject"
            },
            "title": "Data",
            "type": "array"
          },
          "first_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "First Id"
          },
          "has_more": {
            "default": false,
            "title": "Has More",
            "type": "boolean"
          },
          "last_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Id"
          },
          "object": {
            "const": "list",
            "default": "list",
            "title": "Object",
            "type": "string"
          }
        },
        "title": "SessionResourcePaginatedList",
        "type": "object"
      },
      "SessionResponse": {
        "description": "API representation of a session.\n\nReturned by `POST /v1/sessions`, `GET /v1/sessions/{id}`,\nand `PATCH /v1/sessions/{id}`.",
        "properties": {
          "active_response_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Response id of the turn currently in flight, or `None` when the session is idle. Sourced from the server's `_session_active_response_cache` at snapshot build time so a client connecting mid-turn can reopen a streaming `activeResponse` \u2014 the SSE stream is snapshot + live tail with no replay, so the turn-start `running` edge that carried this id is not re-sent on reconnect. Today only native-terminal forwarders (claude-native) stamp a turn id on their status edges; other harnesses leave this `None`.",
            "title": "Active Response Id"
          },
          "agent_id": {
            "description": "Durable identifier of the bound agent, e.g. `\"ag_abc123\"`. Stable across renames of the agent.",
            "title": "Agent Id",
            "type": "string"
          },
          "agent_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Human-readable name of the bound agent, e.g. `\"research-agent\"`. Loaded from the agent row at snapshot-build time. `None` when the agent row cannot be found (deleted or orphaned session).",
            "title": "Agent Name"
          },
          "archived": {
            "default": false,
            "description": "Whether the session is archived. Archived sessions are hidden from the default sidebar listing and surface only behind the \"Show archived\" toggle. `False` for normal sessions. Toggled via `PATCH /v1/sessions/{id}`.",
            "title": "Archived",
            "type": "boolean"
          },
          "background_task_count": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "Background shells (claude-native) still running as of the last status edge, so a reload re-shows \"N shells still running\" even though the session has settled to `\"idle\"`. `None` (the default / omitted) when no shells are tracked.",
            "title": "Background Task Count"
          },
          "background_tasks": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/BackgroundTaskInfo"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Per-shell detail for the running tally above, so a reload can restore each shell's description/command. `None` when none are tracked (or when an older runner reported only the count).",
            "title": "Background Tasks"
          },
          "context_window": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "The model's context window size in tokens as looked up server-side from litellm's registry (or from the `AP_CONTEXT_WINDOW_OVERRIDE` env var), e.g. `200_000`. `None` when the model is not in litellm's registry and no override is set.",
            "title": "Context Window"
          },
          "cost_control_mode_override": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Per-session cost-control switch: `\"on\"` activates the spec's configured cost-control mode, `\"off\"` disables cost control for this session. `None` means no override is active (the spec default applies). Set at create time or via `PATCH /v1/sessions/{id}` (the web \"Cost Optimized\" toggle); read by the cost-control advisor pipeline.",
            "title": "Cost Control Mode Override"
          },
          "created_at": {
            "description": "Unix epoch seconds of creation.",
            "format": "int64",
            "title": "Created At",
            "type": "integer"
          },
          "external_session_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Runtime-native session id this conversation wraps, e.g. a Claude Code session uuid for `omnigent claude` sessions. `None` for regular AP-only conversations. Populated by the wrapper bridge.",
            "title": "External Session Id"
          },
          "git_branch": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Git branch checked out in the session's worktree, e.g. `\"feature/login\"`. Set only when the session was created with a server-created git worktree; `None` otherwise. The Web UI uses a non-`None` value to offer the \"delete local branch\" cleanup checkbox on session delete. See designs/SESSION_GIT_WORKTREE.md.",
            "title": "Git Branch"
          },
          "harness": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "The bound agent's canonical harness, e.g. `\"claude-sdk\"` or `\"openai-agents\"`. Lets the client render the active credential for the correct provider family instead of inferring it from the model string (which is wrong when the agent declares no model). `None` when the agent cannot be looked up.",
            "title": "Harness"
          },
          "host_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Host that launched (or should launch) the runner for this session, e.g. `\"host_a1b2c3d4...\"`. `None` for CLI-initiated sessions.",
            "title": "Host Id"
          },
          "host_online": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "description": "Whether the session's host tunnel is live (status online and fresh within the host liveness TTL). `None` when the session has no `host_id` (CLI/local). Used only to choose what the open view shows when `runner_online` is `False` \u2014 host alive \u21d2 \"send a message to wake the runner\"; host dead \u21d2 \"reconnect / fork\". Never participates in the reachability decision.",
            "title": "Host Online"
          },
          "host_resumable": {
            "default": false,
            "description": "Whether this session is bound to a dormant managed host the server can wake in place (its provider sets `SandboxLauncher.can_resume`). The open view reads it only when `host_online` is `False`, to split a confirmed host-down into a recoverable \"asleep\" state (send a message \u2014 the relaunch path resumes the sandbox) versus the terminal `host_offline` dead-end (reconnect from your machine / fork). `False` for non-managed or non-resumable hosts.",
            "title": "Host Resumable",
            "type": "boolean"
          },
          "id": {
            "description": "Unique session identifier (also the underlying conversation ID), e.g. `\"conv_abc123\"`.",
            "title": "Id",
            "type": "string"
          },
          "inference_configured": {
            "default": false,
            "title": "Inference Configured",
            "type": "boolean"
          },
          "inference_error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Inference Error"
          },
          "items": {
            "description": "Committed conversation items in chronological order. Empty for a freshly created session.",
            "items": {
              "$ref": "#/components/schemas/ConversationItem"
            },
            "title": "Items",
            "type": "array"
          },
          "kind": {
            "default": "default",
            "title": "Kind",
            "type": "string"
          },
          "labels": {
            "additionalProperties": {
              "type": "string"
            },
            "description": "Session-scoped guardrails labels. Empty dict when no labels have been written.",
            "title": "Labels",
            "type": "object"
          },
          "last_task_error": {
            "anyOf": [
              {
                "additionalProperties": {
                  "type": "string"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Error details from the most recently failed task. Only present when `status == \"failed\"` and the task stored an error. Lets clients display the failure reason on historical load without relying on the transient `response.error` SSE event (which may have been emitted before the web client subscribed). Format mirrors the `RetryErrorDetail` SSE shape: `{\"code\": \"executor_error\", \"message\": \"...\"}`. A `runner_rejected_event` failure also carries `item_id`, the persisted item the runner refused, so a web client whose POST answer was lost can match the refusal to its own send. `None` in all other cases.",
            "title": "Last Task Error"
          },
          "last_total_tokens": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "Total token count (input + output) from the most recently completed task's `usage`, e.g. `45231`. `None` when no task has completed yet. Lets clients seed their context-ring on conversation resume without waiting for the next `response.completed` SSE event.",
            "title": "Last Total Tokens"
          },
          "llm_model": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "The model this session is actually on. When the harness has reported one (`reported_model`, written by `external_model_change`), that verbatim value serves here and is the only model value clients display; otherwise the bound agent spec's model, e.g. `\"anthropic/claude-sonnet-4-6\"`. `None` when neither exists.",
            "title": "Llm Model"
          },
          "mcp_startup": {
            "anyOf": [
              {
                "additionalProperties": {
                  "$ref": "#/components/schemas/McpServerStartup"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Mcp Startup"
          },
          "model_options": {
            "description": "Runner-owned model-picker options for native sessions. Claude supplies launch-time gateway aliases; Codex includes each model's supported reasoning efforts. Empty while unavailable.",
            "items": {
              "$ref": "#/components/schemas/NativeModelOption"
            },
            "title": "Model Options",
            "type": "array"
          },
          "model_override": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Per-session LLM model override, e.g. `\"claude-opus-4-7\"`. `None` means no override is active (the agent's `llm_model` applies). Set via `PATCH /v1/sessions/{id}` or the REPL's `/model` command; both write the same column so the web UI and the TUI stay in sync.",
            "title": "Model Override"
          },
          "parent_session_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "For sub-agent sessions, the parent conversation's id, e.g. `\"conv_parent987\"`. `None` for top-level sessions. Lets clients identify a session as a child and link back to its parent without an extra round-trip \u2014 the same conversation row exposes this via `parent_conversation_id` internally.",
            "title": "Parent Session Id"
          },
          "pending_elicitations": {
            "description": "Outstanding approval prompts on this session at the moment the snapshot was built \u2014 the original `response.elicitation_request` event dicts. Lets the UI render the ApprovalCard on cold load, since the live SSE stream has no replay and a prompt emitted before the user opened the chat would otherwise vanish. Empty list when no prompts are outstanding. Sourced from the Omnigent server's in-memory `omnigent.runtime.pending_elicitations` index.",
            "items": {
              "additionalProperties": true,
              "type": "object"
            },
            "title": "Pending Elicitations",
            "type": "array"
          },
          "pending_inputs": {
            "description": "Un-consumed web-composer user messages on native-terminal (claude-native / codex-native) sessions at snapshot time, each `{\"pending_id\", \"content\"}`. Native sessions don't persist a web message at POST time (the transcript forwarder is the single writer), so a client that posted then navigated away / rebound would lose its optimistic bubble; replaying these re-hydrates it. Empty list otherwise. Sourced from the in-memory `omnigent.runtime.pending_inputs` index.",
            "items": {
              "additionalProperties": true,
              "type": "object"
            },
            "title": "Pending Inputs",
            "type": "array"
          },
          "permission_level": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "The requesting user's numeric permission level on this session: `1` = read, `2` = edit, `3` = manage. `None` when permissions are disabled (single-user mode without a permission store).",
            "title": "Permission Level"
          },
          "project_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Project Id"
          },
          "reasoning_effort": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Per-session reasoning-effort hint. Accepted metadata values are `\"none\"`, `\"minimal\"`, `\"low\"`, `\"medium\"`, `\"high\"`, `\"xhigh\"`, and `\"max\"`. Provider-specific support is validated when a turn executes. `None` means use the agent default.",
            "title": "Reasoning Effort"
          },
          "root_conversation_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "The id of this session's spawn-tree root, e.g. `\"conv_root1\"`. Equals `id` for top-level sessions; for sub-agents it points at the top-level ancestor. Lets orchestration tools (e.g. `sys_session_close`) confirm a target shares the caller's spawn tree over the REST path. `None` only when the underlying row predates the `root_conversation_id` column (not expected post-migration).",
            "title": "Root Conversation Id"
          },
          "runner_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Runner currently bound to this session, e.g. `\"runner_abc123\"`. `None` until a client binds one via `PATCH /v1/sessions/{id}`.",
            "title": "Runner Id"
          },
          "runner_online": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "description": "Strict runner liveness \u2014 `True` iff a runner tunnel is currently registered for this session. This is the sole reachability signal: `True` means the client can chat normally. It does **not** fold in host-relaunch optimism (a dead runner on a live host reads `False` here, not `True`) \u2014 the open-session view pairs it with `host_online` to decide what to show. `None` when the server has no runner liveness lookup wired.",
            "title": "Runner Online"
          },
          "sandbox_status": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SandboxStatus"
              },
              {
                "type": "null"
              }
            ],
            "description": "Managed-sandbox launch progress while the session's background sandbox launch is in flight or has failed \u2014 see `SandboxStatus`. `None` for sessions without a managed launch and once the launch succeeds. Sourced from the Omnigent server's in-memory `_session_sandbox_status_cache` at snapshot build time, so a client opening the session mid-launch sees the current stage."
          },
          "share_workspace_files": {
            "default": false,
            "description": "Whether the owner opted into letting view-level collaborators browse the workspace (Files/Changes/GitHub surfaces). `False` by default \u2014 read grants share the conversation only. The web share dialog reads this to render the toggle, and the rail reads it to decide whether to mount the file surfaces for a view-only viewer.",
            "title": "Share Workspace Files",
            "type": "boolean"
          },
          "status": {
            "description": "Session lifecycle status. One of `\"idle\"` (no loop running), `\"running\"` (loop executing), `\"waiting\"` (loop parked on background work / sub-agents), or `\"failed\"` (terminal failure). Current read paths collapse `\"waiting\"` -> `\"running\"` before building this snapshot; the literal stays a superset of what the runtime can produce so a server that forwards the raw status never 500s on serialization.",
            "enum": [
              "idle",
              "running",
              "waiting",
              "failed"
            ],
            "title": "Status",
            "type": "string"
          },
          "sub_agent_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "For sub-agent sessions, the sub-agent type name within the parent's spec tree, e.g. `\"summarizer\"`. `None` for top-level sessions.",
            "title": "Sub Agent Name"
          },
          "subagent_routing_override": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Per-session subagent-routing switch, two-state: `\"on\"` routes subagent spawns, and `\"off\"` or `None` (unset) both leave them unrouted \u2014 the in-session \"Subagent routing\" row renders either as \"Default\". `None` on a row created before this became explicit inherits nothing. Stamped `\"on\"` at create for Smart Routing sessions; also set via `PATCH /v1/sessions/{id}`.",
            "title": "Subagent Routing Override"
          },
          "terminal_launch_args": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Pass-through CLI args the native terminal wrapper (claude / codex) was launched with, e.g. `[\"--dangerously-skip-permissions\"]`. `None` for non-native sessions or a native session launched with none. Lets the launcher reproduce the command on resume.",
            "title": "Terminal Launch Args"
          },
          "terminal_pending": {
            "default": false,
            "description": "`True` while the runner is auto-creating a terminal-first session's terminal (claude-native / codex-native), so the Web UI shows a spinner on the Terminal pill instead of a silent greyed-out button. Cleared to `False` once the terminal lands or auto-create fails; from then on the client relies purely on whether a terminal resource exists. Sourced from the Omnigent server's in-memory `_session_terminal_pending_cache` at snapshot build time, so a client connecting mid-spin-up still sees the spinner.",
            "title": "Terminal Pending",
            "type": "boolean"
          },
          "title": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional human-readable title, e.g. `\"debugging auth flow\"`. `None` when unset.",
            "title": "Title"
          },
          "todos": {
            "description": "Current native Plan items reported by a harness. Each has `content`, `status`, and `activeForm`. Persisted in conversation metadata; empty before the first report or after an explicit clear.",
            "items": {
              "additionalProperties": true,
              "type": "object"
            },
            "title": "Todos",
            "type": "array"
          },
          "total_cost_usd": {
            "anyOf": [
              {
                "format": "double",
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Cumulative LLM spend for this session in USD, e.g. `0.42`. `None` when the session is **unpriced** \u2014 no turn has been priced yet (the model is absent from the pricing catalog, or no usage has been recorded) \u2014 so clients render \"\u2014\" rather than a misleading `$0.00`. Server-computed (cache-aware for relay/codex, exact billing for claude-native), the same total the cost-budget policy gates on. Lets clients seed their cost indicator on resume without waiting for the next `session.usage` SSE event. Also `None` when `usage_included` is `False`.",
            "title": "Total Cost Usd"
          },
          "updated_at": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "Unix epoch timestamp of the last persisted session activity. Advances when conversation items are appended and on session metadata edits (rename, agent switch, archive); a mid-stall rename therefore resets the clock, so an orchestrator treating this as a pure item-append heartbeat should account for that. Can be compared across snapshots independently of lifecycle status.",
            "title": "Updated At"
          },
          "usage_by_model": {
            "anyOf": [
              {
                "additionalProperties": {
                  "$ref": "#/components/schemas/ModelUsage"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Per-model breakdown of the same subtree usage, keyed by the raw harness model id, e.g. `{\"claude-sonnet-4-6\": ModelUsage(input_tokens=12000, ...)}`. `None` when no per-model usage has been recorded (older sessions recorded before this field existed, or before the first turn). Lets the UI show which models a session spent its tokens / budget on. Also `None` when `usage_included` is `False`.",
            "title": "Usage By Model"
          },
          "usage_included": {
            "default": true,
            "description": "`False` when the caller skipped usage aggregation with `include_usage=false`. Both usage fields are then unknown, not zero or this session's own-only spend. Display clients can load them with a separate `GET /v1/sessions/{id}` using `include_usage=true`, `include_items=false`, `include_liveness=false`, and `refresh_state=false`.",
            "title": "Usage Included",
            "type": "boolean"
          },
          "workspace": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Absolute path on disk where the runner cd's, e.g. `\"/Users/corey/universe/src/foo\"`. Set when the session was bound to a host workspace at create-time, or when the CLI captured `os.getcwd()` at session-create. Always `None` when not yet validated against a host. When a git worktree was created for the session, this is the worktree directory path.",
            "title": "Workspace"
          }
        },
        "required": [
          "id",
          "agent_id",
          "status",
          "created_at"
        ],
        "title": "SessionResponse",
        "type": "object"
      },
      "SessionSandboxStatusEvent": {
        "description": "Managed-sandbox launch progress for a `host_type=\"managed\"` session.\n\nA managed create returns before its sandbox exists; the Omnigent\nserver emits this event as the background launch pipeline advances\nso the Web UI can show live provisioning progress on the session\npage instead of a silent dead chat: sandbox provision \u2192 repository\nclone \u2192 host startup \u2192 runner connect \u2192 ready, or a terminal\nfailure with the reason.",
        "properties": {
          "conversation_id": {
            "description": "Session identifier, e.g. `\"conv_abc123\"`.",
            "title": "Conversation Id",
            "type": "string"
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Failure detail when `stage == \"failed\"`, e.g. `\"managed sandbox launch failed: spend limit reached\"`. `None` otherwise. Category: **transient** (SSE-only). On reconnect, clients seed the progress indicator from the session snapshot's `sandbox_status` field, which is populated by `_session_sandbox_status_cache` at snapshot build time.",
            "title": "Error"
          },
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "stage": {
            "description": "The launch stage just entered, e.g. `\"provisioning\"` \u2014 see `SandboxStatus` for the full pipeline order.",
            "enum": [
              "provisioning",
              "cloning",
              "starting",
              "connecting",
              "ready",
              "failed"
            ],
            "title": "Stage",
            "type": "string"
          },
          "type": {
            "const": "session.sandbox_status",
            "description": "Always `\"session.sandbox_status\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "conversation_id",
          "stage"
        ],
        "title": "SessionSandboxStatusEvent",
        "type": "object"
      },
      "SessionStatusEvent": {
        "description": "Session lifecycle status transition.\n\nEmitted by the runtime / session route handler at every\ntransition between `launching` / `running` / `waiting` /\n`idle` / `failed`. Wire shape is\nFLAT (not enveloped): `{\"type\": \"session.status\", \"conversation_id\": \"...\", \"status\": \"...\", \"sequence_number\": null}`.\n\nThe `waiting` value is emitted by the runtime's parent agent\nloop when it parks on the `async_work_complete` drain\n(`_drain_async_completions(block_for_one=True)` in\n`omnigent/runtime/workflow.py`) \u2014 i.e. while the parent\nturn is suspended waiting for background tools or sub-agents\nto complete. Per the session-rearchitecture spec \u00a73\n(\"Event types and direction\"), `waiting` is the\nsession-status companion of the spec's `turn.waiting`\ntransient \u2014 clients should render the session as actively\nblocked-on-async-work, distinct from `running`. When the\ndrain wakes (a child completed), the runtime emits a follow-up\n`running` to resume.",
        "properties": {
          "background_task_count": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Background shells still running at this edge (claude-native `Stop` hook). `None` when the edge carries no information (leave the sticky tally untouched); `0` clears it.",
            "title": "Background Task Count"
          },
          "background_tasks": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/BackgroundTaskInfo"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Per-shell detail backing that tally, so the UI can name each running shell. `None` when the edge reports no detail (an older runner may send only the count).",
            "title": "Background Tasks"
          },
          "blocked_on": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Short human phrase naming what a still-`running` session is parked on, e.g. `\"permission prompt\"` or `\"dialog open\"`. Set by terminal-backed integrations whose agent can block on a dialog the web UI does not mirror, so the client can say *why* nothing is moving instead of showing a bare spinner. `None` whenever the session is not parked. Unrelated to the `waiting` status above, which means the turn has ended and only background work remains. Category: **transient** (SSE-only). Status is rederived on reconnect from the cached last-relayed turn lifecycle event or by re-querying the runner; not persisted by the runtime.",
            "title": "Blocked On"
          },
          "conversation_id": {
            "description": "The conversation/session identifier whose status changed, e.g. `\"conv_abc123\"`.",
            "title": "Conversation Id",
            "type": "string"
          },
          "error": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ErrorDetail"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Machine-readable failure detail, present only when `status == \"failed\"`. Carries the message the runner attached when a turn died \u2014 most importantly a SETUP-phase failure (spec resolution, spawn-env build) that ends the turn before any `response.failed` event is emitted. `None` for every non-failed transition. Clients render `error.message` as the terminal error line; without it a setup failure shows as a silent end."
          },
          "response_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional active response id for terminal-backed integrations, e.g. `\"codex_turn_abc123\"`. Clients use it to associate coarse session status edges with the assistant bubble they describe. `None` for ordinary in-process runtime edges.",
            "title": "Response Id"
          },
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "status": {
            "description": "New session status. `\"launching\"` (session or child task created, but no concrete harness start observed), `\"idle\"` (no loop running), `\"running\"` (loop executing), `\"waiting\"` (parent turn parked on the async-work drain), or `\"failed\"` (terminal failure).",
            "enum": [
              "idle",
              "launching",
              "running",
              "waiting",
              "failed"
            ],
            "title": "Status",
            "type": "string"
          },
          "type": {
            "const": "session.status",
            "description": "Always `\"session.status\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "conversation_id",
          "status"
        ],
        "title": "SessionStatusEvent",
        "type": "object"
      },
      "SessionSupersededEvent": {
        "description": "This conversation was superseded by another and clients should\nfollow to it.\n\nEmitted by `_publish_session_superseded` in\n`omnigent/server/routes/sessions.py` when the claude-native\nforwarder rotates a session away on a Claude `/clear` (the old\nconversation keeps its history but the live terminal moves to a\nfresh conversation \u2014 see `_post_clear_supersession` in\n`omnigent/claude_native_forwarder.py`). A client actively viewing\nthe superseded conversation auto-redirects to `target_conversation_id`.\n\nCategory: **transient** (SSE-only), live-only by design. There is no\nSSE replay: a client that connects after the rotation does not get\nthis event. The durable counterpart is the persisted notice message\nappended to the old conversation (a `message` item linking to the\nnew conversation), which a reloading client renders instead of being\nforce-redirected.\n\nThe wire shape is FLAT (not enveloped):\n`{\"type\": \"session.superseded\", \"conversation_id\": <old>, \"target_conversation_id\": <new>, \"reason\": \"clear\"}`.",
        "properties": {
          "conversation_id": {
            "description": "The superseded (old) conversation id this event rides the stream of, e.g. `\"conv_old\"`.",
            "title": "Conversation Id",
            "type": "string"
          },
          "reason": {
            "const": "clear",
            "default": "clear",
            "description": "Why the session was superseded. Currently always `\"clear\"` (a Claude Code `/clear`); kept as a field so the client can branch on future supersession causes.",
            "title": "Reason",
            "type": "string"
          },
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "target_conversation_id": {
            "description": "The conversation to follow to, e.g. `\"conv_new\"`.",
            "title": "Target Conversation Id",
            "type": "string"
          },
          "type": {
            "const": "session.superseded",
            "description": "Always `\"session.superseded\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "conversation_id",
          "target_conversation_id"
        ],
        "title": "SessionSupersededEvent",
        "type": "object"
      },
      "SessionTerminalActivityEvent": {
        "description": "A terminal's pane produced output (runner-determined activity pulse).\n\nPowers the web \"active\" badge for any terminal without a client PTY\nattach \u2014 the runner's per-terminal pane watcher emits this when the\npane content changes. Transient (a live pulse; not persisted, not in\nthe connect snapshot).",
        "properties": {
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "session_id": {
            "description": "Owning session/conversation id.",
            "title": "Session Id",
            "type": "string"
          },
          "terminal_id": {
            "description": "Opaque terminal resource id, e.g. `\"terminal_zsh_s1\"`.",
            "title": "Terminal Id",
            "type": "string"
          },
          "type": {
            "const": "session.terminal.activity",
            "description": "Always `\"session.terminal.activity\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "session_id",
          "terminal_id"
        ],
        "title": "SessionTerminalActivityEvent",
        "type": "object"
      },
      "SessionTerminalPendingEvent": {
        "description": "Terminal spin-up status for a terminal-first session.\n\nTwo sources emit this event:\n\n1. The Omnigent server at `POST /v1/sessions` for host-launched\n   terminal-first sessions \u2014 the earliest possible point, before\n   the runner even starts, so the spinner appears immediately on\n   session create rather than after the runner boots.\n2. The Omnigent relay when the runner's `session.terminal_pending` frame\n   arrives \u2014 covers non-host-launched sessions (e.g. server-dispatched\n   sub-agents) and carries the authoritative `pending=False` clear\n   emitted by the runner's `finally` block.\n\nTogether they allow web to show a spinner on the Terminal pill\nwhile the backend boots the terminal instead of a silent greyed-out\nbutton, and to distinguish \"still starting up\" from \"no terminal\"\n(killed or never created).",
        "properties": {
          "conversation_id": {
            "description": "Session identifier, e.g. `\"conv_abc123\"`.",
            "title": "Conversation Id",
            "type": "string"
          },
          "pending": {
            "description": "`True` while the terminal is being created; `False` once it lands or auto-create fails. Category: **transient** (SSE-only). On reconnect, clients seed the spinner from the session snapshot's `terminal_pending` field, which is populated by `_session_terminal_pending_cache` at snapshot build time.",
            "title": "Pending",
            "type": "boolean"
          },
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "type": {
            "const": "session.terminal_pending",
            "description": "Always `\"session.terminal_pending\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "conversation_id",
          "pending"
        ],
        "title": "SessionTerminalPendingEvent",
        "type": "object"
      },
      "SessionTitleEvent": {
        "description": "Session-title update from a terminal-backed integration.\n\nEmitted after an `external_session_title` POST from the\n`omnigent claude` transcript forwarder when the operator renames\nthe session inside the Claude Code pane (`/rename`). Lets the web\nsession list show the new name without a reload.",
        "properties": {
          "conversation_id": {
            "description": "Session identifier, e.g. `\"conv_abc123\"`.",
            "title": "Conversation Id",
            "type": "string"
          },
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "title": {
            "description": "Title the session is now on, e.g. `\"auth-refactor\"`. Category: **transient** (SSE-only). The server also writes `title` on the conversation, so on reconnect clients restore the name from the session snapshot rather than from a replayed event.",
            "title": "Title",
            "type": "string"
          },
          "type": {
            "const": "session.title",
            "description": "Always `\"session.title\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "conversation_id",
          "title"
        ],
        "title": "SessionTitleEvent",
        "type": "object"
      },
      "SessionTodosEvent": {
        "description": "Plan/TODO update from a native terminal-backed session.\n\nEmitted after an `external_session_todos` POST from a native\nharness forwarder, which captures structured Plan updates from\nClaude or Codex and forwards them to the Omnigent server. Lets web\nrender a live todo panel in the right column without polling.",
        "properties": {
          "conversation_id": {
            "description": "Session identifier, e.g. `\"conv_abc123\"`.",
            "title": "Conversation Id",
            "type": "string"
          },
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "todos": {
            "description": "Current native Plan/TODO items from a harness. Each entry is a raw dict with `content` (str), `status` (`\"pending\"` | `\"in_progress\"` | `\"completed\"`), and `activeForm` (str, display activity) keys, e.g. `[{\"content\": \"Fix the bug\", \"status\": \"in_progress\", \"activeForm\": \"Fixing the bug\"}]`. Category: **transient** (SSE-only). On reconnect, clients seed the panel from the session snapshot's `todos` field, which is restored from persisted metadata at snapshot build time.",
            "items": {
              "additionalProperties": true,
              "type": "object"
            },
            "title": "Todos",
            "type": "array"
          },
          "type": {
            "const": "session.todos",
            "description": "Always `\"session.todos\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "conversation_id",
          "todos"
        ],
        "title": "SessionTodosEvent",
        "type": "object"
      },
      "SessionUsage": {
        "description": "One session's rolled-up LLM spend for the `GET /v1/usage` report.\n\n`cost_usd` is the subtree total \u2014 the session plus every sub-agent it\nspawned \u2014 read from `session_usage` via\n`omnigent.runtime.policies.builder.load_session_usage`. It is the\nauthoritative session figure (the same value the web session sidebar\nshows as \"Session cost\" and the daily rollup records).\n\n`models` is the per-model cost breakdown, mirroring the web session\nsidebar's per-model list. Deliberately **not guaranteed to sum to\n`cost_usd`**: native harnesses report a single cumulative session\ntotal and the server attributes it to the currently-active model, so on\na session that switched models mid-run each model's bucket is a snapshot\nof the running total rather than that model's own spend. The header\n`cost_usd` stays authoritative; the per-model values are shown\nfaithfully as recorded (same convention as the web UI).",
        "properties": {
          "agent_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Agent Name"
          },
          "cost_usd": {
            "default": 0.0,
            "description": "Authoritative cumulative USD spend for this session's subtree.",
            "format": "double",
            "title": "Cost Usd",
            "type": "number"
          },
          "created_at": {
            "description": "Unix epoch seconds of creation.",
            "format": "int64",
            "title": "Created At",
            "type": "integer"
          },
          "harness": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Harness"
          },
          "id": {
            "description": "Session/conversation identifier, e.g. `\"conv_abc123\"`.",
            "title": "Id",
            "type": "string"
          },
          "llm_model": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Llm Model"
          },
          "models": {
            "additionalProperties": {
              "format": "double",
              "type": "number"
            },
            "description": "Per-model recorded cost, keyed by the raw harness model id (e.g. `{\"claude-opus-4-8\": 14.03}`). Empty when no per-model cost was recorded. May not sum to `cost_usd` (see above).",
            "title": "Models",
            "type": "object"
          },
          "other_harnesses": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Other Harnesses"
          },
          "title": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional human-readable title.",
            "title": "Title"
          },
          "updated_at": {
            "description": "Unix epoch seconds of last activity.",
            "format": "int64",
            "title": "Updated At",
            "type": "integer"
          }
        },
        "required": [
          "id",
          "created_at",
          "updated_at"
        ],
        "title": "SessionUsage",
        "type": "object"
      },
      "SessionUsageEvent": {
        "description": "Token-usage update from a terminal-backed integration.\n\nEmitted after an `external_session_usage` POST from an\nout-of-AP runtime (e.g. the `omnigent claude` transcript\nforwarder). Either field may be absent; clients should leave\ncached values untouched for missing fields.",
        "properties": {
          "context_tokens": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "`input + cache_creation + cache_read` from the latest assistant `message.usage`. `None` on a window-only broadcast.",
            "title": "Context Tokens"
          },
          "context_window": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Resolved window in tokens (e.g. 200_000 normally, 1_000_000 with `opus[1m]` / `sonnet[1m]`). `None` on a tokens-only broadcast.",
            "title": "Context Window"
          },
          "conversation_id": {
            "description": "Session identifier.",
            "title": "Conversation Id",
            "type": "string"
          },
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "total_cost_usd": {
            "anyOf": [
              {
                "format": "double",
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Cumulative session spend in USD after this update, e.g. `0.42` \u2014 the server-computed total the cost-budget policy gates on. Present **only when the session is priced**; omitted (`None`, stripped by `exclude_none`) when unpriced or on a broadcast that carries no cost change, so the client keeps its prior value (the snapshot seeds the initial \"\u2014\" for an unpriced session). Once a session is priced the total only grows, so it never reverts to unpriced.",
            "title": "Total Cost Usd"
          },
          "type": {
            "const": "session.usage",
            "description": "Always `\"session.usage\"`.",
            "title": "Type",
            "type": "string"
          },
          "usage_by_model": {
            "anyOf": [
              {
                "additionalProperties": {
                  "$ref": "#/components/schemas/ModelUsage"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Per-model breakdown of the same subtree usage after this update, keyed by raw harness model id, e.g. `{\"claude-sonnet-4-6\": ModelUsage(input_tokens=12000, ...)}`. `None` (stripped by `exclude_none`) on a broadcast that carries no per-model change, so the client keeps its cached map. Category: **transient** (SSE-only). On reconnect, clients seed the ring from the session snapshot's `last_total_tokens` and `context_window`, the cost indicator from `total_cost_usd`, and the per-model token breakdown from `usage_by_model`.",
            "title": "Usage By Model"
          }
        },
        "required": [
          "type",
          "conversation_id"
        ],
        "title": "SessionUsageEvent",
        "type": "object"
      },
      "SetCodexGoalRequest": {
        "additionalProperties": false,
        "description": "Request body for `PUT /v1/sessions/{id}/codex_goal`.",
        "properties": {
          "objective": {
            "description": "Goal objective text, e.g. `\"Finish the migration and keep tests green\"`. Must be non-empty after trimming and no longer than 4000 characters, matching Codex app-server's goal contract.",
            "maxLength": 4000,
            "minLength": 1,
            "title": "Objective",
            "type": "string"
          },
          "status": {
            "anyOf": [
              {
                "enum": [
                  "active",
                  "paused"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional user-selected goal status. `\"active\"` starts or resumes the goal, and `\"paused\"` stores it paused. Omit this field to preserve Codex's current lifecycle state.",
            "title": "Status"
          },
          "token_budget": {
            "anyOf": [
              {
                "exclusiveMinimum": 0.0,
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional positive token budget, e.g. `40000`. Explicit JSON `null` clears the Codex goal budget; omitting the field leaves it absent from the forwarded request.",
            "title": "Token Budget"
          }
        },
        "required": [
          "objective"
        ],
        "title": "SetCodexGoalRequest",
        "type": "object"
      },
      "SetSharingRequest": {
        "description": "Body for `PUT /v1/sharing`.\n\nEvery field is optional so an admin can update each setting\nindependently; at least one must be present.",
        "properties": {
          "default_public_sessions": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Default Public Sessions"
          },
          "public_sharing": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Public Sharing"
          },
          "sharing_mode": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Sharing Mode"
          }
        },
        "title": "SetSharingRequest",
        "type": "object"
      },
      "SkillContentResponse": {
        "properties": {
          "content": {
            "maxLength": 262144,
            "title": "Content",
            "type": "string"
          },
          "description": {
            "description": "Skill description, capped at 8192 characters.",
            "maxLength": 8192,
            "title": "Description",
            "type": "string"
          },
          "name": {
            "maxLength": 1024,
            "title": "Name",
            "type": "string"
          },
          "truncated": {
            "description": "Whether the SKILL.md body exceeded the 256 KiB UTF-8 limit.",
            "title": "Truncated",
            "type": "boolean"
          }
        },
        "required": [
          "name",
          "description",
          "content",
          "truncated"
        ],
        "title": "SkillContentResponse",
        "type": "object"
      },
      "SkillSummary": {
        "description": "Safe subset of a discovered skill for API exposure.\n\nSurfaces the skill name and one-line description so clients\n(e.g. the web composer's slash-command menu) can list which\nskills the session has access to. The full skill `content`\nis intentionally omitted \u2014 it's only loaded server-side when\nthe harness invokes the skill, and it can be large.",
        "properties": {
          "description": {
            "description": "One-line summary from the SKILL.md frontmatter, e.g. `\"Triage open GitHub issues in the repo.\"`.",
            "title": "Description",
            "type": "string"
          },
          "name": {
            "description": "Skill identifier as parsed from the SKILL.md frontmatter, e.g. `\"triage-issues\"`. Lowercase kebab-case.",
            "title": "Name",
            "type": "string"
          }
        },
        "required": [
          "name",
          "description"
        ],
        "title": "SkillSummary",
        "type": "object"
      },
      "SkillsResponse": {
        "description": "User-invocable skill metadata discovered on a host.",
        "properties": {
          "skills": {
            "items": {
              "$ref": "#/components/schemas/SkillSummary"
            },
            "title": "Skills",
            "type": "array"
          }
        },
        "required": [
          "skills"
        ],
        "title": "SkillsResponse",
        "type": "object"
      },
      "SlashCommandData": {
        "description": "Data payload for a slash-command invocation observed in a\nharness transcript (today: Claude Code's embedded TUI).\n\nListed in `NON_CONTENT_ITEM_TYPES` so the agent loop's\nhistory filter skips it \u2014 a downstream LLM never sees this as a\nphantom tool call. Field names mirror `function_call` so the\nweb renderer can reuse the tool-card layout.\n\n**Parameters**\n\n- `agent` \u2014 Harness/agent name, e.g. `\"claude-native-ui\"`. Serialized as `\"model\"` for parity with other items.",
        "properties": {
          "arguments": {
            "description": "Raw `<command-args>` text. Empty when none.",
            "title": "Arguments",
            "type": "string"
          },
          "kind": {
            "default": "skill",
            "description": "`\"skill\"` for plugin/Skill invocations, `\"command\"` for surfaced CLI built-ins (`/effort`, `/clear`, `/compact`, `/model`, `/ultrareview`). The web renderer uses this to pick the prefix label and icon. Defaults to `\"skill\"` so persisted items predating this field deserialize without backfill.",
            "enum": [
              "skill",
              "command"
            ],
            "title": "Kind",
            "type": "string"
          },
          "model": {
            "title": "Model",
            "type": "string"
          },
          "name": {
            "description": "Command name with leading `/` stripped, e.g. `\"dev-productivity:simplify\"`.",
            "title": "Name",
            "type": "string"
          },
          "output": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "`<local-command-stdout>` text when present, else `None` (the common case \u2014 Skills act via the next assistant turn, not stdout).",
            "title": "Output"
          }
        },
        "required": [
          "model",
          "name",
          "arguments"
        ],
        "title": "SlashCommandData",
        "type": "object"
      },
      "SmartRoutingSourcesInfo": {
        "properties": {
          "external": {
            "title": "External",
            "type": "boolean"
          },
          "oss": {
            "title": "Oss",
            "type": "boolean"
          }
        },
        "required": [
          "external",
          "oss"
        ],
        "title": "SmartRoutingSourcesInfo",
        "type": "object"
      },
      "StoreHarnessCredentialRequest": {
        "description": "Request body for `POST /v1/hosts/{id}/harnesses/{harness}/credential`.\n\nCarries the credential in the body (never the URL). The secret field is\noptional so the `adopt` kind \u2014 which references an existing host env var\nby name rather than sending a value \u2014 can omit it.",
        "properties": {
          "base_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "The gateway base URL, required for `kind=\"gateway\"`.",
            "title": "Base Url"
          },
          "default_model": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional family default model id to pin.",
            "title": "Default Model"
          },
          "env_var": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "For `kind=\"adopt\"`, the host env var to reference.",
            "title": "Env Var"
          },
          "kind": {
            "description": "`\"key\"` (a vendor API key), `\"gateway\"` (a compatible proxy at `base_url`), or `\"adopt\"` (reference host env `env_var`).",
            "title": "Kind",
            "type": "string"
          },
          "secret": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "The API key / gateway token for `key` / `gateway`; `None` for `adopt`.",
            "title": "Secret"
          },
          "wire_api": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional OpenAI wire protocol (`\"chat\"` / `\"responses\"`).",
            "title": "Wire Api"
          }
        },
        "required": [
          "kind"
        ],
        "title": "StoreHarnessCredentialRequest",
        "type": "object"
      },
      "TerminalCommandData": {
        "description": "Data payload for a runner-side terminal command (`!cmd`) observed\nin a harness transcript (today: Claude Code's embedded TUI).\n\nListed in `NON_CONTENT_ITEM_TYPES` so the agent loop never\ninjects this as phantom content into the LLM's message history.\n\nClaude Code writes two sibling transcript records per `!cmd`\ninvocation: one `<bash-input>` record and one combined\n`<bash-stdout>`/`<bash-stderr>` record. Each maps to one\n`terminal_command` item with `kind=\"input\"` or\n`kind=\"output\"` respectively.",
        "properties": {
          "input": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "The raw command string, e.g. `\"pwd\"`. Present when `kind=\"input\"`, `None` otherwise.",
            "title": "Input"
          },
          "kind": {
            "description": "`\"input\"` for the command text, `\"output\"` for the combined stdout/stderr result.",
            "enum": [
              "input",
              "output"
            ],
            "title": "Kind",
            "type": "string"
          },
          "stderr": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Captured stderr text. Present when `kind=\"output\"`, `None` otherwise.",
            "title": "Stderr"
          },
          "stdout": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Captured stdout text. Present when `kind=\"output\"`, `None` otherwise.",
            "title": "Stdout"
          }
        },
        "required": [
          "kind"
        ],
        "title": "TerminalCommandData",
        "type": "object"
      },
      "ToolOutputDeltaEvent": {
        "description": "Incremental output from an in-progress function call.",
        "properties": {
          "call_id": {
            "description": "Function-call correlation id.",
            "title": "Call Id",
            "type": "string"
          },
          "delta": {
            "description": "Command stdout/stderr fragment.",
            "title": "Delta",
            "type": "string"
          },
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "type": {
            "const": "response.function_call_output.delta",
            "description": "Always `\"response.function_call_output.delta\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "call_id",
          "delta"
        ],
        "title": "ToolOutputDeltaEvent",
        "type": "object"
      },
      "TurnCancelledEvent": {
        "description": "Emitted when a turn is interrupted by the user or system.",
        "properties": {
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "session_id": {
            "description": "Session/conversation identifier, e.g. `\"conv_abc123\"`.",
            "title": "Session Id",
            "type": "string"
          },
          "type": {
            "const": "turn.cancelled",
            "description": "Fixed literal `\"turn.cancelled\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "session_id"
        ],
        "title": "TurnCancelledEvent",
        "type": "object"
      },
      "TurnCompletedEvent": {
        "description": "Emitted when a turn finishes successfully with no pending work.",
        "properties": {
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "session_id": {
            "description": "Session/conversation identifier, e.g. `\"conv_abc123\"`.",
            "title": "Session Id",
            "type": "string"
          },
          "type": {
            "const": "turn.completed",
            "description": "Fixed literal `\"turn.completed\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "session_id"
        ],
        "title": "TurnCompletedEvent",
        "type": "object"
      },
      "TurnFailedEvent": {
        "description": "Emitted when a turn fails due to an LLM error, timeout, or crash.",
        "properties": {
          "error": {
            "additionalProperties": true,
            "description": "Error details, e.g. `{\"message\": \"LLM timeout\", \"type\": \"TimeoutError\"}`.",
            "title": "Error",
            "type": "object"
          },
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "session_id": {
            "description": "Session/conversation identifier, e.g. `\"conv_abc123\"`.",
            "title": "Session Id",
            "type": "string"
          },
          "type": {
            "const": "turn.failed",
            "description": "Fixed literal `\"turn.failed\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "session_id"
        ],
        "title": "TurnFailedEvent",
        "type": "object"
      },
      "TurnStartedEvent": {
        "description": "Emitted when the runner starts a new turn for a session.",
        "properties": {
          "sequence_number": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Number"
          },
          "session_id": {
            "description": "Session/conversation identifier, e.g. `\"conv_abc123\"`.",
            "title": "Session Id",
            "type": "string"
          },
          "type": {
            "const": "turn.started",
            "description": "Fixed literal `\"turn.started\"`.",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "session_id"
        ],
        "title": "TurnStartedEvent",
        "type": "object"
      },
      "UpdateCodexGoalStatusRequest": {
        "additionalProperties": false,
        "description": "Request body for `PATCH /v1/sessions/{id}/codex_goal/status`.\n\nCodex app-server represents pause/resume as `thread/goal/set` status\nupdates. Omnigent exposes the two user-driven transitions explicitly:\n`\"paused\"` pauses an active goal, and `\"active\"` resumes a paused,\nblocked, or usage-limited goal.",
        "properties": {
          "status": {
            "description": "Target Codex goal status, either `\"paused\"` or `\"active\"`.",
            "enum": [
              "active",
              "paused"
            ],
            "title": "Status",
            "type": "string"
          }
        },
        "required": [
          "status"
        ],
        "title": "UpdateCodexGoalStatusRequest",
        "type": "object"
      },
      "UpdateCommentRequest": {
        "description": "Request body for `PATCH /sessions/{id}/comments/{comment_id}`.",
        "properties": {
          "body": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "New comment body. `None` leaves it unchanged.",
            "title": "Body"
          },
          "status": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "New status, e.g. `\"addressed\"`. `None` leaves it unchanged.",
            "title": "Status"
          }
        },
        "title": "UpdateCommentRequest",
        "type": "object"
      },
      "UpdateDefaultPolicyRequest": {
        "additionalProperties": false,
        "description": "Request body for `PATCH /v1/policies/{policy_id}`.\n\nAll fields are optional; `None` fields are left unchanged.\nUnknown fields (including `type`, which is immutable) are\nrejected with `422`.",
        "properties": {
          "enabled": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "description": "New enabled flag. `None` leaves it unchanged.",
            "title": "Enabled"
          },
          "handler": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "New handler path or URL. `None` leaves it unchanged.",
            "title": "Handler"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "New policy name. `None` leaves it unchanged.",
            "title": "Name"
          }
        },
        "title": "UpdateDefaultPolicyRequest",
        "type": "object"
      },
      "UpdateProjectRequest": {
        "additionalProperties": false,
        "description": "Request body for `PATCH /v1/projects/{project_id}`.\n\nAll fields optional; `None` leaves a field unchanged.",
        "properties": {
          "config": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "New config object to replace the stored one. `None` leaves it unchanged; an empty object `{}` clears the stored defaults.",
            "title": "Config"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "New project name. `None` leaves it unchanged; otherwise trimmed, non-empty, at most 100 characters.",
            "title": "Name"
          }
        },
        "title": "UpdateProjectRequest",
        "type": "object"
      },
      "UpdateSessionPolicyRequest": {
        "additionalProperties": false,
        "description": "Request body for `PATCH /v1/sessions/{session_id}/policies/{policy_id}`.\n\nAll fields are optional; `None` fields are left unchanged.\nUnknown fields (including `type`, which is immutable) are\nrejected with `422`.",
        "properties": {
          "enabled": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "description": "New enabled flag. `None` leaves it unchanged.",
            "title": "Enabled"
          },
          "handler": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "New handler path or URL. `None` leaves it unchanged.",
            "title": "Handler"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "New policy name. `None` leaves it unchanged.",
            "title": "Name"
          }
        },
        "title": "UpdateSessionPolicyRequest",
        "type": "object"
      },
      "UpdateSessionRequest": {
        "additionalProperties": false,
        "description": "Request body for `PATCH /v1/sessions/{id}`.\n\nThe Alpha runner-state pivot makes this endpoint the mutable\nsession affinity primitive when `runner_id` is provided. The\nserver validates that the runner is online, then replaces\n`conversations.runner_id`. Existing session metadata updates\nremain supported for clients that update title, labels, or\nreasoning effort through the sessions API.",
        "properties": {
          "approval_mode": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Codex-native approval mode to switch a running session to, one of `\"ask-for-approval\"`, `\"approve-for-me\"`, `\"full-access\"`, `\"read-only\"` \u2014 Codex's own `/permissions` presets (the set is codex-version-dependent, so an older build may not offer every one). Only valid for sessions stamped with the codex-native wrapper label. The runner applies it by driving Codex's `/permissions` popup and confirms the switch echoed before returning, so a failure to reach the mode surfaces as an error. The confirmed mode is stored on the read-back label only (Codex owns the durable approval state), so it is not written to `terminal_launch_args`. Omitted leaves unchanged.",
            "title": "Approval Mode"
          },
          "archived": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "description": "New archived state. `True` archives (hides the session from the default sidebar listing), `False` unarchives, `None` leaves unchanged. Owner-only (unlike `title`, which needs only edit access).",
            "title": "Archived"
          },
          "collaboration_mode": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Codex-native collaboration-mode string. `\"plan\"` enters Plan mode and `\"default\"` returns to Default mode for subsequent Codex turns. Only valid for sessions stamped with the codex-native wrapper label. Omitted leaves unchanged.",
            "title": "Collaboration Mode"
          },
          "cost_control_mode_override": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Per-session cost-control switch: `\"on\"` activates the spec's configured cost-control mode, `\"off\"` disables cost control for this session. Explicit JSON `null` clears the override back to the spec default; omitting the field leaves it unchanged (`\"off\"` is a real value here, so the field's *presence* \u2014 not a clear alias \u2014 is the clear signal, unlike `model_override`).",
            "title": "Cost Control Mode Override"
          },
          "delete_worktree": {
            "default": false,
            "description": "With `archived=True`, also remove the session's server-created git worktree directory once the archive teardown runs (after the Undo grace). The branch is kept. Ignored for sessions with no worktree; rejected (400) without `archived=True`.",
            "title": "Delete Worktree",
            "type": "boolean"
          },
          "external_session_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Runtime-native session id captured by a wrapper bridge (e.g. Claude Code's session uuid for `omnigent claude` sessions). Idempotent on same-value writes; the server rejects attempts to overwrite an already-set different value with `invalid_input` to surface programmer errors. `None` leaves unchanged.",
            "title": "External Session Id"
          },
          "labels": {
            "anyOf": [
              {
                "additionalProperties": {
                  "type": "string"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Guardrails labels to upsert. Merges with existing labels; keys not present are left untouched.",
            "title": "Labels"
          },
          "model_override": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Per-session LLM model override, e.g. `\"claude-opus-4-7\"`. The value is forwarded as-is to the executor at turn start; the server does not enumerate valid models. Clear aliases such as `\"default\"`, `\"off\"`, or `\"reset\"` remove the override (matching the REPL's `/model` semantics). `None` leaves unchanged.",
            "title": "Model Override"
          },
          "permission_mode": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Claude-native permission mode to switch a running session to, e.g. `\"auto\"`. Only the modes Claude Code's shift+tab cycle can reach are accepted (`default`, `acceptEdits`, `plan`, `auto`) \u2014 `dontAsk` and `bypassPermissions` are launch-only. Only valid for sessions stamped with the claude-native wrapper label. Unlike the other fields here the switch is applied by the live TUI, so a failure to reach the mode is surfaced as an error rather than persisted. Omitted leaves unchanged.",
            "title": "Permission Mode"
          },
          "project_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "File this session into a first-class project (see `designs/PROJECTS_PRD.md`). A non-empty id moves the session into that project; the empty string `\"\"` unfiles it. **Omitting** the field leaves membership unchanged; an explicit `null` is rejected (400) so it can't silently unfile. Owner-only: because projects are owner-private, only the session owner may file it, and only into a project they own \u2014 the server verifies both. Independent of the legacy `omni_project` label, which is set via `labels`.",
            "title": "Project Id"
          },
          "reasoning_effort": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Per-session reasoning-effort hint. Accepted metadata values are `\"none\"`, `\"minimal\"`, `\"low\"`, `\"medium\"`, `\"high\"`, `\"xhigh\"`, and `\"max\"`. Provider-specific support is validated when a turn executes. Clear aliases such as `\"default\"` remove the session override. `None` leaves unchanged.",
            "title": "Reasoning Effort"
          },
          "runner_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Identifier of a registered runner, e.g. `\"runner_abc123\"`. `None` leaves runner binding unchanged.",
            "title": "Runner Id"
          },
          "share_workspace_files": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "description": "Opt-in that lets people with *view* (read-only) access browse the session's workspace files. `True` turns sharing on, `False` turns it off (back to edit-only, the default), `None` leaves it unchanged. Manage-gated \u2014 it sits with the grant/revoke and public-access controls that decide who can see the session. Never widens absolute-path browsing, which stays owner-only.",
            "title": "Share Workspace Files"
          },
          "silent": {
            "default": false,
            "description": "When `True`, persist metadata changes but skip the runner-side side effects \u2014 specifically the native `/effort` / `/model` / Codex collaboration-mode forwards into the live runtime. Used by automatic bind-time handoffs (web's sticky-pref apply on session switch, the REPL's pre-create `/model` snapshot) where injecting a visible slash command into a freshly-spawned pane would render as an unexpected \"Command model X\" item before the user has sent anything. Default `False` preserves the user-driven picker / `/model` behaviour where the live forward IS the desired feedback.",
            "title": "Silent",
            "type": "boolean"
          },
          "subagent_routing_override": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Per-session subagent-routing switch: `\"on\"` routes subagent spawns, `\"off\"` leaves them unrouted. Explicit JSON `null` clears the override, which lands the session on Default (the same behavior as `\"off\"` \u2014 nothing is inherited); omitting the field leaves it unchanged (same presence-is-the-clear-signal rule as `cost_control_mode_override`). Effective on the next spawn, so it can be changed at any point in a session.",
            "title": "Subagent Routing Override"
          },
          "terminal_launch_args": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Per-session native-terminal pass-through args, e.g. `[\"--dangerously-skip-permissions\"]`. A list (including `[]`) replaces the stored value wholesale \u2014 resume is last-write-wins, never an append. Bounds (count / length) are validated server-side. `None` leaves unchanged.",
            "title": "Terminal Launch Args"
          },
          "title": {
            "anyOf": [
              {
                "maxLength": 200,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "New title, e.g. `\"debugging auth flow\"`. `None` leaves unchanged.",
            "title": "Title"
          }
        },
        "title": "UpdateSessionRequest",
        "type": "object"
      },
      "UpsertMCPServerRequest": {
        "description": "Request body for creating or updating a session agent MCP server.\n\n`env` is still excluded. `headers` is accepted for HTTP servers;\nwhen omitted, existing headers in the bundle are preserved unchanged.",
        "properties": {
          "args": {
            "items": {
              "type": "string"
            },
            "maxItems": 64,
            "title": "Args",
            "type": "array"
          },
          "command": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Command"
          },
          "description": {
            "anyOf": [
              {
                "maxLength": 512,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "headers": {
            "anyOf": [
              {
                "additionalProperties": {
                  "type": "string"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Headers"
          },
          "name": {
            "maxLength": 128,
            "minLength": 1,
            "pattern": "^[A-Za-z0-9_-][A-Za-z0-9_.-]{0,127}$",
            "title": "Name",
            "type": "string"
          },
          "transport": {
            "enum": [
              "http",
              "stdio"
            ],
            "title": "Transport",
            "type": "string"
          },
          "url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Url"
          }
        },
        "required": [
          "name",
          "transport"
        ],
        "title": "UpsertMCPServerRequest",
        "type": "object"
      },
      "Usage": {
        "description": "Token usage statistics for a response.",
        "properties": {
          "cache_creation_input_tokens": {
            "default": 0,
            "description": "Prompt tokens written to the provider prompt cache (cache creation), billed at a premium rate. Like `cache_read_input_tokens`, this is separate from `input_tokens`; `0` when not reported.",
            "format": "int64",
            "title": "Cache Creation Input Tokens",
            "type": "integer"
          },
          "cache_read_input_tokens": {
            "default": 0,
            "description": "Prompt tokens served from a provider prompt cache (cache hit), billed at a reduced rate. Reported by Anthropic-style providers as a count *separate* from `input_tokens` (which carries only the non-cached portion); `0` when the provider does not break out cache usage. Consumed by the cache-aware server-side cost path.",
            "format": "int64",
            "title": "Cache Read Input Tokens",
            "type": "integer"
          },
          "context_tokens": {
            "anyOf": [
              {
                "format": "int64",
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Context-fill estimate for the next turn \u2014 set only by executors that make multiple LLM sub-calls per turn (e.g. `openai-agents`). For single-call executors this is absent and `total_tokens` serves the same purpose. The toolbar context ring and `/context` command use this field when present, falling back to `total_tokens`.",
            "title": "Context Tokens"
          },
          "cost_usd": {
            "anyOf": [
              {
                "format": "double",
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Authoritative per-turn cost in USD reported directly by the harness/provider (e.g. GitHub Copilot's AI-credit total). When present, the server-side cost path uses it in preference to the catalog token-price estimate; `None` when the harness doesn't report a cost (the common case, where cost is computed from token counts x catalog pricing).",
            "title": "Cost Usd"
          },
          "input_tokens": {
            "default": 0,
            "description": "Number of input (prompt) tokens consumed.",
            "format": "int64",
            "title": "Input Tokens",
            "type": "integer"
          },
          "model": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "The LLM model the harness actually used for this turn, e.g. `\"claude-opus-4-8\"` or `\"databricks-gpt-5-5\"`. Reported by relay executors so the server-side cost path can price the turn even when the agent spec pins no `llm.model` (e.g. supervisors that delegate / use the harness default). `None` when the executor doesn't report it; the cost path then falls back to the session override / spec model.",
            "title": "Model"
          },
          "output_tokens": {
            "default": 0,
            "description": "Number of output (completion) tokens generated.",
            "format": "int64",
            "title": "Output Tokens",
            "type": "integer"
          },
          "output_tokens_details": {
            "$ref": "#/components/schemas/UsageDetails",
            "description": "Breakdown of output token usage (e.g. reasoning tokens)."
          },
          "total_tokens": {
            "default": 0,
            "description": "Sum of input and output tokens across all LLM sub-calls for this turn (billing total).",
            "format": "int64",
            "title": "Total Tokens",
            "type": "integer"
          }
        },
        "title": "Usage",
        "type": "object"
      },
      "UsageDetails": {
        "description": "Breakdown of output token usage.",
        "properties": {
          "reasoning_tokens": {
            "default": 0,
            "description": "Number of tokens consumed by chain-of-thought reasoning.",
            "format": "int64",
            "title": "Reasoning Tokens",
            "type": "integer"
          }
        },
        "title": "UsageDetails",
        "type": "object"
      },
      "UsageReport": {
        "description": "Aggregated LLM usage for the calling user, powering `omni usage`.\n\nThe cost summary is sourced from the per-user daily-cost rollup\n(`user_daily_cost`), which attributes spend to the UTC calendar day it\noccurred on. Windows are therefore calendar-day buckets summed back from\ntoday \u2014 `cost_today` / `cost_last_7d` / `cost_last_30d` \u2014 not\nrolling wall-clock hours, so a weeks-old session touched today is not\ncounted wholly in \"today\".\n\nThe `sessions` list is a separate detail view built from each session's\ncumulative `session_usage` (newest activity first), so the summary and\nthe per-session list come from different sources and are not guaranteed\nto tie out to the cent (the summary counts every priced turn ever\nrecorded for the user; the list only covers the user's currently-listed\ntop-level sessions).",
        "properties": {
          "cost_last_30d": {
            "default": 0.0,
            "description": "Total spend over the last 30 UTC days (incl. today).",
            "format": "double",
            "title": "Cost Last 30D",
            "type": "number"
          },
          "cost_last_7d": {
            "default": 0.0,
            "description": "Total spend over the last 7 UTC days (incl. today).",
            "format": "double",
            "title": "Cost Last 7D",
            "type": "number"
          },
          "cost_today": {
            "default": 0.0,
            "description": "Total spend on the current UTC day.",
            "format": "double",
            "title": "Cost Today",
            "type": "number"
          },
          "daily_costs": {
            "items": {
              "$ref": "#/components/schemas/DailyCost"
            },
            "title": "Daily Costs",
            "type": "array"
          },
          "object": {
            "const": "usage_report",
            "default": "usage_report",
            "title": "Object",
            "type": "string"
          },
          "sessions": {
            "description": "Per-session detail, newest activity first.",
            "items": {
              "$ref": "#/components/schemas/SessionUsage"
            },
            "title": "Sessions",
            "type": "array"
          },
          "total_cost_usd": {
            "default": 0.0,
            "description": "All-time total spend from the daily rollup.",
            "format": "double",
            "title": "Total Cost Usd",
            "type": "number"
          }
        },
        "title": "UsageReport",
        "type": "object"
      },
      "ValidationError": {
        "properties": {
          "ctx": {
            "title": "Context",
            "type": "object"
          },
          "input": {
            "title": "Input"
          },
          "loc": {
            "items": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "format": "int64",
                  "type": "integer"
                }
              ]
            },
            "title": "Location",
            "type": "array"
          },
          "msg": {
            "title": "Message",
            "type": "string"
          },
          "type": {
            "title": "Error Type",
            "type": "string"
          }
        },
        "required": [
          "loc",
          "msg",
          "type"
        ],
        "title": "ValidationError",
        "type": "object"
      }
    },
    "securitySchemes": {
      "proxyHeaderAuth": {
        "description": "Trusted-proxy identity header (header-auth mode, the default). The header name is configurable via `OMNIGENT_AUTH_HEADER`.",
        "in": "header",
        "name": "X-Forwarded-Email",
        "type": "apiKey"
      },
      "sessionCookieAuth": {
        "description": "Signed session cookie minted after an interactive OIDC or accounts login (oidc / accounts auth modes). Named `ap_session` over HTTP (the advertised local default); under HTTPS the secure `__Host-ap_session` prefixed form is used instead.",
        "in": "cookie",
        "name": "ap_session",
        "type": "apiKey"
      }
    }
  },
  "info": {
    "description": "Omnigent is an open-source meta-harness for building and running AI agents. This is the REST API exposed by the Omnigent server: use it to create and drive **sessions**, manage **agents**, **hosts**, and **runners**, attach **contextual policies**, post **comments**, and work with session **resources** \u2014 files, terminals, and sandboxed environments.\n\n## Base URL\n\nOmnigent is self-hosted. The server binds `http://127.0.0.1:6767` by default (`omnigent server`); point the base URL at your own deployment.\n\n## Authentication\n\nThere is no API-key or bearer-token scheme. Identity is supplied by the deployment's configured auth provider (`OMNIGENT_AUTH_PROVIDER`):\n\n- **Trusted proxy header** (default) \u2014 an upstream proxy injects an identity header (`X-Forwarded-Email`, configurable). Single-user local runtimes fall back to a reserved `local` user.\n- **Session cookie** \u2014 a signed session cookie minted after an interactive OIDC or accounts login. It is named `ap_session` over HTTP (the advertised local default) and `__Host-ap_session` under HTTPS, where the `__Host-` prefix guards against subdomain cookie-tossing.\n\nAuth is configured server-side; clients send the cookie or proxy header according to your deployment.\n\n## Streaming\n\n`GET /v1/sessions/{session_id}/stream` streams Server-Sent Events (`text/event-stream`). Each event conforms to the `ServerStreamEvent` schema documented below.\n",
    "title": "Omnigent Server",
    "version": "0.1.0"
  },
  "openapi": "3.2.0",
  "paths": {
    "/.well-known/omnigent.json": {
      "get": {
        "description": "Version manifest for NON-BROWSER clients \u2014 chiefly the desktop shell.\n\nThe desktop shell ships and updates on its own cadence, so any\ninstalled build can meet any server version. The shell is the side\nthat must adapt (the user may not update it for months), and to adapt\nit first has to know what it is talking to. This endpoint is that\nanswer, fetched BEFORE the SPA loads \u2014 unlike `/v1/info`, which the\nSPA reads after boot and which is therefore useless to the shell when\ndeciding how to open a window in the first place.\n\nContract, in the order a client should apply it:\n\n1. `manifest_version` (int) versions this ENVELOPE. Clients gate on\n   `>=`, never `==`, so a newer server keeps working with an older\n   shell. See `WELL_KNOWN_MANIFEST_VERSION` for when it bumps \u2014\n   adding a field never does.\n2. `server_version` (str) is the installed omnigent package version,\n   the same value as `/api/version` and `/v1/info.server_version`.\n   Informational: for display and bug reports, NOT for gating. Gate on\n   the fields below, which state capability directly rather than making\n   every client hardcode \"which release added X\".\n3. `min_desktop_version` (str | null) is the oldest desktop build this\n   server still supports. Null means no floor \u2014 the overwhelmingly\n   common case, and what every shipped shell must treat as \"fine\".\n   A server sets it only to signal a genuinely breaking change.\n4. Everything else is additive detail an older client may ignore\n   wholesale. `ui` describes where server-driven chrome lives, so a\n   shell can place its own window furniture without guessing from the\n   version number: `server_picker` is `\"sidebar\"` on builds that\n   dock the picker at the sidebar's bottom (it was `\"titlebar\"`,\n   centered in the macOS title-bar strip, before this).\n5. `auth` tells a native client how this server signs users in,\n   before it loads anything. `mode` is `\"oidc\"`, `\"accounts\"`,\n   `\"header\"`, `\"custom\"` (an embedding app's own provider), or\n   `\"none\"`. `\"oidc\"` also promises the native loopback sign-in\n   (`/auth/login` native parameters + `POST /auth/native-token`).\n   `session_cookie` names the session cookie for `oidc` and\n   `accounts` and is `null` otherwise. A missing `auth` (older\n   servers) means \"sign in as before\".\n6. `server_name` (str | null) is the operator's display name for\n   this deployment (`branding.server_name`), for clients that list\n   several servers. Self-asserted by the server, so clients show it\n   for display only and keep the host in any trust decision. Null\n   when unset; it never falls back to `branding.app_name`.\n\nUnknown fields MUST be ignored, and a missing manifest (404 \u2014 every\nserver older than this route) MUST be treated as the pre-manifest\nbaseline, not an error: the shell falls back to its current behavior.\nThat is what makes an old shell + new server and a new shell + old\nserver both work.\n\nAuthentication: intentionally UNAUTHED, like `/v1/info`. A client\nmust be able to read this before it holds a session cookie \u2014 the whole\npoint is to consult it before loading the app. It exposes only the\nversion already public via `/api/version`, coarse UI-shape\nstrings, and the sign-in mode and cookie name any visitor already\nlearns from `/v1/info` and the login redirect, so there is\nnothing here to leak.\n\nServed under `/.well-known/` (RFC 8615) so it sits at a fixed,\nguessable path that never collides with an SPA client route.\n\n**Returns:** The manifest described above.",
        "operationId": "well_known_manifest__well_known_omnigent_json_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Well Known Manifest  Well Known Omnigent Json Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Well Known Manifest"
      }
    },
    "/api/version": {
      "get": {
        "description": "Return the installed omnigent package version.\n\nUsed by the web UI to include version info in bug reports.\n\n**Returns:** `{\"version\": \"<semver string>\"}`, e.g. `{\"version\": \"0.1.0\"}`.",
        "operationId": "version_api_version_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": {
                    "type": "string"
                  },
                  "title": "Response Version Api Version Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Version",
        "tags": [
          "system"
        ]
      }
    },
    "/health": {
      "get": {
        "description": "Liveness check with optional session-scoped runner status.\n\nWithout session params, returns `{\"status\": \"ok\"}` (bare\nliveness). With `session_id`, adds a single `session`\nobject. With `session_ids` (comma-separated), adds a\n`sessions` dict keyed by id \u2014 used by the sidebar to\nbatch-check all visible sessions in one request. The batch\npath runs a single SQL `IN` query, not N per-id round-trips.\n\nEach per-session object carries both `runner_online` (strict\nrunner reachability) and `host_online` (host tunnel live, or\n`None` when the session has no host binding) \u2014 see\n`~omnigent.server.routes.sessions.SessionLiveness`.\n\n**Returns:** `{\"status\": \"ok\"}` with optional `session` and/or `sessions` fields. Each session object has shape `{\"runner_online\": bool, \"host_online\": bool | None, \"host_version\": str | None}` (the single `session` object also includes its `id`). `host_version` is the bound host's reported version, or `None` when there's no host binding / the version isn't resolvable on this replica.",
        "operationId": "health_health_get",
        "parameters": [
          {
            "description": "Optional single session id, e.g. `\"conv_abc123\"`.",
            "in": "query",
            "name": "session_id",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Session Id"
            }
          },
          {
            "description": "Optional comma-separated session ids for batch lookup, e.g. `\"conv_abc,conv_def,conv_ghi\"`.",
            "in": "query",
            "name": "session_ids",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Session Ids"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Health Health Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Health",
        "tags": [
          "system"
        ]
      }
    },
    "/v1/agents": {
      "get": {
        "description": "List built-in agents with cursor-based pagination.\n\nReturns only built-in agents \u2014 `agent_store.list()` filters\n`session_id IS NULL` \u2014 so session-scoped agents never appear.\n\n**Returns:** A `PaginatedList` of built-in agents.",
        "operationId": "list_builtin_agents_v1_agents_get",
        "parameters": [
          {
            "description": "Maximum number of agents to return (1-1000).",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 20,
              "maximum": 1000,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "description": "Cursor \u2014 return agents after this id.",
            "in": "query",
            "name": "after",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "After"
            }
          },
          {
            "description": "Cursor \u2014 return agents before this id.",
            "in": "query",
            "name": "before",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Before"
            }
          },
          {
            "description": "Sort order, `\"asc\"` or `\"desc\"`.",
            "in": "query",
            "name": "order",
            "required": false,
            "schema": {
              "default": "desc",
              "pattern": "^(asc|desc)$",
              "title": "Order",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaginatedList"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Builtin Agents",
        "tags": [
          "agents"
        ]
      }
    },
    "/v1/branding/logo/{variant}": {
      "get": {
        "description": "Serve a validated public branding asset, or 404 when unset.",
        "operationId": "branding_logo_v1_branding_logo__variant__get",
        "parameters": [
          {
            "in": "path",
            "name": "variant",
            "required": true,
            "schema": {
              "title": "Variant",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "image/gif": {
                "schema": {
                  "format": "binary",
                  "type": "string"
                }
              },
              "image/jpeg": {
                "schema": {
                  "format": "binary",
                  "type": "string"
                }
              },
              "image/png": {
                "schema": {
                  "format": "binary",
                  "type": "string"
                }
              },
              "image/webp": {
                "schema": {
                  "format": "binary",
                  "type": "string"
                }
              },
              "image/x-icon": {
                "schema": {
                  "format": "binary",
                  "type": "string"
                }
              }
            },
            "description": "Validated raster branding image"
          },
          "404": {
            "description": "Branding image not configured or invalid"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Branding Logo"
      }
    },
    "/v1/extensions": {
      "get": {
        "description": "List extensions installed and enabled when the server started.\n\nV1 treats operator installation as enablement. Installing, removing, or\nupgrading a package requires a server restart to refresh this snapshot.",
        "operationId": "list_extensions_v1_extensions_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ExtensionListResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "List Extensions",
        "tags": [
          "extensions"
        ]
      }
    },
    "/v1/extensions/diagnostics": {
      "get": {
        "description": "Show accepted extensions and concise discovery failures to administrators.",
        "operationId": "extension_diagnostics_v1_extensions_diagnostics_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ExtensionDiagnosticsResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Extension Diagnostics",
        "tags": [
          "extensions"
        ]
      }
    },
    "/v1/extensions/{extension_id}": {
      "get": {
        "description": "Return one installed extension's public contribution metadata.",
        "operationId": "get_extension_v1_extensions__extension_id__get",
        "parameters": [
          {
            "in": "path",
            "name": "extension_id",
            "required": true,
            "schema": {
              "title": "Extension Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ExtensionResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Extension",
        "tags": [
          "extensions"
        ]
      }
    },
    "/v1/extensions/{extension_id}/assets/{digest}/{asset_name}": {
      "get": {
        "description": "Return a declared asset only when its bundle digest still matches.",
        "operationId": "get_extension_asset_v1_extensions__extension_id__assets__digest___asset_name__get",
        "parameters": [
          {
            "in": "path",
            "name": "extension_id",
            "required": true,
            "schema": {
              "title": "Extension Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "digest",
            "required": true,
            "schema": {
              "title": "Digest",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "asset_name",
            "required": true,
            "schema": {
              "title": "Asset Name",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              },
              "text/css": {
                "schema": {
                  "format": "binary",
                  "type": "string"
                }
              },
              "text/javascript": {
                "schema": {
                  "format": "binary",
                  "type": "string"
                }
              }
            },
            "description": "Extension JavaScript or CSS asset"
          },
          "404": {
            "description": "Extension asset not found"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Extension Asset",
        "tags": [
          "extensions"
        ]
      }
    },
    "/v1/harnesses": {
      "get": {
        "operationId": "list_harnesses_v1_harnesses_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response List Harnesses V1 Harnesses Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "List Harnesses",
        "tags": [
          "harnesses"
        ]
      }
    },
    "/v1/hosts": {
      "get": {
        "description": "List all hosts owned by the authenticated user.\n\nReturns both online and offline hosts, with live runner\ninformation for online hosts.\n\n**Returns:** `{\"hosts\": [...]}` with host details \u2014 `host_id`, `name`, `owner`, `status`, `sandbox_provider`, `configured_harnesses`, and `gateway_inference` (`None` when no connected host has reported it to this replica).",
        "operationId": "list_hosts_v1_hosts_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": {
                    "items": {
                      "additionalProperties": true,
                      "type": "object"
                    },
                    "type": "array"
                  },
                  "title": "Response List Hosts V1 Hosts Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "List Hosts",
        "tags": [
          "hosts"
        ]
      }
    },
    "/v1/hosts/{host_id}": {
      "get": {
        "description": "Get details for a single host.\n\n**Returns:** Host details dict \u2014 the `list_hosts` fields (including `gateway_inference`, `None` when unreported) plus `runners`.\n\n**Raises**\n\n- `HTTPException` \u2014 404 if the host does not exist.",
        "operationId": "get_host_v1_hosts__host_id__get",
        "parameters": [
          {
            "description": "Host identifier, e.g. `\"host_a1b2c3d4...\"`.",
            "in": "path",
            "name": "host_id",
            "required": true,
            "schema": {
              "title": "Host Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Get Host V1 Hosts  Host Id  Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Host",
        "tags": [
          "hosts"
        ]
      }
    },
    "/v1/hosts/{host_id}/credentials/detected": {
      "get": {
        "description": "List adoptable credentials already present on a connected host.\n\nBacks the setup dialog's \"adopt an existing credential\" affordance: the\nhost reports which UI-auth-family credentials it already has as\nNON-secret descriptors (family + source label + env var name), so the UI\ncan offer a one-click \"Use it\". Owner-scoped and flag-gated like the\ncredential-write route (404 when disabled). Never returns a secret value.\n\n**Returns:** `{\"object\": \"detected_credentials\", \"credentials\": [...]}`.\n\n**Raises**\n\n- `HTTPException` \u2014 404 when disabled or host unknown, 403 when not the owner, 409 when offline, 502/504 on host failure/timeout.",
        "operationId": "detect_host_credentials_v1_hosts__host_id__credentials_detected_get",
        "parameters": [
          {
            "description": "Host identifier.",
            "in": "path",
            "name": "host_id",
            "required": true,
            "schema": {
              "title": "Host Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Detect Host Credentials V1 Hosts  Host Id  Credentials Detected Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Detect Host Credentials",
        "tags": [
          "hosts"
        ]
      }
    },
    "/v1/hosts/{host_id}/credentials/{provider}": {
      "get": {
        "description": "Return the session owner's *provider* credential for *host_id*.\n\nAuthenticated by the launch token (constant-time, expiry-aware, and\nbound to *host_id*), exactly like the host tunnel. `401` when the\ntoken doesn't resolve; `404` for a provider with no broker resolver or\nnot configured on this server; `{\"connected\": false}` when the owner\nhasn't linked it, so a caller can fall back cleanly.",
        "operationId": "host_credential_v1_hosts__host_id__credentials__provider__get",
        "parameters": [
          {
            "in": "path",
            "name": "host_id",
            "required": true,
            "schema": {
              "title": "Host Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "provider",
            "required": true,
            "schema": {
              "title": "Provider",
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "x-omnigent-host-token",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Omnigent-Host-Token"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Host Credential V1 Hosts  Host Id  Credentials  Provider  Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Host Credential",
        "tags": [
          "hosts"
        ]
      }
    },
    "/v1/hosts/{host_id}/directories": {
      "post": {
        "description": "Create a new directory on a host.\n\nBacks the Web UI workspace picker's \"New folder\" action so a\nuser can make a fresh directory to start a session in without\ndropping to a terminal. Owner-scoped exactly like the\nfilesystem browse endpoints (`GET /v1/hosts/{id}/filesystem`):\nonly the host owner can create directories, and \u2014 like browse \u2014\nthis is NOT scoped to a session. The workspace-boundary check\nstill runs at session-create time, so creating a directory here\ndoes not by itself grant an agent access to it.\n\n**Parameters**\n\n- `body` \u2014 Request body carrying the absolute (or tilde-prefixed) `path` to create.\n\n**Returns:** `{\"object\": \"directory\", \"path\": \"<created abs path>\"}`.\n\n**Raises**\n\n- `HTTPException` \u2014 404 if host not found, 403 if not owned by caller, 409 if host is offline or the directory could not be created (already exists / permission denied), 400 on path validation, 504 on host timeout, 502 on host I/O failure.",
        "operationId": "create_host_directory_v1_hosts__host_id__directories_post",
        "parameters": [
          {
            "description": "Host identifier, e.g. `\"host_a1b2c3d4...\"`.",
            "in": "path",
            "name": "host_id",
            "required": true,
            "schema": {
              "title": "Host Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateDirectoryRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Create Host Directory V1 Hosts  Host Id  Directories Post",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Create Host Directory",
        "tags": [
          "hosts"
        ]
      }
    },
    "/v1/hosts/{host_id}/filesystem": {
      "get": {
        "description": "List the contents of the host daemon's home directory.\n\nEmpty trailing path \u2192 forward `~` to the host (the host\nexpands against its own process owner). Used by the\nWeb UI's directory picker to show the \"root\" view.\n\n**Returns:** `{\"object\": \"list\", \"data\": [...], \"has_more\": bool}` mirroring the existing session-scoped filesystem endpoint shape.\n\n**Raises**\n\n- `HTTPException` \u2014 404 if host not found, 403 if not owned by caller, 409 if host is offline, 504 on host timeout, 502 on host I/O failure.",
        "operationId": "list_host_filesystem_root_v1_hosts__host_id__filesystem_get",
        "parameters": [
          {
            "description": "Host identifier, e.g. `\"host_a1b2c3d4...\"`.",
            "in": "path",
            "name": "host_id",
            "required": true,
            "schema": {
              "title": "Host Id",
              "type": "string"
            }
          },
          {
            "description": "Max entries per page.",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 20,
              "maximum": 1000,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "description": "Optional forward pagination cursor (entry path), e.g. `\"/Users/corey/projects/m\"`.",
            "in": "query",
            "name": "after",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "After"
            }
          },
          {
            "description": "Optional backward pagination cursor.",
            "in": "query",
            "name": "before",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Before"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response List Host Filesystem Root V1 Hosts  Host Id  Filesystem Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Host Filesystem Root",
        "tags": [
          "hosts"
        ]
      }
    },
    "/v1/hosts/{host_id}/filesystem/{path}": {
      "get": {
        "description": "List the contents of a directory on a host.\n\nUsed by the Web UI's directory picker (and stat-style\nexistence checks) to render the host's filesystem before\nany runner exists. Owner-scoped: only the host owner can\nbrowse. NOT scoped to a session \u2014 this endpoint exposes\nthe entire host filesystem to the authenticated host owner\nper `designs/SESSION_WORKSPACE_SELECTION.md` \"Security\nsurface\".\n\n**Returns:** `{\"object\": \"list\", \"data\": [...], \"has_more\": bool}`.\n\n**Raises**\n\n- `HTTPException` \u2014 404 (host or path missing), 403 (not owner), 409 (offline), 400 (path validation), 504 (timeout), 502 (host I/O).",
        "operationId": "list_host_filesystem_v1_hosts__host_id__filesystem__path__get",
        "parameters": [
          {
            "description": "Host identifier.",
            "in": "path",
            "name": "host_id",
            "required": true,
            "schema": {
              "title": "Host Id",
              "type": "string"
            }
          },
          {
            "description": "Absolute path on the host (e.g. `\"/Users/corey/universe\"`) OR a tilde-prefixed path (`\"~/foo\"`). The host expands `~` itself. FastAPI's `:path` converter strips the leading `/` from the URL, so we re-add it for absolute paths.",
            "in": "path",
            "name": "path",
            "required": true,
            "schema": {
              "title": "Path",
              "type": "string"
            }
          },
          {
            "description": "Max entries per page.",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 20,
              "maximum": 1000,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "description": "Optional forward pagination cursor.",
            "in": "query",
            "name": "after",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "After"
            }
          },
          {
            "description": "Optional backward pagination cursor.",
            "in": "query",
            "name": "before",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Before"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response List Host Filesystem V1 Hosts  Host Id  Filesystem  Path  Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Host Filesystem",
        "tags": [
          "hosts"
        ]
      }
    },
    "/v1/hosts/{host_id}/harnesses/{harness}/credential": {
      "post": {
        "description": "Write a harness provider credential onto a connected host.\n\nBacks the Web UI setup dialog's \"Add a credential\" action so a user can\nconfigure a Claude / Codex / Pi credential on a connected host without a\nterminal. Owner-scoped, allowlisted, and gated behind\n`harness_install` release feature exactly like the install route\n(404 when disabled). The host daemon does the write with the same\nnon-interactive core the `omnigent setup` wizard uses.\n\nSecurity: the server is an authz'd pass-through \u2014 it validates\nownership + the allowlist and forwards the secret over the (TLS) tunnel;\nit never persists the secret or logs it. The secret rides in the request\nbody (not the URL), and the frame field is redaction-named so it never\nlands on a telemetry span.\n\n**Parameters**\n\n- `body` \u2014 The credential payload (kind + secret / gateway / adopt).\n\n**Returns:** `{\"object\": \"harness_credential\", \"harness\": ..., \"configured_harnesses\": {...}, \"gateway_inference\": {...} | None}` \u2014 refreshed readiness so the UI can flip the badge without a reconnect, plus the refreshed gateway-inference map (`None` when the host didn't report one).\n\n**Raises**\n\n- `HTTPException` \u2014 404 when disabled or host unknown, 400 when the harness isn't UI-configurable or the body is invalid, 403 when not the owner, 409 when offline, 502 on host-side failure, 504 on timeout.",
        "operationId": "store_host_harness_credential_v1_hosts__host_id__harnesses__harness__credential_post",
        "parameters": [
          {
            "description": "Host identifier.",
            "in": "path",
            "name": "host_id",
            "required": true,
            "schema": {
              "title": "Host Id",
              "type": "string"
            }
          },
          {
            "description": "Harness being configured, e.g. `\"claude\"`.",
            "in": "path",
            "name": "harness",
            "required": true,
            "schema": {
              "title": "Harness",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/StoreHarnessCredentialRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Store Host Harness Credential V1 Hosts  Host Id  Harnesses  Harness  Credential Post",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Store Host Harness Credential",
        "tags": [
          "hosts"
        ]
      }
    },
    "/v1/hosts/{host_id}/harnesses/{harness}/install": {
      "post": {
        "description": "Install a missing, npm-installable harness CLI onto a host.\n\nBacks the Web UI's New Chat dialog \"Install\" action so a user can\ninstall a harness the connected host is missing without dropping to a\nterminal. Owner-scoped like the other host actions: only the host owner\nmay install onto it. Scoped to the UI-installable allowlist (claude,\ncodex, pi, opencode, qwen) \u2014 curl/brew and interactive-auth harnesses\nare refused. The whole route is gated behind\n`harness_install` in `OMNIGENT_FEATURES` (default off): when\ndisabled it returns 404 so the feature is invisible until opted in.\n\nConcurrent requests for the same (host, harness) coalesce onto one\nin-flight install so a double-click can't fire two global npm installs.\n\n**Returns:** `{\"object\": \"harness_install\", \"harness\": ..., \"configured_harnesses\": {...}, \"gateway_inference\": {...} | None}` \u2014 the host's refreshed readiness map so the UI can flip the badge without a reconnect, plus its refreshed gateway-inference map (`None` when the host didn't report one).\n\n**Raises**\n\n- `HTTPException` \u2014 404 when the feature is disabled or the host is unknown, 400 when the harness is not UI-installable, 403 when the caller is not the host owner, 409 when the host is offline, 502 on a host-side install failure, 504 on host timeout.",
        "operationId": "install_host_harness_v1_hosts__host_id__harnesses__harness__install_post",
        "parameters": [
          {
            "description": "Host identifier, e.g. `\"host_a1b2c3d4...\"`.",
            "in": "path",
            "name": "host_id",
            "required": true,
            "schema": {
              "title": "Host Id",
              "type": "string"
            }
          },
          {
            "description": "Harness identifier to install, e.g. `\"claude\"`.",
            "in": "path",
            "name": "harness",
            "required": true,
            "schema": {
              "title": "Harness",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Install Host Harness V1 Hosts  Host Id  Harnesses  Harness  Install Post",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Install Host Harness",
        "tags": [
          "hosts"
        ]
      }
    },
    "/v1/hosts/{host_id}/harnesses/{harness}/model-options": {
      "get": {
        "description": "Return pre-launch model choices resolved by the selected host.\n\nA preview of the host's ambient default catalog, not a binding\nsnapshot: launch re-resolves with the session's agent spec, and the\nin-session picker reflects that launch snapshot once the runner is up.",
        "operationId": "get_host_model_options_v1_hosts__host_id__harnesses__harness__model_options_get",
        "parameters": [
          {
            "in": "path",
            "name": "host_id",
            "required": true,
            "schema": {
              "title": "Host Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "harness",
            "required": true,
            "schema": {
              "title": "Harness",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HostModelOptionsResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Host Model Options",
        "tags": [
          "hosts"
        ]
      }
    },
    "/v1/hosts/{host_id}/harnesses/{harness}/skills/{name}": {
      "get": {
        "operationId": "get_skill_content_v1_hosts__host_id__harnesses__harness__skills__name__get",
        "parameters": [
          {
            "in": "path",
            "name": "host_id",
            "required": true,
            "schema": {
              "title": "Host Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "harness",
            "required": true,
            "schema": {
              "title": "Harness",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "name",
            "required": true,
            "schema": {
              "title": "Name",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "source_id",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "pattern": "^[0-9a-f]{64}$",
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Source Id"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SkillContentResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Skill Content",
        "tags": [
          "hosts"
        ]
      }
    },
    "/v1/hosts/{host_id}/harnesses/{harness}/startup": {
      "get": {
        "description": "Read the binary, source, and argument count; never argument values.",
        "operationId": "get_harness_startup_v1_hosts__host_id__harnesses__harness__startup_get",
        "parameters": [
          {
            "in": "path",
            "name": "host_id",
            "required": true,
            "schema": {
              "title": "Host Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "harness",
            "required": true,
            "schema": {
              "title": "Harness",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HarnessStartup"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Harness Startup",
        "tags": [
          "hosts"
        ]
      }
    },
    "/v1/hosts/{host_id}/mcp-servers": {
      "get": {
        "description": "List the user-level MCP servers configured for each harness on a host.\n\nReturns names and non-secret metadata only; the caller must own the host.",
        "operationId": "get_mcp_servers_v1_hosts__host_id__mcp_servers_get",
        "parameters": [
          {
            "in": "path",
            "name": "host_id",
            "required": true,
            "schema": {
              "title": "Host Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/McpServersResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Mcp Servers",
        "tags": [
          "hosts"
        ]
      }
    },
    "/v1/hosts/{host_id}/mcp-servers/tools": {
      "post": {
        "operationId": "get_mcp_tools_v1_hosts__host_id__mcp_servers_tools_post",
        "parameters": [
          {
            "in": "path",
            "name": "host_id",
            "required": true,
            "schema": {
              "title": "Host Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/McpToolsRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/McpToolsResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Mcp Tools",
        "tags": [
          "hosts"
        ]
      }
    },
    "/v1/hosts/{host_id}/plugins": {
      "get": {
        "description": "List installed Claude plugins. The caller must own the host.",
        "operationId": "get_plugins_v1_hosts__host_id__plugins_get",
        "parameters": [
          {
            "in": "path",
            "name": "host_id",
            "required": true,
            "schema": {
              "title": "Host Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PluginsResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Plugins",
        "tags": [
          "hosts"
        ]
      }
    },
    "/v1/hosts/{host_id}/runners": {
      "post": {
        "description": "Launch a runner on a host for a session.\n\nGenerates a binding token, writes the expected runner_id\nto the session row, sends the launch command to the host,\nand waits for the host's acknowledgement.\n\n**Parameters**\n\n- `body` \u2014 Launch request with `session_id` and `workspace`.\n\n**Returns:** `{\"runner_id\": ..., \"status\": \"launching\"}`.\n\n**Raises**\n\n- `HTTPException` \u2014 404 if host not found, 409 if host offline, 403 if caller doesn't own the host, 400 if session already has a runner.",
        "operationId": "launch_runner_v1_hosts__host_id__runners_post",
        "parameters": [
          {
            "description": "Target host, e.g. `\"host_a1b2c3d4...\"`.",
            "in": "path",
            "name": "host_id",
            "required": true,
            "schema": {
              "title": "Host Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LaunchRunnerRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Launch Runner V1 Hosts  Host Id  Runners Post",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Launch Runner",
        "tags": [
          "hosts"
        ]
      }
    },
    "/v1/hosts/{host_id}/worktrees": {
      "get": {
        "description": "List the git worktrees of a repository on a host.\n\nUsed by the Web UI's new-session worktree picker to show the\nworktrees a session can start in directly. Owner-scoped exactly\nlike the filesystem browse endpoints; NOT scoped to a session.\nA path that is not a git repository is reported as 400 so the\npicker can quietly fall back to \"no worktrees\".\n\n**Returns:** `{\"object\": \"list\", \"data\": [{path, branch, is_main, detached, updated_at?}, ...]}` (main first).\n\n**Raises**\n\n- `HTTPException` \u2014 404 if host not found, 403 if not owned by caller, 409 if host is offline/unresponsive, 400 on path validation or a non-git path.",
        "operationId": "list_host_worktrees_v1_hosts__host_id__worktrees_get",
        "parameters": [
          {
            "description": "Host identifier, e.g. `\"host_a1b2c3d4...\"`.",
            "in": "path",
            "name": "host_id",
            "required": true,
            "schema": {
              "title": "Host Id",
              "type": "string"
            }
          },
          {
            "description": "Absolute path inside the repo on the host to list worktrees for, e.g. `\"/Users/alice/myrepo\"`.",
            "in": "query",
            "name": "path",
            "required": true,
            "schema": {
              "title": "Path",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response List Host Worktrees V1 Hosts  Host Id  Worktrees Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Host Worktrees",
        "tags": [
          "hosts"
        ]
      }
    },
    "/v1/imports": {
      "post": {
        "description": "Import one normalized transcript, optionally replacing its prior import.",
        "operationId": "import_session_v1_imports_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ImportSessionRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImportSessionResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Import Session",
        "tags": [
          "imports"
        ]
      }
    },
    "/v1/imports/local": {
      "post": {
        "description": "Import local transcripts from a chosen host.\n\nThe transcripts live on the caller's machine, so the read happens on\nthe connected host over its tunnel \u2014 the server can't see them. The\nhost loads an exact id or enumerates recent sessions, then normalizes\nthem; the server imports those not already imported.\n\nBuffered form: returns the whole batch's tally in one JSON body. For a\nlive per-session list use `POST /v1/imports/local/stream`. Not atomic:\neach session is persisted as its frame arrives, so if the host drops\nmid-stream this raises after the sessions read so far are already\ncommitted; a retry is idempotent (they come back as already-imported).",
        "operationId": "import_local_sessions_v1_imports_local_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LocalImportRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LocalImportResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Import Local Sessions",
        "tags": [
          "imports"
        ]
      }
    },
    "/v1/imports/local/stream": {
      "post": {
        "description": "Stream local transcripts from a chosen host.\n\nSame import as the buffered `POST /v1/imports/local`, but responds with\nNDJSON: one `{\"event\": \"session\", ...}` line per newly imported session\nas its frame lands, so the caller lists sessions as they arrive rather\nthan waiting out the whole batch. Each session that could not be imported\nemits one `{\"event\": \"failed\", \"external_session_id\", \"source\", \"reason\"}` line (after the successes), and a terminal\n`{\"event\": \"done\", ...}` carries the tally plus the full `failures`\nlist. A mid-stream host read failure emits `{\"event\": \"error\", ...}`\nbefore `done` (the sessions read so far are already committed and a\nretry is idempotent). Request validation still fails ahead of the stream\nwith the usual HTTP error.",
        "operationId": "import_local_sessions_stream_v1_imports_local_stream_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LocalImportRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              },
              "application/x-ndjson": {}
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Import Local Sessions Stream",
        "tags": [
          "imports"
        ]
      }
    },
    "/v1/info": {
      "get": {
        "description": "Runtime capabilities probe for the SPA + CLI.\n\nReturned at app boot by the frontend (and by `omnigent login` when it needs to choose between flows). Drives\nconditional route registration and chrome on the SPA side\n\u2014 when `accounts_enabled` is false, the SPA never\nregisters `/login`, `/register`, `/members` and\nnever renders the AccountMenu, so the bundle behaves\nidentically to a pre-PR-2008 build for header / OIDC\ndeploys (in particular, the internal hosted product that\nsyncs from this repo).\n\nAuthentication: this endpoint is intentionally UNAUTHED\nso the SPA can probe it before holding a session cookie.\nIt exposes no sensitive state \u2014 only the active auth\nsource, the login URL, whether first-run admin setup is\nstill pending (`needs_setup`), coarse capability\nbooleans (`databricks_features`,\n`managed_sandboxes_enabled`, `dictation_available`,\n`single_user`), the short sandbox provider name\n(`sandbox_provider`) the web UI labels the new-session\nsandbox option with, and the installed\n`server_version` (already public via `/api/version`).",
        "operationId": "info_v1_info_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ServerInfoResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Info",
        "tags": [
          "system"
        ]
      }
    },
    "/v1/me": {
      "get": {
        "description": "Return the current user's identity.\n\nReads the user from the auth provider (same logic that\nsession routes use). The frontend calls this on load to\ndiscover who it is.\n\nAlso returns `is_admin` \u2014 the mode-agnostic admin signal\n(the shared `users.is_admin` column, set by the admin-list\npromotion at login). The SPA gates admin chrome on it in\nEVERY mode, including OIDC/SSO where the accounts-only\n`/auth/me` endpoint does not exist.\n\nAn identity the admin list names but the database doesn't yet\nflag is promoted here, as login does for OIDC and accounts.\nHeader auth has no login step, so without this a listed admin\nwould see admin chrome that every admin-gated route refuses.\n\nWhen OIDC is active and the user is unauthenticated,\nreturns 401 with a `login_url` so the frontend knows\nwhere to redirect.\n\n**Returns:** `{\"user_id\": \"alice@example.com\", \"is_admin\": true}`, `{\"user_id\": null, \"is_admin\": false}` if unauthenticated in header mode, or 401 with `login_url` in OIDC mode.",
        "operationId": "me_v1_me_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Me",
        "tags": [
          "system"
        ]
      }
    },
    "/v1/policies": {
      "get": {
        "description": "List all default policies.\n\nRequires authentication in multi-user mode.\n\n**Returns:** `{\"object\": \"list\", \"data\": [...]}`.\n\n**Raises**\n\n- `OmnigentError` \u2014 401 if unauthenticated in multi-user mode.",
        "operationId": "list_policies_v1_policies_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response List Policies V1 Policies Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "List Policies",
        "tags": [
          "default_policies"
        ]
      },
      "post": {
        "description": "Create a new default policy.\n\nRequires admin privileges in multi-user mode.\n\n**Parameters**\n\n- `body` \u2014 Policy payload including name, type, and handler.\n\n**Returns:** The created policy as a serialized dict.\n\n**Raises**\n\n- `OmnigentError` \u2014 401/403 if the user lacks admin privileges, or 409 if a policy with the same name already exists.",
        "operationId": "create_policy_v1_policies_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateDefaultPolicyRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Create Policy V1 Policies Post",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Create Policy",
        "tags": [
          "default_policies"
        ]
      }
    },
    "/v1/policies/{policy_id}": {
      "delete": {
        "description": "Delete a default policy.\n\nIdempotent \u2014 deleting a missing policy returns 204.\nRequires admin privileges.\n\n**Returns:** `{\"deleted\": true}`.\n\n**Raises**\n\n- `OmnigentError` \u2014 401/403 if the user lacks admin privileges.",
        "operationId": "delete_policy_v1_policies__policy_id__delete",
        "parameters": [
          {
            "description": "The policy to delete, e.g. `\"pol_abc123\"`.",
            "in": "path",
            "name": "policy_id",
            "required": true,
            "schema": {
              "title": "Policy Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Delete Policy V1 Policies  Policy Id  Delete",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Delete Policy",
        "tags": [
          "default_policies"
        ]
      },
      "get": {
        "description": "Get a single default policy.\n\nRequires authentication in multi-user mode.\n\n**Returns:** The policy as a serialized dict.\n\n**Raises**\n\n- `OmnigentError` \u2014 401 if unauthenticated, or 404 if the policy is not found.",
        "operationId": "get_policy_v1_policies__policy_id__get",
        "parameters": [
          {
            "description": "The policy to retrieve, e.g. `\"pol_abc123\"`.",
            "in": "path",
            "name": "policy_id",
            "required": true,
            "schema": {
              "title": "Policy Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Get Policy V1 Policies  Policy Id  Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Policy",
        "tags": [
          "default_policies"
        ]
      },
      "patch": {
        "description": "Update a default policy's mutable fields.\n\n`type` is immutable \u2014 the caller must delete and\nre-create to change it. Requires admin privileges.\n\n**Parameters**\n\n- `body` \u2014 Fields to update; `None` fields are left unchanged.\n\n**Returns:** The updated policy as a serialized dict.\n\n**Raises**\n\n- `OmnigentError` \u2014 401/403 if the user lacks admin privileges, or 404 if the policy is not found.",
        "operationId": "update_policy_v1_policies__policy_id__patch",
        "parameters": [
          {
            "description": "The policy to update, e.g. `\"pol_abc123\"`.",
            "in": "path",
            "name": "policy_id",
            "required": true,
            "schema": {
              "title": "Policy Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateDefaultPolicyRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Update Policy V1 Policies  Policy Id  Patch",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Update Policy",
        "tags": [
          "default_policies"
        ]
      }
    },
    "/v1/policy-registry": {
      "get": {
        "description": "List all registered policy functions.\n\nReturns the full catalog of built-in policy callables\nwith their handler paths, descriptions, and parameter\nschemas.\n\n**Returns:** `{\"object\": \"list\", \"data\": [...]}`.",
        "operationId": "list_registry_v1_policy_registry_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response List Registry V1 Policy Registry Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "List Registry",
        "tags": [
          "policy_registry"
        ]
      }
    },
    "/v1/projects": {
      "get": {
        "description": "List the caller's projects.\n\n**Returns:** `{\"object\": \"list\", \"data\": [...]}`.\n\n**Raises**\n\n- `OmnigentError` \u2014 401 if unauthenticated in multi-user mode.",
        "operationId": "list_projects_v1_projects_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response List Projects V1 Projects Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "List Projects",
        "tags": [
          "projects"
        ]
      },
      "post": {
        "description": "Create a new, empty project owned by the caller.\n\n**Parameters**\n\n- `body` \u2014 Project payload (name).\n\n**Returns:** The created project as a serialized dict.\n\n**Raises**\n\n- `OmnigentError` \u2014 401 if unauthenticated in multi-user mode, 409 if the caller already has a project with this name.",
        "operationId": "create_project_v1_projects_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateProjectRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Create Project V1 Projects Post",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Create Project",
        "tags": [
          "projects"
        ]
      }
    },
    "/v1/projects/order": {
      "get": {
        "description": "Read the caller's custom order.",
        "operationId": "get_project_order_v1_projects_order_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectOrderResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Get Project Order",
        "tags": [
          "projects"
        ]
      },
      "put": {
        "description": "Save the caller's order and notify their connected clients.",
        "operationId": "save_project_order_v1_projects_order_put",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProjectOrderRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectOrderResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Save Project Order",
        "tags": [
          "projects"
        ]
      }
    },
    "/v1/projects/{project_id}": {
      "delete": {
        "description": "Delete one of the caller's projects.\n\nMember sessions are not deleted; they are left for the caller to\nunfile (clearing their `project_id`).\n\n**Returns:** `{\"id\": ..., \"object\": \"project.deleted\", \"deleted\": True}`.\n\n**Raises**\n\n- `OmnigentError` \u2014 401 if unauthenticated, 404 if not found / not owned by the caller.",
        "operationId": "delete_project_v1_projects__project_id__delete",
        "parameters": [
          {
            "description": "The project to delete.",
            "in": "path",
            "name": "project_id",
            "required": true,
            "schema": {
              "title": "Project Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Delete Project V1 Projects  Project Id  Delete",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Delete Project",
        "tags": [
          "projects"
        ]
      },
      "get": {
        "description": "Return one of the caller's projects.\n\n**Returns:** The project as a serialized dict.\n\n**Raises**\n\n- `OmnigentError` \u2014 401 if unauthenticated, 404 if not found / not owned by the caller.",
        "operationId": "get_project_v1_projects__project_id__get",
        "parameters": [
          {
            "description": "The project to fetch.",
            "in": "path",
            "name": "project_id",
            "required": true,
            "schema": {
              "title": "Project Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Get Project V1 Projects  Project Id  Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Project",
        "tags": [
          "projects"
        ]
      },
      "patch": {
        "description": "Update one of the caller's projects (e.g. rename).\n\n**Parameters**\n\n- `body` \u2014 Fields to change; `None` fields are left unchanged.\n\n**Returns:** The updated project as a serialized dict.\n\n**Raises**\n\n- `OmnigentError` \u2014 401 if unauthenticated, 404 if not found / not owned, 409 if the new name collides with another of the caller's projects.",
        "operationId": "update_project_v1_projects__project_id__patch",
        "parameters": [
          {
            "description": "The project to update.",
            "in": "path",
            "name": "project_id",
            "required": true,
            "schema": {
              "title": "Project Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateProjectRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Update Project V1 Projects  Project Id  Patch",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Update Project",
        "tags": [
          "projects"
        ]
      }
    },
    "/v1/runners": {
      "get": {
        "description": "Return currently online runners owned by the requesting user.\n\nWhen auth is active, only runners whose tunnel was\nestablished by the same user are returned. Without auth,\nall online runners are listed (single-user / dev mode).\n\n**Returns:** A `{\"data\": [...]}` list with runner ids and advertised harnesses.",
        "operationId": "list_runners_v1_runners_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": {
                    "items": {
                      "additionalProperties": true,
                      "type": "object"
                    },
                    "type": "array"
                  },
                  "title": "Response List Runners V1 Runners Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "List Runners",
        "tags": [
          "runners"
        ]
      }
    },
    "/v1/runners/{runner_id}/status": {
      "get": {
        "description": "Return whether a runner currently has an open tunnel.\n\nWhen auth is active, a runner owned by a different user\nappears as offline to prevent enumeration.\n\n**Returns:** A JSON object with `runner_id` and `online`.",
        "operationId": "runner_status_v1_runners__runner_id__status_get",
        "parameters": [
          {
            "description": "Stable runner id, e.g. `\"runner_0123456789abcdef\"`.",
            "in": "path",
            "name": "runner_id",
            "required": true,
            "schema": {
              "title": "Runner Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "boolean"
                      }
                    ]
                  },
                  "title": "Response Runner Status V1 Runners  Runner Id  Status Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Runner Status",
        "tags": [
          "runners"
        ]
      }
    },
    "/v1/runners/{runner_id}/token": {
      "post": {
        "description": "Mint a short-lived owner bearer for a delegated runner.\n\nA host-launched or managed-sandbox runner does not inherit the host\nuser's credential; it presents its server-minted tunnel binding token\n(`X-Omnigent-Runner-Tunnel-Token`) and the server returns a\nshort-lived owner JWT the runner then uses on its HTTP callbacks\n(which gate on `require_user`). This is the HTTP analog of the\nrunner tunnel's binding-token handshake: the same SHA-256 gate\n(`token_bound_runner_id(token) == runner_id`) and the same\nowner resolution (`resolve_managed_runner_owner`), minting a\nbearer instead of registering a tunnel.\n\nThe binding-token match is required unconditionally \u2014 the\nallow-list shortcut honored on some other runner-token checks is\ndeliberately NOT accepted here, because this endpoint issues a\nfull owner credential and delegated runners are token-bound.\n\n**Returns:** `{\"token\": <jwt>, \"expires_at\": <epoch seconds>}`.\n\n**Raises**\n\n- `OmnigentError` \u2014 401 when the binding token is absent, doesn't match `runner_id`, or resolves to no managed-launch owner; 400 when the active auth mode can't mint server-side (header/proxy, or no auth provider).",
        "operationId": "mint_runner_owner_token_v1_runners__runner_id__token_post",
        "parameters": [
          {
            "description": "Token-bound runner id from the path.",
            "in": "path",
            "name": "runner_id",
            "required": true,
            "schema": {
              "title": "Runner Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "integer"
                      }
                    ]
                  },
                  "title": "Response Mint Runner Owner Token V1 Runners  Runner Id  Token Post",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Mint Runner Owner Token",
        "tags": [
          "runners"
        ]
      }
    },
    "/v1/sandbox-providers/{provider}/harnesses/{harness}/model-options": {
      "get": {
        "operationId": "model_options_v1_sandbox_providers__provider__harnesses__harness__model_options_get",
        "parameters": [
          {
            "in": "path",
            "name": "provider",
            "required": true,
            "schema": {
              "title": "Provider",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "harness",
            "required": true,
            "schema": {
              "title": "Harness",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "agent_id",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Agent Id"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Model Options V1 Sandbox Providers  Provider  Harnesses  Harness  Model Options Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Model Options",
        "tags": [
          "sandbox inference"
        ]
      }
    },
    "/v1/sessions": {
      "get": {
        "description": "List sessions with cursor-based pagination.\n\nSessions are conversations with a non-`None` `agent_id`\n\u2014 i.e. those created via `POST /v1/sessions`.\nConversations without an agent binding are excluded.\n\n**Returns:** A `PaginatedList` of `SessionListItem`.",
        "operationId": "list_sessions_v1_sessions_get",
        "parameters": [
          {
            "description": "Maximum number of sessions to return (1-1000, default 20).",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 20,
              "maximum": 1000,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "description": "Cursor \u2014 return sessions after this session ID in sort order, e.g. `\"conv_abc123\"`.",
            "in": "query",
            "name": "after",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "After"
            }
          },
          {
            "description": "Cursor \u2014 return sessions before this session ID.",
            "in": "query",
            "name": "before",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Before"
            }
          },
          {
            "description": "When set, only return sessions bound to this agent, e.g. `\"ag_abc123\"`. `None` returns sessions across all agents.",
            "in": "query",
            "name": "agent_id",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Agent Id"
            }
          },
          {
            "description": "When set, only return sessions whose bound agent row has this name. This intentionally includes session-scoped agents that share a name but have distinct bundles. `None` disables the filter.",
            "in": "query",
            "name": "agent_name",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Agent Name"
            }
          },
          {
            "description": "Sort direction, `\"desc\"` (newest-first) or `\"asc\"` (oldest-first).",
            "in": "query",
            "name": "order",
            "required": false,
            "schema": {
              "default": "desc",
              "pattern": "^(asc|desc)$",
              "title": "Order",
              "type": "string"
            }
          },
          {
            "description": "Column to sort on, `\"created_at\"` or `\"updated_at\"`.",
            "in": "query",
            "name": "sort_by",
            "required": false,
            "schema": {
              "default": "created_at",
              "pattern": "^(created_at|updated_at)$",
              "title": "Sort By",
              "type": "string"
            }
          },
          {
            "description": "Case-insensitive substring filter on the session title or conversation content. `None` or empty string disables the filter. A session matches if its title contains the query or any of its conversation items' text does. Powers the sidebar's session search.",
            "in": "query",
            "name": "search_query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Search Query"
            }
          },
          {
            "description": "When `False` (default), archived sessions are omitted. When `True`, archived sessions are returned alongside active ones (the sidebar groups them into an \"Archived\" section). Powers the sidebar's \"Show archived\" toggle.",
            "in": "query",
            "name": "include_archived",
            "required": false,
            "schema": {
              "default": false,
              "title": "Include Archived",
              "type": "boolean"
            }
          },
          {
            "description": "Conversation kind to return. `\"default\"` (the default) returns only top-level user-initiated sessions \u2014 the sidebar's view. `\"sub_agent\"` returns only sub-agent child sessions. `\"any\"` returns both; this lets the new-session agent picker discover agents that are only bound to sub-agent sessions (e.g. ones uploaded via `sys_session_create`).",
            "in": "query",
            "name": "kind",
            "required": false,
            "schema": {
              "default": "default",
              "pattern": "^(default|sub_agent|any)$",
              "title": "Kind",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "project",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Project"
            }
          },
          {
            "description": "When `True`, return only sessions the user has pinned (the `omnigent.pinned` label). Lets the sidebar enumerate pinned sessions that fall outside the loaded pagination window. `False` (default) disables it.",
            "in": "query",
            "name": "pinned",
            "required": false,
            "schema": {
              "default": false,
              "title": "Pinned",
              "type": "boolean"
            }
          },
          {
            "description": "Ownership/archive filter for the sidebar tabs. `\"mine\"` returns only sessions the caller owns (owner-level grant). `\"shared\"` returns only sessions accessible but not owned. `\"archived\"` returns only archived sessions. `\"all\"` (default) returns all accessible non-archived sessions, matching the legacy behaviour.",
            "in": "query",
            "name": "visibility",
            "required": false,
            "schema": {
              "default": "all",
              "pattern": "^(all|mine|shared|archived)$",
              "title": "Visibility",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SessionList"
                }
              }
            },
            "description": "Successful Response"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "The `after`/`before` cursor names an item that no longer exists (it was deleted, or archived out of the filtered set) so the keyset bound cannot be resolved. The `error.code` is `stale_cursor`. Enumeration cannot continue from this cursor: restart from the first page, without a cursor."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Sessions",
        "tags": [
          "sessions"
        ]
      },
      "post": {
        "description": "Create a session.\n\n`application/json` preserves the existing contract: bind to\nan already-registered agent by `agent_id` and return the full\nsession snapshot. `multipart/form-data` is the Alpha\nrunner-state create path: the request carries a JSON\n`metadata` part and a `bundle` file part, then the server\nstores the bundle and creates the conversation row plus\nsession-scoped agent row in one database transaction.\n\n**Returns:** `SessionResponse` for JSON create, or `CreatedSessionResponse` for bundled create.\n\n**Raises**\n\n- `OmnigentError` \u2014 If metadata, bundle, or agent lookup validation fails, artifact storage is unavailable, or database creation fails.",
        "operationId": "create_session_v1_sessions_post",
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Create Session",
        "tags": [
          "sessions"
        ]
      }
    },
    "/v1/sessions/projects": {
      "get": {
        "description": "Return the caller's project summaries in their preferred display order.\n\nDual-reads both project representations and unions them by name:\n- **First-class projects** (`project_store`) \u2014 carry an `id` and\n  appear even when empty (the whole point of the first-class entity).\n- **Legacy label-projects** (implicit `omni_project` label) \u2014 exist\n  while at least one owned session carries the label; `id` is\n  `None` until such a project is promoted to first-class.\n\nA name present in both sources collapses to one entry that keeps the\nfirst-class `id`. Filing is owner-only, so both halves are scoped to\nthe caller (label-projects to their owned sessions, first-class to\ntheir owned rows) \u2014 a project shared to them but owned by another user\ndoes not surface as one of their own folders.\n\n**Returns:** Project summaries in custom order, or alphabetical order by default.",
        "operationId": "list_session_projects_v1_sessions_projects_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "items": {
                    "$ref": "#/components/schemas/SessionProjectSummary"
                  },
                  "title": "Response List Session Projects V1 Sessions Projects Get",
                  "type": "array"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "List Session Projects",
        "tags": [
          "sessions"
        ]
      }
    },
    "/v1/sessions/{session_id}": {
      "delete": {
        "description": "Delete a session and all associated resources.\n\nRequires owner-level access. Tears down tasks, runner-side\nresources (environments, terminals), session files, and the\nconversation row.\n\n**Returns:** A `ConversationDeleted` confirmation.\n\n**Raises**\n\n- `OmnigentError` \u2014 404 if no session or no access, 403 if insufficient permissions, 409 if `delete_branch=true` and the host is offline so worktree cleanup cannot run.",
        "operationId": "delete_session_v1_sessions__session_id__delete",
        "parameters": [
          {
            "description": "Session/conversation identifier, e.g. `\"conv_abc123\"`.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          },
          {
            "description": "Opt-in git cleanup, as a query param (`?delete_branch=true`). When `True` and the session has a server-created worktree (`git_branch` set), the host removes the worktree directory and deletes its branch (`git worktree remove --force` then `git branch -D`). Ignored for sessions with no worktree. If the host tunnel is down (typically `runner_online: false`), the delete is rejected with 409 so the caller can retry without cleanup rather than receiving a misleading 404. A host-reported git failure is still logged and does not block the delete. Defaults to `False` (worktree and branch left untouched). See designs/SESSION_GIT_WORKTREE.md.",
            "in": "query",
            "name": "delete_branch",
            "required": false,
            "schema": {
              "default": false,
              "title": "Delete Branch",
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversationDeleted"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Delete Session",
        "tags": [
          "sessions"
        ]
      },
      "get": {
        "description": "Return a session snapshot: identity, status, and committed\nitems.\n\n**Returns:** The matching `SessionResponse`.\n\n**Raises**\n\n- `OmnigentError` \u2014 404 if no session exists.",
        "operationId": "get_session_v1_sessions__session_id__get",
        "parameters": [
          {
            "description": "Session/conversation identifier, e.g. `\"conv_abc123\"`.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          },
          {
            "description": "When `False`, skip the committed-items read and return `items=[]`. The web chat surface passes `False` because it hydrates the transcript via the paginated `GET /sessions/{id}/items` endpoint in parallel and never reads the snapshot's copy; the items read is the single most expensive step of the snapshot build.",
            "in": "query",
            "name": "include_items",
            "required": false,
            "schema": {
              "default": true,
              "title": "Include Items",
              "type": "boolean"
            }
          },
          {
            "description": "When `False`, skip the runner/host liveness lookup and return `runner_online`/`host_online` as `None`. The web chat surface passes `False` because it sources liveness from the `/health` poll and the WS stream, not the snapshot.",
            "in": "query",
            "name": "include_liveness",
            "required": false,
            "schema": {
              "default": true,
              "title": "Include Liveness",
              "type": "boolean"
            }
          },
          {
            "description": "When `True`, refresh runner-derived snapshot overlays from the live session instead of serving stale AP-process caches. Browser reload/bind requests use this to recover from fixed bugs without restarting the AP server.",
            "in": "query",
            "name": "refresh_state",
            "required": false,
            "schema": {
              "default": false,
              "title": "Refresh State",
              "type": "boolean"
            }
          },
          {
            "description": "When `False`, skip the subtree usage read and return null usage fields with `usage_included=False`. Display clients can independently request this route with `include_usage=true`, `include_items=false`, `include_liveness=false`, and `refresh_state=false`.",
            "in": "query",
            "name": "include_usage",
            "required": false,
            "schema": {
              "default": true,
              "title": "Include Usage",
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SessionResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Session",
        "tags": [
          "sessions"
        ]
      },
      "patch": {
        "description": "Update a session's mutable fields. When `runner_id` is\nprovided, this is the mutable affinity primitive for the Alpha\nrunner-state pivot: create-bind, resume-bind, and recover-bind\nall send the currently registered runner id, and the server\natomically replaces `conversations.runner_id` with that\nvalue using last-write-wins semantics. Title, labels, and\nreasoning-effort updates remain supported for existing\nsessions clients.\n\n**Parameters**\n\n- `body` \u2014 The validated `UpdateSessionRequest`.\n\n**Returns:** The updated `SessionResponse` snapshot, with `items` always empty \u2014 PATCH callers use only scalar fields, and transcripts are served by `GET /sessions/{id}/items`.\n\n**Raises**\n\n- `OmnigentError` \u2014 400 if the runner is not registered; 404 if no session exists.",
        "operationId": "update_session_v1_sessions__session_id__patch",
        "parameters": [
          {
            "description": "Session/conversation identifier, e.g. `\"conv_abc123\"`.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          },
          {
            "description": "When `False`, skip usage aggregation in the response. Metadata writes during native launch do not need it.",
            "in": "query",
            "name": "include_usage",
            "required": false,
            "schema": {
              "default": true,
              "title": "Include Usage",
              "type": "boolean"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateSessionRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SessionResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Update Session",
        "tags": [
          "sessions"
        ]
      }
    },
    "/v1/sessions/{session_id}/agent": {
      "get": {
        "description": "Return the `AgentObject` for the session's bound agent.\n\nReplaces the standalone `GET /api/agents/{id}` endpoint by\nresolving the agent through the session's `agent_id` foreign\nkey. The caller only needs to know the session id.\n\n**Returns:** The bound agent's `AgentObject`.\n\n**Raises**\n\n- `OmnigentError` \u2014 If the session or agent is not found.",
        "operationId": "get_session_agent_v1_sessions__session_id__agent_get",
        "parameters": [
          {
            "description": "Session identifier, e.g. `\"conv_abc123\"`.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AgentObject"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Session Agent",
        "tags": [
          "sessions"
        ]
      },
      "put": {
        "description": "Replace the session's agent bundle with a new upload.\n\nValidates the new bundle, checks that the spec name matches\nthe existing agent, stores the bundle under a\ncontent-addressed key, updates the agent row, and warm-swaps\nthe cache. Idempotent when the bundle content is unchanged.\nRequires session-owner permission because a bundle can replace MCP servers.\n\n**Parameters**\n\n- `bundle` \u2014 Uploaded `.tar.gz` agent bundle file.\n\n**Returns:** The updated `AgentObject`.\n\n**Raises**\n\n- `OmnigentError` \u2014 If the session or agent is not found, the bundle is invalid, or the spec name doesn't match.",
        "operationId": "update_session_agent_v1_sessions__session_id__agent_put",
        "parameters": [
          {
            "description": "Session identifier, e.g. `\"conv_abc123\"`.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/Body_update_session_agent_v1_sessions__session_id__agent_put"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AgentObject"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Update Session Agent",
        "tags": [
          "sessions"
        ]
      }
    },
    "/v1/sessions/{session_id}/agent-title": {
      "post": {
        "description": "Apply title requirements to an agent proposal before a guarded rename.",
        "operationId": "rename_session_from_agent_v1_sessions__session_id__agent_title_post",
        "parameters": [
          {
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AutomaticSessionRenameRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AutomaticSessionRenameResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Rename Session From Agent",
        "tags": [
          "sessions"
        ]
      }
    },
    "/v1/sessions/{session_id}/agent/contents": {
      "get": {
        "description": "Download the raw `.tar.gz` agent bundle for the session's\nbound agent.\n\nReplaces `GET /api/agents/{id}/contents`. Runners call this\non cache miss to fetch the spec + bundled files.\n\n**Returns:** Raw bundle bytes as `application/gzip`.\n\n**Raises**\n\n- `OmnigentError` \u2014 If the session, agent, or bundle is not found.",
        "operationId": "get_session_agent_contents_v1_sessions__session_id__agent_contents_get",
        "parameters": [
          {
            "description": "Session identifier, e.g. `\"conv_abc123\"`.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/gzip": {}
            },
            "description": "Successful Response"
          },
          "404": {
            "description": "Session or agent not found"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Session Agent Contents",
        "tags": [
          "sessions"
        ]
      }
    },
    "/v1/sessions/{session_id}/agent/mcp-servers": {
      "get": {
        "description": "List safe MCP server summaries for a session's bound agent.",
        "operationId": "list_mcp_servers_v1_sessions__session_id__agent_mcp_servers_get",
        "parameters": [
          {
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response List Mcp Servers V1 Sessions  Session Id  Agent Mcp Servers Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Mcp Servers",
        "tags": [
          "session_mcp_servers"
        ]
      },
      "post": {
        "description": "Create one MCP server declaration on a session-scoped agent.",
        "operationId": "create_mcp_server_v1_sessions__session_id__agent_mcp_servers_post",
        "parameters": [
          {
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpsertMCPServerRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MCPServerSummary"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Create Mcp Server",
        "tags": [
          "session_mcp_servers"
        ]
      }
    },
    "/v1/sessions/{session_id}/agent/mcp-servers/{server_name}": {
      "delete": {
        "description": "Delete one MCP server declaration from a session-scoped agent.",
        "operationId": "delete_mcp_server_v1_sessions__session_id__agent_mcp_servers__server_name__delete",
        "parameters": [
          {
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "server_name",
            "required": true,
            "schema": {
              "title": "Server Name",
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Delete Mcp Server",
        "tags": [
          "session_mcp_servers"
        ]
      },
      "put": {
        "description": "Replace one MCP server declaration on a session-scoped agent.",
        "operationId": "update_mcp_server_v1_sessions__session_id__agent_mcp_servers__server_name__put",
        "parameters": [
          {
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "server_name",
            "required": true,
            "schema": {
              "title": "Server Name",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpsertMCPServerRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MCPServerSummary"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Update Mcp Server",
        "tags": [
          "session_mcp_servers"
        ]
      }
    },
    "/v1/sessions/{session_id}/auto-title": {
      "post": {
        "description": "Replace the deterministic first-message title when still current.",
        "operationId": "automatically_rename_session_v1_sessions__session_id__auto_title_post",
        "parameters": [
          {
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AutomaticSessionRenameRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AutomaticSessionRenameResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Automatically Rename Session",
        "tags": [
          "sessions"
        ]
      }
    },
    "/v1/sessions/{session_id}/child_sessions": {
      "get": {
        "description": "List sub-agent (child) sessions under a parent session.\n\nReturns a page of `ChildSessionSummary` objects\nderived from child conversations (`kind=\"sub_agent\"`,\n`parent_conversation_id=session_id`) plus each child's\nlatest task. Powers the web / REPL debug surfaces' \"child\nsessions\" panel without parsing parent\n`function_call_output` JSON handles. Pagination contract\nmatches `list_session_items` so existing client code\ncan reuse the same cursor logic.\n\n**Returns:** A `PaginatedList` of `ChildSessionSummary` objects.\n\n**Raises**\n\n- `OmnigentError` \u2014 403 if the caller lacks READ on `session_id`; 404 if no session exists there.",
        "operationId": "list_child_sessions_v1_sessions__session_id__child_sessions_get",
        "parameters": [
          {
            "description": "Parent session/conversation identifier, e.g. `\"conv_abc123\"`.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          },
          {
            "description": "Maximum number of children to return (1-1000, default 20 \u2014 sub-agent fan-out is typically sparse compared to conversation items).",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 20,
              "maximum": 1000,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "description": "Cursor \u2014 return children whose id appears after this one in sort order, e.g. `\"conv_child123\"`.",
            "in": "query",
            "name": "after",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "After"
            }
          },
          {
            "description": "Cursor \u2014 return children before this one.",
            "in": "query",
            "name": "before",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Before"
            }
          },
          {
            "description": "Sort direction, `\"desc\"` (newest-first, default) or `\"asc\"`. Sort column is `created_at`.",
            "in": "query",
            "name": "order",
            "required": false,
            "schema": {
              "default": "desc",
              "pattern": "^(asc|desc)$",
              "title": "Order",
              "type": "string"
            }
          },
          {
            "description": "When set, only return children whose title starts with this agent type (the segment before the `\":\"`). Combined with `session_name` to form the exact title `\"{tool}:{session_name}\"` for server-side filtering.",
            "in": "query",
            "name": "tool",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Tool"
            }
          },
          {
            "description": "When set alongside `tool`, only return children whose title matches `\"{tool}:{session_name}\"` exactly.",
            "in": "query",
            "name": "session_name",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Session Name"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChildSessionList"
                }
              }
            },
            "description": "Successful Response"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "The `after`/`before` cursor names an item that no longer exists (it was deleted, or archived out of the filtered set) so the keyset bound cannot be resolved. The `error.code` is `stale_cursor`. Enumeration cannot continue from this cursor: restart from the first page, without a cursor."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Child Sessions",
        "tags": [
          "sessions"
        ]
      }
    },
    "/v1/sessions/{session_id}/codex_goal": {
      "delete": {
        "description": "Clear the current Codex app-server goal.\n\n**Returns:** Whether Codex removed an existing goal.\n\n**Raises**\n\n- `OmnigentError` \u2014 400 for non-Codex sessions, 404 for missing sessions, or 503 when no live Codex runner can clear the goal.",
        "operationId": "clear_codex_goal_v1_sessions__session_id__codex_goal_delete",
        "parameters": [
          {
            "description": "Session/conversation identifier, e.g. `\"conv_abc123\"`.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClearCodexGoalResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Clear Codex Goal",
        "tags": [
          "sessions"
        ]
      },
      "get": {
        "description": "Read the current Codex app-server goal for a Codex-native session.\n\n**Returns:** Current Codex goal state, or `goal=None` when no goal is set.\n\n**Raises**\n\n- `OmnigentError` \u2014 400 for non-Codex sessions, 404 for missing sessions, or 503 when no live Codex runner can read the goal.",
        "operationId": "get_codex_goal_v1_sessions__session_id__codex_goal_get",
        "parameters": [
          {
            "description": "Session/conversation identifier, e.g. `\"conv_abc123\"`.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CodexGoalResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Codex Goal",
        "tags": [
          "sessions"
        ]
      },
      "put": {
        "description": "Set or replace the current Codex app-server goal.\n\n**Parameters**\n\n- `body` \u2014 Goal objective, optional token budget, and optional user-selected status.\n\n**Returns:** Current Codex goal state after the update.\n\n**Raises**\n\n- `OmnigentError` \u2014 400 for non-Codex sessions or blank objectives, 404 for missing sessions, or 503 when no live Codex runner can update the goal.",
        "operationId": "set_codex_goal_v1_sessions__session_id__codex_goal_put",
        "parameters": [
          {
            "description": "Session/conversation identifier, e.g. `\"conv_abc123\"`.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetCodexGoalRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CodexGoalResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Set Codex Goal",
        "tags": [
          "sessions"
        ]
      }
    },
    "/v1/sessions/{session_id}/codex_goal/status": {
      "patch": {
        "description": "Pause or resume the current Codex app-server goal.\n\nCodex exposes this through `thread/goal/set` with only a status\nfield. The Omnigent API keeps that distinct from objective/budget\nedits so callers can implement Pause/Resume controls without\nresending the goal text.\n\n**Parameters**\n\n- `body` \u2014 Target status. `\"paused\"` pauses the goal and `\"active\"` resumes it.\n\n**Returns:** Current Codex goal state after the status update.\n\n**Raises**\n\n- `OmnigentError` \u2014 400 for non-Codex sessions, 404 for missing sessions, or 503 when no live Codex runner can update the goal.",
        "operationId": "update_codex_goal_status_v1_sessions__session_id__codex_goal_status_patch",
        "parameters": [
          {
            "description": "Session/conversation identifier, e.g. `\"conv_abc123\"`.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateCodexGoalStatusRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CodexGoalResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Update Codex Goal Status",
        "tags": [
          "sessions"
        ]
      }
    },
    "/v1/sessions/{session_id}/comments": {
      "get": {
        "description": "List comments for a session, optionally filtered by file.\n\nRequires `LEVEL_READ` on the session in multi-user mode.\n\n**Returns:** List of serialized comment dicts.\n\n**Raises**\n\n- `OmnigentError` \u2014 401/403/404 if the user lacks read permission.",
        "operationId": "list_comments_v1_sessions__session_id__comments_get",
        "parameters": [
          {
            "description": "The session to query, e.g. `\"conv_abc123\"`.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          },
          {
            "description": "When provided, only return comments for this file, e.g. `\"src/App.tsx\"`.",
            "in": "query",
            "name": "path",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Path"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "items": {
                    "additionalProperties": true,
                    "type": "object"
                  },
                  "title": "Response List Comments V1 Sessions  Session Id  Comments Get",
                  "type": "array"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Comments",
        "tags": [
          "comments"
        ]
      },
      "post": {
        "description": "Create a new review comment.\n\nRequires `LEVEL_EDIT` on the session in multi-user mode.\n\n**Parameters**\n\n- `body` \u2014 Comment payload including path, body text, and the two range fields (start_index, end_index).\n\n**Returns:** The created comment as a serialized dict.\n\n**Raises**\n\n- `OmnigentError` \u2014 401/403/404 if the user lacks edit permission.",
        "operationId": "add_comment_v1_sessions__session_id__comments_post",
        "parameters": [
          {
            "description": "The owning session, e.g. `\"conv_abc123\"`.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AddCommentRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Add Comment V1 Sessions  Session Id  Comments Post",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Add Comment",
        "tags": [
          "comments"
        ]
      }
    },
    "/v1/sessions/{session_id}/comments/send": {
      "post": {
        "description": "Mark comments as addressed and format them into an agent message.\n\nFetches each requested comment, marks it `addressed`,\nand formats the full set into a grouped, sorted message string\nsuitable for pasting into the chat composer.\n\nRequires `LEVEL_EDIT` on the session in multi-user mode because\nit transitions comment status from `draft` to `addressed`.\n\n**Parameters**\n\n- `body` \u2014 List of comment IDs to send, with an optional custom instruction prefix.\n\n**Returns:** `{\"formatted_message\": str, \"sent_comment_ids\": list[str]}`.\n\n**Raises**\n\n- `OmnigentError` \u2014 401/403/404 if the user lacks edit permission, or 404 if any requested comment is not found or does not belong to this session.",
        "operationId": "send_to_agent_v1_sessions__session_id__comments_send_post",
        "parameters": [
          {
            "description": "The owning session, e.g. `\"conv_abc123\"`.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SendCommentsRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Send To Agent V1 Sessions  Session Id  Comments Send Post",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Send To Agent",
        "tags": [
          "comments"
        ]
      }
    },
    "/v1/sessions/{session_id}/comments/{comment_id}": {
      "delete": {
        "description": "Delete a comment.\n\nRequires `LEVEL_EDIT` on the session in multi-user mode, and\nadditionally that the caller is the comment's author \u2014 one\ncollaborator may not delete another user's comment.\n\n**Returns:** `{\"deleted\": true}`.\n\n**Raises**\n\n- `OmnigentError` \u2014 401/403/404 if the user lacks edit permission, 403 if the caller is not the comment's author, or 404 if the comment is not found or does not belong to this session.",
        "operationId": "delete_comment_v1_sessions__session_id__comments__comment_id__delete",
        "parameters": [
          {
            "description": "The owning session, e.g. `\"conv_abc123\"`.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          },
          {
            "description": "The comment to delete, e.g. `\"a1b2c3d4-...\"`.",
            "in": "path",
            "name": "comment_id",
            "required": true,
            "schema": {
              "title": "Comment Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Delete Comment V1 Sessions  Session Id  Comments  Comment Id  Delete",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Delete Comment",
        "tags": [
          "comments"
        ]
      },
      "patch": {
        "description": "Update a comment's status and/or body text.\n\nRequires `LEVEL_EDIT` on the session in multi-user mode.\nEditing the `body` additionally requires the caller to be the\ncomment's author: rewriting another user's comment is forbidden,\nwhile changing only the `status` (e.g. marking it `\"addressed\"`)\nstays open to any editor as a shared review-workflow action.\n\n**Parameters**\n\n- `body` \u2014 Fields to update; `None` fields are left unchanged.\n\n**Returns:** The updated serialized comment.\n\n**Raises**\n\n- `OmnigentError` \u2014 401/403/404 if the user lacks edit permission, 403 if a body edit is attempted on another user's comment, or 404 if the comment is not found.",
        "operationId": "update_comment_v1_sessions__session_id__comments__comment_id__patch",
        "parameters": [
          {
            "description": "The owning session, e.g. `\"conv_abc123\"`.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          },
          {
            "description": "The comment to update, e.g. `\"a1b2c3d4-...\"`.",
            "in": "path",
            "name": "comment_id",
            "required": true,
            "schema": {
              "title": "Comment Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateCommentRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Update Comment V1 Sessions  Session Id  Comments  Comment Id  Patch",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Update Comment",
        "tags": [
          "comments"
        ]
      }
    },
    "/v1/sessions/{session_id}/items": {
      "get": {
        "description": "List items in a session with cursor-based pagination.\n\nDelegates to the conversation items store \u2014 session_id is\nthe conversation_id. Same pagination contract as\n`GET /v1/conversations/{id}/items`.\n\n**Returns:** A `PaginatedList` of conversation items.\n\n**Raises**\n\n- `OmnigentError` \u2014 404 if no session exists.",
        "operationId": "list_session_items_v1_sessions__session_id__items_get",
        "parameters": [
          {
            "description": "Session/conversation identifier, e.g. `\"conv_abc123\"`.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          },
          {
            "description": "Maximum number of items to return (1-1000, default 100).",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 100,
              "maximum": 1000,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "description": "Cursor \u2014 return items after this item ID, e.g. `\"msg_abc123\"`.",
            "in": "query",
            "name": "after",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "After"
            }
          },
          {
            "description": "Cursor \u2014 return items before this item ID.",
            "in": "query",
            "name": "before",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Before"
            }
          },
          {
            "description": "Sort order, `\"asc\"` (chronological, default) or `\"desc\"`.",
            "in": "query",
            "name": "order",
            "required": false,
            "schema": {
              "default": "asc",
              "pattern": "^(asc|desc)$",
              "title": "Order",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaginatedList"
                }
              }
            },
            "description": "Successful Response"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "The `after`/`before` cursor names an item that no longer exists (it was deleted, or archived out of the filtered set) so the keyset bound cannot be resolved. The `error.code` is `stale_cursor`. Enumeration cannot continue from this cursor: restart from the first page, without a cursor."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Session Items",
        "tags": [
          "sessions"
        ]
      }
    },
    "/v1/sessions/{session_id}/labels": {
      "get": {
        "description": "Return only the labels for a session.\n\nNative runner bridge setup needs labels during harness spawn,\nbut the full session snapshot also loads history, skills,\nrunner status, and agent metadata. This endpoint keeps that\nspawn-time dependency to one authorized conversation read.\n\n**Returns:** The session id and labels.\n\n**Raises**\n\n- `OmnigentError` \u2014 404 if no session exists.",
        "operationId": "get_session_labels_v1_sessions__session_id__labels_get",
        "parameters": [
          {
            "description": "Session/conversation identifier, e.g. `\"conv_abc123\"`.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SessionLabelsResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Session Labels",
        "tags": [
          "sessions"
        ]
      }
    },
    "/v1/sessions/{session_id}/model-override/reset": {
      "post": {
        "description": "Retire a rejected pick after fallback without replacing a newer selection.",
        "operationId": "reset_session_model_override_v1_sessions__session_id__model_override_reset_post",
        "parameters": [
          {
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ResetSessionModelOverrideRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResetSessionModelOverrideResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Reset Session Model Override",
        "tags": [
          "sessions"
        ]
      }
    },
    "/v1/sessions/{session_id}/owner": {
      "get": {
        "description": "Return the owner of a session.\n\nRequires read-level access.\n\n**Returns:** `{\"owner\": \"<user_id>\"}` or `{\"owner\": null}`.",
        "operationId": "get_session_owner_v1_sessions__session_id__owner_get",
        "parameters": [
          {
            "description": "Session to look up, e.g. `\"conv_abc123\"`.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Session Owner",
        "tags": [
          "sessions"
        ]
      }
    },
    "/v1/sessions/{session_id}/permissions": {
      "get": {
        "description": "List permission grants on a session with cursor pagination.\n\nRequires manage-level access.\n\n**Returns:** `{\"permissions\": [...], \"next_cursor\": str|null}`.\n\n**Raises**\n\n- `OmnigentError` \u2014 404 if no session or no access.",
        "operationId": "list_permissions_v1_sessions__session_id__permissions_get",
        "parameters": [
          {
            "description": "Session to list grants for, e.g. `\"conv_abc123\"`.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          },
          {
            "description": "Max grants to return (1\u20131000, default 100).",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 100,
              "maximum": 1000,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "description": "Cursor: user_id to start after",
            "in": "query",
            "name": "after",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Cursor: user_id to start after",
              "title": "After"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Permissions",
        "tags": [
          "sessions"
        ]
      },
      "put": {
        "description": "Grant or update a permission on a session.\n\nRequires manage-level access. Upserts the grant \u2014 can\nupgrade or downgrade an existing level. Auto-creates the\ngrantee user if they don't exist yet.\n\n**Parameters**\n\n- `body` \u2014 The grant request with `user_id` and `level`.\n\n**Returns:** The resulting `PermissionObject`.\n\n**Raises**\n\n- `OmnigentError` \u2014 404 if no session or no access, 401 if unauthenticated.",
        "operationId": "grant_permission_v1_sessions__session_id__permissions_put",
        "parameters": [
          {
            "description": "Session to grant access to, e.g. `\"conv_abc123\"`.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GrantPermissionRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PermissionObject"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Grant Permission",
        "tags": [
          "sessions"
        ]
      }
    },
    "/v1/sessions/{session_id}/permissions/{target_user_id}": {
      "delete": {
        "description": "Revoke a permission on a session \u2014 someone else's, or your own.\n\nTwo shapes, one endpoint:\n\n* *Revoke* \u2014 removing **another** user's grant is a management\n  action and needs manage access.\n* *Leave* \u2014 removing **your own** grant (\"unshare myself\", so a\n  shared session stops cluttering your sidebar) needs only read\n  access, since giving up access requires no privilege.\n\nEither way the owner grant is protected: it is what keeps the\nsession reachable, so revoking it would orphan the session. That\nguard covers the self case too \u2014 an owner cannot leave, and\narchives or deletes instead. A manage-level *grantee* is still a\nguest and may leave. Leaving records no lasting refusal, so the\nowner re-granting brings the session back.\n\nIdempotent: 204 whether or not a grant existed.\n\n**Returns:** 204 No Content.\n\n**Raises**\n\n- `OmnigentError` \u2014 404 if no session or no access, 403 when the target holds the owner grant, 400 when leaving a sub-agent session, 401 if unauthenticated.",
        "operationId": "revoke_permission_v1_sessions__session_id__permissions__target_user_id__delete",
        "parameters": [
          {
            "description": "Session to revoke access from, e.g. `\"conv_abc123\"`.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          },
          {
            "description": "User whose grant to revoke, or the caller's own id to leave, e.g. `\"alice@example.com\"`.",
            "in": "path",
            "name": "target_user_id",
            "required": true,
            "schema": {
              "title": "Target User Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Revoke Permission",
        "tags": [
          "sessions"
        ]
      }
    },
    "/v1/sessions/{session_id}/policies": {
      "get": {
        "description": "List all policies for a session.\n\nReturns both store-persisted (`source=\"session\"`) and\nspec-declared (`source=\"spec\"`) policies. Spec policies\nhave `id=None` and cannot be patched or deleted.\n\nRequires `LEVEL_READ` on the session in multi-user mode.\n\n**Returns:** `{\"object\": \"list\", \"data\": [...]}`.\n\n**Raises**\n\n- `OmnigentError` \u2014 401/403 if the user lacks read permission, 404 if the session is not found.",
        "operationId": "list_policies_v1_sessions__session_id__policies_get",
        "parameters": [
          {
            "description": "The session to query, e.g. `\"conv_abc123\"`.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response List Policies V1 Sessions  Session Id  Policies Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Policies",
        "tags": [
          "session_policies"
        ]
      },
      "post": {
        "description": "Create a new session policy.\n\nRequires `LEVEL_EDIT` on the session in multi-user mode.\n\n**Parameters**\n\n- `body` \u2014 Policy payload including name, type, and handler.\n\n**Returns:** The created policy as a serialized dict.\n\n**Raises**\n\n- `OmnigentError` \u2014 401/403 if the user lacks edit permission, 404 if the session is not found, or 409 if a policy with the same name already exists.",
        "operationId": "create_policy_v1_sessions__session_id__policies_post",
        "parameters": [
          {
            "description": "The owning session, e.g. `\"conv_abc123\"`.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateSessionPolicyRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Create Policy V1 Sessions  Session Id  Policies Post",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Create Policy",
        "tags": [
          "session_policies"
        ]
      }
    },
    "/v1/sessions/{session_id}/policies/evaluate": {
      "post": {
        "description": "Generic policy evaluation endpoint (proto-compatible).\n\nAccepts an `EvaluationRequest` JSON body whose `event`\nfield carries the phase (`PHASE_TOOL_CALL`,\n`PHASE_TOOL_RESULT`, `PHASE_LLM_REQUEST`,\n`PHASE_LLM_RESPONSE`), the event data, and optional\ncontext. Returns an `EvaluationResponse` with the policy\nverdict (`result`), an optional `reason`, and optional\n`data` for content-rewriting policies.\n\nUsed by Claude Code's `PreToolUse` and `PostToolUse`\ncommand hooks (via `omnigent.harnesses.claude_native.hook`) to\nevaluate admin policies on native tool calls. Also usable\nby any client that speaks the proto-compatible JSON schema.\n\n**Returns:** `EvaluationResponse` JSON with `result`, `reason`, and optional `data`.\n\n**Raises**\n\n- `OmnigentError` \u2014 404 if the session doesn't exist, 400 if the body is malformed.",
        "operationId": "evaluate_policy_v1_sessions__session_id__policies_evaluate_post",
        "parameters": [
          {
            "description": "Omnigent conversation id from the URL path.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Evaluate Policy",
        "tags": [
          "sessions"
        ]
      }
    },
    "/v1/sessions/{session_id}/policies/{policy_id}": {
      "delete": {
        "description": "Delete a session policy.\n\nIdempotent \u2014 deleting a missing policy returns 204.\nRequires `LEVEL_EDIT`.\n\n**Returns:** `{\"deleted\": true}`.\n\n**Raises**\n\n- `OmnigentError` \u2014 401/403 if the user lacks edit permission.",
        "operationId": "delete_policy_v1_sessions__session_id__policies__policy_id__delete",
        "parameters": [
          {
            "description": "The owning session, e.g. `\"conv_abc123\"`.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          },
          {
            "description": "The policy to delete, e.g. `\"pol_abc123\"`.",
            "in": "path",
            "name": "policy_id",
            "required": true,
            "schema": {
              "title": "Policy Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Delete Policy V1 Sessions  Session Id  Policies  Policy Id  Delete",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Delete Policy",
        "tags": [
          "session_policies"
        ]
      },
      "get": {
        "description": "Get a single session policy.\n\nRequires `LEVEL_READ` on the session in multi-user mode.\n\n**Returns:** The policy as a serialized dict.\n\n**Raises**\n\n- `OmnigentError` \u2014 401/403 if the user lacks read permission, or 404 if the policy is not found.",
        "operationId": "get_policy_v1_sessions__session_id__policies__policy_id__get",
        "parameters": [
          {
            "description": "The owning session, e.g. `\"conv_abc123\"`.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          },
          {
            "description": "The policy to retrieve, e.g. `\"pol_abc123\"`.",
            "in": "path",
            "name": "policy_id",
            "required": true,
            "schema": {
              "title": "Policy Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Get Policy V1 Sessions  Session Id  Policies  Policy Id  Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Policy",
        "tags": [
          "session_policies"
        ]
      },
      "patch": {
        "description": "Update a session policy's mutable fields.\n\n`type` is immutable \u2014 the caller must delete and\nre-create to change it. Requires `LEVEL_EDIT`.\n\n**Parameters**\n\n- `body` \u2014 Fields to update; `None` fields are left unchanged.\n\n**Returns:** The updated policy as a serialized dict.\n\n**Raises**\n\n- `OmnigentError` \u2014 401/403 if the user lacks edit permission, 404 if the policy is not found, or 409 if renaming would collide with another policy in this session.",
        "operationId": "update_policy_v1_sessions__session_id__policies__policy_id__patch",
        "parameters": [
          {
            "description": "The owning session, e.g. `\"conv_abc123\"`.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          },
          {
            "description": "The policy to update, e.g. `\"pol_abc123\"`.",
            "in": "path",
            "name": "policy_id",
            "required": true,
            "schema": {
              "title": "Policy Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateSessionPolicyRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Update Policy V1 Sessions  Session Id  Policies  Policy Id  Patch",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Update Policy",
        "tags": [
          "session_policies"
        ]
      }
    },
    "/v1/sessions/{session_id}/read-state": {
      "put": {
        "description": "Set the calling user's read-state for one session.\n\nRequires `LEVEL_READ` on the session in multi-user mode \u2014 you can\nonly track read-state for sessions you can see. Stores the values\nverbatim (the client enforces the baseline's monotonicity and the\nunread semantics); the server does not interpret them against\nsession status. Returns `204` \u2014 the client already has the\noptimistic state and re-reads the authoritative value on the next\n`GET /v1/sessions` poll.\n\n**Parameters**\n\n- `body` \u2014 The validated `ReadStatePutRequest`.\n\n**Returns:** An empty `204 No Content` response.\n\n**Raises**\n\n- `OmnigentError` \u2014 403 if the caller lacks read access.",
        "operationId": "put_read_state_v1_sessions__session_id__read_state_put",
        "parameters": [
          {
            "description": "Session/conversation identifier.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReadStatePutRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Put Read State",
        "tags": [
          "sessions"
        ]
      }
    },
    "/v1/sessions/{session_id}/resources": {
      "get": {
        "description": "Return the runner-authoritative resource inventory for a session.\n\nRequires the session to be bound to a runner via\n`PATCH /v1/sessions/{id}`; raises `conflict` otherwise.\nThe server validates the session exists, then proxies to the\nrunner's `GET /v1/sessions/{id}/resources` endpoint. In\nunit-test / in-process setups with no runner router/client, the\nroute falls back to adapting the local terminal registry.",
        "operationId": "list_session_resources_v1_sessions__session_id__resources_get",
        "parameters": [
          {
            "description": "Session/conversation identifier, e.g. `\"conv_abc123\"`.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          },
          {
            "description": "Optional resource-type filter, e.g. `\"environment\"` / `\"terminal\"` / `\"file\"`. Forwarded to the runner (its registry applies it) and honored by the local-registry fallback and the file-store merge below.",
            "in": "query",
            "name": "type",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Type"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SessionResourcePaginatedList"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Session Resources",
        "tags": [
          "session_resources"
        ]
      }
    },
    "/v1/sessions/{session_id}/resources/environments": {
      "get": {
        "description": "Return only environment resources for a session.\n\n**Returns:** `PaginatedList` of environment resources.",
        "operationId": "list_session_environments_v1_sessions__session_id__resources_environments_get",
        "parameters": [
          {
            "description": "Session/conversation identifier.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Session Environments",
        "tags": [
          "session_resources"
        ]
      }
    },
    "/v1/sessions/{session_id}/resources/environments/{environment_id}": {
      "get": {
        "description": "Return a single environment resource by id.\n\n**Returns:** The environment resource object.",
        "operationId": "get_session_environment_v1_sessions__session_id__resources_environments__environment_id__get",
        "parameters": [
          {
            "description": "Session/conversation identifier.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          },
          {
            "description": "Opaque environment resource id, e.g. `\"default\"`.",
            "in": "path",
            "name": "environment_id",
            "required": true,
            "schema": {
              "title": "Environment Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Session Environment",
        "tags": [
          "session_resources"
        ]
      }
    },
    "/v1/sessions/{session_id}/resources/environments/{environment_id}/changes": {
      "get": {
        "description": "List all files changed since session start (flat, registry-backed).\n\nReturns the watchdog change set for the session \u2014 every file\ncreated, modified, or deleted since the session began, regardless\nof directory depth.  Use for the flat \"changed files\" view.\n\n**Returns:** Flat list of changed filesystem entries with `status`.",
        "operationId": "list_environment_filesystem_changes_v1_sessions__session_id__resources_environments__environment_id__changes_get",
        "parameters": [
          {
            "description": "Session/conversation identifier.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          },
          {
            "description": "Environment resource id.",
            "in": "path",
            "name": "environment_id",
            "required": true,
            "schema": {
              "title": "Environment Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Environment Filesystem Changes",
        "tags": [
          "session_resources"
        ]
      }
    },
    "/v1/sessions/{session_id}/resources/environments/{environment_id}/filesystem": {
      "get": {
        "description": "List root directory of an environment.\n\n**Returns:** PaginatedList of filesystem entries.",
        "operationId": "list_environment_root_v1_sessions__session_id__resources_environments__environment_id__filesystem_get",
        "parameters": [
          {
            "description": "Session/conversation identifier.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          },
          {
            "description": "Environment resource id.",
            "in": "path",
            "name": "environment_id",
            "required": true,
            "schema": {
              "title": "Environment Id",
              "type": "string"
            }
          },
          {
            "description": "Maximum number of entries to return (1-1000, default 20).",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 20,
              "maximum": 1000,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "description": "Cursor entry id for forward pagination.",
            "in": "query",
            "name": "after",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "After"
            }
          },
          {
            "description": "Cursor entry id for backward pagination.",
            "in": "query",
            "name": "before",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Before"
            }
          },
          {
            "description": "Sort order, `\"asc\"` or `\"desc\"`.",
            "in": "query",
            "name": "order",
            "required": false,
            "schema": {
              "default": "desc",
              "pattern": "^(asc|desc)$",
              "title": "Order",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Environment Root",
        "tags": [
          "session_resources"
        ]
      }
    },
    "/v1/sessions/{session_id}/resources/environments/{environment_id}/filesystem/{relative_path}": {
      "delete": {
        "description": "Delete a file or directory in an environment.\n\n**Returns:** Delete result.",
        "operationId": "delete_environment_path_v1_sessions__session_id__resources_environments__environment_id__filesystem__relative_path__delete",
        "parameters": [
          {
            "description": "Session/conversation identifier.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          },
          {
            "description": "Environment resource id.",
            "in": "path",
            "name": "environment_id",
            "required": true,
            "schema": {
              "title": "Environment Id",
              "type": "string"
            }
          },
          {
            "description": "Path relative to environment root.",
            "in": "path",
            "name": "relative_path",
            "required": true,
            "schema": {
              "title": "Relative Path",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Delete Environment Path",
        "tags": [
          "session_resources"
        ]
      },
      "get": {
        "description": "Read a file or list a directory in an environment.\n\n**Returns:** File content or directory listing, or the raw file.",
        "operationId": "read_or_list_environment_path_v1_sessions__session_id__resources_environments__environment_id__filesystem__relative_path__get",
        "parameters": [
          {
            "description": "Session/conversation identifier.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          },
          {
            "description": "Environment resource id.",
            "in": "path",
            "name": "environment_id",
            "required": true,
            "schema": {
              "title": "Environment Id",
              "type": "string"
            }
          },
          {
            "description": "Path relative to environment root.",
            "in": "path",
            "name": "relative_path",
            "required": true,
            "schema": {
              "title": "Relative Path",
              "type": "string"
            }
          },
          {
            "description": "Maximum number of entries to return for directory listings (1-1000, default 20). Ignored for file reads.",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 20,
              "maximum": 1000,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "description": "Cursor entry id for forward pagination.",
            "in": "query",
            "name": "after",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "After"
            }
          },
          {
            "description": "Cursor entry id for backward pagination.",
            "in": "query",
            "name": "before",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Before"
            }
          },
          {
            "description": "Sort order, `\"asc\"` or `\"desc\"`.",
            "in": "query",
            "name": "order",
            "required": false,
            "schema": {
              "default": "desc",
              "pattern": "^(asc|desc)$",
              "title": "Order",
              "type": "string"
            }
          },
          {
            "description": "When `True`, stream the complete file as an attachment with no size cap instead of the capped JSON envelope. A directory rejects it with 400.",
            "in": "query",
            "name": "download",
            "required": false,
            "schema": {
              "default": false,
              "title": "Download",
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              },
              "application/octet-stream": {
                "schema": {
                  "format": "binary",
                  "type": "string"
                }
              }
            },
            "description": "File content or directory listing as JSON; the raw file as an attachment when `download=true`."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Read Or List Environment Path",
        "tags": [
          "session_resources"
        ]
      },
      "patch": {
        "description": "Edit a file in an environment via text replacement.\n\n**Returns:** Edit result.",
        "operationId": "edit_environment_file_v1_sessions__session_id__resources_environments__environment_id__filesystem__relative_path__patch",
        "parameters": [
          {
            "description": "Session/conversation identifier.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          },
          {
            "description": "Environment resource id.",
            "in": "path",
            "name": "environment_id",
            "required": true,
            "schema": {
              "title": "Environment Id",
              "type": "string"
            }
          },
          {
            "description": "Path relative to environment root.",
            "in": "path",
            "name": "relative_path",
            "required": true,
            "schema": {
              "title": "Relative Path",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Edit Environment File",
        "tags": [
          "session_resources"
        ]
      },
      "put": {
        "description": "Write/replace a file in an environment.\n\n**Returns:** Write result.",
        "operationId": "write_environment_file_v1_sessions__session_id__resources_environments__environment_id__filesystem__relative_path__put",
        "parameters": [
          {
            "description": "Session/conversation identifier.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          },
          {
            "description": "Environment resource id.",
            "in": "path",
            "name": "environment_id",
            "required": true,
            "schema": {
              "title": "Environment Id",
              "type": "string"
            }
          },
          {
            "description": "Path relative to environment root.",
            "in": "path",
            "name": "relative_path",
            "required": true,
            "schema": {
              "title": "Relative Path",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Write Environment File",
        "tags": [
          "session_resources"
        ]
      }
    },
    "/v1/sessions/{session_id}/resources/environments/{environment_id}/search": {
      "get": {
        "description": "Search for files recursively by name/path substring and glob filters.\n\nProxies to the runner's search endpoint.  Returns a flat list of\nmatching file entries (not directories) whose name or relative path\ncontains `q` (case-insensitive), optionally scoped by `include` /\n`exclude` globs.  Requires at least one non-whitespace character in\n`q` to prevent accidental full-tree scans.\n\n**Returns:** JSON list response with matching filesystem entries.",
        "operationId": "search_environment_files_v1_sessions__session_id__resources_environments__environment_id__search_get",
        "parameters": [
          {
            "description": "Session/conversation identifier, e.g. `\"conv_abc123\"`.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          },
          {
            "description": "Environment resource id, e.g. `\"default\"`.",
            "in": "path",
            "name": "environment_id",
            "required": true,
            "schema": {
              "title": "Environment Id",
              "type": "string"
            }
          },
          {
            "description": "Case-insensitive search substring, e.g. `\"test.md\"`. Must contain at least one non-whitespace character.",
            "in": "query",
            "name": "q",
            "required": true,
            "schema": {
              "minLength": 1,
              "pattern": ".*\\S.*",
              "title": "Q",
              "type": "string"
            }
          },
          {
            "description": "Comma-separated glob patterns scoping which files are returned, e.g. `\"*.ts,src/**\"`.",
            "in": "query",
            "name": "include",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Include"
            }
          },
          {
            "description": "Comma-separated glob patterns for files to drop, e.g. `\"**/node_modules,*.test.ts\"`.",
            "in": "query",
            "name": "exclude",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Exclude"
            }
          },
          {
            "description": "Maximum number of results (1-500, default 500).",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 500,
              "maximum": 500,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Search Environment Files",
        "tags": [
          "session_resources"
        ]
      }
    },
    "/v1/sessions/{session_id}/resources/environments/{environment_id}/search/{path}": {
      "get": {
        "description": "Search under a directory rather than the whole workspace.\n\nTakes the same path shape as the filesystem routes: relative to the\nworkspace, or absolute with a leading slash. Keeps search covering\nexactly what the file tree is showing.\n\n**Returns:** JSON list response with matching filesystem entries.",
        "operationId": "search_environment_files_under_v1_sessions__session_id__resources_environments__environment_id__search__path__get",
        "parameters": [
          {
            "description": "Session/conversation identifier.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          },
          {
            "description": "Environment resource id.",
            "in": "path",
            "name": "environment_id",
            "required": true,
            "schema": {
              "title": "Environment Id",
              "type": "string"
            }
          },
          {
            "description": "Directory to search under.",
            "in": "path",
            "name": "path",
            "required": true,
            "schema": {
              "title": "Path",
              "type": "string"
            }
          },
          {
            "description": "Case-insensitive search substring.",
            "in": "query",
            "name": "q",
            "required": true,
            "schema": {
              "minLength": 1,
              "pattern": ".*\\S.*",
              "title": "Q",
              "type": "string"
            }
          },
          {
            "description": "Comma-separated include globs.",
            "in": "query",
            "name": "include",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Include"
            }
          },
          {
            "description": "Comma-separated exclude globs.",
            "in": "query",
            "name": "exclude",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Exclude"
            }
          },
          {
            "description": "Maximum number of results (1-500, default 500).",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 500,
              "maximum": 500,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Search Environment Files Under",
        "tags": [
          "session_resources"
        ]
      }
    },
    "/v1/sessions/{session_id}/resources/environments/{environment_id}/shell": {
      "post": {
        "description": "Execute a shell command in an environment.\n\nOwner-only. A command has no path to inspect, so unlike the\nfilesystem proxy there is no workspace-relative form that could\nbe opened to collaborators: any command reaches the owner's own\nmachine, the same boundary `_browse_level` closes for absolute\npaths, and it passes no policy or approval gate on the way.\n\n**Returns:** Shell result.",
        "operationId": "run_environment_shell_v1_sessions__session_id__resources_environments__environment_id__shell_post",
        "parameters": [
          {
            "description": "Session/conversation identifier.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          },
          {
            "description": "Environment resource id.",
            "in": "path",
            "name": "environment_id",
            "required": true,
            "schema": {
              "title": "Environment Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Run Environment Shell",
        "tags": [
          "session_resources"
        ]
      }
    },
    "/v1/sessions/{session_id}/resources/files": {
      "get": {
        "description": "List files owned by a session.\n\n**Returns:** `PaginatedList` of session file resources.",
        "operationId": "list_session_files_v1_sessions__session_id__resources_files_get",
        "parameters": [
          {
            "description": "Session/conversation identifier.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          },
          {
            "description": "Maximum number of files to return.",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 20,
              "maximum": 1000,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "description": "Cursor file ID for forward pagination.",
            "in": "query",
            "name": "after",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "After"
            }
          },
          {
            "description": "Cursor file ID for backward pagination.",
            "in": "query",
            "name": "before",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Before"
            }
          },
          {
            "description": "Sort direction, `\"desc\"` or `\"asc\"`.",
            "in": "query",
            "name": "order",
            "required": false,
            "schema": {
              "default": "desc",
              "pattern": "^(asc|desc)$",
              "title": "Order",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Session Files",
        "tags": [
          "session_resources"
        ]
      },
      "post": {
        "description": "Upload a file into the session file namespace.\n\nAccepts the multipart upload shape used by session file resources.\n\n**Parameters**\n\n- `file` \u2014 The uploaded file (multipart form data).\n\n**Returns:** The session file resource object.",
        "operationId": "upload_session_file_v1_sessions__session_id__resources_files_post",
        "parameters": [
          {
            "description": "Session/conversation identifier.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/Body_upload_session_file_v1_sessions__session_id__resources_files_post"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Upload Session File",
        "tags": [
          "session_resources"
        ]
      }
    },
    "/v1/sessions/{session_id}/resources/files/{file_id}": {
      "delete": {
        "description": "Delete a session file resource and its artifact bytes.\n\n**Returns:** Deletion confirmation object.",
        "operationId": "delete_session_file_v1_sessions__session_id__resources_files__file_id__delete",
        "parameters": [
          {
            "description": "Session/conversation identifier.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          },
          {
            "description": "Unique file identifier.",
            "in": "path",
            "name": "file_id",
            "required": true,
            "schema": {
              "title": "File Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Delete Session File",
        "tags": [
          "session_resources"
        ]
      },
      "get": {
        "description": "Retrieve metadata for a session file resource.\n\nVerifies that `file_id` belongs to `session_id`.\n\n**Returns:** The session file resource object.",
        "operationId": "get_session_file_v1_sessions__session_id__resources_files__file_id__get",
        "parameters": [
          {
            "description": "Session/conversation identifier.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          },
          {
            "description": "Unique file identifier.",
            "in": "path",
            "name": "file_id",
            "required": true,
            "schema": {
              "title": "File Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Session File",
        "tags": [
          "session_resources"
        ]
      }
    },
    "/v1/sessions/{session_id}/resources/files/{file_id}/content": {
      "get": {
        "description": "Download raw content of a session file resource.\n\n**Returns:** Response with file bytes and Content-Type.",
        "operationId": "get_session_file_content_v1_sessions__session_id__resources_files__file_id__content_get",
        "parameters": [
          {
            "description": "Session/conversation identifier.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          },
          {
            "description": "Unique file identifier.",
            "in": "path",
            "name": "file_id",
            "required": true,
            "schema": {
              "title": "File Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Session File Content",
        "tags": [
          "session_resources"
        ]
      }
    },
    "/v1/sessions/{session_id}/resources/files:copy": {
      "post": {
        "description": "Copy lineage-owned files into this (destination) session.\n\nAuthorizes by spawn lineage: `body.source_session_id` must be a\nSTRICT ancestor of this session up the `parent_conversation_id`\nchain \u2014 the session may not name itself as the source. Each source\nfile is read and re-stored as a new child-scoped row owned by\n`session_id` \u2014 this preserves the session-scoping invariant (the\nchild reads its OWN copy; no cross-session read grant is created).\nValidation is all-or-nothing: an unauthorized source, a missing\nfile, or a request past the copy limits copies nothing.\n\nThe request is bounded before any blob is read: the file count and\nthe summed `StoredFile.bytes` are checked against the copy limits\nduring metadata validation, so an over-limit request is rejected\nwithout buffering a single blob. Within the limits, files are copied\none at a time (read \u2192 create \u2192 put) so peak memory is a single blob,\nnot the whole batch.\n\n**Parameters**\n\n- `body` \u2014 Source session id plus the file ids to copy.\n\n**Returns:** A `session.files.copied` object carrying the `{source_file_id: new_file_id}` mapping.",
        "operationId": "copy_session_files_v1_sessions__session_id__resources_files_copy_post",
        "parameters": [
          {
            "description": "Destination (child) session/conversation id.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CopyFilesRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Copy Session Files",
        "tags": [
          "session_resources"
        ]
      }
    },
    "/v1/sessions/{session_id}/resources/github": {
      "get": {
        "description": "Return GitHub context (repo, branch, base ref, PR) for a session.\n\nProxies to the runner, which shells out to `gh`/`git` in the\nworkspace. Returns an `available: false` payload (200) when `gh` is\nmissing or the workspace is not a git repo.\n\n**Returns:** The `session.github.info` object.",
        "operationId": "get_session_github_v1_sessions__session_id__resources_github_get",
        "parameters": [
          {
            "description": "Session/conversation identifier.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "pr_url",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Pr Url"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Session Github",
        "tags": [
          "session_resources"
        ]
      }
    },
    "/v1/sessions/{session_id}/resources/github/changes": {
      "get": {
        "description": "List the PR's changed files (empty when the branch has no PR).\n\n**Returns:** Flat list of changed files with `status` and line counts.",
        "operationId": "list_session_github_changes_v1_sessions__session_id__resources_github_changes_get",
        "parameters": [
          {
            "description": "Session/conversation identifier.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "pr_url",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Pr Url"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Session Github Changes",
        "tags": [
          "session_resources"
        ]
      }
    },
    "/v1/sessions/{session_id}/resources/github/preferences": {
      "post": {
        "description": "Apply the GitHub panel's account (and optional base) selection.\n\nPersists the choice \u2014 a per-workspace account preference in the user\nconfig, and `gh repo set-default` when a base is given \u2014 then returns the\nrefreshed `session.github.info`. Served by the runner when it's online,\nelse by the host over its tunnel (both run the same\n`github_resource.set_github_preference` against the local config +\nworkspace), so a preference change works with the runner asleep.\n\n**Returns:** The refreshed `session.github.info` object.",
        "operationId": "set_session_github_preference_v1_sessions__session_id__resources_github_preferences_post",
        "parameters": [
          {
            "description": "Session/conversation identifier.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Set Session Github Preference",
        "tags": [
          "session_resources"
        ]
      }
    },
    "/v1/sessions/{session_id}/resources/github/prs": {
      "post": {
        "operationId": "update_session_github_pr_v1_sessions__session_id__resources_github_prs_post",
        "parameters": [
          {
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Update Session Github Pr",
        "tags": [
          "session_resources"
        ]
      }
    },
    "/v1/sessions/{session_id}/resources/terminals": {
      "get": {
        "description": "Return only terminal resources for a session.\n\nThe runner endpoint's pagination params (`limit` / `after` /\n`before` / `order`) are forwarded from the incoming query\nstring \u2014 without this, a client-requested `order=asc` (the web\nterminal tabs rely on creation order to keep the session's own\nterminal first) would be silently dropped and the runner's\n`desc` default would apply.\n\n**Returns:** `PaginatedList` of terminal resources.",
        "operationId": "list_session_terminals_v1_sessions__session_id__resources_terminals_get",
        "parameters": [
          {
            "description": "Session/conversation identifier.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Session Terminals",
        "tags": [
          "session_resources"
        ]
      },
      "post": {
        "description": "Launch or return an existing terminal resource.\n\nPreserves `sys_terminal_launch` idempotency: an\nalready-running `(terminal, session_key)` returns the\nexisting resource.\n\nUser-initiated creates are gated on the agent's terminal\naccess: the requested `terminal` must be one of the names\ndeclared in the agent spec's `terminals:` block. Native\nharness bootstrap requests (marked `ensure_native_terminal`\nor `bridge_inject_dir` \u2014 the `omnigent claude` / `codex`\nwrappers launching the session's own CLI terminal) are exempt:\nthey launch undeclared names via the runner's\nsynthesize-from-body path and predate the gate. The markers\nare client-controlled, so the exemption is narrowed to the\nexact shape those wrappers send \u2014 a registered native terminal\nname with `session_key` `\"main\"` \u2014 anything else carrying a\nmarker still goes through the declared-name gate (it would\notherwise be an arbitrary-terminal bypass).\n\n**Returns:** The terminal resource object.\n\n**Raises**\n\n- `OmnigentError` \u2014 400 when the requested terminal is not declared by the agent spec (or the agent has no `terminals:` block at all).",
        "operationId": "create_session_terminal_v1_sessions__session_id__resources_terminals_post",
        "parameters": [
          {
            "description": "Session/conversation identifier.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Create Session Terminal",
        "tags": [
          "session_resources"
        ]
      }
    },
    "/v1/sessions/{session_id}/resources/terminals/{terminal_id}": {
      "delete": {
        "description": "Close a terminal resource.\n\nDelegates to `TerminalRegistry.close()` on the runner.\nReturns 404 for unknown terminals.\n\n**Returns:** Deletion confirmation object.",
        "operationId": "delete_session_terminal_v1_sessions__session_id__resources_terminals__terminal_id__delete",
        "parameters": [
          {
            "description": "Session/conversation identifier.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          },
          {
            "description": "Opaque terminal resource id.",
            "in": "path",
            "name": "terminal_id",
            "required": true,
            "schema": {
              "title": "Terminal Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Delete Session Terminal",
        "tags": [
          "session_resources"
        ]
      },
      "get": {
        "description": "Return a single terminal resource by id.\n\n**Returns:** The terminal resource object.",
        "operationId": "get_session_terminal_v1_sessions__session_id__resources_terminals__terminal_id__get",
        "parameters": [
          {
            "description": "Session/conversation identifier.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          },
          {
            "description": "Opaque terminal resource id.",
            "in": "path",
            "name": "terminal_id",
            "required": true,
            "schema": {
              "title": "Terminal Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Session Terminal",
        "tags": [
          "session_resources"
        ]
      }
    },
    "/v1/sessions/{session_id}/resources/{resource_id}": {
      "get": {
        "description": "Return a single resource by id from the unified inventory.\n\n**Returns:** The resource object regardless of type.",
        "operationId": "get_session_resource_v1_sessions__session_id__resources__resource_id__get",
        "parameters": [
          {
            "description": "Session/conversation identifier.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          },
          {
            "description": "Opaque resource id.",
            "in": "path",
            "name": "resource_id",
            "required": true,
            "schema": {
              "title": "Resource Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Session Resource",
        "tags": [
          "session_resources"
        ]
      }
    },
    "/v1/sessions/{session_id}/sign-in-link": {
      "get": {
        "description": "Return the sign-in link the session's terminal is waiting on right now.\n\nAsked by the error card at click time, so the user opens the live\nprompt rather than a link saved earlier that its launcher process has\nsince abandoned.\n\n**Returns:** The runner's `{\"pending\", \"url\", \"code\", \"terminal_id\"}` payload.",
        "operationId": "get_session_sign_in_link_v1_sessions__session_id__sign_in_link_get",
        "parameters": [
          {
            "description": "Session/conversation identifier.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Session Sign In Link",
        "tags": [
          "sessions"
        ]
      }
    },
    "/v1/sessions/{session_id}/stream": {
      "get": {
        "description": "Subscribe to the session's live SSE event stream.\n\nDoes NOT replay history; clients reconcile via the snapshot\nendpoint. The generator emits `[DONE]` on normal completion\nand uses `finally` only for presence cleanup \u2014 see\n`_stream_live_events`.\n\nHolding this stream open registers the caller as a session\n*viewer* (presence): co-viewers' streams receive\n`session.presence` events on join/leave/idle edges, and\nthis stream's snapshot-on-connect includes the current\nviewer list. Presence is scoped to the session tree's root\nconversation, so viewers of different agents/sub-agents in\none session see each other. See\n`omnigent/server/presence.py`.\n\n**Returns:** An SSE `StreamingResponse`.\n\n**Raises**\n\n- `OmnigentError` \u2014 404 if no session exists.",
        "operationId": "stream_session_v1_sessions__session_id__stream_get",
        "parameters": [
          {
            "description": "Session/conversation identifier, e.g. `\"conv_abc123\"`.",
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          },
          {
            "description": "Presence idle flag computed by the web client at connect time (tab backgrounded \u2265 its debounce). An idle *flip* mid-view arrives as a reconnect carrying the new value \u2014 there is no separate update endpoint.",
            "in": "query",
            "name": "idle",
            "required": false,
            "schema": {
              "default": false,
              "title": "Idle",
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              },
              "text/event-stream": {
                "itemSchema": {
                  "$ref": "#/components/schemas/ServerStreamEvent"
                }
              }
            },
            "description": "SSE stream of `ServerStreamEvent` frames for the session."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Stream Session",
        "tags": [
          "sessions"
        ]
      }
    },
    "/v1/sessions/{source_id}/fork": {
      "post": {
        "description": "Fork an existing session into a new session.\n\nDeep-copies the source session's conversation items and\nclones the agent into a new session. When `body.agent_id`\nis set, the fork binds that agent instead of the\nsource's \u2014 switching harness (e.g. Claude-SDK \u2192 Claude Code,\nor Claude \u2192 Codex). The source's model settings carry over\nonly within the same provider family; a same-family native\ntarget also carries conversation history (the runner rebuilds\nits transcript). The REPL/CLI binds the fork to its runner via\n`PATCH /v1/sessions/{id}` after creation.\n\nWhen `body.up_to_response_id` is set, only history up to and\nincluding that response is copied into the fork (a \"fork from\nthis response\"); a native target then rebuilds its transcript\nfrom the truncated items instead of resuming the source's full\nnative transcript.\n\nThe dialog's run-config picks (`body.model_override`,\n`body.reasoning_effort`, `body.terminal_launch_args` \u2014 the\npermission-/approval-mode selector) override what the fork would\notherwise inherit. Each is opt-in: a field omitted from the request\nkeeps the inherited value (model/effort within the same provider\nfamily; launch args on a same-agent fork), while a field present\nwins \u2014 a clear alias (`\"default\"`) resets to the bound agent's\ndefault, and an explicit launch-args list also drops the source's\ncopied permission-mode / codex-bypass labels so they can't shadow\nthe freshly chosen mode.\n\nA sub-agent source is allowed, which is how a sub-agent is\npromoted to a session of its own: the fork is always a fresh\ntop-level conversation (no parent, its own spawn-tree root, its\nown owner grant), so it appears in the sidebar and outlives the\nparent. The source keeps running under its parent untouched,\nand the fork does not adopt the source's own children.\n\n`body.host_type: \"managed\"` gives the fork its own\nserver-provisioned sandbox instead of leaving it unbound for the\ncaller to bind a host to. It schedules the same background launch\na managed create does \u2014 this POST returns before the sandbox\nexists \u2014 and the sandbox is registered to the FORKING caller, not\nto the source session's owner. The fork's workspace is the\nrepository named by `body.workspace`, or the one the source\nrecorded when that field is omitted.\n\n**Parameters**\n\n- `body` \u2014 The validated `SessionForkRequest`.\n\n**Returns:** A `SessionResponse` describing the newly created fork (status `\"idle\"`).\n\n**Raises**\n\n- `OmnigentError` \u2014 404 if *source_id* does not exist or `body.agent_id` names no agent; 403/404 if the caller lacks read access on the source, or on the session that owns a session-scoped `body.agent_id`; 400 if the source has no agent binding, `body.up_to_response_id` names no response in the source session, or a managed fork asks for a sandbox this server has not configured.",
        "operationId": "fork_session_v1_sessions__source_id__fork_post",
        "parameters": [
          {
            "description": "Session/conversation identifier of the source session to fork, e.g. `\"conv_abc123\"`.",
            "in": "path",
            "name": "source_id",
            "required": true,
            "schema": {
              "title": "Source Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SessionForkRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SessionResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Fork Session",
        "tags": [
          "sessions"
        ]
      }
    },
    "/v1/sharing": {
      "get": {
        "description": "Report every setting, whether each is editable here, and the options.",
        "operationId": "get_sharing_v1_sharing_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Get Sharing V1 Sharing Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Get Sharing",
        "tags": [
          "sharing"
        ]
      },
      "put": {
        "description": "Set the sharing mode, public-access and/or default-public settings (admin only).\n\nUpdates only the fields present in the body; requires at least one.\nRejects an unknown mode value with 400 (no fail-open coercion \u2014 an admin\nsetting a value should learn about a typo). Rejects a write to a setting\nthe deployment manages itself (not file-backed) with 403.",
        "operationId": "set_sharing_v1_sharing_put",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetSharingRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Set Sharing V1 Sharing Put",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Set Sharing",
        "tags": [
          "sharing"
        ]
      }
    },
    "/v1/skills": {
      "get": {
        "description": "Discover skills using a session or an explicit host, harness, and directory.\n\n`session_id` requires session edit access and uses the saved host,\nworkspace, and agent bundle, including its filters and sub-agent scope.\nOtherwise, supply `host_id`, `harness`, and `path`; host ownership\nis required. Optional `agent_id` applies the selected agent's filter\nand bundled skills, with the same access check as session creation.\nThe two forms cannot be combined.",
        "operationId": "get_skills_v1_skills_get",
        "parameters": [
          {
            "in": "query",
            "name": "session_id",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "minLength": 1,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Session Id"
            }
          },
          {
            "in": "query",
            "name": "host_id",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "minLength": 1,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Host Id"
            }
          },
          {
            "in": "query",
            "name": "harness",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "minLength": 1,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Harness"
            }
          },
          {
            "in": "query",
            "name": "path",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "minLength": 1,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Path"
            }
          },
          {
            "in": "query",
            "name": "agent_id",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "minLength": 1,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Agent Id"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SkillsResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Skills",
        "tags": [
          "skills"
        ]
      }
    },
    "/v1/usage": {
      "get": {
        "description": "Aggregate the calling user's LLM spend across their sessions.\n\nrequire_user, not get_user_id: the aggregation scopes to the caller,\nso a request slipping through as `None` in multi-user mode would\nread another scope. Fail closed with 401 instead (`user_id` is\n`None` only when auth is disabled \u2014 the single-user / local case).",
        "operationId": "get_usage_v1_usage_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UsageReport"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Get Usage",
        "tags": [
          "usage"
        ]
      }
    }
  },
  "servers": [
    {
      "description": "Self-hosted Omnigent server (default local port).",
      "url": "http://127.0.0.1:6767"
    }
  ],
  "tags": [
    {
      "description": "Create, inspect, fork, and drive agent sessions \u2014 the core unit of work. Covers session items and events, agent binding, permissions, labels, and child sessions. The files, terminals, and sandboxed environments attached to a session live under Session Resources.",
      "name": "sessions",
      "x-displayName": "Sessions"
    },
    {
      "description": "Files, terminals, and sandboxed environments attached to a session: upload and read files, create and manage terminals, and read, write, edit, and search the environment filesystem.",
      "name": "session_resources",
      "x-displayName": "Session Resources"
    },
    {
      "description": "Manage the MCP server declarations on a session's bound agent: list the configured servers and create, update, and remove them on session-scoped agents.",
      "name": "session_mcp_servers",
      "x-displayName": "Session MCP Servers"
    },
    {
      "description": "Discover the built-in agents available to bind to a session.",
      "name": "agents",
      "x-displayName": "Agents"
    },
    {
      "description": "Inspect installed extension pages and navigation contributions.",
      "name": "extensions",
      "x-displayName": "Extensions"
    },
    {
      "description": "Hosts that can launch runners. Browse the host filesystem and create directories.",
      "name": "hosts",
      "x-displayName": "Hosts"
    },
    {
      "description": "Launch runners on a host and check their status.",
      "name": "runners",
      "x-displayName": "Runners"
    },
    {
      "description": "Contextual policies scoped to a single session \u2014 list, create, update, and remove.",
      "name": "session_policies",
      "x-displayName": "Session Policies"
    },
    {
      "description": "Server-level default policies applied to new sessions.",
      "name": "default_policies",
      "x-displayName": "Default Policies"
    },
    {
      "description": "The catalog of policy types available to instantiate.",
      "name": "policy_registry",
      "x-displayName": "Policy Registry"
    },
    {
      "description": "Threaded comments on a session, including sending a comment to the agent.",
      "name": "comments",
      "x-displayName": "Comments"
    },
    {
      "description": "First-class, owner-private containers that group sessions \u2014 create, list, rename, and delete.",
      "name": "projects",
      "x-displayName": "Projects"
    },
    {
      "description": "Health, version, and identity endpoints for the running server.",
      "name": "system",
      "x-displayName": "System"
    }
  ]
}
