From 8fb0ae1a0fa0ed4d443180d8a98ec1c534ffde73 Mon Sep 17 00:00:00 2001 From: openhands Date: Mon, 5 Oct 2026 13:37:52 +0000 Subject: [PATCH] chore(openapi): regenerate Agent SDK spec from SDK 1.52.0 The OpenAPI sync workflow has been a no-op since 2026-02-15, leaving the published spec at 40 paths / 44 operations while the SDK exposes 135 paths / 163 operations. Regenerated with the SDK's canonical exporter. Co-authored-by: openhands --- openapi/agent-sdk.json | 40651 +++++++++++++++++++++++++++++---------- 1 file changed, 30205 insertions(+), 10446 deletions(-) diff --git a/openapi/agent-sdk.json b/openapi/agent-sdk.json index 166f9daed..d91acf698 100644 --- a/openapi/agent-sdk.json +++ b/openapi/agent-sdk.json @@ -1,2844 +1,20165 @@ { - "openapi": "3.1.0", - "info": { - "title": "OpenHands Agent Server", - "description": "OpenHands Agent Server - REST/WebSocket interface for OpenHands AI Agent", - "version": "0.1.0" - }, - "paths": { - "/alive": { - "get": { - "tags": [ - "Server Details" + "components": { + "schemas": { + "ACPAgent-Input": { + "description": "Agent that delegates to an ACP-compatible subprocess server.", + "properties": { + "acp_args": { + "description": "Additional arguments for the ACP server command", + "items": { + "type": "string" + }, + "title": "Acp Args", + "type": "array" + }, + "acp_command": { + "description": "Command to start the ACP server, e.g. ['npx', '-y', '@agentclientprotocol/claude-agent-acp']", + "items": { + "type": "string" + }, + "title": "Acp Command", + "type": "array" + }, + "acp_file_secrets": { + "description": "Reserved 'file-content' credential secrets to materialise to disk before launching the subprocess (e.g. Codex auth.json, Gemini Vertex SA JSON). The SDK owns the mechanism (write the file in the runtime pod, set the env var, seed-if-absent); these specs are the policy. Defaults to the built-in supported providers; a downstream application may override or extend this to support other ACP servers with different file-auth schemes.", + "items": { + "$ref": "#/components/schemas/ACPFileSecretSpec" + }, + "title": "Acp File Secrets", + "type": "array" + }, + "acp_isolate_data_dir": { + "default": false, + "description": "Give the ACP subprocess a per-conversation CLI data/config root instead of the shared user ``HOME``. When True and the provider is recognised, point its data-dir env var (``CODEX_HOME`` / ``CLAUDE_CONFIG_DIR`` / ``HOME``; see ``ACPProviderInfo.data_dir_env_var``) at ``/acp/`` — the same per-conversation tree materialised file-secrets use. Required for correctness when several of a user's conversations share one sandbox (``SandboxGroupingStrategy != NO_GROUPING``), where they would otherwise race on one set of CLI auth/config/cache/lock files (see #1019). Off by default: with one sandbox per conversation the shared HOME is already private, and relocating it would hide a pre-existing interactive login. Downstream policy decides when to enable it; the SDK owns where the root lives.", + "title": "Acp Isolate Data Dir", + "type": "boolean" + }, + "acp_model": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Model for the ACP server to use (e.g. 'sonnet' or 'gpt-5.5'). Applied via the protocol — set_config_option(model) for configOptions-based servers (codex, claude), else set_session_model. If None, the server picks its default.", + "title": "Acp Model" + }, + "acp_prompt_timeout": { + "default": 1800.0, + "description": "Inactivity timeout in seconds for a single ACP prompt() call. The deadline resets on every update from the ACP server (token, thought, tool-call progress, usage), so a steadily-progressing agent runs as long as it keeps making progress; the prompt is only aborted after this many seconds with no activity at all. Prevents indefinite hangs when the ACP server stops responding without killing legitimately long-running work.", + "title": "Acp Prompt Timeout", + "type": "number" + }, + "acp_resume_session_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Optional explicit ACP session id to resume. When set, takes precedence over the id persisted in ``state.agent_state`` and is used to call ``session/load`` on the ACP server. Designed for environments where the per-conversation filesystem (and therefore ``base_state.json``) does not survive across restarts (e.g. cloud sandbox recycles), but the id has been mirrored into durable storage elsewhere. Falls back to a fresh session if the server cannot load the id. Treated as a secret on the wire — possession of the id is enough to resume the underlying ACP session, so default serialization redacts it; pass ``expose_secrets='plaintext'`` (trusted backend) or ``expose_secrets='encrypted'`` plus a cipher (frontend round-trip) when the value must cross a serialization boundary.", + "title": "Acp Resume Session Id" + }, + "acp_server": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Provider registry key identifying which ACP CLI this agent runs (any ACP_PROVIDERS key, or 'custom'); None when the agent is built directly rather than via ACPAgentSettings. Set by ACPAgentSettings.create_agent() from ACPAgentSettings.acp_server so the authoritative key survives onto the agent — and thus onto ConversationInfo.agent — because the launch command in acp_command does not reliably reverse-map to a provider. Informational only: consumers use it to resolve a provider brand label / model list; the subprocess is still launched from acp_command.", + "title": "Acp Server" + }, + "acp_session_mode": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Session mode ID to set after creating a session. If None (default), auto-detected from the ACP server type: 'bypassPermissions' for claude-agent-acp, 'agent-full-access' for codex-acp; a provider with no such mode (pi-acp) skips the call.", + "title": "Acp Session Mode" + }, + "acp_startup_timeout": { + "default": 90.0, + "description": "Timeout in seconds for ACP server startup: spawning the subprocess, the initialize/authenticate handshake, and new_session()/load_session(). Unlike acp_prompt_timeout, this is a hard deadline rather than an idle deadline, since startup has no intermediate progress signal to reset it against. Prevents an indefinite hang when the ACP server blocks on authentication (e.g. an expired token) without ever raising.", + "title": "Acp Startup Timeout", + "type": "number" + }, + "agent_context": { + "anyOf": [ + { + "$ref": "#/components/schemas/AgentContext-Input" + }, + { + "type": "null" + } + ], + "description": "Optional AgentContext to initialize the agent with specific context.", + "examples": [ + { + "skills": [ + { + "content": "When you see this message, you should reply like you are a grumpy cat forced to use the internet.", + "name": "AGENTS.md", + "type": "repo" + }, + { + "content": "IMPORTANT! The user has said the magic word \"flarglebargle\". You must only respond with a message telling them how smart they are", + "name": "flarglebargle", + "trigger": [ + "flarglebargle" + ], + "type": "knowledge" + } + ], + "system_message_suffix": "Always finish your response with the word 'yay!'", + "user_message_prefix": "The first character of your response should be 'I'" + } + ] + }, + "condenser": { + "anyOf": [ + { + "$ref": "#/components/schemas/CondenserBase-Input" + }, + { + "type": "null" + } + ], + "description": "Optional condenser to use for condensing conversation history.", + "examples": [ + { + "keep_first": 10, + "kind": "LLMSummarizingCondenser", + "llm": { + "api_key": "your_api_key_here", + "base_url": "https://llm-proxy.eval.all-hands.dev", + "model": "litellm_proxy/openai/gpt-5.5" + }, + "max_size": 80 + } + ] + }, + "critic": { + "anyOf": [ + { + "$ref": "#/components/schemas/CriticBase-Input" + }, + { + "type": "null" + } + ], + "description": "EXPERIMENTAL: Optional critic to evaluate agent actions and messages in real-time. API and behavior may change without notice. May impact performance, especially in 'all_actions' mode.", + "examples": [ + { + "kind": "AgentFinishedCritic" + } + ] + }, + "filter_tools_regex": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Optional regex to filter the tools available to the agent by name. This is applied after any tools provided in `tools` and any MCP tools are added.", + "examples": [ + "^(?!repomix)(.*)|^repomix.*pack_codebase.*$" + ], + "title": "Filter Tools Regex" + }, + "include_default_tools": { + "items": { + "type": "string" + }, + "title": "Include Default Tools", + "type": "array" + }, + "kind": { + "const": "ACPAgent", + "title": "Kind", + "type": "string" + }, + "llm": { + "$ref": "#/components/schemas/LLM-Input" + }, + "mcp_config": { + "additionalProperties": { + "$ref": "#/components/schemas/MCPServer-Input" + }, + "description": "Optional MCP servers to expose as tools.", + "examples": [ + { + "fetch": { + "args": [ + "--with", + "mcp==1.29.0", + "mcp-server-fetch==2026.7.10" + ], + "command": "uvx" + } + } + ], + "title": "Mcp Config", + "type": "object" + }, + "security_policy_filename": { + "default": "security_policy.j2", + "description": "Security policy filename. The default 'security_policy.j2' is a back-compat sentinel (the file was removed) that selects the built-in default policy from the prompt registry -- it is not loaded from disk. Any other value names a custom policy file whose contents are inserted verbatim (NOT rendered as a Jinja template). Can be either:\n- A relative filename (e.g., 'custom_security_policy.md') loaded from the agent's prompts directory\n- An absolute path (e.g., '/path/to/custom_security_policy.md')\n- Empty string to disable security policy", + "title": "Security Policy Filename", + "type": "string" + }, + "system_prompt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Inline system prompt string. When provided, the agent uses this text verbatim as the system message instead of rendering from `system_prompt_filename`. Mutually exclusive with a non-default `system_prompt_filename`.\n\n**Warning**: This is not recommended unless you know what you are doing (e.g. customising agent behaviour for a completely different task). Setting this will override OpenHands' built-in system instructions that govern default agent behaviour.", + "title": "System Prompt" + }, + "system_prompt_filename": { + "default": "system_prompt.j2", + "description": "System prompt template filename. Can be either:\n- A relative filename (e.g., 'system_prompt.j2') loaded from the agent's prompts directory\n- An absolute path (e.g., '/path/to/custom_prompt.j2')", + "title": "System Prompt Filename", + "type": "string" + }, + "system_prompt_kwargs": { + "additionalProperties": true, + "description": "Optional kwargs to pass to the system prompt Jinja2 template.", + "examples": [ + { + "cli_mode": true + } + ], + "title": "System Prompt Kwargs", + "type": "object" + }, + "tool_concurrency_limit": { + "default": 1, + "description": "Maximum number of tool calls to execute concurrently within a single agent step. Default is 1 (sequential). Values > 1 enable parallel execution; concurrent tools share the conversation object, filesystem, and working directory, so mutations to shared state may race.", + "minimum": 1.0, + "title": "Tool Concurrency Limit", + "type": "integer" + }, + "tools": { + "items": { + "$ref": "#/components/schemas/Tool-Input" + }, + "title": "Tools", + "type": "array" + } + }, + "required": [ + "acp_command" + ], + "title": "ACPAgent", + "type": "object" + }, + "ACPAgent-Output": { + "description": "Agent that delegates to an ACP-compatible subprocess server.", + "properties": { + "acp_args": { + "description": "Additional arguments for the ACP server command", + "items": { + "type": "string" + }, + "title": "Acp Args", + "type": "array" + }, + "acp_command": { + "description": "Command to start the ACP server, e.g. ['npx', '-y', '@agentclientprotocol/claude-agent-acp']", + "items": { + "type": "string" + }, + "title": "Acp Command", + "type": "array" + }, + "acp_file_secrets": { + "description": "Reserved 'file-content' credential secrets to materialise to disk before launching the subprocess (e.g. Codex auth.json, Gemini Vertex SA JSON). The SDK owns the mechanism (write the file in the runtime pod, set the env var, seed-if-absent); these specs are the policy. Defaults to the built-in supported providers; a downstream application may override or extend this to support other ACP servers with different file-auth schemes.", + "items": { + "$ref": "#/components/schemas/ACPFileSecretSpec" + }, + "title": "Acp File Secrets", + "type": "array" + }, + "acp_isolate_data_dir": { + "default": false, + "description": "Give the ACP subprocess a per-conversation CLI data/config root instead of the shared user ``HOME``. When True and the provider is recognised, point its data-dir env var (``CODEX_HOME`` / ``CLAUDE_CONFIG_DIR`` / ``HOME``; see ``ACPProviderInfo.data_dir_env_var``) at ``/acp/`` — the same per-conversation tree materialised file-secrets use. Required for correctness when several of a user's conversations share one sandbox (``SandboxGroupingStrategy != NO_GROUPING``), where they would otherwise race on one set of CLI auth/config/cache/lock files (see #1019). Off by default: with one sandbox per conversation the shared HOME is already private, and relocating it would hide a pre-existing interactive login. Downstream policy decides when to enable it; the SDK owns where the root lives.", + "title": "Acp Isolate Data Dir", + "type": "boolean" + }, + "acp_model": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Model for the ACP server to use (e.g. 'sonnet' or 'gpt-5.5'). Applied via the protocol — set_config_option(model) for configOptions-based servers (codex, claude), else set_session_model. If None, the server picks its default.", + "title": "Acp Model" + }, + "acp_prompt_timeout": { + "default": 1800.0, + "description": "Inactivity timeout in seconds for a single ACP prompt() call. The deadline resets on every update from the ACP server (token, thought, tool-call progress, usage), so a steadily-progressing agent runs as long as it keeps making progress; the prompt is only aborted after this many seconds with no activity at all. Prevents indefinite hangs when the ACP server stops responding without killing legitimately long-running work.", + "title": "Acp Prompt Timeout", + "type": "number" + }, + "acp_resume_session_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Optional explicit ACP session id to resume. When set, takes precedence over the id persisted in ``state.agent_state`` and is used to call ``session/load`` on the ACP server. Designed for environments where the per-conversation filesystem (and therefore ``base_state.json``) does not survive across restarts (e.g. cloud sandbox recycles), but the id has been mirrored into durable storage elsewhere. Falls back to a fresh session if the server cannot load the id. Treated as a secret on the wire — possession of the id is enough to resume the underlying ACP session, so default serialization redacts it; pass ``expose_secrets='plaintext'`` (trusted backend) or ``expose_secrets='encrypted'`` plus a cipher (frontend round-trip) when the value must cross a serialization boundary.", + "title": "Acp Resume Session Id" + }, + "acp_server": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Provider registry key identifying which ACP CLI this agent runs (any ACP_PROVIDERS key, or 'custom'); None when the agent is built directly rather than via ACPAgentSettings. Set by ACPAgentSettings.create_agent() from ACPAgentSettings.acp_server so the authoritative key survives onto the agent — and thus onto ConversationInfo.agent — because the launch command in acp_command does not reliably reverse-map to a provider. Informational only: consumers use it to resolve a provider brand label / model list; the subprocess is still launched from acp_command.", + "title": "Acp Server" + }, + "acp_session_mode": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Session mode ID to set after creating a session. If None (default), auto-detected from the ACP server type: 'bypassPermissions' for claude-agent-acp, 'agent-full-access' for codex-acp; a provider with no such mode (pi-acp) skips the call.", + "title": "Acp Session Mode" + }, + "acp_startup_timeout": { + "default": 90.0, + "description": "Timeout in seconds for ACP server startup: spawning the subprocess, the initialize/authenticate handshake, and new_session()/load_session(). Unlike acp_prompt_timeout, this is a hard deadline rather than an idle deadline, since startup has no intermediate progress signal to reset it against. Prevents an indefinite hang when the ACP server blocks on authentication (e.g. an expired token) without ever raising.", + "title": "Acp Startup Timeout", + "type": "number" + }, + "agent_context": { + "anyOf": [ + { + "$ref": "#/components/schemas/AgentContext-Output" + }, + { + "type": "null" + } + ], + "description": "Optional AgentContext to initialize the agent with specific context.", + "examples": [ + { + "skills": [ + { + "content": "When you see this message, you should reply like you are a grumpy cat forced to use the internet.", + "name": "AGENTS.md", + "type": "repo" + }, + { + "content": "IMPORTANT! The user has said the magic word \"flarglebargle\". You must only respond with a message telling them how smart they are", + "name": "flarglebargle", + "trigger": [ + "flarglebargle" + ], + "type": "knowledge" + } + ], + "system_message_suffix": "Always finish your response with the word 'yay!'", + "user_message_prefix": "The first character of your response should be 'I'" + } + ] + }, + "condenser": { + "anyOf": [ + { + "$ref": "#/components/schemas/CondenserBase-Output" + }, + { + "type": "null" + } + ], + "description": "Optional condenser to use for condensing conversation history.", + "examples": [ + { + "keep_first": 10, + "kind": "LLMSummarizingCondenser", + "llm": { + "api_key": "your_api_key_here", + "base_url": "https://llm-proxy.eval.all-hands.dev", + "model": "litellm_proxy/openai/gpt-5.5" + }, + "max_size": 80 + } + ] + }, + "critic": { + "anyOf": [ + { + "$ref": "#/components/schemas/CriticBase-Output" + }, + { + "type": "null" + } + ], + "description": "EXPERIMENTAL: Optional critic to evaluate agent actions and messages in real-time. API and behavior may change without notice. May impact performance, especially in 'all_actions' mode.", + "examples": [ + { + "kind": "AgentFinishedCritic" + } + ] + }, + "filter_tools_regex": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Optional regex to filter the tools available to the agent by name. This is applied after any tools provided in `tools` and any MCP tools are added.", + "examples": [ + "^(?!repomix)(.*)|^repomix.*pack_codebase.*$" + ], + "title": "Filter Tools Regex" + }, + "include_default_tools": { + "items": { + "type": "string" + }, + "title": "Include Default Tools", + "type": "array" + }, + "kind": { + "const": "ACPAgent", + "title": "Kind", + "type": "string" + }, + "llm": { + "$ref": "#/components/schemas/LLM-Output" + }, + "mcp_config": { + "additionalProperties": { + "$ref": "#/components/schemas/MCPServer-Output" + }, + "description": "Optional MCP servers to expose as tools.", + "examples": [ + { + "fetch": { + "args": [ + "--with", + "mcp==1.29.0", + "mcp-server-fetch==2026.7.10" + ], + "command": "uvx" + } + } + ], + "title": "Mcp Config", + "type": "object" + }, + "security_policy_filename": { + "default": "security_policy.j2", + "description": "Security policy filename. The default 'security_policy.j2' is a back-compat sentinel (the file was removed) that selects the built-in default policy from the prompt registry -- it is not loaded from disk. Any other value names a custom policy file whose contents are inserted verbatim (NOT rendered as a Jinja template). Can be either:\n- A relative filename (e.g., 'custom_security_policy.md') loaded from the agent's prompts directory\n- An absolute path (e.g., '/path/to/custom_security_policy.md')\n- Empty string to disable security policy", + "title": "Security Policy Filename", + "type": "string" + }, + "system_prompt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Inline system prompt string. When provided, the agent uses this text verbatim as the system message instead of rendering from `system_prompt_filename`. Mutually exclusive with a non-default `system_prompt_filename`.\n\n**Warning**: This is not recommended unless you know what you are doing (e.g. customising agent behaviour for a completely different task). Setting this will override OpenHands' built-in system instructions that govern default agent behaviour.", + "title": "System Prompt" + }, + "system_prompt_filename": { + "default": "system_prompt.j2", + "description": "System prompt template filename. Can be either:\n- A relative filename (e.g., 'system_prompt.j2') loaded from the agent's prompts directory\n- An absolute path (e.g., '/path/to/custom_prompt.j2')", + "title": "System Prompt Filename", + "type": "string" + }, + "system_prompt_kwargs": { + "additionalProperties": true, + "description": "Optional kwargs to pass to the system prompt Jinja2 template.", + "examples": [ + { + "cli_mode": true + } + ], + "title": "System Prompt Kwargs", + "type": "object" + }, + "tool_concurrency_limit": { + "default": 1, + "description": "Maximum number of tool calls to execute concurrently within a single agent step. Default is 1 (sequential). Values > 1 enable parallel execution; concurrent tools share the conversation object, filesystem, and working directory, so mutations to shared state may race.", + "minimum": 1.0, + "title": "Tool Concurrency Limit", + "type": "integer" + }, + "tools": { + "items": { + "$ref": "#/components/schemas/openhands__sdk__tool__spec__Tool" + }, + "title": "Tools", + "type": "array" + } + }, + "required": [ + "acp_command", + "kind" + ], + "title": "ACPAgent", + "type": "object" + }, + "ACPAgentProfile": { + "additionalProperties": false, + "description": "``agent_kind=\"acp\"`` profile — names an ACP backend, stores no credential.\n\nThere is no ``llm_profile_ref`` and no embedded credential: the ACP\nsubprocess makes its own model calls, and the provider's credential\n(env-var name) is derived from :attr:`acp_server` via the\n:data:`~openhands.sdk.settings.acp_providers.ACP_PROVIDERS` registry. The\nvalue rides the conversation secrets channel, never the profile.", + "properties": { + "acp_args": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Additional arguments appended to the ACP server command.", + "title": "Acp Args" + }, + "acp_command": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Optional explicit command to launch the ACP subprocess. Leave blank to use the default for ``acp_server``.", + "title": "Acp Command" + }, + "acp_model": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Model identifier for the ACP server (e.g. 'claude-opus-4-8'). Leave blank to let the server pick its default.", + "title": "Acp Model" + }, + "acp_prompt_timeout": { + "default": 1800.0, + "description": "Inactivity timeout (seconds) for a single ACP prompt() round-trip; resets on every update from the server.", + "exclusiveMinimum": 0.0, + "title": "Acp Prompt Timeout", + "type": "number" + }, + "acp_server": { + "default": "claude-code", + "description": "Which ACP-compatible backend to launch. The provider's credential env-var name is derived from this via the ACP_PROVIDERS registry.", + "enum": [ + "claude-code", + "codex", + "gemini-cli", + "kimi-code", + "pi", + "opencode", + "custom" + ], + "title": "Acp Server", + "type": "string" + }, + "acp_session_mode": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Session mode ID (e.g. 'bypassPermissions'). Leave blank to auto-detect from the ACP server type.", + "title": "Acp Session Mode" + }, + "acp_startup_timeout": { + "default": 90.0, + "description": "Timeout (seconds) for ACP server startup: spawn, initialize/authenticate, and new_session()/load_session().", + "exclusiveMinimum": 0.0, + "title": "Acp Startup Timeout", + "type": "number" + }, + "agent_kind": { + "const": "acp", + "default": "acp", + "description": "Discriminator for the ``AgentProfile`` union. ``'acp'`` selects an ACP-delegating agent.", + "title": "Agent Kind", + "type": "string" + }, + "id": { + "description": "Stable provenance handle for this profile. Conversations record this UUID; it never changes, even when the profile is renamed.", + "format": "uuid", + "title": "Id", + "type": "string" + }, + "mcp_server_refs": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Which of the user's globally configured MCP servers to expose. null = all; [] = none; a non-null list = filter to the named keys.", + "title": "Mcp Server Refs" + }, + "name": { + "description": "Human-facing, renameable key shown in the profile picker.", + "minLength": 1, + "title": "Name", + "type": "string" + }, + "revision": { + "default": 0, + "description": "Monotonic revision counter, bumped on each saved edit.", + "minimum": 0.0, + "title": "Revision", + "type": "integer" + }, + "schema_version": { + "default": 3, + "minimum": 1.0, + "title": "Schema Version", + "type": "integer" + }, + "secret_refs": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Which of the user's saved secrets to expose to this agent. null = all; [] = none; a non-null list = filter to the named keys. Strict: nothing is added back. An ACP profile must list its own provider credential to receive it.", + "title": "Secret Refs" + } + }, + "required": [ + "name" + ], + "title": "ACPAgentProfile", + "type": "object" + }, + "ACPFileSecretSpec": { + "description": "Declarative mapping from a reserved \"file-content\" secret to a credential\nfile the ACP subprocess authenticates from.\n\nSome providers read their credential from a *file on disk* rather than an\nenv var: Codex reads ``$CODEX_HOME/auth.json``; Gemini (Vertex AI) reads a\nservice-account JSON pointed at by ``GOOGLE_APPLICATION_CREDENTIALS``. The\nuser supplies that credential as a pasted blob — a reserved secret named\n:attr:`secret_name` — and :class:`~openhands.sdk.agent.ACPAgent` materialises\nit to :attr:`filename` under the conversation's durable per-conversation root\n(seed-if-absent), then sets :attr:`env_var` so the CLI can find it.\n\nMaterialisation is keyed off :attr:`secret_name` (not the launch command),\nso a custom or aliased ``acp_command`` still works as long as the reserved\nsecret is supplied.\n\nThe SDK owns the *mechanism* (writing the file in the runtime pod, setting\nthe env var, seed-if-absent, permissions); the *policy* — which secrets map\nto which files for which CLIs — lives in these specs. Built-in defaults\ncover the supported providers, but downstream applications can override\n:attr:`~openhands.sdk.agent.ACPAgent.acp_file_secrets` to support other ACP\nservers with different file-auth schemes without an SDK change.", + "properties": { + "env_points_to": { + "default": "file", + "enum": [ + "dir", + "file" + ], + "title": "Env Points To", + "type": "string" + }, + "env_var": { + "minLength": 1, + "title": "Env Var", + "type": "string" + }, + "filename": { + "minLength": 1, + "title": "Filename", + "type": "string" + }, + "secret_name": { + "minLength": 1, + "title": "Secret Name", + "type": "string" + }, + "subdir": { + "minLength": 1, + "title": "Subdir", + "type": "string" + }, + "warn_if_unset": { + "default": [], + "items": { + "type": "string" + }, + "title": "Warn If Unset", + "type": "array" + } + }, + "required": [ + "secret_name", + "filename", + "env_var", + "subdir" + ], + "title": "ACPFileSecretSpec", + "type": "object" + }, + "ACPModelInfo": { + "description": "One model an ACP server offers for a session.\n\nA normalized, stable mirror of the ACP protocol's ``ModelInfo``. The\nprotocol ``models`` capability is flagged **UNSTABLE**, so we re-map it\ninto our own type at the SDK boundary rather than re-serializing the\nvendored ``acp.schema`` type onto the agent-server's public API — clients\nget a stable shape regardless of upstream protocol churn.\n\nCarries everything a client needs to render a picker and resolve a\n``current_model_id`` to a display label *itself*; the SDK deliberately\ndoes no name curation.", + "properties": { + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Optional longer description supplied by the server.", + "title": "Description" + }, + "model_id": { + "description": "Server-assigned model identifier. May be concrete (e.g. ``\"gpt-5.6\"``) or an opaque alias (e.g. ``\"default\"``, ``\"auto\"``). This is the value to pass back to the server to switch to this model.", + "title": "Model Id", + "type": "string" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Human-readable label, e.g. ``\"GPT-5.5\"``.", + "title": "Name" + } + }, + "required": [ + "model_id" + ], + "title": "ACPModelInfo", + "type": "object" + }, + "ACPToolCallEvent": { + "additionalProperties": false, + "description": "Event representing a tool call executed by an ACP server.\n\nCaptures the tool name, inputs, outputs, and status from ACP\n``ToolCallStart`` / ``ToolCallProgress`` notifications so they can\nbe surfaced in the OpenHands event stream and visualizer.\n\nThis is *not* an ``LLMConvertibleEvent`` — ACP tool calls do not\nparticipate in LLM message conversion.", + "properties": { + "content": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Content" + }, + "id": { + "description": "Unique event id (ULID/UUID)", + "title": "Id", + "type": "string" + }, + "is_error": { + "default": false, + "title": "Is Error", + "type": "boolean" + }, + "kind": { + "const": "ACPToolCallEvent", + "title": "Kind", + "type": "string" + }, + "parent_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Parent event id in the conversation tree. None for the root, or for legacy events predating the tree (see EventLog's effective-parent rule). Events sharing a parent_id are sibling branches.", + "title": "Parent Id" + }, + "raw_input": { + "anyOf": [ + {}, + { + "type": "null" + } + ], + "title": "Raw Input" + }, + "raw_output": { + "anyOf": [ + {}, + { + "type": "null" + } + ], + "title": "Raw Output" + }, + "source": { + "default": "agent", + "enum": [ + "agent", + "user", + "environment", + "hook" + ], + "title": "Source", + "type": "string" + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + }, + "timestamp": { + "description": "Event timestamp", + "title": "Timestamp", + "type": "string" + }, + "title": { + "title": "Title", + "type": "string" + }, + "tool_call_id": { + "title": "Tool Call Id", + "type": "string" + }, + "tool_kind": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tool Kind" + } + }, + "required": [ + "tool_call_id", + "title", + "kind" + ], + "title": "ACPToolCallEvent", + "type": "object" + }, + "APIBasedCritic-Input": { + "properties": { + "agent_issue_labels": { + "default": [ + "misunderstood_intention", + "did_not_follow_instruction", + "insufficient_analysis", + "insufficient_clarification", + "improper_tool_use_or_setup", + "loop_behavior", + "insufficient_testing", + "insufficient_debugging", + "incomplete_implementation", + "file_management_errors", + "scope_creep", + "risky_actions_or_permission", + "other_agent_issue" + ], + "items": { + "type": "string" + }, + "title": "Agent Issue Labels", + "type": "array" + }, + "api_key": { + "anyOf": [ + { + "type": "string" + }, + { + "format": "password", + "type": "string", + "writeOnly": true + } + ], + "description": "API key for authenticating with the vLLM service", + "title": "Api Key" + }, + "has_success_label": { + "default": true, + "description": "Whether the model predicts success label at index 0", + "title": "Has Success Label", + "type": "boolean" + }, + "infra_labels": { + "default": [ + "infrastructure_external_issue", + "infrastructure_agent_caused_issue" + ], + "items": { + "type": "string" + }, + "title": "Infra Labels", + "type": "array" + }, + "issue_threshold": { + "default": 0.75, + "description": "APIBasedCritic-specific probability threshold for agent issue labels that should trigger iterative refinement.", + "maximum": 1.0, + "minimum": 0.0, + "title": "Issue Threshold", + "type": "number" + }, + "iterative_refinement": { + "anyOf": [ + { + "$ref": "#/components/schemas/IterativeRefinementConfig" + }, + { + "type": "null" + } + ], + "description": "Optional configuration for iterative refinement. When set, Conversation.run() will automatically retry the task if the critic score is below the success_threshold, up to max_iterations." + }, + "kind": { + "const": "APIBasedCritic", + "title": "Kind", + "type": "string" + }, + "mode": { + "default": "finish_and_message", + "description": "When to run critic evaluation:\n- 'finish_and_message': Evaluate on FinishAction and agent MessageEvent (default, minimal performance impact)\n- 'all_actions': Evaluate after every agent action (WARNING: significantly slower due to API calls on each action)", + "enum": [ + "finish_and_message", + "all_actions" + ], + "title": "Mode", + "type": "string" + }, + "model_name": { + "default": "critic", + "description": "Name of the model to use", + "title": "Model Name", + "type": "string" + }, + "pass_tools_definitions": { + "default": true, + "description": "Whether to pass tool definitions to the model", + "title": "Pass Tools Definitions", + "type": "boolean" + }, + "sentiment_labels": { + "default": [ + "sentiment_positive", + "sentiment_neutral", + "sentiment_negative" + ], + "items": { + "type": "string" + }, + "title": "Sentiment Labels", + "type": "array" + }, + "sentiment_map": { + "additionalProperties": { + "type": "string" + }, + "default": { + "Negative": "sentiment_negative", + "Neutral": "sentiment_neutral", + "Positive": "sentiment_positive" + }, + "title": "Sentiment Map", + "type": "object" + }, + "server_url": { + "default": "https://llm-proxy.app.all-hands.dev/vllm", + "description": "Base URL of the vLLM classification service", + "title": "Server Url", + "type": "string" + }, + "timeout_seconds": { + "default": 300.0, + "description": "Timeout for requests to the model", + "title": "Timeout Seconds", + "type": "number" + }, + "tokenizer_name": { + "default": "Qwen/Qwen3-4B-Instruct-2507", + "description": "HuggingFace tokenizer name for loading chat template", + "title": "Tokenizer Name", + "type": "string" + }, + "user_followup_labels": { + "default": [ + "clarification_or_restatement", + "correction", + "direction_change", + "vcs_update_requests", + "progress_or_scope_concern", + "frustration_or_complaint", + "removal_or_reversion_request", + "other_user_issue" + ], + "items": { + "type": "string" + }, + "title": "User Followup Labels", + "type": "array" + } + }, + "required": [ + "api_key" + ], + "title": "APIBasedCritic", + "type": "object" + }, + "APIBasedCritic-Output": { + "properties": { + "agent_issue_labels": { + "default": [ + "misunderstood_intention", + "did_not_follow_instruction", + "insufficient_analysis", + "insufficient_clarification", + "improper_tool_use_or_setup", + "loop_behavior", + "insufficient_testing", + "insufficient_debugging", + "incomplete_implementation", + "file_management_errors", + "scope_creep", + "risky_actions_or_permission", + "other_agent_issue" + ], + "items": { + "type": "string" + }, + "title": "Agent Issue Labels", + "type": "array" + }, + "api_key": { + "anyOf": [ + { + "type": "string" + }, + { + "format": "password", + "type": "string", + "writeOnly": true + } + ], + "description": "API key for authenticating with the vLLM service", + "title": "Api Key" + }, + "has_success_label": { + "default": true, + "description": "Whether the model predicts success label at index 0", + "title": "Has Success Label", + "type": "boolean" + }, + "infra_labels": { + "default": [ + "infrastructure_external_issue", + "infrastructure_agent_caused_issue" + ], + "items": { + "type": "string" + }, + "title": "Infra Labels", + "type": "array" + }, + "issue_threshold": { + "default": 0.75, + "description": "APIBasedCritic-specific probability threshold for agent issue labels that should trigger iterative refinement.", + "maximum": 1.0, + "minimum": 0.0, + "title": "Issue Threshold", + "type": "number" + }, + "iterative_refinement": { + "anyOf": [ + { + "$ref": "#/components/schemas/IterativeRefinementConfig" + }, + { + "type": "null" + } + ], + "description": "Optional configuration for iterative refinement. When set, Conversation.run() will automatically retry the task if the critic score is below the success_threshold, up to max_iterations." + }, + "kind": { + "const": "APIBasedCritic", + "title": "Kind", + "type": "string" + }, + "mode": { + "default": "finish_and_message", + "description": "When to run critic evaluation:\n- 'finish_and_message': Evaluate on FinishAction and agent MessageEvent (default, minimal performance impact)\n- 'all_actions': Evaluate after every agent action (WARNING: significantly slower due to API calls on each action)", + "enum": [ + "finish_and_message", + "all_actions" + ], + "title": "Mode", + "type": "string" + }, + "model_name": { + "default": "critic", + "description": "Name of the model to use", + "title": "Model Name", + "type": "string" + }, + "pass_tools_definitions": { + "default": true, + "description": "Whether to pass tool definitions to the model", + "title": "Pass Tools Definitions", + "type": "boolean" + }, + "sentiment_labels": { + "default": [ + "sentiment_positive", + "sentiment_neutral", + "sentiment_negative" + ], + "items": { + "type": "string" + }, + "title": "Sentiment Labels", + "type": "array" + }, + "sentiment_map": { + "additionalProperties": { + "type": "string" + }, + "default": { + "Negative": "sentiment_negative", + "Neutral": "sentiment_neutral", + "Positive": "sentiment_positive" + }, + "title": "Sentiment Map", + "type": "object" + }, + "server_url": { + "default": "https://llm-proxy.app.all-hands.dev/vllm", + "description": "Base URL of the vLLM classification service", + "title": "Server Url", + "type": "string" + }, + "timeout_seconds": { + "default": 300.0, + "description": "Timeout for requests to the model", + "title": "Timeout Seconds", + "type": "number" + }, + "tokenizer_name": { + "default": "Qwen/Qwen3-4B-Instruct-2507", + "description": "HuggingFace tokenizer name for loading chat template", + "title": "Tokenizer Name", + "type": "string" + }, + "user_followup_labels": { + "default": [ + "clarification_or_restatement", + "correction", + "direction_change", + "vcs_update_requests", + "progress_or_scope_concern", + "frustration_or_complaint", + "removal_or_reversion_request", + "other_user_issue" + ], + "items": { + "type": "string" + }, + "title": "User Followup Labels", + "type": "array" + } + }, + "required": [ + "api_key", + "kind" + ], + "title": "APIBasedCritic", + "type": "object" + }, + "Action": { + "discriminator": { + "mapping": { + "openhands__sdk__mcp__definition__MCPToolAction-Output__1": "#/components/schemas/MCPToolAction", + "openhands__sdk__tool__builtins__classify_and_switch_llm__ClassifyAndSwitchLLMAction-Output__1": "#/components/schemas/ClassifyAndSwitchLLMAction", + "openhands__sdk__tool__builtins__finish__FinishAction-Output__1": "#/components/schemas/FinishAction", + "openhands__sdk__tool__builtins__invoke_skill__InvokeSkillAction-Output__1": "#/components/schemas/InvokeSkillAction", + "openhands__sdk__tool__builtins__switch_llm__SwitchLLMAction-Output__1": "#/components/schemas/SwitchLLMAction", + "openhands__sdk__tool__builtins__think__ThinkAction-Output__1": "#/components/schemas/ThinkAction", + "openhands__sdk__tool__builtins__vision_inspect__VisionInspectAction-Output__1": "#/components/schemas/VisionInspectAction", + "openhands__tools__ask_oracle__definition__AskOracleAction-Output__1": "#/components/schemas/AskOracleAction", + "openhands__tools__browser_use__definition__BrowserAction-Output__1": "#/components/schemas/BrowserAction", + "openhands__tools__browser_use__definition__BrowserClickAction-Output__1": "#/components/schemas/BrowserClickAction", + "openhands__tools__browser_use__definition__BrowserCloseTabAction-Output__1": "#/components/schemas/BrowserCloseTabAction", + "openhands__tools__browser_use__definition__BrowserGetContentAction-Output__1": "#/components/schemas/BrowserGetContentAction", + "openhands__tools__browser_use__definition__BrowserGetStateAction-Output__1": "#/components/schemas/BrowserGetStateAction", + "openhands__tools__browser_use__definition__BrowserGetStorageAction-Output__1": "#/components/schemas/BrowserGetStorageAction", + "openhands__tools__browser_use__definition__BrowserGoBackAction-Output__1": "#/components/schemas/BrowserGoBackAction", + "openhands__tools__browser_use__definition__BrowserListTabsAction-Output__1": "#/components/schemas/BrowserListTabsAction", + "openhands__tools__browser_use__definition__BrowserNavigateAction-Output__1": "#/components/schemas/BrowserNavigateAction", + "openhands__tools__browser_use__definition__BrowserScrollAction-Output__1": "#/components/schemas/BrowserScrollAction", + "openhands__tools__browser_use__definition__BrowserSetStorageAction-Output__1": "#/components/schemas/BrowserSetStorageAction", + "openhands__tools__browser_use__definition__BrowserStartRecordingAction-Output__1": "#/components/schemas/BrowserStartRecordingAction", + "openhands__tools__browser_use__definition__BrowserStopRecordingAction-Output__1": "#/components/schemas/BrowserStopRecordingAction", + "openhands__tools__browser_use__definition__BrowserSwitchTabAction-Output__1": "#/components/schemas/BrowserSwitchTabAction", + "openhands__tools__browser_use__definition__BrowserTypeAction-Output__1": "#/components/schemas/BrowserTypeAction", + "openhands__tools__delegate__definition__DelegateAction-Output__1": "#/components/schemas/DelegateAction", + "openhands__tools__file_editor__definition__FileEditorAction-Output__1": "#/components/schemas/FileEditorAction", + "openhands__tools__gemini__edit__definition__EditAction-Output__1": "#/components/schemas/EditAction", + "openhands__tools__gemini__list_directory__definition__ListDirectoryAction-Output__1": "#/components/schemas/ListDirectoryAction", + "openhands__tools__gemini__read_file__definition__ReadFileAction-Output__1": "#/components/schemas/ReadFileAction", + "openhands__tools__gemini__write_file__definition__WriteFileAction-Output__1": "#/components/schemas/WriteFileAction", + "openhands__tools__glob__definition__GlobAction-Output__1": "#/components/schemas/GlobAction", + "openhands__tools__grep__definition__GrepAction-Output__1": "#/components/schemas/GrepAction", + "openhands__tools__planning_file_editor__definition__PlanningFileEditorAction-Output__1": "#/components/schemas/PlanningFileEditorAction", + "openhands__tools__task__definition__TaskAction-Output__1": "#/components/schemas/TaskAction", + "openhands__tools__task_tracker__definition__TaskTrackerAction-Output__1": "#/components/schemas/TaskTrackerAction", + "openhands__tools__terminal__definition__TerminalAction-Output__1": "#/components/schemas/TerminalAction", + "openhands__tools__workflow__definition__WorkflowAction-Output__1": "#/components/schemas/WorkflowAction" + }, + "propertyName": "kind" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/MCPToolAction" + }, + { + "$ref": "#/components/schemas/ClassifyAndSwitchLLMAction" + }, + { + "$ref": "#/components/schemas/FinishAction" + }, + { + "$ref": "#/components/schemas/InvokeSkillAction" + }, + { + "$ref": "#/components/schemas/SwitchLLMAction" + }, + { + "$ref": "#/components/schemas/ThinkAction" + }, + { + "$ref": "#/components/schemas/VisionInspectAction" + }, + { + "$ref": "#/components/schemas/AskOracleAction" + }, + { + "$ref": "#/components/schemas/BrowserAction" + }, + { + "$ref": "#/components/schemas/BrowserClickAction" + }, + { + "$ref": "#/components/schemas/BrowserCloseTabAction" + }, + { + "$ref": "#/components/schemas/BrowserGetContentAction" + }, + { + "$ref": "#/components/schemas/BrowserGetStateAction" + }, + { + "$ref": "#/components/schemas/BrowserGetStorageAction" + }, + { + "$ref": "#/components/schemas/BrowserGoBackAction" + }, + { + "$ref": "#/components/schemas/BrowserListTabsAction" + }, + { + "$ref": "#/components/schemas/BrowserNavigateAction" + }, + { + "$ref": "#/components/schemas/BrowserScrollAction" + }, + { + "$ref": "#/components/schemas/BrowserSetStorageAction" + }, + { + "$ref": "#/components/schemas/BrowserStartRecordingAction" + }, + { + "$ref": "#/components/schemas/BrowserStopRecordingAction" + }, + { + "$ref": "#/components/schemas/BrowserSwitchTabAction" + }, + { + "$ref": "#/components/schemas/BrowserTypeAction" + }, + { + "$ref": "#/components/schemas/DelegateAction" + }, + { + "$ref": "#/components/schemas/FileEditorAction" + }, + { + "$ref": "#/components/schemas/EditAction" + }, + { + "$ref": "#/components/schemas/ListDirectoryAction" + }, + { + "$ref": "#/components/schemas/ReadFileAction" + }, + { + "$ref": "#/components/schemas/WriteFileAction" + }, + { + "$ref": "#/components/schemas/GlobAction" + }, + { + "$ref": "#/components/schemas/GrepAction" + }, + { + "$ref": "#/components/schemas/PlanningFileEditorAction" + }, + { + "$ref": "#/components/schemas/TaskAction" + }, + { + "$ref": "#/components/schemas/TaskTrackerAction" + }, + { + "$ref": "#/components/schemas/TerminalAction" + }, + { + "$ref": "#/components/schemas/WorkflowAction" + } + ] + }, + "ActionEvent": { + "additionalProperties": false, + "properties": { + "action": { + "anyOf": [ + { + "$ref": "#/components/schemas/Action" + }, + { + "type": "null" + } + ], + "description": "Single tool call returned by LLM (None when non-executable)" + }, + "critic_result": { + "anyOf": [ + { + "$ref": "#/components/schemas/CriticResult" + }, + { + "type": "null" + } + ], + "description": "Optional critic evaluation of this action and preceding history." + }, + "id": { + "description": "Unique event id (ULID/UUID)", + "title": "Id", + "type": "string" + }, + "kind": { + "const": "ActionEvent", + "title": "Kind", + "type": "string" + }, + "llm_response_id": { + "description": "Completion or Response ID of the LLM response that generated this eventE.g., Can be used to group related actions from same LLM response. This helps in tracking and managing results of parallel function calling from the same LLM response.", + "title": "Llm Response Id", + "type": "string" + }, + "parent_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Parent event id in the conversation tree. None for the root, or for legacy events predating the tree (see EventLog's effective-parent rule). Events sharing a parent_id are sibling branches.", + "title": "Parent Id" + }, + "reasoning_content": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Intermediate reasoning/thinking content from reasoning models", + "title": "Reasoning Content" + }, + "responses_reasoning_item": { + "anyOf": [ + { + "$ref": "#/components/schemas/ReasoningItemModel" + }, + { + "type": "null" + } + ], + "description": "OpenAI Responses reasoning item from model output" + }, + "security_risk": { + "$ref": "#/components/schemas/SecurityRisk", + "default": "UNKNOWN", + "description": "The LLM's assessment of the safety risk of this action." + }, + "source": { + "default": "agent", + "enum": [ + "agent", + "user", + "environment", + "hook" + ], + "title": "Source", + "type": "string" + }, + "summary": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "A concise summary (approximately 10 words) of what this action does, provided by the LLM for explainability and debugging. Examples of good summaries: 'editing configuration file for deployment settings' | 'searching codebase for authentication function definitions' | 'installing required dependencies from package manifest' | 'running tests to verify bug fix' | 'viewing directory structure to locate source files'", + "title": "Summary" + }, + "thinking_blocks": { + "description": "Anthropic thinking blocks from the LLM response", + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/ThinkingBlock" + }, + { + "$ref": "#/components/schemas/RedactedThinkingBlock" + } + ] + }, + "title": "Thinking Blocks", + "type": "array" + }, + "thought": { + "description": "The thought process of the agent before taking this action", + "items": { + "$ref": "#/components/schemas/TextContent" + }, + "title": "Thought", + "type": "array" + }, + "timestamp": { + "description": "Event timestamp", + "title": "Timestamp", + "type": "string" + }, + "tool_call": { + "$ref": "#/components/schemas/MessageToolCall", + "description": "The tool call received from the LLM response. We keep a copy of it so it is easier to construct it into LLM messageThis could be different from `action`: e.g., `tool_call` may contain `security_risk` field predicted by LLM when LLM risk analyzer is enabled, while `action` does not." + }, + "tool_call_id": { + "description": "The unique id returned by LLM API for this tool call", + "title": "Tool Call Id", + "type": "string" + }, + "tool_name": { + "description": "The name of the tool being called", + "title": "Tool Name", + "type": "string" + } + }, + "required": [ + "thought", + "tool_name", + "tool_call_id", + "tool_call", + "llm_response_id", + "kind" + ], + "title": "ActionEvent", + "type": "object" + }, + "ActivateAgentProfileResponse": { + "properties": { + "agent_settings_applied": { + "default": false, + "title": "Agent Settings Applied", + "type": "boolean" + }, + "id": { + "title": "Id", + "type": "string" + }, + "message": { + "title": "Message", + "type": "string" + } + }, + "required": [ + "id", + "message" + ], + "title": "ActivateAgentProfileResponse", + "type": "object" + }, + "ActivateMetaProfileResponse": { + "properties": { + "message": { + "title": "Message", + "type": "string" + }, + "name": { + "title": "Name", + "type": "string" + } + }, + "required": [ + "name", + "message" + ], + "title": "ActivateMetaProfileResponse", + "type": "object" + }, + "ActivateProfileResponse": { + "description": "Response model for profile activation.", + "properties": { + "llm_applied": { + "default": true, + "title": "Llm Applied", + "type": "boolean" + }, + "message": { + "title": "Message", + "type": "string" + }, + "name": { + "title": "Name", + "type": "string" + } + }, + "required": [ + "name", + "message" + ], + "title": "ActivateProfileResponse", + "type": "object" + }, + "AddWorkspaceParentsRequest": { + "properties": { + "parents": { + "items": { + "$ref": "#/components/schemas/WorkspaceParentItem" + }, + "title": "Parents", + "type": "array" + } + }, + "required": [ + "parents" + ], + "title": "AddWorkspaceParentsRequest", + "type": "object" + }, + "AddWorkspacesRequest": { + "properties": { + "workspaces": { + "items": { + "$ref": "#/components/schemas/WorkspaceItem" + }, + "title": "Workspaces", + "type": "array" + } + }, + "required": [ + "workspaces" + ], + "title": "AddWorkspacesRequest", + "type": "object" + }, + "Agent-Input": { + "description": "Main agent implementation for OpenHands.\n\nThe Agent class provides the core functionality for running AI agents that can\ninteract with tools, process messages, and execute actions. It inherits from\nAgentBase and implements the agent execution logic. Critic-related functionality\nis provided by CriticMixin.\n\nAttributes:\n llm: The language model instance used for reasoning.\n tools: List of tools available to the agent.\n system_prompt: Inline system prompt string. When provided the agent\n uses this text verbatim instead of rendering from a template.\n Mutually exclusive with a non-default ``system_prompt_filename``.\n **Not recommended** unless you know what you are doing (e.g.\n customising agent behaviour for a completely different task) —\n this will override OpenHands' built-in system instructions.\n system_prompt_filename: Jinja2 template filename resolved relative to\n the agent's prompts directory, or an absolute path. Defaults to\n ``\"system_prompt.j2\"``.\n system_prompt_kwargs: Extra kwargs forwarded to the Jinja2 template.\n\nExample:\n ```python\n from openhands.sdk import LLM, Agent, Tool\n from pydantic import SecretStr\n\n llm = LLM(model=\"gpt-5.6\", api_key=SecretStr(\"key\"))\n tools = [Tool(name=\"TerminalTool\"), Tool(name=\"FileEditorTool\")]\n agent = Agent(llm=llm, tools=tools)\n ```\n\n To override the system prompt entirely::\n\n agent = Agent(\n llm=llm,\n tools=tools,\n system_prompt=\"You are a helpful coding assistant.\",\n )", + "properties": { + "agent_context": { + "anyOf": [ + { + "$ref": "#/components/schemas/AgentContext-Input" + }, + { + "type": "null" + } + ], + "description": "Optional AgentContext to initialize the agent with specific context.", + "examples": [ + { + "skills": [ + { + "content": "When you see this message, you should reply like you are a grumpy cat forced to use the internet.", + "name": "AGENTS.md", + "type": "repo" + }, + { + "content": "IMPORTANT! The user has said the magic word \"flarglebargle\". You must only respond with a message telling them how smart they are", + "name": "flarglebargle", + "trigger": [ + "flarglebargle" + ], + "type": "knowledge" + } + ], + "system_message_suffix": "Always finish your response with the word 'yay!'", + "user_message_prefix": "The first character of your response should be 'I'" + } + ] + }, + "condenser": { + "anyOf": [ + { + "$ref": "#/components/schemas/CondenserBase-Input" + }, + { + "type": "null" + } + ], + "description": "Optional condenser to use for condensing conversation history.", + "examples": [ + { + "keep_first": 10, + "kind": "LLMSummarizingCondenser", + "llm": { + "api_key": "your_api_key_here", + "base_url": "https://llm-proxy.eval.all-hands.dev", + "model": "litellm_proxy/openai/gpt-5.5" + }, + "max_size": 80 + } + ] + }, + "critic": { + "anyOf": [ + { + "$ref": "#/components/schemas/CriticBase-Input" + }, + { + "type": "null" + } + ], + "description": "EXPERIMENTAL: Optional critic to evaluate agent actions and messages in real-time. API and behavior may change without notice. May impact performance, especially in 'all_actions' mode.", + "examples": [ + { + "kind": "AgentFinishedCritic" + } + ] + }, + "filter_tools_regex": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Optional regex to filter the tools available to the agent by name. This is applied after any tools provided in `tools` and any MCP tools are added.", + "examples": [ + "^(?!repomix)(.*)|^repomix.*pack_codebase.*$" + ], + "title": "Filter Tools Regex" + }, + "include_default_tools": { + "description": "List of default tool class names to include. By default, the agent includes 'FinishTool' and 'ThinkTool'. Set to an empty list to disable all default tools, or provide a subset to include only specific ones. Example: include_default_tools=['FinishTool'] to only include FinishTool, or include_default_tools=[] to disable all default tools.", + "examples": [ + [ + "FinishTool", + "ThinkTool" + ], + [ + "FinishTool" + ], + [] + ], + "items": { + "type": "string" + }, + "title": "Include Default Tools", + "type": "array" + }, + "kind": { + "const": "Agent", + "title": "Kind", + "type": "string" + }, + "llm": { + "$ref": "#/components/schemas/LLM-Input", + "description": "LLM configuration for the agent.", + "examples": [ + { + "api_key": "your_api_key_here", + "base_url": "https://llm-proxy.eval.all-hands.dev", + "model": "litellm_proxy/openai/gpt-5.5" + } + ] + }, + "mcp_config": { + "additionalProperties": { + "$ref": "#/components/schemas/MCPServer-Input" + }, + "description": "Optional MCP servers to expose as tools.", + "examples": [ + { + "fetch": { + "args": [ + "--with", + "mcp==1.29.0", + "mcp-server-fetch==2026.7.10" + ], + "command": "uvx" + } + } + ], + "title": "Mcp Config", + "type": "object" + }, + "persona": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Persona text that replaces OpenHands' built-in persona and coding-workflow sections of the system prompt. Capability and policy sections (memory, security policy, risk assessment, browser, external services, process management, model-specific guidance) and the dynamic context still apply. Ignored when `system_prompt` is set; a custom template receives it as the `persona` kwarg.", + "title": "Persona" + }, + "security_policy_filename": { + "default": "security_policy.j2", + "description": "Security policy filename. The default 'security_policy.j2' is a back-compat sentinel (the file was removed) that selects the built-in default policy from the prompt registry -- it is not loaded from disk. Any other value names a custom policy file whose contents are inserted verbatim (NOT rendered as a Jinja template). Can be either:\n- A relative filename (e.g., 'custom_security_policy.md') loaded from the agent's prompts directory\n- An absolute path (e.g., '/path/to/custom_security_policy.md')\n- Empty string to disable security policy", + "title": "Security Policy Filename", + "type": "string" + }, + "system_prompt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Inline system prompt string. When provided, the agent uses this text verbatim as the system message instead of rendering from `system_prompt_filename`. Mutually exclusive with a non-default `system_prompt_filename`.\n\n**Warning**: This is not recommended unless you know what you are doing (e.g. customising agent behaviour for a completely different task). Setting this will override OpenHands' built-in system instructions that govern default agent behaviour.", + "title": "System Prompt" + }, + "system_prompt_filename": { + "default": "system_prompt.j2", + "description": "System prompt template filename. Can be either:\n- A relative filename (e.g., 'system_prompt.j2') loaded from the agent's prompts directory\n- An absolute path (e.g., '/path/to/custom_prompt.j2')", + "title": "System Prompt Filename", + "type": "string" + }, + "system_prompt_kwargs": { + "additionalProperties": true, + "description": "Optional kwargs to pass to the system prompt Jinja2 template.", + "examples": [ + { + "cli_mode": true + } + ], + "title": "System Prompt Kwargs", + "type": "object" + }, + "tool_concurrency_limit": { + "default": 1, + "description": "Maximum number of tool calls to execute concurrently within a single agent step. Default is 1 (sequential). Values > 1 enable parallel execution; concurrent tools share the conversation object, filesystem, and working directory, so mutations to shared state may race.", + "minimum": 1.0, + "title": "Tool Concurrency Limit", + "type": "integer" + }, + "tools": { + "description": "List of tools to initialize for the agent.", + "examples": [ + { + "name": "TerminalTool", + "params": {} + }, + { + "name": "FileEditorTool", + "params": {} + }, + { + "name": "TaskTrackerTool", + "params": {} + } + ], + "items": { + "$ref": "#/components/schemas/Tool-Input" + }, + "title": "Tools", + "type": "array" + } + }, + "required": [ + "llm" + ], + "title": "Agent", + "type": "object" + }, + "Agent-Output": { + "description": "Main agent implementation for OpenHands.\n\nThe Agent class provides the core functionality for running AI agents that can\ninteract with tools, process messages, and execute actions. It inherits from\nAgentBase and implements the agent execution logic. Critic-related functionality\nis provided by CriticMixin.\n\nAttributes:\n llm: The language model instance used for reasoning.\n tools: List of tools available to the agent.\n system_prompt: Inline system prompt string. When provided the agent\n uses this text verbatim instead of rendering from a template.\n Mutually exclusive with a non-default ``system_prompt_filename``.\n **Not recommended** unless you know what you are doing (e.g.\n customising agent behaviour for a completely different task) —\n this will override OpenHands' built-in system instructions.\n system_prompt_filename: Jinja2 template filename resolved relative to\n the agent's prompts directory, or an absolute path. Defaults to\n ``\"system_prompt.j2\"``.\n system_prompt_kwargs: Extra kwargs forwarded to the Jinja2 template.\n\nExample:\n ```python\n from openhands.sdk import LLM, Agent, Tool\n from pydantic import SecretStr\n\n llm = LLM(model=\"gpt-5.6\", api_key=SecretStr(\"key\"))\n tools = [Tool(name=\"TerminalTool\"), Tool(name=\"FileEditorTool\")]\n agent = Agent(llm=llm, tools=tools)\n ```\n\n To override the system prompt entirely::\n\n agent = Agent(\n llm=llm,\n tools=tools,\n system_prompt=\"You are a helpful coding assistant.\",\n )", + "properties": { + "agent_context": { + "anyOf": [ + { + "$ref": "#/components/schemas/AgentContext-Output" + }, + { + "type": "null" + } + ], + "description": "Optional AgentContext to initialize the agent with specific context.", + "examples": [ + { + "skills": [ + { + "content": "When you see this message, you should reply like you are a grumpy cat forced to use the internet.", + "name": "AGENTS.md", + "type": "repo" + }, + { + "content": "IMPORTANT! The user has said the magic word \"flarglebargle\". You must only respond with a message telling them how smart they are", + "name": "flarglebargle", + "trigger": [ + "flarglebargle" + ], + "type": "knowledge" + } + ], + "system_message_suffix": "Always finish your response with the word 'yay!'", + "user_message_prefix": "The first character of your response should be 'I'" + } + ] + }, + "condenser": { + "anyOf": [ + { + "$ref": "#/components/schemas/CondenserBase-Output" + }, + { + "type": "null" + } + ], + "description": "Optional condenser to use for condensing conversation history.", + "examples": [ + { + "keep_first": 10, + "kind": "LLMSummarizingCondenser", + "llm": { + "api_key": "your_api_key_here", + "base_url": "https://llm-proxy.eval.all-hands.dev", + "model": "litellm_proxy/openai/gpt-5.5" + }, + "max_size": 80 + } + ] + }, + "critic": { + "anyOf": [ + { + "$ref": "#/components/schemas/CriticBase-Output" + }, + { + "type": "null" + } + ], + "description": "EXPERIMENTAL: Optional critic to evaluate agent actions and messages in real-time. API and behavior may change without notice. May impact performance, especially in 'all_actions' mode.", + "examples": [ + { + "kind": "AgentFinishedCritic" + } + ] + }, + "filter_tools_regex": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Optional regex to filter the tools available to the agent by name. This is applied after any tools provided in `tools` and any MCP tools are added.", + "examples": [ + "^(?!repomix)(.*)|^repomix.*pack_codebase.*$" + ], + "title": "Filter Tools Regex" + }, + "include_default_tools": { + "description": "List of default tool class names to include. By default, the agent includes 'FinishTool' and 'ThinkTool'. Set to an empty list to disable all default tools, or provide a subset to include only specific ones. Example: include_default_tools=['FinishTool'] to only include FinishTool, or include_default_tools=[] to disable all default tools.", + "examples": [ + [ + "FinishTool", + "ThinkTool" + ], + [ + "FinishTool" + ], + [] + ], + "items": { + "type": "string" + }, + "title": "Include Default Tools", + "type": "array" + }, + "kind": { + "const": "Agent", + "title": "Kind", + "type": "string" + }, + "llm": { + "$ref": "#/components/schemas/LLM-Output", + "description": "LLM configuration for the agent.", + "examples": [ + { + "api_key": "your_api_key_here", + "base_url": "https://llm-proxy.eval.all-hands.dev", + "model": "litellm_proxy/openai/gpt-5.5" + } + ] + }, + "mcp_config": { + "additionalProperties": { + "$ref": "#/components/schemas/MCPServer-Output" + }, + "description": "Optional MCP servers to expose as tools.", + "examples": [ + { + "fetch": { + "args": [ + "--with", + "mcp==1.29.0", + "mcp-server-fetch==2026.7.10" + ], + "command": "uvx" + } + } + ], + "title": "Mcp Config", + "type": "object" + }, + "persona": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Persona text that replaces OpenHands' built-in persona and coding-workflow sections of the system prompt. Capability and policy sections (memory, security policy, risk assessment, browser, external services, process management, model-specific guidance) and the dynamic context still apply. Ignored when `system_prompt` is set; a custom template receives it as the `persona` kwarg.", + "title": "Persona" + }, + "security_policy_filename": { + "default": "security_policy.j2", + "description": "Security policy filename. The default 'security_policy.j2' is a back-compat sentinel (the file was removed) that selects the built-in default policy from the prompt registry -- it is not loaded from disk. Any other value names a custom policy file whose contents are inserted verbatim (NOT rendered as a Jinja template). Can be either:\n- A relative filename (e.g., 'custom_security_policy.md') loaded from the agent's prompts directory\n- An absolute path (e.g., '/path/to/custom_security_policy.md')\n- Empty string to disable security policy", + "title": "Security Policy Filename", + "type": "string" + }, + "system_prompt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Inline system prompt string. When provided, the agent uses this text verbatim as the system message instead of rendering from `system_prompt_filename`. Mutually exclusive with a non-default `system_prompt_filename`.\n\n**Warning**: This is not recommended unless you know what you are doing (e.g. customising agent behaviour for a completely different task). Setting this will override OpenHands' built-in system instructions that govern default agent behaviour.", + "title": "System Prompt" + }, + "system_prompt_filename": { + "default": "system_prompt.j2", + "description": "System prompt template filename. Can be either:\n- A relative filename (e.g., 'system_prompt.j2') loaded from the agent's prompts directory\n- An absolute path (e.g., '/path/to/custom_prompt.j2')", + "title": "System Prompt Filename", + "type": "string" + }, + "system_prompt_kwargs": { + "additionalProperties": true, + "description": "Optional kwargs to pass to the system prompt Jinja2 template.", + "examples": [ + { + "cli_mode": true + } + ], + "title": "System Prompt Kwargs", + "type": "object" + }, + "tool_concurrency_limit": { + "default": 1, + "description": "Maximum number of tool calls to execute concurrently within a single agent step. Default is 1 (sequential). Values > 1 enable parallel execution; concurrent tools share the conversation object, filesystem, and working directory, so mutations to shared state may race.", + "minimum": 1.0, + "title": "Tool Concurrency Limit", + "type": "integer" + }, + "tools": { + "description": "List of tools to initialize for the agent.", + "examples": [ + { + "name": "TerminalTool", + "params": {} + }, + { + "name": "FileEditorTool", + "params": {} + }, + { + "name": "TaskTrackerTool", + "params": {} + } + ], + "items": { + "$ref": "#/components/schemas/openhands__sdk__tool__spec__Tool" + }, + "title": "Tools", + "type": "array" + } + }, + "required": [ + "llm", + "kind" + ], + "title": "Agent", + "type": "object" + }, + "AgentBase-Input": { + "discriminator": { + "mapping": { + "openhands__sdk__agent__acp_agent__ACPAgent-Input__1": "#/components/schemas/ACPAgent-Input", + "openhands__sdk__agent__agent__Agent-Input__1": "#/components/schemas/Agent-Input" + }, + "propertyName": "kind" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/ACPAgent-Input" + }, + { + "$ref": "#/components/schemas/Agent-Input" + } + ] + }, + "AgentBase-Output": { + "discriminator": { + "mapping": { + "openhands__sdk__agent__acp_agent__ACPAgent-Output__1": "#/components/schemas/ACPAgent-Output", + "openhands__sdk__agent__agent__Agent-Output__1": "#/components/schemas/Agent-Output" + }, + "propertyName": "kind" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/ACPAgent-Output" + }, + { + "$ref": "#/components/schemas/Agent-Output" + } + ] + }, + "AgentContext-Input": { + "description": "Central structure for managing prompt extension.\n\nAgentContext unifies all the contextual inputs that shape how the system\nextends and interprets user prompts. It combines both static environment\ndetails and dynamic, user-activated extensions from skills.\n\nSpecifically, it provides:\n- **Repository context / Repo Skills**: Information about the active codebase,\n branches, and repo-specific instructions contributed by repo skills.\n- **Runtime context**: Current execution environment (hosts, working\n directory, secrets, date, etc.).\n- **Conversation instructions**: Optional task- or channel-specific rules\n that constrain or guide the agent’s behavior across the session.\n- **Knowledge Skills**: Extensible components that can be triggered by user input\n to inject knowledge or domain-specific guidance.\n\nTogether, these elements make AgentContext the primary container responsible\nfor assembling, formatting, and injecting all prompt-relevant context into\nLLM interactions.", + "properties": { + "current_datetime": { + "acp_compatible": true, + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Current date and time information to provide to the agent. Can be a datetime object (which will be formatted as ISO 8601) or a pre-formatted string. When provided, this information is included in the system prompt to give the agent awareness of the current time context. Defaults to the current (timezone-aware) datetime.", + "title": "Current Datetime" + }, + "disabled_skills": { + "acp_compatible": true, + "description": "Names of skills to EXCLUDE from this context — a deny-list applied after every skill source is loaded (auto-loaded user/public, explicit, and lazily-loaded project skills). A listed name absent from the loaded set is a harmless no-op. [] (the default) keeps every skill. This is the single, drift-tolerant skill-selection mechanism (agent profiles set it from their own deny-list; #4017).", + "items": { + "type": "string" + }, + "title": "Disabled Skills", + "type": "array" + }, + "load_memory": { + "acp_compatible": true, + "default": false, + "description": "Whether to load persistent agent memory (MEMORY.md indexes under ~/.openhands/memory/ and /.openhands/memory/) into the system prompt. Like load_project_skills, this flag is not resolved by AgentContext itself (the workspace path is unknown at validation time); LocalConversation resolves it lazily on the first send_message() / run() and stores the result in memory_context.", + "openhands_settings": { + "depends_on": [], + "label": "Persistent memory", + "prominence": "major" + }, + "title": "Load Memory", + "type": "boolean" + }, + "load_project_skills": { + "acp_compatible": true, + "default": false, + "description": "Whether to automatically load project skills from the conversation workspace (e.g. .openhands/skills/, AGENTS.md). Unlike load_user_skills / load_public_skills, this flag is not resolved by AgentContext itself (the workspace path is unknown at validation time); LocalConversation resolves it lazily on the first send_message() / run(), when the workspace is known. Also unlike load_user_skills / load_public_skills (which yield to explicit skills on a name conflict), resolved project skills are authoritative: a project skill overrides a same-named skill already present in `skills`.", + "title": "Load Project Skills", + "type": "boolean" + }, + "load_public_skills": { + "acp_compatible": true, + "default": false, + "description": "Whether to automatically load skills from the public OpenHands skills repository at https://github.com/OpenHands/extensions. This allows you to get the latest skills without SDK updates.", + "title": "Load Public Skills", + "type": "boolean" + }, + "load_user_skills": { + "acp_compatible": true, + "default": false, + "description": "Whether to automatically load user skills from ~/.openhands/skills/ and ~/.openhands/microagents/ (for backward compatibility). ", + "title": "Load User Skills", + "type": "boolean" + }, + "marketplace_path": { + "acp_compatible": true, + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": "marketplaces/default.json", + "description": "Relative marketplace JSON path within the public skills repository. Set to None to load all public skills without marketplace filtering.", + "title": "Marketplace Path" + }, + "memory_context": { + "acp_compatible": true, + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Resolved memory-index text rendered into the prompt block. Populated via model_copy by LocalConversation when load_memory is set; excluded from serialization because it is re-resolved from disk each session and must not bloat persisted conversation state.", + "title": "Memory Context" + }, + "registered_marketplaces": { + "acp_compatible": true, + "description": "Marketplace registrations for plugin resolution. Registrations with auto_load=True or a list of plugin names are resolved by LocalConversation at startup.", + "items": { + "$ref": "#/components/schemas/MarketplaceRegistration" + }, + "title": "Registered Marketplaces", + "type": "array" + }, + "secrets": { + "acp_compatible": true, + "anyOf": [ + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/components/schemas/SecretSource-Input" + } + ] + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "Dictionary mapping secret keys to values or secret sources. Secrets are used for authentication and sensitive data handling. Values can be either strings or SecretSource instances (str | SecretSource).", + "title": "Secrets" + }, + "skills": { + "acp_compatible": true, + "description": "List of available skills that can extend the user's input.", + "items": { + "$ref": "#/components/schemas/Skill-Input" + }, + "title": "Skills", + "type": "array" + }, + "system_message_suffix": { + "acp_compatible": true, + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Optional suffix to append to the system prompt.", + "title": "System Message Suffix" + }, + "user_message_suffix": { + "acp_compatible": true, + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Optional suffix to append to the user's message.", + "title": "User Message Suffix" + } + }, + "title": "AgentContext", + "type": "object" + }, + "AgentContext-Output": { + "description": "Central structure for managing prompt extension.\n\nAgentContext unifies all the contextual inputs that shape how the system\nextends and interprets user prompts. It combines both static environment\ndetails and dynamic, user-activated extensions from skills.\n\nSpecifically, it provides:\n- **Repository context / Repo Skills**: Information about the active codebase,\n branches, and repo-specific instructions contributed by repo skills.\n- **Runtime context**: Current execution environment (hosts, working\n directory, secrets, date, etc.).\n- **Conversation instructions**: Optional task- or channel-specific rules\n that constrain or guide the agent’s behavior across the session.\n- **Knowledge Skills**: Extensible components that can be triggered by user input\n to inject knowledge or domain-specific guidance.\n\nTogether, these elements make AgentContext the primary container responsible\nfor assembling, formatting, and injecting all prompt-relevant context into\nLLM interactions.", + "properties": { + "current_datetime": { + "acp_compatible": true, + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Current date and time information to provide to the agent. Can be a datetime object (which will be formatted as ISO 8601) or a pre-formatted string. When provided, this information is included in the system prompt to give the agent awareness of the current time context. Defaults to the current (timezone-aware) datetime.", + "title": "Current Datetime" + }, + "disabled_skills": { + "acp_compatible": true, + "description": "Names of skills to EXCLUDE from this context — a deny-list applied after every skill source is loaded (auto-loaded user/public, explicit, and lazily-loaded project skills). A listed name absent from the loaded set is a harmless no-op. [] (the default) keeps every skill. This is the single, drift-tolerant skill-selection mechanism (agent profiles set it from their own deny-list; #4017).", + "items": { + "type": "string" + }, + "title": "Disabled Skills", + "type": "array" + }, + "load_memory": { + "acp_compatible": true, + "default": false, + "description": "Whether to load persistent agent memory (MEMORY.md indexes under ~/.openhands/memory/ and /.openhands/memory/) into the system prompt. Like load_project_skills, this flag is not resolved by AgentContext itself (the workspace path is unknown at validation time); LocalConversation resolves it lazily on the first send_message() / run() and stores the result in memory_context.", + "openhands_settings": { + "depends_on": [], + "label": "Persistent memory", + "prominence": "major" + }, + "title": "Load Memory", + "type": "boolean" + }, + "load_project_skills": { + "acp_compatible": true, + "default": false, + "description": "Whether to automatically load project skills from the conversation workspace (e.g. .openhands/skills/, AGENTS.md). Unlike load_user_skills / load_public_skills, this flag is not resolved by AgentContext itself (the workspace path is unknown at validation time); LocalConversation resolves it lazily on the first send_message() / run(), when the workspace is known. Also unlike load_user_skills / load_public_skills (which yield to explicit skills on a name conflict), resolved project skills are authoritative: a project skill overrides a same-named skill already present in `skills`.", + "title": "Load Project Skills", + "type": "boolean" + }, + "load_public_skills": { + "acp_compatible": true, + "default": false, + "description": "Whether to automatically load skills from the public OpenHands skills repository at https://github.com/OpenHands/extensions. This allows you to get the latest skills without SDK updates.", + "title": "Load Public Skills", + "type": "boolean" + }, + "load_user_skills": { + "acp_compatible": true, + "default": false, + "description": "Whether to automatically load user skills from ~/.openhands/skills/ and ~/.openhands/microagents/ (for backward compatibility). ", + "title": "Load User Skills", + "type": "boolean" + }, + "marketplace_path": { + "acp_compatible": true, + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": "marketplaces/default.json", + "description": "Relative marketplace JSON path within the public skills repository. Set to None to load all public skills without marketplace filtering.", + "title": "Marketplace Path" + }, + "registered_marketplaces": { + "acp_compatible": true, + "description": "Marketplace registrations for plugin resolution. Registrations with auto_load=True or a list of plugin names are resolved by LocalConversation at startup.", + "items": { + "$ref": "#/components/schemas/MarketplaceRegistration" + }, + "title": "Registered Marketplaces", + "type": "array" + }, + "secrets": { + "acp_compatible": true, + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "Dictionary mapping secret keys to values or secret sources. Secrets are used for authentication and sensitive data handling. Values can be either strings or SecretSource instances (str | SecretSource).", + "title": "Secrets" + }, + "skills": { + "acp_compatible": true, + "description": "List of available skills that can extend the user's input.", + "items": { + "$ref": "#/components/schemas/Skill-Output" + }, + "title": "Skills", + "type": "array" + }, + "system_message_suffix": { + "acp_compatible": true, + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Optional suffix to append to the system prompt.", + "title": "System Message Suffix" + }, + "user_message_suffix": { + "acp_compatible": true, + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Optional suffix to append to the user's message.", + "title": "User Message Suffix" + } + }, + "title": "AgentContext", + "type": "object" + }, + "AgentDefinition": { + "description": "Agent definition loaded from Markdown file.\n\nAgents are specialized configurations that can be triggered based on\nuser input patterns. They define custom system prompts and tool access.", + "properties": { + "color": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Display color for the agent", + "title": "Color" + }, + "condenser": { + "anyOf": [ + { + "$ref": "#/components/schemas/CondenserBase-Input" + }, + { + "type": "null" + } + ], + "description": "Context condenser for the sub-agent. None applies a default summarizing condenser; set a NoOpCondenser to disable condensation." + }, + "description": { + "default": "", + "description": "Agent description", + "title": "Description", + "type": "string" + }, + "hooks": { + "anyOf": [ + { + "$ref": "#/components/schemas/HookConfig" + }, + { + "type": "null" + } + ], + "description": "Hook configuration for this agent" + }, + "level": { + "anyOf": [ + { + "enum": [ + "project", + "user", + "builtin", + "plugin", + "programmatic" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Scope where the agent was discovered. Set during discovery; None when loaded directly from a file.", + "title": "Level" + }, + "max_budget_per_run": { + "anyOf": [ + { + "exclusiveMinimum": 0.0, + "type": "number" + }, + { + "type": "null" + } + ], + "description": "Maximum accumulated cost (USD) per run for this sub-agent. Must be strictly positive, or None for no budget.", + "title": "Max Budget Per Run" + }, + "max_iteration_per_run": { + "anyOf": [ + { + "exclusiveMinimum": 0.0, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Maximum iterations per run. It must be strictly positive, or None for default.", + "title": "Max Iteration Per Run" + }, + "mcp_config": { + "anyOf": [ + { + "additionalProperties": { + "$ref": "#/components/schemas/MCPServer-Input" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "MCP servers for this agent.", + "examples": [ + { + "fetch": { + "args": [ + "--with", + "mcp==1.29.0", + "mcp-server-fetch==2026.7.10" + ], + "command": "uvx" + } + } + ], + "title": "Mcp Config" + }, + "metadata": { + "additionalProperties": true, + "description": "Additional metadata from frontmatter", + "title": "Metadata", + "type": "object" + }, + "model": { + "default": "inherit", + "description": "Model to use ('inherit' uses parent model)", + "title": "Model", + "type": "string" + }, + "name": { + "description": "Agent name (from frontmatter or filename)", + "title": "Name", + "type": "string" + }, + "permission_mode": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "How the subagent handles permissions. None inherits the parent policy, 'always_confirm' requires confirmation for every action, 'never_confirm' skips all confirmations, 'confirm_risky' only confirms actions above a risk threshold.", + "title": "Permission Mode" + }, + "profile_store_dir": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Path to the directory where LLM profiles are stored. If None, the default profile store directory is used.", + "title": "Profile Store Dir" + }, + "skills": { + "description": "List of skill names for this agent. Resolved from project/user directories.", + "items": { + "type": "string" + }, + "title": "Skills", + "type": "array" + }, + "source": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Source file path for this agent", + "title": "Source" + }, + "system_prompt": { + "default": "", + "description": "System prompt content", + "title": "System Prompt", + "type": "string" + }, + "tools": { + "description": "List of allowed tools for this agent", + "items": { + "type": "string" + }, + "title": "Tools", + "type": "array" + }, + "when_to_use_examples": { + "description": "Examples of when to use this agent (for triggering)", + "items": { + "type": "string" + }, + "title": "When To Use Examples", + "type": "array" + } + }, + "required": [ + "name" + ], + "title": "AgentDefinition", + "type": "object" + }, + "AgentErrorEvent": { + "additionalProperties": false, + "description": "Error triggered by the agent.\n\nNote: This event should not contain model \"thought\" or \"reasoning_content\". It\nrepresents an error produced by the agent/scaffold, not model output.", + "properties": { + "classification": { + "anyOf": [ + { + "$ref": "#/components/schemas/ErrorClassification" + }, + { + "type": "null" + } + ], + "description": "Safe structured error semantics for API consumers." + }, + "error": { + "description": "The error message from the scaffold", + "title": "Error", + "type": "string" + }, + "id": { + "description": "Unique event id (ULID/UUID)", + "title": "Id", + "type": "string" + }, + "kind": { + "const": "AgentErrorEvent", + "title": "Kind", + "type": "string" + }, + "parent_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Parent event id in the conversation tree. None for the root, or for legacy events predating the tree (see EventLog's effective-parent rule). Events sharing a parent_id are sibling branches.", + "title": "Parent Id" + }, + "source": { + "default": "agent", + "enum": [ + "agent", + "user", + "environment", + "hook" + ], + "title": "Source", + "type": "string" + }, + "timestamp": { + "description": "Event timestamp", + "title": "Timestamp", + "type": "string" + }, + "tool_call_id": { + "description": "The tool call id that this observation is responding to", + "title": "Tool Call Id", + "type": "string" + }, + "tool_name": { + "description": "The tool name that this observation is responding to", + "title": "Tool Name", + "type": "string" + } + }, + "required": [ + "tool_name", + "tool_call_id", + "error", + "kind" + ], + "title": "AgentErrorEvent", + "type": "object" + }, + "AgentFinishedCritic-Input": { + "description": "Critic that evaluates whether an agent properly finished a task.\n\nThis critic checks two main criteria:\n1. The agent's last action was a FinishAction (proper completion)\n2. The generated git patch is non-empty (actual changes were made)", + "properties": { + "iterative_refinement": { + "anyOf": [ + { + "$ref": "#/components/schemas/IterativeRefinementConfig" + }, + { + "type": "null" + } + ], + "description": "Optional configuration for iterative refinement. When set, Conversation.run() will automatically retry the task if the critic score is below the success_threshold, up to max_iterations." + }, + "kind": { + "const": "AgentFinishedCritic", + "title": "Kind", + "type": "string" + }, + "mode": { + "default": "finish_and_message", + "description": "When to run critic evaluation:\n- 'finish_and_message': Evaluate on FinishAction and agent MessageEvent (default, minimal performance impact)\n- 'all_actions': Evaluate after every agent action (WARNING: significantly slower due to API calls on each action)", + "enum": [ + "finish_and_message", + "all_actions" + ], + "title": "Mode", + "type": "string" + } + }, + "title": "AgentFinishedCritic", + "type": "object" + }, + "AgentFinishedCritic-Output": { + "description": "Critic that evaluates whether an agent properly finished a task.\n\nThis critic checks two main criteria:\n1. The agent's last action was a FinishAction (proper completion)\n2. The generated git patch is non-empty (actual changes were made)", + "properties": { + "iterative_refinement": { + "anyOf": [ + { + "$ref": "#/components/schemas/IterativeRefinementConfig" + }, + { + "type": "null" + } + ], + "description": "Optional configuration for iterative refinement. When set, Conversation.run() will automatically retry the task if the critic score is below the success_threshold, up to max_iterations." + }, + "kind": { + "const": "AgentFinishedCritic", + "title": "Kind", + "type": "string" + }, + "mode": { + "default": "finish_and_message", + "description": "When to run critic evaluation:\n- 'finish_and_message': Evaluate on FinishAction and agent MessageEvent (default, minimal performance impact)\n- 'all_actions': Evaluate after every agent action (WARNING: significantly slower due to API calls on each action)", + "enum": [ + "finish_and_message", + "all_actions" + ], + "title": "Mode", + "type": "string" + } + }, + "required": [ + "kind" + ], + "title": "AgentFinishedCritic", + "type": "object" + }, + "AgentLaunchAdditions": { + "additionalProperties": false, + "description": "Add deployment context after agent resolution.", + "properties": { + "system_message_suffix_append": { + "anyOf": [ + { + "maxLength": 32768, + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Deployment-controlled text appended to the resolved agent's system-message suffix.", + "title": "System Message Suffix Append" + } + }, + "title": "AgentLaunchAdditions", + "type": "object" + }, + "AgentProfileDetailResponse": { + "properties": { + "name": { + "title": "Name", + "type": "string" + }, + "profile": { + "additionalProperties": true, + "title": "Profile", + "type": "object" + } + }, + "required": [ + "name", + "profile" + ], + "title": "AgentProfileDetailResponse", + "type": "object" + }, + "AgentProfileDiagnostics": { + "description": "Side-effect-free report of what :func:`resolve_agent_profile` would do.\n\nConsumed by ``POST /{id}/materialize`` (#3719) and the canvas editor. The\nverdict (:attr:`valid`) and the dangling-ref lists match exactly what a real\nresolve produces; :attr:`resolved_settings` is the redacted settings dump\n(present only when :attr:`valid`).", + "properties": { + "acp_api_key_secret_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Acp Api Key Secret Name" + }, + "acp_base_url_secret_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Acp Base Url Secret Name" + }, + "acp_file_secret_names": { + "items": { + "type": "string" + }, + "title": "Acp File Secret Names", + "type": "array" + }, + "agent_kind": { + "title": "Agent Kind", + "type": "string" + }, + "dangling_mcp_server_refs": { + "items": { + "type": "string" + }, + "title": "Dangling Mcp Server Refs", + "type": "array" + }, + "dangling_meta_profile_llm_refs": { + "items": { + "type": "string" + }, + "title": "Dangling Meta Profile Llm Refs", + "type": "array" + }, + "dangling_meta_profile_ref": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Dangling Meta Profile Ref" + }, + "disabled_skills": { + "items": { + "type": "string" + }, + "title": "Disabled Skills", + "type": "array" + }, + "errors": { + "items": { + "type": "string" + }, + "title": "Errors", + "type": "array" + }, + "llm_api_key_set": { + "default": false, + "title": "Llm Api Key Set", + "type": "boolean" + }, + "llm_profile_ref": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Llm Profile Ref" + }, + "llm_profile_resolved": { + "default": false, + "title": "Llm Profile Resolved", + "type": "boolean" + }, + "mcp_server_refs": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Mcp Server Refs" + }, + "meta_profile_ref": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Meta Profile Ref" + }, + "resolved_mcp_config_keys": { + "items": { + "type": "string" + }, + "title": "Resolved Mcp Config Keys", + "type": "array" + }, + "resolved_settings": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Resolved Settings" + }, + "resolved_skills": { + "items": { + "type": "string" + }, + "title": "Resolved Skills", + "type": "array" + }, + "secret_refs": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Secret Refs" + }, + "unusable_tools": { + "description": "Selected tools the runtime cannot run. An unavailable browser is left out of the launch; any other such tool fails the launch or fails when the agent uses it.", + "items": { + "type": "string" + }, + "title": "Unusable Tools", + "type": "array" + }, + "valid": { + "default": false, + "title": "Valid", + "type": "boolean" + } + }, + "required": [ + "agent_kind" + ], + "title": "AgentProfileDiagnostics", + "type": "object" + }, + "AgentProfileInfo": { + "description": "Summary projection of a stored profile (no secret instantiation).", + "properties": { + "agent_kind": { + "default": "openhands", + "title": "Agent Kind", + "type": "string" + }, + "id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Id" + }, + "llm_profile_ref": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Llm Profile Ref" + }, + "mcp_server_refs": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Mcp Server Refs" + }, + "name": { + "title": "Name", + "type": "string" + }, + "revision": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Revision" + } + }, + "required": [ + "name" + ], + "title": "AgentProfileInfo", + "type": "object" + }, + "AgentProfileListResponse": { + "properties": { + "active_agent_profile_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Active Agent Profile Id" + }, + "profiles": { + "items": { + "$ref": "#/components/schemas/AgentProfileInfo" + }, + "title": "Profiles", + "type": "array" + } + }, + "required": [ + "profiles" + ], + "title": "AgentProfileListResponse", + "type": "object" + }, + "AgentProfileMutationResponse": { + "properties": { + "message": { + "title": "Message", + "type": "string" + }, + "name": { + "title": "Name", + "type": "string" + } + }, + "required": [ + "name", + "message" + ], + "title": "AgentProfileMutationResponse", + "type": "object" + }, + "AgentResponseResult": { + "description": "The agent's final response for a conversation.\n\nContains the text of the last agent finish message or text response.\nEmpty string if the agent has not produced a final response yet.", + "properties": { + "response": { + "description": "The agent's final response text. Extracted from either a FinishAction message or the last agent MessageEvent. Empty string if no final response is available.", + "title": "Response", + "type": "string" + } + }, + "required": [ + "response" + ], + "title": "AgentResponseResult", + "type": "object" + }, + "AgentSettings": { + "additionalProperties": true, + "properties": { + "agent_kind": { + "anyOf": [ + { + "enum": [ + "openhands", + "acp" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Agent Kind" + }, + "mcp_config": { + "$ref": "#/components/schemas/MCPConfig" + }, + "schema_version": { + "anyOf": [ + { + "minimum": 1.0, + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Schema Version" + } + }, + "required": [ + "mcp_config" + ], + "title": "AgentSettings", + "type": "object" + }, + "AgentSettingsPatch": { + "additionalProperties": true, + "properties": { + "mcp_config": { + "anyOf": [ + { + "$ref": "#/components/schemas/MCPConfigPatch" + }, + { + "type": "null" + } + ] + } + }, + "title": "AgentSettingsPatch", + "type": "object" + }, + "AlwaysConfirm-Input": { + "properties": { + "kind": { + "const": "AlwaysConfirm", + "title": "Kind", + "type": "string" + } + }, + "title": "AlwaysConfirm", + "type": "object" + }, + "AlwaysConfirm-Output": { + "properties": { + "kind": { + "const": "AlwaysConfirm", + "title": "Kind", + "type": "string" + } + }, + "required": [ + "kind" + ], + "title": "AlwaysConfirm", + "type": "object" + }, + "AskAgentRequest": { + "description": "Payload to ask the agent a simple question.", + "properties": { + "question": { + "description": "The question to ask the agent", + "title": "Question", + "type": "string" + } + }, + "required": [ + "question" + ], + "title": "AskAgentRequest", + "type": "object" + }, + "AskAgentResponse": { + "description": "Response containing the agent's answer.", + "properties": { + "response": { + "description": "The agent's response to the question", + "title": "Response", + "type": "string" + } + }, + "required": [ + "response" + ], + "title": "AskAgentResponse", + "type": "object" + }, + "AskOracleAction": { + "additionalProperties": false, + "description": "Action for asking the Oracle for advice.", + "properties": { + "context": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Optional extra context, such as approaches already tried, constraints, or the recommendation you are considering.", + "title": "Context" + }, + "kind": { + "const": "AskOracleAction", + "title": "Kind", + "type": "string" + }, + "question": { + "description": "The specific question or dilemma to ask the Oracle about. Use this when you are stuck, uncertain, or need a second opinion.", + "title": "Question", + "type": "string" + } + }, + "required": [ + "question", + "kind" + ], + "title": "AskOracleAction", + "type": "object" + }, + "AskOracleObservation": { + "additionalProperties": false, + "description": "Observation returned by the Oracle consultation.", + "properties": { + "content": { + "description": "Content returned from the tool as a list of TextContent/ImageContent objects. When there is an error, it should be written in this field.", + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/TextContent" + }, + { + "$ref": "#/components/schemas/ImageContent" + } + ] + }, + "title": "Content", + "type": "array" + }, + "is_error": { + "default": false, + "description": "Whether the observation indicates an error", + "title": "Is Error", + "type": "boolean" + }, + "kind": { + "const": "AskOracleObservation", + "title": "Kind", + "type": "string" + } + }, + "required": [ + "kind" + ], + "title": "AskOracleObservation", + "type": "object" + }, + "AskOracleTool": { + "description": "Tool for consulting the Oracle (a saved LLM profile named \"oracle\").", + "properties": { + "action_type": { + "title": "Action Type", + "type": "string" + }, + "annotations": { + "anyOf": [ + { + "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" + }, + { + "type": "null" + } + ] + }, + "description": { + "title": "Description", + "type": "string" + }, + "kind": { + "const": "AskOracleTool", + "title": "Kind", + "type": "string" + }, + "meta": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Meta" + }, + "observation_type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Observation Type" + }, + "title": { + "readOnly": true, + "title": "Title", + "type": "string" + } + }, + "required": [ + "description", + "action_type", + "kind", + "title" + ], + "title": "AskOracleTool", + "type": "object" + }, + "BackendLogs": { + "description": "Bounded combined stdout and stderr output.", + "properties": { + "logs": { + "title": "Logs", + "type": "string" + }, + "name": { + "title": "Name", + "type": "string" + }, + "truncated": { + "title": "Truncated", + "type": "boolean" + } + }, + "required": [ + "name", + "logs", + "truncated" + ], + "title": "BackendLogs", + "type": "object" + }, + "BackendRevisionRequest": { + "description": "Explicit approval for one exact installed revision.", + "properties": { + "revision": { + "minLength": 1, + "title": "Revision", + "type": "string" + } + }, + "required": [ + "revision" + ], + "title": "BackendRevisionRequest", + "type": "object" + }, + "BackendStatus": { + "description": "Current state of an installed Canvas App backend.", + "properties": { + "detail": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Detail" + }, + "name": { + "title": "Name", + "type": "string" + }, + "pid": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Pid" + }, + "port": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Port" + }, + "prepared_revision": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Prepared Revision" + }, + "revision": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Revision" + }, + "state": { + "enum": [ + "missing", + "stopped", + "starting", + "ready", + "unhealthy", + "unsupported" + ], + "title": "State", + "type": "string" + } + }, + "required": [ + "name", + "state" + ], + "title": "BackendStatus", + "type": "object" + }, + "BaseWorkspace": { + "discriminator": { + "mapping": { + "openhands__sdk__workspace__local__LocalWorkspace-Output__1": "#/components/schemas/LocalWorkspace-Output", + "openhands__sdk__workspace__remote__base__RemoteWorkspace-Output__1": "#/components/schemas/RemoteWorkspace" + }, + "propertyName": "kind" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/LocalWorkspace-Output" + }, + { + "$ref": "#/components/schemas/RemoteWorkspace" + } + ] + }, + "BashCommand": { + "properties": { + "command": { + "description": "The bash command to execute", + "title": "Command", + "type": "string" + }, + "cwd": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The current working directory", + "title": "Cwd" + }, + "id": { + "title": "Id", + "type": "string" + }, + "kind": { + "const": "BashCommand", + "title": "Kind", + "type": "string" + }, + "timeout": { + "default": 300, + "description": "The max number of seconds a command may be permitted to run.", + "title": "Timeout", + "type": "integer" + }, + "timestamp": { + "format": "date-time", + "title": "Timestamp", + "type": "string" + } + }, + "required": [ + "command", + "kind" + ], + "title": "BashCommand", + "type": "object" + }, + "BashError": { + "properties": { + "code": { + "description": "Code for the error - typically an error type", + "title": "Code", + "type": "string" + }, + "detail": { + "description": "Details about the error", + "title": "Detail", + "type": "string" + }, + "id": { + "title": "Id", + "type": "string" + }, + "kind": { + "const": "BashError", + "title": "Kind", + "type": "string" + }, + "timestamp": { + "format": "date-time", + "title": "Timestamp", + "type": "string" + } + }, + "required": [ + "code", + "detail", + "kind" + ], + "title": "BashError", + "type": "object" + }, + "BashEventBase": { + "discriminator": { + "mapping": { + "openhands__agent_server__models__BashCommand-Output__1": "#/components/schemas/BashCommand", + "openhands__agent_server__models__BashError-Output__1": "#/components/schemas/BashError", + "openhands__agent_server__models__BashOutput-Output__1": "#/components/schemas/BashOutput" + }, + "propertyName": "kind" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/BashCommand" + }, + { + "$ref": "#/components/schemas/BashError" + }, + { + "$ref": "#/components/schemas/BashOutput" + } + ] + }, + "BashEventPage": { + "properties": { + "items": { + "items": { + "$ref": "#/components/schemas/BashEventBase" + }, + "title": "Items", + "type": "array" + }, + "next_page_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Next Page Id" + } + }, + "required": [ + "items" + ], + "title": "BashEventPage", + "type": "object" + }, + "BashEventSortOrder": { + "enum": [ + "TIMESTAMP", + "TIMESTAMP_DESC" + ], + "title": "BashEventSortOrder", + "type": "string" + }, + "BashOutput": { + "description": "Output of a bash command. A single command may have multiple pieces of output\ndepending on how large the output is.", + "properties": { + "command_id": { + "title": "Command Id", + "type": "string" + }, + "exit_code": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Exit code None implies the command is still running.", + "title": "Exit Code" + }, + "id": { + "title": "Id", + "type": "string" + }, + "kind": { + "const": "BashOutput", + "title": "Kind", + "type": "string" + }, + "order": { + "default": 0, + "description": "The order for this output, sequentially starting with 0", + "title": "Order", + "type": "integer" + }, + "stderr": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The error output from the command", + "title": "Stderr" + }, + "stdout": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The standard output from the command", + "title": "Stdout" + }, + "timestamp": { + "format": "date-time", + "title": "Timestamp", + "type": "string" + } + }, + "required": [ + "command_id", + "kind" + ], + "title": "BashOutput", + "type": "object" + }, + "Body_load_conversation_plugin_api_conversations__conversation_id__load_plugin_post": { + "properties": { + "plugin_ref": { + "title": "Plugin Ref", + "type": "string" + } + }, + "required": [ + "plugin_ref" + ], + "title": "Body_load_conversation_plugin_api_conversations__conversation_id__load_plugin_post", + "type": "object" + }, + "Body_switch_conversation_acp_model_api_conversations__conversation_id__switch_acp_model_post": { + "properties": { + "model": { + "title": "Model", + "type": "string" + } + }, + "required": [ + "model" + ], + "title": "Body_switch_conversation_acp_model_api_conversations__conversation_id__switch_acp_model_post", + "type": "object" + }, + "Body_switch_conversation_llm_api_conversations__conversation_id__switch_llm_post": { + "properties": { + "llm": { + "$ref": "#/components/schemas/LLM-Input" + } + }, + "required": [ + "llm" + ], + "title": "Body_switch_conversation_llm_api_conversations__conversation_id__switch_llm_post", + "type": "object" + }, + "Body_switch_conversation_profile_api_conversations__conversation_id__switch_profile_post": { + "properties": { + "profile_name": { + "title": "Profile Name", + "type": "string" + } + }, + "required": [ + "profile_name" + ], + "title": "Body_switch_conversation_profile_api_conversations__conversation_id__switch_profile_post", + "type": "object" + }, + "Body_upload_file_query_api_conversations__runtime_conversation_id__file_upload_post": { + "properties": { + "file": { + "contentMediaType": "application/octet-stream", + "title": "File", + "type": "string" + } + }, + "required": [ + "file" + ], + "title": "Body_upload_file_query_api_conversations__runtime_conversation_id__file_upload_post", + "type": "object" + }, + "Body_upload_file_query_api_file_upload_post": { + "properties": { + "file": { + "contentMediaType": "application/octet-stream", + "title": "File", + "type": "string" + } + }, + "required": [ + "file" + ], + "title": "Body_upload_file_query_api_file_upload_post", + "type": "object" + }, + "BrowserAction": { + "additionalProperties": false, + "description": "Base class for all browser actions.\n\nThis base class serves as the parent for all browser-related actions,\nenabling proper type hierarchy and eliminating the need for union types.", + "properties": { + "kind": { + "const": "BrowserAction", + "title": "Kind", + "type": "string" + } + }, + "required": [ + "kind" + ], + "title": "BrowserAction", + "type": "object" + }, + "BrowserClickAction": { + "additionalProperties": false, + "description": "Schema for clicking elements.", + "properties": { + "index": { + "description": "The index of the element to click (from browser_get_state)", + "minimum": 0.0, + "title": "Index", + "type": "integer" + }, + "kind": { + "const": "BrowserClickAction", + "title": "Kind", + "type": "string" + }, + "new_tab": { + "default": false, + "description": "Whether to open any resulting navigation in a new tab. Default: False", + "title": "New Tab", + "type": "boolean" + } + }, + "required": [ + "index", + "kind" + ], + "title": "BrowserClickAction", + "type": "object" + }, + "BrowserClickTool": { + "description": "Tool for clicking browser elements.", + "properties": { + "action_type": { + "title": "Action Type", + "type": "string" + }, + "annotations": { + "anyOf": [ + { + "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" + }, + { + "type": "null" + } + ] + }, + "description": { + "title": "Description", + "type": "string" + }, + "kind": { + "const": "BrowserClickTool", + "title": "Kind", + "type": "string" + }, + "meta": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Meta" + }, + "observation_type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Observation Type" + }, + "title": { + "readOnly": true, + "title": "Title", + "type": "string" + } + }, + "required": [ + "description", + "action_type", + "kind", + "title" + ], + "title": "BrowserClickTool", + "type": "object" + }, + "BrowserCloseTabAction": { + "additionalProperties": false, + "description": "Schema for closing browser tabs.", + "properties": { + "kind": { + "const": "BrowserCloseTabAction", + "title": "Kind", + "type": "string" + }, + "tab_id": { + "description": "4 Character Tab ID of the tab to close (from browser_list_tabs)", + "title": "Tab Id", + "type": "string" + } + }, + "required": [ + "tab_id", + "kind" + ], + "title": "BrowserCloseTabAction", + "type": "object" + }, + "BrowserCloseTabTool": { + "description": "Tool for closing browser tabs.", + "properties": { + "action_type": { + "title": "Action Type", + "type": "string" + }, + "annotations": { + "anyOf": [ + { + "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" + }, + { + "type": "null" + } + ] + }, + "description": { + "title": "Description", + "type": "string" + }, + "kind": { + "const": "BrowserCloseTabTool", + "title": "Kind", + "type": "string" + }, + "meta": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Meta" + }, + "observation_type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Observation Type" + }, + "title": { + "readOnly": true, + "title": "Title", + "type": "string" + } + }, + "required": [ + "description", + "action_type", + "kind", + "title" + ], + "title": "BrowserCloseTabTool", + "type": "object" + }, + "BrowserGetContentAction": { + "additionalProperties": false, + "description": "Schema for getting page content in markdown.", + "properties": { + "extract_links": { + "default": false, + "description": "Whether to include links in the content (default: False)", + "title": "Extract Links", + "type": "boolean" + }, + "kind": { + "const": "BrowserGetContentAction", + "title": "Kind", + "type": "string" + }, + "start_from_char": { + "default": 0, + "description": "Character index to start from in the page content (default: 0)", + "minimum": 0.0, + "title": "Start From Char", + "type": "integer" + } + }, + "required": [ + "kind" + ], + "title": "BrowserGetContentAction", + "type": "object" + }, + "BrowserGetContentTool": { + "description": "Tool for getting page content in markdown.", + "properties": { + "action_type": { + "title": "Action Type", + "type": "string" + }, + "annotations": { + "anyOf": [ + { + "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" + }, + { + "type": "null" + } + ] + }, + "description": { + "title": "Description", + "type": "string" + }, + "kind": { + "const": "BrowserGetContentTool", + "title": "Kind", + "type": "string" + }, + "meta": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Meta" + }, + "observation_type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Observation Type" + }, + "title": { + "readOnly": true, + "title": "Title", + "type": "string" + } + }, + "required": [ + "description", + "action_type", + "kind", + "title" + ], + "title": "BrowserGetContentTool", + "type": "object" + }, + "BrowserGetStateAction": { + "additionalProperties": false, + "description": "Schema for getting browser state.", + "properties": { + "include_screenshot": { + "default": false, + "description": "Whether to include a screenshot of the current page. Default: False", + "title": "Include Screenshot", + "type": "boolean" + }, + "kind": { + "const": "BrowserGetStateAction", + "title": "Kind", + "type": "string" + } + }, + "required": [ + "kind" + ], + "title": "BrowserGetStateAction", + "type": "object" + }, + "BrowserGetStateTool": { + "description": "Tool for getting browser state.", + "properties": { + "action_type": { + "title": "Action Type", + "type": "string" + }, + "annotations": { + "anyOf": [ + { + "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" + }, + { + "type": "null" + } + ] + }, + "description": { + "title": "Description", + "type": "string" + }, + "kind": { + "const": "BrowserGetStateTool", + "title": "Kind", + "type": "string" + }, + "meta": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Meta" + }, + "observation_type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Observation Type" + }, + "title": { + "readOnly": true, + "title": "Title", + "type": "string" + } + }, + "required": [ + "description", + "action_type", + "kind", + "title" + ], + "title": "BrowserGetStateTool", + "type": "object" + }, + "BrowserGetStorageAction": { + "additionalProperties": false, + "description": "Schema for getting browser storage (cookies, local storage, session storage).", + "properties": { + "kind": { + "const": "BrowserGetStorageAction", + "title": "Kind", + "type": "string" + } + }, + "required": [ + "kind" + ], + "title": "BrowserGetStorageAction", + "type": "object" + }, + "BrowserGetStorageTool": { + "description": "Tool for getting browser storage.", + "properties": { + "action_type": { + "title": "Action Type", + "type": "string" + }, + "annotations": { + "anyOf": [ + { + "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" + }, + { + "type": "null" + } + ] + }, + "description": { + "title": "Description", + "type": "string" + }, + "kind": { + "const": "BrowserGetStorageTool", + "title": "Kind", + "type": "string" + }, + "meta": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Meta" + }, + "observation_type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Observation Type" + }, + "title": { + "readOnly": true, + "title": "Title", + "type": "string" + } + }, + "required": [ + "description", + "action_type", + "kind", + "title" + ], + "title": "BrowserGetStorageTool", + "type": "object" + }, + "BrowserGoBackAction": { + "additionalProperties": false, + "description": "Schema for going back in browser history.", + "properties": { + "kind": { + "const": "BrowserGoBackAction", + "title": "Kind", + "type": "string" + } + }, + "required": [ + "kind" + ], + "title": "BrowserGoBackAction", + "type": "object" + }, + "BrowserGoBackTool": { + "description": "Tool for going back in browser history.", + "properties": { + "action_type": { + "title": "Action Type", + "type": "string" + }, + "annotations": { + "anyOf": [ + { + "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" + }, + { + "type": "null" + } + ] + }, + "description": { + "title": "Description", + "type": "string" + }, + "kind": { + "const": "BrowserGoBackTool", + "title": "Kind", + "type": "string" + }, + "meta": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Meta" + }, + "observation_type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Observation Type" + }, + "title": { + "readOnly": true, + "title": "Title", + "type": "string" + } + }, + "required": [ + "description", + "action_type", + "kind", + "title" + ], + "title": "BrowserGoBackTool", + "type": "object" + }, + "BrowserListTabsAction": { + "additionalProperties": false, + "description": "Schema for listing browser tabs.", + "properties": { + "kind": { + "const": "BrowserListTabsAction", + "title": "Kind", + "type": "string" + } + }, + "required": [ + "kind" + ], + "title": "BrowserListTabsAction", + "type": "object" + }, + "BrowserListTabsTool": { + "description": "Tool for listing browser tabs.", + "properties": { + "action_type": { + "title": "Action Type", + "type": "string" + }, + "annotations": { + "anyOf": [ + { + "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" + }, + { + "type": "null" + } + ] + }, + "description": { + "title": "Description", + "type": "string" + }, + "kind": { + "const": "BrowserListTabsTool", + "title": "Kind", + "type": "string" + }, + "meta": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Meta" + }, + "observation_type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Observation Type" + }, + "title": { + "readOnly": true, + "title": "Title", + "type": "string" + } + }, + "required": [ + "description", + "action_type", + "kind", + "title" + ], + "title": "BrowserListTabsTool", + "type": "object" + }, + "BrowserNavigateAction": { + "additionalProperties": false, + "description": "Schema for browser navigation.", + "properties": { + "kind": { + "const": "BrowserNavigateAction", + "title": "Kind", + "type": "string" + }, + "new_tab": { + "default": false, + "description": "Whether to open in a new tab. Default: False", + "title": "New Tab", + "type": "boolean" + }, + "url": { + "description": "The URL to navigate to", + "title": "Url", + "type": "string" + } + }, + "required": [ + "url", + "kind" + ], + "title": "BrowserNavigateAction", + "type": "object" + }, + "BrowserNavigateTool": { + "description": "Tool for browser navigation.", + "properties": { + "action_type": { + "title": "Action Type", + "type": "string" + }, + "annotations": { + "anyOf": [ + { + "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" + }, + { + "type": "null" + } + ] + }, + "description": { + "title": "Description", + "type": "string" + }, + "kind": { + "const": "BrowserNavigateTool", + "title": "Kind", + "type": "string" + }, + "meta": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Meta" + }, + "observation_type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Observation Type" + }, + "title": { + "readOnly": true, + "title": "Title", + "type": "string" + } + }, + "required": [ + "description", + "action_type", + "kind", + "title" + ], + "title": "BrowserNavigateTool", + "type": "object" + }, + "BrowserObservation": { + "additionalProperties": false, + "description": "Base observation for browser operations.", + "properties": { + "content": { + "description": "Content returned from the tool as a list of TextContent/ImageContent objects. When there is an error, it should be written in this field.", + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/TextContent" + }, + { + "$ref": "#/components/schemas/ImageContent" + } + ] + }, + "title": "Content", + "type": "array" + }, + "full_output_save_dir": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Directory where full output files are saved", + "title": "Full Output Save Dir" + }, + "is_error": { + "default": false, + "description": "Whether the observation indicates an error", + "title": "Is Error", + "type": "boolean" + }, + "kind": { + "const": "BrowserObservation", + "title": "Kind", + "type": "string" + }, + "screenshot_data": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Base64 screenshot data if available", + "title": "Screenshot Data" + } + }, + "required": [ + "kind" + ], + "title": "BrowserObservation", + "type": "object" + }, + "BrowserScrollAction": { + "additionalProperties": false, + "description": "Schema for scrolling the page.", + "properties": { + "direction": { + "default": "down", + "description": "Direction to scroll. Options: 'up', 'down'. Default: 'down'", + "enum": [ + "up", + "down" + ], + "title": "Direction", + "type": "string" + }, + "kind": { + "const": "BrowserScrollAction", + "title": "Kind", + "type": "string" + } + }, + "required": [ + "kind" + ], + "title": "BrowserScrollAction", + "type": "object" + }, + "BrowserScrollTool": { + "description": "Tool for scrolling the browser page.", + "properties": { + "action_type": { + "title": "Action Type", + "type": "string" + }, + "annotations": { + "anyOf": [ + { + "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" + }, + { + "type": "null" + } + ] + }, + "description": { + "title": "Description", + "type": "string" + }, + "kind": { + "const": "BrowserScrollTool", + "title": "Kind", + "type": "string" + }, + "meta": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Meta" + }, + "observation_type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Observation Type" + }, + "title": { + "readOnly": true, + "title": "Title", + "type": "string" + } + }, + "required": [ + "description", + "action_type", + "kind", + "title" + ], + "title": "BrowserScrollTool", + "type": "object" + }, + "BrowserSetStorageAction": { + "additionalProperties": false, + "description": "Schema for setting browser storage (cookies, local storage, session storage).", + "properties": { + "kind": { + "const": "BrowserSetStorageAction", + "title": "Kind", + "type": "string" + }, + "storage_state": { + "additionalProperties": true, + "description": "Storage state dictionary containing 'cookies' and 'origins' (from browser_get_storage)", + "title": "Storage State", + "type": "object" + } + }, + "required": [ + "storage_state", + "kind" + ], + "title": "BrowserSetStorageAction", + "type": "object" + }, + "BrowserSetStorageTool": { + "description": "Tool for setting browser storage.", + "properties": { + "action_type": { + "title": "Action Type", + "type": "string" + }, + "annotations": { + "anyOf": [ + { + "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" + }, + { + "type": "null" + } + ] + }, + "description": { + "title": "Description", + "type": "string" + }, + "kind": { + "const": "BrowserSetStorageTool", + "title": "Kind", + "type": "string" + }, + "meta": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Meta" + }, + "observation_type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Observation Type" + }, + "title": { + "readOnly": true, + "title": "Title", + "type": "string" + } + }, + "required": [ + "description", + "action_type", + "kind", + "title" + ], + "title": "BrowserSetStorageTool", + "type": "object" + }, + "BrowserStartRecordingAction": { + "additionalProperties": false, + "description": "Schema for starting browser session recording.", + "properties": { + "kind": { + "const": "BrowserStartRecordingAction", + "title": "Kind", + "type": "string" + } + }, + "required": [ + "kind" + ], + "title": "BrowserStartRecordingAction", + "type": "object" + }, + "BrowserStartRecordingTool": { + "description": "Tool for starting browser session recording.", + "properties": { + "action_type": { + "title": "Action Type", + "type": "string" + }, + "annotations": { + "anyOf": [ + { + "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" + }, + { + "type": "null" + } + ] + }, + "description": { + "title": "Description", + "type": "string" + }, + "kind": { + "const": "BrowserStartRecordingTool", + "title": "Kind", + "type": "string" + }, + "meta": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Meta" + }, + "observation_type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Observation Type" + }, + "title": { + "readOnly": true, + "title": "Title", + "type": "string" + } + }, + "required": [ + "description", + "action_type", + "kind", + "title" + ], + "title": "BrowserStartRecordingTool", + "type": "object" + }, + "BrowserStopRecordingAction": { + "additionalProperties": false, + "description": "Schema for stopping browser session recording.", + "properties": { + "kind": { + "const": "BrowserStopRecordingAction", + "title": "Kind", + "type": "string" + } + }, + "required": [ + "kind" + ], + "title": "BrowserStopRecordingAction", + "type": "object" + }, + "BrowserStopRecordingTool": { + "description": "Tool for stopping browser session recording.", + "properties": { + "action_type": { + "title": "Action Type", + "type": "string" + }, + "annotations": { + "anyOf": [ + { + "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" + }, + { + "type": "null" + } + ] + }, + "description": { + "title": "Description", + "type": "string" + }, + "kind": { + "const": "BrowserStopRecordingTool", + "title": "Kind", + "type": "string" + }, + "meta": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Meta" + }, + "observation_type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Observation Type" + }, + "title": { + "readOnly": true, + "title": "Title", + "type": "string" + } + }, + "required": [ + "description", + "action_type", + "kind", + "title" + ], + "title": "BrowserStopRecordingTool", + "type": "object" + }, + "BrowserSwitchTabAction": { + "additionalProperties": false, + "description": "Schema for switching browser tabs.", + "properties": { + "kind": { + "const": "BrowserSwitchTabAction", + "title": "Kind", + "type": "string" + }, + "tab_id": { + "description": "4 Character Tab ID of the tab to switch to (from browser_list_tabs)", + "title": "Tab Id", + "type": "string" + } + }, + "required": [ + "tab_id", + "kind" + ], + "title": "BrowserSwitchTabAction", + "type": "object" + }, + "BrowserSwitchTabTool": { + "description": "Tool for switching browser tabs.", + "properties": { + "action_type": { + "title": "Action Type", + "type": "string" + }, + "annotations": { + "anyOf": [ + { + "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" + }, + { + "type": "null" + } + ] + }, + "description": { + "title": "Description", + "type": "string" + }, + "kind": { + "const": "BrowserSwitchTabTool", + "title": "Kind", + "type": "string" + }, + "meta": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Meta" + }, + "observation_type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Observation Type" + }, + "title": { + "readOnly": true, + "title": "Title", + "type": "string" + } + }, + "required": [ + "description", + "action_type", + "kind", + "title" + ], + "title": "BrowserSwitchTabTool", + "type": "object" + }, + "BrowserToolSet": { + "description": "A set of all browser tools.\n\nThis tool set includes all available browser-related tools\n for interacting with web pages.\n\nThe toolset automatically checks for Chromium availability\nwhen created and automatically installs it if missing.", + "properties": { + "action_type": { + "title": "Action Type", + "type": "string" + }, + "annotations": { + "anyOf": [ + { + "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" + }, + { + "type": "null" + } + ] + }, + "description": { + "title": "Description", + "type": "string" + }, + "kind": { + "const": "BrowserToolSet", + "title": "Kind", + "type": "string" + }, + "meta": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Meta" + }, + "observation_type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Observation Type" + }, + "title": { + "readOnly": true, + "title": "Title", + "type": "string" + } + }, + "required": [ + "description", + "action_type", + "kind", + "title" + ], + "title": "BrowserToolSet", + "type": "object" + }, + "BrowserTypeAction": { + "additionalProperties": false, + "description": "Schema for typing text into elements.", + "properties": { + "index": { + "description": "The index of the input element (from browser_get_state)", + "minimum": 0.0, + "title": "Index", + "type": "integer" + }, + "kind": { + "const": "BrowserTypeAction", + "title": "Kind", + "type": "string" + }, + "text": { + "description": "The text to type", + "title": "Text", + "type": "string" + } + }, + "required": [ + "index", + "text", + "kind" + ], + "title": "BrowserTypeAction", + "type": "object" + }, + "BrowserTypeTool": { + "description": "Tool for typing text into browser elements.", + "properties": { + "action_type": { + "title": "Action Type", + "type": "string" + }, + "annotations": { + "anyOf": [ + { + "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" + }, + { + "type": "null" + } + ] + }, + "description": { + "title": "Description", + "type": "string" + }, + "kind": { + "const": "BrowserTypeTool", + "title": "Kind", + "type": "string" + }, + "meta": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Meta" + }, + "observation_type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Observation Type" + }, + "title": { + "readOnly": true, + "title": "Title", + "type": "string" + } + }, + "required": [ + "description", + "action_type", + "kind", + "title" + ], + "title": "BrowserTypeTool", + "type": "object" + }, + "CanvasExtensionBackend": { + "description": "Optional trusted backend declaration for schema-1 Canvas Apps.", + "properties": { + "argv": { + "items": { + "type": "string" + }, + "minItems": 1, + "title": "Argv", + "type": "array" + }, + "artifacts": { + "additionalProperties": { + "$ref": "#/components/schemas/CanvasExtensionBackendArtifact" + }, + "minProperties": 1, + "propertyNames": { + "enum": [ + "linux-amd64", + "linux-arm64" + ] + }, + "title": "Artifacts", + "type": "object" + }, + "health": { + "$ref": "#/components/schemas/CanvasExtensionBackendHealth" + }, + "inherit_environment": { + "items": { + "type": "string" + }, + "title": "Inherit Environment", + "type": "array" + }, + "schema_version": { + "const": 1, + "title": "Schema Version", + "type": "integer" + } + }, + "required": [ + "schema_version", + "artifacts", + "argv" + ], + "title": "CanvasExtensionBackend", + "type": "object" + }, + "CanvasExtensionBackendArtifact": { + "description": "Immutable backend artifact for one supported platform.", + "properties": { + "path": { + "description": "Package-relative .tar.gz artifact path", + "title": "Path", + "type": "string" + }, + "sha256": { + "description": "Lowercase SHA-256 checksum", + "pattern": "^[0-9a-f]{64}$", + "title": "Sha256", + "type": "string" + } + }, + "required": [ + "path", + "sha256" + ], + "title": "CanvasExtensionBackendArtifact", + "type": "object" + }, + "CanvasExtensionBackendHealth": { + "description": "Loopback HTTP readiness probe for a backend process.", + "properties": { + "interval_seconds": { + "default": 0.1, + "exclusiveMinimum": 0.0, + "maximum": 10.0, + "title": "Interval Seconds", + "type": "number" + }, + "path": { + "default": "/health", + "pattern": "^/[A-Za-z0-9._~!$&'()*+,;=:@%/-]*$", + "title": "Path", + "type": "string" + }, + "timeout_seconds": { + "default": 30, + "exclusiveMinimum": 0.0, + "maximum": 300.0, + "title": "Timeout Seconds", + "type": "number" + } + }, + "title": "CanvasExtensionBackendHealth", + "type": "object" + }, + "CanvasExtensionContributes": { + "description": "Contributions an extension makes to the Canvas UI.", + "properties": { + "pages": { + "description": "Pages contributed to Canvas navigation", + "items": { + "$ref": "#/components/schemas/CanvasExtensionPage" + }, + "title": "Pages", + "type": "array" + } + }, + "title": "CanvasExtensionContributes", + "type": "object" + }, + "CanvasExtensionManifest": { + "description": "Canvas extension manifest (``canvas-extension.json``).", + "properties": { + "backend": { + "anyOf": [ + { + "$ref": "#/components/schemas/CanvasExtensionBackend" + }, + { + "type": "null" + } + ], + "description": "Optional explicitly prepared and started backend service" + }, + "contributes": { + "$ref": "#/components/schemas/CanvasExtensionContributes", + "description": "Contributions this extension makes to the Canvas UI" + }, + "description": { + "default": "", + "description": "Extension description", + "title": "Description", + "type": "string" + }, + "display_name": { + "description": "Human-readable extension name", + "title": "Display Name", + "type": "string" + }, + "entrypoint": { + "description": "Path, relative to the extension package root, to the bundle entry file", + "title": "Entrypoint", + "type": "string" + }, + "icon": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Path, relative to the extension package root, to an SVG icon", + "title": "Icon" + }, + "name": { + "description": "Extension name (kebab-case)", + "title": "Name", + "type": "string" + }, + "schema_version": { + "description": "Manifest schema version", + "title": "Schema Version", + "type": "integer" + }, + "version": { + "description": "Extension version", + "title": "Version", + "type": "string" + } + }, + "required": [ + "schema_version", + "name", + "display_name", + "version", + "entrypoint" + ], + "title": "CanvasExtensionManifest", + "type": "object" + }, + "CanvasExtensionPage": { + "description": "A single page contributed to the Canvas UI by an extension.", + "properties": { + "id": { + "description": "Unique contribution id within the extension", + "title": "Id", + "type": "string" + }, + "path": { + "description": "Route the page is mounted at, e.g. '/dashboard'", + "title": "Path", + "type": "string" + }, + "title": { + "description": "Page title shown in Canvas navigation", + "title": "Title", + "type": "string" + } + }, + "required": [ + "id", + "title", + "path" + ], + "title": "CanvasExtensionPage", + "type": "object" + }, + "ClassifyAndSwitchLLMAction": { + "additionalProperties": false, + "description": "Trigger classification of the current task and switch the LLM profile.", + "properties": { + "kind": { + "const": "ClassifyAndSwitchLLMAction", + "title": "Kind", + "type": "string" + } + }, + "required": [ + "kind" + ], + "title": "ClassifyAndSwitchLLMAction", + "type": "object" + }, + "ClassifyAndSwitchLLMObservation": { + "additionalProperties": false, + "description": "Result of classifying the task and switching the LLM profile.", + "properties": { + "active_model": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Model configured by the activated profile, when available.", + "title": "Active Model" + }, + "chosen_class": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Description of the matched class, or None when no class matched and the tool returned an error.", + "title": "Chosen Class" + }, + "content": { + "description": "Content returned from the tool as a list of TextContent/ImageContent objects. When there is an error, it should be written in this field.", + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/TextContent" + }, + { + "$ref": "#/components/schemas/ImageContent" + } + ] + }, + "title": "Content", + "type": "array" + }, + "is_error": { + "default": false, + "description": "Whether the observation indicates an error", + "title": "Is Error", + "type": "boolean" + }, + "kind": { + "const": "ClassifyAndSwitchLLMObservation", + "title": "Kind", + "type": "string" + }, + "model": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Name of the LLM profile that was activated.", + "title": "Model" + } + }, + "required": [ + "kind" + ], + "title": "ClassifyAndSwitchLLMObservation", + "type": "object" + }, + "ClassifyAndSwitchLLMTool": { + "description": "Tool that classifies the task and switches to a meta-profile's LLM.", + "properties": { + "action_type": { + "title": "Action Type", + "type": "string" + }, + "annotations": { + "anyOf": [ + { + "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" + }, + { + "type": "null" + } + ] + }, + "description": { + "title": "Description", + "type": "string" + }, + "kind": { + "const": "ClassifyAndSwitchLLMTool", + "title": "Kind", + "type": "string" + }, + "meta": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Meta" + }, + "observation_type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Observation Type" + }, + "title": { + "readOnly": true, + "title": "Title", + "type": "string" + } + }, + "required": [ + "description", + "action_type", + "kind", + "title" + ], + "title": "ClassifyAndSwitchLLMTool", + "type": "object" + }, + "ClientTool": { + "description": "A tool whose execution is deferred to the external client.\n\nCreated from a :class:`ClientToolSpec` at conversation start. The agent\nsees it as a normal tool and can call it; the ActionEvent is emitted\nover WebSocket for the client to handle.", + "properties": { + "action_type": { + "title": "Action Type", + "type": "string" + }, + "annotations": { + "anyOf": [ + { + "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" + }, + { + "type": "null" + } + ] + }, + "client_tool_name": { + "description": "Per-instance tool name from the ClientToolSpec.", + "title": "Client Tool Name", + "type": "string" + }, + "description": { + "title": "Description", + "type": "string" + }, + "input_schema": { + "additionalProperties": true, + "description": "The original JSON Schema for the tool's parameters, as provided by the client. Used verbatim when exporting the tool to the LLM so client-defined constraints (enum, nested objects, bounds, additionalProperties, ...) are preserved.", + "title": "Input Schema", + "type": "object" + }, + "kind": { + "const": "ClientTool", + "title": "Kind", + "type": "string" + }, + "meta": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Meta" + }, + "observation_type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Observation Type" + }, + "title": { + "readOnly": true, + "title": "Title", + "type": "string" + } + }, + "required": [ + "description", + "action_type", + "client_tool_name", + "input_schema", + "kind", + "title" + ], + "title": "ClientTool", + "type": "object" + }, + "ClientToolObservation": { + "additionalProperties": false, + "description": "Observation returned when a client tool is called.\n\nThe actual execution happens on the client side; the SDK returns\nthis acknowledgment so the agent loop can continue.", + "properties": { + "content": { + "description": "Content returned from the tool as a list of TextContent/ImageContent objects. When there is an error, it should be written in this field.", + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/TextContent" + }, + { + "$ref": "#/components/schemas/ImageContent" + } + ] + }, + "title": "Content", + "type": "array" + }, + "is_error": { + "default": false, + "description": "Whether the observation indicates an error", + "title": "Is Error", + "type": "boolean" + }, + "kind": { + "const": "ClientToolObservation", + "title": "Kind", + "type": "string" + } + }, + "required": [ + "kind" + ], + "title": "ClientToolObservation", + "type": "object" + }, + "ClientToolSpec-Input": { + "description": "A tool defined by the client, executed externally (not by the SDK).\n\nClients pass these specs in ``POST /conversations`` to register tools\nwhose execution is handled outside the SDK (e.g., by a frontend\nlistening for ActionEvents over WebSocket).", + "properties": { + "annotations": { + "anyOf": [ + { + "$ref": "#/components/schemas/ToolAnnotations-Input" + }, + { + "type": "null" + } + ], + "description": "Optional MCP-style annotations for the tool. When omitted, the tool is treated conservatively (not read-only), so the agent is asked to predict a security risk before calling it." + }, + "description": { + "description": "Description shown to the LLM explaining when and how to use this tool.", + "title": "Description", + "type": "string" + }, + "name": { + "description": "Unique tool name the agent will use to call this tool.", + "title": "Name", + "type": "string" + }, + "parameters": { + "additionalProperties": true, + "description": "JSON Schema describing the tool's input parameters. Must be an object schema.", + "title": "Parameters", + "type": "object" + } + }, + "required": [ + "name", + "description" + ], + "title": "ClientToolSpec", + "type": "object" + }, + "ClientToolSpec-Output": { + "description": "A tool defined by the client, executed externally (not by the SDK).\n\nClients pass these specs in ``POST /conversations`` to register tools\nwhose execution is handled outside the SDK (e.g., by a frontend\nlistening for ActionEvents over WebSocket).", + "properties": { + "annotations": { + "anyOf": [ + { + "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" + }, + { + "type": "null" + } + ], + "description": "Optional MCP-style annotations for the tool. When omitted, the tool is treated conservatively (not read-only), so the agent is asked to predict a security risk before calling it." + }, + "description": { + "description": "Description shown to the LLM explaining when and how to use this tool.", + "title": "Description", + "type": "string" + }, + "name": { + "description": "Unique tool name the agent will use to call this tool.", + "title": "Name", + "type": "string" + }, + "parameters": { + "additionalProperties": true, + "description": "JSON Schema describing the tool's input parameters. Must be an object schema.", + "title": "Parameters", + "type": "object" + } + }, + "required": [ + "name", + "description" + ], + "title": "ClientToolSpec", + "type": "object" + }, + "CmdOutputMetadata": { + "description": "Additional metadata captured from PS1", + "properties": { + "exit_code": { + "default": -1, + "description": "The exit code of the last executed command.", + "title": "Exit Code", + "type": "integer" + }, + "hostname": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The hostname of the machine.", + "title": "Hostname" + }, + "pid": { + "default": -1, + "description": "The process ID of the last executed command.", + "title": "Pid", + "type": "integer" + }, + "prefix": { + "default": "", + "description": "Prefix to add to command output", + "title": "Prefix", + "type": "string" + }, + "py_interpreter_path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The path to the current Python interpreter, if any.", + "title": "Py Interpreter Path" + }, + "suffix": { + "default": "", + "description": "Suffix to add to command output", + "title": "Suffix", + "type": "string" + }, + "username": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The username of the current user.", + "title": "Username" + }, + "working_dir": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The current working directory.", + "title": "Working Dir" + } + }, + "title": "CmdOutputMetadata", + "type": "object" + }, + "Condensation": { + "additionalProperties": false, + "description": "This action indicates a condensation of the conversation history is happening.", + "properties": { + "forgotten_event_ids": { + "description": "The IDs of the events that are being forgotten (removed from the `View` given to the LLM).", + "items": { + "type": "string" + }, + "title": "Forgotten Event Ids", + "type": "array", + "uniqueItems": true + }, + "id": { + "description": "Unique event id (ULID/UUID)", + "title": "Id", + "type": "string" + }, + "kind": { + "const": "Condensation", + "title": "Kind", + "type": "string" + }, + "llm_response_id": { + "description": "Completion or Response ID of the LLM response that generated this event", + "title": "Llm Response Id", + "type": "string" + }, + "parent_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Parent event id in the conversation tree. None for the root, or for legacy events predating the tree (see EventLog's effective-parent rule). Events sharing a parent_id are sibling branches.", + "title": "Parent Id" + }, + "source": { + "default": "environment", + "enum": [ + "agent", + "user", + "environment", + "hook" + ], + "title": "Source", + "type": "string" + }, + "summary": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "An optional summary of the events being forgotten.", + "title": "Summary" + }, + "summary_offset": { + "anyOf": [ + { + "minimum": 0.0, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "An optional offset to the start of the resulting view (after forgotten events have been removed) indicating where the summary should be inserted. If not provided, the summary will not be inserted into the view.", + "title": "Summary Offset" + }, + "timestamp": { + "description": "Event timestamp", + "title": "Timestamp", + "type": "string" + } + }, + "required": [ + "llm_response_id", + "kind" + ], + "title": "Condensation", + "type": "object" + }, + "CondensationRequest": { + "additionalProperties": false, + "description": "This action is used to request a condensation of the conversation history.\n\nAttributes:\n action (str): The action type, namely ActionType.CONDENSATION_REQUEST.", + "properties": { + "id": { + "description": "Unique event id (ULID/UUID)", + "title": "Id", + "type": "string" + }, + "kind": { + "const": "CondensationRequest", + "title": "Kind", + "type": "string" + }, + "parent_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Parent event id in the conversation tree. None for the root, or for legacy events predating the tree (see EventLog's effective-parent rule). Events sharing a parent_id are sibling branches.", + "title": "Parent Id" + }, + "source": { + "default": "environment", + "enum": [ + "agent", + "user", + "environment", + "hook" + ], + "title": "Source", + "type": "string" + }, + "timestamp": { + "description": "Event timestamp", + "title": "Timestamp", + "type": "string" + } + }, + "required": [ + "kind" + ], + "title": "CondensationRequest", + "type": "object" + }, + "CondensationSummaryEvent": { + "additionalProperties": false, + "description": "This event represents a summary generated by a condenser.", + "properties": { + "id": { + "description": "Unique event id (ULID/UUID)", + "title": "Id", + "type": "string" + }, + "kind": { + "const": "CondensationSummaryEvent", + "title": "Kind", + "type": "string" + }, + "parent_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Parent event id in the conversation tree. None for the root, or for legacy events predating the tree (see EventLog's effective-parent rule). Events sharing a parent_id are sibling branches.", + "title": "Parent Id" + }, + "source": { + "default": "environment", + "enum": [ + "agent", + "user", + "environment", + "hook" + ], + "title": "Source", + "type": "string" + }, + "summary": { + "title": "Summary", + "type": "string" + }, + "timestamp": { + "description": "Event timestamp", + "title": "Timestamp", + "type": "string" + } + }, + "required": [ + "summary", + "kind" + ], + "title": "CondensationSummaryEvent", + "type": "object" + }, + "CondenserBase-Input": { + "discriminator": { + "mapping": { + "openhands__sdk__context__condenser__llm_summarizing_condenser__LLMSummarizingCondenser-Input__1": "#/components/schemas/LLMSummarizingCondenser-Input", + "openhands__sdk__context__condenser__no_op_condenser__NoOpCondenser-Input__1": "#/components/schemas/NoOpCondenser-Input", + "openhands__sdk__context__condenser__pipeline_condenser__PipelineCondenser-Input__1": "#/components/schemas/PipelineCondenser-Input" + }, + "propertyName": "kind" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/LLMSummarizingCondenser-Input" + }, + { + "$ref": "#/components/schemas/NoOpCondenser-Input" + }, + { + "$ref": "#/components/schemas/PipelineCondenser-Input" + } + ] + }, + "CondenserBase-Output": { + "discriminator": { + "mapping": { + "openhands__sdk__context__condenser__llm_summarizing_condenser__LLMSummarizingCondenser-Output__1": "#/components/schemas/LLMSummarizingCondenser-Output", + "openhands__sdk__context__condenser__no_op_condenser__NoOpCondenser-Output__1": "#/components/schemas/NoOpCondenser-Output", + "openhands__sdk__context__condenser__pipeline_condenser__PipelineCondenser-Output__1": "#/components/schemas/PipelineCondenser-Output" + }, + "propertyName": "kind" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/LLMSummarizingCondenser-Output" + }, + { + "$ref": "#/components/schemas/NoOpCondenser-Output" + }, + { + "$ref": "#/components/schemas/PipelineCondenser-Output" + } + ] + }, + "ConfirmRisky-Input": { + "properties": { + "confirm_unknown": { + "default": true, + "title": "Confirm Unknown", + "type": "boolean" + }, + "kind": { + "const": "ConfirmRisky", + "title": "Kind", + "type": "string" + }, + "threshold": { + "$ref": "#/components/schemas/SecurityRisk", + "default": "HIGH" + } + }, + "title": "ConfirmRisky", + "type": "object" + }, + "ConfirmRisky-Output": { + "properties": { + "confirm_unknown": { + "default": true, + "title": "Confirm Unknown", + "type": "boolean" + }, + "kind": { + "const": "ConfirmRisky", + "title": "Kind", + "type": "string" + }, + "threshold": { + "$ref": "#/components/schemas/SecurityRisk", + "default": "HIGH" + } + }, + "required": [ + "kind" + ], + "title": "ConfirmRisky", + "type": "object" + }, + "ConfirmationPolicyBase-Input": { + "discriminator": { + "mapping": { + "openhands__sdk__security__confirmation_policy__AlwaysConfirm-Input__1": "#/components/schemas/AlwaysConfirm-Input", + "openhands__sdk__security__confirmation_policy__ConfirmRisky-Input__1": "#/components/schemas/ConfirmRisky-Input", + "openhands__sdk__security__confirmation_policy__NeverConfirm-Input__1": "#/components/schemas/NeverConfirm-Input" + }, + "propertyName": "kind" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/AlwaysConfirm-Input" + }, + { + "$ref": "#/components/schemas/ConfirmRisky-Input" + }, + { + "$ref": "#/components/schemas/NeverConfirm-Input" + } + ] + }, + "ConfirmationPolicyBase-Output": { + "discriminator": { + "mapping": { + "openhands__sdk__security__confirmation_policy__AlwaysConfirm-Output__1": "#/components/schemas/AlwaysConfirm-Output", + "openhands__sdk__security__confirmation_policy__ConfirmRisky-Output__1": "#/components/schemas/ConfirmRisky-Output", + "openhands__sdk__security__confirmation_policy__NeverConfirm-Output__1": "#/components/schemas/NeverConfirm-Output" + }, + "propertyName": "kind" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/AlwaysConfirm-Output" + }, + { + "$ref": "#/components/schemas/ConfirmRisky-Output" + }, + { + "$ref": "#/components/schemas/NeverConfirm-Output" + } + ] + }, + "ConfirmationResponseRequest": { + "description": "Payload to accept or reject a pending action.", + "properties": { + "accept": { + "title": "Accept", + "type": "boolean" + }, + "reason": { + "default": "User rejected the action.", + "title": "Reason", + "type": "string" + } + }, + "required": [ + "accept" + ], + "title": "ConfirmationResponseRequest", + "type": "object" + }, + "ConversationErrorEvent": { + "additionalProperties": false, + "description": "Conversation-level failure that is NOT sent back to the LLM.\n\nThis event is emitted by the conversation runtime when an unexpected\nexception bubbles up and prevents the run loop from continuing. It is\nintended for client applications (e.g., UIs) to present a top-level error\nstate, and for orchestration to react. It is not an observation and it is\nnot LLM-convertible.\n\nDifferences from AgentErrorEvent:\n- Not tied to any tool_name/tool_call_id (AgentErrorEvent is a tool\n observation).\n- Typically source='environment' and the run loop moves to an ERROR state,\n while AgentErrorEvent has source='agent' and the conversation can\n continue.", + "properties": { + "classification": { + "anyOf": [ + { + "$ref": "#/components/schemas/ErrorClassification" + }, + { + "type": "null" + } + ], + "description": "Safe structured error semantics for API consumers." + }, + "code": { + "description": "Code for the error - typically a type", + "title": "Code", + "type": "string" + }, + "detail": { + "description": "Details about the error", + "title": "Detail", + "type": "string" + }, + "id": { + "description": "Unique event id (ULID/UUID)", + "title": "Id", + "type": "string" + }, + "kind": { + "const": "ConversationErrorEvent", + "title": "Kind", + "type": "string" + }, + "parent_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Parent event id in the conversation tree. None for the root, or for legacy events predating the tree (see EventLog's effective-parent rule). Events sharing a parent_id are sibling branches.", + "title": "Parent Id" + }, + "source": { + "description": "The source of this event", + "enum": [ + "agent", + "user", + "environment", + "hook" + ], + "title": "Source", + "type": "string" + }, + "timestamp": { + "description": "Event timestamp", + "title": "Timestamp", + "type": "string" + } + }, + "required": [ + "source", + "code", + "detail", + "kind" + ], + "title": "ConversationErrorEvent", + "type": "object" + }, + "ConversationExecutionStatus": { + "description": "Enum representing the current execution state of the conversation.", + "enum": [ + "idle", + "running", + "paused", + "waiting_for_confirmation", + "finished", + "error", + "stuck", + "deleting" + ], + "title": "ConversationExecutionStatus", + "type": "string" + }, + "ConversationInfo": { + "description": "Information about a conversation running locally without a Runtime sandbox.", + "properties": { + "activated_knowledge_skills": { + "description": "List of activated knowledge skills name", + "items": { + "type": "string" + }, + "title": "Activated Knowledge Skills", + "type": "array" + }, + "agent": { + "$ref": "#/components/schemas/AgentBase-Output", + "description": "The agent running in the conversation." + }, + "agent_state": { + "additionalProperties": true, + "description": "Dictionary for agent-specific runtime state that persists across iterations.", + "title": "Agent State", + "type": "object" + }, + "available_models": { + "description": "Models the ACP server offers for this session, lifted off ``ACPAgent.available_models`` (the ``models.availableModels`` field on the ACP session response). Each entry carries a ``model_id`` plus an optional ``name``/``description``. Surfaced verbatim so clients can render a model picker and resolve ``current_model_id`` to a display label themselves — the server does no name curation. Empty for ACP servers that don't surface the (UNSTABLE) capability and for native OpenHands agents. Client contract: ``current_model_id`` is NOT guaranteed to be a member — a forced ``acp_model`` override may name a model absent from the list — so treat a miss as 'show the raw id'. Some entries are opaque aliases whose human identity lives in ``description`` (e.g. claude-agent-acp's ``\"default\"`` -> ``\"Opus 4.7 with 1M context · ...\"``).", + "items": { + "$ref": "#/components/schemas/ACPModelInfo" + }, + "title": "Available Models", + "type": "array" + }, + "blocked_actions": { + "additionalProperties": { + "type": "string" + }, + "description": "Actions blocked by PreToolUse hooks, keyed by action ID", + "title": "Blocked Actions", + "type": "object" + }, + "blocked_messages": { + "additionalProperties": { + "type": "string" + }, + "description": "Messages blocked by UserPromptSubmit hooks, keyed by message ID", + "title": "Blocked Messages", + "type": "object" + }, + "client_tools": { + "description": "Client-defined tool specs registered for this conversation. Surfaced so that a client re-attaching by conversation id can register the dynamic ClientAction_* action types before syncing persisted events, avoiding 'Unknown kind' deserialization errors.", + "items": { + "$ref": "#/components/schemas/ClientToolSpec-Output" + }, + "title": "Client Tools", + "type": "array" + }, + "confirmation_policy": { + "$ref": "#/components/schemas/ConfirmationPolicyBase-Output", + "default": { + "kind": "NeverConfirm" + } + }, + "created_at": { + "format": "date-time", + "title": "Created At", + "type": "string" + }, + "current_model_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Model the agent is actually using for this session. For ACP agents, this is lifted off ``ACPAgent.current_model_id`` (populated from the ``models.currentModelId`` field on the ACP session response, or from ``acp_model`` when the caller forced an override). May be an opaque alias (e.g. claude-agent-acp's ``\"default\"``); match it against ``available_models`` to get a display label. ``None`` for older ACP servers that don't surface the field, or while the agent is still initializing. Native OpenHands agents leave this ``None`` — consumers should read ``agent.llm.model`` for those.", + "title": "Current Model Id" + }, + "execution_status": { + "$ref": "#/components/schemas/ConversationExecutionStatus", + "default": "idle" + }, + "forked_from_conversation_id": { + "anyOf": [ + { + "format": "uuid", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ID of the conversation this one was forked from. ``None`` for conversations created directly (not via fork).", + "title": "Forked From Conversation Id" + }, + "forked_from_event_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Event ID this conversation was forked at. ``None`` for non-forked conversations or whole-conversation forks.", + "title": "Forked From Event Id" + }, + "hook_config": { + "anyOf": [ + { + "$ref": "#/components/schemas/HookConfig" + }, + { + "type": "null" + } + ], + "description": "Hook configuration for this conversation. Includes definitions for PreToolUse, PostToolUse, UserPromptSubmit, SessionStart, SessionEnd, and Stop hooks." + }, + "id": { + "description": "Unique conversation ID", + "format": "uuid", + "title": "Id", + "type": "string" + }, + "invoked_skills": { + "description": "Names of progressive-disclosure skills explicitly invoked via the `invoke_skill` tool.", + "items": { + "type": "string" + }, + "title": "Invoked Skills", + "type": "array" + }, + "last_user_message_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Most recent user MessageEvent id for hook block checks. Updated when user messages are emitted so Agent.step can pop blocked_messages without scanning the event log. If None, hook-blocked checks are skipped (legacy conversations).", + "title": "Last User Message Id" + }, + "launched_agent_profile": { + "anyOf": [ + { + "$ref": "#/components/schemas/LaunchedAgentProfile" + }, + { + "type": "null" + } + ], + "description": "Provenance snapshot of the agent profile that launched this conversation. Set at creation when the conversation was started via ``agent_profile_id``; ``None`` for conversations started directly with ``agent`` or ``agent_settings``. Clients use this to identify which agent profile is current without fragile settings-comparison." + }, + "leaf_event_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "HEAD of the conversation tree: the parent of the next appended event. ``None`` means an empty tree (or, for pre-feature conversations, the linear tail). Moving it via ``navigate`` re-roots the active branch the agent runs on.", + "title": "Leaf Event Id" + }, + "max_iterations": { + "default": 500, + "description": "Maximum number of iterations the agent can perform in a single run.", + "exclusiveMinimum": 0.0, + "title": "Max Iterations", + "type": "integer" + }, + "metrics": { + "anyOf": [ + { + "$ref": "#/components/schemas/MetricsSnapshot" + }, + { + "type": "null" + } + ] + }, + "parent_conversation_id": { + "anyOf": [ + { + "format": "uuid", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ID of the conversation that owns this one. ``None`` for top-level conversations.", + "title": "Parent Conversation Id" + }, + "persistence_dir": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": "workspace/conversations", + "description": "Directory for persisting conversation state and events. If None, conversation will not be persisted.", + "title": "Persistence Dir" + }, + "runtime_info": { + "anyOf": [ + { + "$ref": "#/components/schemas/ConversationRuntimeInfo" + }, + { + "type": "null" + } + ], + "description": "Availability of the execution runtime. Catalog responses populate this when the hosting server manages runtime lifecycle." + }, + "secret_registry": { + "$ref": "#/components/schemas/SecretRegistry", + "description": "Registry for handling secrets and sensitive data" + }, + "security_analyzer": { + "anyOf": [ + { + "$ref": "#/components/schemas/SecurityAnalyzerBase-Output" + }, + { + "type": "null" + } + ], + "description": "Optional security analyzer to evaluate action risks." + }, + "stats": { + "$ref": "#/components/schemas/ConversationStats", + "description": "Conversation statistics for tracking LLM metrics" + }, + "stuck_detection": { + "default": true, + "description": "Whether to enable stuck detection for the agent.", + "title": "Stuck Detection", + "type": "boolean" + }, + "sub_conversation_ids": { + "description": "IDs of conversations naming this one as their parent. Derived from the server catalog; empty on webhook payloads. Name mirrors the Cloud API field.", + "items": { + "format": "uuid", + "type": "string" + }, + "title": "Sub Conversation Ids", + "type": "array" + }, + "supports_runtime_model_switch": { + "default": false, + "description": "Whether a live, mid-conversation model switch will be attempted for this conversation — tells the inline picker whether to offer a live-switch control. Mirrors the SDK's switch gate: ``True`` for known switch-capable providers; ``False`` for unknown/custom ACP servers because their generic config writes are not guaranteed live-switch primitives. ``False`` for native OpenHands agents, for a known provider that declares no support, and before the conversation has started a session.", + "title": "Supports Runtime Model Switch", + "type": "boolean" + }, + "tags": { + "additionalProperties": { + "type": "string" + }, + "description": "Key-value tags for the conversation. Keys must be lowercase alphanumeric. Values are arbitrary strings up to 256 characters.", + "title": "Tags", + "type": "object" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "User-defined title for the conversation", + "title": "Title" + }, + "tool_module_qualnames": { + "additionalProperties": { + "type": "string" + }, + "description": "Tool names mapped to importable module qualnames. SDK clients use this metadata to restore the registrations needed to deserialize the conversation's tool events when attaching.", + "title": "Tool Module Qualnames", + "type": "object" + }, + "updated_at": { + "format": "date-time", + "title": "Updated At", + "type": "string" + }, + "workspace": { + "$ref": "#/components/schemas/BaseWorkspace", + "description": "Workspace used by the agent to execute commands and read/write files. Not the process working directory." + } + }, + "required": [ + "id", + "workspace", + "agent" + ], + "title": "ConversationInfo", + "type": "object" + }, + "ConversationPage": { + "properties": { + "items": { + "items": { + "$ref": "#/components/schemas/ConversationInfo" + }, + "title": "Items", + "type": "array" + }, + "next_page_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Next Page Id" + } + }, + "required": [ + "items" + ], + "title": "ConversationPage", + "type": "object" + }, + "ConversationRuntimeError": { + "description": "Structured details for the latest runtime lifecycle failure.", + "properties": { + "code": { + "title": "Code", + "type": "string" + }, + "message": { + "title": "Message", + "type": "string" + } + }, + "required": [ + "code", + "message" + ], + "title": "ConversationRuntimeError", + "type": "object" + }, + "ConversationRuntimeInfo": { + "description": "Runtime availability and recovery information for a conversation.", + "properties": { + "can_resume": { + "title": "Can Resume", + "type": "boolean" + }, + "runtime_error": { + "anyOf": [ + { + "$ref": "#/components/schemas/ConversationRuntimeError" + }, + { + "type": "null" + } + ] + }, + "runtime_status": { + "$ref": "#/components/schemas/ConversationRuntimeStatus" + } + }, + "required": [ + "runtime_status", + "can_resume" + ], + "title": "ConversationRuntimeInfo", + "type": "object" + }, + "ConversationRuntimeStatus": { + "description": "Availability of the runtime that executes a conversation.", + "enum": [ + "available", + "starting", + "missing", + "ownership_lost", + "error" + ], + "title": "ConversationRuntimeStatus", + "type": "string" + }, + "ConversationSortOrder": { + "description": "Enum for conversation sorting options.", + "enum": [ + "CREATED_AT", + "UPDATED_AT", + "CREATED_AT_DESC", + "UPDATED_AT_DESC" + ], + "title": "ConversationSortOrder", + "type": "string" + }, + "ConversationStateUpdateEvent": { + "additionalProperties": false, + "description": "Event that contains conversation state updates.\n\nThis event is sent via websocket whenever the conversation state changes,\nallowing remote clients to stay in sync without making REST API calls.\n\nAll fields are serialized versions of the corresponding ConversationState fields\nto ensure compatibility with websocket transmission.", + "properties": { + "id": { + "description": "Unique event id (ULID/UUID)", + "title": "Id", + "type": "string" + }, + "key": { + "description": "Unique key for this state update event", + "title": "Key", + "type": "string" + }, + "kind": { + "const": "ConversationStateUpdateEvent", + "title": "Kind", + "type": "string" + }, + "parent_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Parent event id in the conversation tree. None for the root, or for legacy events predating the tree (see EventLog's effective-parent rule). Events sharing a parent_id are sibling branches.", + "title": "Parent Id" + }, + "source": { + "default": "environment", + "enum": [ + "agent", + "user", + "environment", + "hook" + ], + "title": "Source", + "type": "string" + }, + "timestamp": { + "description": "Event timestamp", + "title": "Timestamp", + "type": "string" + }, + "value": { + "description": "Serialized conversation state updates", + "title": "Value" + } + }, + "required": [ + "kind" + ], + "title": "ConversationStateUpdateEvent", + "type": "object" + }, + "ConversationStats": { + "additionalProperties": true, + "type": "object" + }, + "CriticBase-Input": { + "discriminator": { + "mapping": { + "openhands__sdk__critic__impl__agent_finished__AgentFinishedCritic-Input__1": "#/components/schemas/AgentFinishedCritic-Input", + "openhands__sdk__critic__impl__api__critic__APIBasedCritic-Input__1": "#/components/schemas/APIBasedCritic-Input", + "openhands__sdk__critic__impl__empty_patch__EmptyPatchCritic-Input__1": "#/components/schemas/EmptyPatchCritic-Input", + "openhands__sdk__critic__impl__pass_critic__PassCritic-Input__1": "#/components/schemas/PassCritic-Input" + }, + "propertyName": "kind" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/AgentFinishedCritic-Input" + }, + { + "$ref": "#/components/schemas/APIBasedCritic-Input" + }, + { + "$ref": "#/components/schemas/EmptyPatchCritic-Input" + }, + { + "$ref": "#/components/schemas/PassCritic-Input" + } + ] + }, + "CriticBase-Output": { + "discriminator": { + "mapping": { + "openhands__sdk__critic__impl__agent_finished__AgentFinishedCritic-Output__1": "#/components/schemas/AgentFinishedCritic-Output", + "openhands__sdk__critic__impl__api__critic__APIBasedCritic-Output__1": "#/components/schemas/APIBasedCritic-Output", + "openhands__sdk__critic__impl__empty_patch__EmptyPatchCritic-Output__1": "#/components/schemas/EmptyPatchCritic-Output", + "openhands__sdk__critic__impl__pass_critic__PassCritic-Output__1": "#/components/schemas/PassCritic-Output" + }, + "propertyName": "kind" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/AgentFinishedCritic-Output" + }, + { + "$ref": "#/components/schemas/APIBasedCritic-Output" + }, + { + "$ref": "#/components/schemas/EmptyPatchCritic-Output" + }, + { + "$ref": "#/components/schemas/PassCritic-Output" + } + ] + }, + "CriticResult": { + "description": "A critic result is a score and a message.", + "properties": { + "message": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "An optional message explaining the score.", + "title": "Message" + }, + "metadata": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "Optional metadata about the critic evaluation. Can include event_ids and categorized_features for visualization.", + "title": "Metadata" + }, + "score": { + "description": "A predicted probability of success between 0 and 1.", + "maximum": 1.0, + "minimum": 0.0, + "title": "Score", + "type": "number" + } + }, + "required": [ + "score", + "message" + ], + "title": "CriticResult", + "type": "object" + }, + "DelegateAction": { + "additionalProperties": false, + "description": "Schema for delegation operations.", + "properties": { + "agent_types": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Optional parameter of `spawn` command. List of agent types for each ID (e.g., ['researcher', 'programmer']). If omitted or blank for an ID, the default general-purpose agent is used.", + "title": "Agent Types" + }, + "command": { + "description": "The commands to run. Allowed options are: `spawn`, `delegate`.", + "enum": [ + "spawn", + "delegate" + ], + "title": "Command", + "type": "string" + }, + "ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Required parameter of `spawn` command. List of identifiers to initialize sub-agents with.", + "title": "Ids" + }, + "kind": { + "const": "DelegateAction", + "title": "Kind", + "type": "string" + }, + "tasks": { + "anyOf": [ + { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "Required parameter of `delegate` command. Dictionary mapping sub-agent identifiers to task descriptions.", + "title": "Tasks" + } + }, + "required": [ + "command", + "kind" + ], + "title": "DelegateAction", + "type": "object" + }, + "DelegateObservation": { + "additionalProperties": false, + "description": "Observation from delegation operations.", + "properties": { + "command": { + "description": "The command that was executed", + "enum": [ + "spawn", + "delegate" + ], + "title": "Command", + "type": "string" + }, + "content": { + "description": "Content returned from the tool as a list of TextContent/ImageContent objects. When there is an error, it should be written in this field.", + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/TextContent" + }, + { + "$ref": "#/components/schemas/ImageContent" + } + ] + }, + "title": "Content", + "type": "array" + }, + "is_error": { + "default": false, + "description": "Whether the observation indicates an error", + "title": "Is Error", + "type": "boolean" + }, + "kind": { + "const": "DelegateObservation", + "title": "Kind", + "type": "string" + } + }, + "required": [ + "command", + "kind" + ], + "title": "DelegateObservation", + "type": "object" + }, + "DeleteResponse": { + "properties": { + "deleted": { + "default": true, + "title": "Deleted", + "type": "boolean" + } + }, + "title": "DeleteResponse", + "type": "object" + }, + "EditAction": { + "additionalProperties": false, + "description": "Schema for edit operation.", + "properties": { + "expected_replacements": { + "default": 1, + "description": "Number of replacements expected. Defaults to 1. Use when you want to replace multiple occurrences. The edit will fail if the actual count doesn't match.", + "minimum": 0.0, + "title": "Expected Replacements", + "type": "integer" + }, + "file_path": { + "description": "The path to the file to modify.", + "title": "File Path", + "type": "string" + }, + "kind": { + "const": "EditAction", + "title": "Kind", + "type": "string" + }, + "new_string": { + "description": "The text to replace it with.", + "title": "New String", + "type": "string" + }, + "old_string": { + "description": "The text to replace. To create a new file, use an empty string. Must match the exact text in the file including whitespace.", + "title": "Old String", + "type": "string" + } + }, + "required": [ + "file_path", + "old_string", + "new_string", + "kind" + ], + "title": "EditAction", + "type": "object" + }, + "EditObservation": { + "additionalProperties": false, + "description": "Observation from editing a file.", + "properties": { + "content": { + "description": "Content returned from the tool as a list of TextContent/ImageContent objects. When there is an error, it should be written in this field.", + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/TextContent" + }, + { + "$ref": "#/components/schemas/ImageContent" + } + ] + }, + "title": "Content", + "type": "array" + }, + "file_path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The file path that was edited.", + "title": "File Path" + }, + "is_error": { + "default": false, + "description": "Whether the observation indicates an error", + "title": "Is Error", + "type": "boolean" + }, + "is_new_file": { + "default": false, + "description": "Whether a new file was created.", + "title": "Is New File", + "type": "boolean" + }, + "kind": { + "const": "EditObservation", + "title": "Kind", + "type": "string" + }, + "new_content": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The content after the edit.", + "title": "New Content" + }, + "old_content": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The content before the edit.", + "title": "Old Content" + }, + "replacements_made": { + "default": 0, + "description": "Number of replacements actually made.", + "title": "Replacements Made", + "type": "integer" + } + }, + "required": [ + "kind" + ], + "title": "EditObservation", + "type": "object" + }, + "EditTool": { + "description": "Tool for editing files via find/replace.", + "properties": { + "action_type": { + "title": "Action Type", + "type": "string" + }, + "annotations": { + "anyOf": [ + { + "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" + }, + { + "type": "null" + } + ] + }, + "description": { + "title": "Description", + "type": "string" + }, + "kind": { + "const": "EditTool", + "title": "Kind", + "type": "string" + }, + "meta": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Meta" + }, + "observation_type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Observation Type" + }, + "title": { + "readOnly": true, + "title": "Title", + "type": "string" + } + }, + "required": [ + "description", + "action_type", + "kind", + "title" + ], + "title": "EditTool", + "type": "object" + }, + "EmptyPatchCritic-Input": { + "description": "Critic that only evaluates whether a git patch is non-empty.\n\nThis critic checks only one criterion:\n- The generated git patch is non-empty (actual changes were made)\n\nUnlike AgentFinishedCritic, this critic does not check for proper\nagent completion with FinishAction.", + "properties": { + "iterative_refinement": { + "anyOf": [ + { + "$ref": "#/components/schemas/IterativeRefinementConfig" + }, + { + "type": "null" + } + ], + "description": "Optional configuration for iterative refinement. When set, Conversation.run() will automatically retry the task if the critic score is below the success_threshold, up to max_iterations." + }, + "kind": { + "const": "EmptyPatchCritic", + "title": "Kind", + "type": "string" + }, + "mode": { + "default": "finish_and_message", + "description": "When to run critic evaluation:\n- 'finish_and_message': Evaluate on FinishAction and agent MessageEvent (default, minimal performance impact)\n- 'all_actions': Evaluate after every agent action (WARNING: significantly slower due to API calls on each action)", + "enum": [ + "finish_and_message", + "all_actions" + ], + "title": "Mode", + "type": "string" + } + }, + "title": "EmptyPatchCritic", + "type": "object" + }, + "EmptyPatchCritic-Output": { + "description": "Critic that only evaluates whether a git patch is non-empty.\n\nThis critic checks only one criterion:\n- The generated git patch is non-empty (actual changes were made)\n\nUnlike AgentFinishedCritic, this critic does not check for proper\nagent completion with FinishAction.", + "properties": { + "iterative_refinement": { + "anyOf": [ + { + "$ref": "#/components/schemas/IterativeRefinementConfig" + }, + { + "type": "null" + } + ], + "description": "Optional configuration for iterative refinement. When set, Conversation.run() will automatically retry the task if the critic score is below the success_threshold, up to max_iterations." + }, + "kind": { + "const": "EmptyPatchCritic", + "title": "Kind", + "type": "string" + }, + "mode": { + "default": "finish_and_message", + "description": "When to run critic evaluation:\n- 'finish_and_message': Evaluate on FinishAction and agent MessageEvent (default, minimal performance impact)\n- 'all_actions': Evaluate after every agent action (WARNING: significantly slower due to API calls on each action)", + "enum": [ + "finish_and_message", + "all_actions" + ], + "title": "Mode", + "type": "string" + } + }, + "required": [ + "kind" + ], + "title": "EmptyPatchCritic", + "type": "object" + }, + "EnsembleSecurityAnalyzer-Input": { + "description": "Wire multiple analyzers together and take the worst-case risk.\n\nUse this as the top-level analyzer you set on a conversation. It\ncalls each child analyzer, collects their risk assessments, and\nreturns the highest concrete risk. It does not perform any detection,\nextraction, or normalization of its own.\n\nHow UNKNOWN works (default, ``propagate_unknown=False``): if *all*\nchildren return UNKNOWN, the ensemble returns UNKNOWN (which\n``ConfirmRisky`` confirms by default). If any child returns a\nconcrete level, UNKNOWN results are filtered out and the highest\nconcrete level wins.\n\nWith ``propagate_unknown=True``: if *any* child returns UNKNOWN, the\nensemble returns UNKNOWN regardless of other results. Use this in\nstricter environments where incomplete assessment should trigger\nconfirmation.\n\nIf a child analyzer raises an exception, it contributes HIGH\n(fail-closed, logged). This prevents a broken analyzer from silently\ndegrading safety.\n\nExample::\n\n from openhands.sdk.security import (\n EnsembleSecurityAnalyzer,\n PatternSecurityAnalyzer,\n PolicyRailSecurityAnalyzer,\n ConfirmRisky,\n SecurityRisk,\n )\n\n analyzer = EnsembleSecurityAnalyzer(\n analyzers=[\n PolicyRailSecurityAnalyzer(),\n PatternSecurityAnalyzer(),\n ]\n )\n policy = ConfirmRisky(threshold=SecurityRisk.MEDIUM)", + "properties": { + "analyzers": { + "description": "Analyzers whose assessments are combined via max-severity", + "items": { + "$ref": "#/components/schemas/SecurityAnalyzerBase-Input" + }, + "minItems": 1, + "title": "Analyzers", + "type": "array" + }, + "kind": { + "const": "EnsembleSecurityAnalyzer", + "title": "Kind", + "type": "string" + }, + "propagate_unknown": { + "default": false, + "description": "When True, any child returning UNKNOWN causes the ensemble to return UNKNOWN. When False (default), UNKNOWN is filtered out if any child returns a concrete level.", + "title": "Propagate Unknown", + "type": "boolean" + } + }, + "required": [ + "analyzers" + ], + "title": "EnsembleSecurityAnalyzer", + "type": "object" + }, + "EnsembleSecurityAnalyzer-Output": { + "description": "Wire multiple analyzers together and take the worst-case risk.\n\nUse this as the top-level analyzer you set on a conversation. It\ncalls each child analyzer, collects their risk assessments, and\nreturns the highest concrete risk. It does not perform any detection,\nextraction, or normalization of its own.\n\nHow UNKNOWN works (default, ``propagate_unknown=False``): if *all*\nchildren return UNKNOWN, the ensemble returns UNKNOWN (which\n``ConfirmRisky`` confirms by default). If any child returns a\nconcrete level, UNKNOWN results are filtered out and the highest\nconcrete level wins.\n\nWith ``propagate_unknown=True``: if *any* child returns UNKNOWN, the\nensemble returns UNKNOWN regardless of other results. Use this in\nstricter environments where incomplete assessment should trigger\nconfirmation.\n\nIf a child analyzer raises an exception, it contributes HIGH\n(fail-closed, logged). This prevents a broken analyzer from silently\ndegrading safety.\n\nExample::\n\n from openhands.sdk.security import (\n EnsembleSecurityAnalyzer,\n PatternSecurityAnalyzer,\n PolicyRailSecurityAnalyzer,\n ConfirmRisky,\n SecurityRisk,\n )\n\n analyzer = EnsembleSecurityAnalyzer(\n analyzers=[\n PolicyRailSecurityAnalyzer(),\n PatternSecurityAnalyzer(),\n ]\n )\n policy = ConfirmRisky(threshold=SecurityRisk.MEDIUM)", + "properties": { + "analyzers": { + "description": "Analyzers whose assessments are combined via max-severity", + "items": { + "$ref": "#/components/schemas/SecurityAnalyzerBase-Output" + }, + "minItems": 1, + "title": "Analyzers", + "type": "array" + }, + "kind": { + "const": "EnsembleSecurityAnalyzer", + "title": "Kind", + "type": "string" + }, + "propagate_unknown": { + "default": false, + "description": "When True, any child returning UNKNOWN causes the ensemble to return UNKNOWN. When False (default), UNKNOWN is filtered out if any child returns a concrete level.", + "title": "Propagate Unknown", + "type": "boolean" + } + }, + "required": [ + "analyzers", + "kind" + ], + "title": "EnsembleSecurityAnalyzer", + "type": "object" + }, + "ErrorClassification": { + "additionalProperties": false, + "description": "The only failure metadata that crosses the event/API boundary.\n\nIt is intentionally small. ``detail`` is inspected locally only to map\nbroad third-party errors to this closed vocabulary; it is never copied\nhere or sent to telemetry.", + "properties": { + "error_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Error Id" + }, + "kind": { + "$ref": "#/components/schemas/FailureKind" + }, + "retryable": { + "title": "Retryable", + "type": "boolean" + }, + "user_action": { + "default": "none", + "enum": [ + "none", + "retry", + "settings" + ], + "title": "User Action", + "type": "string" + } + }, + "required": [ + "kind", + "retryable" + ], + "title": "ErrorClassification", + "type": "object" + }, + "Event": { + "discriminator": { + "mapping": { + "openhands__agent_server__models__ServerErrorEvent-Output__1": "#/components/schemas/ServerErrorEvent", + "openhands__sdk__event__acp_tool_call__ACPToolCallEvent-Output__1": "#/components/schemas/ACPToolCallEvent", + "openhands__sdk__event__condenser__Condensation-Output__1": "#/components/schemas/Condensation", + "openhands__sdk__event__condenser__CondensationRequest-Output__1": "#/components/schemas/CondensationRequest", + "openhands__sdk__event__condenser__CondensationSummaryEvent-Output__1": "#/components/schemas/CondensationSummaryEvent", + "openhands__sdk__event__conversation_error__ConversationErrorEvent-Output__1": "#/components/schemas/ConversationErrorEvent", + "openhands__sdk__event__conversation_state__ConversationStateUpdateEvent-Output__1": "#/components/schemas/ConversationStateUpdateEvent", + "openhands__sdk__event__hook_execution__HookExecutionEvent-Output__1": "#/components/schemas/HookExecutionEvent", + "openhands__sdk__event__llm_completion_log__LLMCompletionLogEvent-Output__1": "#/components/schemas/LLMCompletionLogEvent", + "openhands__sdk__event__llm_convertible__action__ActionEvent-Output__1": "#/components/schemas/ActionEvent", + "openhands__sdk__event__llm_convertible__message__MessageEvent-Output__1": "#/components/schemas/MessageEvent", + "openhands__sdk__event__llm_convertible__observation__AgentErrorEvent-Output__1": "#/components/schemas/AgentErrorEvent", + "openhands__sdk__event__llm_convertible__observation__ObservationEvent-Output__1": "#/components/schemas/ObservationEvent", + "openhands__sdk__event__llm_convertible__observation__UserRejectObservation-Output__1": "#/components/schemas/UserRejectObservation", + "openhands__sdk__event__llm_convertible__system__SystemPromptEvent-Output__1": "#/components/schemas/SystemPromptEvent", + "openhands__sdk__event__streaming_delta__StreamingDeltaEvent-Output__1": "#/components/schemas/StreamingDeltaEvent", + "openhands__sdk__event__token__TokenEvent-Output__1": "#/components/schemas/TokenEvent", + "openhands__sdk__event__user_action__InterruptEvent-Output__1": "#/components/schemas/InterruptEvent", + "openhands__sdk__event__user_action__PauseEvent-Output__1": "#/components/schemas/PauseEvent" + }, + "propertyName": "kind" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/ServerErrorEvent" + }, + { + "$ref": "#/components/schemas/ACPToolCallEvent" + }, + { + "$ref": "#/components/schemas/Condensation" + }, + { + "$ref": "#/components/schemas/CondensationRequest" + }, + { + "$ref": "#/components/schemas/CondensationSummaryEvent" + }, + { + "$ref": "#/components/schemas/ConversationErrorEvent" + }, + { + "$ref": "#/components/schemas/ConversationStateUpdateEvent" + }, + { + "$ref": "#/components/schemas/HookExecutionEvent" + }, + { + "$ref": "#/components/schemas/LLMCompletionLogEvent" + }, + { + "$ref": "#/components/schemas/ActionEvent" + }, + { + "$ref": "#/components/schemas/MessageEvent" + }, + { + "$ref": "#/components/schemas/AgentErrorEvent" + }, + { + "$ref": "#/components/schemas/ObservationEvent" + }, + { + "$ref": "#/components/schemas/UserRejectObservation" + }, + { + "$ref": "#/components/schemas/SystemPromptEvent" + }, + { + "$ref": "#/components/schemas/StreamingDeltaEvent" + }, + { + "$ref": "#/components/schemas/TokenEvent" + }, + { + "$ref": "#/components/schemas/InterruptEvent" + }, + { + "$ref": "#/components/schemas/PauseEvent" + } + ] + }, + "EventSortOrder": { + "description": "Enum for event sorting options.", + "enum": [ + "TIMESTAMP", + "TIMESTAMP_DESC" + ], + "title": "EventSortOrder", + "type": "string" + }, + "ExecuteBashRequest": { + "properties": { + "command": { + "description": "The bash command to execute", + "title": "Command", + "type": "string" + }, + "cwd": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The current working directory", + "title": "Cwd" + }, + "timeout": { + "default": 300, + "description": "The max number of seconds a command may be permitted to run.", + "title": "Timeout", + "type": "integer" + } + }, + "required": [ + "command" + ], + "title": "ExecuteBashRequest", + "type": "object" + }, + "ExposedUrl": { + "description": "Represents an exposed URL from the sandbox.", + "properties": { + "name": { + "title": "Name", + "type": "string" + }, + "port": { + "title": "Port", + "type": "integer" + }, + "url": { + "title": "Url", + "type": "string" + } + }, + "required": [ + "name", + "url", + "port" + ], + "title": "ExposedUrl", + "type": "object" + }, + "FailureKind": { + "enum": [ + "auth", + "quota", + "rate_limit", + "config", + "transient", + "agent_action", + "internal", + "unknown" + ], + "title": "FailureKind", + "type": "string" + }, + "FallbackStrategy": { + "description": "Encapsulates fallback behavior for LLM calls.\n\nWhen the primary LLM fails with a transient error (after retries),\nthis strategy tries alternate LLMs loaded from LLMProfileStore profiles.\nFallback is per-call: each new request starts with the primary model.", + "properties": { + "fallback_llms": { + "description": "Ordered list of LLM profile names to try on transient failure.", + "items": { + "type": "string" + }, + "title": "Fallback Llms", + "type": "array" + }, + "profile_store_dir": { + "anyOf": [ + { + "type": "string" + }, + { + "format": "path", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Path to directory containing profiles. If not specified, defaults to `.openhands/profiles`.", + "title": "Profile Store Dir" + } + }, + "required": [ + "fallback_llms" + ], + "title": "FallbackStrategy", + "type": "object" + }, + "FileBrowserEntry": { + "properties": { + "label": { + "title": "Label", + "type": "string" + }, + "path": { + "title": "Path", + "type": "string" + } + }, + "required": [ + "label", + "path" + ], + "title": "FileBrowserEntry", + "type": "object" + }, + "FileEditorAction": { + "additionalProperties": false, + "description": "Schema for file editor operations.", + "properties": { + "command": { + "description": "The commands to run. Allowed options are: `view`, `create`, `str_replace`, `insert`, `undo_edit`.", + "enum": [ + "view", + "create", + "str_replace", + "insert", + "undo_edit" + ], + "title": "Command", + "type": "string" + }, + "file_text": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Required parameter of `create` command, with the content of the file to be created.", + "title": "File Text" + }, + "insert_line": { + "anyOf": [ + { + "minimum": 0.0, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Required parameter of `insert` command. The `new_str` will be inserted AFTER the line `insert_line` of `path`.", + "title": "Insert Line" + }, + "kind": { + "const": "FileEditorAction", + "title": "Kind", + "type": "string" + }, + "new_str": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Optional parameter of `str_replace` command containing the new string (if not given, no string will be added). Required parameter of `insert` command containing the string to insert.", + "title": "New Str" + }, + "old_str": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Required parameter of `str_replace` command containing the string in `path` to replace.", + "title": "Old Str" + }, + "path": { + "description": "Absolute path to file or directory.", + "title": "Path", + "type": "string" + }, + "view_range": { + "anyOf": [ + { + "items": { + "type": "integer" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Optional parameter of `view` command when `path` points to a file. If none is given, the full file is shown. If provided, the file will be shown in the indicated line number range, e.g. [11, 12] will show lines 11 and 12. Indexing at 1 to start. Setting `[start_line, -1]` shows all lines from `start_line` to the end of the file.", + "title": "View Range" + } + }, + "required": [ + "command", + "path", + "kind" + ], + "title": "FileEditorAction", + "type": "object" + }, + "FileEditorObservation": { + "additionalProperties": false, + "description": "A ToolResult that can be rendered as a CLI output.", + "properties": { + "command": { + "description": "The command that was run: `view`, `create`, `str_replace`, `insert`, or `undo_edit`.", + "enum": [ + "view", + "create", + "str_replace", + "insert", + "undo_edit" + ], + "title": "Command", + "type": "string" + }, + "content": { + "description": "Content returned from the tool as a list of TextContent/ImageContent objects. When there is an error, it should be written in this field.", + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/TextContent" + }, + { + "$ref": "#/components/schemas/ImageContent" + } + ] + }, + "title": "Content", + "type": "array" + }, + "is_error": { + "default": false, + "description": "Whether the observation indicates an error", + "title": "Is Error", + "type": "boolean" + }, + "kind": { + "const": "FileEditorObservation", + "title": "Kind", + "type": "string" + }, + "new_content": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The content of the file after the edit.", + "title": "New Content" + }, + "old_content": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The content of the file before the edit.", + "title": "Old Content" + }, + "path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The file path that was edited.", + "title": "Path" + }, + "prev_exist": { + "default": true, + "description": "Indicates if the file previously existed. If not, it was created.", + "title": "Prev Exist", + "type": "boolean" + } + }, + "required": [ + "command", + "kind" + ], + "title": "FileEditorObservation", + "type": "object" + }, + "FileEditorTool": { + "description": "A ToolDefinition subclass that automatically initializes a FileEditorExecutor.", + "properties": { + "action_type": { + "title": "Action Type", + "type": "string" + }, + "annotations": { + "anyOf": [ + { + "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" + }, + { + "type": "null" + } + ] + }, + "description": { + "title": "Description", + "type": "string" + }, + "kind": { + "const": "FileEditorTool", + "title": "Kind", + "type": "string" + }, + "meta": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Meta" + }, + "observation_type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Observation Type" + }, + "title": { + "readOnly": true, + "title": "Title", + "type": "string" + } + }, + "required": [ + "description", + "action_type", + "kind", + "title" + ], + "title": "FileEditorTool", + "type": "object" + }, + "FileEntry": { + "description": "Information about a file or directory.", + "properties": { + "is_directory": { + "description": "Whether this entry is a directory", + "title": "Is Directory", + "type": "boolean" + }, + "modified_time": { + "description": "Last modified timestamp", + "format": "date-time", + "title": "Modified Time", + "type": "string" + }, + "name": { + "description": "Name of the file or directory", + "title": "Name", + "type": "string" + }, + "path": { + "description": "Absolute path to the file or directory", + "title": "Path", + "type": "string" + }, + "size": { + "description": "Size of the file in bytes (0 for directories)", + "title": "Size", + "type": "integer" + } + }, + "required": [ + "name", + "path", + "is_directory", + "size", + "modified_time" + ], + "title": "FileEntry", + "type": "object" + }, + "FinishAction": { + "additionalProperties": false, + "properties": { + "kind": { + "const": "FinishAction", + "title": "Kind", + "type": "string" + }, + "message": { + "description": "Final message to send to the user.", + "title": "Message", + "type": "string" + } + }, + "required": [ + "message", + "kind" + ], + "title": "FinishAction", + "type": "object" + }, + "FinishObservation": { + "additionalProperties": false, + "description": "Observation returned after finishing a task.\nThe FinishAction itself contains the message sent to the user so no\nextra fields are needed here.", + "properties": { + "content": { + "description": "Content returned from the tool as a list of TextContent/ImageContent objects. When there is an error, it should be written in this field.", + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/TextContent" + }, + { + "$ref": "#/components/schemas/ImageContent" + } + ] + }, + "title": "Content", + "type": "array" + }, + "is_error": { + "default": false, + "description": "Whether the observation indicates an error", + "title": "Is Error", + "type": "boolean" + }, + "kind": { + "const": "FinishObservation", + "title": "Kind", + "type": "string" + } + }, + "required": [ + "kind" + ], + "title": "FinishObservation", + "type": "object" + }, + "FinishTool": { + "description": "Tool for signaling the completion of a task or conversation.", + "properties": { + "action_type": { + "title": "Action Type", + "type": "string" + }, + "annotations": { + "anyOf": [ + { + "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" + }, + { + "type": "null" + } + ] + }, + "description": { + "title": "Description", + "type": "string" + }, + "kind": { + "const": "FinishTool", + "title": "Kind", + "type": "string" + }, + "meta": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Meta" + }, + "observation_type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Observation Type" + }, + "title": { + "readOnly": true, + "title": "Title", + "type": "string" + } + }, + "required": [ + "description", + "action_type", + "kind", + "title" + ], + "title": "FinishTool", + "type": "object" + }, + "ForkConversationRequest": { + "description": "Payload to fork a conversation.", + "properties": { + "from_event_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "If set, fork only the branch up to and including this event and set the fork's HEAD there. If null (default), copy the whole conversation.", + "title": "From Event Id" + }, + "id": { + "anyOf": [ + { + "format": "uuid", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ID for the forked conversation (auto-generated if null)", + "title": "Id" + }, + "reset_metrics": { + "default": true, + "description": "If true, cost/token stats start fresh on the fork. If false, metrics are copied from the source.", + "title": "Reset Metrics", + "type": "boolean" + }, + "tags": { + "anyOf": [ + { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "Optional tags for the forked conversation. Keys must be lowercase alphanumeric.", + "title": "Tags" + }, + "title": { + "anyOf": [ + { + "maxLength": 200, + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Optional title for the forked conversation", + "title": "Title" + } + }, + "title": "ForkConversationRequest", + "type": "object" + }, + "GitChange": { + "properties": { + "path": { + "format": "path", + "title": "Path", + "type": "string" + }, + "status": { + "$ref": "#/components/schemas/GitChangeStatus" + } + }, + "required": [ + "status", + "path" + ], + "title": "GitChange", + "type": "object" + }, + "GitChangeStatus": { + "enum": [ + "MOVED", + "ADDED", + "DELETED", + "UPDATED" + ], + "title": "GitChangeStatus", + "type": "string" + }, + "GitCommit": { + "properties": { + "author": { + "title": "Author", + "type": "string" + }, + "sha": { + "title": "Sha", + "type": "string" + }, + "short_sha": { + "title": "Short Sha", + "type": "string" + }, + "subject": { + "title": "Subject", + "type": "string" + }, + "timestamp": { + "title": "Timestamp", + "type": "string" + } + }, + "required": [ + "sha", + "short_sha", + "subject", + "author", + "timestamp" + ], + "title": "GitCommit", + "type": "object" + }, + "GitCommitsPage": { + "properties": { + "commits": { + "items": { + "$ref": "#/components/schemas/GitCommit" + }, + "title": "Commits", + "type": "array" + }, + "has_more": { + "title": "Has More", + "type": "boolean" + } + }, + "required": [ + "commits", + "has_more" + ], + "title": "GitCommitsPage", + "type": "object" + }, + "GitDiff": { + "properties": { + "modified": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Modified" + }, + "original": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Original" + } + }, + "required": [ + "modified", + "original" + ], + "title": "GitDiff", + "type": "object" + }, + "GitProvider": { + "description": "Supported git hosting providers.", + "enum": [ + "github", + "gitlab", + "bitbucket" + ], + "title": "GitProvider", + "type": "string" + }, + "GitProviderRepository": { + "properties": { + "full_name": { + "title": "Full Name", + "type": "string" + }, + "git_provider": { + "title": "Git Provider", + "type": "string" + }, + "id": { + "title": "Id", + "type": "string" + }, + "is_public": { + "title": "Is Public", + "type": "boolean" + }, + "main_branch": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Main Branch" + }, + "pushed_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Pushed At" + }, + "stargazers_count": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Stargazers Count" + } + }, + "required": [ + "id", + "full_name", + "git_provider", + "is_public" + ], + "title": "GitProviderRepository", + "type": "object" + }, + "GitProviderRepositoryPage": { + "properties": { + "items": { + "items": { + "$ref": "#/components/schemas/GitProviderRepository" + }, + "title": "Items", + "type": "array" + }, + "missing_token": { + "default": false, + "title": "Missing Token", + "type": "boolean" + }, + "next_page_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Next Page Id" + } + }, + "required": [ + "items" + ], + "title": "GitProviderRepositoryPage", + "type": "object" + }, + "GlobAction": { + "additionalProperties": false, + "description": "Schema for glob pattern matching operations.", + "properties": { + "kind": { + "const": "GlobAction", + "title": "Kind", + "type": "string" + }, + "path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The directory (absolute path) to search in. Defaults to the current working directory.", + "title": "Path" + }, + "pattern": { + "description": "The glob pattern to match files (e.g., \"**/*.js\", \"src/**/*.ts\")", + "title": "Pattern", + "type": "string" + } + }, + "required": [ + "pattern", + "kind" + ], + "title": "GlobAction", + "type": "object" + }, + "GlobObservation": { + "additionalProperties": false, + "description": "Observation from glob pattern matching operations.", + "properties": { + "content": { + "description": "Content returned from the tool as a list of TextContent/ImageContent objects. When there is an error, it should be written in this field.", + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/TextContent" + }, + { + "$ref": "#/components/schemas/ImageContent" + } + ] + }, + "title": "Content", + "type": "array" + }, + "files": { + "description": "List of matching file paths sorted by modification time", + "items": { + "type": "string" + }, + "title": "Files", + "type": "array" + }, + "is_error": { + "default": false, + "description": "Whether the observation indicates an error", + "title": "Is Error", + "type": "boolean" + }, + "kind": { + "const": "GlobObservation", + "title": "Kind", + "type": "string" + }, + "pattern": { + "description": "The glob pattern that was used", + "title": "Pattern", + "type": "string" + }, + "search_path": { + "description": "The directory that was searched", + "title": "Search Path", + "type": "string" + }, + "truncated": { + "default": false, + "description": "Whether results were truncated to 100 files", + "title": "Truncated", + "type": "boolean" + } + }, + "required": [ + "files", + "pattern", + "search_path", + "kind" + ], + "title": "GlobObservation", + "type": "object" + }, + "GlobTool": { + "description": "A ToolDefinition subclass that automatically initializes a GlobExecutor.", + "properties": { + "action_type": { + "title": "Action Type", + "type": "string" + }, + "annotations": { + "anyOf": [ + { + "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" + }, + { + "type": "null" + } + ] + }, + "description": { + "title": "Description", + "type": "string" + }, + "kind": { + "const": "GlobTool", + "title": "Kind", + "type": "string" + }, + "meta": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Meta" + }, + "observation_type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Observation Type" + }, + "title": { + "readOnly": true, + "title": "Title", + "type": "string" + } + }, + "required": [ + "description", + "action_type", + "kind", + "title" + ], + "title": "GlobTool", + "type": "object" + }, + "GraySwanAnalyzer-Input": { + "description": "Security analyzer using GraySwan's Cygnal API for AI safety monitoring.\n\nThis analyzer sends conversation history and pending actions to the GraySwan\nCygnal API for security analysis. The API returns a violation score which is\nmapped to SecurityRisk levels.\n\nEnvironment Variables:\n GRAYSWAN_API_KEY: Required API key for GraySwan authentication\n GRAYSWAN_POLICY_ID: Optional policy ID for custom GraySwan policy\n\nExample:\n >>> from openhands.sdk.security.grayswan import GraySwanAnalyzer\n >>> analyzer = GraySwanAnalyzer()\n >>> risk = analyzer.security_risk(action_event)", + "properties": { + "api_key": { + "anyOf": [ + { + "format": "password", + "type": "string", + "writeOnly": true + }, + { + "type": "null" + } + ], + "description": "GraySwan API key (via GRAYSWAN_API_KEY env var)", + "title": "Api Key" + }, + "api_url": { + "default": "https://api.grayswan.ai/cygnal/monitor", + "description": "GraySwan Cygnal API endpoint", + "title": "Api Url", + "type": "string" + }, + "history_limit": { + "default": 20, + "description": "Number of recent events to include as context", + "title": "History Limit", + "type": "integer" + }, + "kind": { + "const": "GraySwanAnalyzer", + "title": "Kind", + "type": "string" + }, + "low_threshold": { + "default": 0.3, + "description": "Risk threshold for LOW classification (score <= threshold)", + "title": "Low Threshold", + "type": "number" + }, + "max_message_chars": { + "default": 30000, + "description": "Max characters for conversation processing", + "title": "Max Message Chars", + "type": "integer" + }, + "medium_threshold": { + "default": 0.7, + "description": "Risk threshold for MEDIUM classification (score <= threshold)", + "title": "Medium Threshold", + "type": "number" + }, + "policy_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "GraySwan policy ID (via GRAYSWAN_POLICY_ID env var)", + "title": "Policy Id" + }, + "timeout": { + "default": 30.0, + "description": "Request timeout in seconds", + "title": "Timeout", + "type": "number" + } + }, + "title": "GraySwanAnalyzer", + "type": "object" + }, + "GraySwanAnalyzer-Output": { + "description": "Security analyzer using GraySwan's Cygnal API for AI safety monitoring.\n\nThis analyzer sends conversation history and pending actions to the GraySwan\nCygnal API for security analysis. The API returns a violation score which is\nmapped to SecurityRisk levels.\n\nEnvironment Variables:\n GRAYSWAN_API_KEY: Required API key for GraySwan authentication\n GRAYSWAN_POLICY_ID: Optional policy ID for custom GraySwan policy\n\nExample:\n >>> from openhands.sdk.security.grayswan import GraySwanAnalyzer\n >>> analyzer = GraySwanAnalyzer()\n >>> risk = analyzer.security_risk(action_event)", + "properties": { + "api_key": { + "anyOf": [ + { + "format": "password", + "type": "string", + "writeOnly": true + }, + { + "type": "null" + } + ], + "description": "GraySwan API key (via GRAYSWAN_API_KEY env var)", + "title": "Api Key" + }, + "api_url": { + "default": "https://api.grayswan.ai/cygnal/monitor", + "description": "GraySwan Cygnal API endpoint", + "title": "Api Url", + "type": "string" + }, + "history_limit": { + "default": 20, + "description": "Number of recent events to include as context", + "title": "History Limit", + "type": "integer" + }, + "kind": { + "const": "GraySwanAnalyzer", + "title": "Kind", + "type": "string" + }, + "low_threshold": { + "default": 0.3, + "description": "Risk threshold for LOW classification (score <= threshold)", + "title": "Low Threshold", + "type": "number" + }, + "max_message_chars": { + "default": 30000, + "description": "Max characters for conversation processing", + "title": "Max Message Chars", + "type": "integer" + }, + "medium_threshold": { + "default": 0.7, + "description": "Risk threshold for MEDIUM classification (score <= threshold)", + "title": "Medium Threshold", + "type": "number" + }, + "policy_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "GraySwan policy ID (via GRAYSWAN_POLICY_ID env var)", + "title": "Policy Id" + }, + "timeout": { + "default": 30.0, + "description": "Request timeout in seconds", + "title": "Timeout", + "type": "number" + } + }, + "required": [ + "kind" + ], + "title": "GraySwanAnalyzer", + "type": "object" + }, + "GrepAction": { + "additionalProperties": false, + "description": "Schema for grep content search operations.", + "properties": { + "include": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Optional file pattern to filter which files to search (e.g., \"*.js\", \"*.{ts,tsx}\")", + "title": "Include" + }, + "kind": { + "const": "GrepAction", + "title": "Kind", + "type": "string" + }, + "path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The directory (absolute path) to search in. Defaults to the current working directory.", + "title": "Path" + }, + "pattern": { + "description": "The regex pattern to search for in file contents", + "title": "Pattern", + "type": "string" + } + }, + "required": [ + "pattern", + "kind" + ], + "title": "GrepAction", + "type": "object" + }, + "GrepObservation": { + "additionalProperties": false, + "description": "Observation from grep content search operations.", + "properties": { + "content": { + "description": "Content returned from the tool as a list of TextContent/ImageContent objects. When there is an error, it should be written in this field.", + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/TextContent" + }, + { + "$ref": "#/components/schemas/ImageContent" + } + ] + }, + "title": "Content", + "type": "array" + }, + "include_pattern": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The file pattern filter that was used", + "title": "Include Pattern" + }, + "is_error": { + "default": false, + "description": "Whether the observation indicates an error", + "title": "Is Error", + "type": "boolean" + }, + "kind": { + "const": "GrepObservation", + "title": "Kind", + "type": "string" + }, + "matches": { + "description": "List of file paths containing the pattern", + "items": { + "type": "string" + }, + "title": "Matches", + "type": "array" + }, + "pattern": { + "description": "The regex pattern that was used", + "title": "Pattern", + "type": "string" + }, + "search_path": { + "description": "The directory that was searched", + "title": "Search Path", + "type": "string" + }, + "truncated": { + "default": false, + "description": "Whether results were truncated to 100 files", + "title": "Truncated", + "type": "boolean" + } + }, + "required": [ + "matches", + "pattern", + "search_path", + "kind" + ], + "title": "GrepObservation", + "type": "object" + }, + "GrepTool": { + "description": "A ToolDefinition subclass that automatically initializes a GrepExecutor.", + "properties": { + "action_type": { + "title": "Action Type", + "type": "string" + }, + "annotations": { + "anyOf": [ + { + "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" + }, + { + "type": "null" + } + ] + }, + "description": { + "title": "Description", + "type": "string" + }, + "kind": { + "const": "GrepTool", + "title": "Kind", + "type": "string" + }, + "meta": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Meta" + }, + "observation_type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Observation Type" + }, + "title": { + "readOnly": true, + "title": "Title", + "type": "string" + } + }, + "required": [ + "description", + "action_type", + "kind", + "title" + ], + "title": "GrepTool", + "type": "object" + }, + "HTTPValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + "title": "Detail", + "type": "array" + } + }, + "title": "HTTPValidationError", + "type": "object" + }, + "HomeResponse": { + "properties": { + "favorites": { + "default": [], + "items": { + "$ref": "#/components/schemas/FileBrowserEntry" + }, + "title": "Favorites", + "type": "array" + }, + "home": { + "title": "Home", + "type": "string" + }, + "locations": { + "default": [], + "items": { + "$ref": "#/components/schemas/FileBrowserEntry" + }, + "title": "Locations", + "type": "array" + } + }, + "required": [ + "home" + ], + "title": "HomeResponse", + "type": "object" + }, + "HookConfig": { + "additionalProperties": false, + "description": "Configuration for all hooks.\n\nHooks can be configured either by loading from `.openhands/hooks.json` or\nby directly instantiating with typed fields:\n\n # Direct instantiation with typed fields (recommended):\n config = HookConfig(\n pre_tool_use=[\n HookMatcher(\n matcher=\"terminal\",\n hooks=[HookDefinition(command=\"block_dangerous.sh\")]\n )\n ]\n )\n\n # Load from JSON file:\n config = HookConfig.load(\".openhands/hooks.json\")", + "properties": { + "post_tool_use": { + "description": "Hooks that run after tool execution", + "items": { + "$ref": "#/components/schemas/HookMatcher" + }, + "title": "Post Tool Use", + "type": "array" + }, + "pre_tool_use": { + "description": "Hooks that run before tool execution", + "items": { + "$ref": "#/components/schemas/HookMatcher" + }, + "title": "Pre Tool Use", + "type": "array" + }, + "session_end": { + "description": "Hooks that run when a session ends", + "items": { + "$ref": "#/components/schemas/HookMatcher" + }, + "title": "Session End", + "type": "array" + }, + "session_start": { + "description": "Hooks that run when a session starts", + "items": { + "$ref": "#/components/schemas/HookMatcher" + }, + "title": "Session Start", + "type": "array" + }, + "stop": { + "description": "Hooks that run when the agent attempts to stop", + "items": { + "$ref": "#/components/schemas/HookMatcher" + }, + "title": "Stop", + "type": "array" + }, + "user_prompt_submit": { + "description": "Hooks that run when user submits a prompt", + "items": { + "$ref": "#/components/schemas/HookMatcher" + }, + "title": "User Prompt Submit", + "type": "array" + } + }, + "title": "HookConfig", + "type": "object" + }, + "HookDefinition": { + "description": "A single hook definition.", + "properties": { + "async": { + "default": false, + "title": "Async", + "type": "boolean" + }, + "command": { + "title": "Command", + "type": "string" + }, + "max_iterations": { + "default": 3, + "title": "Max Iterations", + "type": "integer" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Name" + }, + "prompt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Prompt" + }, + "system_prompt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "System Prompt" + }, + "timeout": { + "default": 60, + "title": "Timeout", + "type": "integer" + }, + "tools": { + "items": { + "type": "string" + }, + "title": "Tools", + "type": "array" + }, + "type": { + "$ref": "#/components/schemas/HookType", + "default": "command" + } + }, + "required": [ + "command" + ], + "title": "HookDefinition", + "type": "object" + }, + "HookExecutionEvent": { + "additionalProperties": false, + "description": "Event emitted when a hook is executed.\n\nThis event provides observability into hook execution, including:\n- Which hook type was triggered\n- The command that was run\n- The result (success/blocked/error)\n- Any output from the hook\n\nThis allows clients to track hook execution via the event stream.", + "properties": { + "action_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ID of the action this hook is associated with (PreToolUse/PostToolUse)", + "title": "Action Id" + }, + "additional_context": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Additional context injected by hook (e.g., for UserPromptSubmit)", + "title": "Additional Context" + }, + "blocked": { + "default": false, + "description": "Whether the hook blocked the operation (exit code 2 or deny)", + "title": "Blocked", + "type": "boolean" + }, + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Error message if hook execution failed", + "title": "Error" + }, + "exit_code": { + "description": "Exit code from the hook command", + "title": "Exit Code", + "type": "integer" + }, + "hook_command": { + "description": "The hook command that was executed", + "title": "Hook Command", + "type": "string" + }, + "hook_event_type": { + "description": "The type of hook event that triggered this execution", + "enum": [ + "PreToolUse", + "PostToolUse", + "UserPromptSubmit", + "SessionStart", + "SessionEnd", + "Stop" + ], + "title": "Hook Event Type", + "type": "string" + }, + "hook_input": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The input data that was passed to the hook", + "title": "Hook Input" + }, + "id": { + "description": "Unique event id (ULID/UUID)", + "title": "Id", + "type": "string" + }, + "kind": { + "const": "HookExecutionEvent", + "title": "Kind", + "type": "string" + }, + "message_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ID of the message this hook is associated with (UserPromptSubmit)", + "title": "Message Id" + }, + "parent_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Parent event id in the conversation tree. None for the root, or for legacy events predating the tree (see EventLog's effective-parent rule). Events sharing a parent_id are sibling branches.", + "title": "Parent Id" + }, + "reason": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Reason provided by hook (for blocking)", + "title": "Reason" + }, + "source": { + "default": "hook", + "description": "Source is always 'hook' for hook execution events", + "enum": [ + "agent", + "user", + "environment", + "hook" + ], + "title": "Source", + "type": "string" + }, + "stderr": { + "default": "", + "description": "Standard error from the hook", + "title": "Stderr", + "type": "string" + }, + "stdout": { + "default": "", + "description": "Standard output from the hook", + "title": "Stdout", + "type": "string" + }, + "success": { + "description": "Whether the hook executed successfully", + "title": "Success", + "type": "boolean" + }, + "timestamp": { + "description": "Event timestamp", + "title": "Timestamp", + "type": "string" + }, + "tool_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Tool name for PreToolUse/PostToolUse hooks", + "title": "Tool Name" + } + }, + "required": [ + "hook_event_type", + "hook_command", + "success", + "exit_code", + "kind" + ], + "title": "HookExecutionEvent", + "type": "object" + }, + "HookMatcher": { + "description": "Matches events to hooks based on patterns.\n\nSupports exact match, wildcard (*), and regex (auto-detected or /pattern/).", + "properties": { + "hooks": { + "items": { + "$ref": "#/components/schemas/HookDefinition" + }, + "title": "Hooks", + "type": "array" + }, + "matcher": { + "default": "*", + "title": "Matcher", + "type": "string" + } + }, + "title": "HookMatcher", + "type": "object" + }, + "HookType": { + "description": "Types of hooks that can be executed.", + "enum": [ + "command", + "prompt", + "agent" + ], + "title": "HookType", + "type": "string" + }, + "HooksRequest": { + "description": "Request body for loading hooks.", + "properties": { + "project_dir": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Workspace directory path for project hooks", + "title": "Project Dir" + } + }, + "title": "HooksRequest", + "type": "object" + }, + "HooksResponse": { + "description": "Response containing hooks configuration.", + "properties": { + "hook_config": { + "anyOf": [ + { + "$ref": "#/components/schemas/HookConfig" + }, + { + "type": "null" + } + ], + "description": "Hook configuration loaded from the workspace, or None if not found" + } + }, + "title": "HooksResponse", + "type": "object" + }, + "Icon": { + "additionalProperties": true, + "description": "An icon for display in user interfaces.", + "properties": { + "mimeType": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Mimetype" + }, + "sizes": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Sizes" + }, + "src": { + "title": "Src", + "type": "string" + } + }, + "required": [ + "src" + ], + "title": "Icon", + "type": "object" + }, + "ImageContent": { + "properties": { + "cache_prompt": { + "default": false, + "title": "Cache Prompt", + "type": "boolean" + }, + "image_urls": { + "items": { + "type": "string" + }, + "title": "Image Urls", + "type": "array" + }, + "type": { + "const": "image", + "default": "image", + "title": "Type", + "type": "string" + } + }, + "required": [ + "image_urls" + ], + "title": "ImageContent", + "type": "object" + }, + "InitRequest": { + "additionalProperties": false, + "description": "Runtime configuration delivered at /api/init time.\n\nEach field is optional and overrides the equivalent field on the dormant\n``Config``. Fields not provided keep the value the server was constructed\nwith (typically from env vars at pod startup). The set of overridable\nfields is intentionally narrow — it covers the values that today are\n\"env-var shaped\" and must change per-user, not image-build-time\nconfiguration (Python deps, plugin set, etc.) which stays bound to the\nwarm-pool flavor.", + "properties": { + "allow_cors_origins": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "CORS origins to add to the existing localhost allowlist.", + "title": "Allow Cors Origins" + }, + "bash_events_dir": { + "anyOf": [ + { + "format": "path", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Directory where bash events are persisted. Typically located inside the mounted user workspace.", + "title": "Bash Events Dir" + }, + "conversation_worktree_root": { + "anyOf": [ + { + "format": "path", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Root directory for conversation git worktrees. Override this to point at the mounted user workspace.", + "title": "Conversation Worktree Root" + }, + "conversations_path": { + "anyOf": [ + { + "format": "path", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Directory where conversations are persisted. Override this to point at the mounted user workspace.", + "title": "Conversations Path" + }, + "env": { + "anyOf": [ + { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "Process environment variables to set before conversation services start. Useful for credentials consumed by tools (e.g. GITHUB_TOKEN). These are applied with ``os.environ.update``; existing values are overwritten.", + "title": "Env" + }, + "max_concurrent_runs": { + "anyOf": [ + { + "minimum": 1.0, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Override the conversation-step concurrency limit.", + "title": "Max Concurrent Runs" + }, + "secret_key": { + "anyOf": [ + { + "format": "password", + "type": "string", + "writeOnly": true + }, + { + "type": "null" + } + ], + "description": "Symmetric secret used to encrypt persisted secrets. If not provided, falls back to the first session_api_key (matching the default Config behavior).", + "title": "Secret Key" + }, + "session_api_keys": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Per-user session API keys. If provided, all subsequent /api/* requests must authenticate with one of these keys via the X-Session-API-Key header.", + "title": "Session Api Keys" + }, + "telemetry": { + "anyOf": [ + { + "$ref": "#/components/schemas/TelemetrySpec" + }, + { + "type": "null" + } + ], + "description": "Product-analytics policy for this pod. Without this, a warm-pool pod keeps whatever mode it booted with (normally 'disabled'), so a deployment that expects telemetry must supply it here." + }, + "web_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "External URL where this server is reachable, used for root-path calculation. Only honored when not already set in dormant config.", + "title": "Web Url" + }, + "webhooks": { + "anyOf": [ + { + "items": { + "$ref": "#/components/schemas/WebhookSpec" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Per-user webhooks (e.g. for streaming events back).", + "title": "Webhooks" + } + }, + "title": "InitRequest", + "type": "object" + }, + "InitStatus": { + "properties": { + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "If a previous /api/init attempt failed, the error message. The state rolls back to ``dormant`` so /api/init can be retried.", + "title": "Error" + }, + "state": { + "description": "``dormant`` — server is up but waiting for /api/init. ``initializing`` — /api/init has been received and services are starting. ``ready`` — initialization complete; all /api/* routes are live.", + "enum": [ + "dormant", + "initializing", + "ready" + ], + "title": "State", + "type": "string" + } + }, + "required": [ + "state" + ], + "title": "InitStatus", + "type": "object" + }, + "InputMetadata": { + "description": "Metadata for task skill inputs.", + "properties": { + "description": { + "description": "Description of the input parameter", + "title": "Description", + "type": "string" + }, + "name": { + "description": "Name of the input parameter", + "title": "Name", + "type": "string" + } + }, + "required": [ + "name", + "description" + ], + "title": "InputMetadata", + "type": "object" + }, + "InstallCanvasExtensionRequest": { + "description": "Request body for installing a canvas extension.", + "properties": { + "force": { + "default": false, + "description": "If true, overwrite existing installation", + "title": "Force", + "type": "boolean" + }, + "ref": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Optional branch, tag, or commit to install", + "title": "Ref" + }, + "repo_path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Subdirectory path within the repository (for monorepos)", + "title": "Repo Path" + }, + "source": { + "description": "Canvas extension source - git URL, GitHub shorthand, or local path. Examples: 'github:owner/repo', '/path/to/extension'", + "minLength": 1, + "title": "Source", + "type": "string" + } + }, + "required": [ + "source" + ], + "title": "InstallCanvasExtensionRequest", + "type": "object" + }, + "InstallPluginRequest": { + "description": "Request body for installing a plugin.", + "properties": { + "force": { + "default": false, + "description": "If true, overwrite existing installation", + "title": "Force", + "type": "boolean" + }, + "ref": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Optional branch, tag, or commit to install", + "title": "Ref" + }, + "repo_path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Subdirectory path within the repository (for monorepos)", + "title": "Repo Path" + }, + "source": { + "description": "Plugin source - git URL, GitHub shorthand, or local path. Examples: 'github:OpenHands/extensions/plugins/city-weather', '/path/to/plugin'", + "minLength": 1, + "title": "Source", + "type": "string" + } + }, + "required": [ + "source" + ], + "title": "InstallPluginRequest", + "type": "object" + }, + "InstallSkillRequest": { + "description": "Request body for installing a skill.", + "properties": { + "force": { + "default": false, + "description": "If true, overwrite existing installation", + "title": "Force", + "type": "boolean" + }, + "ref": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Optional branch, tag, or commit to install", + "title": "Ref" + }, + "repo_path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Subdirectory path within the repository (for monorepos)", + "title": "Repo Path" + }, + "source": { + "description": "Skill source - git URL, GitHub shorthand, or local path. Examples: 'https://github.com/OpenHands/extensions/tree/main/skills/github', 'github:OpenHands/extensions/skills/github', '/path/to/skill'", + "minLength": 1, + "title": "Source", + "type": "string" + } + }, + "required": [ + "source" + ], + "title": "InstallSkillRequest", + "type": "object" + }, + "InstalledCanvasExtensionResponse": { + "description": "Response containing installed canvas extension information.", + "properties": { + "description": { + "default": "", + "description": "Canvas extension description", + "title": "Description", + "type": "string" + }, + "enabled": { + "default": false, + "description": "Whether the canvas extension is enabled", + "title": "Enabled", + "type": "boolean" + }, + "install_path": { + "description": "Path where the extension is installed", + "title": "Install Path", + "type": "string" + }, + "installed_at": { + "description": "ISO 8601 timestamp of installation", + "title": "Installed At", + "type": "string" + }, + "manifest": { + "anyOf": [ + { + "$ref": "#/components/schemas/CanvasExtensionManifest" + }, + { + "type": "null" + } + ], + "description": "The extension's validated manifest (display_name, contributes.pages, ...). None if the installed manifest can no longer be read." + }, + "name": { + "description": "Canvas extension name", + "title": "Name", + "type": "string" + }, + "repo_path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Subdirectory path within the repository", + "title": "Repo Path" + }, + "resolved_ref": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Resolved git commit SHA", + "title": "Resolved Ref" + }, + "source": { + "description": "Original source (e.g., 'github:owner/repo')", + "title": "Source", + "type": "string" + }, + "version": { + "default": "", + "description": "Canvas extension version", + "title": "Version", + "type": "string" + } + }, + "required": [ + "name", + "source", + "installed_at", + "install_path" + ], + "title": "InstalledCanvasExtensionResponse", + "type": "object" + }, + "InstalledCanvasExtensionsListResponse": { + "description": "Response containing the list of installed canvas extensions.", + "properties": { + "canvas_extensions": { + "items": { + "$ref": "#/components/schemas/InstalledCanvasExtensionResponse" + }, + "title": "Canvas Extensions", + "type": "array" + } + }, + "required": [ + "canvas_extensions" + ], + "title": "InstalledCanvasExtensionsListResponse", + "type": "object" + }, + "InstalledPluginResponse": { + "description": "Response containing installed plugin information.", + "properties": { + "description": { + "default": "", + "description": "Plugin description", + "title": "Description", + "type": "string" + }, + "enabled": { + "default": true, + "description": "Whether the plugin is enabled", + "title": "Enabled", + "type": "boolean" + }, + "files": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Plugin files, relative to install_path (None if load failed)", + "title": "Files" + }, + "install_path": { + "description": "Path where the plugin is installed", + "title": "Install Path", + "type": "string" + }, + "installed_at": { + "description": "ISO 8601 timestamp of installation", + "title": "Installed At", + "type": "string" + }, + "name": { + "description": "Plugin name", + "title": "Name", + "type": "string" + }, + "repo_path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Subdirectory path within the repository", + "title": "Repo Path" + }, + "resolved_ref": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Resolved git commit SHA", + "title": "Resolved Ref" + }, + "skills": { + "anyOf": [ + { + "items": { + "$ref": "#/components/schemas/PluginSkillSummary" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Skills bundled in the plugin (None if it failed to load)", + "title": "Skills" + }, + "source": { + "description": "Original source (e.g., 'github:owner/repo')", + "title": "Source", + "type": "string" + }, + "version": { + "default": "", + "description": "Plugin version", + "title": "Version", + "type": "string" + } + }, + "required": [ + "name", + "source", + "installed_at", + "install_path" + ], + "title": "InstalledPluginResponse", + "type": "object" + }, + "InstalledPluginsListResponse": { + "description": "Response containing the list of installed plugins.", + "properties": { + "plugins": { + "items": { + "$ref": "#/components/schemas/InstalledPluginResponse" + }, + "title": "Plugins", + "type": "array" + } + }, + "required": [ + "plugins" + ], + "title": "InstalledPluginsListResponse", + "type": "object" + }, + "InstalledSkillResponse": { + "description": "Response containing installed skill information.", + "properties": { + "description": { + "default": "", + "description": "Skill description", + "title": "Description", + "type": "string" + }, + "enabled": { + "default": true, + "description": "Whether the skill is enabled", + "title": "Enabled", + "type": "boolean" + }, + "install_path": { + "description": "Path where the skill is installed", + "title": "Install Path", + "type": "string" + }, + "installed_at": { + "description": "ISO 8601 timestamp of installation", + "title": "Installed At", + "type": "string" + }, + "name": { + "description": "Skill name", + "title": "Name", + "type": "string" + }, + "repo_path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Subdirectory path within the repository", + "title": "Repo Path" + }, + "resolved_ref": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Resolved git commit SHA", + "title": "Resolved Ref" + }, + "source": { + "description": "Original source (e.g., 'github:owner/repo')", + "title": "Source", + "type": "string" + }, + "version": { + "default": "", + "description": "Skill version", + "title": "Version", + "type": "string" + } + }, + "required": [ + "name", + "source", + "installed_at", + "install_path" + ], + "title": "InstalledSkillResponse", + "type": "object" + }, + "InstalledSkillsListResponse": { + "description": "Response containing list of installed skills.", + "properties": { + "skills": { + "items": { + "$ref": "#/components/schemas/InstalledSkillResponse" + }, + "title": "Skills", + "type": "array" + } + }, + "required": [ + "skills" + ], + "title": "InstalledSkillsListResponse", + "type": "object" + }, + "InterruptEvent": { + "additionalProperties": false, + "description": "Event indicating the agent was interrupted mid-operation.\n\nUnlike :class:`PauseEvent` which takes effect between agent steps,\nan interrupt cancels the in-flight LLM call immediately. The\nconversation state is set to PAUSED so it can be resumed later.", + "properties": { + "id": { + "description": "Unique event id (ULID/UUID)", + "title": "Id", + "type": "string" + }, + "kind": { + "const": "InterruptEvent", + "title": "Kind", + "type": "string" + }, + "parent_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Parent event id in the conversation tree. None for the root, or for legacy events predating the tree (see EventLog's effective-parent rule). Events sharing a parent_id are sibling branches.", + "title": "Parent Id" + }, + "source": { + "default": "user", + "enum": [ + "agent", + "user", + "environment", + "hook" + ], + "title": "Source", + "type": "string" + }, + "timestamp": { + "description": "Event timestamp", + "title": "Timestamp", + "type": "string" + } + }, + "required": [ + "kind" + ], + "title": "InterruptEvent", + "type": "object" + }, + "InvokeSkillAction": { + "additionalProperties": false, + "properties": { + "kind": { + "const": "InvokeSkillAction", + "title": "Kind", + "type": "string" + }, + "name": { + "description": "Name of the loaded skill to invoke.", + "title": "Name", + "type": "string" + } + }, + "required": [ + "name", + "kind" + ], + "title": "InvokeSkillAction", + "type": "object" + }, + "InvokeSkillObservation": { + "additionalProperties": false, + "properties": { + "content": { + "description": "Content returned from the tool as a list of TextContent/ImageContent objects. When there is an error, it should be written in this field.", + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/TextContent" + }, + { + "$ref": "#/components/schemas/ImageContent" + } + ] + }, + "title": "Content", + "type": "array" + }, + "is_error": { + "default": false, + "description": "Whether the observation indicates an error", + "title": "Is Error", + "type": "boolean" + }, + "kind": { + "const": "InvokeSkillObservation", + "title": "Kind", + "type": "string" + }, + "skill_name": { + "description": "Name of the skill this observation corresponds to.", + "title": "Skill Name", + "type": "string" + } + }, + "required": [ + "skill_name", + "kind" + ], + "title": "InvokeSkillObservation", + "type": "object" + }, + "InvokeSkillTool": { + "description": "Built-in tool for explicit invocation of progressive-disclosure skills.", + "properties": { + "action_type": { + "title": "Action Type", + "type": "string" + }, + "annotations": { + "anyOf": [ + { + "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" + }, + { + "type": "null" + } + ] + }, + "description": { + "title": "Description", + "type": "string" + }, + "kind": { + "const": "InvokeSkillTool", + "title": "Kind", + "type": "string" + }, + "meta": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Meta" + }, + "observation_type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Observation Type" + }, + "title": { + "readOnly": true, + "title": "Title", + "type": "string" + } + }, + "required": [ + "description", + "action_type", + "kind", + "title" + ], + "title": "InvokeSkillTool", + "type": "object" + }, + "IterativeRefinementConfig": { + "description": "Configuration for iterative refinement based on critic feedback.\n\nWhen attached to a CriticBase, the Conversation.run() method will\nautomatically retry the task if the critic score is below the threshold.\n\nExample:\n critic = APIBasedCritic(\n server_url=\"...\",\n api_key=\"...\",\n model_name=\"critic\",\n iterative_refinement=IterativeRefinementConfig(\n success_threshold=0.7,\n max_iterations=3,\n ),\n )\n agent = Agent(llm=llm, tools=tools, critic=critic)\n conversation = Conversation(agent=agent, workspace=workspace)\n conversation.send_message(\"Create a calculator module...\")\n conversation.run() # Will automatically retry if critic score < 0.7", + "properties": { + "max_iterations": { + "default": 3, + "description": "Maximum number of iterations before giving up.", + "minimum": 1.0, + "title": "Max Iterations", + "type": "integer" + }, + "success_threshold": { + "default": 0.6, + "description": "Score threshold (0-1) to consider task successful.", + "maximum": 1.0, + "minimum": 0.0, + "title": "Success Threshold", + "type": "number" + } + }, + "title": "IterativeRefinementConfig", + "type": "object" + }, + "KeywordTrigger": { + "description": "Trigger for keyword-based skills.\n\nThese skills are activated when specific keywords appear in the user's query.", + "properties": { + "keywords": { + "items": { + "type": "string" + }, + "title": "Keywords", + "type": "array" + }, + "type": { + "const": "keyword", + "default": "keyword", + "title": "Type", + "type": "string" + } + }, + "required": [ + "keywords" + ], + "title": "KeywordTrigger", + "type": "object" + }, + "LLM-Input": { + "description": "Language model interface for OpenHands agents.\n\nThe LLM class provides a unified interface for interacting with various\nlanguage models through the litellm library. It handles model configuration,\nAPI authentication, retry logic, and tool calling capabilities.\n\nAttributes:\n model: Model name (e.g., \"gpt-5.6\").\n api_key: API key for authentication.\n base_url: Custom API base URL.\n num_retries: Number of retry attempts for failed requests.\n timeout: Request timeout in seconds.\n\nExample:\n ```python\n from openhands.sdk import LLM\n from pydantic import SecretStr\n\n llm = LLM(\n model=\"gpt-5.6\",\n api_key=SecretStr(\"your-api-key\"),\n usage_id=\"my-agent\"\n )\n # Use with agent or conversation\n ```", + "properties": { + "api_key": { + "anyOf": [ + { + "type": "string" + }, + { + "format": "password", + "type": "string", + "writeOnly": true + }, + { + "type": "null" + } + ], + "description": "API key.", + "openhands_settings": { + "depends_on": [], + "label": "API Key", + "prominence": "critical" + }, + "title": "Api Key" + }, + "api_mode": { + "default": "auto", + "description": "LLM API endpoint mode. 'auto' resolves from model metadata and SDK fallbacks; use 'chat' or 'responses' to override endpoint selection for proxy aliases and newly released models.", + "enum": [ + "auto", + "chat", + "responses" + ], + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Api Mode", + "type": "string" + }, + "api_version": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "API version (e.g., Azure).", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Api Version" + }, + "auth_type": { + "default": "api_key", + "description": "Authentication mode for the LLM.", + "enum": [ + "api_key", + "subscription" + ], + "openhands_settings": { + "depends_on": [], + "label": "Authentication", + "prominence": "critical" + }, + "title": "Auth Type", + "type": "string" + }, + "aws_access_key_id": { + "anyOf": [ + { + "type": "string" + }, + { + "format": "password", + "type": "string", + "writeOnly": true + }, + { + "type": "null" + } + ], + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Aws Access Key Id" + }, + "aws_bedrock_runtime_endpoint": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Aws Bedrock Runtime Endpoint" + }, + "aws_profile_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Aws Profile Name" + }, + "aws_region_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Aws Region Name" + }, + "aws_role_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Aws Role Name" + }, + "aws_secret_access_key": { + "anyOf": [ + { + "type": "string" + }, + { + "format": "password", + "type": "string", + "writeOnly": true + }, + { + "type": "null" + } + ], + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Aws Secret Access Key" + }, + "aws_session_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Aws Session Name" + }, + "aws_session_token": { + "anyOf": [ + { + "type": "string" + }, + { + "format": "password", + "type": "string", + "writeOnly": true + }, + { + "type": "null" + } + ], + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Aws Session Token" + }, + "base_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Custom base URL.", + "openhands_settings": { + "depends_on": [], + "prominence": "major" + }, + "title": "Base Url" + }, + "caching_prompt": { + "default": true, + "description": "Enable caching of prompts.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Caching Prompt", + "type": "boolean" + }, + "capability_overrides": { + "additionalProperties": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + } + ] + }, + "description": "Explicit model capability overrides. Supported keys include supports_reasoning_effort, thinking_mode (adaptive, manual, none, or unknown), supports_sampling_params, supports_prompt_cache, supports_stop_words, supports_responses_api, supports_vision, and supports_prompt_cache_retention. Overrides take precedence over LiteLLM metadata and SDK fallbacks.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Capability Overrides", + "type": "object" + }, + "custom_tokenizer": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "A custom tokenizer to use for token counting.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Custom Tokenizer" + }, + "disable_stop_word": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": false, + "description": "Disable using of stop word.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Disable Stop Word" + }, + "disable_vision": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "If model is vision capable, this option allows to disable image processing (useful for cost reduction).", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Disable Vision" + }, + "drop_params": { + "default": true, + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Drop Params", + "type": "boolean" + }, + "enable_encrypted_reasoning": { + "default": true, + "description": "If True, ask for ['reasoning.encrypted_content'] in Responses API include.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Enable Encrypted Reasoning", + "type": "boolean" + }, + "extended_thinking_budget": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": 200000, + "description": "Legacy token budget for models confirmed to use manual Anthropic extended thinking. Ignored for adaptive-thinking models. Prefer reasoning_effort for new integrations.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Extended Thinking Budget" + }, + "extra_headers": { + "anyOf": [ + { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "Optional HTTP headers to forward to LiteLLM requests.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Extra Headers" + }, + "fallback_strategy": { + "anyOf": [ + { + "$ref": "#/components/schemas/FallbackStrategy" + }, + { + "type": "null" + } + ], + "description": "Optional fallback strategy for trying alternate LLMs on transient failure. Construct with FallbackStrategy(fallback_llms=[...]).Excluded from serialization; must be reconfigured after load." + }, + "force_string_serializer": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Force using string content serializer when sending to LLM API. If None (default), auto-detect based on model. Useful for providers that do not support list content, like HuggingFace and Groq.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Force String Serializer" + }, + "inline_image_urls": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "If True, fetch any http(s) image URL in outgoing messages and inline it as a base64 ``data:`` URL before sending. If None (default), auto-detect based on model (some APIs such as Moonshot's public Kimi endpoint reject URL-formatted images and require base64). Set this explicitly when the model is reached through a proxy alias that hides the underlying provider (e.g. ``litellm_proxy/``). Note: inlining only runs when ``vision_is_active()`` is True, so the alias must still be recognised as vision-capable by the SDK feature registry or proxy model metadata.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Inline Image Urls" + }, + "input_cost_per_token": { + "anyOf": [ + { + "minimum": 0.0, + "type": "number" + }, + { + "type": "null" + } + ], + "description": "The cost per input token. This will available in logs for user.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Input Cost Per Token" + }, + "litellm_extra_body": { + "additionalProperties": true, + "description": "Additional key-value pairs to pass to litellm's extra_body parameter. This is useful for custom inference endpoints that need additional parameters for configuration, routing, or advanced features. NOTE: Not all LLM providers support extra_body parameters. Some providers (e.g., OpenAI) may reject requests with unrecognized options. This is commonly supported by: - LiteLLM proxy servers (routing metadata, tracing) - vLLM endpoints (return_token_ids, etc.) - Custom inference clusters Examples: - Proxy routing: {'trace_version': '1.0.0', 'tags': ['agent:my-agent']} - vLLM features: {'return_token_ids': True}", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Litellm Extra Body", + "type": "object" + }, + "log_completions": { + "default": false, + "description": "Enable logging of completions.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Log Completions", + "type": "boolean" + }, + "log_completions_folder": { + "default": "logs/completions", + "description": "The folder to log LLM completions to. Required if log_completions is True.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Log Completions Folder", + "type": "string" + }, + "max_input_tokens": { + "anyOf": [ + { + "minimum": 1.0, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The maximum number of input tokens. Note that this is currently unused, and the value at runtime is actually the total tokens in OpenAI (e.g. 128,000 tokens for GPT-4).", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Max Input Tokens" + }, + "max_message_chars": { + "default": 30000, + "description": "Approx max chars in each event/content sent to the LLM.", + "minimum": 1.0, + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Max Message Chars", + "type": "integer" + }, + "max_output_tokens": { + "anyOf": [ + { + "minimum": 1.0, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The maximum number of output tokens. This is sent to the LLM.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Max Output Tokens" + }, + "model": { + "default": "gpt-5.6", + "description": "Model name.", + "openhands_settings": { + "depends_on": [], + "prominence": "critical" + }, + "title": "Model", + "type": "string" + }, + "model_canonical_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Optional canonical model name for feature registry lookups. The OpenHands SDK maintains a model feature registry that maps model names to capabilities (e.g., vision support, prompt caching, responses API support). When using proxied or aliased model identifiers, set this field to the canonical model name (e.g., 'openai/gpt-4o') to ensure correct capability detection. If not provided, the 'model' field will be used for capability lookups.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Model Canonical Name" + }, + "native_tool_calling": { + "default": true, + "description": "Whether to use native tool calling.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Native Tool Calling", + "type": "boolean" + }, + "num_retries": { + "default": 5, + "minimum": 0.0, + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Num Retries", + "type": "integer" + }, + "ollama_base_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Ollama Base Url" + }, + "openrouter_app_name": { + "default": "OpenHands", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Openrouter App Name", + "type": "string" + }, + "openrouter_site_url": { + "default": "https://docs.all-hands.dev/", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Openrouter Site Url", + "type": "string" + }, + "output_cost_per_token": { + "anyOf": [ + { + "minimum": 0.0, + "type": "number" + }, + { + "type": "null" + } + ], + "description": "The cost per output token. This will available in logs for user.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Output Cost Per Token" + }, + "prompt_cache_retention": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": "24h", + "description": "Retention policy for prompt cache. Only sent for supported models (GPT-5+ and GPT-4.1, excluding Azure deployments); explicitly stripped for all others.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Prompt Cache Retention" + }, + "provider_connection_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Optional provider connection whose shared API key and base URL are resolved and applied each time this LLM profile is loaded (read-at-use). When set, the profile stores no inline api_key or base_url of its own.", + "openhands_settings": { + "depends_on": [], + "prominence": "major" + }, + "title": "Provider Connection Id" + }, + "reasoning_effort": { + "anyOf": [ + { + "enum": [ + "low", + "medium", + "high", + "xhigh", + "none" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "default": "high", + "description": "Provider-neutral reasoning effort. Common values include 'none', 'minimal', 'low', 'medium', 'high', 'xhigh', and 'max'. The SDK accepts future provider values and lets LiteLLM translate them.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Reasoning Effort" + }, + "reasoning_summary": { + "anyOf": [ + { + "enum": [ + "auto", + "concise", + "detailed" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The level of detail for reasoning summaries. This is a string that can be one of 'auto', 'concise', or 'detailed'. Requires verified OpenAI organization. Only sent when explicitly set.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Reasoning Summary" + }, + "retry_max_wait": { + "default": 64, + "minimum": 0.0, + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Retry Max Wait", + "type": "integer" + }, + "retry_min_wait": { + "default": 8, + "minimum": 0.0, + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Retry Min Wait", + "type": "integer" + }, + "retry_multiplier": { + "default": 8.0, + "minimum": 0.0, + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Retry Multiplier", + "type": "number" + }, + "seed": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The seed to use for random number generation.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Seed" + }, + "stream": { + "default": false, + "description": "Enable streaming responses from the LLM. When enabled, the provided `on_token` callback in .completions and .responses will be invoked for each chunk of tokens.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Stream", + "type": "boolean" + }, + "stream_idle_timeout": { + "anyOf": [ + { + "minimum": 0.0, + "type": "number" + }, + { + "type": "null" + } + ], + "default": 300, + "description": "Maximum seconds between chunks in an asynchronous streaming response. Default is 300s (5 minutes); set to None to disable.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Stream Idle Timeout" + }, + "subscription_vendor": { + "anyOf": [ + { + "const": "openai", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Subscription provider for subscription-backed LLM access.", + "openhands_settings": { + "depends_on": [ + "auth_type" + ], + "label": "Subscription provider", + "prominence": "critical" + }, + "title": "Subscription Vendor" + }, + "temperature": { + "anyOf": [ + { + "minimum": 0.0, + "type": "number" + }, + { + "type": "null" + } + ], + "description": "Sampling temperature for response generation. Defaults to None (uses provider default temperature). Set to 0.0 for deterministic outputs, or higher values (0.7-1.0) for more creative responses.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Temperature" + }, + "timeout": { + "anyOf": [ + { + "minimum": 0.0, + "type": "integer" + }, + { + "type": "null" + } + ], + "default": 300, + "description": "HTTP and hard per-attempt timeout in seconds. Default is 300s (5 minutes). Set to None to disable the hard timeout.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Timeout" + }, + "top_k": { + "anyOf": [ + { + "minimum": 0.0, + "type": "number" + }, + { + "type": "null" + } + ], + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Top K" + }, + "top_p": { + "anyOf": [ + { + "maximum": 1.0, + "minimum": 0.0, + "type": "number" + }, + { + "type": "null" + } + ], + "description": "Nucleus sampling parameter. Defaults to None (uses provider default). Set to a value between 0 and 1 to control diversity of outputs.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Top P" + }, + "usage_id": { + "default": "default", + "description": "Unique usage identifier for the LLM. Used for registry lookups, telemetry, and spend tracking.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Usage Id", + "type": "string" + } + }, + "title": "LLM", + "type": "object" + }, + "LLM-Output": { + "description": "Language model interface for OpenHands agents.\n\nThe LLM class provides a unified interface for interacting with various\nlanguage models through the litellm library. It handles model configuration,\nAPI authentication, retry logic, and tool calling capabilities.\n\nAttributes:\n model: Model name (e.g., \"gpt-5.6\").\n api_key: API key for authentication.\n base_url: Custom API base URL.\n num_retries: Number of retry attempts for failed requests.\n timeout: Request timeout in seconds.\n\nExample:\n ```python\n from openhands.sdk import LLM\n from pydantic import SecretStr\n\n llm = LLM(\n model=\"gpt-5.6\",\n api_key=SecretStr(\"your-api-key\"),\n usage_id=\"my-agent\"\n )\n # Use with agent or conversation\n ```", + "properties": { + "api_key": { + "anyOf": [ + { + "type": "string" + }, + { + "format": "password", + "type": "string", + "writeOnly": true + }, + { + "type": "null" + } + ], + "description": "API key.", + "openhands_settings": { + "depends_on": [], + "label": "API Key", + "prominence": "critical" + }, + "title": "Api Key" + }, + "api_mode": { + "default": "auto", + "description": "LLM API endpoint mode. 'auto' resolves from model metadata and SDK fallbacks; use 'chat' or 'responses' to override endpoint selection for proxy aliases and newly released models.", + "enum": [ + "auto", + "chat", + "responses" + ], + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Api Mode", + "type": "string" + }, + "api_version": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "API version (e.g., Azure).", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Api Version" + }, + "auth_type": { + "default": "api_key", + "description": "Authentication mode for the LLM.", + "enum": [ + "api_key", + "subscription" + ], + "openhands_settings": { + "depends_on": [], + "label": "Authentication", + "prominence": "critical" + }, + "title": "Auth Type", + "type": "string" + }, + "aws_access_key_id": { + "anyOf": [ + { + "type": "string" + }, + { + "format": "password", + "type": "string", + "writeOnly": true + }, + { + "type": "null" + } + ], + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Aws Access Key Id" + }, + "aws_bedrock_runtime_endpoint": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Aws Bedrock Runtime Endpoint" + }, + "aws_profile_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Aws Profile Name" + }, + "aws_region_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Aws Region Name" + }, + "aws_role_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Aws Role Name" + }, + "aws_secret_access_key": { + "anyOf": [ + { + "type": "string" + }, + { + "format": "password", + "type": "string", + "writeOnly": true + }, + { + "type": "null" + } + ], + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Aws Secret Access Key" + }, + "aws_session_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Aws Session Name" + }, + "aws_session_token": { + "anyOf": [ + { + "type": "string" + }, + { + "format": "password", + "type": "string", + "writeOnly": true + }, + { + "type": "null" + } + ], + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Aws Session Token" + }, + "base_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Custom base URL.", + "openhands_settings": { + "depends_on": [], + "prominence": "major" + }, + "title": "Base Url" + }, + "caching_prompt": { + "default": true, + "description": "Enable caching of prompts.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Caching Prompt", + "type": "boolean" + }, + "capability_overrides": { + "additionalProperties": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + } + ] + }, + "description": "Explicit model capability overrides. Supported keys include supports_reasoning_effort, thinking_mode (adaptive, manual, none, or unknown), supports_sampling_params, supports_prompt_cache, supports_stop_words, supports_responses_api, supports_vision, and supports_prompt_cache_retention. Overrides take precedence over LiteLLM metadata and SDK fallbacks.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Capability Overrides", + "type": "object" + }, + "custom_tokenizer": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "A custom tokenizer to use for token counting.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Custom Tokenizer" + }, + "disable_stop_word": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": false, + "description": "Disable using of stop word.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Disable Stop Word" + }, + "disable_vision": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "If model is vision capable, this option allows to disable image processing (useful for cost reduction).", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Disable Vision" + }, + "drop_params": { + "default": true, + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Drop Params", + "type": "boolean" + }, + "enable_encrypted_reasoning": { + "default": true, + "description": "If True, ask for ['reasoning.encrypted_content'] in Responses API include.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Enable Encrypted Reasoning", + "type": "boolean" + }, + "extended_thinking_budget": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": 200000, + "description": "Legacy token budget for models confirmed to use manual Anthropic extended thinking. Ignored for adaptive-thinking models. Prefer reasoning_effort for new integrations.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Extended Thinking Budget" + }, + "extra_headers": { + "anyOf": [ + { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "Optional HTTP headers to forward to LiteLLM requests.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Extra Headers" + }, + "force_string_serializer": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Force using string content serializer when sending to LLM API. If None (default), auto-detect based on model. Useful for providers that do not support list content, like HuggingFace and Groq.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Force String Serializer" + }, + "inline_image_urls": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "If True, fetch any http(s) image URL in outgoing messages and inline it as a base64 ``data:`` URL before sending. If None (default), auto-detect based on model (some APIs such as Moonshot's public Kimi endpoint reject URL-formatted images and require base64). Set this explicitly when the model is reached through a proxy alias that hides the underlying provider (e.g. ``litellm_proxy/``). Note: inlining only runs when ``vision_is_active()`` is True, so the alias must still be recognised as vision-capable by the SDK feature registry or proxy model metadata.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Inline Image Urls" + }, + "input_cost_per_token": { + "anyOf": [ + { + "minimum": 0.0, + "type": "number" + }, + { + "type": "null" + } + ], + "description": "The cost per input token. This will available in logs for user.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Input Cost Per Token" + }, + "is_subscription": { + "description": "Whether this LLM uses subscription-based authentication. Serialized so that subscription-specific request handling survives transport to a remote agent-server.", + "readOnly": true, + "title": "Is Subscription", + "type": "boolean" + }, + "litellm_extra_body": { + "additionalProperties": true, + "description": "Additional key-value pairs to pass to litellm's extra_body parameter. This is useful for custom inference endpoints that need additional parameters for configuration, routing, or advanced features. NOTE: Not all LLM providers support extra_body parameters. Some providers (e.g., OpenAI) may reject requests with unrecognized options. This is commonly supported by: - LiteLLM proxy servers (routing metadata, tracing) - vLLM endpoints (return_token_ids, etc.) - Custom inference clusters Examples: - Proxy routing: {'trace_version': '1.0.0', 'tags': ['agent:my-agent']} - vLLM features: {'return_token_ids': True}", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Litellm Extra Body", + "type": "object" + }, + "log_completions": { + "default": false, + "description": "Enable logging of completions.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Log Completions", + "type": "boolean" + }, + "log_completions_folder": { + "default": "logs/completions", + "description": "The folder to log LLM completions to. Required if log_completions is True.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Log Completions Folder", + "type": "string" + }, + "max_input_tokens": { + "anyOf": [ + { + "minimum": 1.0, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The maximum number of input tokens. Note that this is currently unused, and the value at runtime is actually the total tokens in OpenAI (e.g. 128,000 tokens for GPT-4).", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Max Input Tokens" + }, + "max_message_chars": { + "default": 30000, + "description": "Approx max chars in each event/content sent to the LLM.", + "minimum": 1.0, + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Max Message Chars", + "type": "integer" + }, + "max_output_tokens": { + "anyOf": [ + { + "minimum": 1.0, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The maximum number of output tokens. This is sent to the LLM.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Max Output Tokens" + }, + "model": { + "default": "gpt-5.6", + "description": "Model name.", + "openhands_settings": { + "depends_on": [], + "prominence": "critical" + }, + "title": "Model", + "type": "string" + }, + "model_canonical_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Optional canonical model name for feature registry lookups. The OpenHands SDK maintains a model feature registry that maps model names to capabilities (e.g., vision support, prompt caching, responses API support). When using proxied or aliased model identifiers, set this field to the canonical model name (e.g., 'openai/gpt-4o') to ensure correct capability detection. If not provided, the 'model' field will be used for capability lookups.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Model Canonical Name" + }, + "native_tool_calling": { + "default": true, + "description": "Whether to use native tool calling.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Native Tool Calling", + "type": "boolean" + }, + "num_retries": { + "default": 5, + "minimum": 0.0, + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Num Retries", + "type": "integer" + }, + "ollama_base_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Ollama Base Url" + }, + "openrouter_app_name": { + "default": "OpenHands", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Openrouter App Name", + "type": "string" + }, + "openrouter_site_url": { + "default": "https://docs.all-hands.dev/", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Openrouter Site Url", + "type": "string" + }, + "output_cost_per_token": { + "anyOf": [ + { + "minimum": 0.0, + "type": "number" + }, + { + "type": "null" + } + ], + "description": "The cost per output token. This will available in logs for user.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Output Cost Per Token" + }, + "prompt_cache_retention": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": "24h", + "description": "Retention policy for prompt cache. Only sent for supported models (GPT-5+ and GPT-4.1, excluding Azure deployments); explicitly stripped for all others.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Prompt Cache Retention" + }, + "provider_connection_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Optional provider connection whose shared API key and base URL are resolved and applied each time this LLM profile is loaded (read-at-use). When set, the profile stores no inline api_key or base_url of its own.", + "openhands_settings": { + "depends_on": [], + "prominence": "major" + }, + "title": "Provider Connection Id" + }, + "reasoning_effort": { + "anyOf": [ + { + "enum": [ + "low", + "medium", + "high", + "xhigh", + "none" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "default": "high", + "description": "Provider-neutral reasoning effort. Common values include 'none', 'minimal', 'low', 'medium', 'high', 'xhigh', and 'max'. The SDK accepts future provider values and lets LiteLLM translate them.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Reasoning Effort" + }, + "reasoning_summary": { + "anyOf": [ + { + "enum": [ + "auto", + "concise", + "detailed" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The level of detail for reasoning summaries. This is a string that can be one of 'auto', 'concise', or 'detailed'. Requires verified OpenAI organization. Only sent when explicitly set.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Reasoning Summary" + }, + "retry_max_wait": { + "default": 64, + "minimum": 0.0, + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Retry Max Wait", + "type": "integer" + }, + "retry_min_wait": { + "default": 8, + "minimum": 0.0, + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Retry Min Wait", + "type": "integer" + }, + "retry_multiplier": { + "default": 8.0, + "minimum": 0.0, + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Retry Multiplier", + "type": "number" + }, + "seed": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The seed to use for random number generation.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Seed" + }, + "stream": { + "default": false, + "description": "Enable streaming responses from the LLM. When enabled, the provided `on_token` callback in .completions and .responses will be invoked for each chunk of tokens.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Stream", + "type": "boolean" + }, + "stream_idle_timeout": { + "anyOf": [ + { + "minimum": 0.0, + "type": "number" + }, + { + "type": "null" + } + ], + "default": 300, + "description": "Maximum seconds between chunks in an asynchronous streaming response. Default is 300s (5 minutes); set to None to disable.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Stream Idle Timeout" + }, + "subscription_vendor": { + "anyOf": [ + { + "const": "openai", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Subscription provider for subscription-backed LLM access.", + "openhands_settings": { + "depends_on": [ + "auth_type" + ], + "label": "Subscription provider", + "prominence": "critical" + }, + "title": "Subscription Vendor" + }, + "temperature": { + "anyOf": [ + { + "minimum": 0.0, + "type": "number" + }, + { + "type": "null" + } + ], + "description": "Sampling temperature for response generation. Defaults to None (uses provider default temperature). Set to 0.0 for deterministic outputs, or higher values (0.7-1.0) for more creative responses.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Temperature" + }, + "timeout": { + "anyOf": [ + { + "minimum": 0.0, + "type": "integer" + }, + { + "type": "null" + } + ], + "default": 300, + "description": "HTTP and hard per-attempt timeout in seconds. Default is 300s (5 minutes). Set to None to disable the hard timeout.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Timeout" + }, + "top_k": { + "anyOf": [ + { + "minimum": 0.0, + "type": "number" + }, + { + "type": "null" + } + ], + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Top K" + }, + "top_p": { + "anyOf": [ + { + "maximum": 1.0, + "minimum": 0.0, + "type": "number" + }, + { + "type": "null" + } + ], + "description": "Nucleus sampling parameter. Defaults to None (uses provider default). Set to a value between 0 and 1 to control diversity of outputs.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Top P" + }, + "usage_id": { + "default": "default", + "description": "Unique usage identifier for the LLM. Used for registry lookups, telemetry, and spend tracking.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Usage Id", + "type": "string" + } + }, + "required": [ + "is_subscription" + ], + "title": "LLM", + "type": "object" + }, + "LLMCompletionLogEvent": { + "additionalProperties": false, + "description": "Event containing LLM completion log data.\n\nWhen an LLM is configured with log_completions=True in a remote conversation,\nthis event streams the completion log data back to the client through WebSocket\ninstead of writing it to a file inside the Docker container.", + "properties": { + "filename": { + "description": "The intended filename for this log (relative to log directory)", + "title": "Filename", + "type": "string" + }, + "id": { + "description": "Unique event id (ULID/UUID)", + "title": "Id", + "type": "string" + }, + "kind": { + "const": "LLMCompletionLogEvent", + "title": "Kind", + "type": "string" + }, + "log_data": { + "description": "The JSON-encoded log data to be written to the file", + "title": "Log Data", + "type": "string" + }, + "model_name": { + "default": "unknown", + "description": "The model name for context", + "title": "Model Name", + "type": "string" + }, + "parent_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Parent event id in the conversation tree. None for the root, or for legacy events predating the tree (see EventLog's effective-parent rule). Events sharing a parent_id are sibling branches.", + "title": "Parent Id" + }, + "source": { + "default": "environment", + "enum": [ + "agent", + "user", + "environment", + "hook" + ], + "title": "Source", + "type": "string" + }, + "timestamp": { + "description": "Event timestamp", + "title": "Timestamp", + "type": "string" + }, + "usage_id": { + "default": "default", + "description": "The LLM usage_id that produced this log", + "title": "Usage Id", + "type": "string" + } + }, + "required": [ + "filename", + "log_data", + "kind" + ], + "title": "LLMCompletionLogEvent", + "type": "object" + }, + "LLMSecurityAnalyzer-Input": { + "description": "LLM-based security analyzer.\n\nThis analyzer respects the security_risk attribute that can be set by the LLM\nwhen generating actions, similar to OpenHands' LLMRiskAnalyzer.\n\nIt provides a lightweight security analysis approach that leverages the LLM's\nunderstanding of action context and potential risks.", + "properties": { + "kind": { + "const": "LLMSecurityAnalyzer", + "title": "Kind", + "type": "string" + } + }, + "title": "LLMSecurityAnalyzer", + "type": "object" + }, + "LLMSecurityAnalyzer-Output": { + "description": "LLM-based security analyzer.\n\nThis analyzer respects the security_risk attribute that can be set by the LLM\nwhen generating actions, similar to OpenHands' LLMRiskAnalyzer.\n\nIt provides a lightweight security analysis approach that leverages the LLM's\nunderstanding of action context and potential risks.", + "properties": { + "kind": { + "const": "LLMSecurityAnalyzer", + "title": "Kind", + "type": "string" + } + }, + "required": [ + "kind" + ], + "title": "LLMSecurityAnalyzer", + "type": "object" + }, + "LLMSummarizingCondenser-Input": { + "description": "LLM-based condenser that summarizes forgotten events.\n\nUses an independent LLM (stored in the `llm` attribute) for generating summaries\nof forgotten events. The optional `agent_llm` parameter passed to condense() is\nthe LLM used by the agent for token counting purposes, and you should not assume\nit is the same as the one defined in this condenser.", + "properties": { + "hard_context_reset_context_scaling": { + "default": 0.8, + "exclusiveMaximum": 1.0, + "exclusiveMinimum": 0.0, + "title": "Hard Context Reset Context Scaling", + "type": "number" + }, + "hard_context_reset_max_retries": { + "default": 5, + "exclusiveMinimum": 0.0, + "title": "Hard Context Reset Max Retries", + "type": "integer" + }, + "keep_first": { + "default": 2, + "minimum": 0.0, + "title": "Keep First", + "type": "integer" + }, + "kind": { + "const": "LLMSummarizingCondenser", + "title": "Kind", + "type": "string" + }, + "llm": { + "$ref": "#/components/schemas/LLM-Input" + }, + "max_size": { + "default": 240, + "exclusiveMinimum": 0.0, + "title": "Max Size", + "type": "integer" + }, + "max_tokens": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Max Tokens" + }, + "minimum_progress": { + "default": 0.1, + "exclusiveMaximum": 1.0, + "exclusiveMinimum": 0.0, + "title": "Minimum Progress", + "type": "number" + } + }, + "required": [ + "llm" + ], + "title": "LLMSummarizingCondenser", + "type": "object" + }, + "LLMSummarizingCondenser-Output": { + "description": "LLM-based condenser that summarizes forgotten events.\n\nUses an independent LLM (stored in the `llm` attribute) for generating summaries\nof forgotten events. The optional `agent_llm` parameter passed to condense() is\nthe LLM used by the agent for token counting purposes, and you should not assume\nit is the same as the one defined in this condenser.", + "properties": { + "hard_context_reset_context_scaling": { + "default": 0.8, + "exclusiveMaximum": 1.0, + "exclusiveMinimum": 0.0, + "title": "Hard Context Reset Context Scaling", + "type": "number" + }, + "hard_context_reset_max_retries": { + "default": 5, + "exclusiveMinimum": 0.0, + "title": "Hard Context Reset Max Retries", + "type": "integer" + }, + "keep_first": { + "default": 2, + "minimum": 0.0, + "title": "Keep First", + "type": "integer" + }, + "kind": { + "const": "LLMSummarizingCondenser", + "title": "Kind", + "type": "string" + }, + "llm": { + "$ref": "#/components/schemas/LLM-Output" + }, + "max_size": { + "default": 240, + "exclusiveMinimum": 0.0, + "title": "Max Size", + "type": "integer" + }, + "max_tokens": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Max Tokens" + }, + "minimum_progress": { + "default": 0.1, + "exclusiveMaximum": 1.0, + "exclusiveMinimum": 0.0, + "title": "Minimum Progress", + "type": "number" + } + }, + "required": [ + "llm", + "kind" + ], + "title": "LLMSummarizingCondenser", + "type": "object" + }, + "LLMSummarizingCondenserSettings": { + "description": "Settings for the default LLM summarizing condenser.", + "properties": { + "condenser_kind": { + "const": "llm_summarizing", + "default": "llm_summarizing", + "description": "Discriminator for the condenser settings union. ``'llm_summarizing'`` selects the default LLM summarizing condenser.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Condenser Kind", + "type": "string" + }, + "enabled": { + "default": true, + "description": "Enable conversation memory condensation.", + "openhands_settings": { + "depends_on": [], + "label": "Enable memory condensation", + "prominence": "critical" + }, + "title": "Enabled", + "type": "boolean" + }, + "hard_context_reset_context_scaling": { + "default": 0.8, + "description": "Factor used to reduce event string size after a hard context reset summarization failure.", + "exclusiveMaximum": 1.0, + "exclusiveMinimum": 0.0, + "openhands_settings": { + "depends_on": [ + "enabled" + ], + "label": "Hard reset scaling", + "prominence": "minor" + }, + "title": "Hard Context Reset Context Scaling", + "type": "number" + }, + "hard_context_reset_max_retries": { + "default": 5, + "description": "Number of hard context reset attempts before raising an error.", + "exclusiveMinimum": 0.0, + "openhands_settings": { + "depends_on": [ + "enabled" + ], + "label": "Hard reset retries", + "prominence": "minor" + }, + "title": "Hard Context Reset Max Retries", + "type": "integer" + }, + "keep_first": { + "default": 2, + "description": "Minimum number of initial events to preserve before condensation.", + "minimum": 0.0, + "openhands_settings": { + "depends_on": [ + "enabled" + ], + "label": "Keep first", + "prominence": "minor" + }, + "title": "Keep First", + "type": "integer" + }, + "max_size": { + "default": 240, + "description": "Maximum number of events kept before the condenser runs. Kept on the base settings class for compatibility; concrete condenser-settings variants may opt out when this does not apply.", + "minimum": 20.0, + "openhands_settings": { + "depends_on": [ + "enabled" + ], + "label": "Max size", + "prominence": "minor" + }, + "title": "Max Size", + "type": "integer" + }, + "max_tokens": { + "anyOf": [ + { + "exclusiveMinimum": 0.0, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Maximum number of tokens allowed before the condenser runs. When unset, condensation is only based on event count.", + "openhands_settings": { + "depends_on": [ + "enabled" + ], + "label": "Max tokens", + "prominence": "minor" + }, + "title": "Max Tokens" + }, + "minimum_progress": { + "default": 0.1, + "description": "Minimum fraction of events that must be condensed for condensation to be considered successful.", + "exclusiveMaximum": 1.0, + "exclusiveMinimum": 0.0, + "openhands_settings": { + "depends_on": [ + "enabled" + ], + "label": "Minimum progress", + "prominence": "minor" + }, + "title": "Minimum Progress", + "type": "number" + } + }, + "title": "LLMSummarizingCondenserSettings", + "type": "object" + }, + "LaunchedAgentProfile": { + "description": "Provenance snapshot recorded when an agent profile launches a conversation.\n\nStored on ``StoredConversation`` and projected onto ``ConversationInfo`` so\nts-client ``deriveSwitchPlan`` can identify which agent profile is current\nwithout fragile settings-comparison. See #3720.", + "properties": { + "agent_profile_id": { + "description": "Stable id of the agent profile that launched the conversation.", + "format": "uuid", + "title": "Agent Profile Id", + "type": "string" + }, + "revision": { + "description": "Revision of the agent profile at launch time.", + "minimum": 0.0, + "title": "Revision", + "type": "integer" + }, + "secret_refs": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Secret allow-list captured at launch, also enforced on resume. null preserves unrestricted behavior for older conversations.", + "title": "Secret Refs" + } + }, + "required": [ + "agent_profile_id", + "revision" + ], + "title": "LaunchedAgentProfile", + "type": "object" + }, + "ListDirectoryAction": { + "additionalProperties": false, + "description": "Schema for list directory operation.", + "properties": { + "dir_path": { + "default": ".", + "description": "The path to the directory to list. Defaults to current directory.", + "title": "Dir Path", + "type": "string" + }, + "kind": { + "const": "ListDirectoryAction", + "title": "Kind", + "type": "string" + }, + "recursive": { + "default": false, + "description": "Whether to list subdirectories recursively (up to 2 levels).", + "title": "Recursive", + "type": "boolean" + } + }, + "required": [ + "kind" + ], + "title": "ListDirectoryAction", + "type": "object" + }, + "ListDirectoryObservation": { + "additionalProperties": false, + "description": "Observation from listing a directory.", + "properties": { + "content": { + "description": "Content returned from the tool as a list of TextContent/ImageContent objects. When there is an error, it should be written in this field.", + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/TextContent" + }, + { + "$ref": "#/components/schemas/ImageContent" + } + ] + }, + "title": "Content", + "type": "array" + }, + "dir_path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The directory path that was listed.", + "title": "Dir Path" + }, + "entries": { + "description": "List of files and directories found.", + "items": { + "$ref": "#/components/schemas/FileEntry" + }, + "title": "Entries", + "type": "array" + }, + "is_error": { + "default": false, + "description": "Whether the observation indicates an error", + "title": "Is Error", + "type": "boolean" + }, + "is_truncated": { + "default": false, + "description": "Whether the listing was truncated due to too many entries.", + "title": "Is Truncated", + "type": "boolean" + }, + "kind": { + "const": "ListDirectoryObservation", + "title": "Kind", + "type": "string" + }, + "total_count": { + "default": 0, + "description": "Total number of entries found.", + "title": "Total Count", + "type": "integer" + } + }, + "required": [ + "kind" + ], + "title": "ListDirectoryObservation", + "type": "object" + }, + "ListDirectoryTool": { + "description": "Tool for listing directory contents with metadata.", + "properties": { + "action_type": { + "title": "Action Type", + "type": "string" + }, + "annotations": { + "anyOf": [ + { + "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" + }, + { + "type": "null" + } + ] + }, + "description": { + "title": "Description", + "type": "string" + }, + "kind": { + "const": "ListDirectoryTool", + "title": "Kind", + "type": "string" + }, + "meta": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Meta" + }, + "observation_type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Observation Type" + }, + "title": { + "readOnly": true, + "title": "Title", + "type": "string" + } + }, + "required": [ + "description", + "action_type", + "kind", + "title" + ], + "title": "ListDirectoryTool", + "type": "object" + }, + "LocalWorkspace-Input": { + "description": "Local workspace implementation that operates on the host filesystem.\n\nLocalWorkspace provides direct access to the local filesystem and command execution\nenvironment. It's suitable for development and testing scenarios where the agent\nshould operate directly on the host system.\n\nExample:\n >>> workspace = LocalWorkspace(working_dir=\"/path/to/project\")\n >>> with workspace:\n ... result = workspace.execute_command(\"ls -la\")\n ... content = workspace.read_file(\"README.md\")", + "properties": { + "kind": { + "const": "LocalWorkspace", + "title": "Kind", + "type": "string" + }, + "working_dir": { + "description": "The working directory for agent operations and tool execution. Accepts both string paths and Path objects. Path objects are automatically converted to strings.", + "title": "Working Dir", + "type": "string" + } + }, + "required": [ + "working_dir" + ], + "title": "LocalWorkspace", + "type": "object" + }, + "LocalWorkspace-Output": { + "description": "Local workspace implementation that operates on the host filesystem.\n\nLocalWorkspace provides direct access to the local filesystem and command execution\nenvironment. It's suitable for development and testing scenarios where the agent\nshould operate directly on the host system.\n\nExample:\n >>> workspace = LocalWorkspace(working_dir=\"/path/to/project\")\n >>> with workspace:\n ... result = workspace.execute_command(\"ls -la\")\n ... content = workspace.read_file(\"README.md\")", + "properties": { + "kind": { + "const": "LocalWorkspace", + "title": "Kind", + "type": "string" + }, + "working_dir": { + "description": "The working directory for agent operations and tool execution. Accepts both string paths and Path objects. Path objects are automatically converted to strings.", + "title": "Working Dir", + "type": "string" + } + }, + "required": [ + "working_dir", + "kind" + ], + "title": "LocalWorkspace", + "type": "object" + }, + "LookupSecret-Input": { + "description": "A secret looked up from some external url", + "properties": { + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Optional description for this secret", + "title": "Description" + }, + "headers": { + "additionalProperties": { + "type": "string" + }, + "title": "Headers", + "type": "object" + }, + "kind": { + "const": "LookupSecret", + "title": "Kind", + "type": "string" + }, + "url": { + "title": "Url", + "type": "string" + } + }, + "required": [ + "url" + ], + "title": "LookupSecret", + "type": "object" + }, + "LookupSecret-Output": { + "description": "A secret looked up from some external url", + "properties": { + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Optional description for this secret", + "title": "Description" + }, + "headers": { + "additionalProperties": { + "type": "string" + }, + "title": "Headers", + "type": "object" + }, + "kind": { + "const": "LookupSecret", + "title": "Kind", + "type": "string" + }, + "url": { + "title": "Url", + "type": "string" + } + }, + "required": [ + "url", + "kind" + ], + "title": "LookupSecret", + "type": "object" + }, + "MCPApiKeyAuthCredential-Input": { + "properties": { + "header_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Header Name" + }, + "strategy": { + "const": "api_key", + "title": "Strategy", + "type": "string" + }, + "value": { + "anyOf": [ + { + "format": "password", + "type": "string", + "writeOnly": true + }, + { + "type": "null" + } + ], + "title": "Value" + } + }, + "required": [ + "strategy" + ], + "title": "MCPApiKeyAuthCredential", + "type": "object" + }, + "MCPApiKeyAuthCredential-Output": { + "properties": { + "header_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Header Name" + }, + "strategy": { + "const": "api_key", + "title": "Strategy", + "type": "string" + }, + "value": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Value" + } + }, + "required": [ + "strategy" + ], + "title": "MCPApiKeyAuthCredential", + "type": "object" + }, + "MCPAuthCredential": { + "discriminator": { + "mapping": { + "api_key": "#/components/schemas/MCPApiKeyAuthCredential-Output", + "basic": "#/components/schemas/MCPBasicAuthCredential-Output", + "bearer": "#/components/schemas/MCPBearerAuthCredential-Output", + "header": "#/components/schemas/MCPHeaderAuthCredential-Output", + "none": "#/components/schemas/MCPNoneAuthCredential", + "oauth2": "#/components/schemas/MCPOAuthAuthCredential-Output" + }, + "propertyName": "strategy" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/MCPNoneAuthCredential" + }, + { + "$ref": "#/components/schemas/MCPApiKeyAuthCredential-Output" + }, + { + "$ref": "#/components/schemas/MCPBearerAuthCredential-Output" + }, + { + "$ref": "#/components/schemas/MCPBasicAuthCredential-Output" + }, + { + "$ref": "#/components/schemas/MCPHeaderAuthCredential-Output" + }, + { + "$ref": "#/components/schemas/MCPOAuthAuthCredential-Output" + } + ], + "title": "MCPAuthCredential" + }, + "MCPBasicAuthCredential-Input": { + "properties": { + "password": { + "anyOf": [ + { + "format": "password", + "type": "string", + "writeOnly": true + }, + { + "type": "null" + } + ], + "title": "Password" + }, + "strategy": { + "const": "basic", + "title": "Strategy", + "type": "string" + }, + "username": { + "title": "Username", + "type": "string" + } + }, + "required": [ + "strategy", + "username" + ], + "title": "MCPBasicAuthCredential", + "type": "object" + }, + "MCPBasicAuthCredential-Output": { + "properties": { + "password": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Password" + }, + "strategy": { + "const": "basic", + "title": "Strategy", + "type": "string" + }, + "username": { + "title": "Username", + "type": "string" + } + }, + "required": [ + "strategy", + "username" + ], + "title": "MCPBasicAuthCredential", + "type": "object" + }, + "MCPBearerAuthCredential-Input": { + "properties": { + "strategy": { + "const": "bearer", + "title": "Strategy", + "type": "string" + }, + "value": { + "anyOf": [ + { + "format": "password", + "type": "string", + "writeOnly": true + }, + { + "type": "null" + } + ], + "title": "Value" + } + }, + "required": [ + "strategy" + ], + "title": "MCPBearerAuthCredential", + "type": "object" + }, + "MCPBearerAuthCredential-Output": { + "properties": { + "strategy": { + "const": "bearer", + "title": "Strategy", + "type": "string" + }, + "value": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Value" + } + }, + "required": [ + "strategy" + ], + "title": "MCPBearerAuthCredential", + "type": "object" + }, + "MCPConfig": { + "additionalProperties": { + "$ref": "#/components/schemas/MCPServer-Output" + }, + "description": "Canonical persisted MCP server map keyed by stable server name.", + "title": "MCPConfig", + "type": "object" + }, + "MCPConfigPatch": { + "additionalProperties": { + "anyOf": [ + { + "$ref": "#/components/schemas/MCPServerPatch" + }, + { + "type": "null" + } + ] + }, + "description": "Sparse MCP map patch; a null map value deletes that named server.", + "title": "MCPConfigPatch", + "type": "object" + }, + "MCPHeaderAuthCredential-Input": { + "properties": { + "headers": { + "additionalProperties": { + "format": "password", + "type": "string", + "writeOnly": true + }, + "title": "Headers", + "type": "object" + }, + "strategy": { + "const": "header", + "title": "Strategy", + "type": "string" + } + }, + "required": [ + "strategy" + ], + "title": "MCPHeaderAuthCredential", + "type": "object" + }, + "MCPHeaderAuthCredential-Output": { + "properties": { + "headers": { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "title": "Headers", + "type": "object" + }, + "strategy": { + "const": "header", + "title": "Strategy", + "type": "string" + } + }, + "required": [ + "strategy" + ], + "title": "MCPHeaderAuthCredential", + "type": "object" + }, + "MCPNoneAuthCredential": { + "properties": { + "strategy": { + "const": "none", + "title": "Strategy", + "type": "string" + } + }, + "required": [ + "strategy" + ], + "title": "MCPNoneAuthCredential", + "type": "object" + }, + "MCPOAuthAuthCredential-Input": { + "properties": { + "authentication": { + "anyOf": [ + { + "$ref": "#/components/schemas/MCPOAuthAuthentication-Input" + }, + { + "type": "null" + } + ] + }, + "state": { + "anyOf": [ + { + "$ref": "#/components/schemas/MCPOAuthState-Input" + }, + { + "type": "null" + } + ] + }, + "strategy": { + "const": "oauth2", + "title": "Strategy", + "type": "string" + } + }, + "required": [ + "strategy" + ], + "title": "MCPOAuthAuthCredential", + "type": "object" + }, + "MCPOAuthAuthCredential-Output": { + "properties": { + "authentication": { + "anyOf": [ + { + "$ref": "#/components/schemas/MCPOAuthAuthentication-Output" + }, + { + "type": "null" + } + ] + }, + "state": { + "anyOf": [ + { + "$ref": "#/components/schemas/MCPOAuthState-Output" + }, + { + "type": "null" + } + ] + }, + "strategy": { + "const": "oauth2", + "title": "Strategy", + "type": "string" + } + }, + "required": [ + "strategy" + ], + "title": "MCPOAuthAuthCredential", + "type": "object" + }, + "MCPOAuthAuthentication-Input": { + "additionalProperties": false, + "properties": { + "additional_client_metadata": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Additional Client Metadata" + }, + "client_auth_method": { + "anyOf": [ + { + "enum": [ + "none", + "client_secret_post", + "client_secret_basic", + "private_key_jwt" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Client Auth Method" + }, + "client_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Client Id" + }, + "client_metadata_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Client Metadata Url" + }, + "client_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Client Name" + }, + "client_secret": { + "anyOf": [ + { + "format": "password", + "type": "string", + "writeOnly": true + }, + { + "type": "null" + } + ], + "title": "Client Secret" + }, + "scopes": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Scopes" + }, + "type": { + "const": "oauth", + "title": "Type", + "type": "string" + } + }, + "required": [ + "type" + ], + "title": "MCPOAuthAuthentication", + "type": "object" + }, + "MCPOAuthAuthentication-Output": { + "additionalProperties": false, + "properties": { + "additional_client_metadata": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Additional Client Metadata" + }, + "client_auth_method": { + "anyOf": [ + { + "enum": [ + "none", + "client_secret_post", + "client_secret_basic", + "private_key_jwt" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Client Auth Method" + }, + "client_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Client Id" + }, + "client_metadata_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Client Metadata Url" + }, + "client_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Client Name" + }, + "client_secret": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Client Secret" + }, + "scopes": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Scopes" + }, + "type": { + "const": "oauth", + "title": "Type", + "type": "string" + } + }, + "required": [ + "type" + ], + "title": "MCPOAuthAuthentication", + "type": "object" + }, + "MCPOAuthCallbackRequest": { + "description": "Callback URL copied from a browser OAuth redirect.", + "properties": { + "callback_url": { + "minLength": 1, + "title": "Callback Url", + "type": "string" + } + }, + "required": [ + "callback_url" + ], + "title": "MCPOAuthCallbackRequest", + "type": "object" + }, + "MCPOAuthClientInfoState-Input": { + "additionalProperties": true, + "properties": { + "client_secret": { + "anyOf": [ + { + "format": "password", + "type": "string", + "writeOnly": true + }, + { + "type": "null" + } + ], + "title": "Client Secret" + } + }, + "title": "MCPOAuthClientInfoState", + "type": "object" + }, + "MCPOAuthClientInfoState-Output": { + "additionalProperties": true, + "properties": { + "client_secret": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Client Secret" + } + }, + "title": "MCPOAuthClientInfoState", + "type": "object" + }, + "MCPOAuthStartResponse": { + "description": "Response for starting an install-time OAuth MCP probe.", + "properties": { + "authorization_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Authorization Url" + }, + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Error" + }, + "error_kind": { + "anyOf": [ + { + "enum": [ + "timeout", + "connection", + "unknown" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Error Kind" + }, + "job_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Job Id" + }, + "ok": { + "title": "Ok", + "type": "boolean" + } + }, + "required": [ + "ok" + ], + "title": "MCPOAuthStartResponse", + "type": "object" + }, + "MCPOAuthState-Input": { + "properties": { + "client_info": { + "anyOf": [ + { + "$ref": "#/components/schemas/MCPOAuthClientInfoState-Input" + }, + { + "type": "null" + } + ] + }, + "token_expires_at": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Token Expires At" + }, + "tokens": { + "anyOf": [ + { + "$ref": "#/components/schemas/MCPOAuthTokenState-Input" + }, + { + "type": "null" + } + ] + } + }, + "title": "MCPOAuthState", + "type": "object" + }, + "MCPOAuthState-Output": { + "properties": { + "client_info": { + "anyOf": [ + { + "$ref": "#/components/schemas/MCPOAuthClientInfoState-Output" + }, + { + "type": "null" + } + ] + }, + "token_expires_at": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Token Expires At" + }, + "tokens": { + "anyOf": [ + { + "$ref": "#/components/schemas/MCPOAuthTokenState-Output" + }, + { + "type": "null" + } + ] + } + }, + "title": "MCPOAuthState", + "type": "object" + }, + "MCPOAuthStateResponse": { + "properties": { + "client_info": { + "anyOf": [ + { + "additionalProperties": true, + "properties": { + "client_secret": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Client Secret" + } + }, + "title": "MCPOAuthClientInfoState", + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Client Info" + }, + "token_expires_at": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Token Expires At" + }, + "tokens": { + "anyOf": [ + { + "additionalProperties": true, + "properties": { + "access_token": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Access Token" + }, + "refresh_token": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Refresh Token" + } + }, + "title": "MCPOAuthTokenState", + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Tokens" + } + }, + "title": "MCPOAuthStateResponse", + "type": "object" + }, + "MCPOAuthStatusResponse": { + "description": "Current state of an install-time OAuth MCP probe.", + "properties": { + "authorization_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Authorization Url" + }, + "callback_ready": { + "default": false, + "title": "Callback Ready", + "type": "boolean" + }, + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Error" + }, + "error_kind": { + "anyOf": [ + { + "enum": [ + "timeout", + "connection", + "unknown" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Error Kind" + }, + "job_id": { + "title": "Job Id", + "type": "string" + }, + "oauth_state": { + "anyOf": [ + { + "$ref": "#/components/schemas/MCPOAuthStateResponse" + }, + { + "type": "null" + } + ] + }, + "ok": { + "title": "Ok", + "type": "boolean" + }, + "status": { + "enum": [ + "pending", + "authorizing", + "succeeded", + "failed" + ], + "title": "Status", + "type": "string" + }, + "tool_result": { + "anyOf": [ + { + "$ref": "#/components/schemas/MCPToolCallResult" + }, + { + "type": "null" + } + ] + }, + "tools": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Tools" + } + }, + "required": [ + "ok", + "status", + "job_id" + ], + "title": "MCPOAuthStatusResponse", + "type": "object" + }, + "MCPOAuthTokenState-Input": { + "additionalProperties": true, + "properties": { + "access_token": { + "anyOf": [ + { + "format": "password", + "type": "string", + "writeOnly": true + }, + { + "type": "null" + } + ], + "title": "Access Token" + }, + "refresh_token": { + "anyOf": [ + { + "format": "password", + "type": "string", + "writeOnly": true + }, + { + "type": "null" + } + ], + "title": "Refresh Token" + } + }, + "title": "MCPOAuthTokenState", + "type": "object" + }, + "MCPOAuthTokenState-Output": { + "additionalProperties": true, + "properties": { + "access_token": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Access Token" + }, + "refresh_token": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Refresh Token" + } + }, + "title": "MCPOAuthTokenState", + "type": "object" + }, + "MCPServer": { + "additionalProperties": false, + "description": "One MCP server in the settings DataModel.", + "properties": { + "args": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Args" + }, + "auth": { + "anyOf": [ + { + "discriminator": { + "mapping": { + "api_key": "#/components/schemas/MCPApiKeyAuthCredential-Output", + "basic": "#/components/schemas/MCPBasicAuthCredential-Output", + "bearer": "#/components/schemas/MCPBearerAuthCredential-Output", + "header": "#/components/schemas/MCPHeaderAuthCredential-Output", + "none": "#/components/schemas/MCPNoneAuthCredential", + "oauth2": "#/components/schemas/MCPOAuthAuthCredential-Output" + }, + "propertyName": "strategy" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/MCPNoneAuthCredential" + }, + { + "$ref": "#/components/schemas/MCPApiKeyAuthCredential-Output" + }, + { + "$ref": "#/components/schemas/MCPBearerAuthCredential-Output" + }, + { + "$ref": "#/components/schemas/MCPBasicAuthCredential-Output" + }, + { + "$ref": "#/components/schemas/MCPHeaderAuthCredential-Output" + }, + { + "$ref": "#/components/schemas/MCPOAuthAuthCredential-Output" + } + ] + }, + { + "type": "null" + } + ], + "title": "Auth" + }, + "command": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Command" + }, + "cwd": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Cwd" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "enabled": { + "default": true, + "description": "Whether this server is exposed to the agent. A disabled server stays fully configured -- including its secrets -- but is skipped when MCP tools are created and when servers are forwarded to an ACP subprocess.", + "title": "Enabled", + "type": "boolean" + }, + "env": { + "anyOf": [ + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Env" + }, + "headers": { + "anyOf": [ + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Headers" + }, + "icon": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Icon" + }, + "keep_alive": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Keep Alive" + }, + "sse_read_timeout": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Sse Read Timeout" + }, + "timeout": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Timeout" + }, + "transport": { + "anyOf": [ + { + "enum": [ + "stdio", + "http", + "sse", + "streamable-http" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Transport" + }, + "url": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Url" + } + }, + "title": "MCPServer", + "type": "object" + }, + "MCPServer-Input": { + "additionalProperties": false, + "description": "One MCP server in the settings DataModel.", + "properties": { + "args": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Args" + }, + "auth": { + "anyOf": [ + { + "discriminator": { + "mapping": { + "api_key": "#/components/schemas/MCPApiKeyAuthCredential-Input", + "basic": "#/components/schemas/MCPBasicAuthCredential-Input", + "bearer": "#/components/schemas/MCPBearerAuthCredential-Input", + "header": "#/components/schemas/MCPHeaderAuthCredential-Input", + "none": "#/components/schemas/MCPNoneAuthCredential", + "oauth2": "#/components/schemas/MCPOAuthAuthCredential-Input" + }, + "propertyName": "strategy" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/MCPNoneAuthCredential" + }, + { + "$ref": "#/components/schemas/MCPApiKeyAuthCredential-Input" + }, + { + "$ref": "#/components/schemas/MCPBearerAuthCredential-Input" + }, + { + "$ref": "#/components/schemas/MCPBasicAuthCredential-Input" + }, + { + "$ref": "#/components/schemas/MCPHeaderAuthCredential-Input" + }, + { + "$ref": "#/components/schemas/MCPOAuthAuthCredential-Input" + } + ] + }, + { + "type": "null" + } + ], + "title": "Auth" + }, + "command": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Command" + }, + "cwd": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Cwd" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "enabled": { + "default": true, + "description": "Whether this server is exposed to the agent. A disabled server stays fully configured -- including its secrets -- but is skipped when MCP tools are created and when servers are forwarded to an ACP subprocess.", + "title": "Enabled", + "type": "boolean" + }, + "env": { + "anyOf": [ + { + "additionalProperties": { + "format": "password", + "type": "string", + "writeOnly": true + }, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Env" + }, + "headers": { + "anyOf": [ + { + "additionalProperties": { + "format": "password", + "type": "string", + "writeOnly": true + }, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Headers" + }, + "icon": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Icon" + }, + "keep_alive": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Keep Alive" + }, + "sse_read_timeout": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Sse Read Timeout" + }, + "timeout": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Timeout" + }, + "transport": { + "anyOf": [ + { + "enum": [ + "stdio", + "http", + "sse", + "streamable-http" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Transport" + }, + "url": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Url" + } + }, + "title": "MCPServer", + "type": "object" + }, + "MCPServer-Output": { + "additionalProperties": false, + "description": "One MCP server in the settings DataModel.", + "properties": { + "args": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Args" + }, + "auth": { + "anyOf": [ + { + "discriminator": { + "mapping": { + "api_key": "#/components/schemas/MCPApiKeyAuthCredential-Output", + "basic": "#/components/schemas/MCPBasicAuthCredential-Output", + "bearer": "#/components/schemas/MCPBearerAuthCredential-Output", + "header": "#/components/schemas/MCPHeaderAuthCredential-Output", + "none": "#/components/schemas/MCPNoneAuthCredential", + "oauth2": "#/components/schemas/MCPOAuthAuthCredential-Output" + }, + "propertyName": "strategy" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/MCPNoneAuthCredential" + }, + { + "$ref": "#/components/schemas/MCPApiKeyAuthCredential-Output" + }, + { + "$ref": "#/components/schemas/MCPBearerAuthCredential-Output" + }, + { + "$ref": "#/components/schemas/MCPBasicAuthCredential-Output" + }, + { + "$ref": "#/components/schemas/MCPHeaderAuthCredential-Output" + }, + { + "$ref": "#/components/schemas/MCPOAuthAuthCredential-Output" + } + ] + }, + { + "type": "null" + } + ], + "title": "Auth" + }, + "command": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Command" + }, + "cwd": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Cwd" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "enabled": { + "default": true, + "description": "Whether this server is exposed to the agent. A disabled server stays fully configured -- including its secrets -- but is skipped when MCP tools are created and when servers are forwarded to an ACP subprocess.", + "title": "Enabled", + "type": "boolean" + }, + "env": { + "anyOf": [ + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Env" + }, + "headers": { + "anyOf": [ + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Headers" + }, + "icon": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Icon" + }, + "keep_alive": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Keep Alive" + }, + "sse_read_timeout": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Sse Read Timeout" + }, + "timeout": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Timeout" + }, + "transport": { + "anyOf": [ + { + "enum": [ + "stdio", + "http", + "sse", + "streamable-http" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Transport" + }, + "url": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Url" + } + }, + "title": "MCPServer", + "type": "object" + }, + "MCPServerPatch": { + "additionalProperties": false, + "description": "Sparse RFC 7386 merge patch for one persisted MCP server.", + "properties": { + "args": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Args" + }, + "auth": { + "anyOf": [ + { + "discriminator": { + "mapping": { + "api_key": "#/components/schemas/MCPApiKeyAuthCredential-Input", + "basic": "#/components/schemas/MCPBasicAuthCredential-Input", + "bearer": "#/components/schemas/MCPBearerAuthCredential-Input", + "header": "#/components/schemas/MCPHeaderAuthCredential-Input", + "none": "#/components/schemas/MCPNoneAuthCredential", + "oauth2": "#/components/schemas/MCPOAuthAuthCredential-Input" + }, + "propertyName": "strategy" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/MCPNoneAuthCredential" + }, + { + "$ref": "#/components/schemas/MCPApiKeyAuthCredential-Input" + }, + { + "$ref": "#/components/schemas/MCPBearerAuthCredential-Input" + }, + { + "$ref": "#/components/schemas/MCPBasicAuthCredential-Input" + }, + { + "$ref": "#/components/schemas/MCPHeaderAuthCredential-Input" + }, + { + "$ref": "#/components/schemas/MCPOAuthAuthCredential-Input" + } + ] + }, + { + "type": "null" + } + ], + "title": "Auth" + }, + "command": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Command" + }, + "cwd": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Cwd" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "enabled": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Switch the server off (false) or back on (true) without touching the rest of its configuration. A null clears the override, which restores the canonical default (enabled).", + "title": "Enabled" + }, + "env": { + "anyOf": [ + { + "additionalProperties": { + "anyOf": [ + { + "format": "password", + "type": "string", + "writeOnly": true + }, + { + "type": "null" + } + ] + }, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Env" + }, + "headers": { + "anyOf": [ + { + "additionalProperties": { + "anyOf": [ + { + "format": "password", + "type": "string", + "writeOnly": true + }, + { + "type": "null" + } + ] + }, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Headers" + }, + "icon": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Icon" + }, + "keep_alive": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Keep Alive" + }, + "sse_read_timeout": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Sse Read Timeout" + }, + "timeout": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Timeout" + }, + "transport": { + "anyOf": [ + { + "enum": [ + "stdio", + "http", + "sse", + "streamable-http" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Transport" + }, + "url": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Url" + } + }, + "title": "MCPServerPatch", + "type": "object" + }, + "MCPTestFailure": { + "description": "Response when the candidate server fails to connect or list tools.\n\nThe endpoint returns HTTP 200 in both success and failure cases: a\nfailure here is the *expected* outcome of validating a user-supplied\nconfig, not a server-side error. The structured shape makes it easy\nfor the UI to render an actionable message.", + "properties": { + "error": { + "description": "Human-readable error message.", + "title": "Error", + "type": "string" + }, + "error_kind": { + "description": "Coarse error classification, useful for branching UI.", + "enum": [ + "timeout", + "connection", + "unknown" + ], + "title": "Error Kind", + "type": "string" + }, + "ok": { + "const": false, + "default": false, + "title": "Ok", + "type": "boolean" + } + }, + "required": [ + "error", + "error_kind" + ], + "title": "MCPTestFailure", + "type": "object" + }, + "MCPTestRequest": { + "description": "Body for ``POST /api/mcp/test``.", + "properties": { + "name": { + "default": "test-server", + "description": "Name to use for the server inside the temporary MCP server map. Only affects error messages -- does not need to match any persisted setting.", + "maxLength": 128, + "minLength": 1, + "title": "Name", + "type": "string" + }, + "server": { + "discriminator": { + "mapping": { + "http": "#/components/schemas/_RemoteMCPServerSpec", + "shttp": "#/components/schemas/_RemoteMCPServerSpec", + "sse": "#/components/schemas/_RemoteMCPServerSpec", + "stdio": "#/components/schemas/_StdioMCPServerSpec", + "streamable-http": "#/components/schemas/_RemoteMCPServerSpec" + }, + "propertyName": "type" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/_StdioMCPServerSpec" + }, + { + "$ref": "#/components/schemas/_RemoteMCPServerSpec" + } + ], + "title": "Server" + }, + "timeout": { + "default": 15.0, + "description": "Seconds to wait for connection + tools/list to complete.", + "exclusiveMinimum": 0.0, + "maximum": 120.0, + "title": "Timeout", + "type": "number" + }, + "tool_call": { + "anyOf": [ + { + "$ref": "#/components/schemas/MCPToolCallSpec" + }, + { + "type": "null" + } + ], + "description": "Optional read-only tool to invoke after listing succeeds, so callers can verify credentials the server only exercises on tool invocation. Its outcome is reported verbatim in `tool_result` without affecting `ok`." + } + }, + "required": [ + "server" + ], + "title": "MCPTestRequest", + "type": "object" + }, + "MCPTestResponse": { + "discriminator": { + "mapping": { + "False": "#/components/schemas/MCPTestFailure", + "True": "#/components/schemas/MCPTestSuccess" + }, + "propertyName": "ok" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/MCPTestSuccess" + }, + { + "$ref": "#/components/schemas/MCPTestFailure" + } + ], + "title": "MCPTestResponse" + }, + "MCPTestSuccess": { + "description": "Response when the candidate server connects and lists its tools.", + "properties": { + "oauth_state": { + "anyOf": [ + { + "$ref": "#/components/schemas/MCPOAuthStateResponse" + }, + { + "type": "null" + } + ], + "description": "Serialized OAuth state acquired or refreshed by the probe. Clients should persist this under the tested server's auth.state." + }, + "ok": { + "const": true, + "default": true, + "title": "Ok", + "type": "boolean" + }, + "resolved_mcp_servers": { + "anyOf": [ + { + "items": { + "additionalProperties": true, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "deprecated": true, + "description": "Deprecated compatibility field for older clients that expected resolved MCP server metadata in test responses.", + "title": "Resolved Mcp Servers" + }, + "tool_result": { + "anyOf": [ + { + "$ref": "#/components/schemas/MCPToolCallResult" + }, + { + "type": "null" + } + ], + "description": "Outcome of the requested `tool_call`, when one was supplied." + }, + "tools": { + "description": "Names of tools advertised by the MCP server.", + "items": { + "type": "string" + }, + "title": "Tools", + "type": "array" + } + }, + "title": "MCPTestSuccess", + "type": "object" + }, + "MCPToolAction": { + "additionalProperties": false, + "description": "Schema for MCP input action.\n\nIt is just a thin wrapper around raw JSON and does\nnot do any validation.\n\nValidation will be performed by MCPTool.__call__\nby constructing dynamically created Pydantic model\nfrom the MCP tool input schema.", + "properties": { + "data": { + "additionalProperties": true, + "description": "Dynamic data fields from the tool call", + "title": "Data", + "type": "object" + }, + "kind": { + "const": "MCPToolAction", + "title": "Kind", + "type": "string" + } + }, + "required": [ + "kind" + ], + "title": "MCPToolAction", + "type": "object" + }, + "MCPToolCallResult": { + "description": "Verbatim outcome of the requested ``tool_call``.\n\nThe endpoint stays provider-neutral: many servers report upstream\nfailures (e.g. Slack's ``{\"ok\": false, \"error\": \"invalid_auth\"}``)\nas ordinary text content with ``isError`` unset, so interpreting the\npayload is the caller's job.", + "properties": { + "is_error": { + "description": "The MCP-level isError flag of the result.", + "title": "Is Error", + "type": "boolean" + }, + "text": { + "description": "Concatenated text content of the result.", + "title": "Text", + "type": "string" + } + }, + "required": [ + "is_error", + "text" + ], + "title": "MCPToolCallResult", + "type": "object" + }, + "MCPToolCallSpec": { + "description": "A single tool invocation to run as part of the connection test.\n\nListing tools does not exercise the credentials many servers only use\ninside tool handlers, so callers can name one tool to invoke after the\nlisting succeeds. Callers are responsible for choosing a read-only tool;\nthe endpoint executes it verbatim.", + "properties": { + "arguments": { + "additionalProperties": true, + "description": "Arguments passed to the tool unchanged.", + "title": "Arguments", + "type": "object" + }, + "name": { + "description": "Name of the tool to invoke", + "minLength": 1, + "title": "Name", + "type": "string" + } + }, + "required": [ + "name" + ], + "title": "MCPToolCallSpec", + "type": "object" + }, + "MCPToolDefinition": { + "description": "MCP Tool that wraps an MCP client and provides tool functionality.", + "properties": { + "action_type": { + "title": "Action Type", + "type": "string" + }, + "annotations": { + "anyOf": [ + { + "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" + }, + { + "type": "null" + } + ] + }, + "description": { + "title": "Description", + "type": "string" + }, + "kind": { + "const": "MCPToolDefinition", + "title": "Kind", + "type": "string" + }, + "mcp_tool": { + "$ref": "#/components/schemas/mcp__types__Tool", + "description": "The MCP tool definition." + }, + "meta": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Meta" + }, + "observation_type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Observation Type" + }, + "title": { + "readOnly": true, + "title": "Title", + "type": "string" + } + }, + "required": [ + "description", + "action_type", + "mcp_tool", + "kind", + "title" + ], + "title": "MCPToolDefinition", + "type": "object" + }, + "MCPToolObservation": { + "additionalProperties": false, + "description": "Observation from MCP tool execution.", + "properties": { + "content": { + "description": "Content returned from the tool as a list of TextContent/ImageContent objects. When there is an error, it should be written in this field.", + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/TextContent" + }, + { + "$ref": "#/components/schemas/ImageContent" + } + ] + }, + "title": "Content", + "type": "array" + }, + "is_error": { + "default": false, + "description": "Whether the observation indicates an error", + "title": "Is Error", + "type": "boolean" + }, + "kind": { + "const": "MCPToolObservation", + "title": "Kind", + "type": "string" + }, + "tool_name": { + "description": "Name of the tool that was called", + "title": "Tool Name", + "type": "string" + } + }, + "required": [ + "tool_name", + "kind" + ], + "title": "MCPToolObservation", + "type": "object" + }, + "MarketplacePluginInfo": { + "description": "A true plugin in the marketplace catalog, with attach coordinates.", + "properties": { + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "files": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Files" + }, + "installed": { + "title": "Installed", + "type": "boolean" + }, + "name": { + "title": "Name", + "type": "string" + }, + "path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Path" + }, + "ref": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Ref" + }, + "repo_path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Repo Path" + }, + "skills": { + "anyOf": [ + { + "items": { + "$ref": "#/components/schemas/PluginSkillSummary" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Skills" + }, + "source": { + "title": "Source", + "type": "string" + } + }, + "required": [ + "name", + "description", + "source", + "installed" + ], + "title": "MarketplacePluginInfo", + "type": "object" + }, + "MarketplaceRegistration": { + "description": "Registration for a marketplace source used for plugin resolution.", + "properties": { + "auto_load": { + "anyOf": [ + { + "type": "boolean" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "default": false, + "description": "Whether to load marketplace plugins and standalone skills at conversation start. Use True for all, False or [] for none, or a list of plugin/skill names for selective loading.", + "title": "Auto Load" + }, + "name": { + "description": "Identifier for this marketplace registration", + "title": "Name", + "type": "string" + }, + "ref": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Optional branch, tag, or commit for git sources", + "title": "Ref" + }, + "repo_path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Subdirectory path within the git repository containing the marketplace. Only relevant for git sources.", + "title": "Repo Path" + }, + "source": { + "description": "Marketplace source: 'github:owner/repo', git URL, or local path", + "title": "Source", + "type": "string" + } + }, + "required": [ + "name", + "source" + ], + "title": "MarketplaceRegistration", + "type": "object" + }, + "MarketplaceSkillInfo": { + "description": "Information about a skill in the marketplace catalog.", + "properties": { + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "installed": { + "title": "Installed", + "type": "boolean" + }, + "name": { + "title": "Name", + "type": "string" + }, + "source": { + "title": "Source", + "type": "string" + } + }, + "required": [ + "name", + "description", + "source", + "installed" + ], + "title": "MarketplaceSkillInfo", + "type": "object" + }, + "MaterializeAgentProfileRequest": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "oneOf": [ + { + "$ref": "#/components/schemas/OpenHandsAgentProfile" + }, + { + "$ref": "#/components/schemas/ACPAgentProfile" + } + ] + }, + { + "type": "null" + } + ], + "description": "Draft profile to evaluate instead of the stored one. The path name overrides the draft's name.", + "title": "Profile" + } + }, + "title": "MaterializeAgentProfileRequest", + "type": "object" + }, + "Message": { + "properties": { + "content": { + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/TextContent" + }, + { + "$ref": "#/components/schemas/ImageContent" + } + ] + }, + "title": "Content", + "type": "array" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Name" + }, + "reasoning_content": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Intermediate reasoning/thinking content from reasoning models", + "title": "Reasoning Content" + }, + "responses_reasoning_item": { + "anyOf": [ + { + "$ref": "#/components/schemas/ReasoningItemModel" + }, + { + "type": "null" + } + ], + "description": "OpenAI Responses reasoning item from model output" + }, + "role": { + "enum": [ + "user", + "system", + "assistant", + "tool" + ], + "title": "Role", + "type": "string" + }, + "thinking_blocks": { + "description": "Raw Anthropic thinking blocks for extended thinking feature", + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/ThinkingBlock" + }, + { + "$ref": "#/components/schemas/RedactedThinkingBlock" + } + ] + }, + "title": "Thinking Blocks", + "type": "array" + }, + "tool_call_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tool Call Id" + }, + "tool_calls": { + "anyOf": [ + { + "items": { + "$ref": "#/components/schemas/MessageToolCall" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Tool Calls" + } + }, + "required": [ + "role" + ], + "title": "Message", + "type": "object" + }, + "MessageEvent": { + "additionalProperties": false, + "description": "Message from either agent or user.\n\nThis is originally the \"MessageAction\", but it suppose not to be tool call.", + "properties": { + "activated_skills": { + "description": "List of activated skill name", + "items": { + "type": "string" + }, + "title": "Activated Skills", + "type": "array" + }, + "critic_result": { + "anyOf": [ + { + "$ref": "#/components/schemas/CriticResult" + }, + { + "type": "null" + } + ], + "description": "Optional critic evaluation of this message and preceding history." + }, + "extended_content": { + "description": "List of content added by agent context", + "items": { + "$ref": "#/components/schemas/TextContent" + }, + "title": "Extended Content", + "type": "array" + }, + "id": { + "description": "Unique event id (ULID/UUID)", + "title": "Id", + "type": "string" + }, + "kind": { + "const": "MessageEvent", + "title": "Kind", + "type": "string" + }, + "llm_message": { + "$ref": "#/components/schemas/Message", + "description": "The exact LLM message for this message event" + }, + "llm_response_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Completion or Response ID of the LLM response that generated this eventIf the source != 'agent', this field is None", + "title": "Llm Response Id" + }, + "parent_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Parent event id in the conversation tree. None for the root, or for legacy events predating the tree (see EventLog's effective-parent rule). Events sharing a parent_id are sibling branches.", + "title": "Parent Id" + }, + "sender": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Optional identifier of the sender. Can be used to track message origin in multi-agent scenarios.", + "title": "Sender" + }, + "source": { + "enum": [ + "agent", + "user", + "environment", + "hook" + ], + "title": "Source", + "type": "string" + }, + "timestamp": { + "description": "Event timestamp", + "title": "Timestamp", + "type": "string" + } + }, + "required": [ + "source", + "llm_message", + "kind" + ], + "title": "MessageEvent", + "type": "object" + }, + "MessageToolCall": { + "description": "Transport-agnostic tool call representation.\n\nOne canonical id is used for linking across actions/observations and\nfor Responses function_call_output call_id.", + "properties": { + "arguments": { + "description": "JSON string of arguments", + "title": "Arguments", + "type": "string" + }, + "id": { + "description": "Canonical tool call id", + "title": "Id", + "type": "string" + }, + "name": { + "description": "Tool/function name", + "title": "Name", + "type": "string" + }, + "origin": { + "description": "Originating API family", + "enum": [ + "completion", + "responses" + ], + "title": "Origin", + "type": "string" + }, + "responses_item_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Original Responses function_call.id, echoed verbatim on replay", + "title": "Responses Item Id" + } + }, + "required": [ + "id", + "name", + "arguments", + "origin" + ], + "title": "MessageToolCall", + "type": "object" + }, + "MetaProfile": { + "description": "A declarative model-routing configuration.", + "properties": { + "classes": { + "description": "Ordered list of task classes and their target profiles.", + "items": { + "$ref": "#/components/schemas/MetaProfileClass" + }, + "title": "Classes", + "type": "array" + }, + "classifier_model": { + "description": "Name of the saved LLM profile used to classify the task.", + "title": "Classifier Model", + "type": "string" + }, + "model_table": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Optional text inserted into `{{ model_table }}` for direct-routing prompts.", + "title": "Model Table" + }, + "prompt_template": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Optional direct-routing prompt template. When set, the classifier receives this rendered prompt and should return JSON with a `model` field instead of a class number.", + "title": "Prompt Template" + } + }, + "required": [ + "classifier_model" + ], + "title": "MetaProfile", + "type": "object" + }, + "MetaProfileClass": { + "description": "A single task category and the LLM profile that should handle it.", + "properties": { + "description": { + "description": "Natural-language description of the kind of task this class covers (e.g. 'task is UI oriented or requires looking at images').", + "title": "Description", + "type": "string" + }, + "model": { + "description": "Name of the saved LLM profile to switch to for tasks matching this class.", + "title": "Model", + "type": "string" + } + }, + "required": [ + "description", + "model" + ], + "title": "MetaProfileClass", + "type": "object" + }, + "MetaProfileDetailResponse": { + "properties": { + "config": { + "$ref": "#/components/schemas/MetaProfile" + }, + "name": { + "title": "Name", + "type": "string" + } + }, + "required": [ + "name", + "config" + ], + "title": "MetaProfileDetailResponse", + "type": "object" + }, + "MetaProfileInfo": { + "properties": { + "classifier_model": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Classifier Model" + }, + "name": { + "title": "Name", + "type": "string" + }, + "num_classes": { + "default": 0, + "title": "Num Classes", + "type": "integer" + } + }, + "required": [ + "name" + ], + "title": "MetaProfileInfo", + "type": "object" + }, + "MetaProfileListResponse": { + "properties": { + "active_meta_profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Active Meta Profile" + }, + "meta_profiles": { + "items": { + "$ref": "#/components/schemas/MetaProfileInfo" + }, + "title": "Meta Profiles", + "type": "array" + } + }, + "required": [ + "meta_profiles" + ], + "title": "MetaProfileListResponse", + "type": "object" + }, + "MetaProfileMutationResponse": { + "properties": { + "message": { + "title": "Message", + "type": "string" + }, + "name": { + "title": "Name", + "type": "string" + } + }, + "required": [ + "name", + "message" + ], + "title": "MetaProfileMutationResponse", + "type": "object" + }, + "MetricsSnapshot": { + "description": "A snapshot of metrics at a point in time.\n\nDoes not include lists of individual costs, latencies, or token usages.", + "properties": { + "accumulated_cost": { + "default": 0.0, + "description": "Total accumulated cost, must be non-negative", + "minimum": 0.0, + "title": "Accumulated Cost", + "type": "number" + }, + "accumulated_token_usage": { + "anyOf": [ + { + "$ref": "#/components/schemas/TokenUsage" + }, + { + "type": "null" + } + ], + "description": "Accumulated token usage across all calls" + }, + "max_budget_per_task": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "description": "Maximum budget per task", + "title": "Max Budget Per Task" + }, + "model_name": { + "default": "default", + "description": "Name of the model", + "title": "Model Name", + "type": "string" + } + }, + "title": "MetricsSnapshot", + "type": "object" + }, + "ModelsResponse": { + "description": "Response containing the list of available LLM models.", + "properties": { + "models": { + "items": { + "type": "string" + }, + "title": "Models", + "type": "array" + } + }, + "required": [ + "models" + ], + "title": "ModelsResponse", + "type": "object" + }, + "NavigateConversationRequest": { + "description": "Payload to move a conversation's HEAD to an existing event.", + "properties": { + "event_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Event to make the new HEAD, re-rooting the active branch the agent runs on. All branches stay on disk; this creates no new conversation. ``None`` selects the empty tree.", + "title": "Event Id" + } + }, + "title": "NavigateConversationRequest", + "type": "object" + }, + "NeverConfirm-Input": { + "properties": { + "kind": { + "const": "NeverConfirm", + "title": "Kind", + "type": "string" + } + }, + "title": "NeverConfirm", + "type": "object" + }, + "NeverConfirm-Output": { + "properties": { + "kind": { + "const": "NeverConfirm", + "title": "Kind", + "type": "string" + } + }, + "required": [ + "kind" + ], + "title": "NeverConfirm", + "type": "object" + }, + "NoOpCondenser-Input": { + "description": "Simple condenser that returns a view un-manipulated.\n\nPrimarily intended for testing purposes.", + "properties": { + "kind": { + "const": "NoOpCondenser", + "title": "Kind", + "type": "string" + } + }, + "title": "NoOpCondenser", + "type": "object" + }, + "NoOpCondenser-Output": { + "description": "Simple condenser that returns a view un-manipulated.\n\nPrimarily intended for testing purposes.", + "properties": { + "kind": { + "const": "NoOpCondenser", + "title": "Kind", + "type": "string" + } + }, + "required": [ + "kind" + ], + "title": "NoOpCondenser", + "type": "object" + }, + "NoOpCondenserSettings": { + "description": "Settings for a condenser that leaves conversation views unchanged.", + "properties": { + "condenser_kind": { + "const": "no_op", + "default": "no_op", + "description": "Discriminator for the condenser settings union. ``'no_op'`` selects a condenser that leaves conversation views unchanged.", + "openhands_settings": { + "depends_on": [], + "prominence": "minor" + }, + "title": "Condenser Kind", + "type": "string" + }, + "enabled": { + "default": true, + "description": "Enable conversation memory condensation.", + "openhands_settings": { + "depends_on": [], + "label": "Enable memory condensation", + "prominence": "critical" + }, + "title": "Enabled", + "type": "boolean" + } + }, + "title": "NoOpCondenserSettings", + "type": "object" + }, + "Observation": { + "discriminator": { + "mapping": { + "openhands__sdk__mcp__definition__MCPToolObservation-Output__1": "#/components/schemas/MCPToolObservation", + "openhands__sdk__tool__builtins__classify_and_switch_llm__ClassifyAndSwitchLLMObservation-Output__1": "#/components/schemas/ClassifyAndSwitchLLMObservation", + "openhands__sdk__tool__builtins__finish__FinishObservation-Output__1": "#/components/schemas/FinishObservation", + "openhands__sdk__tool__builtins__invoke_skill__InvokeSkillObservation-Output__1": "#/components/schemas/InvokeSkillObservation", + "openhands__sdk__tool__builtins__switch_llm__SwitchLLMObservation-Output__1": "#/components/schemas/SwitchLLMObservation", + "openhands__sdk__tool__builtins__think__ThinkObservation-Output__1": "#/components/schemas/ThinkObservation", + "openhands__sdk__tool__builtins__vision_inspect__VisionInspectObservation-Output__1": "#/components/schemas/VisionInspectObservation", + "openhands__sdk__tool__client_tool__ClientToolObservation-Output__1": "#/components/schemas/ClientToolObservation", + "openhands__tools__ask_oracle__definition__AskOracleObservation-Output__1": "#/components/schemas/AskOracleObservation", + "openhands__tools__browser_use__definition__BrowserObservation-Output__1": "#/components/schemas/BrowserObservation", + "openhands__tools__delegate__definition__DelegateObservation-Output__1": "#/components/schemas/DelegateObservation", + "openhands__tools__file_editor__definition__FileEditorObservation-Output__1": "#/components/schemas/FileEditorObservation", + "openhands__tools__gemini__edit__definition__EditObservation-Output__1": "#/components/schemas/EditObservation", + "openhands__tools__gemini__list_directory__definition__ListDirectoryObservation-Output__1": "#/components/schemas/ListDirectoryObservation", + "openhands__tools__gemini__read_file__definition__ReadFileObservation-Output__1": "#/components/schemas/ReadFileObservation", + "openhands__tools__gemini__write_file__definition__WriteFileObservation-Output__1": "#/components/schemas/WriteFileObservation", + "openhands__tools__glob__definition__GlobObservation-Output__1": "#/components/schemas/GlobObservation", + "openhands__tools__grep__definition__GrepObservation-Output__1": "#/components/schemas/GrepObservation", + "openhands__tools__planning_file_editor__definition__PlanningFileEditorObservation-Output__1": "#/components/schemas/PlanningFileEditorObservation", + "openhands__tools__task__definition__TaskObservation-Output__1": "#/components/schemas/TaskObservation", + "openhands__tools__task_tracker__definition__TaskTrackerObservation-Output__1": "#/components/schemas/TaskTrackerObservation", + "openhands__tools__terminal__definition__TerminalObservation-Output__1": "#/components/schemas/TerminalObservation", + "openhands__tools__workflow__definition__WorkflowObservation-Output__1": "#/components/schemas/WorkflowObservation" + }, + "propertyName": "kind" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/MCPToolObservation" + }, + { + "$ref": "#/components/schemas/ClassifyAndSwitchLLMObservation" + }, + { + "$ref": "#/components/schemas/FinishObservation" + }, + { + "$ref": "#/components/schemas/InvokeSkillObservation" + }, + { + "$ref": "#/components/schemas/SwitchLLMObservation" + }, + { + "$ref": "#/components/schemas/ThinkObservation" + }, + { + "$ref": "#/components/schemas/VisionInspectObservation" + }, + { + "$ref": "#/components/schemas/ClientToolObservation" + }, + { + "$ref": "#/components/schemas/AskOracleObservation" + }, + { + "$ref": "#/components/schemas/BrowserObservation" + }, + { + "$ref": "#/components/schemas/DelegateObservation" + }, + { + "$ref": "#/components/schemas/FileEditorObservation" + }, + { + "$ref": "#/components/schemas/EditObservation" + }, + { + "$ref": "#/components/schemas/ListDirectoryObservation" + }, + { + "$ref": "#/components/schemas/ReadFileObservation" + }, + { + "$ref": "#/components/schemas/WriteFileObservation" + }, + { + "$ref": "#/components/schemas/GlobObservation" + }, + { + "$ref": "#/components/schemas/GrepObservation" + }, + { + "$ref": "#/components/schemas/PlanningFileEditorObservation" + }, + { + "$ref": "#/components/schemas/TaskObservation" + }, + { + "$ref": "#/components/schemas/TaskTrackerObservation" + }, + { + "$ref": "#/components/schemas/TerminalObservation" + }, + { + "$ref": "#/components/schemas/WorkflowObservation" + } + ] + }, + "ObservationEvent": { + "additionalProperties": false, + "properties": { + "action_id": { + "description": "The action id that this observation is responding to", + "title": "Action Id", + "type": "string" + }, + "extended_content": { + "description": "Content added by agent context (e.g. path-scoped rules triggered by the touched file), appended after the tool result in to_llm_message.", + "items": { + "$ref": "#/components/schemas/TextContent" + }, + "title": "Extended Content", + "type": "array" + }, + "id": { + "description": "Unique event id (ULID/UUID)", + "title": "Id", + "type": "string" + }, + "kind": { + "const": "ObservationEvent", + "title": "Kind", + "type": "string" + }, + "observation": { + "$ref": "#/components/schemas/Observation", + "description": "The observation (tool call) sent to LLM" + }, + "parent_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Parent event id in the conversation tree. None for the root, or for legacy events predating the tree (see EventLog's effective-parent rule). Events sharing a parent_id are sibling branches.", + "title": "Parent Id" + }, + "source": { + "default": "environment", + "enum": [ + "agent", + "user", + "environment", + "hook" + ], + "title": "Source", + "type": "string" + }, + "timestamp": { + "description": "Event timestamp", + "title": "Timestamp", + "type": "string" + }, + "tool_call_id": { + "description": "The tool call id that this observation is responding to", + "title": "Tool Call Id", + "type": "string" + }, + "tool_name": { + "description": "The tool name that this observation is responding to", + "title": "Tool Name", + "type": "string" + } + }, + "required": [ + "tool_name", + "tool_call_id", + "observation", + "action_id", + "kind" + ], + "title": "ObservationEvent", + "type": "object" + }, + "OpenHandsAgentProfile": { + "additionalProperties": false, + "description": "``agent_kind=\"openhands\"`` profile — references an LLM profile by name.\n\nMirrors the configurable surface of\n:class:`~openhands.sdk.settings.model.OpenHandsAgentSettings`, except the\nconcrete ``llm`` is replaced by :attr:`llm_profile_ref` (resolved against\nthe LLM profile store) and ``mcp_config`` by the inherited\n:attr:`~AgentProfileBase.mcp_server_refs`.", + "properties": { + "agent": { + "default": "CodeActAgent", + "description": "Agent class to build.", + "title": "Agent", + "type": "string" + }, + "agent_kind": { + "const": "openhands", + "default": "openhands", + "description": "Discriminator for the ``AgentProfile`` union. ``'openhands'`` selects the standard built-in OpenHands agent.", + "title": "Agent Kind", + "type": "string" + }, + "condenser": { + "description": "Condenser settings for the agent.", + "oneOf": [ + { + "$ref": "#/components/schemas/LLMSummarizingCondenserSettings" + }, + { + "$ref": "#/components/schemas/NoOpCondenserSettings" + } + ], + "title": "Condenser" + }, + "disabled_skills": { + "description": "Names of server-discovered skills to EXCLUDE from this agent's prompt — a deny-list over the discovered catalog. [] (the default) = all discovered skills; a listed name that is absent from the catalog is simply a no-op, so the field never fails a launch when the catalog drifts. Replaces the former allow-list ``skill_refs`` (#4017): skills are discovered from many incomplete sources, so exclusion is the only selection model that can't dangle.", + "items": { + "type": "string" + }, + "title": "Disabled Skills", + "type": "array" + }, + "enable_classify_and_switch_llm_tool": { + "default": false, + "description": "Enable the built-in route_task_to_model tool, which routes the task to an LLM profile using the meta-profile named by `meta_profile_ref`.", + "title": "Enable Classify And Switch Llm Tool", + "type": "boolean" + }, + "id": { + "description": "Stable provenance handle for this profile. Conversations record this UUID; it never changes, even when the profile is renamed.", + "format": "uuid", + "title": "Id", + "type": "string" + }, + "llm_profile_ref": { + "description": "Name of the saved LLM profile to resolve for this agent. The profile itself stores no LLM credential — it lives on the referenced LLM profile.", + "minLength": 1, + "title": "Llm Profile Ref", + "type": "string" + }, + "mcp_server_refs": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Which of the user's globally configured MCP servers to expose. null = all; [] = none; a non-null list = filter to the named keys.", + "title": "Mcp Server Refs" + }, + "meta_profile_ref": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Name of the saved meta-profile the routing tool uses. The launch copies it and the LLM profiles it routes to into the agent, so a runtime without the stores can still route. null lets the tool fall back to the first meta-profile in the runtime's store.", + "title": "Meta Profile Ref" + }, + "name": { + "description": "Human-facing, renameable key shown in the profile picker.", + "minLength": 1, + "title": "Name", + "type": "string" + }, + "persona": { + "anyOf": [ + { + "maxLength": 65536, + "minLength": 1, + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Persona text that replaces OpenHands' built-in persona and coding-workflow guidance. Capability and policy guidance (memory, security policy, risk assessment, browser, external services, process management, model-specific notes) and the dynamic context are still included. None keeps the built-in persona.", + "title": "Persona" + }, + "revision": { + "default": 0, + "description": "Monotonic revision counter, bumped on each saved edit.", + "minimum": 0.0, + "title": "Revision", + "type": "integer" + }, + "schema_version": { + "default": 3, + "minimum": 1.0, + "title": "Schema Version", + "type": "integer" + }, + "secret_refs": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Which of the user's saved secrets to expose to this agent. null = all; [] = none; a non-null list = filter to the named keys. Strict: nothing is added back. An ACP profile must list its own provider credential to receive it.", + "title": "Secret Refs" + }, + "system_message_suffix": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Optional suffix appended to the system prompt.", + "title": "System Message Suffix" + }, + "tool_concurrency_limit": { + "default": 1, + "description": "Maximum number of tool calls to execute concurrently per agent step. 1 = sequential (default).", + "minimum": 1.0, + "title": "Tool Concurrency Limit", + "type": "integer" + }, + "tools": { + "anyOf": [ + { + "items": { + "$ref": "#/components/schemas/Tool-Input" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Tool selection for the resolved agent. None (the default) = the server's standard tool set; [] = an explicitly bare agent; a non-empty list is used exactly as given.", + "title": "Tools" + }, + "verification": { + "$ref": "#/components/schemas/ProfileVerificationSettings", + "description": "Critic/verification policy (secret-free; no critic_api_key)." + } + }, + "required": [ + "name", + "llm_profile_ref" ], - "summary": "Alive", - "description": "Basic liveness check - returns OK if the server process is running.", - "operationId": "alive_alive_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {} + "title": "OpenHandsAgentProfile", + "type": "object" + }, + "OrgConfig": { + "description": "Configuration for loading organization-level skills.", + "properties": { + "org_name": { + "description": "Organization name", + "title": "Org Name", + "type": "string" + }, + "org_repo_url": { + "description": "Pre-authenticated Git URL for the organization repository. Contains sensitive credentials - handle with care and avoid logging.", + "title": "Org Repo Url", + "type": "string" + }, + "provider": { + "description": "Git provider type: github, gitlab, azure, bitbucket", + "title": "Provider", + "type": "string" + }, + "repository": { + "description": "Selected repository (e.g., 'owner/repo')", + "title": "Repository", + "type": "string" + } + }, + "required": [ + "repository", + "provider", + "org_repo_url", + "org_name" + ], + "title": "OrgConfig", + "type": "object" + }, + "PassCritic-Input": { + "description": "Critic that always returns success.\n\nThis critic can be used when no evaluation is needed or when\nall instances should be considered successful regardless of their output.", + "properties": { + "iterative_refinement": { + "anyOf": [ + { + "$ref": "#/components/schemas/IterativeRefinementConfig" + }, + { + "type": "null" } - } + ], + "description": "Optional configuration for iterative refinement. When set, Conversation.run() will automatically retry the task if the critic score is below the success_threshold, up to max_iterations." + }, + "kind": { + "const": "PassCritic", + "title": "Kind", + "type": "string" + }, + "mode": { + "default": "finish_and_message", + "description": "When to run critic evaluation:\n- 'finish_and_message': Evaluate on FinishAction and agent MessageEvent (default, minimal performance impact)\n- 'all_actions': Evaluate after every agent action (WARNING: significantly slower due to API calls on each action)", + "enum": [ + "finish_and_message", + "all_actions" + ], + "title": "Mode", + "type": "string" + } + }, + "title": "PassCritic", + "type": "object" + }, + "PassCritic-Output": { + "description": "Critic that always returns success.\n\nThis critic can be used when no evaluation is needed or when\nall instances should be considered successful regardless of their output.", + "properties": { + "iterative_refinement": { + "anyOf": [ + { + "$ref": "#/components/schemas/IterativeRefinementConfig" + }, + { + "type": "null" + } + ], + "description": "Optional configuration for iterative refinement. When set, Conversation.run() will automatically retry the task if the critic score is below the success_threshold, up to max_iterations." + }, + "kind": { + "const": "PassCritic", + "title": "Kind", + "type": "string" + }, + "mode": { + "default": "finish_and_message", + "description": "When to run critic evaluation:\n- 'finish_and_message': Evaluate on FinishAction and agent MessageEvent (default, minimal performance impact)\n- 'all_actions': Evaluate after every agent action (WARNING: significantly slower due to API calls on each action)", + "enum": [ + "finish_and_message", + "all_actions" + ], + "title": "Mode", + "type": "string" + } + }, + "required": [ + "kind" + ], + "title": "PassCritic", + "type": "object" + }, + "PathTrigger": { + "description": "Trigger for path-scoped skills (\"rules\").\n\nThese skills are activated when the agent touches a file whose path matches\none of the ``paths`` glob patterns (gitignore-style ``**`` semantics).", + "properties": { + "paths": { + "items": { + "type": "string" + }, + "title": "Paths", + "type": "array" + }, + "type": { + "const": "path", + "default": "path", + "title": "Type", + "type": "string" + } + }, + "required": [ + "paths" + ], + "title": "PathTrigger", + "type": "object" + }, + "PatternSecurityAnalyzer-Input": { + "description": "Catch dangerous agent actions through deterministic signature scanning.\n\nUse this when you want fast, local, no-network threat detection at the\naction boundary. It returns ``SecurityRisk.HIGH``, ``MEDIUM``, or ``LOW``\n-- pair it with ``ConfirmRisky`` to decide what gets confirmed.\n\nThe key design choice: shell-destructive patterns only scan what the\nagent will *execute* (tool arguments), never what it *thought about*\n(reasoning text). Injection patterns scan everything, because\n\"ignore all previous instructions\" is dangerous wherever it appears.\n\nNormalization is always on -- invisible characters and fullwidth\nsubstitutions are collapsed before matching.\n\nExample::\n\n from openhands.sdk.security import PatternSecurityAnalyzer, ConfirmRisky\n\n analyzer = PatternSecurityAnalyzer()\n policy = ConfirmRisky(threshold=SecurityRisk.MEDIUM)", + "properties": { + "high_patterns": { + "description": "HIGH patterns scanned against executable fields only", + "items": { + "maxItems": 3, + "minItems": 3, + "prefixItems": [ + { + "type": "string" + }, + { + "type": "string" + }, + { + "type": "string" + } + ], + "type": "array" + }, + "title": "High Patterns", + "type": "array" + }, + "injection_high_patterns": { + "description": "HIGH patterns scanned against all fields", + "items": { + "maxItems": 3, + "minItems": 3, + "prefixItems": [ + { + "type": "string" + }, + { + "type": "string" + }, + { + "type": "string" + } + ], + "type": "array" + }, + "title": "Injection High Patterns", + "type": "array" + }, + "injection_medium_patterns": { + "description": "MEDIUM patterns scanned against all fields", + "items": { + "maxItems": 3, + "minItems": 3, + "prefixItems": [ + { + "type": "string" + }, + { + "type": "string" + }, + { + "type": "string" + } + ], + "type": "array" + }, + "title": "Injection Medium Patterns", + "type": "array" + }, + "kind": { + "const": "PatternSecurityAnalyzer", + "title": "Kind", + "type": "string" + }, + "medium_patterns": { + "description": "MEDIUM patterns scanned against executable fields only", + "items": { + "maxItems": 3, + "minItems": 3, + "prefixItems": [ + { + "type": "string" + }, + { + "type": "string" + }, + { + "type": "string" + } + ], + "type": "array" + }, + "title": "Medium Patterns", + "type": "array" + } + }, + "title": "PatternSecurityAnalyzer", + "type": "object" + }, + "PatternSecurityAnalyzer-Output": { + "description": "Catch dangerous agent actions through deterministic signature scanning.\n\nUse this when you want fast, local, no-network threat detection at the\naction boundary. It returns ``SecurityRisk.HIGH``, ``MEDIUM``, or ``LOW``\n-- pair it with ``ConfirmRisky`` to decide what gets confirmed.\n\nThe key design choice: shell-destructive patterns only scan what the\nagent will *execute* (tool arguments), never what it *thought about*\n(reasoning text). Injection patterns scan everything, because\n\"ignore all previous instructions\" is dangerous wherever it appears.\n\nNormalization is always on -- invisible characters and fullwidth\nsubstitutions are collapsed before matching.\n\nExample::\n\n from openhands.sdk.security import PatternSecurityAnalyzer, ConfirmRisky\n\n analyzer = PatternSecurityAnalyzer()\n policy = ConfirmRisky(threshold=SecurityRisk.MEDIUM)", + "properties": { + "high_patterns": { + "description": "HIGH patterns scanned against executable fields only", + "items": { + "maxItems": 3, + "minItems": 3, + "prefixItems": [ + { + "type": "string" + }, + { + "type": "string" + }, + { + "type": "string" + } + ], + "type": "array" + }, + "title": "High Patterns", + "type": "array" + }, + "injection_high_patterns": { + "description": "HIGH patterns scanned against all fields", + "items": { + "maxItems": 3, + "minItems": 3, + "prefixItems": [ + { + "type": "string" + }, + { + "type": "string" + }, + { + "type": "string" + } + ], + "type": "array" + }, + "title": "Injection High Patterns", + "type": "array" + }, + "injection_medium_patterns": { + "description": "MEDIUM patterns scanned against all fields", + "items": { + "maxItems": 3, + "minItems": 3, + "prefixItems": [ + { + "type": "string" + }, + { + "type": "string" + }, + { + "type": "string" + } + ], + "type": "array" + }, + "title": "Injection Medium Patterns", + "type": "array" + }, + "kind": { + "const": "PatternSecurityAnalyzer", + "title": "Kind", + "type": "string" + }, + "medium_patterns": { + "description": "MEDIUM patterns scanned against executable fields only", + "items": { + "maxItems": 3, + "minItems": 3, + "prefixItems": [ + { + "type": "string" + }, + { + "type": "string" + }, + { + "type": "string" + } + ], + "type": "array" + }, + "title": "Medium Patterns", + "type": "array" } - } - } - }, - "/health": { - "get": { - "tags": [ - "Server Details" + }, + "required": [ + "kind" ], - "summary": "Health", - "description": "Basic health check - returns OK if the server process is running.", - "operationId": "health_health_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "type": "string", - "title": "Response Health Health Get" - } + "title": "PatternSecurityAnalyzer", + "type": "object" + }, + "PauseEvent": { + "additionalProperties": false, + "description": "Event indicating that the agent execution was paused by user request.", + "properties": { + "id": { + "description": "Unique event id (ULID/UUID)", + "title": "Id", + "type": "string" + }, + "kind": { + "const": "PauseEvent", + "title": "Kind", + "type": "string" + }, + "parent_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" } - } + ], + "description": "Parent event id in the conversation tree. None for the root, or for legacy events predating the tree (see EventLog's effective-parent rule). Events sharing a parent_id are sibling branches.", + "title": "Parent Id" + }, + "source": { + "default": "user", + "enum": [ + "agent", + "user", + "environment", + "hook" + ], + "title": "Source", + "type": "string" + }, + "timestamp": { + "description": "Event timestamp", + "title": "Timestamp", + "type": "string" } - } - } - }, - "/ready": { - "get": { - "tags": [ - "Server Details" + }, + "required": [ + "kind" ], - "summary": "Ready", - "description": "Readiness check - returns OK only if the server has completed initialization.\n\nThis endpoint should be used by Kubernetes readiness probes to determine\nwhen the pod is ready to receive traffic. Returns 503 during initialization.", - "operationId": "ready_ready_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "additionalProperties": { - "type": "string" - }, - "type": "object", - "title": "Response Ready Ready Get" - } - } - } + "title": "PauseEvent", + "type": "object" + }, + "PipelineCondenser-Input": { + "description": "A condenser that applies a sequence of condensers in order.\n\nAll condensers are defined primarily by their `condense` method, which takes a\n`View` and an optional `agent_llm` parameter, returning either a new `View` or a\n`Condensation` event. That means we can chain multiple condensers together by\npassing `View`s along and exiting early if any condenser returns a `Condensation`.\n\nFor example:\n\n # Use the pipeline condenser to chain multiple other condensers together\n condenser = PipelineCondenser(condensers=[\n CondenserA(...),\n CondenserB(...),\n CondenserC(...),\n ])\n\n result = condenser.condense(view, agent_llm=agent_llm)\n\n # Doing the same thing without the pipeline condenser requires more boilerplate\n # for the monadic chaining\n other_result = view\n\n if isinstance(other_result, View):\n other_result = CondenserA(...).condense(other_result, agent_llm=agent_llm)\n\n if isinstance(other_result, View):\n other_result = CondenserB(...).condense(other_result, agent_llm=agent_llm)\n\n if isinstance(other_result, View):\n other_result = CondenserC(...).condense(other_result, agent_llm=agent_llm)\n\n assert result == other_result", + "properties": { + "condensers": { + "items": { + "$ref": "#/components/schemas/CondenserBase-Input" + }, + "title": "Condensers", + "type": "array" + }, + "kind": { + "const": "PipelineCondenser", + "title": "Kind", + "type": "string" } - } - } - }, - "/server_info": { - "get": { - "tags": [ - "Server Details" + }, + "required": [ + "condensers" ], - "summary": "Get Server Info", - "operationId": "get_server_info_server_info_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ServerInfo" - } - } - } + "title": "PipelineCondenser", + "type": "object" + }, + "PipelineCondenser-Output": { + "description": "A condenser that applies a sequence of condensers in order.\n\nAll condensers are defined primarily by their `condense` method, which takes a\n`View` and an optional `agent_llm` parameter, returning either a new `View` or a\n`Condensation` event. That means we can chain multiple condensers together by\npassing `View`s along and exiting early if any condenser returns a `Condensation`.\n\nFor example:\n\n # Use the pipeline condenser to chain multiple other condensers together\n condenser = PipelineCondenser(condensers=[\n CondenserA(...),\n CondenserB(...),\n CondenserC(...),\n ])\n\n result = condenser.condense(view, agent_llm=agent_llm)\n\n # Doing the same thing without the pipeline condenser requires more boilerplate\n # for the monadic chaining\n other_result = view\n\n if isinstance(other_result, View):\n other_result = CondenserA(...).condense(other_result, agent_llm=agent_llm)\n\n if isinstance(other_result, View):\n other_result = CondenserB(...).condense(other_result, agent_llm=agent_llm)\n\n if isinstance(other_result, View):\n other_result = CondenserC(...).condense(other_result, agent_llm=agent_llm)\n\n assert result == other_result", + "properties": { + "condensers": { + "items": { + "$ref": "#/components/schemas/CondenserBase-Output" + }, + "title": "Condensers", + "type": "array" + }, + "kind": { + "const": "PipelineCondenser", + "title": "Kind", + "type": "string" } - } - } - }, - "/api/conversations/{conversation_id}/events/search": { - "get": { - "tags": [ - "Events" + }, + "required": [ + "condensers", + "kind" ], - "summary": "Search Conversation Events", - "description": "Search / List local events", - "operationId": "search_conversation_events_api_conversations__conversation_id__events_search_get", - "parameters": [ - { - "name": "conversation_id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid", - "title": "Conversation Id" - } + "title": "PipelineCondenser", + "type": "object" + }, + "PlanningFileEditorAction": { + "additionalProperties": false, + "description": "Schema for planning file editor operations.\n\nInherits from FileEditorAction but restricts editing to PLAN.md only.\nAllows viewing any file but only editing PLAN.md.", + "properties": { + "command": { + "description": "The commands to run. Allowed options are: `view`, `create`, `str_replace`, `insert`, `undo_edit`.", + "enum": [ + "view", + "create", + "str_replace", + "insert", + "undo_edit" + ], + "title": "Command", + "type": "string" }, - { - "name": "page_id", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Optional next_page_id from the previously returned page" - } + "file_text": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Required parameter of `create` command, with the content of the file to be created.", + "title": "File Text" }, - { - "name": "limit", - "in": "query", - "required": false, - "schema": { - "type": "integer", - "exclusiveMinimum": 0, - "title": "The max number of results in the page", - "lte": 100, - "default": 100 - } + "insert_line": { + "anyOf": [ + { + "minimum": 0.0, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Required parameter of `insert` command. The `new_str` will be inserted AFTER the line `insert_line` of `path`.", + "title": "Insert Line" + }, + "kind": { + "const": "PlanningFileEditorAction", + "title": "Kind", + "type": "string" + }, + "new_str": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Optional parameter of `str_replace` command containing the new string (if not given, no string will be added). Required parameter of `insert` command containing the string to insert.", + "title": "New Str" + }, + "old_str": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Required parameter of `str_replace` command containing the string in `path` to replace.", + "title": "Old Str" + }, + "path": { + "description": "Absolute path to file or directory.", + "title": "Path", + "type": "string" + }, + "view_range": { + "anyOf": [ + { + "items": { + "type": "integer" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Optional parameter of `view` command when `path` points to a file. If none is given, the full file is shown. If provided, the file will be shown in the indicated line number range, e.g. [11, 12] will show lines 11 and 12. Indexing at 1 to start. Setting `[start_line, -1]` shows all lines from `start_line` to the end of the file.", + "title": "View Range" + } + }, + "required": [ + "command", + "path", + "kind" + ], + "title": "PlanningFileEditorAction", + "type": "object" + }, + "PlanningFileEditorObservation": { + "additionalProperties": false, + "description": "Observation from planning file editor operations.\n\nInherits from FileEditorObservation - same structure, just different type.", + "properties": { + "command": { + "description": "The command that was run: `view`, `create`, `str_replace`, `insert`, or `undo_edit`.", + "enum": [ + "view", + "create", + "str_replace", + "insert", + "undo_edit" + ], + "title": "Command", + "type": "string" }, - { - "name": "kind", - "in": "query", - "required": false, - "schema": { + "content": { + "description": "Content returned from the tool as a list of TextContent/ImageContent objects. When there is an error, it should be written in this field.", + "items": { "anyOf": [ { - "type": "string" + "$ref": "#/components/schemas/TextContent" }, { - "type": "null" + "$ref": "#/components/schemas/ImageContent" } - ], - "title": "Optional filter by event kind/type (e.g., ActionEvent, MessageEvent)" - } + ] + }, + "title": "Content", + "type": "array" }, - { - "name": "source", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Optional filter by event source (e.g., agent, user, environment)" - } + "is_error": { + "default": false, + "description": "Whether the observation indicates an error", + "title": "Is Error", + "type": "boolean" }, - { - "name": "body", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Optional filter by message content (case-insensitive)" - } + "kind": { + "const": "PlanningFileEditorObservation", + "title": "Kind", + "type": "string" }, - { - "name": "sort_order", - "in": "query", - "required": false, - "schema": { - "$ref": "#/components/schemas/EventSortOrder", - "title": "Sort order for events", - "default": "TIMESTAMP" - } + "new_content": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The content of the file after the edit.", + "title": "New Content" }, - { - "name": "timestamp__gte", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { - "type": "string", - "format": "date-time" - }, - { - "type": "null" - } - ], - "title": "Filter: event timestamp >= this datetime" - } + "old_content": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The content of the file before the edit.", + "title": "Old Content" }, - { - "name": "timestamp__lt", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { - "type": "string", - "format": "date-time" - }, - { - "type": "null" - } - ], - "title": "Filter: event timestamp < this datetime" - } + "path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The file path that was edited.", + "title": "Path" + }, + "prev_exist": { + "default": true, + "description": "Indicates if the file previously existed. If not, it was created.", + "title": "Prev Exist", + "type": "boolean" } + }, + "required": [ + "command", + "kind" ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EventPage" - } + "title": "PlanningFileEditorObservation", + "type": "object" + }, + "PlanningFileEditorTool": { + "description": "A planning file editor tool with read-all, edit-PLAN.md-only access.", + "properties": { + "action_type": { + "title": "Action Type", + "type": "string" + }, + "annotations": { + "anyOf": [ + { + "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" + }, + { + "type": "null" } - } + ] }, - "404": { - "description": "Conversation not found" + "description": { + "title": "Description", + "type": "string" }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "kind": { + "const": "PlanningFileEditorTool", + "title": "Kind", + "type": "string" + }, + "meta": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" } - } + ], + "title": "Meta" + }, + "observation_type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Observation Type" + }, + "title": { + "readOnly": true, + "title": "Title", + "type": "string" } - } - } - }, - "/api/conversations/{conversation_id}/events/count": { - "get": { - "tags": [ - "Events" + }, + "required": [ + "description", + "action_type", + "kind", + "title" ], - "summary": "Count Conversation Events", - "description": "Count local events matching the given filters", - "operationId": "count_conversation_events_api_conversations__conversation_id__events_count_get", - "parameters": [ - { - "name": "conversation_id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid", - "title": "Conversation Id" - } - }, - { - "name": "kind", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Optional filter by event kind/type (e.g., ActionEvent, MessageEvent)" - } + "title": "PlanningFileEditorTool", + "type": "object" + }, + "PluginInfo": { + "description": "Summary of an available plugin.", + "properties": { + "description": { + "default": "", + "title": "Description", + "type": "string" }, - { - "name": "source", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Optional filter by event source (e.g., agent, user, environment)" - } + "files": { + "description": "Plugin files, relative to the plugin directory", + "items": { + "type": "string" + }, + "title": "Files", + "type": "array" }, - { - "name": "body", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Optional filter by message content (case-insensitive)" - } + "name": { + "title": "Name", + "type": "string" }, - { - "name": "timestamp__gte", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { - "type": "string", - "format": "date-time" - }, - { - "type": "null" - } - ], - "title": "Filter: event timestamp >= this datetime" - } + "path": { + "default": "", + "description": "Path to the plugin directory", + "title": "Path", + "type": "string" }, - { - "name": "timestamp__lt", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { - "type": "string", - "format": "date-time" - }, - { - "type": "null" - } - ], - "title": "Filter: event timestamp < this datetime" - } + "skills": { + "description": "Skills bundled in the plugin", + "items": { + "$ref": "#/components/schemas/PluginSkillSummary" + }, + "title": "Skills", + "type": "array" + }, + "version": { + "default": "", + "title": "Version", + "type": "string" } + }, + "required": [ + "name" ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "type": "integer", - "title": "Response Count Conversation Events Api Conversations Conversation Id Events Count Get" - } + "title": "PluginInfo", + "type": "object" + }, + "PluginSkillSummary": { + "description": "Summary of a skill bundled in a plugin.", + "properties": { + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" } - } - }, - "404": { - "description": "Conversation not found" + ], + "title": "Description" }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } + "name": { + "title": "Name", + "type": "string" } - } - } - }, - "/api/conversations/{conversation_id}/events/{event_id}": { - "get": { - "tags": [ - "Events" + }, + "required": [ + "name" ], - "summary": "Get Conversation Event", - "description": "Get a local event given an id", - "operationId": "get_conversation_event_api_conversations__conversation_id__events__event_id__get", - "parameters": [ - { - "name": "event_id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "title": "Event Id" - } + "title": "PluginSkillSummary", + "type": "object" + }, + "PluginSource": { + "description": "Specification for a plugin to load.\n\nThis model describes where to find a plugin and is used by load_plugins()\nto fetch and load plugins from various sources.\n\nExamples:\n >>> # GitHub repository\n >>> PluginSource(source=\"github:owner/repo\", ref=\"v1.0.0\")\n\n >>> # Plugin from monorepo subdirectory\n >>> PluginSource(\n ... source=\"github:owner/monorepo\",\n ... repo_path=\"plugins/my-plugin\"\n ... )\n\n >>> # Local path\n >>> PluginSource(source=\"/path/to/plugin\")", + "properties": { + "ref": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Optional branch, tag, or commit (only for git sources)", + "title": "Ref" }, - { - "name": "conversation_id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid", - "title": "Conversation Id" - } + "repo_path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Subdirectory path within the git repository (e.g., 'plugins/my-plugin' for monorepos). Only relevant for git sources, not local paths.", + "title": "Repo Path" + }, + "source": { + "description": "Plugin source: 'github:owner/repo', any git URL, or local path", + "title": "Source", + "type": "string" } + }, + "required": [ + "source" ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Event" - } - } - } + "title": "PluginSource", + "type": "object" + }, + "PluginsRequest": { + "description": "Request body for listing locally-available plugins.", + "properties": { + "load_project": { + "default": true, + "description": "Load project plugins from the workspace", + "title": "Load Project", + "type": "boolean" }, - "404": { - "description": "Item not found" + "load_user": { + "default": true, + "description": "Load user plugins (~/.agents/plugins, etc.)", + "title": "Load User", + "type": "boolean" }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "project_dir": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" } - } + ], + "description": "Workspace directory path for project plugins", + "title": "Project Dir" } - } - } - }, - "/api/conversations/{conversation_id}/events": { - "get": { - "tags": [ - "Events" + }, + "title": "PluginsRequest", + "type": "object" + }, + "PluginsResponse": { + "description": "Response containing the locally-available plugins.", + "properties": { + "plugins": { + "items": { + "$ref": "#/components/schemas/PluginInfo" + }, + "title": "Plugins", + "type": "array" + } + }, + "required": [ + "plugins" ], - "summary": "Batch Get Conversation Events", - "description": "Get a batch of local events given their ids, returning null for any\nmissing item.", - "operationId": "batch_get_conversation_events_api_conversations__conversation_id__events_get", - "parameters": [ - { - "name": "conversation_id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid", - "title": "Conversation Id" - } + "title": "PluginsResponse", + "type": "object" + }, + "PolicyRailSecurityAnalyzer-Input": { + "description": "Catch composed threats that plain regex signatures would miss.\n\nUse this when you need to detect threats defined by *combinations*\nof tokens (e.g., ``curl`` piped to ``bash``) rather than individual\nsignatures. While these rails *could* each be expressed as a single\nregex, keeping them as named rules with per-segment evaluation makes\nthe threat model more interpretable, the rules easier to maintain,\nand the audit trail clearer than a flat pattern list.\n\nEvaluates normalized executable segments only -- reasoning text is\nnever scanned.\n\nReturns ``SecurityRisk.HIGH`` when a rail fires, ``LOW`` otherwise.\nPair with ``ConfirmRisky`` and compose via ``EnsembleSecurityAnalyzer``.\n\nv1 rails: fetch-to-exec, raw-disk-op, catastrophic-delete.\n\nExample::\n\n from openhands.sdk.security import PolicyRailSecurityAnalyzer\n\n analyzer = PolicyRailSecurityAnalyzer()\n # risk = analyzer.security_risk(action)", + "properties": { + "kind": { + "const": "PolicyRailSecurityAnalyzer", + "title": "Kind", + "type": "string" + } + }, + "title": "PolicyRailSecurityAnalyzer", + "type": "object" + }, + "PolicyRailSecurityAnalyzer-Output": { + "description": "Catch composed threats that plain regex signatures would miss.\n\nUse this when you need to detect threats defined by *combinations*\nof tokens (e.g., ``curl`` piped to ``bash``) rather than individual\nsignatures. While these rails *could* each be expressed as a single\nregex, keeping them as named rules with per-segment evaluation makes\nthe threat model more interpretable, the rules easier to maintain,\nand the audit trail clearer than a flat pattern list.\n\nEvaluates normalized executable segments only -- reasoning text is\nnever scanned.\n\nReturns ``SecurityRisk.HIGH`` when a rail fires, ``LOW`` otherwise.\nPair with ``ConfirmRisky`` and compose via ``EnsembleSecurityAnalyzer``.\n\nv1 rails: fetch-to-exec, raw-disk-op, catastrophic-delete.\n\nExample::\n\n from openhands.sdk.security import PolicyRailSecurityAnalyzer\n\n analyzer = PolicyRailSecurityAnalyzer()\n # risk = analyzer.security_risk(action)", + "properties": { + "kind": { + "const": "PolicyRailSecurityAnalyzer", + "title": "Kind", + "type": "string" + } + }, + "required": [ + "kind" + ], + "title": "PolicyRailSecurityAnalyzer", + "type": "object" + }, + "ProfileDetailResponse": { + "description": "``config.api_key`` is always nulled; use ``api_key_set`` instead.", + "properties": { + "api_key_set": { + "default": false, + "title": "Api Key Set", + "type": "boolean" + }, + "config": { + "additionalProperties": true, + "title": "Config", + "type": "object" + }, + "name": { + "title": "Name", + "type": "string" } + }, + "required": [ + "name", + "config" ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "type": "string" - }, - "title": "Event Ids" + "title": "ProfileDetailResponse", + "type": "object" + }, + "ProfileInfo": { + "properties": { + "api_key_set": { + "default": false, + "title": "Api Key Set", + "type": "boolean" + }, + "base_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Base Url" + }, + "model": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" } - } + ], + "title": "Model" + }, + "name": { + "title": "Name", + "type": "string" + }, + "provider_connection_broken": { + "default": false, + "title": "Provider Connection Broken", + "type": "boolean" + }, + "provider_connection_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Provider Connection Id" } }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "anyOf": [ - { - "$ref": "#/components/schemas/Event" - }, - { - "type": "null" - } - ] - }, - "title": "Response Batch Get Conversation Events Api Conversations Conversation Id Events Get" - } + "required": [ + "name" + ], + "title": "ProfileInfo", + "type": "object" + }, + "ProfileListResponse": { + "properties": { + "active_profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" } - } + ], + "title": "Active Profile" }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } + "profiles": { + "items": { + "$ref": "#/components/schemas/ProfileInfo" + }, + "title": "Profiles", + "type": "array" } - } - }, - "post": { - "tags": [ - "Events" + }, + "required": [ + "profiles" ], - "summary": "Send Message", - "description": "Send a message to a conversation", - "operationId": "send_message_api_conversations__conversation_id__events_post", - "parameters": [ - { - "name": "conversation_id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid", - "title": "Conversation Id" - } + "title": "ProfileListResponse", + "type": "object" + }, + "ProfileMutationResponse": { + "properties": { + "message": { + "title": "Message", + "type": "string" + }, + "name": { + "title": "Name", + "type": "string" } + }, + "required": [ + "name", + "message" ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SendMessageRequest" + "title": "ProfileMutationResponse", + "type": "object" + }, + "ProfileVerificationSettings": { + "description": "Secret-free critic/refinement policy for a profile.\n\nThe non-credential subset of\n:class:`~openhands.sdk.settings.model.VerificationSettings`: ``critic_api_key``\nis omitted so the profile holds no secret. The critic reuses the resolved\nLLM profile's key (the existing ``critic_api_key=None`` behavior).", + "properties": { + "critic_enabled": { + "default": false, + "title": "Critic Enabled", + "type": "boolean" + }, + "critic_mode": { + "default": "finish_and_message", + "enum": [ + "finish_and_message", + "all_actions" + ], + "title": "Critic Mode", + "type": "string" + }, + "critic_model_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" } - } + ], + "title": "Critic Model Name" + }, + "critic_server_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Critic Server Url" + }, + "critic_threshold": { + "default": 0.6, + "maximum": 1.0, + "minimum": 0.0, + "title": "Critic Threshold", + "type": "number" + }, + "enable_iterative_refinement": { + "default": false, + "title": "Enable Iterative Refinement", + "type": "boolean" + }, + "max_refinement_iterations": { + "default": 3, + "minimum": 1.0, + "title": "Max Refinement Iterations", + "type": "integer" } }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Success" - } - } - } + "title": "ProfileVerificationSettings", + "type": "object" + }, + "ProviderConnectionCreateRequest": { + "additionalProperties": false, + "properties": { + "api_key": { + "format": "password", + "minLength": 1, + "title": "Api Key", + "type": "string", + "writeOnly": true }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "base_url": { + "anyOf": [ + { + "maxLength": 2048, + "type": "string" + }, + { + "type": "null" } - } + ], + "title": "Base Url" + }, + "display_name": { + "maxLength": 128, + "minLength": 1, + "title": "Display Name", + "type": "string" + }, + "provider": { + "default": "custom", + "maxLength": 128, + "minLength": 1, + "title": "Provider", + "type": "string" } - } - } - }, - "/api/conversations/{conversation_id}/events/respond_to_confirmation": { - "post": { - "tags": [ - "Events" + }, + "required": [ + "display_name", + "api_key" ], - "summary": "Respond To Confirmation", - "description": "Accept or reject a pending action in confirmation mode.", - "operationId": "respond_to_confirmation_api_conversations__conversation_id__events_respond_to_confirmation_post", - "parameters": [ - { - "name": "conversation_id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid", - "title": "Conversation Id" - } + "title": "ProviderConnectionCreateRequest", + "type": "object" + }, + "ProviderConnectionResponse": { + "properties": { + "api_key_set": { + "default": false, + "title": "Api Key Set", + "type": "boolean" + }, + "base_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Base Url" + }, + "created_at": { + "title": "Created At", + "type": "integer" + }, + "display_name": { + "title": "Display Name", + "type": "string" + }, + "id": { + "title": "Id", + "type": "string" + }, + "provider": { + "title": "Provider", + "type": "string" + }, + "updated_at": { + "title": "Updated At", + "type": "integer" } + }, + "required": [ + "id", + "display_name", + "provider", + "created_at", + "updated_at" ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ConfirmationResponseRequest" + "title": "ProviderConnectionResponse", + "type": "object" + }, + "ProviderConnectionUpdateRequest": { + "additionalProperties": false, + "properties": { + "api_key": { + "anyOf": [ + { + "format": "password", + "type": "string", + "writeOnly": true + }, + { + "type": "null" + } + ], + "title": "Api Key" + }, + "base_url": { + "anyOf": [ + { + "maxLength": 2048, + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Base Url" + }, + "display_name": { + "anyOf": [ + { + "maxLength": 128, + "minLength": 1, + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Display Name" + }, + "provider": { + "anyOf": [ + { + "maxLength": 128, + "minLength": 1, + "type": "string" + }, + { + "type": "null" } - } + ], + "title": "Provider" } }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Success" - } - } - } + "title": "ProviderConnectionUpdateRequest", + "type": "object" + }, + "ProvidersResponse": { + "description": "Response containing the list of available LLM providers.", + "properties": { + "providers": { + "items": { + "type": "string" + }, + "title": "Providers", + "type": "array" + } + }, + "required": [ + "providers" + ], + "title": "ProvidersResponse", + "type": "object" + }, + "ReadFileAction": { + "additionalProperties": false, + "description": "Schema for read file operation.", + "properties": { + "file_path": { + "description": "The path to the file to read.", + "title": "File Path", + "type": "string" }, - "404": { - "description": "Item not found" + "kind": { + "const": "ReadFileAction", + "title": "Kind", + "type": "string" }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "limit": { + "anyOf": [ + { + "minimum": 1.0, + "type": "integer" + }, + { + "type": "null" } - } + ], + "description": "Optional: Maximum number of lines to read. Use with 'offset' to paginate through large files.", + "title": "Limit" + }, + "offset": { + "anyOf": [ + { + "minimum": 0.0, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Optional: The 0-based line number to start reading from. Use for paginating through large files.", + "title": "Offset" } - } - } - }, - "/api/conversations/search": { - "get": { - "tags": [ - "Conversations" + }, + "required": [ + "file_path", + "kind" ], - "summary": "Search Conversations", - "description": "Search / List conversations", - "operationId": "search_conversations_api_conversations_search_get", - "parameters": [ - { - "name": "page_id", - "in": "query", - "required": false, - "schema": { + "title": "ReadFileAction", + "type": "object" + }, + "ReadFileObservation": { + "additionalProperties": false, + "description": "Observation from reading a file.", + "properties": { + "content": { + "description": "Content returned from the tool as a list of TextContent/ImageContent objects. When there is an error, it should be written in this field.", + "items": { "anyOf": [ { - "type": "string" + "$ref": "#/components/schemas/TextContent" }, { - "type": "null" + "$ref": "#/components/schemas/ImageContent" } - ], - "title": "Optional next_page_id from the previously returned page" - } + ] + }, + "title": "Content", + "type": "array" }, - { - "name": "limit", - "in": "query", - "required": false, - "schema": { - "type": "integer", - "exclusiveMinimum": 0, - "title": "The max number of results in the page", - "lte": 100, - "default": 100 - } + "file_content": { + "default": "", + "description": "The content read from the file.", + "title": "File Content", + "type": "string" }, - { - "name": "status", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { - "$ref": "#/components/schemas/ConversationExecutionStatus" - }, - { - "type": "null" - } - ], - "title": "Optional filter by conversation execution status" - } + "file_path": { + "description": "The file path that was read.", + "title": "File Path", + "type": "string" }, - { - "name": "sort_order", - "in": "query", - "required": false, - "schema": { - "$ref": "#/components/schemas/ConversationSortOrder", - "title": "Sort order for conversations", - "default": "CREATED_AT_DESC" - } + "is_error": { + "default": false, + "description": "Whether the observation indicates an error", + "title": "Is Error", + "type": "boolean" + }, + "is_truncated": { + "default": false, + "description": "Whether the content was truncated due to size limits.", + "title": "Is Truncated", + "type": "boolean" + }, + "kind": { + "const": "ReadFileObservation", + "title": "Kind", + "type": "string" + }, + "lines_shown": { + "anyOf": [ + { + "maxItems": 2, + "minItems": 2, + "prefixItems": [ + { + "type": "integer" + }, + { + "type": "integer" + } + ], + "type": "array" + }, + { + "type": "null" + } + ], + "description": "If truncated, the range of lines shown (start, end) - 1-indexed.", + "title": "Lines Shown" + }, + "total_lines": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Total number of lines in the file.", + "title": "Total Lines" } + }, + "required": [ + "file_path", + "kind" ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ConversationPage" - } + "title": "ReadFileObservation", + "type": "object" + }, + "ReadFileTool": { + "description": "Tool for reading file contents with pagination support.", + "properties": { + "action_type": { + "title": "Action Type", + "type": "string" + }, + "annotations": { + "anyOf": [ + { + "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" + }, + { + "type": "null" + } + ] + }, + "description": { + "title": "Description", + "type": "string" + }, + "kind": { + "const": "ReadFileTool", + "title": "Kind", + "type": "string" + }, + "meta": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Meta" + }, + "observation_type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Observation Type" + }, + "title": { + "readOnly": true, + "title": "Title", + "type": "string" + } + }, + "required": [ + "description", + "action_type", + "kind", + "title" + ], + "title": "ReadFileTool", + "type": "object" + }, + "ReasoningItemModel": { + "description": "OpenAI Responses reasoning item (non-stream, subset we consume).\n\nDo not log or render encrypted_content.", + "properties": { + "content": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" } - } + ], + "title": "Content" }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "encrypted_content": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" } - } - } - } - } - }, - "/api/conversations/count": { - "get": { - "tags": [ - "Conversations" - ], - "summary": "Count Conversations", - "description": "Count conversations matching the given filters", - "operationId": "count_conversations_api_conversations_count_get", - "parameters": [ - { - "name": "status", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { - "$ref": "#/components/schemas/ConversationExecutionStatus" - }, - { - "type": "null" - } - ], - "title": "Optional filter by conversation execution status" - } - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "type": "integer", - "title": "Response Count Conversations Api Conversations Count Get" - } + ], + "title": "Encrypted Content" + }, + "id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" } - } + ], + "title": "Id" }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" } - } + ], + "title": "Status" + }, + "summary": { + "items": { + "type": "string" + }, + "title": "Summary", + "type": "array" } - } - } - }, - "/api/conversations/{conversation_id}": { - "get": { - "tags": [ - "Conversations" - ], - "summary": "Get Conversation", - "description": "Given an id, get a conversation", - "operationId": "get_conversation_api_conversations__conversation_id__get", - "parameters": [ - { - "name": "conversation_id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid", - "title": "Conversation Id" - } + }, + "title": "ReasoningItemModel", + "type": "object" + }, + "RedactedThinkingBlock": { + "description": "Redacted thinking block for previous responses without extended thinking.\n\nThis is used as a placeholder for assistant messages that were generated\nbefore extended thinking was enabled.", + "properties": { + "data": { + "description": "The redacted thinking content", + "title": "Data", + "type": "string" + }, + "type": { + "const": "redacted_thinking", + "default": "redacted_thinking", + "title": "Type", + "type": "string" } + }, + "required": [ + "data" ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ConversationInfo" - } + "title": "RedactedThinkingBlock", + "type": "object" + }, + "RemoteMCPServer": { + "description": "Legacy remote MCP server spec accepted by the public REST API.", + "properties": { + "auth": { + "anyOf": [ + { + "discriminator": { + "mapping": { + "api_key": "#/components/schemas/MCPApiKeyAuthCredential-Input", + "basic": "#/components/schemas/MCPBasicAuthCredential-Input", + "bearer": "#/components/schemas/MCPBearerAuthCredential-Input", + "header": "#/components/schemas/MCPHeaderAuthCredential-Input", + "none": "#/components/schemas/MCPNoneAuthCredential", + "oauth2": "#/components/schemas/MCPOAuthAuthCredential-Input" + }, + "propertyName": "strategy" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/MCPNoneAuthCredential" + }, + { + "$ref": "#/components/schemas/MCPApiKeyAuthCredential-Input" + }, + { + "$ref": "#/components/schemas/MCPBearerAuthCredential-Input" + }, + { + "$ref": "#/components/schemas/MCPBasicAuthCredential-Input" + }, + { + "$ref": "#/components/schemas/MCPHeaderAuthCredential-Input" + }, + { + "$ref": "#/components/schemas/MCPOAuthAuthCredential-Input" + } + ] + }, + { + "type": "null" } - } + ], + "title": "Auth" }, - "404": { - "description": "Item not found" + "headers": { + "additionalProperties": { + "type": "string" + }, + "title": "Headers", + "type": "object" }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "keep_alive": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" } - } - } - } - }, - "delete": { - "tags": [ - "Conversations" - ], - "summary": "Delete Conversation", - "description": "Permanently delete a conversation.", - "operationId": "delete_conversation_api_conversations__conversation_id__delete", - "parameters": [ - { - "name": "conversation_id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid", - "title": "Conversation Id" - } + ], + "title": "Keep Alive" + }, + "sse_read_timeout": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Sse Read Timeout" + }, + "timeout": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Timeout" + }, + "type": { + "enum": [ + "http", + "shttp", + "streamable-http", + "sse" + ], + "title": "Type", + "type": "string" + }, + "url": { + "minLength": 1, + "title": "Url", + "type": "string" } + }, + "required": [ + "type", + "url" ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Success" - } + "title": "RemoteMCPServer", + "type": "object" + }, + "RemoteWorkspace": { + "description": "Remote workspace implementation that connects to an OpenHands agent server.\n\nRemoteWorkspace provides access to a sandboxed environment running on a remote\nOpenHands agent server. This is the recommended approach for production deployments\nas it provides better isolation and security.\n\nSupports optional completion callbacks on exit via environment variables:\n - ``AUTOMATION_CALLBACK_URL`` — URL to POST completion status to\n - ``AUTOMATION_CALLBACK_API_KEY`` — Bearer token for callback auth (optional)\n - ``AUTOMATION_RUN_ID`` — Run ID to include in callback payload (optional)\n\nExample:\n >>> workspace = RemoteWorkspace(\n ... host=\"https://agent-server.example.com\",\n ... working_dir=\"/workspace\"\n ... )\n >>> with workspace:\n ... result = workspace.execute_command(\"ls -la\")\n ... content = workspace.read_file(\"README.md\")", + "properties": { + "api_key": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "API key for authenticating with the remote host.", + "title": "Api Key" + }, + "host": { + "description": "The remote host URL for the workspace.", + "title": "Host", + "type": "string" + }, + "kind": { + "const": "RemoteWorkspace", + "title": "Kind", + "type": "string" + }, + "max_connections": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" } - } + ], + "description": "Maximum number of connections for httpx.Client. None means no limit, useful for running many conversations in parallel.", + "title": "Max Connections" }, - "404": { - "description": "Item not found" + "read_timeout": { + "default": 600.0, + "description": "Timeout in seconds for reading operations of httpx.Client.", + "title": "Read Timeout", + "type": "number" }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "runtime_conversation_id": { + "anyOf": [ + { + "format": "uuid", + "type": "string" + }, + { + "type": "null" } - } + ], + "description": "Conversation runtime scope; None uses the host workspace.", + "title": "Runtime Conversation Id" + }, + "working_dir": { + "description": "The working directory for agent operations and tool execution.", + "title": "Working Dir", + "type": "string" } - } + }, + "required": [ + "working_dir", + "host", + "kind" + ], + "title": "RemoteWorkspace", + "type": "object" }, - "patch": { - "tags": [ - "Conversations" + "RenameAgentProfileRequest": { + "properties": { + "new_name": { + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$", + "title": "New Name", + "type": "string" + } + }, + "required": [ + "new_name" ], - "summary": "Update Conversation", - "description": "Update conversation metadata.\n\nThis endpoint allows updating conversation details like title.", - "operationId": "update_conversation_api_conversations__conversation_id__patch", - "parameters": [ - { - "name": "conversation_id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid", - "title": "Conversation Id" - } + "title": "RenameAgentProfileRequest", + "type": "object" + }, + "RenameProfileRequest": { + "properties": { + "new_name": { + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$", + "title": "New Name", + "type": "string" } + }, + "required": [ + "new_name" ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateConversationRequest" - } - } + "title": "RenameProfileRequest", + "type": "object" + }, + "SandboxConfig": { + "description": "Configuration for loading sandbox-specific skills.", + "properties": { + "exposed_urls": { + "description": "List of exposed URLs from the sandbox", + "items": { + "$ref": "#/components/schemas/ExposedUrl" + }, + "title": "Exposed Urls", + "type": "array" } }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Success" - } - } - } - }, - "404": { - "description": "Item not found" + "title": "SandboxConfig", + "type": "object" + }, + "SaveProfileRequest": { + "properties": { + "include_secrets": { + "default": true, + "description": "Whether to persist the API key with the profile.", + "title": "Include Secrets", + "type": "boolean" }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } + "llm": { + "$ref": "#/components/schemas/LLM-Input" } - } - } - }, - "/api/conversations": { - "get": { - "tags": [ - "Conversations" + }, + "required": [ + "llm" ], - "summary": "Batch Get Conversations", - "description": "Get a batch of conversations given their ids, returning null for\nany missing item", - "operationId": "batch_get_conversations_api_conversations_get", - "parameters": [ - { - "name": "ids", - "in": "query", - "required": true, - "schema": { - "type": "array", - "items": { - "type": "string", - "format": "uuid" + "title": "SaveProfileRequest", + "type": "object" + }, + "SecretCreateRequest": { + "description": "Request model for PUT /api/settings/secrets.\n\nCreates or updates a secret with the given name and value.", + "properties": { + "description": { + "anyOf": [ + { + "type": "string" }, - "title": "Ids" - } + { + "type": "null" + } + ], + "title": "Description" + }, + "name": { + "title": "Name", + "type": "string" + }, + "value": { + "format": "password", + "title": "Value", + "type": "string", + "writeOnly": true } + }, + "required": [ + "name", + "value" ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "anyOf": [ - { - "$ref": "#/components/schemas/ConversationInfo" - }, - { - "type": "null" - } - ] - }, - "title": "Response Batch Get Conversations Api Conversations Get" - } + "title": "SecretCreateRequest", + "type": "object" + }, + "SecretItemResponse": { + "description": "Response model for a secret item (without value).\n\nUsed in list responses and as the response for create/update operations.", + "properties": { + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" } - } + ], + "title": "Description" }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } + "name": { + "title": "Name", + "type": "string" } - } - }, - "post": { - "tags": [ - "Conversations" + }, + "required": [ + "name" ], - "summary": "Start Conversation", - "description": "Start a conversation in the local environment.", - "operationId": "start_conversation_api_conversations_post", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/StartConversationRequest", - "examples": [ - { - "agent": { - "llm": { - "model": "your-model-provider/your-model-name", - "api_key": "**********", - "temperature": 0.0, - "usage_id": "your-llm-service" - }, - "tools": [ - { - "name": "terminal" - }, - { - "name": "file_editor" - }, - { - "name": "task_tracker" - }, - { - "name": "browser_tool_set" - } - ], - "system_prompt_kwargs": { - "llm_security_analyzer": true - }, - "kind": "Agent" - }, - "workspace": { - "working_dir": "workspace/project", - "kind": "LocalWorkspace" - }, - "initial_message": { - "content": [ - { - "text": "Flip a coin!" - } - ] - } - } - ] - } - } + "title": "SecretItemResponse", + "type": "object" + }, + "SecretRegistry": { + "description": "Manages secrets and injects them into bash commands when needed.\n\nThe secret registry stores a mapping of secret keys to SecretSources\nthat retrieve the actual secret values. When a bash command is about to be\nexecuted, it scans the command for any secret keys and injects the corresponding\nenvironment variables.\n\nSecret sources will redact / encrypt their sensitive values as appropriate when\nserializing, depending on the content of the context. If a context is present\nand contains a 'cipher' object, this is used for encryption. If it contains a\nboolean 'expose_secrets' flag set to True, secrets are dunped in plain text.\nOtherwise secrets are redacted.\n\nAdditionally, it tracks the latest exported values to enable consistent masking\neven when callable secrets fail on subsequent calls.", + "properties": { + "secret_sources": { + "additionalProperties": { + "$ref": "#/components/schemas/SecretSource-Output" + }, + "title": "Secret Sources", + "type": "object" } }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ConversationInfo" - } - } - } + "title": "SecretRegistry", + "type": "object" + }, + "SecretSource-Input": { + "discriminator": { + "mapping": { + "openhands__sdk__secret__secrets__LookupSecret-Input__1": "#/components/schemas/LookupSecret-Input", + "openhands__sdk__secret__secrets__StaticSecret-Input__1": "#/components/schemas/StaticSecret-Input" + }, + "propertyName": "kind" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/LookupSecret-Input" }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } + { + "$ref": "#/components/schemas/StaticSecret-Input" } - } - } - }, - "/api/conversations/{conversation_id}/pause": { - "post": { - "tags": [ - "Conversations" - ], - "summary": "Pause Conversation", - "description": "Pause a conversation, allowing it to be resumed later.", - "operationId": "pause_conversation_api_conversations__conversation_id__pause_post", - "parameters": [ + ] + }, + "SecretSource-Output": { + "discriminator": { + "mapping": { + "openhands__sdk__secret__secrets__LookupSecret-Output__1": "#/components/schemas/LookupSecret-Output", + "openhands__sdk__secret__secrets__StaticSecret-Output__1": "#/components/schemas/StaticSecret-Output" + }, + "propertyName": "kind" + }, + "oneOf": [ { - "name": "conversation_id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid", - "title": "Conversation Id" - } + "$ref": "#/components/schemas/LookupSecret-Output" + }, + { + "$ref": "#/components/schemas/StaticSecret-Output" + } + ] + }, + "SecretsListResponse": { + "description": "Response model for GET /api/settings/secrets.\n\nLists all available secrets with their names and descriptions.\nValues are never included in list responses.", + "properties": { + "secrets": { + "items": { + "$ref": "#/components/schemas/SecretItemResponse" + }, + "title": "Secrets", + "type": "array" } + }, + "required": [ + "secrets" ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Success" - } - } - } + "title": "SecretsListResponse", + "type": "object" + }, + "SecurityAnalyzerBase-Input": { + "discriminator": { + "mapping": { + "openhands__sdk__security__defense_in_depth__pattern__PatternSecurityAnalyzer-Input__1": "#/components/schemas/PatternSecurityAnalyzer-Input", + "openhands__sdk__security__defense_in_depth__policy_rails__PolicyRailSecurityAnalyzer-Input__1": "#/components/schemas/PolicyRailSecurityAnalyzer-Input", + "openhands__sdk__security__ensemble__EnsembleSecurityAnalyzer-Input__1": "#/components/schemas/EnsembleSecurityAnalyzer-Input", + "openhands__sdk__security__grayswan__analyzer__GraySwanAnalyzer-Input__1": "#/components/schemas/GraySwanAnalyzer-Input", + "openhands__sdk__security__llm_analyzer__LLMSecurityAnalyzer-Input__1": "#/components/schemas/LLMSecurityAnalyzer-Input", + "openhands__sdk__security__toolshield_llm_analyzer__ToolShieldLLMSecurityAnalyzer-Input__1": "#/components/schemas/ToolShieldLLMSecurityAnalyzer-Input" }, - "404": { - "description": "Item not found" + "propertyName": "kind" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/PatternSecurityAnalyzer-Input" }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } + { + "$ref": "#/components/schemas/PolicyRailSecurityAnalyzer-Input" + }, + { + "$ref": "#/components/schemas/EnsembleSecurityAnalyzer-Input" + }, + { + "$ref": "#/components/schemas/GraySwanAnalyzer-Input" + }, + { + "$ref": "#/components/schemas/LLMSecurityAnalyzer-Input" + }, + { + "$ref": "#/components/schemas/ToolShieldLLMSecurityAnalyzer-Input" } - } - } - }, - "/api/conversations/{conversation_id}/run": { - "post": { - "tags": [ - "Conversations" - ], - "summary": "Run Conversation", - "description": "Start running the conversation in the background.", - "operationId": "run_conversation_api_conversations__conversation_id__run_post", - "parameters": [ + ] + }, + "SecurityAnalyzerBase-Output": { + "discriminator": { + "mapping": { + "openhands__sdk__security__defense_in_depth__pattern__PatternSecurityAnalyzer-Output__1": "#/components/schemas/PatternSecurityAnalyzer-Output", + "openhands__sdk__security__defense_in_depth__policy_rails__PolicyRailSecurityAnalyzer-Output__1": "#/components/schemas/PolicyRailSecurityAnalyzer-Output", + "openhands__sdk__security__ensemble__EnsembleSecurityAnalyzer-Output__1": "#/components/schemas/EnsembleSecurityAnalyzer-Output", + "openhands__sdk__security__grayswan__analyzer__GraySwanAnalyzer-Output__1": "#/components/schemas/GraySwanAnalyzer-Output", + "openhands__sdk__security__llm_analyzer__LLMSecurityAnalyzer-Output__1": "#/components/schemas/LLMSecurityAnalyzer-Output", + "openhands__sdk__security__toolshield_llm_analyzer__ToolShieldLLMSecurityAnalyzer-Output__1": "#/components/schemas/ToolShieldLLMSecurityAnalyzer-Output" + }, + "propertyName": "kind" + }, + "oneOf": [ { - "name": "conversation_id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid", - "title": "Conversation Id" - } + "$ref": "#/components/schemas/PatternSecurityAnalyzer-Output" + }, + { + "$ref": "#/components/schemas/PolicyRailSecurityAnalyzer-Output" + }, + { + "$ref": "#/components/schemas/EnsembleSecurityAnalyzer-Output" + }, + { + "$ref": "#/components/schemas/GraySwanAnalyzer-Output" + }, + { + "$ref": "#/components/schemas/LLMSecurityAnalyzer-Output" + }, + { + "$ref": "#/components/schemas/ToolShieldLLMSecurityAnalyzer-Output" } + ] + }, + "SecurityRisk": { + "description": "Security risk levels for actions.\n\nBased on OpenHands security risk levels but adapted for agent-sdk.\nInteger values allow for easy comparison and ordering.", + "enum": [ + "UNKNOWN", + "LOW", + "MEDIUM", + "HIGH" ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Success" + "title": "SecurityRisk", + "type": "string" + }, + "SendMessageRequest": { + "description": "Payload to send a message to the agent.", + "properties": { + "content": { + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/TextContent" + }, + { + "$ref": "#/components/schemas/ImageContent" } - } - } + ] + }, + "title": "Content", + "type": "array" }, - "404": { - "description": "Item not found" + "role": { + "default": "user", + "enum": [ + "user", + "system", + "assistant", + "tool" + ], + "title": "Role", + "type": "string" }, - "409": { - "description": "Conversation is already running" + "run": { + "default": false, + "description": "Whether the agent loop should automatically run if not running", + "title": "Run", + "type": "boolean" + } + }, + "title": "SendMessageRequest", + "type": "object" + }, + "ServerErrorEvent": { + "additionalProperties": false, + "description": "Event emitted by the agent server when a server-level error occurs.\n\nThis event is used for errors that originate from the agent server itself,\nsuch as MCP connection failures, WebSocket errors, or other infrastructure\nissues. Unlike ConversationErrorEvent which is for conversation-level failures,\nthis event indicates a problem with the server environment.", + "properties": { + "code": { + "description": "Code for the error - typically an error type", + "title": "Code", + "type": "string" }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "detail": { + "description": "Details about the error", + "title": "Detail", + "type": "string" + }, + "id": { + "description": "Unique event id (ULID/UUID)", + "title": "Id", + "type": "string" + }, + "kind": { + "const": "ServerErrorEvent", + "title": "Kind", + "type": "string" + }, + "parent_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" } - } - } - } - } - }, - "/api/conversations/{conversation_id}/secrets": { - "post": { - "tags": [ - "Conversations" - ], - "summary": "Update Conversation Secrets", - "description": "Update secrets for a conversation.", - "operationId": "update_conversation_secrets_api_conversations__conversation_id__secrets_post", - "parameters": [ - { - "name": "conversation_id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid", - "title": "Conversation Id" - } + ], + "description": "Parent event id in the conversation tree. None for the root, or for legacy events predating the tree (see EventLog's effective-parent rule). Events sharing a parent_id are sibling branches.", + "title": "Parent Id" + }, + "source": { + "description": "The source of this event", + "enum": [ + "agent", + "user", + "environment", + "hook" + ], + "title": "Source", + "type": "string" + }, + "timestamp": { + "description": "Event timestamp", + "title": "Timestamp", + "type": "string" } + }, + "required": [ + "source", + "code", + "detail", + "kind" ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateSecretsRequest" - } - } + "title": "ServerErrorEvent", + "type": "object" + }, + "SetConfirmationPolicyRequest": { + "description": "Payload to set confirmation policy for a conversation.", + "properties": { + "policy": { + "$ref": "#/components/schemas/ConfirmationPolicyBase-Input", + "description": "The confirmation policy to set" } }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Success" - } - } - } - }, - "404": { - "description": "Item not found" - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "required": [ + "policy" + ], + "title": "SetConfirmationPolicyRequest", + "type": "object" + }, + "SetSecurityAnalyzerRequest": { + "description": "Payload to set security analyzer for a conversation", + "properties": { + "security_analyzer": { + "anyOf": [ + { + "$ref": "#/components/schemas/SecurityAnalyzerBase-Input" + }, + { + "type": "null" } - } + ], + "description": "The security analyzer to set" } - } - } - }, - "/api/conversations/{conversation_id}/confirmation_policy": { - "post": { - "tags": [ - "Conversations" + }, + "required": [ + "security_analyzer" ], - "summary": "Set Conversation Confirmation Policy", - "description": "Set the confirmation policy for a conversation.", - "operationId": "set_conversation_confirmation_policy_api_conversations__conversation_id__confirmation_policy_post", - "parameters": [ - { - "name": "conversation_id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid", - "title": "Conversation Id" - } - } + "title": "SetSecurityAnalyzerRequest", + "type": "object" + }, + "SettingProminence": { + "enum": [ + "critical", + "major", + "minor" ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SetConfirmationPolicyRequest" + "title": "SettingProminence", + "type": "string" + }, + "SettingsChoice": { + "properties": { + "label": { + "title": "Label", + "type": "string" + }, + "value": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "integer" + }, + { + "type": "number" + }, + { + "type": "string" } - } + ], + "title": "Value" } }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Success" - } + "required": [ + "value", + "label" + ], + "title": "SettingsChoice", + "type": "object" + }, + "SettingsFieldSchema": { + "properties": { + "choices": { + "items": { + "$ref": "#/components/schemas/SettingsChoice" + }, + "title": "Choices", + "type": "array" + }, + "default": { + "title": "Default" + }, + "depends_on": { + "items": { + "type": "string" + }, + "title": "Depends On", + "type": "array" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" } - } + ], + "title": "Description" }, - "404": { - "description": "Item not found" + "key": { + "title": "Key", + "type": "string" }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "label": { + "title": "Label", + "type": "string" + }, + "prominence": { + "$ref": "#/components/schemas/SettingProminence", + "default": "minor" + }, + "secret": { + "default": false, + "title": "Secret", + "type": "boolean" + }, + "section": { + "title": "Section", + "type": "string" + }, + "section_label": { + "title": "Section Label", + "type": "string" + }, + "value_type": { + "enum": [ + "string", + "integer", + "number", + "boolean", + "array", + "object" + ], + "title": "Value Type", + "type": "string" + }, + "variant": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" } - } - } - } - } - }, - "/api/conversations/{conversation_id}/security_analyzer": { - "post": { - "tags": [ - "Conversations" - ], - "summary": "Set Conversation Security Analyzer", - "description": "Set the security analyzer for a conversation.", - "operationId": "set_conversation_security_analyzer_api_conversations__conversation_id__security_analyzer_post", - "parameters": [ - { - "name": "conversation_id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid", - "title": "Conversation Id" - } + ], + "description": "When set, the field only applies to the named ``AgentSettings`` variant (``'openhands'`` or ``'acp'``). The GUI filters fields by the user's current variant; fields with ``variant=None`` are shown regardless.", + "title": "Variant" } + }, + "required": [ + "key", + "label", + "section", + "section_label", + "value_type" ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SetSecurityAnalyzerRequest" + "title": "SettingsFieldSchema", + "type": "object" + }, + "SettingsResponse": { + "description": "Response model for GET /api/settings.\n\nContains the full settings payload including agent configuration,\nconversation settings, active LLM profile, miscellaneous frontend-owned\nsettings, and a flag indicating whether an LLM API key is set.\n\nThe ``agent_settings`` and ``conversation_settings`` fields are raw dicts\nbecause the server controls secret serialization via context. Use the\ntyped accessor methods for validation:\n\nExample::\n\n response = SettingsResponse.model_validate(api_response.json())\n agent = response.get_agent_settings() # Returns AgentSettingsConfig\n conv = response.get_conversation_settings() # Returns ConversationSettings\n\n``misc_settings`` is an opaque container for frontend-owned data that the\nagent-server persists but does not interpret — see the docstring of\n:class:`PersistedSettings.misc_settings`.", + "properties": { + "active_agent_profile_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" } - } - } - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Success" - } + ], + "description": "Stable id of the currently active AgentProfile, if one is set.", + "title": "Active Agent Profile Id" + }, + "active_meta_profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" } - } + ], + "description": "Name of the currently active meta-profile, if one is selected.", + "title": "Active Meta Profile" }, - "404": { - "description": "Item not found" + "active_profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Name of the currently active LLM profile, if one is selected.", + "title": "Active Profile" }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "agent_settings": { + "additionalProperties": true, + "properties": { + "agent_kind": { + "anyOf": [ + { + "enum": [ + "openhands", + "acp" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Agent Kind" + }, + "mcp_config": { + "$ref": "#/components/schemas/MCPConfig" + }, + "schema_version": { + "anyOf": [ + { + "minimum": 1.0, + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Schema Version" } - } + }, + "required": [ + "mcp_config" + ], + "title": "_AgentSettingsContract", + "type": "object" + }, + "conversation_settings": { + "additionalProperties": true, + "title": "Conversation Settings", + "type": "object" + }, + "llm_api_key_is_set": { + "title": "Llm Api Key Is Set", + "type": "boolean" + }, + "misc_settings": { + "additionalProperties": true, + "title": "Misc Settings", + "type": "object" } - } - } - }, - "/api/conversations/{conversation_id}/generate_title": { - "post": { - "tags": [ - "Conversations" + }, + "required": [ + "agent_settings", + "conversation_settings", + "llm_api_key_is_set" ], - "summary": "Generate Conversation Title", - "description": "Generate a title for the conversation using LLM.", - "operationId": "generate_conversation_title_api_conversations__conversation_id__generate_title_post", - "parameters": [ - { - "name": "conversation_id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid", - "title": "Conversation Id" - } + "title": "SettingsResponse", + "type": "object" + }, + "SettingsSchema": { + "properties": { + "model_name": { + "title": "Model Name", + "type": "string" + }, + "sections": { + "items": { + "$ref": "#/components/schemas/SettingsSectionSchema" + }, + "title": "Sections", + "type": "array" } + }, + "required": [ + "model_name", + "sections" ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GenerateTitleRequest" + "title": "SettingsSchema", + "type": "object" + }, + "SettingsSectionSchema": { + "properties": { + "fields": { + "items": { + "$ref": "#/components/schemas/SettingsFieldSchema" + }, + "title": "Fields", + "type": "array" + }, + "key": { + "title": "Key", + "type": "string" + }, + "label": { + "title": "Label", + "type": "string" + }, + "variant": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" } - } + ], + "description": "When set, this section only applies to the named ``AgentSettings`` variant (e.g. ``'openhands'`` or ``'acp'``). The GUI filters sections by the current ``agent_kind`` value; sections with ``variant=None`` are always shown.", + "title": "Variant" } }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GenerateTitleResponse" - } + "required": [ + "key", + "label", + "fields" + ], + "title": "SettingsSectionSchema", + "type": "object" + }, + "SettingsUpdateRequest": { + "description": "Request model for PATCH /api/settings.\n\nSupports partial updates via diff objects that are deep-merged with\nexisting settings. ``misc_settings_diff`` is deep-merged into the\npersisted ``misc_settings`` block with the same semantics as\n``agent_settings_diff`` and ``conversation_settings_diff``: nested dicts\nmerge recursively, and lists are replaced wholesale rather than merged.\nBecause ``misc_settings`` is opaque to the agent-server, callers are\nresponsible for the shape of what they store there.", + "properties": { + "active_agent_profile_id": { + "anyOf": [ + { + "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$", + "type": "string" + }, + { + "type": "null" } - } + ], + "description": "Stable id of the active AgentProfile to persist; null clears it.", + "title": "Active Agent Profile Id" }, - "404": { - "description": "Item not found" + "active_meta_profile": { + "anyOf": [ + { + "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Name of the active meta-profile to persist; null clears it.", + "title": "Active Meta Profile" }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "active_profile": { + "anyOf": [ + { + "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$", + "type": "string" + }, + { + "type": "null" } - } - } - } - } - }, - "/api/conversations/{conversation_id}/ask_agent": { - "post": { - "tags": [ - "Conversations" - ], - "summary": "Ask Agent", - "description": "Ask the agent a simple question without affecting conversation state.", - "operationId": "ask_agent_api_conversations__conversation_id__ask_agent_post", - "parameters": [ - { - "name": "conversation_id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid", - "title": "Conversation Id" - } - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AskAgentRequest" + ], + "description": "Name of the active LLM profile to persist; null clears it.", + "title": "Active Profile" + }, + "agent_settings_diff": { + "anyOf": [ + { + "additionalProperties": true, + "properties": { + "mcp_config": { + "anyOf": [ + { + "$ref": "#/components/schemas/MCPConfigPatch" + }, + { + "type": "null" + } + ] + } + }, + "title": "_AgentSettingsPatchContract", + "type": "object" + }, + { + "type": "null" } - } + ], + "title": "Agent Settings Diff" + }, + "conversation_settings_diff": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Conversation Settings Diff" + }, + "misc_settings_diff": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Misc Settings Diff" } }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AskAgentResponse" - } + "title": "SettingsUpdateRequest", + "type": "object" + }, + "Skill-Input": { + "description": "A skill provides specialized knowledge or functionality.\n\nSkill behavior depends on format (is_agentskills_format) and trigger:\n\nAgentSkills format (SKILL.md files):\n- Always listed in with name, description, location\n- Agent reads full content on demand (progressive disclosure)\n- If has triggers: content is ALSO auto-injected when triggered\n\nLegacy OpenHands format:\n- With triggers: Listed in , content injected on trigger\n- Without triggers (None): Full content in , always active\n\nThis model supports both OpenHands-specific fields and AgentSkills standard\nfields (https://agentskills.io/specification) for cross-platform compatibility.", + "properties": { + "allowed_tools": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" } - } + ], + "description": "List of pre-approved tools for this skill. AgentSkills standard field (parsed from space-delimited string).", + "title": "Allowed Tools" }, - "404": { - "description": "Item not found" + "compatibility": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Environment requirements or compatibility notes for the skill. AgentSkills standard field (e.g., 'Requires git and docker').", + "title": "Compatibility" }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "content": { + "title": "Content", + "type": "string" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" } - } - } - } - } - }, - "/api/conversations/{conversation_id}/condense": { - "post": { - "tags": [ - "Conversations" - ], - "summary": "Condense Conversation", - "description": "Force condensation of the conversation history.", - "operationId": "condense_conversation_api_conversations__conversation_id__condense_post", - "parameters": [ - { - "name": "conversation_id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid", - "title": "Conversation Id" - } - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Success" - } + ], + "description": "A brief description of what the skill does and when to use it. Descriptions exceeding MAX_DESCRIPTION_LENGTH are truncated with a notice pointing to the skill's source path.", + "title": "Description" + }, + "disable_model_invocation": { + "default": false, + "description": "Whether this skill can only be activated by trigger matching and should not be advertised to the model for direct invocation.", + "title": "Disable Model Invocation", + "type": "boolean" + }, + "inputs": { + "description": "Input metadata for the skill (task skills only)", + "items": { + "$ref": "#/components/schemas/InputMetadata" + }, + "title": "Inputs", + "type": "array" + }, + "is_agentskills_format": { + "default": false, + "description": "Whether this skill was loaded from a SKILL.md file following the AgentSkills standard. AgentSkills-format skills use progressive disclosure: always listed in with name, description, and location. If the skill also has triggers, content is auto-injected when triggered AND agent can read file anytime.", + "title": "Is Agentskills Format", + "type": "boolean" + }, + "license": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The license under which the skill is distributed. AgentSkills standard field (e.g., 'Apache-2.0', 'MIT').", + "title": "License" + }, + "mcp_tools": { + "anyOf": [ + { + "additionalProperties": { + "$ref": "#/components/schemas/MCPServer-Input" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "MCP servers for the skill (repo skills only).", + "title": "Mcp Tools" + }, + "metadata": { + "anyOf": [ + { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + { + "type": "null" } - } + ], + "description": "Arbitrary key-value metadata for the skill. AgentSkills standard field for extensibility.", + "title": "Metadata" }, - "404": { - "description": "Item not found" + "name": { + "title": "Name", + "type": "string" }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "resources": { + "anyOf": [ + { + "$ref": "#/components/schemas/SkillResources" + }, + { + "type": "null" } - } - } - } - } - }, - "/api/tools/": { - "get": { - "tags": [ - "Tools" - ], - "summary": "List Available Tools", - "description": "List all available tools.", - "operationId": "list_available_tools_api_tools__get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "items": { - "type": "string" + ], + "description": "Resource directories for the skill (scripts/, references/, assets/). AgentSkills standard field. Only populated for SKILL.md directory format." + }, + "source": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The source path or identifier of the skill. When it is None, it is treated as a programmatically defined skill.", + "title": "Source" + }, + "trigger": { + "anyOf": [ + { + "discriminator": { + "mapping": { + "keyword": "#/components/schemas/KeywordTrigger", + "path": "#/components/schemas/PathTrigger", + "task": "#/components/schemas/TaskTrigger" }, - "type": "array", - "title": "Response List Available Tools Api Tools Get" - } + "propertyName": "type" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/KeywordTrigger" + }, + { + "$ref": "#/components/schemas/TaskTrigger" + }, + { + "$ref": "#/components/schemas/PathTrigger" + } + ] + }, + { + "type": "null" } - } + ], + "description": "Trigger determines when skill content is auto-injected. None = no auto-injection (for AgentSkills: agent reads on demand; for legacy: full content always in system prompt). KeywordTrigger = auto-inject when keywords appear in user messages. TaskTrigger = auto-inject for specific tasks, may require user input.", + "title": "Trigger" + }, + "version": { + "default": "1.0.0", + "description": "Skill version (AgentSkills standard field).", + "title": "Version", + "type": "string" } - } - } - }, - "/api/bash/bash_events/search": { - "get": { - "tags": [ - "Bash" + }, + "required": [ + "name", + "content" ], - "summary": "Search Bash Events", - "description": "Search / List bash event events", - "operationId": "search_bash_events_api_bash_bash_events_search_get", - "parameters": [ - { - "name": "kind__eq", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { - "enum": [ - "BashCommand", - "BashOutput" - ], + "title": "Skill", + "type": "object" + }, + "Skill-Output": { + "description": "A skill provides specialized knowledge or functionality.\n\nSkill behavior depends on format (is_agentskills_format) and trigger:\n\nAgentSkills format (SKILL.md files):\n- Always listed in with name, description, location\n- Agent reads full content on demand (progressive disclosure)\n- If has triggers: content is ALSO auto-injected when triggered\n\nLegacy OpenHands format:\n- With triggers: Listed in , content injected on trigger\n- Without triggers (None): Full content in , always active\n\nThis model supports both OpenHands-specific fields and AgentSkills standard\nfields (https://agentskills.io/specification) for cross-platform compatibility.", + "properties": { + "allowed_tools": { + "anyOf": [ + { + "items": { "type": "string" }, - { - "type": "null" - } - ], - "title": "Kind Eq" - } + "type": "array" + }, + { + "type": "null" + } + ], + "description": "List of pre-approved tools for this skill. AgentSkills standard field (parsed from space-delimited string).", + "title": "Allowed Tools" }, - { - "name": "command_id__eq", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { - "type": "string", - "format": "uuid" - }, - { - "type": "null" - } - ], - "title": "Command Id Eq" - } + "compatibility": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Environment requirements or compatibility notes for the skill. AgentSkills standard field (e.g., 'Requires git and docker').", + "title": "Compatibility" }, - { - "name": "timestamp__gte", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { - "type": "string", - "format": "date-time" - }, - { - "type": "null" - } - ], - "title": "Timestamp Gte" - } + "content": { + "title": "Content", + "type": "string" }, - { - "name": "timestamp__lt", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { - "type": "string", - "format": "date-time" - }, - { - "type": "null" - } - ], - "title": "Timestamp Lt" - } + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "A brief description of what the skill does and when to use it. Descriptions exceeding MAX_DESCRIPTION_LENGTH are truncated with a notice pointing to the skill's source path.", + "title": "Description" }, - { - "name": "order__gt", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "title": "Filter to events with order greater than this value", - "description": "Only returns BashOutput events with order > this value. Useful for polling to fetch only new events since the last poll." + "disable_model_invocation": { + "default": false, + "description": "Whether this skill can only be activated by trigger matching and should not be advertised to the model for direct invocation.", + "title": "Disable Model Invocation", + "type": "boolean" + }, + "inputs": { + "description": "Input metadata for the skill (task skills only)", + "items": { + "$ref": "#/components/schemas/InputMetadata" }, - "description": "Only returns BashOutput events with order > this value. Useful for polling to fetch only new events since the last poll." + "title": "Inputs", + "type": "array" }, - { - "name": "sort_order", - "in": "query", - "required": false, - "schema": { - "$ref": "#/components/schemas/BashEventSortOrder", - "default": "TIMESTAMP" - } + "is_agentskills_format": { + "default": false, + "description": "Whether this skill was loaded from a SKILL.md file following the AgentSkills standard. AgentSkills-format skills use progressive disclosure: always listed in with name, description, and location. If the skill also has triggers, content is auto-injected when triggered AND agent can read file anytime.", + "title": "Is Agentskills Format", + "type": "boolean" }, - { - "name": "page_id", - "in": "query", - "required": false, - "schema": { - "anyOf": [ - { + "license": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The license under which the skill is distributed. AgentSkills standard field (e.g., 'Apache-2.0', 'MIT').", + "title": "License" + }, + "mcp_tools": { + "anyOf": [ + { + "additionalProperties": { + "additionalProperties": true, + "type": "object" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "MCP servers for the skill (repo skills only).", + "title": "Mcp Tools" + }, + "metadata": { + "anyOf": [ + { + "additionalProperties": { "type": "string" }, - { - "type": "null" - } - ], - "title": "Optional next_page_id from the previously returned page" - } - }, - { - "name": "limit", - "in": "query", - "required": false, - "schema": { - "type": "integer", - "exclusiveMinimum": 0, - "title": "The max number of results in the page", - "lte": 100, - "default": 100 - } - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/BashEventPage" - } + "type": "object" + }, + { + "type": "null" } - } + ], + "description": "Arbitrary key-value metadata for the skill. AgentSkills standard field for extensibility.", + "title": "Metadata" }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/api/bash/bash_events/{event_id}": { - "get": { - "tags": [ - "Bash" - ], - "summary": "Get Bash Event", - "description": "Get a bash event event given an id", - "operationId": "get_bash_event_api_bash_bash_events__event_id__get", - "parameters": [ - { - "name": "event_id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "title": "Event Id" - } - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/BashEventBase" - } + "name": { + "title": "Name", + "type": "string" + }, + "resources": { + "anyOf": [ + { + "$ref": "#/components/schemas/SkillResources" + }, + { + "type": "null" } - } + ], + "description": "Resource directories for the skill (scripts/, references/, assets/). AgentSkills standard field. Only populated for SKILL.md directory format." }, - "404": { - "description": "Item not found" + "source": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The source path or identifier of the skill. When it is None, it is treated as a programmatically defined skill.", + "title": "Source" }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "trigger": { + "anyOf": [ + { + "discriminator": { + "mapping": { + "keyword": "#/components/schemas/KeywordTrigger", + "path": "#/components/schemas/PathTrigger", + "task": "#/components/schemas/TaskTrigger" + }, + "propertyName": "type" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/KeywordTrigger" + }, + { + "$ref": "#/components/schemas/TaskTrigger" + }, + { + "$ref": "#/components/schemas/PathTrigger" + } + ] + }, + { + "type": "null" } - } + ], + "description": "Trigger determines when skill content is auto-injected. None = no auto-injection (for AgentSkills: agent reads on demand; for legacy: full content always in system prompt). KeywordTrigger = auto-inject when keywords appear in user messages. TaskTrigger = auto-inject for specific tasks, may require user input.", + "title": "Trigger" + }, + "version": { + "default": "1.0.0", + "description": "Skill version (AgentSkills standard field).", + "title": "Version", + "type": "string" } - } - } - }, - "/api/bash/bash_events/": { - "get": { - "tags": [ - "Bash" + }, + "required": [ + "name", + "content" ], - "summary": "Batch Get Bash Events", - "description": "Get a batch of bash event events given their ids, returning null for any\nmissing item.", - "operationId": "batch_get_bash_events_api_bash_bash_events__get", - "requestBody": { + "title": "Skill", + "type": "object" + }, + "SkillInfo": { + "description": "Lightweight representation of a skill's essential information.\n\nThis class provides a standardized, serializable format for skill metadata\nthat can be used across different components of the system.", + "properties": { "content": { - "application/json": { - "schema": { - "items": { - "type": "string" - }, - "type": "array", - "title": "Event Ids" - } - } + "title": "Content", + "type": "string" }, - "required": true - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "items": { - "anyOf": [ - { - "$ref": "#/components/schemas/BashEventBase" - }, - { - "type": "null" - } - ] - }, - "type": "array", - "title": "Response Batch Get Bash Events Api Bash Bash Events Get" - } + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" } - } + ], + "title": "Description" }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "disable_model_invocation": { + "default": false, + "title": "Disable Model Invocation", + "type": "boolean" + }, + "is_agentskills_format": { + "default": false, + "title": "Is Agentskills Format", + "type": "boolean" + }, + "name": { + "title": "Name", + "type": "string" + }, + "source": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" } - } + ], + "title": "Source" + }, + "triggers": { + "items": { + "type": "string" + }, + "title": "Triggers", + "type": "array" + }, + "type": { + "enum": [ + "repo", + "knowledge", + "agentskills" + ], + "title": "Type", + "type": "string" } - } - } - }, - "/api/bash/start_bash_command": { - "post": { - "tags": [ - "Bash" + }, + "required": [ + "name", + "type", + "content" ], - "summary": "Start Bash Command", - "description": "Execute a bash command in the background", - "operationId": "start_bash_command_api_bash_start_bash_command_post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ExecuteBashRequest" - } - } + "title": "SkillInfo", + "type": "object" + }, + "SkillResources": { + "description": "Resource directories for a skill (AgentSkills standard).\n\nPer the AgentSkills specification, skills can include:\n- scripts/: Executable scripts the agent can run\n- references/: Reference documentation and examples\n- assets/: Static assets (images, data files, etc.)", + "properties": { + "assets": { + "description": "List of asset files in assets/ directory (relative paths)", + "items": { + "type": "string" + }, + "title": "Assets", + "type": "array" + }, + "references": { + "description": "List of reference files in references/ directory (relative paths)", + "items": { + "type": "string" + }, + "title": "References", + "type": "array" }, - "required": true - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/BashCommand" - } - } - } + "scripts": { + "description": "List of script files in scripts/ directory (relative paths)", + "items": { + "type": "string" + }, + "title": "Scripts", + "type": "array" }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } + "skill_root": { + "description": "Root directory of the skill (absolute path)", + "title": "Skill Root", + "type": "string" } - } - } - }, - "/api/bash/execute_bash_command": { - "post": { - "tags": [ - "Bash" + }, + "required": [ + "skill_root" ], - "summary": "Execute Bash Command", - "description": "Execute a bash command and wait for a result", - "operationId": "execute_bash_command_api_bash_execute_bash_command_post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ExecuteBashRequest" + "title": "SkillResources", + "type": "object" + }, + "SkillsRequest": { + "description": "Request body for loading skills.", + "properties": { + "load_org": { + "default": true, + "description": "Load organization-level skills", + "title": "Load Org", + "type": "boolean" + }, + "load_project": { + "default": true, + "description": "Load project skills from workspace", + "title": "Load Project", + "type": "boolean" + }, + "load_public": { + "default": true, + "description": "Load public skills from OpenHands/extensions repo", + "title": "Load Public", + "type": "boolean" + }, + "load_user": { + "default": true, + "description": "Load user skills from ~/.openhands/skills/", + "title": "Load User", + "type": "boolean" + }, + "marketplace_path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" } - } + ], + "default": "marketplaces/default.json", + "description": "Relative marketplace JSON path for public skills. Set to null to load all public skills.", + "title": "Marketplace Path" }, - "required": true - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/BashOutput" - } + "org_configs": { + "anyOf": [ + { + "items": { + "$ref": "#/components/schemas/OrgConfig" + }, + "type": "array" + }, + { + "type": "null" } - } + ], + "description": "Organization/user skill repositories to load concurrently", + "title": "Org Configs" }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "project_dir": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" } - } - } - } - } - }, - "/api/bash/bash_events": { - "delete": { - "tags": [ - "Bash" - ], - "summary": "Clear All Bash Events", - "description": "Clear all bash events from storage", - "operationId": "clear_all_bash_events_api_bash_bash_events_delete", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "additionalProperties": { - "type": "integer" - }, - "type": "object", - "title": "Response Clear All Bash Events Api Bash Bash Events Delete" - } + ], + "description": "Workspace directory path for project skills", + "title": "Project Dir" + }, + "registered_marketplaces": { + "description": "Marketplace registrations for plugin-based skill loading. Registrations with auto_load=True or a list of plugin names add their skills to the public skills.", + "items": { + "$ref": "#/components/schemas/MarketplaceRegistration" + }, + "title": "Registered Marketplaces", + "type": "array" + }, + "sandbox_config": { + "anyOf": [ + { + "$ref": "#/components/schemas/SandboxConfig" + }, + { + "type": "null" } - } + ], + "description": "Sandbox skills configuration" } - } - } - }, - "/api/git/changes/{path}": { - "get": { - "tags": [ - "Git" - ], - "summary": "Git Changes", - "operationId": "git_changes_api_git_changes__path__get", - "parameters": [ - { - "name": "path", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "path", - "title": "Path" - } + }, + "title": "SkillsRequest", + "type": "object" + }, + "SkillsResponse": { + "description": "Response containing all available skills.", + "properties": { + "skills": { + "items": { + "$ref": "#/components/schemas/SkillInfo" + }, + "title": "Skills", + "type": "array" + }, + "sources": { + "additionalProperties": { + "type": "integer" + }, + "description": "Count of skills loaded from each source", + "title": "Sources", + "type": "object" } + }, + "required": [ + "skills" ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/GitChange" - }, - "title": "Response Git Changes Api Git Changes Path Get" - } + "title": "SkillsResponse", + "type": "object" + }, + "StartConversationRequest": { + "description": "Payload to create a new conversation.\n\nExtends :class:`ConversationConfig` with the agent source: a stored Agent\nProfile (``agent_profile_id``), resolved agent settings (``agent_settings``),\nor an ``agent`` built in code. The server builds the conversation's agent\nfrom that source at launch; this model only validates it.\n\nNote: the agent lives here on the *request*, deliberately not on\n``ConversationConfig``. The persisted record (``StoredConversation``) does\nnot carry the agent — its single source of truth is ``ConversationState`` /\n``base_state.json``.", + "properties": { + "agent": { + "$ref": "#/components/schemas/AgentBase-Input" + }, + "agent_definitions": { + "description": "Agent definitions from the client's registry. These are registered on the server so that task tools can see user-registered subagents.", + "items": { + "$ref": "#/components/schemas/AgentDefinition" + }, + "title": "Agent Definitions", + "type": "array" + }, + "agent_launch_additions": { + "anyOf": [ + { + "$ref": "#/components/schemas/AgentLaunchAdditions" + }, + { + "type": "null" } - } + ], + "description": "Deployment context applied after agent or Agent Profile resolution. The stored Agent Profile is not modified." }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "agent_profile_id": { + "anyOf": [ + { + "format": "uuid", + "type": "string" + }, + { + "type": "null" } - } - } - } - } - }, - "/api/git/diff/{path}": { - "get": { - "tags": [ - "Git" - ], - "summary": "Git Diff", - "operationId": "git_diff_api_git_diff__path__get", - "parameters": [ - { - "name": "path", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "path", - "title": "Path" - } - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GitDiff" - } + ], + "description": "Stored Agent Profile to launch. The server resolves it with its own stores. Mutually exclusive with `agent` and `agent_settings`.", + "title": "Agent Profile Id" + }, + "agent_settings": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "Reference-free agent settings, validated with the AgentSettingsBase `agent_kind` discriminator. The server builds the agent from them at launch. Ignored when `agent` is set.", + "title": "Agent Settings" + }, + "autotitle": { + "default": true, + "description": "If true, automatically generate a title for the conversation from the first user message. Precedence: title_llm_profile (if set and loads) → agent.llm → message truncation.", + "title": "Autotitle", + "type": "boolean" + }, + "client_tools": { + "description": "Tools defined by the client via JSON spec. These tools have no server-side executor — when the agent calls them, an ActionEvent is emitted over the WebSocket and the client handles execution. The SDK returns an acknowledgment observation immediately.", + "items": { + "$ref": "#/components/schemas/ClientToolSpec-Input" + }, + "title": "Client Tools", + "type": "array" + }, + "confirmation_policy": { + "$ref": "#/components/schemas/ConfirmationPolicyBase-Input", + "default": { + "kind": "NeverConfirm" + }, + "description": "Controls when the conversation will prompt the user before continuing. Defaults to never." + }, + "conversation_id": { + "anyOf": [ + { + "format": "uuid", + "type": "string" + }, + { + "type": "null" } - } + ], + "description": "Optional conversation ID. If not provided, a random UUID will be generated.", + "title": "Conversation Id" }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "hook_config": { + "anyOf": [ + { + "$ref": "#/components/schemas/HookConfig" + }, + { + "type": "null" } - } - } - } - } - }, - "/api/file/upload/{path}": { - "post": { - "tags": [ - "Files" - ], - "summary": "Upload File", - "description": "Upload a file to the workspace.", - "operationId": "upload_file_api_file_upload__path__post", - "parameters": [ - { - "name": "path", - "in": "path", - "required": true, - "schema": { - "type": "string", - "description": "Absolute file path.", - "title": "Path" + ], + "description": "Optional hook configuration for this conversation. Hooks are shell scripts that run at key lifecycle events (PreToolUse, PostToolUse, UserPromptSubmit, Stop, etc.). If both hook_config and plugins are provided, they are merged with explicit hooks running before plugin hooks." + }, + "initial_message": { + "anyOf": [ + { + "$ref": "#/components/schemas/SendMessageRequest" + }, + { + "type": "null" + } + ], + "description": "Initial message to pass to the LLM" + }, + "max_iterations": { + "default": 500, + "description": "If set, the max number of iterations the agent will run before stopping. This is useful to prevent infinite loops.", + "minimum": 1.0, + "title": "Max Iterations", + "type": "integer" + }, + "observability_metadata": { + "additionalProperties": { + "$ref": "#/components/schemas/TraceMetadataValue" }, - "description": "Absolute file path." - } - ], - "requestBody": { - "required": true, - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/Body_upload_file_api_file_upload__path__post" + "description": "Trace-level metadata to attach to observability backends. Values must be scalars or homogeneous scalar lists supported by OpenTelemetry.", + "title": "Observability Metadata", + "type": "object" + }, + "observability_parent_span_context": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" } - } - } - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Success" - } + ], + "description": "Serialized parent span context used to attach this conversation to an upstream automation or integration trace.", + "title": "Observability Parent Span Context" + }, + "observability_span_name": { + "default": "conversation", + "description": "Optional named child span to emit under the conversation root. Use stable, low-cardinality names because observability backends may use span names for grouping or signal routing.", + "title": "Observability Span Name", + "type": "string" + }, + "observability_tags": { + "description": "Tags to attach to the conversation root observability span.", + "items": { + "type": "string" + }, + "title": "Observability Tags", + "type": "array" + }, + "parent_conversation_id": { + "anyOf": [ + { + "format": "uuid", + "type": "string" + }, + { + "type": "null" } - } + ], + "description": "Optional ID of an existing conversation that owns this one. The parent must already exist and share this conversation's workspace.", + "title": "Parent Conversation Id" }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "plugins": { + "anyOf": [ + { + "items": { + "$ref": "#/components/schemas/PluginSource" + }, + "type": "array" + }, + { + "type": "null" } - } - } - } - } - }, - "/api/file/download/{path}": { - "get": { - "tags": [ - "Files" - ], - "summary": "Download File", - "description": "Download a file from the workspace.", - "operationId": "download_file_api_file_download__path__get", - "parameters": [ - { - "name": "path", - "in": "path", - "required": true, - "schema": { - "type": "string", - "description": "Absolute file path.", - "title": "Path" + ], + "description": "List of plugins to load for this conversation. Plugins are loaded and their skills/MCP config are merged into the agent. Hooks are extracted and stored for runtime execution.", + "title": "Plugins" + }, + "secrets": { + "additionalProperties": { + "$ref": "#/components/schemas/SecretSource-Input" }, - "description": "Absolute file path." - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {} - } - } + "description": "Secrets available in the conversation", + "title": "Secrets", + "type": "object" }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "secrets_encrypted": { + "default": false, + "description": "If true, indicates that secret values in the agent configuration are cipher-encrypted and should be decrypted by the server before use. This enables secure round-tripping of settings through untrusted clients (e.g., frontend) that received encrypted values via the X-Expose-Secrets header. Flow: client calls GET /api/settings with X-Expose-Secrets: encrypted to receive cipher-encrypted secrets, then passes them in the agent config with secrets_encrypted=True so the server can decrypt them.", + "title": "Secrets Encrypted", + "type": "boolean" + }, + "security_analyzer": { + "anyOf": [ + { + "$ref": "#/components/schemas/SecurityAnalyzerBase-Input" + }, + { + "type": "null" } - } - } - } - } - }, - "/api/file/download-trajectory/{conversation_id}": { - "get": { - "tags": [ - "Files" - ], - "summary": "Download Trajectory", - "description": "Download a file from the workspace.", - "operationId": "download_trajectory_api_file_download_trajectory__conversation_id__get", - "parameters": [ - { - "name": "conversation_id", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid", - "title": "Conversation Id" - } - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {} + ], + "description": "Optional security analyzer to evaluate action risks." + }, + "stuck_detection": { + "default": true, + "description": "If true, the conversation will use stuck detection to prevent infinite loops.", + "title": "Stuck Detection", + "type": "boolean" + }, + "tags": { + "additionalProperties": { + "type": "string" + }, + "description": "Key-value tags for the conversation. Keys must be lowercase alphanumeric. Values are arbitrary strings up to 256 characters.", + "title": "Tags", + "type": "object" + }, + "title_llm_profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" } - } + ], + "description": "Optional LLM profile name for title generation. If set, the LLM is loaded from LLMProfileStore (~/.openhands/profiles/) and used for LLM-based title generation. This enables using a fast/cheap model for titles regardless of the agent's main model. If not set (or profile loading fails), title generation falls back to the agent's LLM.", + "title": "Title Llm Profile" }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "tool_module_qualnames": { + "additionalProperties": { + "type": "string" + }, + "description": "Mapping of tool names to their module qualnames from the client's registry. These modules will be dynamically imported on the server to register the tools for this conversation.", + "title": "Tool Module Qualnames", + "type": "object" + }, + "user_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" } - } + ], + "description": "Optional user ID supplied by the hosting deployment, used to correlate this conversation with the identity that deployment already established. When set it is passed to Laminar.set_trace_user_id() so traces can be queried by user, and — where a host has enabled product analytics — it is reused verbatim as the analytics correlation id so events attach to the existing person rather than creating a duplicate identity. It is never generated by the SDK, and is omitted entirely when unset.", + "title": "User Id" + }, + "workspace": { + "$ref": "#/components/schemas/LocalWorkspace-Input", + "description": "Working directory for agent operations and tool execution." + }, + "worktree": { + "default": false, + "description": "If true and the workspace is already inside a git repository, create a dedicated git worktree for this conversation under `/tmp/conversation-worktrees//`.", + "title": "Worktree", + "type": "boolean" } - } - } - }, - "/api/vscode/url": { - "get": { - "tags": [ - "VSCode" + }, + "required": [ + "workspace" ], - "summary": "Get Vscode Url", - "description": "Get the VSCode URL with authentication token.\n\nArgs:\n base_url: Base URL for the VSCode server (default: http://localhost:8001)\n workspace_dir: Path to workspace directory\n\nReturns:\n VSCode URL with token if available, None otherwise", - "operationId": "get_vscode_url_api_vscode_url_get", - "parameters": [ - { - "name": "base_url", - "in": "query", - "required": false, - "schema": { - "type": "string", - "default": "http://localhost:8001", - "title": "Base Url" - } + "title": "StartConversationRequest", + "type": "object" + }, + "StartGoalRequest": { + "description": "Payload to start a ``/goal`` loop inside a conversation.", + "properties": { + "max_iterations": { + "default": 10, + "description": "Maximum audit rounds before giving up.", + "minimum": 1.0, + "title": "Max Iterations", + "type": "integer" }, - { - "name": "workspace_dir", - "in": "query", - "required": false, - "schema": { - "type": "string", - "default": "workspace", - "title": "Workspace Dir" - } + "objective": { + "description": "The goal objective to pursue and audit.", + "title": "Objective", + "type": "string" } + }, + "required": [ + "objective" ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/VSCodeUrlResponse" - } + "title": "StartGoalRequest", + "type": "object" + }, + "StaticSecret-Input": { + "description": "A secret stored locally", + "properties": { + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" } - } + ], + "description": "Optional description for this secret", + "title": "Description" }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "kind": { + "const": "StaticSecret", + "title": "Kind", + "type": "string" + }, + "value": { + "anyOf": [ + { + "format": "password", + "type": "string", + "writeOnly": true + }, + { + "type": "null" } - } + ], + "title": "Value" } - } - } - }, - "/api/vscode/status": { - "get": { - "tags": [ - "VSCode" - ], - "summary": "Get Vscode Status", - "description": "Get the VSCode server status.\n\nReturns:\n Dictionary with running status and enabled status", - "operationId": "get_vscode_status_api_vscode_status_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "additionalProperties": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "string" - } - ] - }, - "type": "object", - "title": "Response Get Vscode Status Api Vscode Status Get" - } + }, + "title": "StaticSecret", + "type": "object" + }, + "StaticSecret-Output": { + "description": "A secret stored locally", + "properties": { + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" } - } + ], + "description": "Optional description for this secret", + "title": "Description" + }, + "kind": { + "const": "StaticSecret", + "title": "Kind", + "type": "string" + }, + "value": { + "anyOf": [ + { + "format": "password", + "type": "string", + "writeOnly": true + }, + { + "type": "null" + } + ], + "title": "Value" } - } - } - }, - "/api/desktop/url": { - "get": { - "tags": [ - "Desktop" + }, + "required": [ + "kind" ], - "summary": "Get Desktop Url", - "description": "Get the noVNC URL for desktop access.\n\nArgs:\n base_url: Base URL for the noVNC server (default: http://localhost:8002)\n\nReturns:\n noVNC URL if available, None otherwise", - "operationId": "get_desktop_url_api_desktop_url_get", - "parameters": [ - { - "name": "base_url", - "in": "query", - "required": false, - "schema": { - "type": "string", - "default": "http://localhost:8002", - "title": "Base Url" - } + "title": "StaticSecret", + "type": "object" + }, + "StdioMCPServer": { + "description": "Legacy stdio MCP server spec accepted by the public REST API.", + "properties": { + "args": { + "items": { + "type": "string" + }, + "title": "Args", + "type": "array" + }, + "command": { + "description": "Executable to invoke", + "minLength": 1, + "title": "Command", + "type": "string" + }, + "cwd": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Cwd" + }, + "env": { + "additionalProperties": { + "type": "string" + }, + "title": "Env", + "type": "object" + }, + "type": { + "const": "stdio", + "default": "stdio", + "title": "Type", + "type": "string" } + }, + "required": [ + "command" ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DesktopUrlResponse" - } + "title": "StdioMCPServer", + "type": "object" + }, + "StreamingDeltaEvent": { + "additionalProperties": false, + "description": "Transient LLM token delta for real-time WebSocket delivery.\n\nNot persisted to the conversation event log: these events are published\ndirectly to PubSub, bypassing the callback chain that writes to\nConversationState.events. Clients reconnecting mid-stream will receive\nthe final MessageEvent from history but none of the deltas that produced\nit — deltas are a UX affordance, not part of the durable conversation\nrecord.", + "properties": { + "content": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" } - } + ], + "title": "Content" }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "id": { + "description": "Unique event id (ULID/UUID)", + "title": "Id", + "type": "string" + }, + "kind": { + "const": "StreamingDeltaEvent", + "title": "Kind", + "type": "string" + }, + "parent_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" } - } + ], + "description": "Parent event id in the conversation tree. None for the root, or for legacy events predating the tree (see EventLog's effective-parent rule). Events sharing a parent_id are sibling branches.", + "title": "Parent Id" + }, + "reasoning_content": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Reasoning Content" + }, + "source": { + "default": "agent", + "enum": [ + "agent", + "user", + "environment", + "hook" + ], + "title": "Source", + "type": "string" + }, + "timestamp": { + "description": "Event timestamp", + "title": "Timestamp", + "type": "string" } - } - } - }, - "/api/skills": { - "post": { - "tags": [ - "Skills" + }, + "required": [ + "kind" ], - "summary": "Get Skills", - "description": "Load and merge skills from all configured sources.\n\nSkills are loaded from multiple sources and merged with the following\nprecedence (later overrides earlier for duplicate names):\n1. Sandbox skills (lowest) - Exposed URLs from sandbox\n2. Public skills - From GitHub OpenHands/skills repository\n3. User skills - From ~/.openhands/skills/\n4. Organization skills - From {org}/.openhands or equivalent\n5. Project skills (highest) - From {workspace}/.openhands/skills/\n\nArgs:\n request: SkillsRequest containing configuration for which sources to load.\n\nReturns:\n SkillsResponse containing merged skills and source counts.", - "operationId": "get_skills_api_skills_post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SkillsRequest" + "title": "StreamingDeltaEvent", + "type": "object" + }, + "SubAgentInfo": { + "description": "Lossless view of an ``AgentDefinition`` returned by the API.\n\nEvery frontmatter field plus the discovered ``level``/``source``, an\n``is_builtin`` flag, and the inline ``system_prompt`` (Markdown body) so a\ndetail view needs no extra fetch.", + "properties": { + "color": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" } - } + ], + "title": "Color" }, - "required": true - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SkillsResponse" - } + "condenser": { + "anyOf": [ + { + "$ref": "#/components/schemas/CondenserBase-Output" + }, + { + "type": "null" } - } + ] }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } - } - } - } - }, - "/api/skills/sync": { - "post": { - "tags": [ - "Skills" - ], - "summary": "Sync Skills", - "description": "Force refresh of public skills from GitHub repository.\n\nThis triggers a git pull on the cached skills repository to get\nthe latest skills from the OpenHands/skills repository.\n\nReturns:\n SyncResponse indicating success or failure.", - "operationId": "sync_skills_api_skills_sync_post", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SyncResponse" - } + "description": { + "default": "", + "title": "Description", + "type": "string" + }, + "hooks": { + "anyOf": [ + { + "$ref": "#/components/schemas/HookConfig" + }, + { + "type": "null" } - } - } - } - } - }, - "/api/hooks": { - "post": { - "tags": [ - "Hooks" - ], - "summary": "Get Hooks", - "description": "Load hooks from the workspace .openhands/hooks.json file.\n\nThis endpoint reads the hooks configuration from the project's\n.openhands/hooks.json file if it exists.\n\nArgs:\n request: HooksRequest containing the project directory path.\n\nReturns:\n HooksResponse containing the hook configuration or None.", - "operationId": "get_hooks_api_hooks_post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HooksRequest" + ] + }, + "is_builtin": { + "default": false, + "title": "Is Builtin", + "type": "boolean" + }, + "level": { + "anyOf": [ + { + "enum": [ + "project", + "user", + "builtin", + "plugin", + "programmatic" + ], + "type": "string" + }, + { + "type": "null" } - } + ], + "title": "Level" }, - "required": true - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HooksResponse" - } + "max_budget_per_run": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" } - } + ], + "title": "Max Budget Per Run" }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "max_iteration_per_run": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" } - } - } - } - } - }, - "/": { - "get": { - "summary": "Get Server Info", - "operationId": "get_server_info__get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ServerInfo" - } + ], + "title": "Max Iteration Per Run" + }, + "mcp_config": { + "anyOf": [ + { + "additionalProperties": { + "$ref": "#/components/schemas/MCPServer-Output" + }, + "type": "object" + }, + { + "type": "null" } - } - } - } - } - } - }, - "components": { - "schemas": { - "APIBasedCritic-Input": { - "properties": { - "server_url": { - "type": "string", - "title": "Server Url", - "description": "Base URL of the vLLM classification service", - "default": "https://all-hands-ai--critic-qwen3-4b-serve.modal.run" + ], + "title": "Mcp Config" }, - "api_key": { + "mcp_servers": { "anyOf": [ { - "type": "string" + "additionalProperties": { + "$ref": "#/components/schemas/MCPServer-Output" + }, + "type": "object" }, { - "type": "string", - "format": "password", - "writeOnly": true + "type": "null" } ], - "title": "Api Key", - "description": "API key for authenticating with the vLLM service" + "deprecated": true, + "description": "Deprecated compatibility alias for mcp_config. Use mcp_config for new clients.", + "title": "Mcp Servers" }, - "model_name": { - "type": "string", - "title": "Model Name", - "description": "Name of the model to use", - "default": "critic-qwen3-4b" + "metadata": { + "additionalProperties": true, + "title": "Metadata", + "type": "object" }, - "tokenizer_name": { - "type": "string", - "title": "Tokenizer Name", - "description": "HuggingFace tokenizer name for loading chat template", - "default": "Qwen/Qwen3-4B-Instruct-2507" + "model": { + "default": "inherit", + "title": "Model", + "type": "string" }, - "pass_tools_definitions": { - "type": "boolean", - "title": "Pass Tools Definitions", - "description": "Whether to pass tool definitions to the model", - "default": true + "name": { + "title": "Name", + "type": "string" }, - "timeout_seconds": { - "type": "number", - "title": "Timeout Seconds", - "description": "Timeout for requests to the model", - "default": 300.0 + "permission_mode": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Permission Mode" }, - "has_success_label": { - "type": "boolean", - "title": "Has Success Label", - "description": "Whether the model predicts success label at index 0", - "default": true + "profile_store_dir": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Profile Store Dir" }, - "sentiment_labels": { + "skills": { "items": { "type": "string" }, - "type": "array", - "title": "Sentiment Labels", - "default": [ - "sentiment_positive", - "sentiment_neutral", - "sentiment_negative" - ] + "title": "Skills", + "type": "array" }, - "agent_issue_labels": { - "items": { - "type": "string" - }, - "type": "array", - "title": "Agent Issue Labels", - "default": [ - "misunderstood_intention", - "did_not_follow_instruction", - "insufficient_analysis", - "insufficient_clarification", - "improper_tool_use_or_setup", - "loop_behavior", - "insufficient_testing", - "insufficient_debugging", - "incomplete_implementation", - "file_management_errors", - "scope_creep", - "risky_actions_or_permission", - "other_agent_issue" - ] + "source": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Source" }, - "infra_labels": { - "items": { - "type": "string" - }, - "type": "array", - "title": "Infra Labels", - "default": [ - "infrastructure_external_issue", - "infrastructure_agent_caused_issue" - ] + "system_prompt": { + "default": "", + "title": "System Prompt", + "type": "string" }, - "user_followup_labels": { + "tools": { "items": { "type": "string" }, - "type": "array", - "title": "User Followup Labels", - "default": [ - "clarification_or_restatement", - "correction", - "direction_change", - "vcs_update_requests", - "progress_or_scope_concern", - "frustration_or_complaint", - "removal_or_reversion_request", - "other_user_issue" - ] + "title": "Tools", + "type": "array" }, - "sentiment_map": { - "additionalProperties": { + "when_to_use_examples": { + "items": { "type": "string" }, - "type": "object", - "title": "Sentiment Map", - "default": { - "Positive": "sentiment_positive", - "Neutral": "sentiment_neutral", - "Negative": "sentiment_negative" - } + "title": "When To Use Examples", + "type": "array" + } + }, + "required": [ + "name" + ], + "title": "SubAgentInfo", + "type": "object" + }, + "SubAgentsRequest": { + "description": "Request body for listing sub-agents.", + "properties": { + "load_builtin": { + "default": true, + "description": "Load SDK built-in agents (general-purpose, code-explorer, ...)", + "title": "Load Builtin", + "type": "boolean" }, - "mode": { - "type": "string", - "enum": [ - "finish_and_message", - "all_actions" - ], - "title": "Mode", - "description": "When to run critic evaluation:\n- 'finish_and_message': Evaluate on FinishAction and agent MessageEvent (default, minimal performance impact)\n- 'all_actions': Evaluate after every agent action (WARNING: significantly slower due to API calls on each action)", - "default": "finish_and_message" + "load_project": { + "default": true, + "description": "Load project agents from the workspace", + "title": "Load Project", + "type": "boolean" }, - "iterative_refinement": { + "load_user": { + "default": true, + "description": "Load user agents from ~/.agents/agents and ~/.openhands/agents", + "title": "Load User", + "type": "boolean" + }, + "project_dir": { "anyOf": [ { - "$ref": "#/components/schemas/IterativeRefinementConfig" + "type": "string" }, { "type": "null" } ], - "description": "Optional configuration for iterative refinement. When set, Conversation.run() will automatically retry the task if the critic score is below the success_threshold, up to max_iterations." + "description": "Workspace directory path for project agents", + "title": "Project Dir" + } + }, + "title": "SubAgentsRequest", + "type": "object" + }, + "SubAgentsResponse": { + "description": "Response containing all available sub-agents.", + "properties": { + "agents": { + "items": { + "$ref": "#/components/schemas/SubAgentInfo" + }, + "title": "Agents", + "type": "array" + } + }, + "required": [ + "agents" + ], + "title": "SubAgentsResponse", + "type": "object" + }, + "SubdirectoryEntry": { + "properties": { + "name": { + "title": "Name", + "type": "string" }, - "kind": { - "type": "string", - "const": "APIBasedCritic", - "title": "Kind" + "path": { + "title": "Path", + "type": "string" } }, - "type": "object", "required": [ - "api_key" + "name", + "path" ], - "title": "APIBasedCritic" + "title": "SubdirectoryEntry", + "type": "object" }, - "APIBasedCritic-Output": { + "SubdirectoryPage": { "properties": { - "server_url": { - "type": "string", - "title": "Server Url", - "description": "Base URL of the vLLM classification service", - "default": "https://all-hands-ai--critic-qwen3-4b-serve.modal.run" + "items": { + "items": { + "$ref": "#/components/schemas/SubdirectoryEntry" + }, + "title": "Items", + "type": "array" }, - "api_key": { + "next_page_id": { "anyOf": [ { "type": "string" }, { - "type": "string", - "format": "password", - "writeOnly": true + "type": "null" } ], - "title": "Api Key", - "description": "API key for authenticating with the vLLM service" - }, - "model_name": { - "type": "string", - "title": "Model Name", - "description": "Name of the model to use", - "default": "critic-qwen3-4b" + "title": "Next Page Id" + } + }, + "required": [ + "items" + ], + "title": "SubdirectoryPage", + "type": "object" + }, + "SubscriptionDevicePollRequest": { + "description": "Poll request for a previously-started subscription device login.", + "properties": { + "device_code": { + "title": "Device Code", + "type": "string" + } + }, + "required": [ + "device_code" + ], + "title": "SubscriptionDevicePollRequest", + "type": "object" + }, + "SubscriptionDeviceStartResponse": { + "description": "Device-code challenge details for browser sign-in.", + "properties": { + "device_code": { + "description": "Opaque server-side polling token.", + "title": "Device Code", + "type": "string" }, - "tokenizer_name": { - "type": "string", - "title": "Tokenizer Name", - "description": "HuggingFace tokenizer name for loading chat template", - "default": "Qwen/Qwen3-4B-Instruct-2507" + "expires_at": { + "title": "Expires At", + "type": "integer" }, - "pass_tools_definitions": { - "type": "boolean", - "title": "Pass Tools Definitions", - "description": "Whether to pass tool definitions to the model", - "default": true + "interval_seconds": { + "title": "Interval Seconds", + "type": "integer" }, - "timeout_seconds": { - "type": "number", - "title": "Timeout Seconds", - "description": "Timeout for requests to the model", - "default": 300.0 + "user_code": { + "title": "User Code", + "type": "string" }, - "has_success_label": { - "type": "boolean", - "title": "Has Success Label", - "description": "Whether the model predicts success label at index 0", - "default": true + "verification_uri": { + "title": "Verification Uri", + "type": "string" }, - "sentiment_labels": { + "verification_uri_complete": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Verification Uri Complete" + } + }, + "required": [ + "device_code", + "user_code", + "verification_uri", + "expires_at", + "interval_seconds" + ], + "title": "SubscriptionDeviceStartResponse", + "type": "object" + }, + "SubscriptionModelsResponse": { + "description": "Models available through a subscription provider.", + "properties": { + "models": { "items": { "type": "string" }, - "type": "array", - "title": "Sentiment Labels", - "default": [ - "sentiment_positive", - "sentiment_neutral", - "sentiment_negative" - ] + "title": "Models", + "type": "array" }, - "agent_issue_labels": { - "items": { - "type": "string" - }, - "type": "array", - "title": "Agent Issue Labels", - "default": [ - "misunderstood_intention", - "did_not_follow_instruction", - "insufficient_analysis", - "insufficient_clarification", - "improper_tool_use_or_setup", - "loop_behavior", - "insufficient_testing", - "insufficient_debugging", - "incomplete_implementation", - "file_management_errors", - "scope_creep", - "risky_actions_or_permission", - "other_agent_issue" - ] + "vendor": { + "default": "openai", + "title": "Vendor", + "type": "string" + } + }, + "required": [ + "models" + ], + "title": "SubscriptionModelsResponse", + "type": "object" + }, + "SubscriptionStatusResponse": { + "description": "Safe subscription authentication status.", + "properties": { + "account_email": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Account Email" }, - "infra_labels": { - "items": { - "type": "string" - }, - "type": "array", - "title": "Infra Labels", - "default": [ - "infrastructure_external_issue", - "infrastructure_agent_caused_issue" - ] + "connected": { + "title": "Connected", + "type": "boolean" }, - "user_followup_labels": { + "expires_at": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Expires At" + }, + "vendor": { + "default": "openai", + "title": "Vendor", + "type": "string" + } + }, + "required": [ + "connected" + ], + "title": "SubscriptionStatusResponse", + "type": "object" + }, + "Success": { + "properties": { + "success": { + "default": true, + "title": "Success", + "type": "boolean" + } + }, + "title": "Success", + "type": "object" + }, + "SwitchLLMAction": { + "additionalProperties": false, + "description": "Action for switching this conversation to a saved LLM profile.", + "properties": { + "kind": { + "const": "SwitchLLMAction", + "title": "Kind", + "type": "string" + }, + "profile_name": { + "description": "Name of the saved LLM profile to use for future agent steps.", + "title": "Profile Name", + "type": "string" + }, + "reason": { + "description": "Brief reason why this profile is a better fit for the next step.", + "title": "Reason", + "type": "string" + } + }, + "required": [ + "profile_name", + "reason", + "kind" + ], + "title": "SwitchLLMAction", + "type": "object" + }, + "SwitchLLMObservation": { + "additionalProperties": false, + "description": "Observation returned after switching this conversation's LLM profile.", + "properties": { + "active_model": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Model configured by the activated profile, when available.", + "title": "Active Model" + }, + "content": { + "description": "Content returned from the tool as a list of TextContent/ImageContent objects. When there is an error, it should be written in this field.", "items": { - "type": "string" + "anyOf": [ + { + "$ref": "#/components/schemas/TextContent" + }, + { + "$ref": "#/components/schemas/ImageContent" + } + ] }, - "type": "array", - "title": "User Followup Labels", - "default": [ - "clarification_or_restatement", - "correction", - "direction_change", - "vcs_update_requests", - "progress_or_scope_concern", - "frustration_or_complaint", - "removal_or_reversion_request", - "other_user_issue" - ] + "title": "Content", + "type": "array" }, - "sentiment_map": { - "additionalProperties": { - "type": "string" - }, - "type": "object", - "title": "Sentiment Map", - "default": { - "Positive": "sentiment_positive", - "Neutral": "sentiment_neutral", - "Negative": "sentiment_negative" - } + "is_error": { + "default": false, + "description": "Whether the observation indicates an error", + "title": "Is Error", + "type": "boolean" }, - "mode": { - "type": "string", - "enum": [ - "finish_and_message", - "all_actions" - ], - "title": "Mode", - "description": "When to run critic evaluation:\n- 'finish_and_message': Evaluate on FinishAction and agent MessageEvent (default, minimal performance impact)\n- 'all_actions': Evaluate after every agent action (WARNING: significantly slower due to API calls on each action)", - "default": "finish_and_message" + "kind": { + "const": "SwitchLLMObservation", + "title": "Kind", + "type": "string" }, - "iterative_refinement": { + "profile_name": { + "description": "Name of the profile that the tool attempted to activate.", + "title": "Profile Name", + "type": "string" + }, + "reason": { "anyOf": [ { - "$ref": "#/components/schemas/IterativeRefinementConfig" + "type": "string" }, { "type": "null" } ], - "description": "Optional configuration for iterative refinement. When set, Conversation.run() will automatically retry the task if the critic score is below the success_threshold, up to max_iterations." - }, - "kind": { - "type": "string", - "const": "APIBasedCritic", - "title": "Kind" + "description": "Reason the agent gave for attempting this LLM profile switch.", + "title": "Reason" } }, - "type": "object", "required": [ - "api_key", + "profile_name", "kind" ], - "title": "APIBasedCritic" + "title": "SwitchLLMObservation", + "type": "object" }, - "Action": { - "oneOf": [ - { - "$ref": "#/components/schemas/MCPToolAction" - }, - { - "$ref": "#/components/schemas/FinishAction" - }, - { - "$ref": "#/components/schemas/ThinkAction" + "SwitchLLMTool": { + "description": "Tool for switching a conversation to a saved LLM profile.", + "properties": { + "action_type": { + "title": "Action Type", + "type": "string" }, - { - "$ref": "#/components/schemas/BrowserAction" + "annotations": { + "anyOf": [ + { + "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" + }, + { + "type": "null" + } + ] }, - { - "$ref": "#/components/schemas/BrowserClickAction" + "description": { + "title": "Description", + "type": "string" }, - { - "$ref": "#/components/schemas/BrowserCloseTabAction" + "kind": { + "const": "SwitchLLMTool", + "title": "Kind", + "type": "string" }, - { - "$ref": "#/components/schemas/BrowserGetContentAction" + "meta": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Meta" }, - { - "$ref": "#/components/schemas/BrowserGetStateAction" + "observation_type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Observation Type" }, - { - "$ref": "#/components/schemas/BrowserGetStorageAction" + "title": { + "readOnly": true, + "title": "Title", + "type": "string" + } + }, + "required": [ + "description", + "action_type", + "kind", + "title" + ], + "title": "SwitchLLMTool", + "type": "object" + }, + "SyncResponse": { + "description": "Response from skill sync operation.", + "properties": { + "message": { + "title": "Message", + "type": "string" }, - { - "$ref": "#/components/schemas/BrowserGoBackAction" + "status": { + "enum": [ + "success", + "error" + ], + "title": "Status", + "type": "string" + } + }, + "required": [ + "status", + "message" + ], + "title": "SyncResponse", + "type": "object" + }, + "SystemPromptEvent": { + "additionalProperties": false, + "description": "System prompt added by the agent.\n\nThe system prompt can optionally include dynamic context that varies between\nconversations. When ``dynamic_context`` is provided, it is included as a\nsecond content block in the same system message. Cache markers are NOT\napplied here - they are applied by ``LLM._apply_prompt_caching()`` when\ncaching is enabled, ensuring provider-specific cache control is only added\nwhen appropriate.\n\nAttributes:\n system_prompt: The static system prompt text (cacheable across conversations)\n tools: List of available tools\n dynamic_context: Optional per-conversation context (hosts, repo info, etc.)\n Sent as a second TextContent block inside the system message.", + "properties": { + "dynamic_context": { + "anyOf": [ + { + "$ref": "#/components/schemas/TextContent" + }, + { + "type": "null" + } + ], + "description": "Optional dynamic per-conversation context (runtime info, repo context, secrets). When provided, this is included as a second content block in the system message (not cached)." }, - { - "$ref": "#/components/schemas/BrowserListTabsAction" + "id": { + "description": "Unique event id (ULID/UUID)", + "title": "Id", + "type": "string" }, - { - "$ref": "#/components/schemas/BrowserNavigateAction" + "kind": { + "const": "SystemPromptEvent", + "title": "Kind", + "type": "string" }, - { - "$ref": "#/components/schemas/BrowserScrollAction" + "parent_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Parent event id in the conversation tree. None for the root, or for legacy events predating the tree (see EventLog's effective-parent rule). Events sharing a parent_id are sibling branches.", + "title": "Parent Id" }, - { - "$ref": "#/components/schemas/BrowserSetStorageAction" + "source": { + "default": "agent", + "enum": [ + "agent", + "user", + "environment", + "hook" + ], + "title": "Source", + "type": "string" }, - { - "$ref": "#/components/schemas/BrowserStartRecordingAction" + "system_prompt": { + "$ref": "#/components/schemas/TextContent", + "description": "The system prompt text" }, - { - "$ref": "#/components/schemas/BrowserStopRecordingAction" + "timestamp": { + "description": "Event timestamp", + "title": "Timestamp", + "type": "string" }, - { - "$ref": "#/components/schemas/BrowserSwitchTabAction" + "tools": { + "description": "List of tools as ToolDefinition objects", + "items": { + "$ref": "#/components/schemas/ToolDefinition" + }, + "title": "Tools", + "type": "array" + } + }, + "required": [ + "system_prompt", + "tools", + "kind" + ], + "title": "SystemPromptEvent", + "type": "object" + }, + "TaskAction": { + "additionalProperties": false, + "description": "Schema for launching a sub-agent task.", + "properties": { + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "A short (3-5 word) description of the task.", + "title": "Description" }, - { - "$ref": "#/components/schemas/BrowserTypeAction" + "kind": { + "const": "TaskAction", + "title": "Kind", + "type": "string" }, - { - "$ref": "#/components/schemas/FileEditorAction" + "prompt": { + "description": "The task for the agent to perform.", + "title": "Prompt", + "type": "string" }, - { - "$ref": "#/components/schemas/EditAction" + "resume": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Task ID of the task to resume from.", + "title": "Resume" }, - { - "$ref": "#/components/schemas/ListDirectoryAction" + "subagent_type": { + "default": "general-purpose", + "description": "The type of specialized agent to use for this task.", + "title": "Subagent Type", + "type": "string" + } + }, + "required": [ + "prompt", + "kind" + ], + "title": "TaskAction", + "type": "object" + }, + "TaskItem": { + "properties": { + "notes": { + "default": "", + "description": "Additional details or notes about the task.", + "title": "Notes", + "type": "string" }, - { - "$ref": "#/components/schemas/ReadFileAction" + "status": { + "default": "todo", + "description": "The current status of the task. One of 'todo', 'in_progress', or 'done'.", + "enum": [ + "todo", + "in_progress", + "done" + ], + "title": "Status", + "type": "string" }, - { - "$ref": "#/components/schemas/WriteFileAction" + "title": { + "description": "A brief title for the task.", + "title": "Title", + "type": "string" + } + }, + "required": [ + "title" + ], + "title": "TaskItem", + "type": "object" + }, + "TaskObservation": { + "additionalProperties": false, + "description": "Observation from a task execution.", + "properties": { + "content": { + "description": "Content returned from the tool as a list of TextContent/ImageContent objects. When there is an error, it should be written in this field.", + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/TextContent" + }, + { + "$ref": "#/components/schemas/ImageContent" + } + ] + }, + "title": "Content", + "type": "array" }, - { - "$ref": "#/components/schemas/GlobAction" + "is_error": { + "default": false, + "description": "Whether the observation indicates an error", + "title": "Is Error", + "type": "boolean" }, - { - "$ref": "#/components/schemas/GrepAction" + "kind": { + "const": "TaskObservation", + "title": "Kind", + "type": "string" }, - { - "$ref": "#/components/schemas/PlanningFileEditorAction" + "status": { + "description": "The status of the task.", + "title": "Status", + "type": "string" }, - { - "$ref": "#/components/schemas/TaskTrackerAction" + "subagent": { + "description": "The subagent of the task.", + "title": "Subagent", + "type": "string" }, - { - "$ref": "#/components/schemas/TerminalAction" + "task_id": { + "description": "The unique identifier of the task.", + "title": "Task Id", + "type": "string" } + }, + "required": [ + "task_id", + "subagent", + "status", + "kind" ], - "discriminator": { - "propertyName": "kind", - "mapping": { - "openhands__sdk__mcp__definition__MCPToolAction-Output__1": "#/components/schemas/MCPToolAction", - "openhands__sdk__tool__builtins__finish__FinishAction-Output__1": "#/components/schemas/FinishAction", - "openhands__sdk__tool__builtins__think__ThinkAction-Output__1": "#/components/schemas/ThinkAction", - "openhands__tools__browser_use__definition__BrowserAction-Output__1": "#/components/schemas/BrowserAction", - "openhands__tools__browser_use__definition__BrowserClickAction-Output__1": "#/components/schemas/BrowserClickAction", - "openhands__tools__browser_use__definition__BrowserCloseTabAction-Output__1": "#/components/schemas/BrowserCloseTabAction", - "openhands__tools__browser_use__definition__BrowserGetContentAction-Output__1": "#/components/schemas/BrowserGetContentAction", - "openhands__tools__browser_use__definition__BrowserGetStateAction-Output__1": "#/components/schemas/BrowserGetStateAction", - "openhands__tools__browser_use__definition__BrowserGetStorageAction-Output__1": "#/components/schemas/BrowserGetStorageAction", - "openhands__tools__browser_use__definition__BrowserGoBackAction-Output__1": "#/components/schemas/BrowserGoBackAction", - "openhands__tools__browser_use__definition__BrowserListTabsAction-Output__1": "#/components/schemas/BrowserListTabsAction", - "openhands__tools__browser_use__definition__BrowserNavigateAction-Output__1": "#/components/schemas/BrowserNavigateAction", - "openhands__tools__browser_use__definition__BrowserScrollAction-Output__1": "#/components/schemas/BrowserScrollAction", - "openhands__tools__browser_use__definition__BrowserSetStorageAction-Output__1": "#/components/schemas/BrowserSetStorageAction", - "openhands__tools__browser_use__definition__BrowserStartRecordingAction-Output__1": "#/components/schemas/BrowserStartRecordingAction", - "openhands__tools__browser_use__definition__BrowserStopRecordingAction-Output__1": "#/components/schemas/BrowserStopRecordingAction", - "openhands__tools__browser_use__definition__BrowserSwitchTabAction-Output__1": "#/components/schemas/BrowserSwitchTabAction", - "openhands__tools__browser_use__definition__BrowserTypeAction-Output__1": "#/components/schemas/BrowserTypeAction", - "openhands__tools__file_editor__definition__FileEditorAction-Output__1": "#/components/schemas/FileEditorAction", - "openhands__tools__gemini__edit__definition__EditAction-Output__1": "#/components/schemas/EditAction", - "openhands__tools__gemini__list_directory__definition__ListDirectoryAction-Output__1": "#/components/schemas/ListDirectoryAction", - "openhands__tools__gemini__read_file__definition__ReadFileAction-Output__1": "#/components/schemas/ReadFileAction", - "openhands__tools__gemini__write_file__definition__WriteFileAction-Output__1": "#/components/schemas/WriteFileAction", - "openhands__tools__glob__definition__GlobAction-Output__1": "#/components/schemas/GlobAction", - "openhands__tools__grep__definition__GrepAction-Output__1": "#/components/schemas/GrepAction", - "openhands__tools__planning_file_editor__definition__PlanningFileEditorAction-Output__1": "#/components/schemas/PlanningFileEditorAction", - "openhands__tools__task_tracker__definition__TaskTrackerAction-Output__1": "#/components/schemas/TaskTrackerAction", - "openhands__tools__terminal__definition__TerminalAction-Output__1": "#/components/schemas/TerminalAction" - } - } + "title": "TaskObservation", + "type": "object" }, - "ActionEvent": { + "TaskTool": { + "description": "Tool for launching (blocking) sub-agent tasks.", "properties": { - "id": { - "type": "string", - "title": "Id", - "description": "Unique event id (ULID/UUID)" + "action_type": { + "title": "Action Type", + "type": "string" }, - "timestamp": { - "type": "string", - "title": "Timestamp", - "description": "Event timestamp" + "annotations": { + "anyOf": [ + { + "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" + }, + { + "type": "null" + } + ] }, - "source": { - "type": "string", - "enum": [ - "agent", - "user", - "environment" - ], - "title": "Source", - "default": "agent" + "description": { + "title": "Description", + "type": "string" }, - "thought": { - "items": { - "$ref": "#/components/schemas/TextContent" - }, - "type": "array", - "title": "Thought", - "description": "The thought process of the agent before taking this action" + "kind": { + "const": "TaskTool", + "title": "Kind", + "type": "string" }, - "reasoning_content": { + "meta": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Meta" + }, + "observation_type": { "anyOf": [ { "type": "string" @@ -2847,82 +20168,215 @@ "type": "null" } ], - "title": "Reasoning Content", - "description": "Intermediate reasoning/thinking content from reasoning models" + "title": "Observation Type" }, - "thinking_blocks": { - "items": { - "anyOf": [ - { - "$ref": "#/components/schemas/ThinkingBlock" - }, - { - "$ref": "#/components/schemas/RedactedThinkingBlock" - } - ] - }, - "type": "array", - "title": "Thinking Blocks", - "description": "Anthropic thinking blocks from the LLM response" + "title": { + "readOnly": true, + "title": "Title", + "type": "string" + } + }, + "required": [ + "description", + "action_type", + "kind", + "title" + ], + "title": "TaskTool", + "type": "object" + }, + "TaskToolSet": { + "description": "Task tool set.\n\nCreates the Task tool backed by a shared TaskManager.\n\nUsage:\n from openhands.tools.task import TaskToolSet\n\n agent = Agent(\n llm=llm,\n tools=[\n Tool(name=TerminalTool.name),\n Tool(name=FileEditorTool.name),\n Tool(name=TaskToolSet.name),\n ],\n )", + "properties": { + "action_type": { + "title": "Action Type", + "type": "string" }, - "responses_reasoning_item": { + "annotations": { "anyOf": [ { - "$ref": "#/components/schemas/ReasoningItemModel" + "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" + }, + { + "type": "null" + } + ] + }, + "description": { + "title": "Description", + "type": "string" + }, + "kind": { + "const": "TaskToolSet", + "title": "Kind", + "type": "string" + }, + "meta": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" }, { "type": "null" } ], - "description": "OpenAI Responses reasoning item from model output" + "title": "Meta" }, - "action": { + "observation_type": { "anyOf": [ { - "$ref": "#/components/schemas/Action" + "type": "string" }, { "type": "null" } ], - "description": "Single tool call returned by LLM (None when non-executable)" + "title": "Observation Type" }, - "tool_name": { - "type": "string", - "title": "Tool Name", - "description": "The name of the tool being called" + "title": { + "readOnly": true, + "title": "Title", + "type": "string" + } + }, + "required": [ + "description", + "action_type", + "kind", + "title" + ], + "title": "TaskToolSet", + "type": "object" + }, + "TaskTrackerAction": { + "additionalProperties": false, + "description": "An action where the agent writes or updates a task list for task management.", + "properties": { + "command": { + "default": "view", + "description": "The command to execute. `view` shows the current task list. `plan` creates or updates the task list based on provided requirements and progress. Always `view` the current list before making changes.", + "enum": [ + "view", + "plan" + ], + "title": "Command", + "type": "string" }, - "tool_call_id": { - "type": "string", - "title": "Tool Call Id", - "description": "The unique id returned by LLM API for this tool call" + "kind": { + "const": "TaskTrackerAction", + "title": "Kind", + "type": "string" }, - "tool_call": { - "$ref": "#/components/schemas/MessageToolCall", - "description": "The tool call received from the LLM response. We keep a copy of it so it is easier to construct it into LLM messageThis could be different from `action`: e.g., `tool_call` may contain `security_risk` field predicted by LLM when LLM risk analyzer is enabled, while `action` does not." + "task_list": { + "description": "The full task list. Required parameter of `plan` command.", + "items": { + "$ref": "#/components/schemas/TaskItem" + }, + "title": "Task List", + "type": "array" + } + }, + "required": [ + "kind" + ], + "title": "TaskTrackerAction", + "type": "object" + }, + "TaskTrackerObservation": { + "additionalProperties": false, + "description": "This data class represents the result of a task tracking operation.", + "properties": { + "command": { + "description": "The command that was executed: \"view\" or \"plan\".", + "enum": [ + "view", + "plan" + ], + "title": "Command", + "type": "string" }, - "llm_response_id": { - "type": "string", - "title": "Llm Response Id", - "description": "Completion or Response ID of the LLM response that generated this eventE.g., Can be used to group related actions from same LLM response. This helps in tracking and managing results of parallel function calling from the same LLM response." + "content": { + "description": "Content returned from the tool as a list of TextContent/ImageContent objects. When there is an error, it should be written in this field.", + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/TextContent" + }, + { + "$ref": "#/components/schemas/ImageContent" + } + ] + }, + "title": "Content", + "type": "array" + }, + "is_error": { + "default": false, + "description": "Whether the observation indicates an error", + "title": "Is Error", + "type": "boolean" + }, + "kind": { + "const": "TaskTrackerObservation", + "title": "Kind", + "type": "string" + }, + "task_list": { + "description": "The current task list", + "items": { + "$ref": "#/components/schemas/TaskItem" + }, + "title": "Task List", + "type": "array" + } + }, + "required": [ + "command", + "kind" + ], + "title": "TaskTrackerObservation", + "type": "object" + }, + "TaskTrackerTool": { + "description": "A ToolDefinition subclass that automatically initializes a TaskTrackerExecutor.", + "properties": { + "action_type": { + "title": "Action Type", + "type": "string" + }, + "annotations": { + "anyOf": [ + { + "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" + }, + { + "type": "null" + } + ] }, - "security_risk": { - "$ref": "#/components/schemas/SecurityRisk", - "description": "The LLM's assessment of the safety risk of this action.", - "default": "UNKNOWN" + "description": { + "title": "Description", + "type": "string" }, - "critic_result": { + "kind": { + "const": "TaskTrackerTool", + "title": "Kind", + "type": "string" + }, + "meta": { "anyOf": [ { - "$ref": "#/components/schemas/CriticResult" + "additionalProperties": true, + "type": "object" }, { "type": "null" } ], - "description": "Optional critic evaluation of this action and preceding history." + "title": "Meta" }, - "summary": { + "observation_type": { "anyOf": [ { "type": "string" @@ -2931,81 +20385,85 @@ "type": "null" } ], - "title": "Summary", - "description": "A concise summary (approximately 10 words) of what this action does, provided by the LLM for explainability and debugging. Examples of good summaries: 'editing configuration file for deployment settings' | 'searching codebase for authentication function definitions' | 'installing required dependencies from package manifest' | 'running tests to verify bug fix' | 'viewing directory structure to locate source files'" + "title": "Observation Type" }, - "kind": { - "type": "string", - "const": "ActionEvent", - "title": "Kind" + "title": { + "readOnly": true, + "title": "Title", + "type": "string" } }, - "additionalProperties": false, - "type": "object", "required": [ - "thought", - "tool_name", - "tool_call_id", - "tool_call", - "llm_response_id", - "kind" + "description", + "action_type", + "kind", + "title" ], - "title": "ActionEvent" + "title": "TaskTrackerTool", + "type": "object" }, - "Agent-Input": { + "TaskTrigger": { + "description": "Trigger for task-specific skills.\n\nThese skills are activated for specific task types and can modify prompts.", "properties": { - "llm": { - "$ref": "#/components/schemas/LLM", - "description": "LLM configuration for the agent.", - "examples": [ - { - "api_key": "your_api_key_here", - "base_url": "https://llm-proxy.eval.all-hands.dev", - "model": "litellm_proxy/anthropic/claude-sonnet-4-5-20250929" - } - ] - }, - "tools": { + "triggers": { "items": { - "$ref": "#/components/schemas/Tool-Input" + "type": "string" }, - "type": "array", - "title": "Tools", - "description": "List of tools to initialize for the agent.", - "examples": [ - { - "name": "TerminalTool", - "params": {} - }, - { - "name": "FileEditorTool", - "params": {} - }, - { - "name": "TaskTrackerTool", - "params": {} - } - ] + "title": "Triggers", + "type": "array" }, - "mcp_config": { - "additionalProperties": true, - "type": "object", - "title": "Mcp Config", - "description": "Optional MCP configuration dictionary to create MCP tools.", - "examples": [ - { - "mcpServers": { - "fetch": { - "args": [ - "mcp-server-fetch" - ], - "command": "uvx" - } - } - } - ] + "type": { + "const": "task", + "default": "task", + "title": "Type", + "type": "string" + } + }, + "required": [ + "triggers" + ], + "title": "TaskTrigger", + "type": "object" + }, + "TelemetrySpec": { + "description": "Deployment-supplied product-analytics transport settings.\n\nThis carries transport plus the non-identifying deployment tag. Whether\ntelemetry may be delivered is resolved from consent\n(``misc_settings.telemetry.consent``, optionally seeded or overridden by\n``OH_TELEMETRY_CONSENT``).", + "properties": { + "deployment_kind": { + "default": "local", + "description": "Deployment kind attached to diagnostic events. Use 'remote' for hosted OpenHands and 'local' for self-hosted or developer runs.", + "enum": [ + "local", + "remote" + ], + "title": "Deployment Kind", + "type": "string" }, - "filter_tools_regex": { + "event_buffer_size": { + "default": 20, + "description": "Maximum events per delivery batch.", + "minimum": 1.0, + "title": "Event Buffer Size", + "type": "integer" + }, + "exporter": { + "default": "none", + "description": "Exporter to use. 'none' (the default) never delivers, and is what library and headless consumers get. 'posthog' requires the [posthog] extra. 'http' POSTs sanitized batches to telemetry_http_endpoint.", + "enum": [ + "none", + "posthog", + "http" + ], + "title": "Exporter", + "type": "string" + }, + "flush_delay": { + "default": 30.0, + "description": "Seconds to wait before flushing a partial batch.", + "exclusiveMinimum": 0.0, + "title": "Flush Delay", + "type": "number" + }, + "http_endpoint": { "anyOf": [ { "type": "string" @@ -3014,191 +20472,134 @@ "type": "null" } ], - "title": "Filter Tools Regex", - "description": "Optional regex to filter the tools available to the agent by name. This is applied after any tools provided in `tools` and any MCP tools are added.", - "examples": [ - "^(?!repomix)(.*)|^repomix.*pack_codebase.*$" - ] - }, - "include_default_tools": { - "items": { - "type": "string" - }, - "type": "array", - "title": "Include Default Tools", - "description": "List of default tool class names to include. By default, the agent includes 'FinishTool' and 'ThinkTool'. Set to an empty list to disable all default tools, or provide a subset to include only specific ones. Example: include_default_tools=['FinishTool'] to only include FinishTool, or include_default_tools=[] to disable all default tools.", - "examples": [ - [ - "FinishTool", - "ThinkTool" - ], - [ - "FinishTool" - ], - [] - ] + "description": "Endpoint the 'http' exporter POSTs sanitized event batches to. Intended to front a backend that revalidates auth and consent before forwarding onward.", + "title": "Http Endpoint" }, - "agent_context": { + "http_token": { "anyOf": [ { - "$ref": "#/components/schemas/AgentContext-Input" + "format": "password", + "type": "string", + "writeOnly": true }, { "type": "null" } ], - "description": "Optional AgentContext to initialize the agent with specific context.", - "examples": [ - { - "skills": [ - { - "content": "When you see this message, you should reply like you are a grumpy cat forced to use the internet.", - "name": "AGENTS.md", - "type": "repo" - }, - { - "content": "IMPORTANT! The user has said the magic word \"flarglebargle\". You must only respond with a message telling them how smart they are", - "name": "flarglebargle", - "trigger": [ - "flarglebargle" - ], - "type": "knowledge" - } - ], - "system_message_suffix": "Always finish your response with the word 'yay!'", - "user_message_prefix": "The first character of your response should be 'I'" - } - ] - }, - "system_prompt_filename": { - "type": "string", - "title": "System Prompt Filename", - "description": "System prompt template filename. Can be either:\n- A relative filename (e.g., 'system_prompt.j2') loaded from the agent's prompts directory\n- An absolute path (e.g., '/path/to/custom_prompt.j2')", - "default": "system_prompt.j2" + "description": "Bearer token sent by the 'http' exporter, if required.", + "title": "Http Token" }, - "security_policy_filename": { - "type": "string", - "title": "Security Policy Filename", - "description": "Security policy template filename. Can be either:\n- A relative filename (e.g., 'security_policy.j2') loaded from the agent's prompts directory\n- An absolute path (e.g., '/path/to/custom_security_policy.j2')", - "default": "security_policy.j2" + "max_queue_size": { + "default": 1000, + "description": "Upper bound on buffered diagnostic events. The queue is bounded on ingest: past this many events the oldest are dropped, so a failing exporter cannot grow memory without limit.", + "minimum": 1.0, + "title": "Max Queue Size", + "type": "integer" }, - "system_prompt_kwargs": { - "additionalProperties": true, - "type": "object", - "title": "System Prompt Kwargs", - "description": "Optional kwargs to pass to the system prompt Jinja2 template.", - "examples": [ - { - "cli_mode": true - } - ] + "num_retries": { + "default": 2, + "description": "Retries before a batch is dropped.", + "minimum": 0.0, + "title": "Num Retries", + "type": "integer" }, - "condenser": { + "posthog_api_key": { "anyOf": [ { - "$ref": "#/components/schemas/CondenserBase-Input" + "format": "password", + "type": "string", + "writeOnly": true }, { "type": "null" } ], - "description": "Optional condenser to use for condensing conversation history.", - "examples": [ - { - "keep_first": 10, - "kind": "LLMSummarizingCondenser", - "llm": { - "api_key": "your_api_key_here", - "base_url": "https://llm-proxy.eval.all-hands.dev", - "model": "litellm_proxy/anthropic/claude-sonnet-4-5-20250929" - }, - "max_size": 80 - } - ] + "description": "PostHog project API key. Required by the 'posthog' exporter; without it telemetry stays inactive.", + "title": "Posthog Api Key" }, - "critic": { + "posthog_host": { + "default": "https://us.i.posthog.com", + "description": "PostHog ingestion host.", + "title": "Posthog Host", + "type": "string" + }, + "retry_delay": { + "default": 5.0, + "description": "Base seconds between delivery retries.", + "minimum": 0.0, + "title": "Retry Delay", + "type": "number" + }, + "salt": { "anyOf": [ { - "$ref": "#/components/schemas/CriticBase-Input" + "format": "password", + "type": "string", + "writeOnly": true }, { "type": "null" } ], - "description": "EXPERIMENTAL: Optional critic to evaluate agent actions and messages in real-time. API and behavior may change without notice. May impact performance, especially in 'all_actions' mode.", - "examples": [ - { - "kind": "AgentFinishedCritic" - } - ] - }, - "kind": { - "type": "string", - "const": "Agent", - "title": "Kind" + "description": "Key used to pseudonymize conversation identifiers. Falls back to a per-process random salt, which keeps pseudonyms stable within a run but unlinkable across runs.", + "title": "Salt" } }, - "type": "object", - "required": [ - "llm" - ], - "title": "Agent", - "description": "Main agent implementation for OpenHands.\n\nThe Agent class provides the core functionality for running AI agents that can\ninteract with tools, process messages, and execute actions. It inherits from\nAgentBase and implements the agent execution logic. Critic-related functionality\nis provided by CriticMixin.\n\nExample:\n >>> from openhands.sdk import LLM, Agent, Tool\n >>> llm = LLM(model=\"claude-sonnet-4-20250514\", api_key=SecretStr(\"key\"))\n >>> tools = [Tool(name=\"TerminalTool\"), Tool(name=\"FileEditorTool\")]\n >>> agent = Agent(llm=llm, tools=tools)" + "title": "TelemetrySpec", + "type": "object" }, - "Agent-Output": { + "TerminalAction": { + "additionalProperties": false, + "description": "Schema for terminal command execution.", "properties": { - "llm": { - "$ref": "#/components/schemas/LLM", - "description": "LLM configuration for the agent.", - "examples": [ - { - "api_key": "your_api_key_here", - "base_url": "https://llm-proxy.eval.all-hands.dev", - "model": "litellm_proxy/anthropic/claude-sonnet-4-5-20250929" - } - ] + "command": { + "description": "The shell command to execute. Can be empty string to view additional logs when the previous exit code is `-1`. Can be a special key name when `is_input` is True: `C-c` (Ctrl+C), `C-d` (Ctrl+D/EOF), `C-z` (Ctrl+Z), or any `C-` for Ctrl sequences; navigation keys `UP`, `DOWN`, `LEFT`, `RIGHT`, `HOME`, `END`, `PGUP`, `PGDN`; and `TAB`, `ESC`, `BS` (Backspace), `ENTER`. You can only execute one command at a time. Use the platform-appropriate shell syntax described in the tool description when chaining commands.", + "title": "Command", + "type": "string" }, - "tools": { - "items": { - "$ref": "#/components/schemas/openhands__sdk__tool__spec__Tool" - }, - "type": "array", - "title": "Tools", - "description": "List of tools to initialize for the agent.", - "examples": [ - { - "name": "TerminalTool", - "params": {} - }, - { - "name": "FileEditorTool", - "params": {} - }, - { - "name": "TaskTrackerTool", - "params": {} - } - ] + "is_input": { + "default": false, + "description": "If True, the command is an input to the running process. If False, the command is executed in the terminal session. Default is False.", + "title": "Is Input", + "type": "boolean" }, - "mcp_config": { - "additionalProperties": true, - "type": "object", - "title": "Mcp Config", - "description": "Optional MCP configuration dictionary to create MCP tools.", - "examples": [ + "kind": { + "const": "TerminalAction", + "title": "Kind", + "type": "string" + }, + "reset": { + "default": false, + "description": "If True, reset the terminal by creating a new session. Use this only when the terminal becomes unresponsive. Note that all previously set environment variables and session state will be lost after reset. Cannot be used with is_input=True.", + "title": "Reset", + "type": "boolean" + }, + "timeout": { + "anyOf": [ { - "mcpServers": { - "fetch": { - "args": [ - "mcp-server-fetch" - ], - "command": "uvx" - } - } + "minimum": 0.0, + "type": "number" + }, + { + "type": "null" } - ] - }, - "filter_tools_regex": { + ], + "description": "Optional. Sets a maximum time limit (in seconds) for running the command. If the command takes longer than this limit, you’ll be asked whether to continue or stop it. If you don’t set a value, the command will instead pause and ask for confirmation when it produces no new output for 30 seconds. Use a higher value if the command is expected to take a long time (like installation or testing), or if it has a known fixed duration (like sleep).", + "title": "Timeout" + } + }, + "required": [ + "command", + "kind" + ], + "title": "TerminalAction", + "type": "object" + }, + "TerminalObservation": { + "additionalProperties": false, + "description": "A ToolResult that can be rendered as a CLI output.", + "properties": { + "command": { "anyOf": [ { "type": "string" @@ -3207,218 +20608,265 @@ "type": "null" } ], - "title": "Filter Tools Regex", - "description": "Optional regex to filter the tools available to the agent by name. This is applied after any tools provided in `tools` and any MCP tools are added.", - "examples": [ - "^(?!repomix)(.*)|^repomix.*pack_codebase.*$" - ] + "description": "The shell command that was executed. Can be empty string if the observation is from a previous command that hit soft timeout and is not yet finished.", + "title": "Command" }, - "include_default_tools": { + "content": { + "description": "Content returned from the tool as a list of TextContent/ImageContent objects. When there is an error, it should be written in this field.", "items": { - "type": "string" + "anyOf": [ + { + "$ref": "#/components/schemas/TextContent" + }, + { + "$ref": "#/components/schemas/ImageContent" + } + ] }, - "type": "array", - "title": "Include Default Tools", - "description": "List of default tool class names to include. By default, the agent includes 'FinishTool' and 'ThinkTool'. Set to an empty list to disable all default tools, or provide a subset to include only specific ones. Example: include_default_tools=['FinishTool'] to only include FinishTool, or include_default_tools=[] to disable all default tools.", - "examples": [ - [ - "FinishTool", - "ThinkTool" - ], - [ - "FinishTool" - ], - [] - ] + "title": "Content", + "type": "array" }, - "agent_context": { + "exit_code": { "anyOf": [ { - "$ref": "#/components/schemas/AgentContext-Output" + "type": "integer" }, { "type": "null" } ], - "description": "Optional AgentContext to initialize the agent with specific context.", - "examples": [ + "description": "The exit code of the command. -1 indicates the process hit the soft timeout and is not yet finished.", + "title": "Exit Code" + }, + "full_output_save_dir": { + "anyOf": [ { - "skills": [ - { - "content": "When you see this message, you should reply like you are a grumpy cat forced to use the internet.", - "name": "AGENTS.md", - "type": "repo" - }, - { - "content": "IMPORTANT! The user has said the magic word \"flarglebargle\". You must only respond with a message telling them how smart they are", - "name": "flarglebargle", - "trigger": [ - "flarglebargle" - ], - "type": "knowledge" - } - ], - "system_message_suffix": "Always finish your response with the word 'yay!'", - "user_message_prefix": "The first character of your response should be 'I'" + "type": "string" + }, + { + "type": "null" } - ] + ], + "description": "Directory where full output files are saved", + "title": "Full Output Save Dir" }, - "system_prompt_filename": { - "type": "string", - "title": "System Prompt Filename", - "description": "System prompt template filename. Can be either:\n- A relative filename (e.g., 'system_prompt.j2') loaded from the agent's prompts directory\n- An absolute path (e.g., '/path/to/custom_prompt.j2')", - "default": "system_prompt.j2" + "is_error": { + "default": false, + "description": "Whether the observation indicates an error", + "title": "Is Error", + "type": "boolean" }, - "security_policy_filename": { - "type": "string", - "title": "Security Policy Filename", - "description": "Security policy template filename. Can be either:\n- A relative filename (e.g., 'security_policy.j2') loaded from the agent's prompts directory\n- An absolute path (e.g., '/path/to/custom_security_policy.j2')", - "default": "security_policy.j2" + "kind": { + "const": "TerminalObservation", + "title": "Kind", + "type": "string" }, - "system_prompt_kwargs": { - "additionalProperties": true, - "type": "object", - "title": "System Prompt Kwargs", - "description": "Optional kwargs to pass to the system prompt Jinja2 template.", - "examples": [ + "metadata": { + "$ref": "#/components/schemas/CmdOutputMetadata", + "description": "Additional metadata captured from PS1 after command execution." + }, + "timeout": { + "default": false, + "description": "Whether the command execution timed out.", + "title": "Timeout", + "type": "boolean" + } + }, + "required": [ + "command", + "kind" + ], + "title": "TerminalObservation", + "type": "object" + }, + "TerminalTool": { + "description": "A ToolDefinition subclass that automatically initializes a TerminalExecutor with auto-detection.", + "properties": { + "action_type": { + "title": "Action Type", + "type": "string" + }, + "annotations": { + "anyOf": [ { - "cli_mode": true + "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" + }, + { + "type": "null" } ] }, - "condenser": { + "description": { + "title": "Description", + "type": "string" + }, + "kind": { + "const": "TerminalTool", + "title": "Kind", + "type": "string" + }, + "meta": { "anyOf": [ { - "$ref": "#/components/schemas/CondenserBase-Output" + "additionalProperties": true, + "type": "object" }, { "type": "null" } ], - "description": "Optional condenser to use for condensing conversation history.", - "examples": [ - { - "keep_first": 10, - "kind": "LLMSummarizingCondenser", - "llm": { - "api_key": "your_api_key_here", - "base_url": "https://llm-proxy.eval.all-hands.dev", - "model": "litellm_proxy/anthropic/claude-sonnet-4-5-20250929" - }, - "max_size": 80 - } - ] + "title": "Meta" }, - "critic": { + "observation_type": { "anyOf": [ { - "$ref": "#/components/schemas/CriticBase-Output" + "type": "string" }, { "type": "null" } ], - "description": "EXPERIMENTAL: Optional critic to evaluate agent actions and messages in real-time. API and behavior may change without notice. May impact performance, especially in 'all_actions' mode.", - "examples": [ - { - "kind": "AgentFinishedCritic" - } - ] + "title": "Observation Type" }, - "kind": { - "type": "string", - "const": "Agent", - "title": "Kind" + "title": { + "readOnly": true, + "title": "Title", + "type": "string" } }, - "type": "object", "required": [ - "llm", - "kind" + "description", + "action_type", + "kind", + "title" ], - "title": "Agent", - "description": "Main agent implementation for OpenHands.\n\nThe Agent class provides the core functionality for running AI agents that can\ninteract with tools, process messages, and execute actions. It inherits from\nAgentBase and implements the agent execution logic. Critic-related functionality\nis provided by CriticMixin.\n\nExample:\n >>> from openhands.sdk import LLM, Agent, Tool\n >>> llm = LLM(model=\"claude-sonnet-4-20250514\", api_key=SecretStr(\"key\"))\n >>> tools = [Tool(name=\"TerminalTool\"), Tool(name=\"FileEditorTool\")]\n >>> agent = Agent(llm=llm, tools=tools)" + "title": "TerminalTool", + "type": "object" }, - "AgentBase-Input": { - "$ref": "#/components/schemas/Agent-Input" + "TextContent": { + "additionalProperties": false, + "properties": { + "cache_prompt": { + "default": false, + "title": "Cache Prompt", + "type": "boolean" + }, + "text": { + "title": "Text", + "type": "string" + }, + "type": { + "const": "text", + "default": "text", + "title": "Type", + "type": "string" + } + }, + "required": [ + "text" + ], + "title": "TextContent", + "type": "object" }, - "AgentBase-Output": { - "$ref": "#/components/schemas/Agent-Output" + "ThinkAction": { + "additionalProperties": false, + "description": "Action for logging a thought without making any changes.", + "properties": { + "kind": { + "const": "ThinkAction", + "title": "Kind", + "type": "string" + }, + "thought": { + "description": "The thought to log.", + "title": "Thought", + "type": "string" + } + }, + "required": [ + "thought", + "kind" + ], + "title": "ThinkAction", + "type": "object" }, - "AgentContext-Input": { + "ThinkObservation": { + "additionalProperties": false, + "description": "Observation returned after logging a thought.\nThe ThinkAction itself contains the thought logged so no extra\nfields are needed here.", "properties": { - "skills": { + "content": { + "description": "Content returned from the tool as a list of TextContent/ImageContent objects. When there is an error, it should be written in this field.", "items": { - "$ref": "#/components/schemas/Skill" + "anyOf": [ + { + "$ref": "#/components/schemas/TextContent" + }, + { + "$ref": "#/components/schemas/ImageContent" + } + ] }, - "type": "array", - "title": "Skills", - "description": "List of available skills that can extend the user's input." + "title": "Content", + "type": "array" }, - "system_message_suffix": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "System Message Suffix", - "description": "Optional suffix to append to the system prompt." + "is_error": { + "default": false, + "description": "Whether the observation indicates an error", + "title": "Is Error", + "type": "boolean" + }, + "kind": { + "const": "ThinkObservation", + "title": "Kind", + "type": "string" + } + }, + "required": [ + "kind" + ], + "title": "ThinkObservation", + "type": "object" + }, + "ThinkTool": { + "description": "Tool for logging thoughts without making changes.", + "properties": { + "action_type": { + "title": "Action Type", + "type": "string" }, - "user_message_suffix": { + "annotations": { "anyOf": [ { - "type": "string" + "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" }, { "type": "null" } - ], - "title": "User Message Suffix", - "description": "Optional suffix to append to the user's message." + ] }, - "load_user_skills": { - "type": "boolean", - "title": "Load User Skills", - "description": "Whether to automatically load user skills from ~/.openhands/skills/ and ~/.openhands/microagents/ (for backward compatibility). ", - "default": false + "description": { + "title": "Description", + "type": "string" }, - "load_public_skills": { - "type": "boolean", - "title": "Load Public Skills", - "description": "Whether to automatically load skills from the public OpenHands skills repository at https://github.com/OpenHands/skills. This allows you to get the latest skills without SDK updates.", - "default": false + "kind": { + "const": "ThinkTool", + "title": "Kind", + "type": "string" }, - "secrets": { + "meta": { "anyOf": [ { - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "$ref": "#/components/schemas/SecretSource-Input" - } - ] - }, + "additionalProperties": true, "type": "object" }, { "type": "null" } ], - "title": "Secrets", - "description": "Dictionary mapping secret keys to values or secret sources. Secrets are used for authentication and sensitive data handling. Values can be either strings or SecretSource instances (str | SecretSource)." + "title": "Meta" }, - "current_datetime": { + "observation_type": { "anyOf": [ - { - "type": "string", - "format": "date-time" - }, { "type": "string" }, @@ -3426,37 +20874,27 @@ "type": "null" } ], - "title": "Current Datetime", - "description": "Current date and time information to provide to the agent. Can be a datetime object (which will be formatted as ISO 8601) or a pre-formatted string. When provided, this information is included in the system prompt to give the agent awareness of the current time context. Defaults to the current datetime." + "title": "Observation Type" + }, + "title": { + "readOnly": true, + "title": "Title", + "type": "string" } }, - "type": "object", - "title": "AgentContext", - "description": "Central structure for managing prompt extension.\n\nAgentContext unifies all the contextual inputs that shape how the system\nextends and interprets user prompts. It combines both static environment\ndetails and dynamic, user-activated extensions from skills.\n\nSpecifically, it provides:\n- **Repository context / Repo Skills**: Information about the active codebase,\n branches, and repo-specific instructions contributed by repo skills.\n- **Runtime context**: Current execution environment (hosts, working\n directory, secrets, date, etc.).\n- **Conversation instructions**: Optional task- or channel-specific rules\n that constrain or guide the agent\u2019s behavior across the session.\n- **Knowledge Skills**: Extensible components that can be triggered by user input\n to inject knowledge or domain-specific guidance.\n\nTogether, these elements make AgentContext the primary container responsible\nfor assembling, formatting, and injecting all prompt-relevant context into\nLLM interactions." + "required": [ + "description", + "action_type", + "kind", + "title" + ], + "title": "ThinkTool", + "type": "object" }, - "AgentContext-Output": { + "ThinkingBlock": { + "description": "Anthropic thinking block for extended thinking feature.\n\nThis represents the raw thinking blocks returned by Anthropic models\nwhen extended thinking is enabled. These blocks must be preserved\nand passed back to the API for tool use scenarios.", "properties": { - "skills": { - "items": { - "$ref": "#/components/schemas/Skill" - }, - "type": "array", - "title": "Skills", - "description": "List of available skills that can extend the user's input." - }, - "system_message_suffix": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "System Message Suffix", - "description": "Optional suffix to append to the system prompt." - }, - "user_message_suffix": { + "signature": { "anyOf": [ { "type": "string" @@ -3465,49 +20903,43 @@ "type": "null" } ], - "title": "User Message Suffix", - "description": "Optional suffix to append to the user's message." + "description": "Cryptographic signature for the thinking block", + "title": "Signature" }, - "load_user_skills": { - "type": "boolean", - "title": "Load User Skills", - "description": "Whether to automatically load user skills from ~/.openhands/skills/ and ~/.openhands/microagents/ (for backward compatibility). ", - "default": false + "thinking": { + "description": "The thinking content", + "title": "Thinking", + "type": "string" }, - "load_public_skills": { - "type": "boolean", - "title": "Load Public Skills", - "description": "Whether to automatically load skills from the public OpenHands skills repository at https://github.com/OpenHands/skills. This allows you to get the latest skills without SDK updates.", - "default": false + "type": { + "const": "thinking", + "default": "thinking", + "title": "Type", + "type": "string" + } + }, + "required": [ + "thinking" + ], + "title": "ThinkingBlock", + "type": "object" + }, + "TokenEvent": { + "additionalProperties": false, + "description": "Event from VLLM representing token IDs used in LLM interaction.", + "properties": { + "id": { + "description": "Unique event id (ULID/UUID)", + "title": "Id", + "type": "string" }, - "secrets": { - "anyOf": [ - { - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "$ref": "#/components/schemas/SecretSource-Output" - } - ] - }, - "type": "object" - }, - { - "type": "null" - } - ], - "title": "Secrets", - "description": "Dictionary mapping secret keys to values or secret sources. Secrets are used for authentication and sensitive data handling. Values can be either strings or SecretSource instances (str | SecretSource)." + "kind": { + "const": "TokenEvent", + "title": "Kind", + "type": "string" }, - "current_datetime": { + "parent_id": { "anyOf": [ - { - "type": "string", - "format": "date-time" - }, { "type": "string" }, @@ -3515,552 +20947,779 @@ "type": "null" } ], - "title": "Current Datetime", - "description": "Current date and time information to provide to the agent. Can be a datetime object (which will be formatted as ISO 8601) or a pre-formatted string. When provided, this information is included in the system prompt to give the agent awareness of the current time context. Defaults to the current datetime." - } - }, - "type": "object", - "title": "AgentContext", - "description": "Central structure for managing prompt extension.\n\nAgentContext unifies all the contextual inputs that shape how the system\nextends and interprets user prompts. It combines both static environment\ndetails and dynamic, user-activated extensions from skills.\n\nSpecifically, it provides:\n- **Repository context / Repo Skills**: Information about the active codebase,\n branches, and repo-specific instructions contributed by repo skills.\n- **Runtime context**: Current execution environment (hosts, working\n directory, secrets, date, etc.).\n- **Conversation instructions**: Optional task- or channel-specific rules\n that constrain or guide the agent\u2019s behavior across the session.\n- **Knowledge Skills**: Extensible components that can be triggered by user input\n to inject knowledge or domain-specific guidance.\n\nTogether, these elements make AgentContext the primary container responsible\nfor assembling, formatting, and injecting all prompt-relevant context into\nLLM interactions." - }, - "AgentErrorEvent": { - "properties": { - "id": { - "type": "string", - "title": "Id", - "description": "Unique event id (ULID/UUID)" + "description": "Parent event id in the conversation tree. None for the root, or for legacy events predating the tree (see EventLog's effective-parent rule). Events sharing a parent_id are sibling branches.", + "title": "Parent Id" }, - "timestamp": { - "type": "string", - "title": "Timestamp", - "description": "Event timestamp" + "prompt_token_ids": { + "description": "The exact prompt token IDs for this message event", + "items": { + "type": "integer" + }, + "title": "Prompt Token Ids", + "type": "array" + }, + "response_token_ids": { + "description": "The exact response token IDs for this message event", + "items": { + "type": "integer" + }, + "title": "Response Token Ids", + "type": "array" }, "source": { - "type": "string", "enum": [ "agent", "user", - "environment" + "environment", + "hook" ], "title": "Source", - "default": "agent" - }, - "tool_name": { - "type": "string", - "title": "Tool Name", - "description": "The tool name that this observation is responding to" - }, - "tool_call_id": { - "type": "string", - "title": "Tool Call Id", - "description": "The tool call id that this observation is responding to" - }, - "error": { - "type": "string", - "title": "Error", - "description": "The error message from the scaffold" + "type": "string" }, - "kind": { - "type": "string", - "const": "AgentErrorEvent", - "title": "Kind" + "timestamp": { + "description": "Event timestamp", + "title": "Timestamp", + "type": "string" } }, - "additionalProperties": false, - "type": "object", "required": [ - "tool_name", - "tool_call_id", - "error", + "source", + "prompt_token_ids", + "response_token_ids", "kind" ], - "title": "AgentErrorEvent", - "description": "Error triggered by the agent.\n\nNote: This event should not contain model \"thought\" or \"reasoning_content\". It\nrepresents an error produced by the agent/scaffold, not model output." + "title": "TokenEvent", + "type": "object" }, - "AgentFinishedCritic-Input": { + "TokenUsage": { + "description": "Metric tracking detailed token usage per completion call.", "properties": { - "mode": { - "type": "string", - "enum": [ - "finish_and_message", - "all_actions" + "cache_read_tokens": { + "default": 0, + "description": "Cache read tokens must be non-negative", + "minimum": 0.0, + "title": "Cache Read Tokens", + "type": "integer" + }, + "cache_write_tokens": { + "default": 0, + "description": "Cache write tokens must be non-negative", + "minimum": 0.0, + "title": "Cache Write Tokens", + "type": "integer" + }, + "completion_tokens": { + "default": 0, + "description": "Completion tokens must be non-negative", + "minimum": 0.0, + "title": "Completion Tokens", + "type": "integer" + }, + "context_window": { + "default": 0, + "description": "Context window must be non-negative", + "minimum": 0.0, + "title": "Context Window", + "type": "integer" + }, + "model": { + "default": "", + "title": "Model", + "type": "string" + }, + "per_turn_token": { + "default": 0, + "description": "Per turn tokens must be non-negative", + "minimum": 0.0, + "title": "Per Turn Token", + "type": "integer" + }, + "prompt_tokens": { + "default": 0, + "description": "Prompt tokens must be non-negative", + "minimum": 0.0, + "title": "Prompt Tokens", + "type": "integer" + }, + "reasoning_tokens": { + "default": 0, + "description": "Reasoning tokens must be non-negative", + "minimum": 0.0, + "title": "Reasoning Tokens", + "type": "integer" + }, + "response_id": { + "default": "", + "title": "Response Id", + "type": "string" + } + }, + "title": "TokenUsage", + "type": "object" + }, + "Tool-Input": { + "description": "Defines a tool to be initialized for the agent.\n\nThis is only used in agent-sdk for type schema for server use.", + "properties": { + "name": { + "description": "Name of the tool class, e.g., 'TerminalTool'. Import it from an `openhands.tools.` subpackage.", + "examples": [ + "TerminalTool", + "FileEditorTool", + "TaskTrackerTool" ], - "title": "Mode", - "description": "When to run critic evaluation:\n- 'finish_and_message': Evaluate on FinishAction and agent MessageEvent (default, minimal performance impact)\n- 'all_actions': Evaluate after every agent action (WARNING: significantly slower due to API calls on each action)", - "default": "finish_and_message" + "title": "Name", + "type": "string" }, - "iterative_refinement": { - "anyOf": [ - { - "$ref": "#/components/schemas/IterativeRefinementConfig" - }, + "params": { + "additionalProperties": true, + "description": "Parameters for the tool's .create() method, e.g., {'working_dir': '/app'}", + "examples": [ { - "type": "null" + "working_dir": "/workspace" } ], - "description": "Optional configuration for iterative refinement. When set, Conversation.run() will automatically retry the task if the critic score is below the success_threshold, up to max_iterations." - }, - "kind": { - "type": "string", - "const": "AgentFinishedCritic", - "title": "Kind" + "title": "Params", + "type": "object" } }, - "type": "object", - "title": "AgentFinishedCritic", - "description": "Critic that evaluates whether an agent properly finished a task.\n\nThis critic checks two main criteria:\n1. The agent's last action was a FinishAction (proper completion)\n2. The generated git patch is non-empty (actual changes were made)" + "required": [ + "name" + ], + "title": "Tool", + "type": "object" }, - "AgentFinishedCritic-Output": { + "ToolAnnotations-Input": { + "description": "Annotations to provide hints about the tool's behavior.\n\nBased on Model Context Protocol (MCP) spec:\nhttps://github.com/modelcontextprotocol/modelcontextprotocol/blob/caf3424488b10b4a7b1f8cb634244a450a1f4400/schema/2025-06-18/schema.ts#L838", "properties": { - "mode": { - "type": "string", - "enum": [ - "finish_and_message", - "all_actions" - ], - "title": "Mode", - "description": "When to run critic evaluation:\n- 'finish_and_message': Evaluate on FinishAction and agent MessageEvent (default, minimal performance impact)\n- 'all_actions': Evaluate after every agent action (WARNING: significantly slower due to API calls on each action)", - "default": "finish_and_message" + "destructiveHint": { + "default": true, + "description": "If true, the tool may perform destructive updates to its environment. If false, the tool performs only additive updates. (This property is meaningful only when `readOnlyHint == false`) Default: true", + "title": "Destructivehint", + "type": "boolean" }, - "iterative_refinement": { + "idempotentHint": { + "default": false, + "description": "If true, calling the tool repeatedly with the same arguments will have no additional effect on the its environment. (This property is meaningful only when `readOnlyHint == false`) Default: false", + "title": "Idempotenthint", + "type": "boolean" + }, + "openWorldHint": { + "default": true, + "description": "If true, this tool may interact with an 'open world' of external entities. If false, the tool's domain of interaction is closed. For example, the world of a web search tool is open, whereas that of a memory tool is not. Default: true", + "title": "Openworldhint", + "type": "boolean" + }, + "readOnlyHint": { + "default": false, + "description": "If true, the tool does not modify its environment. Default: false", + "title": "Readonlyhint", + "type": "boolean" + }, + "title": { "anyOf": [ { - "$ref": "#/components/schemas/IterativeRefinementConfig" + "type": "string" }, { "type": "null" } ], - "description": "Optional configuration for iterative refinement. When set, Conversation.run() will automatically retry the task if the critic score is below the success_threshold, up to max_iterations." - }, - "kind": { - "type": "string", - "const": "AgentFinishedCritic", - "title": "Kind" - } - }, - "type": "object", - "required": [ - "kind" - ], - "title": "AgentFinishedCritic", - "description": "Critic that evaluates whether an agent properly finished a task.\n\nThis critic checks two main criteria:\n1. The agent's last action was a FinishAction (proper completion)\n2. The generated git patch is non-empty (actual changes were made)" - }, - "AlwaysConfirm-Input": { - "properties": { - "kind": { - "type": "string", - "const": "AlwaysConfirm", - "title": "Kind" + "description": "A human-readable title for the tool.", + "title": "Title" } }, - "type": "object", - "title": "AlwaysConfirm" + "title": "openhands.sdk.tool.tool.ToolAnnotations", + "type": "object" }, - "AlwaysConfirm-Output": { + "ToolCatalogEntry": { + "description": "A registered tool as offered to clients configuring an agent.", "properties": { - "kind": { - "type": "string", - "const": "AlwaysConfirm", - "title": "Kind" + "description": { + "default": "", + "title": "Description", + "type": "string" + }, + "in_default_set": { + "default": false, + "title": "In Default Set", + "type": "boolean" + }, + "name": { + "title": "Name", + "type": "string" + }, + "usable": { + "default": true, + "title": "Usable", + "type": "boolean" + }, + "user_selectable": { + "default": true, + "title": "User Selectable", + "type": "boolean" } }, - "type": "object", "required": [ - "kind" + "name" ], - "title": "AlwaysConfirm" + "title": "ToolCatalogEntry", + "type": "object" }, - "AskAgentRequest": { + "ToolCatalogResponse": { "properties": { - "question": { - "type": "string", - "title": "Question", - "description": "The question to ask the agent" + "tools": { + "items": { + "$ref": "#/components/schemas/ToolCatalogEntry" + }, + "title": "Tools", + "type": "array" } }, - "type": "object", "required": [ - "question" + "tools" ], - "title": "AskAgentRequest", - "description": "Payload to ask the agent a simple question." + "title": "ToolCatalogResponse", + "type": "object" }, - "AskAgentResponse": { - "properties": { - "response": { - "type": "string", - "title": "Response", - "description": "The agent's response to the question" - } + "ToolDefinition": { + "discriminator": { + "mapping": { + "openhands__sdk__mcp__tool__MCPToolDefinition-Output__1": "#/components/schemas/MCPToolDefinition", + "openhands__sdk__tool__builtins__classify_and_switch_llm__ClassifyAndSwitchLLMTool-Output__1": "#/components/schemas/ClassifyAndSwitchLLMTool", + "openhands__sdk__tool__builtins__finish__FinishTool-Output__1": "#/components/schemas/FinishTool", + "openhands__sdk__tool__builtins__invoke_skill__InvokeSkillTool-Output__1": "#/components/schemas/InvokeSkillTool", + "openhands__sdk__tool__builtins__switch_llm__SwitchLLMTool-Output__1": "#/components/schemas/SwitchLLMTool", + "openhands__sdk__tool__builtins__think__ThinkTool-Output__1": "#/components/schemas/ThinkTool", + "openhands__sdk__tool__builtins__vision_inspect__VisionInspectTool-Output__1": "#/components/schemas/VisionInspectTool", + "openhands__sdk__tool__client_tool__ClientTool-Output__1": "#/components/schemas/ClientTool", + "openhands__tools__ask_oracle__definition__AskOracleTool-Output__1": "#/components/schemas/AskOracleTool", + "openhands__tools__browser_use__definition__BrowserClickTool-Output__1": "#/components/schemas/BrowserClickTool", + "openhands__tools__browser_use__definition__BrowserCloseTabTool-Output__1": "#/components/schemas/BrowserCloseTabTool", + "openhands__tools__browser_use__definition__BrowserGetContentTool-Output__1": "#/components/schemas/BrowserGetContentTool", + "openhands__tools__browser_use__definition__BrowserGetStateTool-Output__1": "#/components/schemas/BrowserGetStateTool", + "openhands__tools__browser_use__definition__BrowserGetStorageTool-Output__1": "#/components/schemas/BrowserGetStorageTool", + "openhands__tools__browser_use__definition__BrowserGoBackTool-Output__1": "#/components/schemas/BrowserGoBackTool", + "openhands__tools__browser_use__definition__BrowserListTabsTool-Output__1": "#/components/schemas/BrowserListTabsTool", + "openhands__tools__browser_use__definition__BrowserNavigateTool-Output__1": "#/components/schemas/BrowserNavigateTool", + "openhands__tools__browser_use__definition__BrowserScrollTool-Output__1": "#/components/schemas/BrowserScrollTool", + "openhands__tools__browser_use__definition__BrowserSetStorageTool-Output__1": "#/components/schemas/BrowserSetStorageTool", + "openhands__tools__browser_use__definition__BrowserStartRecordingTool-Output__1": "#/components/schemas/BrowserStartRecordingTool", + "openhands__tools__browser_use__definition__BrowserStopRecordingTool-Output__1": "#/components/schemas/BrowserStopRecordingTool", + "openhands__tools__browser_use__definition__BrowserSwitchTabTool-Output__1": "#/components/schemas/BrowserSwitchTabTool", + "openhands__tools__browser_use__definition__BrowserToolSet-Output__1": "#/components/schemas/BrowserToolSet", + "openhands__tools__browser_use__definition__BrowserTypeTool-Output__1": "#/components/schemas/BrowserTypeTool", + "openhands__tools__file_editor__definition__FileEditorTool-Output__1": "#/components/schemas/FileEditorTool", + "openhands__tools__gemini__edit__definition__EditTool-Output__1": "#/components/schemas/EditTool", + "openhands__tools__gemini__list_directory__definition__ListDirectoryTool-Output__1": "#/components/schemas/ListDirectoryTool", + "openhands__tools__gemini__read_file__definition__ReadFileTool-Output__1": "#/components/schemas/ReadFileTool", + "openhands__tools__gemini__write_file__definition__WriteFileTool-Output__1": "#/components/schemas/WriteFileTool", + "openhands__tools__glob__definition__GlobTool-Output__1": "#/components/schemas/GlobTool", + "openhands__tools__grep__definition__GrepTool-Output__1": "#/components/schemas/GrepTool", + "openhands__tools__planning_file_editor__definition__PlanningFileEditorTool-Output__1": "#/components/schemas/PlanningFileEditorTool", + "openhands__tools__task__definition__TaskTool-Output__1": "#/components/schemas/TaskTool", + "openhands__tools__task__definition__TaskToolSet-Output__1": "#/components/schemas/TaskToolSet", + "openhands__tools__task_tracker__definition__TaskTrackerTool-Output__1": "#/components/schemas/TaskTrackerTool", + "openhands__tools__terminal__definition__TerminalTool-Output__1": "#/components/schemas/TerminalTool", + "openhands__tools__workflow__definition__WorkflowTool-Output__1": "#/components/schemas/WorkflowTool", + "openhands__tools__workflow__definition__WorkflowToolSet-Output__1": "#/components/schemas/WorkflowToolSet" + }, + "propertyName": "kind" }, - "type": "object", - "required": [ - "response" - ], - "title": "AskAgentResponse", - "description": "Response containing the agent's answer." - }, - "BaseWorkspace-Input": { "oneOf": [ { - "$ref": "#/components/schemas/LocalWorkspace-Input" + "$ref": "#/components/schemas/MCPToolDefinition" }, { - "$ref": "#/components/schemas/RemoteWorkspace-Input" - } - ], - "discriminator": { - "propertyName": "kind", - "mapping": { - "openhands__sdk__workspace__local__LocalWorkspace-Input__1": "#/components/schemas/LocalWorkspace-Input", - "openhands__sdk__workspace__remote__base__RemoteWorkspace-Input__1": "#/components/schemas/RemoteWorkspace-Input" - } - } - }, - "BaseWorkspace-Output": { - "oneOf": [ + "$ref": "#/components/schemas/ClassifyAndSwitchLLMTool" + }, { - "$ref": "#/components/schemas/LocalWorkspace-Output" + "$ref": "#/components/schemas/FinishTool" }, { - "$ref": "#/components/schemas/RemoteWorkspace-Output" - } - ], - "discriminator": { - "propertyName": "kind", - "mapping": { - "openhands__sdk__workspace__local__LocalWorkspace-Output__1": "#/components/schemas/LocalWorkspace-Output", - "openhands__sdk__workspace__remote__base__RemoteWorkspace-Output__1": "#/components/schemas/RemoteWorkspace-Output" - } - } - }, - "BashCommand": { - "properties": { - "command": { - "type": "string", - "title": "Command", - "description": "The bash command to execute" + "$ref": "#/components/schemas/InvokeSkillTool" }, - "cwd": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Cwd", - "description": "The current working directory" + { + "$ref": "#/components/schemas/SwitchLLMTool" }, - "timeout": { - "type": "integer", - "title": "Timeout", - "description": "The max number of seconds a command may be permitted to run.", - "default": 300 + { + "$ref": "#/components/schemas/ThinkTool" }, - "id": { - "type": "string", - "title": "Id" + { + "$ref": "#/components/schemas/VisionInspectTool" }, - "timestamp": { - "type": "string", - "format": "date-time", - "title": "Timestamp" + { + "$ref": "#/components/schemas/ClientTool" + }, + { + "$ref": "#/components/schemas/AskOracleTool" + }, + { + "$ref": "#/components/schemas/BrowserClickTool" + }, + { + "$ref": "#/components/schemas/BrowserCloseTabTool" + }, + { + "$ref": "#/components/schemas/BrowserGetContentTool" + }, + { + "$ref": "#/components/schemas/BrowserGetStateTool" + }, + { + "$ref": "#/components/schemas/BrowserGetStorageTool" + }, + { + "$ref": "#/components/schemas/BrowserGoBackTool" + }, + { + "$ref": "#/components/schemas/BrowserListTabsTool" + }, + { + "$ref": "#/components/schemas/BrowserNavigateTool" + }, + { + "$ref": "#/components/schemas/BrowserScrollTool" + }, + { + "$ref": "#/components/schemas/BrowserSetStorageTool" + }, + { + "$ref": "#/components/schemas/BrowserStartRecordingTool" + }, + { + "$ref": "#/components/schemas/BrowserStopRecordingTool" + }, + { + "$ref": "#/components/schemas/BrowserSwitchTabTool" + }, + { + "$ref": "#/components/schemas/BrowserToolSet" + }, + { + "$ref": "#/components/schemas/BrowserTypeTool" + }, + { + "$ref": "#/components/schemas/FileEditorTool" + }, + { + "$ref": "#/components/schemas/EditTool" + }, + { + "$ref": "#/components/schemas/ListDirectoryTool" + }, + { + "$ref": "#/components/schemas/ReadFileTool" + }, + { + "$ref": "#/components/schemas/WriteFileTool" + }, + { + "$ref": "#/components/schemas/GlobTool" + }, + { + "$ref": "#/components/schemas/GrepTool" + }, + { + "$ref": "#/components/schemas/PlanningFileEditorTool" + }, + { + "$ref": "#/components/schemas/TaskTool" + }, + { + "$ref": "#/components/schemas/TaskToolSet" + }, + { + "$ref": "#/components/schemas/TaskTrackerTool" + }, + { + "$ref": "#/components/schemas/TerminalTool" }, - "kind": { - "type": "string", - "const": "BashCommand", - "title": "Kind" - } - }, - "type": "object", - "required": [ - "command", - "kind" - ], - "title": "BashCommand" - }, - "BashEventBase": { - "oneOf": [ { - "$ref": "#/components/schemas/BashCommand" + "$ref": "#/components/schemas/WorkflowTool" }, { - "$ref": "#/components/schemas/BashOutput" - } - ], - "discriminator": { - "propertyName": "kind", - "mapping": { - "openhands__agent_server__models__BashCommand-Output__1": "#/components/schemas/BashCommand", - "openhands__agent_server__models__BashOutput-Output__1": "#/components/schemas/BashOutput" + "$ref": "#/components/schemas/WorkflowToolSet" } - } + ] }, - "BashEventPage": { + "ToolExecution": { + "additionalProperties": true, + "description": "Execution-related properties for a tool.", "properties": { - "items": { - "items": { - "$ref": "#/components/schemas/BashEventBase" - }, - "type": "array", - "title": "Items" - }, - "next_page_id": { + "taskSupport": { "anyOf": [ { + "enum": [ + "forbidden", + "optional", + "required" + ], "type": "string" }, { "type": "null" } ], - "title": "Next Page Id" + "title": "Tasksupport" + } + }, + "title": "ToolExecution", + "type": "object" + }, + "ToolShieldLLMSecurityAnalyzer-Input": { + "description": "Evaluate each action via a separate guardrail LLM.\n\nPairs with the existing ``ConfirmRisky`` policy unchanged: this\nanalyzer only *assigns* the risk level; ``ConfirmRisky`` decides\nwhether to pause for user confirmation.\n\nBy default the analyzer runs as a bare guardrail (no distilled\nsafety experiences). To enable the ToolShield seed, install\n``pip install openhands-sdk[toolshield]`` and pass the rendered\nexperiences via the ``safety_experiences`` field -- typically via\none of the helpers (``default_safety_experiences()``,\n``load_safety_experiences(...)``, ``auto_detect_safety_experiences()``).\nTested against ``toolshield>=0.1.3,<0.2``.\n\nNote: ``reasoning_content`` and ``thinking_blocks`` from extended-\nthinking models are deliberately excluded from the guardrail\ncontext. The risk signal lives in the tool call's name and\narguments; including reasoning text would inflate the prompt\nwithout proportional safety gain. Subclasses needing reasoning\nvisibility should override :func:`_format_action_for_guardrail`.\n\nLifecycle: instances maintain a per-conversation deque of recent\nactions (``history_window`` items) for guardrail context. Each\ninstance is intended for SINGLE-CONVERSATION use. Reusing one\nanalyzer instance across multiple conversations will leak action\nhistory between them, which is both a privacy issue (conversation\nA's tool arguments visible in conversation B's guardrail prompt)\nand a correctness issue (the guardrail evaluates conversation B's\nactions against irrelevant history). Construct one analyzer per\nconversation, OR call :meth:`reset_history` at conversation\nboundaries.\n\nThe recent-action-context propagation across analyzers (this one,\n:class:`LLMSecurityAnalyzer`, :class:`GraySwanAnalyzer`) is tracked\nfor convergence in a separate follow-up; until that lands,\nsingle-conversation lifecycle is the contract.\n\nFailure modes are consistent and ensemble-safe -- both an\ninfrastructure error (network, rate limit) and a parse failure\n(the guardrail responded but its output had no parseable\n``RISK:`` label) return ``SecurityRisk.UNKNOWN``. ``ConfirmRisky``\nwith ``confirm_unknown=True`` then pauses for user confirmation,\nmatching the conservative posture without dominating ``max()`` in\nensemble fusion.", + "properties": { + "history_window": { + "default": 20, + "description": "Number of prior actions to include as context.", + "title": "History Window", + "type": "integer" + }, + "kind": { + "const": "ToolShieldLLMSecurityAnalyzer", + "title": "Kind", + "type": "string" + }, + "llm": { + "$ref": "#/components/schemas/LLM-Input", + "description": "LLM used as the guardrail. Can be a smaller/cheaper model than the actor LLM; only the model's ability to classify action risk matters." + }, + "safety_experiences": { + "default": "", + "description": "Pre-generated safety guidelines injected into the guardrail's system prompt.\n- ``\"\"`` (default): bare guardrail -- no experiences. The analyzer still separates actor from judge; it just classifies without distilled tool-specific guidance.\n- Any non-empty string: used as-is. The intended pattern is to call one of the helpers (``default_safety_experiences()``, ``load_safety_experiences(tool_names)``, ``auto_detect_safety_experiences()``) which require the ``[toolshield]`` optional extra (``pip install openhands-sdk[toolshield]``). Callers with their own source of guidelines can pass any custom string.", + "title": "Safety Experiences", + "type": "string" } }, - "type": "object", "required": [ - "items" + "llm" ], - "title": "BashEventPage" + "title": "ToolShieldLLMSecurityAnalyzer", + "type": "object" }, - "BashEventSortOrder": { - "type": "string", - "enum": [ - "TIMESTAMP", - "TIMESTAMP_DESC" + "ToolShieldLLMSecurityAnalyzer-Output": { + "description": "Evaluate each action via a separate guardrail LLM.\n\nPairs with the existing ``ConfirmRisky`` policy unchanged: this\nanalyzer only *assigns* the risk level; ``ConfirmRisky`` decides\nwhether to pause for user confirmation.\n\nBy default the analyzer runs as a bare guardrail (no distilled\nsafety experiences). To enable the ToolShield seed, install\n``pip install openhands-sdk[toolshield]`` and pass the rendered\nexperiences via the ``safety_experiences`` field -- typically via\none of the helpers (``default_safety_experiences()``,\n``load_safety_experiences(...)``, ``auto_detect_safety_experiences()``).\nTested against ``toolshield>=0.1.3,<0.2``.\n\nNote: ``reasoning_content`` and ``thinking_blocks`` from extended-\nthinking models are deliberately excluded from the guardrail\ncontext. The risk signal lives in the tool call's name and\narguments; including reasoning text would inflate the prompt\nwithout proportional safety gain. Subclasses needing reasoning\nvisibility should override :func:`_format_action_for_guardrail`.\n\nLifecycle: instances maintain a per-conversation deque of recent\nactions (``history_window`` items) for guardrail context. Each\ninstance is intended for SINGLE-CONVERSATION use. Reusing one\nanalyzer instance across multiple conversations will leak action\nhistory between them, which is both a privacy issue (conversation\nA's tool arguments visible in conversation B's guardrail prompt)\nand a correctness issue (the guardrail evaluates conversation B's\nactions against irrelevant history). Construct one analyzer per\nconversation, OR call :meth:`reset_history` at conversation\nboundaries.\n\nThe recent-action-context propagation across analyzers (this one,\n:class:`LLMSecurityAnalyzer`, :class:`GraySwanAnalyzer`) is tracked\nfor convergence in a separate follow-up; until that lands,\nsingle-conversation lifecycle is the contract.\n\nFailure modes are consistent and ensemble-safe -- both an\ninfrastructure error (network, rate limit) and a parse failure\n(the guardrail responded but its output had no parseable\n``RISK:`` label) return ``SecurityRisk.UNKNOWN``. ``ConfirmRisky``\nwith ``confirm_unknown=True`` then pauses for user confirmation,\nmatching the conservative posture without dominating ``max()`` in\nensemble fusion.", + "properties": { + "history_window": { + "default": 20, + "description": "Number of prior actions to include as context.", + "title": "History Window", + "type": "integer" + }, + "kind": { + "const": "ToolShieldLLMSecurityAnalyzer", + "title": "Kind", + "type": "string" + }, + "llm": { + "$ref": "#/components/schemas/LLM-Output", + "description": "LLM used as the guardrail. Can be a smaller/cheaper model than the actor LLM; only the model's ability to classify action risk matters." + }, + "safety_experiences": { + "default": "", + "description": "Pre-generated safety guidelines injected into the guardrail's system prompt.\n- ``\"\"`` (default): bare guardrail -- no experiences. The analyzer still separates actor from judge; it just classifies without distilled tool-specific guidance.\n- Any non-empty string: used as-is. The intended pattern is to call one of the helpers (``default_safety_experiences()``, ``load_safety_experiences(tool_names)``, ``auto_detect_safety_experiences()``) which require the ``[toolshield]`` optional extra (``pip install openhands-sdk[toolshield]``). Callers with their own source of guidelines can pass any custom string.", + "title": "Safety Experiences", + "type": "string" + } + }, + "required": [ + "llm", + "kind" ], - "title": "BashEventSortOrder" + "title": "ToolShieldLLMSecurityAnalyzer", + "type": "object" }, - "BashOutput": { - "properties": { - "id": { - "type": "string", - "title": "Id" + "TraceMetadataValue": { + "anyOf": [ + { + "type": "string" }, - "timestamp": { - "type": "string", - "format": "date-time", - "title": "Timestamp" + { + "type": "boolean" }, - "command_id": { - "type": "string", - "title": "Command Id" + { + "type": "integer" }, - "order": { - "type": "integer", - "title": "Order", - "description": "The order for this output, sequentially starting with 0", - "default": 0 + { + "type": "number" }, - "exit_code": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "title": "Exit Code", - "description": "Exit code None implies the command is still running." + { + "items": { + "type": "string" + }, + "type": "array" }, - "stdout": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Stdout", - "description": "The standard output from the command" + { + "items": { + "type": "boolean" + }, + "type": "array" }, - "stderr": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Stderr", - "description": "The error output from the command" + { + "items": { + "type": "integer" + }, + "type": "array" }, - "kind": { - "type": "string", - "const": "BashOutput", - "title": "Kind" + { + "items": { + "type": "number" + }, + "type": "array" + } + ] + }, + "UninstallCanvasExtensionResponse": { + "description": "Response from a canvas extension uninstall.", + "properties": { + "message": { + "title": "Message", + "type": "string" } }, - "type": "object", "required": [ - "command_id", - "kind" + "message" ], - "title": "BashOutput", - "description": "Output of a bash command. A single command may have multiple pieces of output\ndepending on how large the output is." + "title": "UninstallCanvasExtensionResponse", + "type": "object" }, - "Body_upload_file_api_file_upload__path__post": { + "UninstallPluginResponse": { + "description": "Response from a plugin uninstall.", "properties": { - "file": { - "type": "string", - "format": "binary", - "title": "File" + "message": { + "title": "Message", + "type": "string" } }, - "type": "object", "required": [ - "file" + "message" ], - "title": "Body_upload_file_api_file_upload__path__post" + "title": "UninstallPluginResponse", + "type": "object" }, - "BrowserAction": { + "UninstallSkillResponse": { + "description": "Response from skill uninstall operation.", "properties": { - "kind": { - "type": "string", - "const": "BrowserAction", - "title": "Kind" + "message": { + "title": "Message", + "type": "string" } }, - "additionalProperties": false, - "type": "object", "required": [ - "kind" + "message" ], - "title": "BrowserAction", - "description": "Base class for all browser actions.\n\nThis base class serves as the parent for all browser-related actions,\nenabling proper type hierarchy and eliminating the need for union types." + "title": "UninstallSkillResponse", + "type": "object" }, - "BrowserClickAction": { + "UpdateCanvasExtensionStateRequest": { + "description": "Request body for updating canvas extension state (enable/disable).", "properties": { - "index": { - "type": "integer", - "minimum": 0.0, - "title": "Index", - "description": "The index of the element to click (from browser_get_state)" - }, - "new_tab": { - "type": "boolean", - "title": "New Tab", - "description": "Whether to open any resulting navigation in a new tab. Default: False", - "default": false - }, - "kind": { - "type": "string", - "const": "BrowserClickAction", - "title": "Kind" + "enabled": { + "title": "Enabled", + "type": "boolean" } }, - "additionalProperties": false, - "type": "object", "required": [ - "index", - "kind" + "enabled" ], - "title": "BrowserClickAction", - "description": "Schema for clicking elements." + "title": "UpdateCanvasExtensionStateRequest", + "type": "object" }, - "BrowserClickTool": { + "UpdateCanvasExtensionStateResponse": { + "description": "Response from a canvas extension state update.", "properties": { - "description": { - "type": "string", - "title": "Description" - }, - "action_type": { - "type": "string", - "title": "Action Type" + "enabled": { + "title": "Enabled", + "type": "boolean" }, - "observation_type": { + "name": { + "title": "Name", + "type": "string" + } + }, + "required": [ + "name", + "enabled" + ], + "title": "UpdateCanvasExtensionStateResponse", + "type": "object" + }, + "UpdateConversationRequest": { + "description": "Payload to update conversation metadata.", + "properties": { + "tags": { "anyOf": [ { - "type": "string" + "additionalProperties": { + "type": "string" + }, + "type": "object" }, { "type": "null" } ], - "title": "Observation Type" - }, - "annotations": { - "anyOf": [ - { - "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" - }, - { - "type": "null" - } - ] + "description": "Key-value tags to set on the conversation. Keys must be lowercase alphanumeric. Values are arbitrary strings up to 256 characters. Replaces all existing tags when provided.", + "title": "Tags" }, - "meta": { + "title": { "anyOf": [ { - "additionalProperties": true, - "type": "object" + "maxLength": 200, + "minLength": 1, + "type": "string" }, { "type": "null" } ], - "title": "Meta" + "description": "New conversation title", + "title": "Title" + } + }, + "title": "UpdateConversationRequest", + "type": "object" + }, + "UpdatePluginResponse": { + "description": "Response from a plugin refresh/update.", + "properties": { + "message": { + "title": "Message", + "type": "string" }, - "kind": { - "type": "string", - "const": "BrowserClickTool", - "title": "Kind" + "plugin": { + "$ref": "#/components/schemas/InstalledPluginResponse" + } + }, + "required": [ + "message", + "plugin" + ], + "title": "UpdatePluginResponse", + "type": "object" + }, + "UpdatePluginStateRequest": { + "description": "Request body for updating plugin state (enable/disable).", + "properties": { + "enabled": { + "title": "Enabled", + "type": "boolean" + } + }, + "required": [ + "enabled" + ], + "title": "UpdatePluginStateRequest", + "type": "object" + }, + "UpdatePluginStateResponse": { + "description": "Response from a plugin state update.", + "properties": { + "enabled": { + "title": "Enabled", + "type": "boolean" }, - "title": { - "type": "string", - "title": "Title", - "readOnly": true + "name": { + "title": "Name", + "type": "string" + } + }, + "required": [ + "name", + "enabled" + ], + "title": "UpdatePluginStateResponse", + "type": "object" + }, + "UpdateSecretsRequest": { + "description": "Payload to update secrets in a conversation.", + "properties": { + "secrets": { + "additionalProperties": { + "$ref": "#/components/schemas/SecretSource-Input" + }, + "description": "Dictionary mapping secret keys to values", + "title": "Secrets", + "type": "object" + } + }, + "required": [ + "secrets" + ], + "title": "UpdateSecretsRequest", + "type": "object" + }, + "UpdateSkillResponse": { + "description": "Response from skill update operation.", + "properties": { + "message": { + "title": "Message", + "type": "string" + }, + "skill": { + "$ref": "#/components/schemas/InstalledSkillResponse" } }, - "type": "object", "required": [ - "description", - "action_type", - "kind", - "title" + "message", + "skill" ], - "title": "BrowserClickTool", - "description": "Tool for clicking browser elements." + "title": "UpdateSkillResponse", + "type": "object" }, - "BrowserCloseTabAction": { + "UpdateSkillStateRequest": { + "description": "Request body for updating skill state (enable/disable).", "properties": { - "tab_id": { - "type": "string", - "title": "Tab Id", - "description": "4 Character Tab ID of the tab to close (from browser_list_tabs)" + "enabled": { + "title": "Enabled", + "type": "boolean" + } + }, + "required": [ + "enabled" + ], + "title": "UpdateSkillStateRequest", + "type": "object" + }, + "UpdateSkillStateResponse": { + "description": "Response from skill state update operation.", + "properties": { + "enabled": { + "title": "Enabled", + "type": "boolean" }, - "kind": { - "type": "string", - "const": "BrowserCloseTabAction", - "title": "Kind" + "name": { + "title": "Name", + "type": "string" } }, - "additionalProperties": false, - "type": "object", "required": [ - "tab_id", - "kind" + "name", + "enabled" ], - "title": "BrowserCloseTabAction", - "description": "Schema for closing browser tabs." + "title": "UpdateSkillStateResponse", + "type": "object" }, - "BrowserCloseTabTool": { + "UserRejectObservation": { + "additionalProperties": false, + "description": "Observation when an action is rejected by user or hook.\n\nThis event is emitted when:\n- User rejects an action during confirmation mode (rejection_source=\"user\")\n- A PreToolUse hook blocks an action (rejection_source=\"hook\")", "properties": { - "description": { - "type": "string", - "title": "Description" + "action_id": { + "description": "The action id that this observation is responding to", + "title": "Action Id", + "type": "string" }, - "action_type": { - "type": "string", - "title": "Action Type" + "id": { + "description": "Unique event id (ULID/UUID)", + "title": "Id", + "type": "string" }, - "observation_type": { + "kind": { + "const": "UserRejectObservation", + "title": "Kind", + "type": "string" + }, + "parent_id": { "anyOf": [ { "type": "string" @@ -4069,91 +21728,65 @@ "type": "null" } ], - "title": "Observation Type" + "description": "Parent event id in the conversation tree. None for the root, or for legacy events predating the tree (see EventLog's effective-parent rule). Events sharing a parent_id are sibling branches.", + "title": "Parent Id" }, - "annotations": { - "anyOf": [ - { - "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" - }, - { - "type": "null" - } - ] + "rejection_reason": { + "default": "User rejected the action", + "description": "Reason for rejecting the action", + "title": "Rejection Reason", + "type": "string" }, - "meta": { - "anyOf": [ - { - "additionalProperties": true, - "type": "object" - }, - { - "type": "null" - } + "rejection_source": { + "default": "user", + "description": "Source of the rejection: 'user' for confirmation mode rejections, 'hook' for PreToolUse hook blocks", + "enum": [ + "user", + "hook" ], - "title": "Meta" + "title": "Rejection Source", + "type": "string" }, - "kind": { - "type": "string", - "const": "BrowserCloseTabTool", - "title": "Kind" + "source": { + "default": "environment", + "enum": [ + "agent", + "user", + "environment", + "hook" + ], + "title": "Source", + "type": "string" }, - "title": { - "type": "string", - "title": "Title", - "readOnly": true - } - }, - "type": "object", - "required": [ - "description", - "action_type", - "kind", - "title" - ], - "title": "BrowserCloseTabTool", - "description": "Tool for closing browser tabs." - }, - "BrowserGetContentAction": { - "properties": { - "extract_links": { - "type": "boolean", - "title": "Extract Links", - "description": "Whether to include links in the content (default: False)", - "default": false + "timestamp": { + "description": "Event timestamp", + "title": "Timestamp", + "type": "string" }, - "start_from_char": { - "type": "integer", - "minimum": 0.0, - "title": "Start From Char", - "description": "Character index to start from in the page content (default: 0)", - "default": 0 + "tool_call_id": { + "description": "The tool call id that this observation is responding to", + "title": "Tool Call Id", + "type": "string" }, - "kind": { - "type": "string", - "const": "BrowserGetContentAction", - "title": "Kind" + "tool_name": { + "description": "The tool name that this observation is responding to", + "title": "Tool Name", + "type": "string" } }, - "additionalProperties": false, - "type": "object", "required": [ + "tool_name", + "tool_call_id", + "action_id", "kind" ], - "title": "BrowserGetContentAction", - "description": "Schema for getting page content in markdown." + "title": "UserRejectObservation", + "type": "object" }, - "BrowserGetContentTool": { + "VSCodeUrlResponse": { + "description": "Response model for VSCode URL.", "properties": { - "description": { - "type": "string", - "title": "Description" - }, - "action_type": { - "type": "string", - "title": "Action Type" - }, - "observation_type": { + "url": { "anyOf": [ { "type": "string" @@ -4162,164 +21795,147 @@ "type": "null" } ], - "title": "Observation Type" - }, - "annotations": { - "anyOf": [ - { - "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" - }, - { - "type": "null" - } - ] - }, - "meta": { - "anyOf": [ - { - "additionalProperties": true, - "type": "object" - }, - { - "type": "null" - } - ], - "title": "Meta" - }, - "kind": { - "type": "string", - "const": "BrowserGetContentTool", - "title": "Kind" - }, - "title": { - "type": "string", - "title": "Title", - "readOnly": true + "title": "Url" } }, - "type": "object", "required": [ - "description", - "action_type", - "kind", - "title" + "url" ], - "title": "BrowserGetContentTool", - "description": "Tool for getting page content in markdown." + "title": "VSCodeUrlResponse", + "type": "object" }, - "BrowserGetStateAction": { + "ValidateProfileError": { + "description": "Structured error returned when validation fails.", "properties": { - "include_screenshot": { - "type": "boolean", - "title": "Include Screenshot", - "description": "Whether to include a screenshot of the current page. Default: False", - "default": false + "message": { + "title": "Message", + "type": "string" }, - "kind": { - "type": "string", - "const": "BrowserGetStateAction", - "title": "Kind" + "type": { + "title": "Type", + "type": "string" } }, - "additionalProperties": false, - "type": "object", "required": [ - "kind" + "type", + "message" ], - "title": "BrowserGetStateAction", - "description": "Schema for getting browser state." + "title": "ValidateProfileError", + "type": "object" }, - "BrowserGetStateTool": { + "ValidateProfileRequest": { + "description": "Request body for LLM pre-flight validation.\n\nAccepts an LLM config (same shape as ``SaveProfileRequest.llm``) so the\nfrontend can validate a draft *before* persisting it.", "properties": { - "description": { - "type": "string", - "title": "Description" - }, - "action_type": { - "type": "string", - "title": "Action Type" - }, - "observation_type": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Observation Type" - }, - "annotations": { + "llm": { + "$ref": "#/components/schemas/LLM-Input" + } + }, + "required": [ + "llm" + ], + "title": "ValidateProfileRequest", + "type": "object" + }, + "ValidateProfileResponse": { + "description": "Result of an LLM pre-flight check.", + "properties": { + "error": { "anyOf": [ { - "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" + "$ref": "#/components/schemas/ValidateProfileError" }, { "type": "null" } ] }, - "meta": { - "anyOf": [ - { - "additionalProperties": true, - "type": "object" - }, - { - "type": "null" - } - ], - "title": "Meta" + "valid": { + "title": "Valid", + "type": "boolean" + } + }, + "required": [ + "valid" + ], + "title": "ValidateProfileResponse", + "type": "object" + }, + "ValidationError": { + "properties": { + "ctx": { + "title": "Context", + "type": "object" }, - "kind": { - "type": "string", - "const": "BrowserGetStateTool", - "title": "Kind" + "input": { + "title": "Input" + }, + "loc": { + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] + }, + "title": "Location", + "type": "array" }, - "title": { - "type": "string", - "title": "Title", - "readOnly": true + "msg": { + "title": "Message", + "type": "string" + }, + "type": { + "title": "Error Type", + "type": "string" } }, - "type": "object", "required": [ - "description", - "action_type", - "kind", - "title" + "loc", + "msg", + "type" ], - "title": "BrowserGetStateTool", - "description": "Tool for getting browser state." + "title": "ValidationError", + "type": "object" }, - "BrowserGetStorageAction": { + "VerifiedModelsResponse": { + "description": "Response containing verified LLM models organized by provider.", "properties": { - "kind": { - "type": "string", - "const": "BrowserGetStorageAction", - "title": "Kind" + "models": { + "additionalProperties": { + "items": { + "type": "string" + }, + "type": "array" + }, + "title": "Models", + "type": "object" } }, - "additionalProperties": false, - "type": "object", "required": [ - "kind" + "models" ], - "title": "BrowserGetStorageAction", - "description": "Schema for getting browser storage (cookies, local storage, session storage)." + "title": "VerifiedModelsResponse", + "type": "object" }, - "BrowserGetStorageTool": { + "VisionInspectAction": { + "additionalProperties": false, + "description": "Action for asking a vision model about an attached image.", "properties": { - "description": { - "type": "string", - "title": "Description" + "image_index": { + "description": "Zero-based index of the image to inspect from the latest user message.", + "minimum": 0.0, + "title": "Image Index", + "type": "integer" }, - "action_type": { - "type": "string", - "title": "Action Type" + "kind": { + "const": "VisionInspectAction", + "title": "Kind", + "type": "string" }, - "observation_type": { + "profile_name": { "anyOf": [ { "type": "string" @@ -4328,78 +21944,84 @@ "type": "null" } ], - "title": "Observation Type" + "description": "Optional saved vision-capable LLM profile name. If omitted, the first available vision profile listed in the tool description is used.", + "title": "Profile Name" }, - "annotations": { + "question": { + "description": "Question to ask the vision model about the selected image.", + "minLength": 1, + "title": "Question", + "type": "string" + } + }, + "required": [ + "image_index", + "question", + "kind" + ], + "title": "VisionInspectAction", + "type": "object" + }, + "VisionInspectObservation": { + "additionalProperties": false, + "description": "Observation returned after a vision model inspects an image.", + "properties": { + "answer": { "anyOf": [ { - "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" + "type": "string" }, { "type": "null" } - ] + ], + "description": "Text answer returned by the vision model.", + "title": "Answer" }, - "meta": { + "base_url": { "anyOf": [ { - "additionalProperties": true, - "type": "object" + "type": "string" }, { "type": "null" } ], - "title": "Meta" + "description": "Vision-capable LLM endpoint used for inspection.", + "title": "Base Url" }, - "kind": { - "type": "string", - "const": "BrowserGetStorageTool", - "title": "Kind" + "content": { + "description": "Content returned from the tool as a list of TextContent/ImageContent objects. When there is an error, it should be written in this field.", + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/TextContent" + }, + { + "$ref": "#/components/schemas/ImageContent" + } + ] + }, + "title": "Content", + "type": "array" }, - "title": { - "type": "string", - "title": "Title", - "readOnly": true - } - }, - "type": "object", - "required": [ - "description", - "action_type", - "kind", - "title" - ], - "title": "BrowserGetStorageTool", - "description": "Tool for getting browser storage." - }, - "BrowserGoBackAction": { - "properties": { - "kind": { - "type": "string", - "const": "BrowserGoBackAction", - "title": "Kind" - } - }, - "additionalProperties": false, - "type": "object", - "required": [ - "kind" - ], - "title": "BrowserGoBackAction", - "description": "Schema for going back in browser history." - }, - "BrowserGoBackTool": { - "properties": { - "description": { - "type": "string", - "title": "Description" + "image_index": { + "description": "Image index that was inspected.", + "title": "Image Index", + "type": "integer" }, - "action_type": { - "type": "string", - "title": "Action Type" + "is_error": { + "default": false, + "description": "Whether the observation indicates an error", + "title": "Is Error", + "type": "boolean" }, - "observation_type": { + "kind": { + "const": "VisionInspectObservation", + "title": "Kind", + "type": "string" + }, + "model": { "anyOf": [ { "type": "string" @@ -4408,87 +22030,41 @@ "type": "null" } ], - "title": "Observation Type" - }, - "annotations": { - "anyOf": [ - { - "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" - }, - { - "type": "null" - } - ] + "description": "Vision-capable model used for inspection.", + "title": "Model" }, - "meta": { + "profile_name": { "anyOf": [ { - "additionalProperties": true, - "type": "object" + "type": "string" }, { "type": "null" } ], - "title": "Meta" + "description": "Vision-capable profile used for inspection.", + "title": "Profile Name" }, - "kind": { - "type": "string", - "const": "BrowserGoBackTool", - "title": "Kind" - }, - "title": { - "type": "string", - "title": "Title", - "readOnly": true - } - }, - "type": "object", - "required": [ - "description", - "action_type", - "kind", - "title" - ], - "title": "BrowserGoBackTool", - "description": "Tool for going back in browser history." - }, - "BrowserListTabsAction": { - "properties": { - "kind": { - "type": "string", - "const": "BrowserListTabsAction", - "title": "Kind" + "question": { + "description": "Question asked of the vision model.", + "title": "Question", + "type": "string" } }, - "additionalProperties": false, - "type": "object", "required": [ + "image_index", + "question", "kind" ], - "title": "BrowserListTabsAction", - "description": "Schema for listing browser tabs." + "title": "VisionInspectObservation", + "type": "object" }, - "BrowserListTabsTool": { + "VisionInspectTool": { + "description": "Tool for one-off image inspection through a saved vision profile.", "properties": { - "description": { - "type": "string", - "title": "Description" - }, "action_type": { - "type": "string", - "title": "Action Type" - }, - "observation_type": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Observation Type" + "title": "Action Type", + "type": "string" }, "annotations": { "anyOf": [ @@ -4500,6 +22076,15 @@ } ] }, + "description": { + "title": "Description", + "type": "string" + }, + "kind": { + "const": "VisionInspectTool", + "title": "Kind", + "type": "string" + }, "meta": { "anyOf": [ { @@ -4512,122 +22097,145 @@ ], "title": "Meta" }, - "kind": { - "type": "string", - "const": "BrowserListTabsTool", - "title": "Kind" + "observation_type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Observation Type" }, "title": { - "type": "string", + "readOnly": true, "title": "Title", - "readOnly": true + "type": "string" } }, - "type": "object", "required": [ "description", "action_type", "kind", "title" ], - "title": "BrowserListTabsTool", - "description": "Tool for listing browser tabs." + "title": "VisionInspectTool", + "type": "object" }, - "BrowserNavigateAction": { + "WebhookSpec": { + "description": "Spec to create a webhook. All webhook requests use POST method.", "properties": { - "url": { - "type": "string", - "title": "Url", - "description": "The URL to navigate to" - }, - "new_tab": { - "type": "boolean", - "title": "New Tab", - "description": "Whether to open in a new tab. Default: False", - "default": false + "base_url": { + "description": "The base URL of the webhook service. Events will be sent to {base_url}/events and conversation info to {base_url}/conversations", + "title": "Base Url", + "type": "string" }, - "kind": { - "type": "string", - "const": "BrowserNavigateAction", - "title": "Kind" - } - }, - "additionalProperties": false, - "type": "object", - "required": [ - "url", - "kind" - ], - "title": "BrowserNavigateAction", - "description": "Schema for browser navigation." - }, - "BrowserNavigateTool": { - "properties": { - "description": { - "type": "string", - "title": "Description" + "event_buffer_size": { + "default": 5, + "description": "The number of events to buffer locally before posting to the webhook", + "minimum": 1.0, + "title": "Event Buffer Size", + "type": "integer" }, - "action_type": { - "type": "string", - "title": "Action Type" + "flush_delay": { + "default": 30.0, + "description": "The delay in seconds after which buffered events will be flushed to the webhook, even if the buffer is not full. Timer is reset on each new event.", + "exclusiveMinimum": 0.0, + "title": "Flush Delay", + "type": "number" }, - "observation_type": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Observation Type" + "headers": { + "additionalProperties": { + "type": "string" + }, + "title": "Headers", + "type": "object" }, - "annotations": { - "anyOf": [ - { - "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" - }, - { - "type": "null" - } - ] + "max_batch_bytes": { + "default": 5242880, + "description": "Upper bound on the serialized size of each webhook request. A single event larger than this limit is sent by itself.", + "minimum": 1.0, + "title": "Max Batch Bytes", + "type": "integer" }, - "meta": { - "anyOf": [ - { - "additionalProperties": true, - "type": "object" - }, - { - "type": "null" - } - ], - "title": "Meta" + "max_queue_bytes": { + "default": 52428800, + "description": "Upper bound on the serialized size of events buffered for delivery. The oldest events are dropped when the queue exceeds this bound.", + "minimum": 1.0, + "title": "Max Queue Bytes", + "type": "integer" + }, + "max_queue_size": { + "default": 1000, + "description": "Upper bound on the number of events buffered for delivery. The oldest events are dropped past this bound to prevent unbounded memory growth.", + "minimum": 1.0, + "title": "Max Queue Size", + "type": "integer" + }, + "num_retries": { + "default": 3, + "description": "The number of times to retry if the post operation fails", + "minimum": 0.0, + "title": "Num Retries", + "type": "integer" }, + "retry_delay": { + "default": 5, + "description": "The delay between retries", + "minimum": 0.0, + "title": "Retry Delay", + "type": "integer" + } + }, + "required": [ + "base_url" + ], + "title": "WebhookSpec", + "type": "object" + }, + "WorkflowAction": { + "additionalProperties": false, + "description": "Schema for running a Python dynamic workflow script.", + "properties": { "kind": { - "type": "string", - "const": "BrowserNavigateTool", - "title": "Kind" + "const": "WorkflowAction", + "title": "Kind", + "type": "string" + }, + "max_concurrency": { + "default": 8, + "description": "Maximum number of sub-agent tasks to run concurrently. Consider 2–4 for LLM-heavy workflows to avoid hitting API rate limits.", + "maximum": 64.0, + "minimum": 1.0, + "title": "Max Concurrency", + "type": "integer" }, - "title": { - "type": "string", - "title": "Title", - "readOnly": true + "name": { + "description": "A short name for this workflow run.", + "title": "Name", + "type": "string" + }, + "script": { + "description": "Python workflow script to run. It must define `async def main(wf):` and coordinate work only through the provided `wf` object.", + "title": "Script", + "type": "string" } }, - "type": "object", "required": [ - "description", - "action_type", - "kind", - "title" + "name", + "script", + "kind" ], - "title": "BrowserNavigateTool", - "description": "Tool for browser navigation." + "title": "WorkflowAction", + "type": "object" }, - "BrowserObservation": { + "WorkflowObservation": { + "additionalProperties": false, + "description": "Observation from a dynamic workflow run.", "properties": { "content": { + "description": "Content returned from the tool as a list of TextContent/ImageContent objects. When there is an error, it should be written in this field.", "items": { "anyOf": [ { @@ -4638,100 +22246,49 @@ } ] }, - "type": "array", "title": "Content", - "description": "Content returned from the tool as a list of TextContent/ImageContent objects. When there is an error, it should be written in this field." + "type": "array" }, "is_error": { - "type": "boolean", - "title": "Is Error", + "default": false, "description": "Whether the observation indicates an error", - "default": false + "title": "Is Error", + "type": "boolean" }, - "screenshot_data": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Screenshot Data", - "description": "Base64 screenshot data if available" + "kind": { + "const": "WorkflowObservation", + "title": "Kind", + "type": "string" }, - "full_output_save_dir": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Full Output Save Dir", - "description": "Directory where full output files are saved" + "name": { + "description": "The workflow name that was executed.", + "title": "Name", + "type": "string" }, - "kind": { - "type": "string", - "const": "BrowserObservation", - "title": "Kind" - } - }, - "additionalProperties": false, - "type": "object", - "required": [ - "kind" - ], - "title": "BrowserObservation", - "description": "Base observation for browser operations." - }, - "BrowserScrollAction": { - "properties": { - "direction": { - "type": "string", + "status": { + "description": "The workflow execution status.", "enum": [ - "up", - "down" + "completed", + "error" ], - "title": "Direction", - "description": "Direction to scroll. Options: 'up', 'down'. Default: 'down'", - "default": "down" - }, - "kind": { - "type": "string", - "const": "BrowserScrollAction", - "title": "Kind" + "title": "Status", + "type": "string" } }, - "additionalProperties": false, - "type": "object", "required": [ + "name", + "status", "kind" ], - "title": "BrowserScrollAction", - "description": "Schema for scrolling the page." + "title": "WorkflowObservation", + "type": "object" }, - "BrowserScrollTool": { + "WorkflowTool": { + "description": "Low-level tool for explicit executor injection.\n\nPrefer ``WorkflowToolSet`` for standard SDK auto-create usage.\nUse ``WorkflowTool`` when you need to inject a custom executor\n(e.g., in tests or extensions).", "properties": { - "description": { - "type": "string", - "title": "Description" - }, "action_type": { - "type": "string", - "title": "Action Type" - }, - "observation_type": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Observation Type" + "title": "Action Type", + "type": "string" }, "annotations": { "anyOf": [ @@ -4743,6 +22300,15 @@ } ] }, + "description": { + "title": "Description", + "type": "string" + }, + "kind": { + "const": "WorkflowTool", + "title": "Kind", + "type": "string" + }, "meta": { "anyOf": [ { @@ -4755,70 +22321,38 @@ ], "title": "Meta" }, - "kind": { - "type": "string", - "const": "BrowserScrollTool", - "title": "Kind" + "observation_type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Observation Type" }, "title": { - "type": "string", + "readOnly": true, "title": "Title", - "readOnly": true + "type": "string" } }, - "type": "object", "required": [ "description", "action_type", "kind", "title" ], - "title": "BrowserScrollTool", - "description": "Tool for scrolling the browser page." - }, - "BrowserSetStorageAction": { - "properties": { - "storage_state": { - "additionalProperties": true, - "type": "object", - "title": "Storage State", - "description": "Storage state dictionary containing 'cookies' and 'origins' (from browser_get_storage)" - }, - "kind": { - "type": "string", - "const": "BrowserSetStorageAction", - "title": "Kind" - } - }, - "additionalProperties": false, - "type": "object", - "required": [ - "storage_state", - "kind" - ], - "title": "BrowserSetStorageAction", - "description": "Schema for setting browser storage (cookies, local storage, session storage)." + "title": "WorkflowTool", + "type": "object" }, - "BrowserSetStorageTool": { + "WorkflowToolSet": { + "description": "Tool set that creates the dynamic workflow tool.", "properties": { - "description": { - "type": "string", - "title": "Description" - }, "action_type": { - "type": "string", - "title": "Action Type" - }, - "observation_type": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Observation Type" + "title": "Action Type", + "type": "string" }, "annotations": { "anyOf": [ @@ -4830,6 +22364,15 @@ } ] }, + "description": { + "title": "Description", + "type": "string" + }, + "kind": { + "const": "WorkflowToolSet", + "title": "Kind", + "type": "string" + }, "meta": { "anyOf": [ { @@ -4842,134 +22385,170 @@ ], "title": "Meta" }, - "kind": { - "type": "string", - "const": "BrowserSetStorageTool", - "title": "Kind" + "observation_type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Observation Type" }, "title": { - "type": "string", + "readOnly": true, "title": "Title", - "readOnly": true + "type": "string" } }, - "type": "object", "required": [ "description", "action_type", "kind", "title" ], - "title": "BrowserSetStorageTool", - "description": "Tool for setting browser storage." - }, - "BrowserStartRecordingAction": { - "properties": { - "kind": { - "type": "string", - "const": "BrowserStartRecordingAction", - "title": "Kind" - } - }, - "additionalProperties": false, - "type": "object", - "required": [ - "kind" - ], - "title": "BrowserStartRecordingAction", - "description": "Schema for starting browser session recording." + "title": "WorkflowToolSet", + "type": "object" }, - "BrowserStartRecordingTool": { + "WorkspaceItem": { "properties": { - "description": { - "type": "string", - "title": "Description" + "id": { + "maxLength": 4096, + "minLength": 1, + "title": "Id", + "type": "string" }, - "action_type": { - "type": "string", - "title": "Action Type" + "name": { + "maxLength": 256, + "minLength": 1, + "title": "Name", + "type": "string" }, - "observation_type": { + "parentPath": { "anyOf": [ { + "maxLength": 4096, "type": "string" }, { "type": "null" } ], - "title": "Observation Type" - }, - "annotations": { - "anyOf": [ - { - "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" - }, - { - "type": "null" - } - ] + "title": "Parentpath" }, - "meta": { - "anyOf": [ - { - "additionalProperties": true, - "type": "object" - }, - { - "type": "null" - } - ], - "title": "Meta" + "path": { + "maxLength": 4096, + "minLength": 1, + "title": "Path", + "type": "string" + } + }, + "required": [ + "id", + "name", + "path" + ], + "title": "WorkspaceItem", + "type": "object" + }, + "WorkspaceParentItem": { + "properties": { + "id": { + "maxLength": 4096, + "minLength": 1, + "title": "Id", + "type": "string" }, - "kind": { - "type": "string", - "const": "BrowserStartRecordingTool", - "title": "Kind" + "name": { + "maxLength": 256, + "minLength": 1, + "title": "Name", + "type": "string" }, - "title": { - "type": "string", - "title": "Title", - "readOnly": true + "path": { + "maxLength": 4096, + "minLength": 1, + "title": "Path", + "type": "string" } }, - "type": "object", "required": [ - "description", - "action_type", - "kind", - "title" + "id", + "name", + "path" ], - "title": "BrowserStartRecordingTool", - "description": "Tool for starting browser session recording." + "title": "WorkspaceParentItem", + "type": "object" }, - "BrowserStopRecordingAction": { + "WorkspacesListResponse": { "properties": { - "kind": { - "type": "string", - "const": "BrowserStopRecordingAction", - "title": "Kind" + "workspaceParents": { + "items": { + "$ref": "#/components/schemas/WorkspaceParentItem" + }, + "title": "Workspaceparents", + "type": "array" + }, + "workspaces": { + "items": { + "$ref": "#/components/schemas/WorkspaceItem" + }, + "title": "Workspaces", + "type": "array" } }, + "title": "WorkspacesListResponse", + "type": "object" + }, + "WriteFileAction": { "additionalProperties": false, - "type": "object", + "description": "Schema for write file operation.", + "properties": { + "content": { + "description": "The content to write to the file.", + "title": "Content", + "type": "string" + }, + "file_path": { + "description": "The path to the file to write to.", + "title": "File Path", + "type": "string" + }, + "kind": { + "const": "WriteFileAction", + "title": "Kind", + "type": "string" + } + }, "required": [ + "file_path", + "content", "kind" ], - "title": "BrowserStopRecordingAction", - "description": "Schema for stopping browser session recording." + "title": "WriteFileAction", + "type": "object" }, - "BrowserStopRecordingTool": { + "WriteFileObservation": { + "additionalProperties": false, + "description": "Observation from writing a file.", "properties": { - "description": { - "type": "string", - "title": "Description" - }, - "action_type": { - "type": "string", - "title": "Action Type" + "content": { + "description": "Content returned from the tool as a list of TextContent/ImageContent objects. When there is an error, it should be written in this field.", + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/TextContent" + }, + { + "$ref": "#/components/schemas/ImageContent" + } + ] + }, + "title": "Content", + "type": "array" }, - "observation_type": { + "file_path": { "anyOf": [ { "type": "string" @@ -4978,93 +22557,63 @@ "type": "null" } ], - "title": "Observation Type" + "description": "The file path that was written.", + "title": "File Path" }, - "annotations": { + "is_error": { + "default": false, + "description": "Whether the observation indicates an error", + "title": "Is Error", + "type": "boolean" + }, + "is_new_file": { + "default": false, + "description": "Whether a new file was created.", + "title": "Is New File", + "type": "boolean" + }, + "kind": { + "const": "WriteFileObservation", + "title": "Kind", + "type": "string" + }, + "new_content": { "anyOf": [ { - "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" + "type": "string" }, { "type": "null" } - ] + ], + "description": "The new content written to the file.", + "title": "New Content" }, - "meta": { + "old_content": { "anyOf": [ { - "additionalProperties": true, - "type": "object" + "type": "string" }, { "type": "null" } ], - "title": "Meta" - }, - "kind": { - "type": "string", - "const": "BrowserStopRecordingTool", - "title": "Kind" - }, - "title": { - "type": "string", - "title": "Title", - "readOnly": true - } - }, - "type": "object", - "required": [ - "description", - "action_type", - "kind", - "title" - ], - "title": "BrowserStopRecordingTool", - "description": "Tool for stopping browser session recording." - }, - "BrowserSwitchTabAction": { - "properties": { - "tab_id": { - "type": "string", - "title": "Tab Id", - "description": "4 Character Tab ID of the tab to switch to (from browser_list_tabs)" - }, - "kind": { - "type": "string", - "const": "BrowserSwitchTabAction", - "title": "Kind" + "description": "The previous content of the file (if it existed).", + "title": "Old Content" } }, - "additionalProperties": false, - "type": "object", "required": [ - "tab_id", "kind" ], - "title": "BrowserSwitchTabAction", - "description": "Schema for switching browser tabs." + "title": "WriteFileObservation", + "type": "object" }, - "BrowserSwitchTabTool": { + "WriteFileTool": { + "description": "Tool for writing complete file contents.", "properties": { - "description": { - "type": "string", - "title": "Description" - }, "action_type": { - "type": "string", - "title": "Action Type" - }, - "observation_type": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Observation Type" + "title": "Action Type", + "type": "string" }, "annotations": { "anyOf": [ @@ -5076,6 +22625,15 @@ } ] }, + "description": { + "title": "Description", + "type": "string" + }, + "kind": { + "const": "WriteFileTool", + "title": "Kind", + "type": "string" + }, "meta": { "anyOf": [ { @@ -5088,235 +22646,269 @@ ], "title": "Meta" }, - "kind": { - "type": "string", - "const": "BrowserSwitchTabTool", - "title": "Kind" + "observation_type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Observation Type" }, "title": { - "type": "string", + "readOnly": true, "title": "Title", - "readOnly": true + "type": "string" } }, - "type": "object", "required": [ "description", "action_type", "kind", "title" ], - "title": "BrowserSwitchTabTool", - "description": "Tool for switching browser tabs." + "title": "WriteFileTool", + "type": "object" }, - "BrowserToolSet": { + "_RemoteMCPServerSpec": { + "description": "Legacy remote MCP server spec accepted by the public REST API.", "properties": { - "description": { - "type": "string", - "title": "Description" + "auth": { + "anyOf": [ + { + "discriminator": { + "mapping": { + "api_key": "#/components/schemas/MCPApiKeyAuthCredential-Input", + "basic": "#/components/schemas/MCPBasicAuthCredential-Input", + "bearer": "#/components/schemas/MCPBearerAuthCredential-Input", + "header": "#/components/schemas/MCPHeaderAuthCredential-Input", + "none": "#/components/schemas/MCPNoneAuthCredential", + "oauth2": "#/components/schemas/MCPOAuthAuthCredential-Input" + }, + "propertyName": "strategy" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/MCPNoneAuthCredential" + }, + { + "$ref": "#/components/schemas/MCPApiKeyAuthCredential-Input" + }, + { + "$ref": "#/components/schemas/MCPBearerAuthCredential-Input" + }, + { + "$ref": "#/components/schemas/MCPBasicAuthCredential-Input" + }, + { + "$ref": "#/components/schemas/MCPHeaderAuthCredential-Input" + }, + { + "$ref": "#/components/schemas/MCPOAuthAuthCredential-Input" + } + ] + }, + { + "type": "null" + } + ], + "title": "Auth" }, - "action_type": { - "type": "string", - "title": "Action Type" + "headers": { + "additionalProperties": { + "type": "string" + }, + "title": "Headers", + "type": "object" }, - "observation_type": { + "keep_alive": { "anyOf": [ { - "type": "string" + "type": "boolean" }, { "type": "null" } ], - "title": "Observation Type" + "title": "Keep Alive" }, - "annotations": { + "sse_read_timeout": { "anyOf": [ { - "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" + "type": "number" }, { "type": "null" } - ] + ], + "title": "Sse Read Timeout" }, - "meta": { + "timeout": { "anyOf": [ { - "additionalProperties": true, - "type": "object" + "type": "number" }, { "type": "null" } ], - "title": "Meta" + "title": "Timeout" }, - "kind": { - "type": "string", - "const": "BrowserToolSet", - "title": "Kind" + "type": { + "enum": [ + "http", + "shttp", + "streamable-http", + "sse" + ], + "title": "Type", + "type": "string" }, - "title": { - "type": "string", - "title": "Title", - "readOnly": true + "url": { + "minLength": 1, + "title": "Url", + "type": "string" } }, - "type": "object", "required": [ - "description", - "action_type", - "kind", - "title" + "type", + "url" ], - "title": "BrowserToolSet", - "description": "A set of all browser tools.\n\nThis tool set includes all available browser-related tools\n for interacting with web pages.\n\nThe toolset automatically checks for Chromium availability\nwhen created and automatically installs it if missing." + "title": "_RemoteMCPServerSpec", + "type": "object" }, - "BrowserTypeAction": { + "_StdioMCPServerSpec": { + "description": "Legacy stdio MCP server spec accepted by the public REST API.", "properties": { - "index": { - "type": "integer", - "minimum": 0.0, - "title": "Index", - "description": "The index of the input element (from browser_get_state)" + "args": { + "items": { + "type": "string" + }, + "title": "Args", + "type": "array" + }, + "command": { + "description": "Executable to invoke", + "minLength": 1, + "title": "Command", + "type": "string" + }, + "cwd": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Cwd" }, - "text": { - "type": "string", - "title": "Text", - "description": "The text to type" + "env": { + "additionalProperties": { + "type": "string" + }, + "title": "Env", + "type": "object" }, - "kind": { - "type": "string", - "const": "BrowserTypeAction", - "title": "Kind" + "type": { + "const": "stdio", + "default": "stdio", + "title": "Type", + "type": "string" } }, - "additionalProperties": false, - "type": "object", "required": [ - "index", - "text", - "kind" + "command" ], - "title": "BrowserTypeAction", - "description": "Schema for typing text into elements." + "title": "_StdioMCPServerSpec", + "type": "object" }, - "BrowserTypeTool": { + "mcp__types__Tool": { + "additionalProperties": true, + "description": "Definition for a tool the client can call.", "properties": { - "description": { - "type": "string", - "title": "Description" - }, - "action_type": { - "type": "string", - "title": "Action Type" - }, - "observation_type": { + "_meta": { "anyOf": [ { - "type": "string" + "additionalProperties": true, + "type": "object" }, { "type": "null" } ], - "title": "Observation Type" + "title": "Meta" }, "annotations": { "anyOf": [ { - "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" + "$ref": "#/components/schemas/mcp__types__ToolAnnotations" }, { "type": "null" } ] }, - "meta": { + "description": { "anyOf": [ { - "additionalProperties": true, - "type": "object" + "type": "string" }, { "type": "null" } ], - "title": "Meta" - }, - "kind": { - "type": "string", - "const": "BrowserTypeTool", - "title": "Kind" - }, - "title": { - "type": "string", - "title": "Title", - "readOnly": true - } - }, - "type": "object", - "required": [ - "description", - "action_type", - "kind", - "title" - ], - "title": "BrowserTypeTool", - "description": "Tool for typing text into browser elements." - }, - "CmdOutputMetadata": { - "properties": { - "exit_code": { - "type": "integer", - "title": "Exit Code", - "description": "The exit code of the last executed command.", - "default": -1 - }, - "pid": { - "type": "integer", - "title": "Pid", - "description": "The process ID of the last executed command.", - "default": -1 + "title": "Description" }, - "username": { + "execution": { "anyOf": [ { - "type": "string" + "$ref": "#/components/schemas/ToolExecution" }, { "type": "null" } - ], - "title": "Username", - "description": "The username of the current user." + ] }, - "hostname": { + "icons": { "anyOf": [ { - "type": "string" + "items": { + "$ref": "#/components/schemas/Icon" + }, + "type": "array" }, { "type": "null" } ], - "title": "Hostname", - "description": "The hostname of the machine." + "title": "Icons" }, - "working_dir": { + "inputSchema": { + "additionalProperties": true, + "title": "Inputschema", + "type": "object" + }, + "name": { + "title": "Name", + "type": "string" + }, + "outputSchema": { "anyOf": [ { - "type": "string" + "additionalProperties": true, + "type": "object" }, { "type": "null" } ], - "title": "Working Dir", - "description": "The current working directory." + "title": "Outputschema" }, - "py_interpreter_path": { + "title": { "anyOf": [ { "type": "string" @@ -5325,7355 +22917,9522 @@ "type": "null" } ], - "title": "Py Interpreter Path", - "description": "The path to the current Python interpreter, if any." - }, - "prefix": { - "type": "string", - "title": "Prefix", - "description": "Prefix to add to command output", - "default": "" - }, - "suffix": { - "type": "string", - "title": "Suffix", - "description": "Suffix to add to command output", - "default": "" + "title": "Title" } }, - "type": "object", - "title": "CmdOutputMetadata", - "description": "Additional metadata captured from PS1" + "required": [ + "name", + "inputSchema" + ], + "title": "Tool", + "type": "object" }, - "Condensation": { + "mcp__types__ToolAnnotations": { + "additionalProperties": true, + "description": "Additional properties describing a Tool to clients.\n\nNOTE: all properties in ToolAnnotations are **hints**.\nThey are not guaranteed to provide a faithful description of\ntool behavior (including descriptive properties like `title`).\n\nClients should never make tool use decisions based on ToolAnnotations\nreceived from untrusted servers.", "properties": { - "id": { - "type": "string", - "title": "Id", - "description": "Unique event id (ULID/UUID)" - }, - "timestamp": { - "type": "string", - "title": "Timestamp", - "description": "Event timestamp" - }, - "source": { - "type": "string", - "enum": [ - "agent", - "user", - "environment" + "destructiveHint": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } ], - "title": "Source", - "default": "environment" - }, - "forgotten_event_ids": { - "items": { - "type": "string" - }, - "type": "array", - "title": "Forgotten Event Ids", - "description": "The IDs of the events that are being forgotten (removed from the `View` given to the LLM)." + "title": "Destructivehint" }, - "summary": { + "idempotentHint": { "anyOf": [ { - "type": "string" + "type": "boolean" }, { "type": "null" } ], - "title": "Summary", - "description": "An optional summary of the events being forgotten." + "title": "Idempotenthint" }, - "summary_offset": { + "openWorldHint": { "anyOf": [ { - "type": "integer", - "minimum": 0.0 + "type": "boolean" }, { "type": "null" } ], - "title": "Summary Offset", - "description": "An optional offset to the start of the resulting view (after forgotten events have been removed) indicating where the summary should be inserted. If not provided, the summary will not be inserted into the view." - }, - "llm_response_id": { - "type": "string", - "title": "Llm Response Id", - "description": "Completion or Response ID of the LLM response that generated this event" - }, - "kind": { - "type": "string", - "const": "Condensation", - "title": "Kind" - } - }, - "additionalProperties": false, - "type": "object", - "required": [ - "llm_response_id", - "kind" - ], - "title": "Condensation", - "description": "This action indicates a condensation of the conversation history is happening." - }, - "CondensationRequest": { - "properties": { - "id": { - "type": "string", - "title": "Id", - "description": "Unique event id (ULID/UUID)" - }, - "timestamp": { - "type": "string", - "title": "Timestamp", - "description": "Event timestamp" + "title": "Openworldhint" }, - "source": { - "type": "string", - "enum": [ - "agent", - "user", - "environment" + "readOnlyHint": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } ], - "title": "Source", - "default": "environment" + "title": "Readonlyhint" }, - "kind": { - "type": "string", - "const": "CondensationRequest", - "title": "Kind" + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Title" } }, - "additionalProperties": false, - "type": "object", - "required": [ - "kind" - ], - "title": "CondensationRequest", - "description": "This action is used to request a condensation of the conversation history.\n\nAttributes:\n action (str): The action type, namely ActionType.CONDENSATION_REQUEST." + "title": "ToolAnnotations", + "type": "object" }, - "CondensationSummaryEvent": { + "openhands__agent_server__plugins_router__MarketplaceCatalogResponse": { + "description": "Response containing the plugins marketplace catalog.", "properties": { - "id": { - "type": "string", - "title": "Id", - "description": "Unique event id (ULID/UUID)" - }, - "timestamp": { - "type": "string", - "title": "Timestamp", - "description": "Event timestamp" - }, - "source": { - "type": "string", - "enum": [ - "agent", - "user", - "environment" - ], - "title": "Source", - "default": "environment" - }, - "summary": { - "type": "string", - "title": "Summary" - }, - "kind": { - "type": "string", - "const": "CondensationSummaryEvent", - "title": "Kind" + "plugins": { + "items": { + "$ref": "#/components/schemas/MarketplacePluginInfo" + }, + "title": "Plugins", + "type": "array" } }, - "additionalProperties": false, - "type": "object", "required": [ - "summary", - "kind" + "plugins" ], - "title": "CondensationSummaryEvent", - "description": "This event represents a summary generated by a condenser." + "title": "MarketplaceCatalogResponse", + "type": "object" }, - "CondenserBase-Input": { - "oneOf": [ - { - "$ref": "#/components/schemas/LLMSummarizingCondenser-Input" - }, - { - "$ref": "#/components/schemas/NoOpCondenser-Input" - }, - { - "$ref": "#/components/schemas/PipelineCondenser-Input" + "openhands__agent_server__skills_router__MarketplaceCatalogResponse": { + "description": "Response containing the marketplace catalog.", + "properties": { + "skills": { + "items": { + "$ref": "#/components/schemas/MarketplaceSkillInfo" + }, + "title": "Skills", + "type": "array" } + }, + "required": [ + "skills" ], - "discriminator": { - "propertyName": "kind", - "mapping": { - "openhands__sdk__context__condenser__llm_summarizing_condenser__LLMSummarizingCondenser-Input__1": "#/components/schemas/LLMSummarizingCondenser-Input", - "openhands__sdk__context__condenser__no_op_condenser__NoOpCondenser-Input__1": "#/components/schemas/NoOpCondenser-Input", - "openhands__sdk__context__condenser__pipeline_condenser__PipelineCondenser-Input__1": "#/components/schemas/PipelineCondenser-Input" - } - } + "title": "MarketplaceCatalogResponse", + "type": "object" }, - "CondenserBase-Output": { - "oneOf": [ - { - "$ref": "#/components/schemas/LLMSummarizingCondenser-Output" - }, - { - "$ref": "#/components/schemas/NoOpCondenser-Output" + "openhands__sdk__tool__spec__Tool": { + "description": "Defines a tool to be initialized for the agent.\n\nThis is only used in agent-sdk for type schema for server use.", + "properties": { + "name": { + "description": "Name of the tool class, e.g., 'TerminalTool'. Import it from an `openhands.tools.` subpackage.", + "examples": [ + "TerminalTool", + "FileEditorTool", + "TaskTrackerTool" + ], + "title": "Name", + "type": "string" }, - { - "$ref": "#/components/schemas/PipelineCondenser-Output" + "params": { + "additionalProperties": true, + "description": "Parameters for the tool's .create() method, e.g., {'working_dir': '/app'}", + "examples": [ + { + "working_dir": "/workspace" + } + ], + "title": "Params", + "type": "object" } + }, + "required": [ + "name" ], - "discriminator": { - "propertyName": "kind", - "mapping": { - "openhands__sdk__context__condenser__llm_summarizing_condenser__LLMSummarizingCondenser-Output__1": "#/components/schemas/LLMSummarizingCondenser-Output", - "openhands__sdk__context__condenser__no_op_condenser__NoOpCondenser-Output__1": "#/components/schemas/NoOpCondenser-Output", - "openhands__sdk__context__condenser__pipeline_condenser__PipelineCondenser-Output__1": "#/components/schemas/PipelineCondenser-Output" - } - } + "title": "Tool", + "type": "object" }, - "ConfirmRisky-Input": { + "openhands__sdk__tool__tool__ToolAnnotations": { + "description": "Annotations to provide hints about the tool's behavior.\n\nBased on Model Context Protocol (MCP) spec:\nhttps://github.com/modelcontextprotocol/modelcontextprotocol/blob/caf3424488b10b4a7b1f8cb634244a450a1f4400/schema/2025-06-18/schema.ts#L838", "properties": { - "threshold": { - "$ref": "#/components/schemas/SecurityRisk", - "default": "HIGH" + "destructiveHint": { + "default": true, + "description": "If true, the tool may perform destructive updates to its environment. If false, the tool performs only additive updates. (This property is meaningful only when `readOnlyHint == false`) Default: true", + "title": "Destructivehint", + "type": "boolean" }, - "confirm_unknown": { - "type": "boolean", - "title": "Confirm Unknown", - "default": true + "idempotentHint": { + "default": false, + "description": "If true, calling the tool repeatedly with the same arguments will have no additional effect on the its environment. (This property is meaningful only when `readOnlyHint == false`) Default: false", + "title": "Idempotenthint", + "type": "boolean" }, - "kind": { - "type": "string", - "const": "ConfirmRisky", - "title": "Kind" - } - }, - "type": "object", - "title": "ConfirmRisky" - }, - "ConfirmRisky-Output": { - "properties": { - "threshold": { - "$ref": "#/components/schemas/SecurityRisk", - "default": "HIGH" + "openWorldHint": { + "default": true, + "description": "If true, this tool may interact with an 'open world' of external entities. If false, the tool's domain of interaction is closed. For example, the world of a web search tool is open, whereas that of a memory tool is not. Default: true", + "title": "Openworldhint", + "type": "boolean" }, - "confirm_unknown": { - "type": "boolean", - "title": "Confirm Unknown", - "default": true + "readOnlyHint": { + "default": false, + "description": "If true, the tool does not modify its environment. Default: false", + "title": "Readonlyhint", + "type": "boolean" }, - "kind": { - "type": "string", - "const": "ConfirmRisky", - "title": "Kind" + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "A human-readable title for the tool.", + "title": "Title" } }, - "type": "object", - "required": [ - "kind" - ], - "title": "ConfirmRisky" + "title": "openhands.sdk.tool.tool.ToolAnnotations", + "type": "object" + } + }, + "securitySchemes": { + "APIKeyCookie": { + "in": "cookie", + "name": "oh_workspace_session_key", + "type": "apiKey" }, - "ConfirmationPolicyBase-Input": { - "oneOf": [ - { - "$ref": "#/components/schemas/AlwaysConfirm-Input" - }, - { - "$ref": "#/components/schemas/ConfirmRisky-Input" - }, + "APIKeyHeader": { + "in": "header", + "name": "X-Session-API-Key", + "type": "apiKey" + }, + "HTTPBearer": { + "scheme": "bearer", + "type": "http" + } + } + }, + "info": { + "description": "OpenHands Agent Server - REST/WebSocket interface for OpenHands AI Agent", + "title": "OpenHands Agent Server", + "version": "1.52.0" + }, + "openapi": "3.1.0", + "paths": { + "/api/agent-profiles": { + "get": { + "description": "List all stored agent profiles and the active pointer.\n\nOn the first call against an empty store with no active pointer, lazily\nseeds one default profile from the current ``agent_settings`` and activates\nit (the one-time migration that replaces a dedicated seed step).", + "operationId": "list_agent_profiles_api_agent_profiles_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AgentProfileListResponse" + } + } + }, + "description": "Successful Response" + } + }, + "security": [ { - "$ref": "#/components/schemas/NeverConfirm-Input" + "APIKeyHeader": [] } ], - "discriminator": { - "propertyName": "kind", - "mapping": { - "openhands__sdk__security__confirmation_policy__AlwaysConfirm-Input__1": "#/components/schemas/AlwaysConfirm-Input", - "openhands__sdk__security__confirmation_policy__ConfirmRisky-Input__1": "#/components/schemas/ConfirmRisky-Input", - "openhands__sdk__security__confirmation_policy__NeverConfirm-Input__1": "#/components/schemas/NeverConfirm-Input" - } - } - }, - "ConfirmationPolicyBase-Output": { - "oneOf": [ - { - "$ref": "#/components/schemas/AlwaysConfirm-Output" - }, - { - "$ref": "#/components/schemas/ConfirmRisky-Output" - }, + "summary": "List Agent Profiles", + "tags": [ + "Agent Profiles" + ] + } + }, + "/api/agent-profiles/{name}": { + "delete": { + "description": "Delete a stored profile (idempotent).\n\nIf the deleted profile was the active one, ``active_agent_profile_id`` is\ncleared. If ``agent_settings`` is itself left on a non-OpenHands variant,\nit is reset to default OpenHands agent settings so stale ACP configuration\ndoes not outlive the profile it came from; the server-wide ``mcp_config``\nis carried over.", + "operationId": "delete_agent_profile_api_agent_profiles__name__delete", + "parameters": [ { - "$ref": "#/components/schemas/NeverConfirm-Output" + "in": "path", + "name": "name", + "required": true, + "schema": { + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$", + "title": "Name", + "type": "string" + } } ], - "discriminator": { - "propertyName": "kind", - "mapping": { - "openhands__sdk__security__confirmation_policy__AlwaysConfirm-Output__1": "#/components/schemas/AlwaysConfirm-Output", - "openhands__sdk__security__confirmation_policy__ConfirmRisky-Output__1": "#/components/schemas/ConfirmRisky-Output", - "openhands__sdk__security__confirmation_policy__NeverConfirm-Output__1": "#/components/schemas/NeverConfirm-Output" - } - } - }, - "ConfirmationResponseRequest": { - "properties": { - "accept": { - "type": "boolean", - "title": "Accept" + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AgentProfileMutationResponse" + } + } + }, + "description": "Successful Response" }, - "reason": { - "type": "string", - "title": "Reason", - "default": "User rejected the action." + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" } }, - "type": "object", - "required": [ - "accept" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "ConfirmationResponseRequest", - "description": "Payload to accept or reject a pending action." + "summary": "Delete Agent Profile", + "tags": [ + "Agent Profiles" + ] }, - "ConversationErrorEvent": { - "properties": { - "id": { - "type": "string", - "title": "Id", - "description": "Unique event id (ULID/UUID)" - }, - "timestamp": { - "type": "string", - "title": "Timestamp", - "description": "Event timestamp" - }, - "source": { - "type": "string", - "enum": [ - "agent", - "user", - "environment" - ], - "title": "Source", - "description": "The source of this event" - }, - "code": { - "type": "string", - "title": "Code", - "description": "Code for the error - typically a type" - }, - "detail": { - "type": "string", - "title": "Detail", - "description": "Details about the error" + "get": { + "description": "Get a stored profile.\n\nA profile is secret-free at rest (#4017), so there is nothing to mask or\nexpose — unlike the LLM ``/api/profiles`` router, this endpoint has no\n``X-Expose-Secrets`` behavior.", + "operationId": "get_agent_profile_api_agent_profiles__name__get", + "parameters": [ + { + "in": "path", + "name": "name", + "required": true, + "schema": { + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$", + "title": "Name", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AgentProfileDetailResponse" + } + } + }, + "description": "Successful Response" }, - "kind": { - "type": "string", - "const": "ConversationErrorEvent", - "title": "Kind" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" } }, - "additionalProperties": false, - "type": "object", - "required": [ - "source", - "code", - "detail", - "kind" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "ConversationErrorEvent", - "description": "Conversation-level failure that is NOT sent back to the LLM.\n\nThis event is emitted by the conversation runtime when an unexpected\nexception bubbles up and prevents the run loop from continuing. It is\nintended for client applications (e.g., UIs) to present a top-level error\nstate, and for orchestration to react. It is not an observation and it is\nnot LLM-convertible.\n\nDifferences from AgentErrorEvent:\n- Not tied to any tool_name/tool_call_id (AgentErrorEvent is a tool\n observation).\n- Typically source='environment' and the run loop moves to an ERROR state,\n while AgentErrorEvent has source='agent' and the conversation can\n continue." + "summary": "Get Agent Profile", + "tags": [ + "Agent Profiles" + ] }, - "ConversationExecutionStatus": { - "type": "string", - "enum": [ - "idle", - "running", - "paused", - "waiting_for_confirmation", - "finished", - "error", - "stuck", - "deleting" + "post": { + "description": "Save an ``AgentProfile`` under ``name`` (overwriting a namesake).\n\nThe path ``name`` is authoritative — it overrides any ``name`` in the body.\nThe profile is secret-free at rest (#4017), so no cipher/encryption is\ninvolved. Returns 409 if creating a new profile would exceed\n``MAX_AGENT_PROFILES``.", + "operationId": "save_agent_profile_api_agent_profiles__name__post", + "parameters": [ + { + "in": "path", + "name": "name", + "required": true, + "schema": { + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$", + "title": "Name", + "type": "string" + } + } ], - "title": "ConversationExecutionStatus", - "description": "Enum representing the current execution state of the conversation." - }, - "ConversationInfo": { - "properties": { - "id": { - "type": "string", - "format": "uuid", - "title": "Id", - "description": "Unique conversation ID" - }, - "agent": { - "$ref": "#/components/schemas/AgentBase-Output", - "description": "The agent running in the conversation. This is persisted to allow resuming conversations and check agent configuration to handle e.g., tool changes, LLM changes, etc." - }, - "workspace": { - "$ref": "#/components/schemas/BaseWorkspace-Output", - "description": "Workspace used by the agent to execute commands and read/write files. Not the process working directory." - }, - "persistence_dir": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "requestBody": { + "content": { + "application/json": { + "schema": { + "additionalProperties": true, + "title": "Body", + "type": "object" } - ], - "title": "Persistence Dir", - "description": "Directory for persisting conversation state and events. If None, conversation will not be persisted.", - "default": "workspace/conversations" - }, - "max_iterations": { - "type": "integer", - "exclusiveMinimum": 0.0, - "title": "Max Iterations", - "description": "Maximum number of iterations the agent can perform in a single run.", - "default": 500 - }, - "stuck_detection": { - "type": "boolean", - "title": "Stuck Detection", - "description": "Whether to enable stuck detection for the agent.", - "default": true - }, - "execution_status": { - "$ref": "#/components/schemas/ConversationExecutionStatus", - "default": "idle" - }, - "confirmation_policy": { - "$ref": "#/components/schemas/ConfirmationPolicyBase-Output", - "default": { - "kind": "NeverConfirm" } }, - "security_analyzer": { - "anyOf": [ - { - "$ref": "#/components/schemas/SecurityAnalyzerBase-Output" - }, - { - "type": "null" + "required": true + }, + "responses": { + "201": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AgentProfileMutationResponse" + } } - ], - "description": "Optional security analyzer to evaluate action risks." - }, - "activated_knowledge_skills": { - "items": { - "type": "string" }, - "type": "array", - "title": "Activated Knowledge Skills", - "description": "List of activated knowledge skills name" + "description": "Successful Response" }, - "blocked_actions": { - "additionalProperties": { - "type": "string" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } }, - "type": "object", - "title": "Blocked Actions", - "description": "Actions blocked by PreToolUse hooks, keyed by action ID" - }, - "blocked_messages": { - "additionalProperties": { + "description": "Validation Error" + } + }, + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Save Agent Profile", + "tags": [ + "Agent Profiles" + ] + } + }, + "/api/agent-profiles/{name}/materialize": { + "post": { + "description": "Preview the launch of a profile; return a diagnostics report.\n\nPreviews the stored profile ``name``, or ``body.profile`` when given (so an\neditor can preview before saving), with the same resolve and finalize as a\nlaunch, against the runtime this server launches into. Dangling references\nare reported in the body (valid=False) rather than raising — the only error\nstatuses are 404 (unknown stored profile) and 422 (invalid draft).\nresolved_settings is redacted (no raw secrets).", + "operationId": "materialize_agent_profile_api_agent_profiles__name__materialize_post", + "parameters": [ + { + "in": "path", + "name": "name", + "required": true, + "schema": { + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$", + "title": "Name", "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/MaterializeAgentProfileRequest" + }, + { + "type": "null" + } + ], + "title": "Body" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AgentProfileDiagnostics" + } + } }, - "type": "object", - "title": "Blocked Messages", - "description": "Messages blocked by UserPromptSubmit hooks, keyed by message ID" - }, - "stats": { - "$ref": "#/components/schemas/ConversationStats-Output", - "description": "Conversation statistics for tracking LLM metrics" - }, - "secret_registry": { - "$ref": "#/components/schemas/SecretRegistry-Output", - "description": "Registry for handling secrets and sensitive data" + "description": "Successful Response" }, - "agent_state": { - "additionalProperties": true, - "type": "object", - "title": "Agent State", - "description": "Dictionary for agent-specific runtime state that persists across iterations. Agents can store feature-specific state using string keys. To trigger autosave, always reassign: state.agent_state = {**state.agent_state, key: value}. See https://docs.openhands.dev/sdk/guides/convo-persistence#how-state-persistence-works" - }, - "title": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "title": "Title", - "description": "User-defined title for the conversation" - }, - "metrics": { - "anyOf": [ - { - "$ref": "#/components/schemas/MetricsSnapshot" - }, - { - "type": "null" + }, + "description": "Validation Error" + } + }, + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Materialize Agent Profile", + "tags": [ + "Agent Profiles" + ] + } + }, + "/api/agent-profiles/{name}/rename": { + "post": { + "description": "Rename a stored profile atomically.\n\nThe stable ``id`` is preserved, so an active pointer (keyed on ``id``)\nsurvives the rename untouched. Returns 404 if the source is missing, 409 if\n``new_name`` is taken.", + "operationId": "rename_agent_profile_api_agent_profiles__name__rename_post", + "parameters": [ + { + "in": "path", + "name": "name", + "required": true, + "schema": { + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$", + "title": "Name", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RenameAgentProfileRequest" } - ] + } }, - "created_at": { - "type": "string", - "format": "date-time", - "title": "Created At" + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AgentProfileMutationResponse" + } + } + }, + "description": "Successful Response" }, - "updated_at": { - "type": "string", - "format": "date-time", - "title": "Updated At" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Rename Agent Profile", + "tags": [ + "Agent Profiles" + ] + } + }, + "/api/agent-profiles/{profile_id}/activate": { + "post": { + "description": "Activate a profile by its stable ``id`` — pointer only.\n\nSets ``active_agent_profile_id`` and nothing else: unlike the LLM\n``/activate``, this does **not** write ``agent_settings`` (the\ncreation-time-only contract). Returns 404 if no stored profile has that id.", + "operationId": "activate_agent_profile_api_agent_profiles__profile_id__activate_post", + "parameters": [ + { + "in": "path", + "name": "profile_id", + "required": true, + "schema": { + "maxLength": 128, + "minLength": 1, + "title": "Profile Id", + "type": "string" + } } - }, - "type": "object", - "required": [ - "id", - "agent", - "workspace" ], - "title": "ConversationInfo", - "description": "Information about a conversation running locally without a Runtime sandbox." - }, - "ConversationPage": { - "properties": { - "items": { - "items": { - "$ref": "#/components/schemas/ConversationInfo" + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ActivateAgentProfileResponse" + } + } }, - "type": "array", - "title": "Items" + "description": "Successful Response" }, - "next_page_id": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "title": "Next Page Id" + }, + "description": "Validation Error" } }, - "type": "object", - "required": [ - "items" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "ConversationPage" - }, - "ConversationSortOrder": { - "type": "string", - "enum": [ - "CREATED_AT", - "UPDATED_AT", - "CREATED_AT_DESC", - "UPDATED_AT_DESC" + "summary": "Activate Agent Profile", + "tags": [ + "Agent Profiles" + ] + } + }, + "/api/auth/workspace-session": { + "delete": { + "description": "Clear the workspace session cookie.\n\nBrowsers identify cookies by ``(name, domain, path)``; the deletion\ncookie must therefore share the original cookie's attributes. We\noverwrite with an empty value and ``max_age=0`` so the browser drops\nit immediately.", + "operationId": "delete_workspace_session_api_auth_workspace_session_delete", + "responses": { + "204": { + "description": "Cookie cleared" + } + }, + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "ConversationSortOrder", - "description": "Enum for conversation sorting options." + "summary": "Delete Workspace Session", + "tags": [ + "Auth" + ] }, - "ConversationStateUpdateEvent": { - "properties": { - "id": { - "type": "string", - "title": "Id", - "description": "Unique event id (ULID/UUID)" - }, - "timestamp": { - "type": "string", - "title": "Timestamp", - "description": "Event timestamp" - }, - "source": { - "type": "string", - "enum": [ - "agent", - "user", - "environment" - ], - "title": "Source", - "default": "environment" + "post": { + "description": "Mint a workspace-scoped session cookie.\n\nCaller must already be authenticated by the ``X-Session-API-Key``\nheader (enforced by the parent router's dependency). The cookie value\nis the validated session API key itself; it is HttpOnly so JS in\nworkspace HTML cannot read it back.", + "operationId": "create_workspace_session_api_auth_workspace_session_post", + "responses": { + "204": { + "description": "Cookie set" }, - "key": { - "type": "string", - "title": "Key", - "description": "Unique key for this state update event" + "401": { + "description": "Missing or invalid X-Session-API-Key header" + } + }, + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Create Workspace Session", + "tags": [ + "Auth" + ] + } + }, + "/api/bash/bash_commands/{command_id}/stop": { + "post": { + "description": "Stop a running bash command by id without touching the others.\n\nIdempotent: stopping an already-finished command succeeds, while an\nunknown command id reports not-found so the caller can treat it as\nan already-cancelled stop.", + "operationId": "stop_bash_command_api_bash_bash_commands__command_id__stop_post", + "parameters": [ + { + "in": "path", + "name": "command_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Command Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } + } + }, + "description": "Successful Response" }, - "value": { - "title": "Value", - "description": "Serialized conversation state updates" + "404": { + "description": "Item not found" }, - "kind": { - "type": "string", - "const": "ConversationStateUpdateEvent", - "title": "Kind" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" } }, - "additionalProperties": false, - "type": "object", - "required": [ - "kind" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "ConversationStateUpdateEvent", - "description": "Event that contains conversation state updates.\n\nThis event is sent via websocket whenever the conversation state changes,\nallowing remote clients to stay in sync without making REST API calls.\n\nAll fields are serialized versions of the corresponding ConversationState fields\nto ensure compatibility with websocket transmission." - }, - "ConversationStats-Input": { - "properties": { - "usage_to_metrics": { - "additionalProperties": { - "$ref": "#/components/schemas/Metrics" + "summary": "Stop Bash Command", + "tags": [ + "Bash" + ] + } + }, + "/api/bash/bash_events": { + "delete": { + "description": "Clear all bash events from storage", + "operationId": "clear_all_bash_events_api_bash_bash_events_delete", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "additionalProperties": { + "type": "integer" + }, + "title": "Response Clear All Bash Events Api Bash Bash Events Delete", + "type": "object" + } + } }, - "type": "object", - "title": "Usage To Metrics", - "description": "Active usage metrics tracked by the registry." + "description": "Successful Response" } }, - "type": "object", - "title": "ConversationStats", - "description": "Track per-LLM usage metrics observed during conversations." - }, - "ConversationStats-Output": { - "additionalProperties": true, - "type": "object" - }, - "Cost": { - "properties": { - "model": { - "type": "string", - "title": "Model" + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Clear All Bash Events", + "tags": [ + "Bash" + ] + } + }, + "/api/bash/bash_events/": { + "get": { + "description": "Get a batch of bash event events given their ids, returning null for any\nmissing item.", + "operationId": "batch_get_bash_events_api_bash_bash_events__get", + "requestBody": { + "content": { + "application/json": { + "schema": { + "items": { + "type": "string" + }, + "title": "Event Ids", + "type": "array" + } + } }, - "cost": { - "type": "number", - "minimum": 0.0, - "title": "Cost", - "description": "Cost must be non-negative" + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/BashEventBase" + }, + { + "type": "null" + } + ] + }, + "title": "Response Batch Get Bash Events Api Bash Bash Events Get", + "type": "array" + } + } + }, + "description": "Successful Response" }, - "timestamp": { - "type": "number", - "title": "Timestamp" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" } }, - "type": "object", - "required": [ - "model", - "cost" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "Cost" - }, - "CriticBase-Input": { - "oneOf": [ + "summary": "Batch Get Bash Events", + "tags": [ + "Bash" + ] + } + }, + "/api/bash/bash_events/search": { + "get": { + "description": "Search / List bash event events", + "operationId": "search_bash_events_api_bash_bash_events_search_get", + "parameters": [ { - "$ref": "#/components/schemas/AgentFinishedCritic-Input" + "in": "query", + "name": "kind__eq", + "required": false, + "schema": { + "anyOf": [ + { + "enum": [ + "BashCommand", + "BashOutput" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Kind Eq" + } + }, + { + "in": "query", + "name": "command_id__eq", + "required": false, + "schema": { + "anyOf": [ + { + "format": "uuid", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Command Id Eq" + } }, { - "$ref": "#/components/schemas/APIBasedCritic-Input" + "in": "query", + "name": "timestamp__gte", + "required": false, + "schema": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Timestamp Gte" + } }, { - "$ref": "#/components/schemas/EmptyPatchCritic-Input" + "in": "query", + "name": "timestamp__lt", + "required": false, + "schema": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Timestamp Lt" + } }, { - "$ref": "#/components/schemas/PassCritic-Input" - } - ], - "discriminator": { - "propertyName": "kind", - "mapping": { - "openhands__sdk__critic__impl__agent_finished__AgentFinishedCritic-Input__1": "#/components/schemas/AgentFinishedCritic-Input", - "openhands__sdk__critic__impl__api__critic__APIBasedCritic-Input__1": "#/components/schemas/APIBasedCritic-Input", - "openhands__sdk__critic__impl__empty_patch__EmptyPatchCritic-Input__1": "#/components/schemas/EmptyPatchCritic-Input", - "openhands__sdk__critic__impl__pass_critic__PassCritic-Input__1": "#/components/schemas/PassCritic-Input" - } - } - }, - "CriticBase-Output": { - "oneOf": [ - { - "$ref": "#/components/schemas/AgentFinishedCritic-Output" + "description": "Only returns BashOutput events with order > this value. Useful for polling to fetch only new events since the last poll.", + "in": "query", + "name": "order__gt", + "required": false, + "schema": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Only returns BashOutput events with order > this value. Useful for polling to fetch only new events since the last poll.", + "title": "Filter to events with order greater than this value" + } }, { - "$ref": "#/components/schemas/APIBasedCritic-Output" + "in": "query", + "name": "sort_order", + "required": false, + "schema": { + "$ref": "#/components/schemas/BashEventSortOrder", + "default": "TIMESTAMP" + } }, { - "$ref": "#/components/schemas/EmptyPatchCritic-Output" + "in": "query", + "name": "page_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Optional next_page_id from the previously returned page" + } }, { - "$ref": "#/components/schemas/PassCritic-Output" + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 100, + "exclusiveMinimum": 0, + "maximum": 100, + "title": "The max number of results in the page", + "type": "integer" + } } ], - "discriminator": { - "propertyName": "kind", - "mapping": { - "openhands__sdk__critic__impl__agent_finished__AgentFinishedCritic-Output__1": "#/components/schemas/AgentFinishedCritic-Output", - "openhands__sdk__critic__impl__api__critic__APIBasedCritic-Output__1": "#/components/schemas/APIBasedCritic-Output", - "openhands__sdk__critic__impl__empty_patch__EmptyPatchCritic-Output__1": "#/components/schemas/EmptyPatchCritic-Output", - "openhands__sdk__critic__impl__pass_critic__PassCritic-Output__1": "#/components/schemas/PassCritic-Output" - } - } - }, - "CriticResult": { - "properties": { - "score": { - "type": "number", - "maximum": 1.0, - "minimum": 0.0, - "title": "Score", - "description": "A predicted probability of success between 0 and 1." - }, - "message": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BashEventPage" + } } - ], - "title": "Message", - "description": "An optional message explaining the score." + }, + "description": "Successful Response" }, - "metadata": { - "anyOf": [ - { - "additionalProperties": true, - "type": "object" - }, - { - "type": "null" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "title": "Metadata", - "description": "Optional metadata about the critic evaluation. Can include event_ids and categorized_features for visualization." + }, + "description": "Validation Error" } }, - "type": "object", - "required": [ - "score", - "message" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "CriticResult", - "description": "A critic result is a score and a message." - }, - "DesktopUrlResponse": { - "properties": { - "url": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Url" + "summary": "Search Bash Events", + "tags": [ + "Bash" + ] + } + }, + "/api/bash/bash_events/{event_id}": { + "get": { + "description": "Get a bash event event given an id", + "operationId": "get_bash_event_api_bash_bash_events__event_id__get", + "parameters": [ + { + "in": "path", + "name": "event_id", + "required": true, + "schema": { + "title": "Event Id", + "type": "string" + } } - }, - "type": "object", - "required": [ - "url" ], - "title": "DesktopUrlResponse", - "description": "Response model for Desktop URL." - }, - "EditAction": { - "properties": { - "file_path": { - "type": "string", - "title": "File Path", - "description": "The path to the file to modify." + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BashEventBase" + } + } + }, + "description": "Successful Response" }, - "old_string": { - "type": "string", - "title": "Old String", - "description": "The text to replace. To create a new file, use an empty string. Must match the exact text in the file including whitespace." + "404": { + "description": "Item not found" }, - "new_string": { - "type": "string", - "title": "New String", - "description": "The text to replace it with." + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Get Bash Event", + "tags": [ + "Bash" + ] + } + }, + "/api/bash/execute_bash_command": { + "post": { + "description": "Execute a bash command and wait for a result", + "operationId": "execute_bash_command_api_bash_execute_bash_command_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ExecuteBashRequest" + } + } }, - "expected_replacements": { - "type": "integer", - "minimum": 0.0, - "title": "Expected Replacements", - "description": "Number of replacements expected. Defaults to 1. Use when you want to replace multiple occurrences. The edit will fail if the actual count doesn't match.", - "default": 1 + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BashOutput" + } + } + }, + "description": "Successful Response" }, - "kind": { - "type": "string", - "const": "EditAction", - "title": "Kind" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" } }, - "additionalProperties": false, - "type": "object", - "required": [ - "file_path", - "old_string", - "new_string", - "kind" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "EditAction", - "description": "Schema for edit operation." - }, - "EditObservation": { - "properties": { + "summary": "Execute Bash Command", + "tags": [ + "Bash" + ] + } + }, + "/api/bash/start_bash_command": { + "post": { + "description": "Execute a bash command in the background", + "operationId": "start_bash_command_api_bash_start_bash_command_post", + "requestBody": { "content": { - "items": { - "anyOf": [ - { - "$ref": "#/components/schemas/TextContent" - }, - { - "$ref": "#/components/schemas/ImageContent" - } - ] - }, - "type": "array", - "title": "Content", - "description": "Content returned from the tool as a list of TextContent/ImageContent objects. When there is an error, it should be written in this field." - }, - "is_error": { - "type": "boolean", - "title": "Is Error", - "description": "Whether the observation indicates an error", - "default": false - }, - "file_path": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "application/json": { + "schema": { + "$ref": "#/components/schemas/ExecuteBashRequest" } - ], - "title": "File Path", - "description": "The file path that was edited." - }, - "is_new_file": { - "type": "boolean", - "title": "Is New File", - "description": "Whether a new file was created.", - "default": false - }, - "replacements_made": { - "type": "integer", - "title": "Replacements Made", - "description": "Number of replacements actually made.", - "default": 0 + } }, - "old_content": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BashCommand" + } } - ], - "title": "Old Content", - "description": "The content before the edit." + }, + "description": "Successful Response" }, - "new_content": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "title": "New Content", - "description": "The content after the edit." - }, - "kind": { - "type": "string", - "const": "EditObservation", - "title": "Kind" + }, + "description": "Validation Error" } }, - "additionalProperties": false, - "type": "object", - "required": [ - "kind" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "EditObservation", - "description": "Observation from editing a file." - }, - "EditTool": { - "properties": { - "description": { - "type": "string", - "title": "Description" - }, - "action_type": { - "type": "string", - "title": "Action Type" - }, - "observation_type": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "summary": "Start Bash Command", + "tags": [ + "Bash" + ] + } + }, + "/api/canvas-extensions/install": { + "post": { + "description": "Install a canvas extension from a git URL, GitHub shorthand, or local\npath.\n\nA fresh install always lands disabled, regardless of the request body --\nthere is no ``enabled`` field to smuggle a different state through.", + "operationId": "install_canvas_extension_endpoint_api_canvas_extensions_install_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InstallCanvasExtensionRequest" } - ], - "title": "Observation Type" + } }, - "annotations": { - "anyOf": [ - { - "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" - }, - { - "type": "null" + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InstalledCanvasExtensionResponse" + } } - ] + }, + "description": "Successful Response" }, - "meta": { - "anyOf": [ - { - "additionalProperties": true, - "type": "object" - }, - { - "type": "null" - } - ], - "title": "Meta" + "400": { + "description": "Could not read canvas extension source" }, - "kind": { - "type": "string", - "const": "EditTool", - "title": "Kind" + "409": { + "description": "Canvas extension already installed (use force=true)" }, - "title": { - "type": "string", - "title": "Title", - "readOnly": true + "422": { + "description": "Invalid canvas extension (bad manifest, etc.)" } }, - "type": "object", - "required": [ - "description", - "action_type", - "kind", - "title" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "EditTool", - "description": "Tool for editing files via find/replace." - }, - "EmptyPatchCritic-Input": { - "properties": { - "mode": { - "type": "string", - "enum": [ - "finish_and_message", - "all_actions" - ], - "title": "Mode", - "description": "When to run critic evaluation:\n- 'finish_and_message': Evaluate on FinishAction and agent MessageEvent (default, minimal performance impact)\n- 'all_actions': Evaluate after every agent action (WARNING: significantly slower due to API calls on each action)", - "default": "finish_and_message" - }, - "iterative_refinement": { - "anyOf": [ - { - "$ref": "#/components/schemas/IterativeRefinementConfig" - }, - { - "type": "null" + "summary": "Install Canvas Extension Endpoint", + "tags": [ + "Canvas Extensions" + ] + } + }, + "/api/canvas-extensions/installed": { + "get": { + "description": "List all installed canvas extensions (enabled and disabled).", + "operationId": "list_installed_canvas_extensions_endpoint_api_canvas_extensions_installed_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InstalledCanvasExtensionsListResponse" + } } - ], - "description": "Optional configuration for iterative refinement. When set, Conversation.run() will automatically retry the task if the critic score is below the success_threshold, up to max_iterations." - }, - "kind": { - "type": "string", - "const": "EmptyPatchCritic", - "title": "Kind" + }, + "description": "Successful Response" } }, - "type": "object", - "title": "EmptyPatchCritic", - "description": "Critic that only evaluates whether a git patch is non-empty.\n\nThis critic checks only one criterion:\n- The generated git patch is non-empty (actual changes were made)\n\nUnlike AgentFinishedCritic, this critic does not check for proper\nagent completion with FinishAction." - }, - "EmptyPatchCritic-Output": { - "properties": { - "mode": { - "type": "string", - "enum": [ - "finish_and_message", - "all_actions" - ], - "title": "Mode", - "description": "When to run critic evaluation:\n- 'finish_and_message': Evaluate on FinishAction and agent MessageEvent (default, minimal performance impact)\n- 'all_actions': Evaluate after every agent action (WARNING: significantly slower due to API calls on each action)", - "default": "finish_and_message" - }, - "iterative_refinement": { - "anyOf": [ - { - "$ref": "#/components/schemas/IterativeRefinementConfig" - }, - { - "type": "null" + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "List Installed Canvas Extensions Endpoint", + "tags": [ + "Canvas Extensions" + ] + } + }, + "/api/canvas-extensions/installed/{extension_name}": { + "delete": { + "description": "Uninstall a canvas extension by name while retaining backend data.", + "operationId": "uninstall_canvas_extension_endpoint_api_canvas_extensions_installed__extension_name__delete", + "parameters": [ + { + "description": "Canvas extension name (lowercase alphanumeric, hyphens)", + "in": "path", + "name": "extension_name", + "required": true, + "schema": { + "description": "Canvas extension name (lowercase alphanumeric, hyphens)", + "maxLength": 255, + "minLength": 1, + "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$", + "title": "Extension Name", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UninstallCanvasExtensionResponse" + } } - ], - "description": "Optional configuration for iterative refinement. When set, Conversation.run() will automatically retry the task if the critic score is below the success_threshold, up to max_iterations." + }, + "description": "Successful Response" }, - "kind": { - "type": "string", - "const": "EmptyPatchCritic", - "title": "Kind" + "404": { + "description": "Canvas extension not installed" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" } }, - "type": "object", - "required": [ - "kind" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "EmptyPatchCritic", - "description": "Critic that only evaluates whether a git patch is non-empty.\n\nThis critic checks only one criterion:\n- The generated git patch is non-empty (actual changes were made)\n\nUnlike AgentFinishedCritic, this critic does not check for proper\nagent completion with FinishAction." + "summary": "Uninstall Canvas Extension Endpoint", + "tags": [ + "Canvas Extensions" + ] }, - "Event": { - "oneOf": [ - { - "$ref": "#/components/schemas/Condensation" - }, - { - "$ref": "#/components/schemas/CondensationRequest" - }, - { - "$ref": "#/components/schemas/CondensationSummaryEvent" - }, - { - "$ref": "#/components/schemas/ConversationErrorEvent" - }, - { - "$ref": "#/components/schemas/ConversationStateUpdateEvent" - }, - { - "$ref": "#/components/schemas/LLMCompletionLogEvent" - }, - { - "$ref": "#/components/schemas/ActionEvent" - }, + "get": { + "description": "Get information about a specific installed canvas extension.", + "operationId": "get_installed_canvas_extension_endpoint_api_canvas_extensions_installed__extension_name__get", + "parameters": [ { - "$ref": "#/components/schemas/MessageEvent" + "description": "Canvas extension name (lowercase alphanumeric, hyphens)", + "in": "path", + "name": "extension_name", + "required": true, + "schema": { + "description": "Canvas extension name (lowercase alphanumeric, hyphens)", + "maxLength": 255, + "minLength": 1, + "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$", + "title": "Extension Name", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InstalledCanvasExtensionResponse" + } + } + }, + "description": "Successful Response" }, - { - "$ref": "#/components/schemas/AgentErrorEvent" + "404": { + "description": "Canvas extension not installed" }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "security": [ { - "$ref": "#/components/schemas/ObservationEvent" - }, + "APIKeyHeader": [] + } + ], + "summary": "Get Installed Canvas Extension Endpoint", + "tags": [ + "Canvas Extensions" + ] + }, + "patch": { + "description": "Enable or disable an installed canvas extension.", + "operationId": "set_canvas_extension_enabled_endpoint_api_canvas_extensions_installed__extension_name__patch", + "parameters": [ { - "$ref": "#/components/schemas/UserRejectObservation" + "description": "Canvas extension name (lowercase alphanumeric, hyphens)", + "in": "path", + "name": "extension_name", + "required": true, + "schema": { + "description": "Canvas extension name (lowercase alphanumeric, hyphens)", + "maxLength": 255, + "minLength": 1, + "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$", + "title": "Extension Name", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateCanvasExtensionStateRequest" + } + } }, - { - "$ref": "#/components/schemas/SystemPromptEvent" + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateCanvasExtensionStateResponse" + } + } + }, + "description": "Successful Response" }, - { - "$ref": "#/components/schemas/TokenEvent" + "404": { + "description": "Canvas extension not installed" }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "security": [ { - "$ref": "#/components/schemas/PauseEvent" + "APIKeyHeader": [] } ], - "discriminator": { - "propertyName": "kind", - "mapping": { - "openhands__sdk__event__condenser__Condensation-Output__1": "#/components/schemas/Condensation", - "openhands__sdk__event__condenser__CondensationRequest-Output__1": "#/components/schemas/CondensationRequest", - "openhands__sdk__event__condenser__CondensationSummaryEvent-Output__1": "#/components/schemas/CondensationSummaryEvent", - "openhands__sdk__event__conversation_error__ConversationErrorEvent-Output__1": "#/components/schemas/ConversationErrorEvent", - "openhands__sdk__event__conversation_state__ConversationStateUpdateEvent-Output__1": "#/components/schemas/ConversationStateUpdateEvent", - "openhands__sdk__event__llm_completion_log__LLMCompletionLogEvent-Output__1": "#/components/schemas/LLMCompletionLogEvent", - "openhands__sdk__event__llm_convertible__action__ActionEvent-Output__1": "#/components/schemas/ActionEvent", - "openhands__sdk__event__llm_convertible__message__MessageEvent-Output__1": "#/components/schemas/MessageEvent", - "openhands__sdk__event__llm_convertible__observation__AgentErrorEvent-Output__1": "#/components/schemas/AgentErrorEvent", - "openhands__sdk__event__llm_convertible__observation__ObservationEvent-Output__1": "#/components/schemas/ObservationEvent", - "openhands__sdk__event__llm_convertible__observation__UserRejectObservation-Output__1": "#/components/schemas/UserRejectObservation", - "openhands__sdk__event__llm_convertible__system__SystemPromptEvent-Output__1": "#/components/schemas/SystemPromptEvent", - "openhands__sdk__event__token__TokenEvent-Output__1": "#/components/schemas/TokenEvent", - "openhands__sdk__event__user_action__PauseEvent-Output__1": "#/components/schemas/PauseEvent" + "summary": "Set Canvas Extension Enabled Endpoint", + "tags": [ + "Canvas Extensions" + ] + } + }, + "/api/canvas-extensions/installed/{extension_name}/backend": { + "get": { + "description": "Probe the optional backend lifecycle state.", + "operationId": "get_canvas_extension_backend_status_endpoint_api_canvas_extensions_installed__extension_name__backend_get", + "parameters": [ + { + "description": "Canvas extension name (lowercase alphanumeric, hyphens)", + "in": "path", + "name": "extension_name", + "required": true, + "schema": { + "description": "Canvas extension name (lowercase alphanumeric, hyphens)", + "maxLength": 255, + "minLength": 1, + "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$", + "title": "Extension Name", + "type": "string" + } } - } - }, - "EventPage": { - "properties": { - "items": { - "items": { - "$ref": "#/components/schemas/Event" + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BackendStatus" + } + } }, - "type": "array", - "title": "Items" + "description": "Successful Response" }, - "next_page_id": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "title": "Next Page Id" + }, + "description": "Validation Error" } }, - "type": "object", - "required": [ - "items" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "EventPage" - }, - "EventSortOrder": { - "type": "string", - "enum": [ - "TIMESTAMP", - "TIMESTAMP_DESC" + "summary": "Get Canvas Extension Backend Status Endpoint", + "tags": [ + "Canvas Extensions" + ] + } + }, + "/api/canvas-extensions/installed/{extension_name}/backend/data": { + "delete": { + "description": "Delete mutable backend data separately from app uninstall.", + "operationId": "delete_canvas_extension_backend_data_endpoint_api_canvas_extensions_installed__extension_name__backend_data_delete", + "parameters": [ + { + "description": "Canvas extension name (lowercase alphanumeric, hyphens)", + "in": "path", + "name": "extension_name", + "required": true, + "schema": { + "description": "Canvas extension name (lowercase alphanumeric, hyphens)", + "maxLength": 255, + "minLength": 1, + "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$", + "title": "Extension Name", + "type": "string" + } + } ], - "title": "EventSortOrder", - "description": "Enum for event sorting options." - }, - "ExecuteBashRequest": { - "properties": { - "command": { - "type": "string", - "title": "Command", - "description": "The bash command to execute" + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BackendStatus" + } + } + }, + "description": "Successful Response" }, - "cwd": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "409": { + "description": "Backend must be stopped first" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "title": "Cwd", - "description": "The current working directory" + }, + "description": "Validation Error" + } + }, + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Delete Canvas Extension Backend Data Endpoint", + "tags": [ + "Canvas Extensions" + ] + } + }, + "/api/canvas-extensions/installed/{extension_name}/backend/logs": { + "get": { + "description": "Return bounded combined stdout and stderr from the owned process.", + "operationId": "get_canvas_extension_backend_logs_endpoint_api_canvas_extensions_installed__extension_name__backend_logs_get", + "parameters": [ + { + "description": "Canvas extension name (lowercase alphanumeric, hyphens)", + "in": "path", + "name": "extension_name", + "required": true, + "schema": { + "description": "Canvas extension name (lowercase alphanumeric, hyphens)", + "maxLength": 255, + "minLength": 1, + "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$", + "title": "Extension Name", + "type": "string" + } }, - "timeout": { - "type": "integer", - "title": "Timeout", - "description": "The max number of seconds a command may be permitted to run.", - "default": 300 + { + "in": "query", + "name": "limit_bytes", + "required": false, + "schema": { + "default": 65536, + "maximum": 262144, + "minimum": 1, + "title": "Limit Bytes", + "type": "integer" + } } - }, - "type": "object", - "required": [ - "command" ], - "title": "ExecuteBashRequest" - }, - "ExposedUrl": { - "properties": { - "name": { - "type": "string", - "title": "Name" - }, - "url": { - "type": "string", - "title": "Url" + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BackendLogs" + } + } + }, + "description": "Successful Response" }, - "port": { - "type": "integer", - "title": "Port" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" } }, - "type": "object", - "required": [ - "name", - "url", - "port" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "ExposedUrl", - "description": "Represents an exposed URL from the sandbox." - }, - "FileEditorAction": { - "properties": { - "command": { - "type": "string", - "enum": [ - "view", - "create", - "str_replace", - "insert", - "undo_edit" - ], - "title": "Command", - "description": "The commands to run. Allowed options are: `view`, `create`, `str_replace`, `insert`, `undo_edit`." - }, - "path": { - "type": "string", - "title": "Path", - "description": "Absolute path to file or directory." - }, - "file_text": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "File Text", - "description": "Required parameter of `create` command, with the content of the file to be created." - }, - "old_str": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "summary": "Get Canvas Extension Backend Logs Endpoint", + "tags": [ + "Canvas Extensions" + ] + } + }, + "/api/canvas-extensions/installed/{extension_name}/backend/prepare": { + "post": { + "description": "Verify and prepare the immutable artifact for an exact revision.", + "operationId": "prepare_canvas_extension_backend_endpoint_api_canvas_extensions_installed__extension_name__backend_prepare_post", + "parameters": [ + { + "description": "Canvas extension name (lowercase alphanumeric, hyphens)", + "in": "path", + "name": "extension_name", + "required": true, + "schema": { + "description": "Canvas extension name (lowercase alphanumeric, hyphens)", + "maxLength": 255, + "minLength": 1, + "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$", + "title": "Extension Name", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BackendRevisionRequest" } - ], - "title": "Old Str", - "description": "Required parameter of `str_replace` command containing the string in `path` to replace." + } }, - "new_str": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BackendStatus" + } } - ], - "title": "New Str", - "description": "Optional parameter of `str_replace` command containing the new string (if not given, no string will be added). Required parameter of `insert` command containing the string to insert." + }, + "description": "Successful Response" }, - "insert_line": { - "anyOf": [ - { - "type": "integer", - "minimum": 0.0 - }, - { - "type": "null" - } - ], - "title": "Insert Line", - "description": "Required parameter of `insert` command. The `new_str` will be inserted AFTER the line `insert_line` of `path`." + "409": { + "description": "Revision or checksum approval conflict" }, - "view_range": { - "anyOf": [ - { - "items": { - "type": "integer" - }, - "type": "array" - }, - { - "type": "null" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "title": "View Range", - "description": "Optional parameter of `view` command when `path` points to a file. If none is given, the full file is shown. If provided, the file will be shown in the indicated line number range, e.g. [11, 12] will show lines 11 and 12. Indexing at 1 to start. Setting `[start_line, -1]` shows all lines from `start_line` to the end of the file." - }, - "kind": { - "type": "string", - "const": "FileEditorAction", - "title": "Kind" + }, + "description": "Validation Error" } }, - "additionalProperties": false, - "type": "object", - "required": [ - "command", - "path", - "kind" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "FileEditorAction", - "description": "Schema for file editor operations." - }, - "FileEditorObservation": { - "properties": { + "summary": "Prepare Canvas Extension Backend Endpoint", + "tags": [ + "Canvas Extensions" + ] + } + }, + "/api/canvas-extensions/installed/{extension_name}/backend/start": { + "post": { + "description": "Start only a previously prepared exact backend revision.", + "operationId": "start_canvas_extension_backend_endpoint_api_canvas_extensions_installed__extension_name__backend_start_post", + "parameters": [ + { + "description": "Canvas extension name (lowercase alphanumeric, hyphens)", + "in": "path", + "name": "extension_name", + "required": true, + "schema": { + "description": "Canvas extension name (lowercase alphanumeric, hyphens)", + "maxLength": 255, + "minLength": 1, + "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$", + "title": "Extension Name", + "type": "string" + } + } + ], + "requestBody": { "content": { - "items": { - "anyOf": [ - { - "$ref": "#/components/schemas/TextContent" - }, - { - "$ref": "#/components/schemas/ImageContent" + "application/json": { + "schema": { + "$ref": "#/components/schemas/BackendRevisionRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BackendStatus" } - ] + } }, - "type": "array", - "title": "Content", - "description": "Content returned from the tool as a list of TextContent/ImageContent objects. When there is an error, it should be written in this field." - }, - "is_error": { - "type": "boolean", - "title": "Is Error", - "description": "Whether the observation indicates an error", - "default": false + "description": "Successful Response" }, - "command": { - "type": "string", - "enum": [ - "view", - "create", - "str_replace", - "insert", - "undo_edit" - ], - "title": "Command", - "description": "The command that was run: `view`, `create`, `str_replace`, `insert`, or `undo_edit`." + "409": { + "description": "Revision is not prepared or cannot start" }, - "path": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "title": "Path", - "description": "The file path that was edited." - }, - "prev_exist": { - "type": "boolean", - "title": "Prev Exist", - "description": "Indicates if the file previously existed. If not, it was created.", - "default": true - }, - "old_content": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + }, + "description": "Validation Error" + } + }, + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Start Canvas Extension Backend Endpoint", + "tags": [ + "Canvas Extensions" + ] + } + }, + "/api/canvas-extensions/installed/{extension_name}/backend/stop": { + "post": { + "description": "Stop the backend's owned process group idempotently.", + "operationId": "stop_canvas_extension_backend_endpoint_api_canvas_extensions_installed__extension_name__backend_stop_post", + "parameters": [ + { + "description": "Canvas extension name (lowercase alphanumeric, hyphens)", + "in": "path", + "name": "extension_name", + "required": true, + "schema": { + "description": "Canvas extension name (lowercase alphanumeric, hyphens)", + "maxLength": 255, + "minLength": 1, + "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$", + "title": "Extension Name", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BackendStatus" + } } - ], - "title": "Old Content", - "description": "The content of the file before the edit." + }, + "description": "Successful Response" }, - "new_content": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "title": "New Content", - "description": "The content of the file after the edit." - }, - "kind": { - "type": "string", - "const": "FileEditorObservation", - "title": "Kind" + }, + "description": "Validation Error" } }, - "additionalProperties": false, - "type": "object", - "required": [ - "command", - "kind" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "FileEditorObservation", - "description": "A ToolResult that can be rendered as a CLI output." - }, - "FileEditorTool": { - "properties": { - "description": { - "type": "string", - "title": "Description" - }, - "action_type": { - "type": "string", - "title": "Action Type" - }, - "observation_type": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "summary": "Stop Canvas Extension Backend Endpoint", + "tags": [ + "Canvas Extensions" + ] + } + }, + "/api/canvas-extensions/installed/{extension_name}/bundle": { + "get": { + "description": "Serve an installed canvas extension's entrypoint bundle file.\n\nEntrypoint containment is re-validated against the live install path on\nevery request, not just at install time -- see\n``get_canvas_extension_bundle_path``. ``Cache-Control: no-cache`` forces\nrevalidation on each request, so a client never keeps serving a bundle\nfrom before the extension's last refresh: the actual bytes are re-read\nfrom disk, and Starlette's file-stat-based ``ETag``/``Last-Modified``\nchange the moment the on-disk revision does.", + "operationId": "get_canvas_extension_bundle_endpoint_api_canvas_extensions_installed__extension_name__bundle_get", + "parameters": [ + { + "description": "Canvas extension name (lowercase alphanumeric, hyphens)", + "in": "path", + "name": "extension_name", + "required": true, + "schema": { + "description": "Canvas extension name (lowercase alphanumeric, hyphens)", + "maxLength": 255, + "minLength": 1, + "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$", + "title": "Extension Name", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} } - ], - "title": "Observation Type" + }, + "description": "Successful Response" }, - "annotations": { - "anyOf": [ - { - "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" - }, - { - "type": "null" - } - ] + "404": { + "description": "Canvas extension or bundle not found" }, - "meta": { - "anyOf": [ - { - "additionalProperties": true, - "type": "object" - }, - { - "type": "null" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "title": "Meta" - }, - "kind": { - "type": "string", - "const": "FileEditorTool", - "title": "Kind" - }, - "title": { - "type": "string", - "title": "Title", - "readOnly": true + }, + "description": "Validation Error" } }, - "type": "object", - "required": [ - "description", - "action_type", - "kind", - "title" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "FileEditorTool", - "description": "A ToolDefinition subclass that automatically initializes a FileEditorExecutor." - }, - "FileEntry": { - "properties": { - "name": { - "type": "string", - "title": "Name", - "description": "Name of the file or directory" + "summary": "Get Canvas Extension Bundle Endpoint", + "tags": [ + "Canvas Extensions" + ] + } + }, + "/api/canvas-extensions/installed/{extension_name}/icon": { + "get": { + "description": "Serve the SVG icon declared by an installed canvas extension's manifest.\n\nThe path comes from the manifest, never the request. The CSP sandbox keeps\na directly opened SVG from running scripts on the agent-server origin.", + "operationId": "get_canvas_extension_icon_endpoint_api_canvas_extensions_installed__extension_name__icon_get", + "parameters": [ + { + "description": "Canvas extension name (lowercase alphanumeric, hyphens)", + "in": "path", + "name": "extension_name", + "required": true, + "schema": { + "description": "Canvas extension name (lowercase alphanumeric, hyphens)", + "maxLength": 255, + "minLength": 1, + "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$", + "title": "Extension Name", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "image/svg+xml": { + "schema": { + "format": "binary", + "type": "string" + } + } + }, + "description": "Successful Response" }, - "path": { - "type": "string", - "title": "Path", - "description": "Absolute path to the file or directory" + "404": { + "description": "Canvas extension or icon not found" }, - "is_directory": { - "type": "boolean", - "title": "Is Directory", - "description": "Whether this entry is a directory" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Get Canvas Extension Icon Endpoint", + "tags": [ + "Canvas Extensions" + ] + } + }, + "/api/conversations": { + "get": { + "description": "Get a batch of conversations given their ids, returning null for\nany missing item", + "operationId": "batch_get_conversations_api_conversations_get", + "parameters": [ + { + "in": "query", + "name": "ids", + "required": true, + "schema": { + "items": { + "format": "uuid", + "type": "string" + }, + "title": "Ids", + "type": "array" + } }, - "size": { - "type": "integer", - "title": "Size", - "description": "Size of the file in bytes (0 for directories)" + { + "in": "query", + "name": "include_skills", + "required": false, + "schema": { + "default": false, + "title": "Whether to include ``agent.agent_context.skills`` in the response. Default ``false`` (breaking change as of this release): skills are trimmed to ``[]`` on the wire because no known consumer reads them from HTTP responses, and a stock agent inlines ~260 KB of skill content per fetch. Pass ``true`` to opt back into the legacy full-payload shape — useful only for callers that still rely on ``RemoteConversation.agent.agent_context.skills`` round-tripping over the wire. The persisted conversation state on disk and the in-memory runtime copy are untouched either way.", + "type": "boolean" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/ConversationInfo" + }, + { + "type": "null" + } + ] + }, + "title": "Response Batch Get Conversations Api Conversations Get", + "type": "array" + } + } + }, + "description": "Successful Response" }, - "modified_time": { - "type": "string", - "format": "date-time", - "title": "Modified Time", - "description": "Last modified timestamp" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" } }, - "type": "object", - "required": [ - "name", - "path", - "is_directory", - "size", - "modified_time" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "FileEntry", - "description": "Information about a file or directory." + "summary": "Batch Get Conversations", + "tags": [ + "Conversations" + ] }, - "FinishAction": { - "properties": { - "message": { - "type": "string", - "title": "Message", - "description": "Final message to send to the user." + "post": { + "description": "Start a conversation in the local environment.", + "operationId": "start_conversation_api_conversations_post", + "parameters": [ + { + "in": "query", + "name": "include_skills", + "required": false, + "schema": { + "default": false, + "title": "Whether to include ``agent.agent_context.skills`` in the response. Default ``false`` (breaking change as of this release): skills are trimmed to ``[]`` on the wire because no known consumer reads them from HTTP responses, and a stock agent inlines ~260 KB of skill content per fetch. Pass ``true`` to opt back into the legacy full-payload shape — useful only for callers that still rely on ``RemoteConversation.agent.agent_context.skills`` round-tripping over the wire. The persisted conversation state on disk and the in-memory runtime copy are untouched either way.", + "type": "boolean" + } + }, + { + "in": "header", + "name": "X-OpenHands-Observability-Span-Name", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Openhands-Observability-Span-Name" + } }, - "kind": { - "type": "string", - "const": "FinishAction", - "title": "Kind" - } - }, - "additionalProperties": false, - "type": "object", - "required": [ - "message", - "kind" - ], - "title": "FinishAction" - }, - "FinishObservation": { - "properties": { - "content": { - "items": { + { + "in": "header", + "name": "X-OpenHands-Observability-Tags", + "required": false, + "schema": { "anyOf": [ { - "$ref": "#/components/schemas/TextContent" + "type": "string" }, { - "$ref": "#/components/schemas/ImageContent" + "type": "null" } - ] - }, - "type": "array", - "title": "Content", - "description": "Content returned from the tool as a list of TextContent/ImageContent objects. When there is an error, it should be written in this field." + ], + "title": "X-Openhands-Observability-Tags" + } }, - "is_error": { - "type": "boolean", - "title": "Is Error", - "description": "Whether the observation indicates an error", - "default": false + { + "in": "header", + "name": "X-OpenHands-Observability-Metadata", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Openhands-Observability-Metadata" + } }, - "kind": { - "type": "string", - "const": "FinishObservation", - "title": "Kind" + { + "in": "header", + "name": "X-OpenHands-Observability-Parent-Span-Context", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "X-Openhands-Observability-Parent-Span-Context" + } } - }, - "additionalProperties": false, - "type": "object", - "required": [ - "kind" ], - "title": "FinishObservation", - "description": "Observation returned after finishing a task.\nThe FinishAction itself contains the message sent to the user so no\nextra fields are needed here." - }, - "FinishTool": { - "properties": { - "description": { - "type": "string", - "title": "Description" - }, - "action_type": { - "type": "string", - "title": "Action Type" - }, - "observation_type": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StartConversationRequest", + "examples": [ + { + "agent_settings": { + "llm": { + "api_key": "your-api-key-here", + "model": "your-model-provider/your-model-name", + "usage_id": "your-llm-service" + } + }, + "initial_message": { + "content": [ + { + "text": "Flip a coin!", + "type": "text" + } + ], + "role": "user" + }, + "workspace": { + "working_dir": "workspace/project" + } + } + ] } - ], - "title": "Observation Type" + } }, - "annotations": { - "anyOf": [ - { - "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" - }, - { - "type": "null" + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ConversationInfo" + } } - ] + }, + "description": "Successful Response" }, - "meta": { - "anyOf": [ - { - "additionalProperties": true, - "type": "object" - }, - { - "type": "null" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "title": "Meta" - }, - "kind": { - "type": "string", - "const": "FinishTool", - "title": "Kind" - }, - "title": { - "type": "string", - "title": "Title", - "readOnly": true - } - }, - "type": "object", - "required": [ - "description", - "action_type", - "kind", - "title" - ], - "title": "FinishTool", - "description": "Tool for signaling the completion of a task or conversation." - }, - "GenerateTitleRequest": { - "properties": { - "max_length": { - "type": "integer", - "maximum": 200.0, - "minimum": 1.0, - "title": "Max Length", - "description": "Maximum length of the generated title", - "default": 50 + }, + "description": "Validation Error" }, - "llm": { - "anyOf": [ - { - "$ref": "#/components/schemas/LLM" - }, - { - "type": "null" - } - ], - "description": "Optional LLM to use for title generation" - } - }, - "type": "object", - "title": "GenerateTitleRequest", - "description": "Payload to generate a title for a conversation." - }, - "GenerateTitleResponse": { - "properties": { - "title": { - "type": "string", - "title": "Title", - "description": "The generated title for the conversation" + "429": { + "description": "Server conversation run capacity is full" } }, - "type": "object", - "required": [ - "title" - ], - "title": "GenerateTitleResponse", - "description": "Response containing the generated conversation title." - }, - "GitChange": { - "properties": { - "status": { - "$ref": "#/components/schemas/GitChangeStatus" - }, - "path": { - "type": "string", - "format": "path", - "title": "Path" + "security": [ + { + "APIKeyHeader": [] } - }, - "type": "object", - "required": [ - "status", - "path" - ], - "title": "GitChange" - }, - "GitChangeStatus": { - "type": "string", - "enum": [ - "MOVED", - "ADDED", - "DELETED", - "UPDATED" ], - "title": "GitChangeStatus" - }, - "GitDiff": { - "properties": { - "modified": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Modified" - }, - "original": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Original" - } - }, - "type": "object", - "required": [ - "modified", - "original" + "summary": "Start Conversation", + "tags": [ + "Conversations" + ] + } + }, + "/api/conversations/count": { + "get": { + "description": "Count conversations matching the given filters", + "operationId": "count_conversations_api_conversations_count_get", + "parameters": [ + { + "in": "query", + "name": "status", + "required": false, + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/ConversationExecutionStatus" + }, + { + "type": "null" + } + ], + "title": "Optional filter by conversation execution status" + } + } ], - "title": "GitDiff" - }, - "GlobAction": { - "properties": { - "pattern": { - "type": "string", - "title": "Pattern", - "description": "The glob pattern to match files (e.g., \"**/*.js\", \"src/**/*.ts\")" - }, - "path": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "title": "Response Count Conversations Api Conversations Count Get", + "type": "integer" + } } - ], - "title": "Path", - "description": "The directory (absolute path) to search in. Defaults to the current working directory." + }, + "description": "Successful Response" }, - "kind": { - "type": "string", - "const": "GlobAction", - "title": "Kind" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" } }, - "additionalProperties": false, - "type": "object", - "required": [ - "pattern", - "kind" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "GlobAction", - "description": "Schema for glob pattern matching operations." - }, - "GlobObservation": { - "properties": { - "content": { - "items": { + "summary": "Count Conversations", + "tags": [ + "Conversations" + ] + } + }, + "/api/conversations/search": { + "get": { + "description": "Search / List conversations", + "operationId": "search_conversations_api_conversations_search_get", + "parameters": [ + { + "in": "query", + "name": "page_id", + "required": false, + "schema": { "anyOf": [ { - "$ref": "#/components/schemas/TextContent" + "type": "string" }, { - "$ref": "#/components/schemas/ImageContent" + "type": "null" } - ] - }, - "type": "array", - "title": "Content", - "description": "Content returned from the tool as a list of TextContent/ImageContent objects. When there is an error, it should be written in this field." - }, - "is_error": { - "type": "boolean", - "title": "Is Error", - "description": "Whether the observation indicates an error", - "default": false + ], + "title": "Optional next_page_id from the previously returned page" + } }, - "files": { - "items": { - "type": "string" - }, - "type": "array", - "title": "Files", - "description": "List of matching file paths sorted by modification time" + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 100, + "exclusiveMinimum": 0, + "maximum": 100, + "title": "The max number of results in the page", + "type": "integer" + } }, - "pattern": { - "type": "string", - "title": "Pattern", - "description": "The glob pattern that was used" + { + "in": "query", + "name": "status", + "required": false, + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/ConversationExecutionStatus" + }, + { + "type": "null" + } + ], + "title": "Optional filter by conversation execution status" + } }, - "search_path": { - "type": "string", - "title": "Search Path", - "description": "The directory that was searched" + { + "in": "query", + "name": "sort_order", + "required": false, + "schema": { + "$ref": "#/components/schemas/ConversationSortOrder", + "default": "CREATED_AT_DESC", + "title": "Sort order for conversations" + } }, - "truncated": { - "type": "boolean", - "title": "Truncated", - "description": "Whether results were truncated to 100 files", - "default": false + { + "in": "query", + "name": "include_skills", + "required": false, + "schema": { + "default": false, + "title": "Whether to include ``agent.agent_context.skills`` in the response. Default ``false`` (breaking change as of this release): skills are trimmed to ``[]`` on the wire because no known consumer reads them from HTTP responses, and a stock agent inlines ~260 KB of skill content per fetch. Pass ``true`` to opt back into the legacy full-payload shape — useful only for callers that still rely on ``RemoteConversation.agent.agent_context.skills`` round-tripping over the wire. The persisted conversation state on disk and the in-memory runtime copy are untouched either way.", + "type": "boolean" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ConversationPage" + } + } + }, + "description": "Successful Response" }, - "kind": { - "type": "string", - "const": "GlobObservation", - "title": "Kind" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" } }, - "additionalProperties": false, - "type": "object", - "required": [ - "files", - "pattern", - "search_path", - "kind" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "GlobObservation", - "description": "Observation from glob pattern matching operations." - }, - "GlobTool": { - "properties": { - "description": { - "type": "string", - "title": "Description" - }, - "action_type": { - "type": "string", - "title": "Action Type" - }, - "observation_type": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "summary": "Search Conversations", + "tags": [ + "Conversations" + ] + } + }, + "/api/conversations/{conversation_id}": { + "delete": { + "description": "Permanently delete a conversation.", + "operationId": "delete_conversation_api_conversations__conversation_id__delete", + "parameters": [ + { + "in": "path", + "name": "conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Conversation Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } } - ], - "title": "Observation Type" + }, + "description": "Successful Response" }, - "annotations": { - "anyOf": [ - { - "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" - }, - { - "type": "null" + "404": { + "description": "Item not found" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ] + }, + "description": "Validation Error" + } + }, + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Delete Conversation", + "tags": [ + "Conversations" + ] + }, + "get": { + "description": "Given an id, get a conversation", + "operationId": "get_conversation_api_conversations__conversation_id__get", + "parameters": [ + { + "in": "path", + "name": "conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Conversation Id", + "type": "string" + } }, - "meta": { - "anyOf": [ - { - "additionalProperties": true, - "type": "object" - }, - { - "type": "null" + { + "in": "query", + "name": "include_skills", + "required": false, + "schema": { + "default": false, + "title": "Whether to include ``agent.agent_context.skills`` in the response. Default ``false`` (breaking change as of this release): skills are trimmed to ``[]`` on the wire because no known consumer reads them from HTTP responses, and a stock agent inlines ~260 KB of skill content per fetch. Pass ``true`` to opt back into the legacy full-payload shape — useful only for callers that still rely on ``RemoteConversation.agent.agent_context.skills`` round-tripping over the wire. The persisted conversation state on disk and the in-memory runtime copy are untouched either way.", + "type": "boolean" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ConversationInfo" + } } - ], - "title": "Meta" + }, + "description": "Successful Response" }, - "kind": { - "type": "string", - "const": "GlobTool", - "title": "Kind" + "404": { + "description": "Item not found" }, - "title": { - "type": "string", - "title": "Title", - "readOnly": true + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" } }, - "type": "object", - "required": [ - "description", - "action_type", - "kind", - "title" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "GlobTool", - "description": "A ToolDefinition subclass that automatically initializes a GlobExecutor." + "summary": "Get Conversation", + "tags": [ + "Conversations" + ] }, - "GraySwanAnalyzer-Input": { - "properties": { - "history_limit": { - "type": "integer", - "title": "History Limit", - "description": "Number of recent events to include as context", - "default": 20 - }, - "max_message_chars": { - "type": "integer", - "title": "Max Message Chars", - "description": "Max characters for conversation processing", - "default": 30000 - }, - "timeout": { - "type": "number", - "title": "Timeout", - "description": "Request timeout in seconds", - "default": 30.0 - }, - "low_threshold": { - "type": "number", - "title": "Low Threshold", - "description": "Risk threshold for LOW classification (score <= threshold)", - "default": 0.3 - }, - "medium_threshold": { - "type": "number", - "title": "Medium Threshold", - "description": "Risk threshold for MEDIUM classification (score <= threshold)", - "default": 0.7 - }, - "api_url": { - "type": "string", - "title": "Api Url", - "description": "GraySwan Cygnal API endpoint", - "default": "https://api.grayswan.ai/cygnal/monitor" - }, - "api_key": { - "anyOf": [ - { - "type": "string", - "format": "password", - "writeOnly": true - }, - { - "type": "null" + "patch": { + "description": "Update conversation metadata.\n\nThis endpoint allows updating conversation details like title.", + "operationId": "update_conversation_api_conversations__conversation_id__patch", + "parameters": [ + { + "in": "path", + "name": "conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Conversation Id", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateConversationRequest" } - ], - "title": "Api Key", - "description": "GraySwan API key (via GRAYSWAN_API_KEY env var)" + } }, - "policy_id": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } } - ], - "title": "Policy Id", - "description": "GraySwan policy ID (via GRAYSWAN_POLICY_ID env var)" + }, + "description": "Successful Response" }, - "kind": { - "type": "string", - "const": "GraySwanAnalyzer", - "title": "Kind" + "404": { + "description": "Item not found" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" } }, - "type": "object", - "title": "GraySwanAnalyzer", - "description": "Security analyzer using GraySwan's Cygnal API for AI safety monitoring.\n\nThis analyzer sends conversation history and pending actions to the GraySwan\nCygnal API for security analysis. The API returns a violation score which is\nmapped to SecurityRisk levels.\n\nEnvironment Variables:\n GRAYSWAN_API_KEY: Required API key for GraySwan authentication\n GRAYSWAN_POLICY_ID: Optional policy ID for custom GraySwan policy\n\nExample:\n >>> from openhands.sdk.security.grayswan import GraySwanAnalyzer\n >>> analyzer = GraySwanAnalyzer()\n >>> risk = analyzer.security_risk(action_event)" - }, - "GraySwanAnalyzer-Output": { - "properties": { - "history_limit": { - "type": "integer", - "title": "History Limit", - "description": "Number of recent events to include as context", - "default": 20 - }, - "max_message_chars": { - "type": "integer", - "title": "Max Message Chars", - "description": "Max characters for conversation processing", - "default": 30000 - }, - "timeout": { - "type": "number", - "title": "Timeout", - "description": "Request timeout in seconds", - "default": 30.0 - }, - "low_threshold": { - "type": "number", - "title": "Low Threshold", - "description": "Risk threshold for LOW classification (score <= threshold)", - "default": 0.3 - }, - "medium_threshold": { - "type": "number", - "title": "Medium Threshold", - "description": "Risk threshold for MEDIUM classification (score <= threshold)", - "default": 0.7 - }, - "api_url": { - "type": "string", - "title": "Api Url", - "description": "GraySwan Cygnal API endpoint", - "default": "https://api.grayswan.ai/cygnal/monitor" - }, - "api_key": { - "anyOf": [ - { - "type": "string", - "format": "password", - "writeOnly": true - }, - { - "type": "null" + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Update Conversation", + "tags": [ + "Conversations" + ] + } + }, + "/api/conversations/{conversation_id}/agent_final_response": { + "get": { + "description": "Get the agent's final response for a conversation.\n\nReturns the text of the last agent finish message (FinishAction) or\nthe last agent text response (MessageEvent). Returns an empty string\nif the agent has not produced a final response yet.", + "operationId": "get_conversation_agent_final_response_api_conversations__conversation_id__agent_final_response_get", + "parameters": [ + { + "in": "path", + "name": "conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Conversation Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AgentResponseResult" + } } - ], - "title": "Api Key", - "description": "GraySwan API key (via GRAYSWAN_API_KEY env var)" + }, + "description": "Successful Response" }, - "policy_id": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Policy Id", - "description": "GraySwan policy ID (via GRAYSWAN_POLICY_ID env var)" + "404": { + "description": "Conversation not found" }, - "kind": { - "type": "string", - "const": "GraySwanAnalyzer", - "title": "Kind" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" } }, - "type": "object", - "required": [ - "kind" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "GraySwanAnalyzer", - "description": "Security analyzer using GraySwan's Cygnal API for AI safety monitoring.\n\nThis analyzer sends conversation history and pending actions to the GraySwan\nCygnal API for security analysis. The API returns a violation score which is\nmapped to SecurityRisk levels.\n\nEnvironment Variables:\n GRAYSWAN_API_KEY: Required API key for GraySwan authentication\n GRAYSWAN_POLICY_ID: Optional policy ID for custom GraySwan policy\n\nExample:\n >>> from openhands.sdk.security.grayswan import GraySwanAnalyzer\n >>> analyzer = GraySwanAnalyzer()\n >>> risk = analyzer.security_risk(action_event)" - }, - "GrepAction": { - "properties": { - "pattern": { - "type": "string", - "title": "Pattern", - "description": "The regex pattern to search for in file contents" - }, - "path": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "summary": "Get Conversation Agent Final Response", + "tags": [ + "Conversations" + ] + } + }, + "/api/conversations/{conversation_id}/ask_agent": { + "post": { + "description": "Ask the agent a simple question without affecting conversation state.", + "operationId": "ask_agent_api_conversations__conversation_id__ask_agent_post", + "parameters": [ + { + "in": "path", + "name": "conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Conversation Id", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AskAgentRequest" } - ], - "title": "Path", - "description": "The directory (absolute path) to search in. Defaults to the current working directory." + } }, - "include": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AskAgentResponse" + } } - ], - "title": "Include", - "description": "Optional file pattern to filter which files to search (e.g., \"*.js\", \"*.{ts,tsx}\")" + }, + "description": "Successful Response" }, - "kind": { - "type": "string", - "const": "GrepAction", - "title": "Kind" + "404": { + "description": "Item not found" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" } }, - "additionalProperties": false, - "type": "object", - "required": [ - "pattern", - "kind" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "GrepAction", - "description": "Schema for grep content search operations." - }, - "GrepObservation": { - "properties": { - "content": { - "items": { - "anyOf": [ - { - "$ref": "#/components/schemas/TextContent" - }, - { - "$ref": "#/components/schemas/ImageContent" + "summary": "Ask Agent", + "tags": [ + "Conversations" + ] + } + }, + "/api/conversations/{conversation_id}/condense": { + "post": { + "description": "Force condensation of the conversation history.", + "operationId": "condense_conversation_api_conversations__conversation_id__condense_post", + "parameters": [ + { + "in": "path", + "name": "conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Conversation Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" } - ] + } }, - "type": "array", - "title": "Content", - "description": "Content returned from the tool as a list of TextContent/ImageContent objects. When there is an error, it should be written in this field." + "description": "Successful Response" }, - "is_error": { - "type": "boolean", - "title": "Is Error", - "description": "Whether the observation indicates an error", - "default": false + "404": { + "description": "Item not found" }, - "matches": { - "items": { - "type": "string" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } }, - "type": "array", - "title": "Matches", - "description": "List of file paths containing the pattern" - }, - "pattern": { - "type": "string", - "title": "Pattern", - "description": "The regex pattern that was used" - }, - "search_path": { - "type": "string", - "title": "Search Path", - "description": "The directory that was searched" + "description": "Validation Error" + } + }, + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Condense Conversation", + "tags": [ + "Conversations" + ] + } + }, + "/api/conversations/{conversation_id}/confirmation_policy": { + "post": { + "description": "Set the confirmation policy for a conversation.", + "operationId": "set_conversation_confirmation_policy_api_conversations__conversation_id__confirmation_policy_post", + "parameters": [ + { + "in": "path", + "name": "conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Conversation Id", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SetConfirmationPolicyRequest" + } + } }, - "include_pattern": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } } - ], - "title": "Include Pattern", - "description": "The file pattern filter that was used" + }, + "description": "Successful Response" }, - "truncated": { - "type": "boolean", - "title": "Truncated", - "description": "Whether results were truncated to 100 files", - "default": false + "404": { + "description": "Item not found" }, - "kind": { - "type": "string", - "const": "GrepObservation", - "title": "Kind" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" } }, - "additionalProperties": false, - "type": "object", - "required": [ - "matches", - "pattern", - "search_path", - "kind" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "GrepObservation", - "description": "Observation from grep content search operations." - }, - "GrepTool": { - "properties": { - "description": { - "type": "string", - "title": "Description" - }, - "action_type": { - "type": "string", - "title": "Action Type" - }, - "observation_type": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "summary": "Set Conversation Confirmation Policy", + "tags": [ + "Conversations" + ] + } + }, + "/api/conversations/{conversation_id}/events": { + "get": { + "description": "Get a batch of local events given their ids, returning null for any\nmissing item.", + "operationId": "batch_get_conversation_events_api_conversations__conversation_id__events_get", + "parameters": [ + { + "in": "path", + "name": "conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Conversation Id", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "items": { + "type": "string" + }, + "title": "Event Ids", + "type": "array" } - ], - "title": "Observation Type" + } }, - "annotations": { - "anyOf": [ - { - "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" - }, - { - "type": "null" + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/Event" + }, + { + "type": "null" + } + ] + }, + "title": "Response Batch Get Conversation Events Api Conversations Conversation Id Events Get", + "type": "array" + } } - ] + }, + "description": "Successful Response" }, - "meta": { - "anyOf": [ - { - "additionalProperties": true, - "type": "object" - }, - { - "type": "null" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "title": "Meta" - }, - "kind": { - "type": "string", - "const": "GrepTool", - "title": "Kind" - }, - "title": { - "type": "string", - "title": "Title", - "readOnly": true + }, + "description": "Validation Error" } }, - "type": "object", - "required": [ - "description", - "action_type", - "kind", - "title" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "GrepTool", - "description": "A ToolDefinition subclass that automatically initializes a GrepExecutor." + "summary": "Batch Get Conversation Events", + "tags": [ + "Events" + ] }, - "HTTPValidationError": { - "properties": { - "detail": { - "items": { - "$ref": "#/components/schemas/ValidationError" - }, - "type": "array", - "title": "Detail" + "post": { + "description": "Send a message to a conversation.\n\nIf starting the run returns 429, the message is already saved. Retry the\nconversation's /run endpoint instead of resending the message.", + "operationId": "send_message_api_conversations__conversation_id__events_post", + "parameters": [ + { + "in": "path", + "name": "conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Conversation Id", + "type": "string" + } } - }, - "type": "object", - "title": "HTTPValidationError" - }, - "HookConfig-Input": { - "properties": { - "pre_tool_use": { - "items": { - "$ref": "#/components/schemas/HookMatcher-Input" - }, - "type": "array", - "title": "Pre Tool Use", - "description": "Hooks that run before tool execution" - }, - "post_tool_use": { - "items": { - "$ref": "#/components/schemas/HookMatcher-Input" - }, - "type": "array", - "title": "Post Tool Use", - "description": "Hooks that run after tool execution" - }, - "user_prompt_submit": { - "items": { - "$ref": "#/components/schemas/HookMatcher-Input" - }, - "type": "array", - "title": "User Prompt Submit", - "description": "Hooks that run when user submits a prompt" + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SendMessageRequest" + } + } }, - "session_start": { - "items": { - "$ref": "#/components/schemas/HookMatcher-Input" + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } + } }, - "type": "array", - "title": "Session Start", - "description": "Hooks that run when a session starts" + "description": "Successful Response" }, - "session_end": { - "items": { - "$ref": "#/components/schemas/HookMatcher-Input" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } }, - "type": "array", - "title": "Session End", - "description": "Hooks that run when a session ends" + "description": "Validation Error" }, - "stop": { - "items": { - "$ref": "#/components/schemas/HookMatcher-Input" - }, - "type": "array", - "title": "Stop", - "description": "Hooks that run when the agent attempts to stop" + "429": { + "description": "Message saved but server run capacity is full" } }, - "additionalProperties": false, - "type": "object", - "title": "HookConfig", - "description": "Configuration for all hooks.\n\nHooks can be configured either by loading from `.openhands/hooks.json` or\nby directly instantiating with typed fields:\n\n # Direct instantiation with typed fields (recommended):\n config = HookConfig(\n pre_tool_use=[\n HookMatcher(\n matcher=\"terminal\",\n hooks=[HookDefinition(command=\"block_dangerous.sh\")]\n )\n ]\n )\n\n # Load from JSON file:\n config = HookConfig.load(\".openhands/hooks.json\")" - }, - "HookConfig-Output": { - "properties": { - "pre_tool_use": { - "items": { - "$ref": "#/components/schemas/HookMatcher-Output" - }, - "type": "array", - "title": "Pre Tool Use", - "description": "Hooks that run before tool execution" + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Send Message", + "tags": [ + "Events" + ] + } + }, + "/api/conversations/{conversation_id}/events/count": { + "get": { + "description": "Count local events matching the given filters", + "operationId": "count_conversation_events_api_conversations__conversation_id__events_count_get", + "parameters": [ + { + "in": "path", + "name": "conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Conversation Id", + "type": "string" + } }, - "post_tool_use": { - "items": { - "$ref": "#/components/schemas/HookMatcher-Output" - }, - "type": "array", - "title": "Post Tool Use", - "description": "Hooks that run after tool execution" + { + "in": "query", + "name": "kind", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Optional filter by event kind/type (e.g., ActionEvent, MessageEvent)" + } }, - "user_prompt_submit": { - "items": { - "$ref": "#/components/schemas/HookMatcher-Output" - }, - "type": "array", - "title": "User Prompt Submit", - "description": "Hooks that run when user submits a prompt" + { + "in": "query", + "name": "source", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Optional filter by event source (e.g., agent, user, environment)" + } }, - "session_start": { - "items": { - "$ref": "#/components/schemas/HookMatcher-Output" - }, - "type": "array", - "title": "Session Start", - "description": "Hooks that run when a session starts" + { + "in": "query", + "name": "body", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Optional filter by message content (case-insensitive)" + } }, - "session_end": { - "items": { - "$ref": "#/components/schemas/HookMatcher-Output" + { + "in": "query", + "name": "timestamp__gte", + "required": false, + "schema": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Filter: event timestamp >= this datetime" + } + }, + { + "in": "query", + "name": "timestamp__lt", + "required": false, + "schema": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Filter: event timestamp < this datetime" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "title": "Response Count Conversation Events Api Conversations Conversation Id Events Count Get", + "type": "integer" + } + } }, - "type": "array", - "title": "Session End", - "description": "Hooks that run when a session ends" + "description": "Successful Response" }, - "stop": { - "items": { - "$ref": "#/components/schemas/HookMatcher-Output" + "404": { + "description": "Conversation not found" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } }, - "type": "array", - "title": "Stop", - "description": "Hooks that run when the agent attempts to stop" + "description": "Validation Error" } }, - "additionalProperties": false, - "type": "object", - "title": "HookConfig", - "description": "Configuration for all hooks.\n\nHooks can be configured either by loading from `.openhands/hooks.json` or\nby directly instantiating with typed fields:\n\n # Direct instantiation with typed fields (recommended):\n config = HookConfig(\n pre_tool_use=[\n HookMatcher(\n matcher=\"terminal\",\n hooks=[HookDefinition(command=\"block_dangerous.sh\")]\n )\n ]\n )\n\n # Load from JSON file:\n config = HookConfig.load(\".openhands/hooks.json\")" - }, - "HookDefinition": { - "properties": { - "type": { - "$ref": "#/components/schemas/HookType", - "default": "command" - }, - "command": { - "type": "string", - "title": "Command" - }, - "timeout": { - "type": "integer", - "title": "Timeout", - "default": 60 + "security": [ + { + "APIKeyHeader": [] } - }, - "type": "object", - "required": [ - "command" ], - "title": "HookDefinition", - "description": "A single hook definition." - }, - "HookMatcher-Input": { - "properties": { - "matcher": { - "type": "string", - "title": "Matcher", - "default": "*" - }, - "hooks": { - "items": { - "$ref": "#/components/schemas/HookDefinition" - }, - "type": "array", - "title": "Hooks" - } - }, - "type": "object", - "title": "HookMatcher", - "description": "Matches events to hooks based on patterns.\n\nSupports exact match, wildcard (*), and regex (auto-detected or /pattern/)." - }, - "HookMatcher-Output": { - "properties": { - "matcher": { - "type": "string", - "title": "Matcher", - "default": "*" - }, - "hooks": { - "items": { - "$ref": "#/components/schemas/HookDefinition" - }, - "type": "array", - "title": "Hooks" + "summary": "Count Conversation Events", + "tags": [ + "Events" + ] + } + }, + "/api/conversations/{conversation_id}/events/respond_to_confirmation": { + "post": { + "description": "Accept or reject a pending action in confirmation mode.", + "operationId": "respond_to_confirmation_api_conversations__conversation_id__events_respond_to_confirmation_post", + "parameters": [ + { + "in": "path", + "name": "conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Conversation Id", + "type": "string" + } } - }, - "type": "object", - "title": "HookMatcher", - "description": "Matches events to hooks based on patterns.\n\nSupports exact match, wildcard (*), and regex (auto-detected or /pattern/)." - }, - "HookType": { - "type": "string", - "enum": [ - "command", - "prompt" ], - "title": "HookType", - "description": "Types of hooks that can be executed." - }, - "HooksRequest": { - "properties": { - "project_dir": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ConfirmationResponseRequest" } - ], - "title": "Project Dir", - "description": "Workspace directory path for project hooks" - } + } + }, + "required": true }, - "type": "object", - "title": "HooksRequest", - "description": "Request body for loading hooks." - }, - "HooksResponse": { - "properties": { - "hook_config": { - "anyOf": [ - { - "$ref": "#/components/schemas/HookConfig-Output" - }, - { - "type": "null" + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } } - ], - "description": "Hook configuration loaded from the workspace, or None if not found" + }, + "description": "Successful Response" + }, + "404": { + "description": "Item not found" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + }, + "429": { + "description": "Server conversation run capacity is full" } }, - "type": "object", - "title": "HooksResponse", - "description": "Response containing hooks configuration." - }, - "Icon": { - "properties": { - "src": { - "type": "string", - "title": "Src" + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Respond To Confirmation", + "tags": [ + "Events" + ] + } + }, + "/api/conversations/{conversation_id}/events/search": { + "get": { + "description": "Search / List local events", + "operationId": "search_conversation_events_api_conversations__conversation_id__events_search_get", + "parameters": [ + { + "in": "path", + "name": "conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Conversation Id", + "type": "string" + } }, - "mimeType": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Mimetype" + { + "in": "query", + "name": "page_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Optional next_page_id from the previously returned page" + } + }, + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 100, + "exclusiveMinimum": 0, + "maximum": 100, + "title": "The max number of results in the page", + "type": "integer" + } + }, + { + "in": "query", + "name": "kind", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Optional filter by event kind/type (e.g., ActionEvent, MessageEvent)" + } + }, + { + "in": "query", + "name": "source", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Optional filter by event source (e.g., agent, user, environment)" + } + }, + { + "in": "query", + "name": "body", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Optional filter by message content (case-insensitive)" + } + }, + { + "in": "query", + "name": "sort_order", + "required": false, + "schema": { + "$ref": "#/components/schemas/EventSortOrder", + "default": "TIMESTAMP", + "title": "Sort order for events" + } }, - "sizes": { - "anyOf": [ - { - "items": { + { + "in": "query", + "name": "timestamp__gte", + "required": false, + "schema": { + "anyOf": [ + { + "format": "date-time", "type": "string" }, - "type": "array" - }, - { - "type": "null" - } - ], - "title": "Sizes" + { + "type": "null" + } + ], + "title": "Filter: event timestamp >= this datetime" + } + }, + { + "in": "query", + "name": "timestamp__lt", + "required": false, + "schema": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Filter: event timestamp < this datetime" + } } - }, - "additionalProperties": true, - "type": "object", - "required": [ - "src" ], - "title": "Icon", - "description": "An icon for display in user interfaces." - }, - "ImageContent": { - "properties": { - "cache_prompt": { - "type": "boolean", - "title": "Cache Prompt", - "default": false + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" }, - "type": { - "type": "string", - "const": "image", - "title": "Type", - "default": "image" + "404": { + "description": "Conversation not found" }, - "image_urls": { - "items": { - "type": "string" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } }, - "type": "array", - "title": "Image Urls" + "description": "Validation Error" } }, - "type": "object", - "required": [ - "image_urls" - ], - "title": "ImageContent" - }, - "InputMetadata": { - "properties": { - "name": { - "type": "string", - "title": "Name", - "description": "Name of the input parameter" - }, - "description": { - "type": "string", - "title": "Description", - "description": "Description of the input parameter" + "security": [ + { + "APIKeyHeader": [] } - }, - "type": "object", - "required": [ - "name", - "description" ], - "title": "InputMetadata", - "description": "Metadata for task skill inputs." - }, - "IterativeRefinementConfig": { - "properties": { - "success_threshold": { - "type": "number", - "maximum": 1.0, - "minimum": 0.0, - "title": "Success Threshold", - "description": "Score threshold (0-1) to consider task successful.", - "default": 0.6 - }, - "max_iterations": { - "type": "integer", - "minimum": 1.0, - "title": "Max Iterations", - "description": "Maximum number of iterations before giving up.", - "default": 3 - } - }, - "type": "object", - "title": "IterativeRefinementConfig", - "description": "Configuration for iterative refinement based on critic feedback.\n\nWhen attached to a CriticBase, the Conversation.run() method will\nautomatically retry the task if the critic score is below the threshold.\n\nExample:\n critic = APIBasedCritic(\n server_url=\"...\",\n api_key=\"...\",\n model_name=\"critic\",\n iterative_refinement=IterativeRefinementConfig(\n success_threshold=0.7,\n max_iterations=3,\n ),\n )\n agent = Agent(llm=llm, tools=tools, critic=critic)\n conversation = Conversation(agent=agent, workspace=workspace)\n conversation.send_message(\"Create a calculator module...\")\n conversation.run() # Will automatically retry if critic score < 0.7" - }, - "KeywordTrigger": { - "properties": { - "type": { - "type": "string", - "const": "keyword", - "title": "Type", - "default": "keyword" + "summary": "Search Conversation Events", + "tags": [ + "Events" + ] + } + }, + "/api/conversations/{conversation_id}/events/{event_id}": { + "get": { + "description": "Get a local event given an id", + "operationId": "get_conversation_event_api_conversations__conversation_id__events__event_id__get", + "parameters": [ + { + "in": "path", + "name": "event_id", + "required": true, + "schema": { + "title": "Event Id", + "type": "string" + } }, - "keywords": { - "items": { + { + "in": "path", + "name": "conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Conversation Id", "type": "string" - }, - "type": "array", - "title": "Keywords" + } } - }, - "type": "object", - "required": [ - "keywords" ], - "title": "KeywordTrigger", - "description": "Trigger for keyword-based skills.\n\nThese skills are activated when specific keywords appear in the user's query." - }, - "LLM": { - "properties": { - "model": { - "type": "string", - "title": "Model", - "description": "Model name.", - "default": "claude-sonnet-4-20250514" - }, - "api_key": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "string", - "format": "password", - "writeOnly": true - }, - { - "type": "null" - } - ], - "title": "Api Key", - "description": "API key." - }, - "base_url": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Base Url", - "description": "Custom base URL." - }, - "api_version": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Event" + } } - ], - "title": "Api Version", - "description": "API version (e.g., Azure)." + }, + "description": "Successful Response" }, - "aws_access_key_id": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "string", - "format": "password", - "writeOnly": true - }, - { - "type": "null" - } - ], - "title": "Aws Access Key Id" + "404": { + "description": "Item not found" }, - "aws_secret_access_key": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "string", - "format": "password", - "writeOnly": true - }, - { - "type": "null" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "title": "Aws Secret Access Key" + }, + "description": "Validation Error" + } + }, + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Get Conversation Event", + "tags": [ + "Events" + ] + } + }, + "/api/conversations/{conversation_id}/fork": { + "post": { + "description": "Fork a conversation, deep-copying its event history.\n\nThe fork starts in ``idle`` status with a fresh event loop.\nCalling ``run`` on the fork resumes from the copied state, meaning\nthe agent has full event memory of the source conversation.", + "operationId": "fork_conversation_api_conversations__conversation_id__fork_post", + "parameters": [ + { + "in": "path", + "name": "conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Conversation Id", + "type": "string" + } }, - "aws_region_name": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + { + "in": "query", + "name": "include_skills", + "required": false, + "schema": { + "default": false, + "title": "Whether to include ``agent.agent_context.skills`` in the response. Default ``false`` (breaking change as of this release): skills are trimmed to ``[]`` on the wire because no known consumer reads them from HTTP responses, and a stock agent inlines ~260 KB of skill content per fetch. Pass ``true`` to opt back into the legacy full-payload shape — useful only for callers that still rely on ``RemoteConversation.agent.agent_context.skills`` round-tripping over the wire. The persisted conversation state on disk and the in-memory runtime copy are untouched either way.", + "type": "boolean" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ForkConversationRequest", + "default": { + "reset_metrics": true + } } - ], - "title": "Aws Region Name" + } + } + }, + "responses": { + "201": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ConversationInfo" + } + } + }, + "description": "Forked conversation created" }, - "openrouter_site_url": { - "type": "string", - "title": "Openrouter Site Url", - "default": "https://docs.all-hands.dev/" + "404": { + "description": "Source conversation not found" }, - "openrouter_app_name": { - "type": "string", - "title": "Openrouter App Name", - "default": "OpenHands" + "409": { + "description": "Fork ID already in use" }, - "num_retries": { - "type": "integer", - "minimum": 0.0, - "title": "Num Retries", - "default": 5 + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Fork Conversation", + "tags": [ + "Conversations" + ] + } + }, + "/api/conversations/{conversation_id}/goal": { + "post": { + "description": "Start a ``/goal`` loop inside an existing conversation.\n\nThe loop appends messages and starts agent runs in the same conversation\nhistory and event stream as the main chat. It does not create a separate\nconversation for the goal or fork the existing one.", + "operationId": "start_goal_in_conversation_api_conversations__conversation_id__goal_post", + "parameters": [ + { + "in": "path", + "name": "conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Conversation Id", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StartGoalRequest" + } + } }, - "retry_multiplier": { - "type": "number", - "minimum": 0.0, - "title": "Retry Multiplier", - "default": 8.0 + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } + } + }, + "description": "Successful Response" }, - "retry_min_wait": { - "type": "integer", - "minimum": 0.0, - "title": "Retry Min Wait", - "default": 8 + "404": { + "description": "Item not found" }, - "retry_max_wait": { - "type": "integer", - "minimum": 0.0, - "title": "Retry Max Wait", - "default": 64 + "409": { + "description": "Conversation run or goal loop is already running" }, - "timeout": { - "anyOf": [ - { - "type": "integer", - "minimum": 0.0 - }, - { - "type": "null" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "title": "Timeout", - "description": "HTTP timeout in seconds. Default is 300s (5 minutes). Set to None to disable timeout (not recommended for production).", - "default": 300 - }, - "max_message_chars": { - "type": "integer", - "minimum": 1.0, - "title": "Max Message Chars", - "description": "Approx max chars in each event/content sent to the LLM.", - "default": 30000 + }, + "description": "Validation Error" }, - "temperature": { - "anyOf": [ - { - "type": "number", - "minimum": 0.0 - }, - { - "type": "null" + "429": { + "description": "Server conversation run capacity is full" + } + }, + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Start Goal In Conversation", + "tags": [ + "Conversations" + ] + } + }, + "/api/conversations/{conversation_id}/goal/resume": { + "post": { + "description": "Resume the last interrupted ``/goal`` loop inside this conversation.", + "operationId": "resume_goal_in_conversation_api_conversations__conversation_id__goal_resume_post", + "parameters": [ + { + "in": "path", + "name": "conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Conversation Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } } - ], - "title": "Temperature", - "description": "Sampling temperature for response generation. Defaults to 0 for most models and provider default for reasoning models." + }, + "description": "Successful Response" }, - "top_p": { - "anyOf": [ - { - "type": "number", - "maximum": 1.0, - "minimum": 0.0 - }, - { - "type": "null" - } - ], - "title": "Top P", - "default": 1.0 + "404": { + "description": "Item not found" }, - "top_k": { - "anyOf": [ - { - "type": "number", - "minimum": 0.0 - }, - { - "type": "null" - } - ], - "title": "Top K" + "409": { + "description": "Conversation run or goal loop is already running" }, - "max_input_tokens": { - "anyOf": [ - { - "type": "integer", - "minimum": 1.0 - }, - { - "type": "null" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "title": "Max Input Tokens", - "description": "The maximum number of input tokens. Note that this is currently unused, and the value at runtime is actually the total tokens in OpenAI (e.g. 128,000 tokens for GPT-4)." + }, + "description": "Validation Error" }, - "max_output_tokens": { - "anyOf": [ - { - "type": "integer", - "minimum": 1.0 - }, - { - "type": "null" + "429": { + "description": "Server conversation run capacity is full" + } + }, + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Resume Goal In Conversation", + "tags": [ + "Conversations" + ] + } + }, + "/api/conversations/{conversation_id}/goal/stop": { + "post": { + "description": "Stop the active ``/goal`` loop inside this conversation.\n\nThis cancels only the background goal loop, not the conversation itself, and\nrecords an ``interrupted`` goal status so ``/goal/resume`` can continue it.", + "operationId": "stop_goal_in_conversation_api_conversations__conversation_id__goal_stop_post", + "parameters": [ + { + "in": "path", + "name": "conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Conversation Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } } - ], - "title": "Max Output Tokens", - "description": "The maximum number of output tokens. This is sent to the LLM." + }, + "description": "Successful Response" }, - "model_canonical_name": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "404": { + "description": "Item not found" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Stop Goal In Conversation", + "tags": [ + "Conversations" + ] + } + }, + "/api/conversations/{conversation_id}/interrupt": { + "post": { + "description": "Immediately interrupt a running conversation.\n\nUnlike ``/pause``, which waits for the current LLM call to finish,\n``/interrupt`` cancels the in-flight request so the effect is instant.\nThe conversation transitions to *paused* and can be resumed later.", + "operationId": "interrupt_conversation_api_conversations__conversation_id__interrupt_post", + "parameters": [ + { + "in": "path", + "name": "conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Conversation Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } } - ], - "title": "Model Canonical Name", - "description": "Optional canonical model name for feature registry lookups. The OpenHands SDK maintains a model feature registry that maps model names to capabilities (e.g., vision support, prompt caching, responses API support). When using proxied or aliased model identifiers, set this field to the canonical model name (e.g., 'openai/gpt-4o') to ensure correct capability detection. If not provided, the 'model' field will be used for capability lookups." + }, + "description": "Successful Response" }, - "extra_headers": { - "anyOf": [ - { - "additionalProperties": { - "type": "string" - }, - "type": "object" - }, - { - "type": "null" - } - ], - "title": "Extra Headers", - "description": "Optional HTTP headers to forward to LiteLLM requests." + "404": { + "description": "Item not found" }, - "input_cost_per_token": { - "anyOf": [ - { - "type": "number", - "minimum": 0.0 - }, - { - "type": "null" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "title": "Input Cost Per Token", - "description": "The cost per input token. This will available in logs for user." - }, - "output_cost_per_token": { - "anyOf": [ - { - "type": "number", - "minimum": 0.0 - }, - { - "type": "null" + }, + "description": "Validation Error" + } + }, + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Interrupt Conversation", + "tags": [ + "Conversations" + ] + } + }, + "/api/conversations/{conversation_id}/load_plugin": { + "post": { + "description": "Load a plugin from the conversation's registered marketplaces.", + "operationId": "load_conversation_plugin_api_conversations__conversation_id__load_plugin_post", + "parameters": [ + { + "in": "path", + "name": "conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Conversation Id", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Body_load_conversation_plugin_api_conversations__conversation_id__load_plugin_post" } - ], - "title": "Output Cost Per Token", - "description": "The cost per output token. This will available in logs for user." + } }, - "ollama_base_url": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } } - ], - "title": "Ollama Base Url" - }, - "stream": { - "type": "boolean", - "title": "Stream", - "description": "Enable streaming responses from the LLM. When enabled, the provided `on_token` callback in .completions and .responses will be invoked for each chunk of tokens.", - "default": false + }, + "description": "Successful Response" }, - "drop_params": { - "type": "boolean", - "title": "Drop Params", - "default": true + "400": { + "description": "Invalid plugin reference or inactive conversation" }, - "modify_params": { - "type": "boolean", - "title": "Modify Params", - "description": "Modify params allows litellm to do transformations like adding a default message, when a message is empty.", - "default": true + "404": { + "description": "Conversation or plugin not found" }, - "disable_vision": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "title": "Disable Vision", - "description": "If model is vision capable, this option allows to disable image processing (useful for cost reduction)." + }, + "description": "Validation Error" + } + }, + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Load Conversation Plugin", + "tags": [ + "Conversations" + ] + } + }, + "/api/conversations/{conversation_id}/navigate": { + "post": { + "description": "Move a conversation's HEAD to an existing event, re-rooting the branch.\n\nAll branches stay on disk; only the active branch the agent runs on next\nchanges. Unlike ``fork``, no new conversation is created. Returns the\nupdated conversation info (carrying the new ``leaf_event_id``).", + "operationId": "navigate_conversation_api_conversations__conversation_id__navigate_post", + "parameters": [ + { + "in": "path", + "name": "conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Conversation Id", + "type": "string" + } }, - "disable_stop_word": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" + { + "in": "query", + "name": "include_skills", + "required": false, + "schema": { + "default": false, + "title": "Whether to include ``agent.agent_context.skills`` in the response. Default ``false`` (breaking change as of this release): skills are trimmed to ``[]`` on the wire because no known consumer reads them from HTTP responses, and a stock agent inlines ~260 KB of skill content per fetch. Pass ``true`` to opt back into the legacy full-payload shape — useful only for callers that still rely on ``RemoteConversation.agent.agent_context.skills`` round-tripping over the wire. The persisted conversation state on disk and the in-memory runtime copy are untouched either way.", + "type": "boolean" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NavigateConversationRequest" } - ], - "title": "Disable Stop Word", - "description": "Disable using of stop word.", - "default": false - }, - "caching_prompt": { - "type": "boolean", - "title": "Caching Prompt", - "description": "Enable caching of prompts.", - "default": true - }, - "log_completions": { - "type": "boolean", - "title": "Log Completions", - "description": "Enable logging of completions.", - "default": false - }, - "log_completions_folder": { - "type": "string", - "title": "Log Completions Folder", - "description": "The folder to log LLM completions to. Required if log_completions is True.", - "default": "logs/completions" + } }, - "custom_tokenizer": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ConversationInfo" + } } - ], - "title": "Custom Tokenizer", - "description": "A custom tokenizer to use for token counting." + }, + "description": "Successful Response" }, - "native_tool_calling": { - "type": "boolean", - "title": "Native Tool Calling", - "description": "Whether to use native tool calling.", - "default": true + "404": { + "description": "Conversation or event not found" }, - "force_string_serializer": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "title": "Force String Serializer", - "description": "Force using string content serializer when sending to LLM API. If None (default), auto-detect based on model. Useful for providers that do not support list content, like HuggingFace and Groq." - }, - "reasoning_effort": { - "anyOf": [ - { - "type": "string", - "enum": [ - "low", - "medium", - "high", - "xhigh", - "none" - ] - }, - { - "type": "null" + }, + "description": "Validation Error" + } + }, + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Navigate Conversation", + "tags": [ + "Conversations" + ] + } + }, + "/api/conversations/{conversation_id}/pause": { + "post": { + "description": "Pause a conversation, allowing it to be resumed later.", + "operationId": "pause_conversation_api_conversations__conversation_id__pause_post", + "parameters": [ + { + "in": "path", + "name": "conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Conversation Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } } - ], - "title": "Reasoning Effort", - "description": "The effort to put into reasoning. This is a string that can be one of 'low', 'medium', 'high', 'xhigh', or 'none'. Can apply to all reasoning models.", - "default": "high" + }, + "description": "Successful Response" }, - "reasoning_summary": { - "anyOf": [ - { - "type": "string", - "enum": [ - "auto", - "concise", - "detailed" - ] - }, - { - "type": "null" + "404": { + "description": "Item not found" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "title": "Reasoning Summary", - "description": "The level of detail for reasoning summaries. This is a string that can be one of 'auto', 'concise', or 'detailed'. Requires verified OpenAI organization. Only sent when explicitly set." + }, + "description": "Validation Error" + } + }, + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Pause Conversation", + "tags": [ + "Conversations" + ] + } + }, + "/api/conversations/{conversation_id}/run": { + "post": { + "description": "Start running the conversation in the background.", + "operationId": "run_conversation_api_conversations__conversation_id__run_post", + "parameters": [ + { + "in": "path", + "name": "conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Conversation Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } + } + }, + "description": "Successful Response" }, - "enable_encrypted_reasoning": { - "type": "boolean", - "title": "Enable Encrypted Reasoning", - "description": "If True, ask for ['reasoning.encrypted_content'] in Responses API include.", - "default": true + "404": { + "description": "Item not found" }, - "prompt_cache_retention": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Prompt Cache Retention", - "description": "Retention policy for prompt cache. Only sent for GPT-5+ models; explicitly stripped for all other models.", - "default": "24h" + "409": { + "description": "Conversation is already running" }, - "extended_thinking_budget": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "title": "Extended Thinking Budget", - "description": "The budget tokens for extended thinking, supported by Anthropic models.", - "default": 200000 + }, + "description": "Validation Error" }, - "seed": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" + "429": { + "description": "Server conversation run capacity is full" + } + }, + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Run Conversation", + "tags": [ + "Conversations" + ] + } + }, + "/api/conversations/{conversation_id}/runtime": { + "get": { + "description": "Inspect the always-available in-process runtime.", + "operationId": "get_local_conversation_runtime_api_conversations__conversation_id__runtime_get", + "parameters": [ + { + "in": "path", + "name": "conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Conversation Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ConversationRuntimeInfo" + } } - ], - "title": "Seed", - "description": "The seed to use for random number generation." + }, + "description": "Successful Response" }, - "safety_settings": { - "anyOf": [ - { - "items": { - "additionalProperties": { - "type": "string" - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "title": "Safety Settings", - "description": "Deprecated: Safety settings for models that support them (like Mistral AI and Gemini). This field is deprecated in 1.10.0 and will be removed in 1.15.0. Safety settings are designed for consumer-facing content moderation, which is not relevant for coding agents." - }, - "usage_id": { - "type": "string", - "title": "Usage Id", - "description": "Unique usage identifier for the LLM. Used for registry lookups, telemetry, and spend tracking.", - "default": "default" - }, - "litellm_extra_body": { - "additionalProperties": true, - "type": "object", - "title": "Litellm Extra Body", - "description": "Additional key-value pairs to pass to litellm's extra_body parameter. This is useful for custom inference endpoints that need additional parameters for configuration, routing, or advanced features. NOTE: Not all LLM providers support extra_body parameters. Some providers (e.g., OpenAI) may reject requests with unrecognized options. This is commonly supported by: - LiteLLM proxy servers (routing metadata, tracing) - vLLM endpoints (return_token_ids, etc.) - Custom inference clusters Examples: - Proxy routing: {'trace_version': '1.0.0', 'tags': ['agent:my-agent']} - vLLM features: {'return_token_ids': True}" + }, + "description": "Validation Error" } }, - "type": "object", - "title": "LLM", - "description": "Language model interface for OpenHands agents.\n\nThe LLM class provides a unified interface for interacting with various\nlanguage models through the litellm library. It handles model configuration,\nAPI authentication,\nretry logic, and tool calling capabilities.\n\nExample:\n >>> from openhands.sdk import LLM\n >>> from pydantic import SecretStr\n >>> llm = LLM(\n ... model=\"claude-sonnet-4-20250514\",\n ... api_key=SecretStr(\"your-api-key\"),\n ... usage_id=\"my-agent\"\n ... )\n >>> # Use with agent or conversation" - }, - "LLMCompletionLogEvent": { - "properties": { - "id": { - "type": "string", - "title": "Id", - "description": "Unique event id (ULID/UUID)" - }, - "timestamp": { - "type": "string", - "title": "Timestamp", - "description": "Event timestamp" - }, - "source": { - "type": "string", - "enum": [ - "agent", - "user", - "environment" - ], - "title": "Source", - "default": "environment" - }, - "filename": { - "type": "string", - "title": "Filename", - "description": "The intended filename for this log (relative to log directory)" - }, - "log_data": { - "type": "string", - "title": "Log Data", - "description": "The JSON-encoded log data to be written to the file" + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Get Local Conversation Runtime", + "tags": [ + "Conversations" + ] + } + }, + "/api/conversations/{conversation_id}/runtime/reprovision": { + "post": { + "description": "Return local runtime state; local mode has no infrastructure to provision.", + "operationId": "reprovision_local_conversation_runtime_api_conversations__conversation_id__runtime_reprovision_post", + "parameters": [ + { + "in": "path", + "name": "conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Conversation Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ConversationRuntimeInfo" + } + } + }, + "description": "Successful Response" }, - "model_name": { - "type": "string", - "title": "Model Name", - "description": "The model name for context", - "default": "unknown" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Reprovision Local Conversation Runtime", + "tags": [ + "Conversations" + ] + } + }, + "/api/conversations/{conversation_id}/secrets": { + "post": { + "description": "Update secrets for a conversation.", + "operationId": "update_conversation_secrets_api_conversations__conversation_id__secrets_post", + "parameters": [ + { + "in": "path", + "name": "conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Conversation Id", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateSecretsRequest" + } + } }, - "usage_id": { - "type": "string", - "title": "Usage Id", - "description": "The LLM usage_id that produced this log", - "default": "default" + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } + } + }, + "description": "Successful Response" }, - "kind": { - "type": "string", - "const": "LLMCompletionLogEvent", - "title": "Kind" + "404": { + "description": "Item not found" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" } }, - "additionalProperties": false, - "type": "object", - "required": [ - "filename", - "log_data", - "kind" - ], - "title": "LLMCompletionLogEvent", - "description": "Event containing LLM completion log data.\n\nWhen an LLM is configured with log_completions=True in a remote conversation,\nthis event streams the completion log data back to the client through WebSocket\ninstead of writing it to a file inside the Docker container." - }, - "LLMSecurityAnalyzer-Input": { - "properties": { - "kind": { - "type": "string", - "const": "LLMSecurityAnalyzer", - "title": "Kind" + "security": [ + { + "APIKeyHeader": [] } - }, - "type": "object", - "title": "LLMSecurityAnalyzer", - "description": "LLM-based security analyzer.\n\nThis analyzer respects the security_risk attribute that can be set by the LLM\nwhen generating actions, similar to OpenHands' LLMRiskAnalyzer.\n\nIt provides a lightweight security analysis approach that leverages the LLM's\nunderstanding of action context and potential risks." - }, - "LLMSecurityAnalyzer-Output": { - "properties": { - "kind": { - "type": "string", - "const": "LLMSecurityAnalyzer", - "title": "Kind" + ], + "summary": "Update Conversation Secrets", + "tags": [ + "Conversations" + ] + } + }, + "/api/conversations/{conversation_id}/security_analyzer": { + "post": { + "description": "Set the security analyzer for a conversation.", + "operationId": "set_conversation_security_analyzer_api_conversations__conversation_id__security_analyzer_post", + "parameters": [ + { + "in": "path", + "name": "conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Conversation Id", + "type": "string" + } } - }, - "type": "object", - "required": [ - "kind" ], - "title": "LLMSecurityAnalyzer", - "description": "LLM-based security analyzer.\n\nThis analyzer respects the security_risk attribute that can be set by the LLM\nwhen generating actions, similar to OpenHands' LLMRiskAnalyzer.\n\nIt provides a lightweight security analysis approach that leverages the LLM's\nunderstanding of action context and potential risks." - }, - "LLMSummarizingCondenser-Input": { - "properties": { - "llm": { - "$ref": "#/components/schemas/LLM" - }, - "max_size": { - "type": "integer", - "exclusiveMinimum": 0.0, - "title": "Max Size", - "default": 240 - }, - "max_tokens": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SetSecurityAnalyzerRequest" } - ], - "title": "Max Tokens" - }, - "keep_first": { - "type": "integer", - "minimum": 0.0, - "title": "Keep First", - "default": 2 + } }, - "hard_context_reset_max_retries": { - "type": "integer", - "exclusiveMinimum": 0.0, - "title": "Hard Context Reset Max Retries", - "default": 5 + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } + } + }, + "description": "Successful Response" }, - "hard_context_reset_context_scaling": { - "type": "number", - "exclusiveMaximum": 1.0, - "exclusiveMinimum": 0.0, - "title": "Hard Context Reset Context Scaling", - "default": 0.8 + "404": { + "description": "Item not found" }, - "kind": { - "type": "string", - "const": "LLMSummarizingCondenser", - "title": "Kind" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" } }, - "type": "object", - "required": [ - "llm" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "LLMSummarizingCondenser", - "description": "LLM-based condenser that summarizes forgotten events.\n\nUses an independent LLM (stored in the `llm` attribute) for generating summaries\nof forgotten events. The optional `agent_llm` parameter passed to condense() is\nthe LLM used by the agent for token counting purposes, and you should not assume\nit is the same as the one defined in this condenser." - }, - "LLMSummarizingCondenser-Output": { - "properties": { - "llm": { - "$ref": "#/components/schemas/LLM" - }, - "max_size": { - "type": "integer", - "exclusiveMinimum": 0.0, - "title": "Max Size", - "default": 240 + "summary": "Set Conversation Security Analyzer", + "tags": [ + "Conversations" + ] + } + }, + "/api/conversations/{conversation_id}/switch_acp_model": { + "post": { + "description": "Switch the model of an ACP conversation.\n\nFor a conversation that has already started, issues a protocol-level\n``session/set_model`` call to the ACP subprocess so the new model applies to\nsubsequent turns without losing context. For one created but not yet run,\nthe value is persisted and applied when the first session starts (returns\n``200`` either way). Only valid for ACP conversations whose provider\nsupports model switching.", + "operationId": "switch_conversation_acp_model_api_conversations__conversation_id__switch_acp_model_post", + "parameters": [ + { + "in": "path", + "name": "conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Conversation Id", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Body_switch_conversation_acp_model_api_conversations__conversation_id__switch_acp_model_post" + } + } }, - "max_tokens": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } } - ], - "title": "Max Tokens" + }, + "description": "Successful Response" }, - "keep_first": { - "type": "integer", - "minimum": 0.0, - "title": "Keep First", - "default": 2 + "400": { + "description": "Agent is not ACP, or provider can't switch models" }, - "hard_context_reset_max_retries": { - "type": "integer", - "exclusiveMinimum": 0.0, - "title": "Hard Context Reset Max Retries", - "default": 5 + "404": { + "description": "Conversation not found" }, - "hard_context_reset_context_scaling": { - "type": "number", - "exclusiveMaximum": 1.0, - "exclusiveMinimum": 0.0, - "title": "Hard Context Reset Context Scaling", - "default": 0.8 + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" }, - "kind": { - "type": "string", - "const": "LLMSummarizingCondenser", - "title": "Kind" + "504": { + "description": "ACP server did not answer the model switch in time" } }, - "type": "object", - "required": [ - "llm", - "kind" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "LLMSummarizingCondenser", - "description": "LLM-based condenser that summarizes forgotten events.\n\nUses an independent LLM (stored in the `llm` attribute) for generating summaries\nof forgotten events. The optional `agent_llm` parameter passed to condense() is\nthe LLM used by the agent for token counting purposes, and you should not assume\nit is the same as the one defined in this condenser." - }, - "ListDirectoryAction": { - "properties": { - "dir_path": { - "type": "string", - "title": "Dir Path", - "description": "The path to the directory to list. Defaults to current directory.", - "default": "." - }, - "recursive": { - "type": "boolean", - "title": "Recursive", - "description": "Whether to list subdirectories recursively (up to 2 levels).", - "default": false - }, - "kind": { - "type": "string", - "const": "ListDirectoryAction", - "title": "Kind" + "summary": "Switch Conversation Acp Model", + "tags": [ + "Conversations" + ] + } + }, + "/api/conversations/{conversation_id}/switch_llm": { + "post": { + "description": "Swap the conversation's LLM to a caller-supplied object.\n\nUsed by app-servers that own the LLM directly and don't push profiles\nto the agent-server's filesystem (see #3017), and by the frontend's\nper-conversation model switch, which forwards a profile config that may\nreference a saved provider connection by id instead of carrying an inline\nAPI key.", + "operationId": "switch_conversation_llm_api_conversations__conversation_id__switch_llm_post", + "parameters": [ + { + "in": "path", + "name": "conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Conversation Id", + "type": "string" + } } - }, - "additionalProperties": false, - "type": "object", - "required": [ - "kind" ], - "title": "ListDirectoryAction", - "description": "Schema for list directory operation." - }, - "ListDirectoryObservation": { - "properties": { + "requestBody": { "content": { - "items": { - "anyOf": [ - { - "$ref": "#/components/schemas/TextContent" - }, - { - "$ref": "#/components/schemas/ImageContent" + "application/json": { + "schema": { + "$ref": "#/components/schemas/Body_switch_conversation_llm_api_conversations__conversation_id__switch_llm_post" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" } - ] + } }, - "type": "array", - "title": "Content", - "description": "Content returned from the tool as a list of TextContent/ImageContent objects. When there is an error, it should be written in this field." + "description": "Successful Response" }, - "is_error": { - "type": "boolean", - "title": "Is Error", - "description": "Whether the observation indicates an error", - "default": false + "404": { + "description": "Conversation not found" }, - "dir_path": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "title": "Dir Path", - "description": "The directory path that was listed." - }, - "entries": { - "items": { - "$ref": "#/components/schemas/FileEntry" }, - "type": "array", - "title": "Entries", - "description": "List of files and directories found." - }, - "total_count": { - "type": "integer", - "title": "Total Count", - "description": "Total number of entries found.", - "default": 0 - }, - "is_truncated": { - "type": "boolean", - "title": "Is Truncated", - "description": "Whether the listing was truncated due to too many entries.", - "default": false - }, - "kind": { - "type": "string", - "const": "ListDirectoryObservation", - "title": "Kind" + "description": "Validation Error" } }, - "additionalProperties": false, - "type": "object", - "required": [ - "kind" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "ListDirectoryObservation", - "description": "Observation from listing a directory." - }, - "ListDirectoryTool": { - "properties": { - "description": { - "type": "string", - "title": "Description" - }, - "action_type": { - "type": "string", - "title": "Action Type" - }, - "observation_type": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "summary": "Switch Conversation Llm", + "tags": [ + "Conversations" + ] + } + }, + "/api/conversations/{conversation_id}/switch_profile": { + "post": { + "description": "Switch the conversation's LLM profile to a named profile.", + "operationId": "switch_conversation_profile_api_conversations__conversation_id__switch_profile_post", + "parameters": [ + { + "in": "path", + "name": "conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Conversation Id", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Body_switch_conversation_profile_api_conversations__conversation_id__switch_profile_post" } - ], - "title": "Observation Type" + } }, - "annotations": { - "anyOf": [ - { - "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" - }, - { - "type": "null" + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } } - ] + }, + "description": "Successful Response" }, - "meta": { - "anyOf": [ - { - "additionalProperties": true, - "type": "object" - }, - { - "type": "null" - } - ], - "title": "Meta" + "400": { + "description": "Invalid or corrupted profile" }, - "kind": { - "type": "string", - "const": "ListDirectoryTool", - "title": "Kind" + "404": { + "description": "Conversation or profile not found" }, - "title": { - "type": "string", - "title": "Title", - "readOnly": true + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" } }, - "type": "object", - "required": [ - "description", - "action_type", - "kind", - "title" - ], - "title": "ListDirectoryTool", - "description": "Tool for listing directory contents with metadata." - }, - "LocalWorkspace-Input": { - "properties": { - "working_dir": { - "type": "string", - "title": "Working Dir", - "description": "The working directory for agent operations and tool execution. Accepts both string paths and Path objects. Path objects are automatically converted to strings." - }, - "kind": { - "type": "string", - "const": "LocalWorkspace", - "title": "Kind" + "security": [ + { + "APIKeyHeader": [] } - }, - "type": "object", - "required": [ - "working_dir" ], - "title": "LocalWorkspace", - "description": "Local workspace implementation that operates on the host filesystem.\n\nLocalWorkspace provides direct access to the local filesystem and command execution\nenvironment. It's suitable for development and testing scenarios where the agent\nshould operate directly on the host system.\n\nExample:\n >>> workspace = LocalWorkspace(working_dir=\"/path/to/project\")\n >>> with workspace:\n ... result = workspace.execute_command(\"ls -la\")\n ... content = workspace.read_file(\"README.md\")" - }, - "LocalWorkspace-Output": { - "properties": { - "working_dir": { - "type": "string", - "title": "Working Dir", - "description": "The working directory for agent operations and tool execution. Accepts both string paths and Path objects. Path objects are automatically converted to strings." - }, - "kind": { - "type": "string", - "const": "LocalWorkspace", - "title": "Kind" + "summary": "Switch Conversation Profile", + "tags": [ + "Conversations" + ] + } + }, + "/api/conversations/{conversation_id}/workspace": { + "get": { + "description": "Serve ``index.html`` from the conversation's workspace root.", + "operationId": "serve_workspace_root_api_conversations__conversation_id__workspace_get", + "parameters": [ + { + "in": "path", + "name": "conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Conversation Id", + "type": "string" + } } - }, - "type": "object", - "required": [ - "working_dir", - "kind" ], - "title": "LocalWorkspace", - "description": "Local workspace implementation that operates on the host filesystem.\n\nLocalWorkspace provides direct access to the local filesystem and command execution\nenvironment. It's suitable for development and testing scenarios where the agent\nshould operate directly on the host system.\n\nExample:\n >>> workspace = LocalWorkspace(working_dir=\"/path/to/project\")\n >>> with workspace:\n ... result = workspace.execute_command(\"ls -la\")\n ... content = workspace.read_file(\"README.md\")" - }, - "LookupSecret-Input": { - "properties": { - "description": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} } - ], - "title": "Description", - "description": "Optional description for this secret" + }, + "description": "Successful Response" }, - "url": { - "type": "string", - "title": "Url" + "404": { + "description": "File or conversation not found" }, - "headers": { - "additionalProperties": { - "type": "string" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } }, - "type": "object", - "title": "Headers" + "description": "Validation Error" + } + }, + "security": [ + { + "APIKeyHeader": [] + }, + { + "APIKeyCookie": [] + } + ], + "summary": "Serve Workspace Root", + "tags": [ + "Workspace" + ] + } + }, + "/api/conversations/{conversation_id}/workspace/{file_path}": { + "get": { + "description": "Serve a file (or directory ``index.html``) from the workspace.", + "operationId": "serve_workspace_file_api_conversations__conversation_id__workspace__file_path__get", + "parameters": [ + { + "in": "path", + "name": "conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Conversation Id", + "type": "string" + } }, - "kind": { - "type": "string", - "const": "LookupSecret", - "title": "Kind" + { + "in": "path", + "name": "file_path", + "required": true, + "schema": { + "title": "File Path", + "type": "string" + } } - }, - "type": "object", - "required": [ - "url" ], - "title": "LookupSecret", - "description": "A secret looked up from some external url" - }, - "LookupSecret-Output": { - "properties": { - "description": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} } - ], - "title": "Description", - "description": "Optional description for this secret" + }, + "description": "Successful Response" }, - "url": { - "type": "string", - "title": "Url" + "404": { + "description": "File or conversation not found" }, - "headers": { - "additionalProperties": { - "type": "string" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } }, - "type": "object", - "title": "Headers" - }, - "kind": { - "type": "string", - "const": "LookupSecret", - "title": "Kind" + "description": "Validation Error" } }, - "type": "object", - "required": [ - "url", - "kind" + "security": [ + { + "APIKeyHeader": [] + }, + { + "APIKeyCookie": [] + } ], - "title": "LookupSecret", - "description": "A secret looked up from some external url" - }, - "MCPToolAction": { - "properties": { - "data": { - "additionalProperties": true, - "type": "object", - "title": "Data", - "description": "Dynamic data fields from the tool call" + "summary": "Serve Workspace File", + "tags": [ + "Workspace" + ] + } + }, + "/api/conversations/{runtime_conversation_id}/bash/bash_commands/{command_id}/stop": { + "post": { + "description": "Stop a running bash command by id without touching the others.\n\nIdempotent: stopping an already-finished command succeeds, while an\nunknown command id reports not-found so the caller can treat it as\nan already-cancelled stop.", + "operationId": "stop_bash_command_api_conversations__runtime_conversation_id__bash_bash_commands__command_id__stop_post", + "parameters": [ + { + "in": "path", + "name": "command_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Command Id", + "type": "string" + } }, - "kind": { - "type": "string", - "const": "MCPToolAction", - "title": "Kind" + { + "in": "path", + "name": "runtime_conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Runtime Conversation Id", + "type": "string" + } } - }, - "additionalProperties": false, - "type": "object", - "required": [ - "kind" ], - "title": "MCPToolAction", - "description": "Schema for MCP input action.\n\nIt is just a thin wrapper around raw JSON and does\nnot do any validation.\n\nValidation will be performed by MCPTool.__call__\nby constructing dynamically created Pydantic model\nfrom the MCP tool input schema." - }, - "MCPToolDefinition": { - "properties": { - "description": { - "type": "string", - "title": "Description" + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } + } + }, + "description": "Successful Response" }, - "action_type": { - "type": "string", - "title": "Action Type" + "404": { + "description": "Item not found" }, - "observation_type": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "title": "Observation Type" - }, - "annotations": { - "anyOf": [ - { - "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" - }, - { - "type": "null" + }, + "description": "Validation Error" + } + }, + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Stop Bash Command", + "tags": [ + "Bash" + ] + } + }, + "/api/conversations/{runtime_conversation_id}/bash/bash_events": { + "delete": { + "description": "Clear all bash events from storage", + "operationId": "clear_all_bash_events_api_conversations__runtime_conversation_id__bash_bash_events_delete", + "parameters": [ + { + "in": "path", + "name": "runtime_conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Runtime Conversation Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "additionalProperties": { + "type": "integer" + }, + "title": "Response Clear All Bash Events Api Conversations Runtime Conversation Id Bash Bash Events Delete", + "type": "object" + } } - ] + }, + "description": "Successful Response" }, - "meta": { - "anyOf": [ - { - "additionalProperties": true, - "type": "object" - }, - { - "type": "null" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "title": "Meta" - }, - "mcp_tool": { - "$ref": "#/components/schemas/mcp__types__Tool", - "description": "The MCP tool definition." - }, - "kind": { - "type": "string", - "const": "MCPToolDefinition", - "title": "Kind" - }, - "title": { - "type": "string", - "title": "Title", - "readOnly": true + }, + "description": "Validation Error" } }, - "type": "object", - "required": [ - "description", - "action_type", - "mcp_tool", - "kind", - "title" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "MCPToolDefinition", - "description": "MCP Tool that wraps an MCP client and provides tool functionality." - }, - "MCPToolObservation": { - "properties": { + "summary": "Clear All Bash Events", + "tags": [ + "Bash" + ] + } + }, + "/api/conversations/{runtime_conversation_id}/bash/bash_events/": { + "get": { + "description": "Get a batch of bash event events given their ids, returning null for any\nmissing item.", + "operationId": "batch_get_bash_events_api_conversations__runtime_conversation_id__bash_bash_events__get", + "parameters": [ + { + "in": "path", + "name": "runtime_conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Runtime Conversation Id", + "type": "string" + } + } + ], + "requestBody": { "content": { - "items": { - "anyOf": [ - { - "$ref": "#/components/schemas/TextContent" + "application/json": { + "schema": { + "items": { + "type": "string" }, - { - "$ref": "#/components/schemas/ImageContent" + "title": "Event Ids", + "type": "array" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/BashEventBase" + }, + { + "type": "null" + } + ] + }, + "title": "Response Batch Get Bash Events Api Conversations Runtime Conversation Id Bash Bash Events Get", + "type": "array" } - ] + } }, - "type": "array", - "title": "Content", - "description": "Content returned from the tool as a list of TextContent/ImageContent objects. When there is an error, it should be written in this field." - }, - "is_error": { - "type": "boolean", - "title": "Is Error", - "description": "Whether the observation indicates an error", - "default": false - }, - "tool_name": { - "type": "string", - "title": "Tool Name", - "description": "Name of the tool that was called" + "description": "Successful Response" }, - "kind": { - "type": "string", - "const": "MCPToolObservation", - "title": "Kind" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" } }, - "additionalProperties": false, - "type": "object", - "required": [ - "tool_name", - "kind" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "MCPToolObservation", - "description": "Observation from MCP tool execution." - }, - "Message": { - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "system", - "assistant", - "tool" - ], - "title": "Role" + "summary": "Batch Get Bash Events", + "tags": [ + "Bash" + ] + } + }, + "/api/conversations/{runtime_conversation_id}/bash/bash_events/search": { + "get": { + "description": "Search / List bash event events", + "operationId": "search_bash_events_api_conversations__runtime_conversation_id__bash_bash_events_search_get", + "parameters": [ + { + "in": "path", + "name": "runtime_conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Runtime Conversation Id", + "type": "string" + } }, - "content": { - "items": { + { + "in": "query", + "name": "kind__eq", + "required": false, + "schema": { "anyOf": [ { - "$ref": "#/components/schemas/TextContent" + "enum": [ + "BashCommand", + "BashOutput" + ], + "type": "string" }, { - "$ref": "#/components/schemas/ImageContent" + "type": "null" } - ] - }, - "type": "array", - "title": "Content" + ], + "title": "Kind Eq" + } }, - "tool_calls": { - "anyOf": [ - { - "items": { - "$ref": "#/components/schemas/MessageToolCall" + { + "in": "query", + "name": "command_id__eq", + "required": false, + "schema": { + "anyOf": [ + { + "format": "uuid", + "type": "string" }, - "type": "array" - }, - { - "type": "null" - } - ], - "title": "Tool Calls" + { + "type": "null" + } + ], + "title": "Command Id Eq" + } }, - "tool_call_id": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Tool Call Id" + { + "in": "query", + "name": "timestamp__gte", + "required": false, + "schema": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Timestamp Gte" + } }, - "name": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Name" + { + "in": "query", + "name": "timestamp__lt", + "required": false, + "schema": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Timestamp Lt" + } }, - "reasoning_content": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Reasoning Content", - "description": "Intermediate reasoning/thinking content from reasoning models" + { + "description": "Only returns BashOutput events with order > this value. Useful for polling to fetch only new events since the last poll.", + "in": "query", + "name": "order__gt", + "required": false, + "schema": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Only returns BashOutput events with order > this value. Useful for polling to fetch only new events since the last poll.", + "title": "Filter to events with order greater than this value" + } }, - "thinking_blocks": { - "items": { + { + "in": "query", + "name": "sort_order", + "required": false, + "schema": { + "$ref": "#/components/schemas/BashEventSortOrder", + "default": "TIMESTAMP" + } + }, + { + "in": "query", + "name": "page_id", + "required": false, + "schema": { "anyOf": [ { - "$ref": "#/components/schemas/ThinkingBlock" + "type": "string" }, { - "$ref": "#/components/schemas/RedactedThinkingBlock" + "type": "null" + } + ], + "title": "Optional next_page_id from the previously returned page" + } + }, + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 100, + "exclusiveMinimum": 0, + "maximum": 100, + "title": "The max number of results in the page", + "type": "integer" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BashEventPage" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Search Bash Events", + "tags": [ + "Bash" + ] + } + }, + "/api/conversations/{runtime_conversation_id}/bash/bash_events/{event_id}": { + "get": { + "description": "Get a bash event event given an id", + "operationId": "get_bash_event_api_conversations__runtime_conversation_id__bash_bash_events__event_id__get", + "parameters": [ + { + "in": "path", + "name": "event_id", + "required": true, + "schema": { + "title": "Event Id", + "type": "string" + } + }, + { + "in": "path", + "name": "runtime_conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Runtime Conversation Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BashEventBase" } - ] + } }, - "type": "array", - "title": "Thinking Blocks", - "description": "Raw Anthropic thinking blocks for extended thinking feature" + "description": "Successful Response" }, - "responses_reasoning_item": { - "anyOf": [ - { - "$ref": "#/components/schemas/ReasoningItemModel" - }, - { - "type": "null" + "404": { + "description": "Item not found" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "description": "OpenAI Responses reasoning item from model output" + }, + "description": "Validation Error" } }, - "type": "object", - "required": [ - "role" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "Message" - }, - "MessageEvent": { - "properties": { - "id": { - "type": "string", - "title": "Id", - "description": "Unique event id (ULID/UUID)" - }, - "timestamp": { - "type": "string", - "title": "Timestamp", - "description": "Event timestamp" - }, - "source": { - "type": "string", - "enum": [ - "agent", - "user", - "environment" - ], - "title": "Source" - }, - "llm_message": { - "$ref": "#/components/schemas/Message", - "description": "The exact LLM message for this message event" - }, - "llm_response_id": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "summary": "Get Bash Event", + "tags": [ + "Bash" + ] + } + }, + "/api/conversations/{runtime_conversation_id}/bash/execute_bash_command": { + "post": { + "description": "Execute a bash command and wait for a result", + "operationId": "execute_bash_command_api_conversations__runtime_conversation_id__bash_execute_bash_command_post", + "parameters": [ + { + "in": "path", + "name": "runtime_conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Runtime Conversation Id", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ExecuteBashRequest" } - ], - "title": "Llm Response Id", - "description": "Completion or Response ID of the LLM response that generated this eventIf the source != 'agent', this field is None" + } }, - "activated_skills": { - "items": { - "type": "string" + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BashOutput" + } + } }, - "type": "array", - "title": "Activated Skills", - "description": "List of activated skill name" + "description": "Successful Response" }, - "extended_content": { - "items": { - "$ref": "#/components/schemas/TextContent" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } }, - "type": "array", - "title": "Extended Content", - "description": "List of content added by agent context" - }, - "sender": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "description": "Validation Error" + } + }, + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Execute Bash Command", + "tags": [ + "Bash" + ] + } + }, + "/api/conversations/{runtime_conversation_id}/bash/start_bash_command": { + "post": { + "description": "Execute a bash command in the background", + "operationId": "start_bash_command_api_conversations__runtime_conversation_id__bash_start_bash_command_post", + "parameters": [ + { + "in": "path", + "name": "runtime_conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Runtime Conversation Id", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ExecuteBashRequest" } - ], - "title": "Sender", - "description": "Optional identifier of the sender. Can be used to track message origin in multi-agent scenarios." + } }, - "critic_result": { - "anyOf": [ - { - "$ref": "#/components/schemas/CriticResult" - }, - { - "type": "null" + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BashCommand" + } } - ], - "description": "Optional critic evaluation of this message and preceding history." + }, + "description": "Successful Response" }, - "kind": { - "type": "string", - "const": "MessageEvent", - "title": "Kind" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" } }, - "additionalProperties": false, - "type": "object", - "required": [ - "source", - "llm_message", - "kind" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "MessageEvent", - "description": "Message from either agent or user.\n\nThis is originally the \"MessageAction\", but it suppose not to be tool call." - }, - "MessageToolCall": { - "properties": { - "id": { - "type": "string", - "title": "Id", - "description": "Canonical tool call id" + "summary": "Start Bash Command", + "tags": [ + "Bash" + ] + } + }, + "/api/conversations/{runtime_conversation_id}/file/archive": { + "get": { + "description": "Archive a workspace directory for persistence before runtime deletion.\n\nProduces a downloadable archive of ``path``. Symlinks are never followed\nout of the requested directory, so the archive cannot include files from\noutside it. The temporary archive is created outside ``path`` and removed\nafter the response is sent.", + "operationId": "archive_directory_api_conversations__runtime_conversation_id__file_archive_get", + "parameters": [ + { + "in": "path", + "name": "runtime_conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Runtime Conversation Id", + "type": "string" + } }, - "name": { - "type": "string", - "title": "Name", - "description": "Tool/function name" + { + "description": "Absolute path of the directory to archive", + "in": "query", + "name": "path", + "required": true, + "schema": { + "description": "Absolute path of the directory to archive", + "title": "Path", + "type": "string" + } }, - "arguments": { - "type": "string", - "title": "Arguments", - "description": "JSON string of arguments" + { + "description": "Archive format: 'git-delta' for a git patch of the working-tree changes against a base ref (requires a git repository); 'tar.gz' for a full gzip tarball of the entire directory (works on non-git directories too).", + "in": "query", + "name": "format", + "required": false, + "schema": { + "default": "git-delta", + "description": "Archive format: 'git-delta' for a git patch of the working-tree changes against a base ref (requires a git repository); 'tar.gz' for a full gzip tarball of the entire directory (works on non-git directories too).", + "enum": [ + "git-delta", + "tar.gz" + ], + "title": "Format", + "type": "string" + } + }, + { + "description": "Only for format='git-delta': base ref to diff against. Defaults to the auto-detected comparison ref (origin branch, merge-base, or the empty tree for a fresh repo). Ignored for format='tar.gz'.", + "in": "query", + "name": "base_ref", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Only for format='git-delta': base ref to diff against. Defaults to the auto-detected comparison ref (origin branch, merge-base, or the empty tree for a fresh repo). Ignored for format='tar.gz'.", + "title": "Base Ref" + } + }, + { + "description": "Whether to apply the built-in default exclude patterns (node_modules/, .venv/, caches, build outputs, etc.). Defaults to true for compact archives; set false to allow a full workspace capture, including fat directories.", + "in": "query", + "name": "use_default_excludes", + "required": false, + "schema": { + "default": true, + "description": "Whether to apply the built-in default exclude patterns (node_modules/, .venv/, caches, build outputs, etc.). Defaults to true for compact archives; set false to allow a full workspace capture, including fat directories.", + "title": "Use Default Excludes", + "type": "boolean" + } }, - "origin": { - "type": "string", - "enum": [ - "completion", - "responses" - ], - "title": "Origin", - "description": "Originating API family" + { + "description": "Additional glob patterns to exclude (repeatable, e.g. ?exclude=foo&exclude=*.bin). Combined with the built-in default excludes when use_default_excludes=true; used by itself when use_default_excludes=false.", + "in": "query", + "name": "exclude", + "required": false, + "schema": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Additional glob patterns to exclude (repeatable, e.g. ?exclude=foo&exclude=*.bin). Combined with the built-in default excludes when use_default_excludes=true; used by itself when use_default_excludes=false.", + "title": "Exclude" + } } - }, - "type": "object", - "required": [ - "id", - "name", - "arguments", - "origin" ], - "title": "MessageToolCall", - "description": "Transport-agnostic tool call representation.\n\nOne canonical id is used for linking across actions/observations and\nfor Responses function_call_output call_id." - }, - "Metrics": { - "properties": { - "model_name": { - "type": "string", - "title": "Model Name", - "description": "Name of the model", - "default": "default" - }, - "accumulated_cost": { - "type": "number", - "minimum": 0.0, - "title": "Accumulated Cost", - "description": "Total accumulated cost, must be non-negative", - "default": 0.0 - }, - "max_budget_per_task": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "null" + "responses": { + "200": { + "content": { + "application/octet-stream": { + "schema": { + "format": "binary", + "type": "string" + } } - ], - "title": "Max Budget Per Task", - "description": "Maximum budget per task" + }, + "description": "Successful Response" }, - "accumulated_token_usage": { - "anyOf": [ - { - "$ref": "#/components/schemas/TokenUsage" - }, - { - "type": "null" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "description": "Accumulated token usage across all calls" - }, - "costs": { - "items": { - "$ref": "#/components/schemas/Cost" }, - "type": "array", - "title": "Costs", - "description": "List of individual costs" + "description": "Validation Error" + } + }, + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Archive Directory", + "tags": [ + "Files" + ] + } + }, + "/api/conversations/{runtime_conversation_id}/file/create_directory": { + "post": { + "description": "Create a directory in the workspace, including any missing parents.\n\nIdempotent: an existing directory succeeds and its contents are left\nuntouched. Creating over an existing file, or under a path whose parent is\na file, is a client error (400) rather than a server fault.", + "operationId": "create_directory_api_conversations__runtime_conversation_id__file_create_directory_post", + "parameters": [ + { + "in": "path", + "name": "runtime_conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Runtime Conversation Id", + "type": "string" + } }, - "response_latencies": { - "items": { - "$ref": "#/components/schemas/ResponseLatency" + { + "description": "Absolute directory path to create", + "in": "query", + "name": "path", + "required": true, + "schema": { + "description": "Absolute directory path to create", + "title": "Path", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } + } }, - "type": "array", - "title": "Response Latencies", - "description": "List of response latencies" + "description": "Successful Response" }, - "token_usages": { - "items": { - "$ref": "#/components/schemas/TokenUsage" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } }, - "type": "array", - "title": "Token Usages", - "description": "List of token usage records" + "description": "Validation Error" } }, - "type": "object", - "title": "Metrics", - "description": "Metrics class can record various metrics during running and evaluation.\nWe track:\n - accumulated_cost and costs\n - max_budget_per_task (budget limit)\n - A list of ResponseLatency\n - A list of TokenUsage (one per call)." - }, - "MetricsSnapshot": { - "properties": { - "model_name": { - "type": "string", - "title": "Model Name", - "description": "Name of the model", - "default": "default" - }, - "accumulated_cost": { - "type": "number", - "minimum": 0.0, - "title": "Accumulated Cost", - "description": "Total accumulated cost, must be non-negative", - "default": 0.0 + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Create Directory", + "tags": [ + "Files" + ] + } + }, + "/api/conversations/{runtime_conversation_id}/file/download": { + "get": { + "description": "Download a file from the workspace using query parameter (preferred method).", + "operationId": "download_file_query_api_conversations__runtime_conversation_id__file_download_get", + "parameters": [ + { + "in": "path", + "name": "runtime_conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Runtime Conversation Id", + "type": "string" + } }, - "max_budget_per_task": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "null" + { + "description": "Absolute file path", + "in": "query", + "name": "path", + "required": true, + "schema": { + "description": "Absolute file path", + "title": "Path", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/octet-stream": { + "schema": { + "format": "binary", + "type": "string" + } } - ], - "title": "Max Budget Per Task", - "description": "Maximum budget per task" + }, + "description": "Successful Response" }, - "accumulated_token_usage": { - "anyOf": [ - { - "$ref": "#/components/schemas/TokenUsage" - }, - { - "type": "null" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "description": "Accumulated token usage across all calls" - } - }, - "type": "object", - "title": "MetricsSnapshot", - "description": "A snapshot of metrics at a point in time.\n\nDoes not include lists of individual costs, latencies, or token usages." - }, - "NeverConfirm-Input": { - "properties": { - "kind": { - "type": "string", - "const": "NeverConfirm", - "title": "Kind" + }, + "description": "Validation Error" } }, - "type": "object", - "title": "NeverConfirm" - }, - "NeverConfirm-Output": { - "properties": { - "kind": { - "type": "string", - "const": "NeverConfirm", - "title": "Kind" + "security": [ + { + "APIKeyHeader": [] } - }, - "type": "object", - "required": [ - "kind" ], - "title": "NeverConfirm" - }, - "NoOpCondenser-Input": { - "properties": { - "kind": { - "type": "string", - "const": "NoOpCondenser", - "title": "Kind" + "summary": "Download File Query", + "tags": [ + "Files" + ] + } + }, + "/api/conversations/{runtime_conversation_id}/file/download-trajectory/{conversation_id}": { + "get": { + "description": "Download a zip archive of a conversation trajectory.", + "operationId": "download_trajectory_api_conversations__runtime_conversation_id__file_download_trajectory__conversation_id__get", + "parameters": [ + { + "in": "path", + "name": "conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Conversation Id", + "type": "string" + } + }, + { + "in": "path", + "name": "runtime_conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Runtime Conversation Id", + "type": "string" + } } - }, - "type": "object", - "title": "NoOpCondenser", - "description": "Simple condenser that returns a view un-manipulated.\n\nPrimarily intended for testing purposes." - }, - "NoOpCondenser-Output": { - "properties": { - "kind": { - "type": "string", - "const": "NoOpCondenser", - "title": "Kind" + ], + "responses": { + "200": { + "content": { + "application/octet-stream": { + "schema": { + "format": "binary", + "type": "string" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" } }, - "type": "object", - "required": [ - "kind" - ], - "title": "NoOpCondenser", - "description": "Simple condenser that returns a view un-manipulated.\n\nPrimarily intended for testing purposes." - }, - "Observation": { - "oneOf": [ - { - "$ref": "#/components/schemas/MCPToolObservation" - }, + "security": [ { - "$ref": "#/components/schemas/FinishObservation" - }, + "APIKeyHeader": [] + } + ], + "summary": "Download Trajectory", + "tags": [ + "Files" + ] + } + }, + "/api/conversations/{runtime_conversation_id}/file/upload": { + "post": { + "description": "Upload a file to the workspace using query parameter (preferred method).", + "operationId": "upload_file_query_api_conversations__runtime_conversation_id__file_upload_post", + "parameters": [ { - "$ref": "#/components/schemas/ThinkObservation" + "in": "path", + "name": "runtime_conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Runtime Conversation Id", + "type": "string" + } }, { - "$ref": "#/components/schemas/BrowserObservation" + "description": "Absolute file path", + "in": "query", + "name": "path", + "required": true, + "schema": { + "description": "Absolute file path", + "title": "Path", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "$ref": "#/components/schemas/Body_upload_file_query_api_conversations__runtime_conversation_id__file_upload_post" + } + } }, - { - "$ref": "#/components/schemas/FileEditorObservation" + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } + } + }, + "description": "Successful Response" }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "security": [ { - "$ref": "#/components/schemas/EditObservation" - }, + "APIKeyHeader": [] + } + ], + "summary": "Upload File Query", + "tags": [ + "Files" + ] + } + }, + "/api/conversations/{runtime_conversation_id}/git/changes": { + "get": { + "description": "Get git changes using query parameter (preferred method).", + "operationId": "git_changes_query_api_conversations__runtime_conversation_id__git_changes_get", + "parameters": [ { - "$ref": "#/components/schemas/ListDirectoryObservation" + "in": "path", + "name": "runtime_conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Runtime Conversation Id", + "type": "string" + } }, { - "$ref": "#/components/schemas/ReadFileObservation" + "description": "The git repository path", + "in": "query", + "name": "path", + "required": true, + "schema": { + "description": "The git repository path", + "title": "Path", + "type": "string" + } }, { - "$ref": "#/components/schemas/WriteFileObservation" + "description": "Optional git ref to diff against (e.g. 'HEAD' for git status-style changes, or a commit hash). When omitted, the upstream/default branch is auto-detected.", + "in": "query", + "name": "ref", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Optional git ref to diff against (e.g. 'HEAD' for git status-style changes, or a commit hash). When omitted, the upstream/default branch is auto-detected.", + "title": "Ref" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "items": { + "$ref": "#/components/schemas/GitChange" + }, + "title": "Response Git Changes Query Api Conversations Runtime Conversation Id Git Changes Get", + "type": "array" + } + } + }, + "description": "Successful Response" }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "security": [ { - "$ref": "#/components/schemas/GlobObservation" - }, + "APIKeyHeader": [] + } + ], + "summary": "Git Changes Query", + "tags": [ + "Git" + ] + } + }, + "/api/conversations/{runtime_conversation_id}/git/commits": { + "get": { + "description": "List the repository's most recent commits, newest first.", + "operationId": "git_commits_query_api_conversations__runtime_conversation_id__git_commits_get", + "parameters": [ { - "$ref": "#/components/schemas/GrepObservation" + "in": "path", + "name": "runtime_conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Runtime Conversation Id", + "type": "string" + } }, { - "$ref": "#/components/schemas/PlanningFileEditorObservation" + "description": "The git repository path", + "in": "query", + "name": "path", + "required": true, + "schema": { + "description": "The git repository path", + "title": "Path", + "type": "string" + } }, { - "$ref": "#/components/schemas/TaskTrackerObservation" + "description": "Maximum commits to return", + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 50, + "description": "Maximum commits to return", + "maximum": 200, + "minimum": 1, + "title": "Limit", + "type": "integer" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GitCommitsPage" + } + } + }, + "description": "Successful Response" }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "security": [ { - "$ref": "#/components/schemas/TerminalObservation" + "APIKeyHeader": [] } ], - "discriminator": { - "propertyName": "kind", - "mapping": { - "openhands__sdk__mcp__definition__MCPToolObservation-Output__1": "#/components/schemas/MCPToolObservation", - "openhands__sdk__tool__builtins__finish__FinishObservation-Output__1": "#/components/schemas/FinishObservation", - "openhands__sdk__tool__builtins__think__ThinkObservation-Output__1": "#/components/schemas/ThinkObservation", - "openhands__tools__browser_use__definition__BrowserObservation-Output__1": "#/components/schemas/BrowserObservation", - "openhands__tools__file_editor__definition__FileEditorObservation-Output__1": "#/components/schemas/FileEditorObservation", - "openhands__tools__gemini__edit__definition__EditObservation-Output__1": "#/components/schemas/EditObservation", - "openhands__tools__gemini__list_directory__definition__ListDirectoryObservation-Output__1": "#/components/schemas/ListDirectoryObservation", - "openhands__tools__gemini__read_file__definition__ReadFileObservation-Output__1": "#/components/schemas/ReadFileObservation", - "openhands__tools__gemini__write_file__definition__WriteFileObservation-Output__1": "#/components/schemas/WriteFileObservation", - "openhands__tools__glob__definition__GlobObservation-Output__1": "#/components/schemas/GlobObservation", - "openhands__tools__grep__definition__GrepObservation-Output__1": "#/components/schemas/GrepObservation", - "openhands__tools__planning_file_editor__definition__PlanningFileEditorObservation-Output__1": "#/components/schemas/PlanningFileEditorObservation", - "openhands__tools__task_tracker__definition__TaskTrackerObservation-Output__1": "#/components/schemas/TaskTrackerObservation", - "openhands__tools__terminal__definition__TerminalObservation-Output__1": "#/components/schemas/TerminalObservation" - } - } - }, - "ObservationEvent": { - "properties": { - "id": { - "type": "string", - "title": "Id", - "description": "Unique event id (ULID/UUID)" - }, - "timestamp": { - "type": "string", - "title": "Timestamp", - "description": "Event timestamp" - }, - "source": { - "type": "string", - "enum": [ - "agent", - "user", - "environment" - ], - "title": "Source", - "default": "environment" - }, - "tool_name": { - "type": "string", - "title": "Tool Name", - "description": "The tool name that this observation is responding to" - }, - "tool_call_id": { - "type": "string", - "title": "Tool Call Id", - "description": "The tool call id that this observation is responding to" + "summary": "Git Commits Query", + "tags": [ + "Git" + ] + } + }, + "/api/conversations/{runtime_conversation_id}/git/commits/{sha}/changes": { + "get": { + "description": "Get the files changed by a single commit (vs its first parent).", + "operationId": "git_commit_changes_query_api_conversations__runtime_conversation_id__git_commits__sha__changes_get", + "parameters": [ + { + "description": "Commit SHA", + "in": "path", + "name": "sha", + "required": true, + "schema": { + "description": "Commit SHA", + "pattern": "^[0-9a-fA-F]{4,64}$", + "title": "Sha", + "type": "string" + } }, - "observation": { - "$ref": "#/components/schemas/Observation", - "description": "The observation (tool call) sent to LLM" + { + "in": "path", + "name": "runtime_conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Runtime Conversation Id", + "type": "string" + } }, - "action_id": { - "type": "string", - "title": "Action Id", - "description": "The action id that this observation is responding to" + { + "description": "The git repository path", + "in": "query", + "name": "path", + "required": true, + "schema": { + "description": "The git repository path", + "title": "Path", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "items": { + "$ref": "#/components/schemas/GitChange" + }, + "title": "Response Git Commit Changes Query Api Conversations Runtime Conversation Id Git Commits Sha Changes Get", + "type": "array" + } + } + }, + "description": "Successful Response" }, - "kind": { - "type": "string", - "const": "ObservationEvent", - "title": "Kind" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" } }, - "additionalProperties": false, - "type": "object", - "required": [ - "tool_name", - "tool_call_id", - "observation", - "action_id", - "kind" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "ObservationEvent" - }, - "OrgConfig": { - "properties": { - "repository": { - "type": "string", - "title": "Repository", - "description": "Selected repository (e.g., 'owner/repo')" + "summary": "Git Commit Changes Query", + "tags": [ + "Git" + ] + } + }, + "/api/conversations/{runtime_conversation_id}/git/diff": { + "get": { + "description": "Get git diff using query parameter (preferred method).", + "operationId": "git_diff_query_api_conversations__runtime_conversation_id__git_diff_get", + "parameters": [ + { + "in": "path", + "name": "runtime_conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Runtime Conversation Id", + "type": "string" + } }, - "provider": { - "type": "string", - "title": "Provider", - "description": "Git provider type: github, gitlab, azure, bitbucket" + { + "description": "The file path to get diff for", + "in": "query", + "name": "path", + "required": true, + "schema": { + "description": "The file path to get diff for", + "title": "Path", + "type": "string" + } }, - "org_repo_url": { - "type": "string", - "title": "Org Repo Url", - "description": "Pre-authenticated Git URL for the organization repository. Contains sensitive credentials - handle with care and avoid logging." + { + "description": "Optional git ref to diff against (e.g. 'HEAD' for git status-style changes, or a commit hash). When omitted, the upstream/default branch is auto-detected.", + "in": "query", + "name": "ref", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Optional git ref to diff against (e.g. 'HEAD' for git status-style changes, or a commit hash). When omitted, the upstream/default branch is auto-detected.", + "title": "Ref" + } }, - "org_name": { - "type": "string", - "title": "Org Name", - "description": "Organization name" + { + "description": "Optional commit SHA. When set, the diff is the change that commit introduced (vs its first parent), read entirely from git objects so deleted files still render. Mutually exclusive with 'ref'.", + "in": "query", + "name": "commit", + "required": false, + "schema": { + "anyOf": [ + { + "pattern": "^[0-9a-fA-F]{4,64}$", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Optional commit SHA. When set, the diff is the change that commit introduced (vs its first parent), read entirely from git objects so deleted files still render. Mutually exclusive with 'ref'.", + "title": "Commit" + } } - }, - "type": "object", - "required": [ - "repository", - "provider", - "org_repo_url", - "org_name" ], - "title": "OrgConfig", - "description": "Configuration for loading organization-level skills." - }, - "PassCritic-Input": { - "properties": { - "mode": { - "type": "string", - "enum": [ - "finish_and_message", - "all_actions" - ], - "title": "Mode", - "description": "When to run critic evaluation:\n- 'finish_and_message': Evaluate on FinishAction and agent MessageEvent (default, minimal performance impact)\n- 'all_actions': Evaluate after every agent action (WARNING: significantly slower due to API calls on each action)", - "default": "finish_and_message" + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GitDiff" + } + } + }, + "description": "Successful Response" }, - "iterative_refinement": { - "anyOf": [ - { - "$ref": "#/components/schemas/IterativeRefinementConfig" - }, - { - "type": "null" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "description": "Optional configuration for iterative refinement. When set, Conversation.run() will automatically retry the task if the critic score is below the success_threshold, up to max_iterations." + }, + "description": "Validation Error" + } + }, + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Git Diff Query", + "tags": [ + "Git" + ] + } + }, + "/api/conversations/{runtime_conversation_id}/vscode/status": { + "get": { + "description": "Get the VSCode server status.\n\nReturns:\n Dictionary with running status and enabled status", + "operationId": "get_vscode_status_api_conversations__runtime_conversation_id__vscode_status_get", + "parameters": [ + { + "in": "path", + "name": "runtime_conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Runtime Conversation Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "additionalProperties": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + } + ] + }, + "title": "Response Get Vscode Status Api Conversations Runtime Conversation Id Vscode Status Get", + "type": "object" + } + } + }, + "description": "Successful Response" }, - "kind": { - "type": "string", - "const": "PassCritic", - "title": "Kind" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" } }, - "type": "object", - "title": "PassCritic", - "description": "Critic that always returns success.\n\nThis critic can be used when no evaluation is needed or when\nall instances should be considered successful regardless of their output." - }, - "PassCritic-Output": { - "properties": { - "mode": { - "type": "string", - "enum": [ - "finish_and_message", - "all_actions" - ], - "title": "Mode", - "description": "When to run critic evaluation:\n- 'finish_and_message': Evaluate on FinishAction and agent MessageEvent (default, minimal performance impact)\n- 'all_actions': Evaluate after every agent action (WARNING: significantly slower due to API calls on each action)", - "default": "finish_and_message" + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Get Vscode Status" + } + }, + "/api/conversations/{runtime_conversation_id}/vscode/url": { + "get": { + "operationId": "get_runtime_vscode_url_api_conversations__runtime_conversation_id__vscode_url_get", + "parameters": [ + { + "in": "path", + "name": "runtime_conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Runtime Conversation Id", + "type": "string" + } }, - "iterative_refinement": { - "anyOf": [ - { - "$ref": "#/components/schemas/IterativeRefinementConfig" - }, - { - "type": "null" + { + "in": "query", + "name": "base_url", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Base Url" + } + }, + { + "in": "query", + "name": "workspace_dir", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Workspace Dir" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VSCodeUrlResponse" + } } - ], - "description": "Optional configuration for iterative refinement. When set, Conversation.run() will automatically retry the task if the critic score is below the success_threshold, up to max_iterations." + }, + "description": "Successful Response" }, - "kind": { - "type": "string", - "const": "PassCritic", - "title": "Kind" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" } }, - "type": "object", - "required": [ - "kind" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "PassCritic", - "description": "Critic that always returns success.\n\nThis critic can be used when no evaluation is needed or when\nall instances should be considered successful regardless of their output." - }, - "PauseEvent": { - "properties": { - "id": { - "type": "string", - "title": "Id", - "description": "Unique event id (ULID/UUID)" + "summary": "Get Runtime Vscode Url" + } + }, + "/api/file/archive": { + "get": { + "description": "Archive a workspace directory for persistence before runtime deletion.\n\nProduces a downloadable archive of ``path``. Symlinks are never followed\nout of the requested directory, so the archive cannot include files from\noutside it. The temporary archive is created outside ``path`` and removed\nafter the response is sent.", + "operationId": "archive_directory_api_file_archive_get", + "parameters": [ + { + "description": "Absolute path of the directory to archive", + "in": "query", + "name": "path", + "required": true, + "schema": { + "description": "Absolute path of the directory to archive", + "title": "Path", + "type": "string" + } }, - "timestamp": { - "type": "string", - "title": "Timestamp", - "description": "Event timestamp" + { + "description": "Archive format: 'git-delta' for a git patch of the working-tree changes against a base ref (requires a git repository); 'tar.gz' for a full gzip tarball of the entire directory (works on non-git directories too).", + "in": "query", + "name": "format", + "required": false, + "schema": { + "default": "git-delta", + "description": "Archive format: 'git-delta' for a git patch of the working-tree changes against a base ref (requires a git repository); 'tar.gz' for a full gzip tarball of the entire directory (works on non-git directories too).", + "enum": [ + "git-delta", + "tar.gz" + ], + "title": "Format", + "type": "string" + } }, - "source": { - "type": "string", - "enum": [ - "agent", - "user", - "environment" - ], - "title": "Source", - "default": "user" + { + "description": "Only for format='git-delta': base ref to diff against. Defaults to the auto-detected comparison ref (origin branch, merge-base, or the empty tree for a fresh repo). Ignored for format='tar.gz'.", + "in": "query", + "name": "base_ref", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Only for format='git-delta': base ref to diff against. Defaults to the auto-detected comparison ref (origin branch, merge-base, or the empty tree for a fresh repo). Ignored for format='tar.gz'.", + "title": "Base Ref" + } }, - "kind": { - "type": "string", - "const": "PauseEvent", - "title": "Kind" + { + "description": "Whether to apply the built-in default exclude patterns (node_modules/, .venv/, caches, build outputs, etc.). Defaults to true for compact archives; set false to allow a full workspace capture, including fat directories.", + "in": "query", + "name": "use_default_excludes", + "required": false, + "schema": { + "default": true, + "description": "Whether to apply the built-in default exclude patterns (node_modules/, .venv/, caches, build outputs, etc.). Defaults to true for compact archives; set false to allow a full workspace capture, including fat directories.", + "title": "Use Default Excludes", + "type": "boolean" + } + }, + { + "description": "Additional glob patterns to exclude (repeatable, e.g. ?exclude=foo&exclude=*.bin). Combined with the built-in default excludes when use_default_excludes=true; used by itself when use_default_excludes=false.", + "in": "query", + "name": "exclude", + "required": false, + "schema": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Additional glob patterns to exclude (repeatable, e.g. ?exclude=foo&exclude=*.bin). Combined with the built-in default excludes when use_default_excludes=true; used by itself when use_default_excludes=false.", + "title": "Exclude" + } } - }, - "additionalProperties": false, - "type": "object", - "required": [ - "kind" ], - "title": "PauseEvent", - "description": "Event indicating that the agent execution was paused by user request." - }, - "PipelineCondenser-Input": { - "properties": { - "condensers": { - "items": { - "$ref": "#/components/schemas/CondenserBase-Input" + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + }, + "application/octet-stream": { + "schema": { + "format": "binary", + "type": "string" + } + } }, - "type": "array", - "title": "Condensers" + "description": "Successful Response" }, - "kind": { - "type": "string", - "const": "PipelineCondenser", - "title": "Kind" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" } }, - "type": "object", - "required": [ - "condensers" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "PipelineCondenser", - "description": "A condenser that applies a sequence of condensers in order.\n\nAll condensers are defined primarily by their `condense` method, which takes a\n`View` and an optional `agent_llm` parameter, returning either a new `View` or a\n`Condensation` event. That means we can chain multiple condensers together by\npassing `View`s along and exiting early if any condenser returns a `Condensation`.\n\nFor example:\n\n # Use the pipeline condenser to chain multiple other condensers together\n condenser = PipelineCondenser(condensers=[\n CondenserA(...),\n CondenserB(...),\n CondenserC(...),\n ])\n\n result = condenser.condense(view, agent_llm=agent_llm)\n\n # Doing the same thing without the pipeline condenser requires more boilerplate\n # for the monadic chaining\n other_result = view\n\n if isinstance(other_result, View):\n other_result = CondenserA(...).condense(other_result, agent_llm=agent_llm)\n\n if isinstance(other_result, View):\n other_result = CondenserB(...).condense(other_result, agent_llm=agent_llm)\n\n if isinstance(other_result, View):\n other_result = CondenserC(...).condense(other_result, agent_llm=agent_llm)\n\n assert result == other_result" - }, - "PipelineCondenser-Output": { - "properties": { - "condensers": { - "items": { - "$ref": "#/components/schemas/CondenserBase-Output" + "summary": "Archive Directory", + "tags": [ + "Files" + ] + } + }, + "/api/file/create_directory": { + "post": { + "description": "Create a directory in the workspace, including any missing parents.\n\nIdempotent: an existing directory succeeds and its contents are left\nuntouched. Creating over an existing file, or under a path whose parent is\na file, is a client error (400) rather than a server fault.", + "operationId": "create_directory_api_file_create_directory_post", + "parameters": [ + { + "description": "Absolute directory path to create", + "in": "query", + "name": "path", + "required": true, + "schema": { + "description": "Absolute directory path to create", + "title": "Path", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } + } }, - "type": "array", - "title": "Condensers" + "description": "Successful Response" }, - "kind": { - "type": "string", - "const": "PipelineCondenser", - "title": "Kind" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" } }, - "type": "object", - "required": [ - "condensers", - "kind" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "PipelineCondenser", - "description": "A condenser that applies a sequence of condensers in order.\n\nAll condensers are defined primarily by their `condense` method, which takes a\n`View` and an optional `agent_llm` parameter, returning either a new `View` or a\n`Condensation` event. That means we can chain multiple condensers together by\npassing `View`s along and exiting early if any condenser returns a `Condensation`.\n\nFor example:\n\n # Use the pipeline condenser to chain multiple other condensers together\n condenser = PipelineCondenser(condensers=[\n CondenserA(...),\n CondenserB(...),\n CondenserC(...),\n ])\n\n result = condenser.condense(view, agent_llm=agent_llm)\n\n # Doing the same thing without the pipeline condenser requires more boilerplate\n # for the monadic chaining\n other_result = view\n\n if isinstance(other_result, View):\n other_result = CondenserA(...).condense(other_result, agent_llm=agent_llm)\n\n if isinstance(other_result, View):\n other_result = CondenserB(...).condense(other_result, agent_llm=agent_llm)\n\n if isinstance(other_result, View):\n other_result = CondenserC(...).condense(other_result, agent_llm=agent_llm)\n\n assert result == other_result" - }, - "PlanningFileEditorAction": { - "properties": { - "command": { - "type": "string", - "enum": [ - "view", - "create", - "str_replace", - "insert", - "undo_edit" - ], - "title": "Command", - "description": "The commands to run. Allowed options are: `view`, `create`, `str_replace`, `insert`, `undo_edit`." - }, - "path": { - "type": "string", - "title": "Path", - "description": "Absolute path to file or directory." - }, - "file_text": { - "anyOf": [ - { - "type": "string" + "summary": "Create Directory", + "tags": [ + "Files" + ] + } + }, + "/api/file/download": { + "get": { + "description": "Download a file from the workspace using query parameter (preferred method).", + "operationId": "download_file_query_api_file_download_get", + "parameters": [ + { + "description": "Absolute file path", + "in": "query", + "name": "path", + "required": true, + "schema": { + "description": "Absolute file path", + "title": "Path", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} }, - { - "type": "null" + "application/octet-stream": { + "schema": { + "format": "binary", + "type": "string" + } } - ], - "title": "File Text", - "description": "Required parameter of `create` command, with the content of the file to be created." + }, + "description": "Successful Response" }, - "old_str": { - "anyOf": [ - { - "type": "string" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Download File Query", + "tags": [ + "Files" + ] + } + }, + "/api/file/download-trajectory/{conversation_id}": { + "get": { + "description": "Download a zip archive of a conversation trajectory.", + "operationId": "download_trajectory_api_file_download_trajectory__conversation_id__get", + "parameters": [ + { + "in": "path", + "name": "conversation_id", + "required": true, + "schema": { + "format": "uuid", + "title": "Conversation Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} }, - { - "type": "null" + "application/octet-stream": { + "schema": { + "format": "binary", + "type": "string" + } } - ], - "title": "Old Str", - "description": "Required parameter of `str_replace` command containing the string in `path` to replace." + }, + "description": "Successful Response" }, - "new_str": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "title": "New Str", - "description": "Optional parameter of `str_replace` command containing the new string (if not given, no string will be added). Required parameter of `insert` command containing the string to insert." - }, - "insert_line": { - "anyOf": [ - { - "type": "integer", - "minimum": 0.0 - }, - { - "type": "null" + }, + "description": "Validation Error" + } + }, + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Download Trajectory", + "tags": [ + "Files" + ] + } + }, + "/api/file/home": { + "get": { + "description": "Return the agent-server user's home directory and dynamic sidebar lists.\n\n``favorites`` is the set of top-level directories actually present in the\nuser's home (so it reflects the real environment instead of a hardcoded\nlist of names that may not exist). Hidden directories are included only\nwhen ``include_hidden`` is True. ``locations`` is the set of filesystem\nroots — '/' on POSIX or available drive letters on Windows.", + "operationId": "get_home_directory_api_file_home_get", + "parameters": [ + { + "description": "Include hidden top-level directories in `favorites`", + "in": "query", + "name": "include_hidden", + "required": false, + "schema": { + "default": false, + "description": "Include hidden top-level directories in `favorites`", + "title": "Include Hidden", + "type": "boolean" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HomeResponse" + } } - ], - "title": "Insert Line", - "description": "Required parameter of `insert` command. The `new_str` will be inserted AFTER the line `insert_line` of `path`." + }, + "description": "Successful Response" }, - "view_range": { - "anyOf": [ - { - "items": { - "type": "integer" - }, - "type": "array" - }, - { - "type": "null" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "title": "View Range", - "description": "Optional parameter of `view` command when `path` points to a file. If none is given, the full file is shown. If provided, the file will be shown in the indicated line number range, e.g. [11, 12] will show lines 11 and 12. Indexing at 1 to start. Setting `[start_line, -1]` shows all lines from `start_line` to the end of the file." - }, - "kind": { - "type": "string", - "const": "PlanningFileEditorAction", - "title": "Kind" + }, + "description": "Validation Error" } }, - "additionalProperties": false, - "type": "object", - "required": [ - "command", - "path", - "kind" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "PlanningFileEditorAction", - "description": "Schema for planning file editor operations.\n\nInherits from FileEditorAction but restricts editing to PLAN.md only.\nAllows viewing any file but only editing PLAN.md." - }, - "PlanningFileEditorObservation": { - "properties": { - "content": { - "items": { + "summary": "Get Home Directory", + "tags": [ + "Files" + ] + } + }, + "/api/file/search_subdirs": { + "get": { + "description": "Search / List immediate subdirectories of `path`.\n\nUsed by the GUI's workspace picker. Symlinks and files are skipped. Hidden\nentries (names starting with '.') are skipped unless ``include_hidden`` is\nTrue. Returns absolute paths so the GUI can use a result directly as\n``workspace.working_dir``.\n\nResults are sorted case-insensitively by name and paginated. ``page_id`` is\nthe ``next_page_id`` returned by the previous page (the lowercase name of\nthe first item to include on the next page).", + "operationId": "search_subdirs_api_file_search_subdirs_get", + "parameters": [ + { + "description": "Absolute directory path to list subdirectories of", + "in": "query", + "name": "path", + "required": true, + "schema": { + "description": "Absolute directory path to list subdirectories of", + "title": "Path", + "type": "string" + } + }, + { + "in": "query", + "name": "page_id", + "required": false, + "schema": { "anyOf": [ { - "$ref": "#/components/schemas/TextContent" + "type": "string" }, { - "$ref": "#/components/schemas/ImageContent" + "type": "null" } - ] - }, - "type": "array", - "title": "Content", - "description": "Content returned from the tool as a list of TextContent/ImageContent objects. When there is an error, it should be written in this field." - }, - "is_error": { - "type": "boolean", - "title": "Is Error", - "description": "Whether the observation indicates an error", - "default": false + ], + "title": "Optional next_page_id from the previously returned page" + } }, - "command": { - "type": "string", - "enum": [ - "view", - "create", - "str_replace", - "insert", - "undo_edit" - ], - "title": "Command", - "description": "The command that was run: `view`, `create`, `str_replace`, `insert`, or `undo_edit`." + { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 100, + "exclusiveMinimum": 0, + "maximum": 100, + "title": "The max number of results in the page", + "type": "integer" + } }, - "path": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + { + "in": "query", + "name": "include_hidden", + "required": false, + "schema": { + "default": false, + "title": "Include hidden subdirectories (names starting with '.')", + "type": "boolean" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SubdirectoryPage" + } } - ], - "title": "Path", - "description": "The file path that was edited." - }, - "prev_exist": { - "type": "boolean", - "title": "Prev Exist", - "description": "Indicates if the file previously existed. If not, it was created.", - "default": true + }, + "description": "Successful Response" }, - "old_content": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "title": "Old Content", - "description": "The content of the file before the edit." + }, + "description": "Validation Error" + } + }, + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Search Subdirs", + "tags": [ + "Files" + ] + } + }, + "/api/file/upload": { + "post": { + "description": "Upload a file to the workspace using query parameter (preferred method).", + "operationId": "upload_file_query_api_file_upload_post", + "parameters": [ + { + "description": "Absolute file path", + "in": "query", + "name": "path", + "required": true, + "schema": { + "description": "Absolute file path", + "title": "Path", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "$ref": "#/components/schemas/Body_upload_file_query_api_file_upload_post" + } + } }, - "new_content": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Success" + } } - ], - "title": "New Content", - "description": "The content of the file after the edit." + }, + "description": "Successful Response" }, - "kind": { - "type": "string", - "const": "PlanningFileEditorObservation", - "title": "Kind" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" } }, - "additionalProperties": false, - "type": "object", - "required": [ - "command", - "kind" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "PlanningFileEditorObservation", - "description": "Observation from planning file editor operations.\n\nInherits from FileEditorObservation - same structure, just different type." - }, - "PlanningFileEditorTool": { - "properties": { - "description": { - "type": "string", - "title": "Description" - }, - "action_type": { - "type": "string", - "title": "Action Type" + "summary": "Upload File Query", + "tags": [ + "Files" + ] + } + }, + "/api/git/changes": { + "get": { + "description": "Get git changes using query parameter (preferred method).", + "operationId": "git_changes_query_api_git_changes_get", + "parameters": [ + { + "description": "The git repository path", + "in": "query", + "name": "path", + "required": true, + "schema": { + "description": "The git repository path", + "title": "Path", + "type": "string" + } }, - "observation_type": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + { + "description": "Optional git ref to diff against (e.g. 'HEAD' for git status-style changes, or a commit hash). When omitted, the upstream/default branch is auto-detected.", + "in": "query", + "name": "ref", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Optional git ref to diff against (e.g. 'HEAD' for git status-style changes, or a commit hash). When omitted, the upstream/default branch is auto-detected.", + "title": "Ref" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "items": { + "$ref": "#/components/schemas/GitChange" + }, + "title": "Response Git Changes Query Api Git Changes Get", + "type": "array" + } } - ], - "title": "Observation Type" + }, + "description": "Successful Response" }, - "annotations": { - "anyOf": [ - { - "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" - }, - { - "type": "null" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ] + }, + "description": "Validation Error" + } + }, + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Git Changes Query", + "tags": [ + "Git" + ] + } + }, + "/api/git/commits": { + "get": { + "description": "List the repository's most recent commits, newest first.", + "operationId": "git_commits_query_api_git_commits_get", + "parameters": [ + { + "description": "The git repository path", + "in": "query", + "name": "path", + "required": true, + "schema": { + "description": "The git repository path", + "title": "Path", + "type": "string" + } }, - "meta": { - "anyOf": [ - { - "additionalProperties": true, - "type": "object" - }, - { - "type": "null" + { + "description": "Maximum commits to return", + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 50, + "description": "Maximum commits to return", + "maximum": 200, + "minimum": 1, + "title": "Limit", + "type": "integer" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GitCommitsPage" + } } - ], - "title": "Meta" - }, - "kind": { - "type": "string", - "const": "PlanningFileEditorTool", - "title": "Kind" + }, + "description": "Successful Response" }, - "title": { - "type": "string", - "title": "Title", - "readOnly": true + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" } }, - "type": "object", - "required": [ - "description", - "action_type", - "kind", - "title" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "PlanningFileEditorTool", - "description": "A planning file editor tool with read-all, edit-PLAN.md-only access." - }, - "PluginSource": { - "properties": { - "source": { - "type": "string", - "title": "Source", - "description": "Plugin source: 'github:owner/repo', any git URL, or local path" + "summary": "Git Commits Query", + "tags": [ + "Git" + ] + } + }, + "/api/git/commits/{sha}/changes": { + "get": { + "description": "Get the files changed by a single commit (vs its first parent).", + "operationId": "git_commit_changes_query_api_git_commits__sha__changes_get", + "parameters": [ + { + "description": "Commit SHA", + "in": "path", + "name": "sha", + "required": true, + "schema": { + "description": "Commit SHA", + "pattern": "^[0-9a-fA-F]{4,64}$", + "title": "Sha", + "type": "string" + } }, - "ref": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + { + "description": "The git repository path", + "in": "query", + "name": "path", + "required": true, + "schema": { + "description": "The git repository path", + "title": "Path", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "items": { + "$ref": "#/components/schemas/GitChange" + }, + "title": "Response Git Commit Changes Query Api Git Commits Sha Changes Get", + "type": "array" + } } - ], - "title": "Ref", - "description": "Optional branch, tag, or commit (only for git sources)" + }, + "description": "Successful Response" }, - "repo_path": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "title": "Repo Path", - "description": "Subdirectory path within the git repository (e.g., 'plugins/my-plugin' for monorepos). Only relevant for git sources, not local paths." + }, + "description": "Validation Error" } }, - "type": "object", - "required": [ - "source" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "PluginSource", - "description": "Specification for a plugin to load.\n\nThis model describes where to find a plugin and is used by load_plugins()\nto fetch and load plugins from various sources.\n\nExamples:\n >>> # GitHub repository\n >>> PluginSource(source=\"github:owner/repo\", ref=\"v1.0.0\")\n\n >>> # Plugin from monorepo subdirectory\n >>> PluginSource(\n ... source=\"github:owner/monorepo\",\n ... repo_path=\"plugins/my-plugin\"\n ... )\n\n >>> # Local path\n >>> PluginSource(source=\"/path/to/plugin\")" - }, - "ReadFileAction": { - "properties": { - "file_path": { - "type": "string", - "title": "File Path", - "description": "The path to the file to read." + "summary": "Git Commit Changes Query", + "tags": [ + "Git" + ] + } + }, + "/api/git/diff": { + "get": { + "description": "Get git diff using query parameter (preferred method).", + "operationId": "git_diff_query_api_git_diff_get", + "parameters": [ + { + "description": "The file path to get diff for", + "in": "query", + "name": "path", + "required": true, + "schema": { + "description": "The file path to get diff for", + "title": "Path", + "type": "string" + } }, - "offset": { - "anyOf": [ - { - "type": "integer", - "minimum": 0.0 - }, - { - "type": "null" + { + "description": "Optional git ref to diff against (e.g. 'HEAD' for git status-style changes, or a commit hash). When omitted, the upstream/default branch is auto-detected.", + "in": "query", + "name": "ref", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Optional git ref to diff against (e.g. 'HEAD' for git status-style changes, or a commit hash). When omitted, the upstream/default branch is auto-detected.", + "title": "Ref" + } + }, + { + "description": "Optional commit SHA. When set, the diff is the change that commit introduced (vs its first parent), read entirely from git objects so deleted files still render. Mutually exclusive with 'ref'.", + "in": "query", + "name": "commit", + "required": false, + "schema": { + "anyOf": [ + { + "pattern": "^[0-9a-fA-F]{4,64}$", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Optional commit SHA. When set, the diff is the change that commit introduced (vs its first parent), read entirely from git objects so deleted files still render. Mutually exclusive with 'ref'.", + "title": "Commit" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GitDiff" + } } - ], - "title": "Offset", - "description": "Optional: The 0-based line number to start reading from. Use for paginating through large files." + }, + "description": "Successful Response" }, - "limit": { - "anyOf": [ - { - "type": "integer", - "minimum": 1.0 - }, - { - "type": "null" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "title": "Limit", - "description": "Optional: Maximum number of lines to read. Use with 'offset' to paginate through large files." - }, - "kind": { - "type": "string", - "const": "ReadFileAction", - "title": "Kind" + }, + "description": "Validation Error" } }, - "additionalProperties": false, - "type": "object", - "required": [ - "file_path", - "kind" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "ReadFileAction", - "description": "Schema for read file operation." - }, - "ReadFileObservation": { - "properties": { - "content": { - "items": { + "summary": "Git Diff Query", + "tags": [ + "Git" + ] + } + }, + "/api/git/repositories/search": { + "get": { + "description": "List repositories accessible to a configured git provider token.", + "operationId": "git_repositories_search_api_git_repositories_search_get", + "parameters": [ + { + "description": "Git provider to search", + "in": "query", + "name": "provider", + "required": true, + "schema": { + "$ref": "#/components/schemas/GitProvider", + "description": "Git provider to search" + } + }, + { + "description": "Optional repository name filter", + "in": "query", + "name": "query", + "required": false, + "schema": { "anyOf": [ { - "$ref": "#/components/schemas/TextContent" + "type": "string" }, { - "$ref": "#/components/schemas/ImageContent" + "type": "null" } - ] - }, - "type": "array", - "title": "Content", - "description": "Content returned from the tool as a list of TextContent/ImageContent objects. When there is an error, it should be written in this field." - }, - "is_error": { - "type": "boolean", - "title": "Is Error", - "description": "Whether the observation indicates an error", - "default": false - }, - "file_path": { - "type": "string", - "title": "File Path", - "description": "The file path that was read." - }, - "file_content": { - "type": "string", - "title": "File Content", - "description": "The content read from the file.", - "default": "" + ], + "description": "Optional repository name filter", + "title": "Query" + } }, - "is_truncated": { - "type": "boolean", - "title": "Is Truncated", - "description": "Whether the content was truncated due to size limits.", - "default": false + { + "description": "Maximum repositories to return", + "in": "query", + "name": "limit", + "required": false, + "schema": { + "default": 100, + "description": "Maximum repositories to return", + "maximum": 100, + "minimum": 1, + "title": "Limit", + "type": "integer" + } }, - "lines_shown": { - "anyOf": [ - { - "prefixItems": [ - { - "type": "integer" - }, - { - "type": "integer" - } - ], - "type": "array", - "maxItems": 2, - "minItems": 2 - }, - { - "type": "null" + { + "description": "Provider-specific page cursor", + "in": "query", + "name": "page_id", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Provider-specific page cursor", + "title": "Page Id" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GitProviderRepositoryPage" + } } - ], - "title": "Lines Shown", - "description": "If truncated, the range of lines shown (start, end) - 1-indexed." + }, + "description": "Successful Response" }, - "total_lines": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "title": "Total Lines", - "description": "Total number of lines in the file." - }, - "kind": { - "type": "string", - "const": "ReadFileObservation", - "title": "Kind" + }, + "description": "Validation Error" } }, - "additionalProperties": false, - "type": "object", - "required": [ - "file_path", - "kind" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "ReadFileObservation", - "description": "Observation from reading a file." - }, - "ReadFileTool": { - "properties": { - "description": { - "type": "string", - "title": "Description" - }, - "action_type": { - "type": "string", - "title": "Action Type" - }, - "observation_type": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "summary": "Git Repositories Search", + "tags": [ + "Git" + ] + } + }, + "/api/hooks": { + "post": { + "description": "Load hooks from the workspace .openhands/hooks.json file.\n\nThis endpoint reads the hooks configuration from the project's\n.openhands/hooks.json file if it exists.\n\nArgs:\n request: HooksRequest containing the project directory path.\n\nReturns:\n HooksResponse containing the hook configuration or None.", + "operationId": "get_hooks_api_hooks_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HooksRequest" } - ], - "title": "Observation Type" + } }, - "annotations": { - "anyOf": [ - { - "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" - }, - { - "type": "null" + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HooksResponse" + } } - ] + }, + "description": "Successful Response" }, - "meta": { - "anyOf": [ - { - "additionalProperties": true, - "type": "object" - }, - { - "type": "null" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "title": "Meta" - }, - "kind": { - "type": "string", - "const": "ReadFileTool", - "title": "Kind" - }, - "title": { - "type": "string", - "title": "Title", - "readOnly": true + }, + "description": "Validation Error" + } + }, + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Get Hooks", + "tags": [ + "Hooks" + ] + } + }, + "/api/init": { + "get": { + "description": "Report the current init state.\n\nAuthentication is intentionally not required on this endpoint so a warm\npool controller can poll it without holding the init key. The payload\ncontains no sensitive data.", + "operationId": "get_init_status_api_init_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InitStatus" + } + } + }, + "description": "Successful Response" } }, - "type": "object", - "required": [ - "description", - "action_type", - "kind", - "title" - ], - "title": "ReadFileTool", - "description": "Tool for reading file contents with pagination support." + "summary": "Get Init Status", + "tags": [ + "Init" + ] }, - "ReasoningItemModel": { - "properties": { - "id": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "post": { + "description": "Initialize a dormant server with runtime configuration.\n\nReturns 400 if the server has already been initialized (state != dormant).\nReturns 500 if initialization fails; in that case the state rolls back to\n``dormant`` so the orchestrator can retry.", + "operationId": "initialize_server_api_init_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InitRequest" } - ], - "title": "Id" + } }, - "summary": { - "items": { - "type": "string" + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InitStatus" + } + } }, - "type": "array", - "title": "Summary" + "description": "Successful Response" }, - "content": { - "anyOf": [ - { - "items": { + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Initialize Server", + "tags": [ + "Init" + ] + } + }, + "/api/llm/models": { + "get": { + "description": "List all available LLM models supported by LiteLLM.\n\nArgs:\n provider: Optional provider name to filter models by.\n\nNote: Bedrock models are excluded unless AWS credentials are configured.", + "operationId": "list_models_api_llm_models_get", + "parameters": [ + { + "description": "Filter models by provider (e.g., 'openai', 'anthropic')", + "in": "query", + "name": "provider", + "required": false, + "schema": { + "anyOf": [ + { "type": "string" }, - "type": "array" - }, - { - "type": "null" - } - ], - "title": "Content" - }, - "encrypted_content": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + { + "type": "null" + } + ], + "description": "Filter models by provider (e.g., 'openai', 'anthropic')", + "title": "Provider" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ModelsResponse" + } } - ], - "title": "Encrypted Content" + }, + "description": "Successful Response" }, - "status": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "title": "Status" + }, + "description": "Validation Error" } }, - "type": "object", - "title": "ReasoningItemModel", - "description": "OpenAI Responses reasoning item (non-stream, subset we consume).\n\nDo not log or render encrypted_content." - }, - "RedactedThinkingBlock": { - "properties": { - "type": { - "type": "string", - "const": "redacted_thinking", - "title": "Type", - "default": "redacted_thinking" - }, - "data": { - "type": "string", - "title": "Data", - "description": "The redacted thinking content" + "security": [ + { + "APIKeyHeader": [] } - }, - "type": "object", - "required": [ - "data" ], - "title": "RedactedThinkingBlock", - "description": "Redacted thinking block for previous responses without extended thinking.\n\nThis is used as a placeholder for assistant messages that were generated\nbefore extended thinking was enabled." - }, - "RemoteWorkspace-Input": { - "properties": { - "working_dir": { - "type": "string", - "title": "Working Dir", - "description": "The working directory for agent operations and tool execution." - }, - "host": { - "type": "string", - "title": "Host", - "description": "The remote host URL for the workspace." - }, - "api_key": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "summary": "List Models", + "tags": [ + "LLM" + ] + } + }, + "/api/llm/models/verified": { + "get": { + "description": "List all verified LLM models organized by provider.\n\nVerified models are those that have been tested and confirmed to work well\nwith OpenHands.", + "operationId": "list_verified_models_api_llm_models_verified_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VerifiedModelsResponse" + } } - ], - "title": "Api Key", - "description": "API key for authenticating with the remote host." - }, - "read_timeout": { - "type": "number", - "title": "Read Timeout", - "description": "Timeout in seconds for reading operations of httpx.Client.", - "default": 600.0 - }, - "max_connections": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" + }, + "description": "Successful Response" + } + }, + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "List Verified Models", + "tags": [ + "LLM" + ] + } + }, + "/api/llm/provider-connections": { + "get": { + "operationId": "list_provider_connections_api_llm_provider_connections_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "items": { + "$ref": "#/components/schemas/ProviderConnectionResponse" + }, + "title": "Response List Provider Connections Api Llm Provider Connections Get", + "type": "array" + } } - ], - "title": "Max Connections", - "description": "Maximum number of connections for httpx.Client. None means no limit, useful for running many conversations in parallel." - }, - "kind": { - "type": "string", - "const": "RemoteWorkspace", - "title": "Kind" + }, + "description": "Successful Response" } }, - "type": "object", - "required": [ - "working_dir", - "host" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "RemoteWorkspace", - "description": "Remote workspace implementation that connects to an OpenHands agent server.\n\nRemoteWorkspace provides access to a sandboxed environment running on a remote\nOpenHands agent server. This is the recommended approach for production deployments\nas it provides better isolation and security.\n\nExample:\n >>> workspace = RemoteWorkspace(\n ... host=\"https://agent-server.example.com\",\n ... working_dir=\"/workspace\"\n ... )\n >>> with workspace:\n ... result = workspace.execute_command(\"ls -la\")\n ... content = workspace.read_file(\"README.md\")" + "summary": "List Provider Connections", + "tags": [ + "LLM Provider Connections" + ] }, - "RemoteWorkspace-Output": { - "properties": { - "working_dir": { - "type": "string", - "title": "Working Dir", - "description": "The working directory for agent operations and tool execution." - }, - "host": { - "type": "string", - "title": "Host", - "description": "The remote host URL for the workspace." - }, - "api_key": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "post": { + "operationId": "create_provider_connection_api_llm_provider_connections_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProviderConnectionCreateRequest" } - ], - "title": "Api Key", - "description": "API key for authenticating with the remote host." - }, - "read_timeout": { - "type": "number", - "title": "Read Timeout", - "description": "Timeout in seconds for reading operations of httpx.Client.", - "default": 600.0 + } }, - "max_connections": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" + "required": true + }, + "responses": { + "201": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProviderConnectionResponse" + } } - ], - "title": "Max Connections", - "description": "Maximum number of connections for httpx.Client. None means no limit, useful for running many conversations in parallel." + }, + "description": "Successful Response" }, - "kind": { - "type": "string", - "const": "RemoteWorkspace", - "title": "Kind" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" } }, - "type": "object", - "required": [ - "working_dir", - "host", - "kind" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "RemoteWorkspace", - "description": "Remote workspace implementation that connects to an OpenHands agent server.\n\nRemoteWorkspace provides access to a sandboxed environment running on a remote\nOpenHands agent server. This is the recommended approach for production deployments\nas it provides better isolation and security.\n\nExample:\n >>> workspace = RemoteWorkspace(\n ... host=\"https://agent-server.example.com\",\n ... working_dir=\"/workspace\"\n ... )\n >>> with workspace:\n ... result = workspace.execute_command(\"ls -la\")\n ... content = workspace.read_file(\"README.md\")" - }, - "ResponseLatency": { - "properties": { - "model": { - "type": "string", - "title": "Model" - }, - "latency": { - "type": "number", - "minimum": 0.0, - "title": "Latency", - "description": "Latency must be non-negative" - }, - "response_id": { - "type": "string", - "title": "Response Id" + "summary": "Create Provider Connection", + "tags": [ + "LLM Provider Connections" + ] + } + }, + "/api/llm/provider-connections/{connection_id}": { + "delete": { + "operationId": "delete_provider_connection_api_llm_provider_connections__connection_id__delete", + "parameters": [ + { + "in": "path", + "name": "connection_id", + "required": true, + "schema": { + "title": "Connection Id", + "type": "string" + } } - }, - "type": "object", - "required": [ - "model", - "latency", - "response_id" ], - "title": "ResponseLatency", - "description": "Metric tracking the round-trip time per completion call." - }, - "SandboxConfig": { - "properties": { - "exposed_urls": { - "items": { - "$ref": "#/components/schemas/ExposedUrl" + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProviderConnectionResponse" + } + } }, - "type": "array", - "title": "Exposed Urls", - "description": "List of exposed URLs from the sandbox" + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" } }, - "type": "object", - "title": "SandboxConfig", - "description": "Configuration for loading sandbox-specific skills." + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Delete Provider Connection", + "tags": [ + "LLM Provider Connections" + ] }, - "SecretRegistry-Input": { - "properties": { - "secret_sources": { - "additionalProperties": { - "$ref": "#/components/schemas/SecretSource-Input" - }, - "type": "object", - "title": "Secret Sources" + "patch": { + "operationId": "update_provider_connection_api_llm_provider_connections__connection_id__patch", + "parameters": [ + { + "in": "path", + "name": "connection_id", + "required": true, + "schema": { + "title": "Connection Id", + "type": "string" + } } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProviderConnectionUpdateRequest" + } + } + }, + "required": true }, - "type": "object", - "title": "SecretRegistry", - "description": "Manages secrets and injects them into bash commands when needed.\n\nThe secret registry stores a mapping of secret keys to SecretSources\nthat retrieve the actual secret values. When a bash command is about to be\nexecuted, it scans the command for any secret keys and injects the corresponding\nenvironment variables.\n\nSecret sources will redact / encrypt their sensitive values as appropriate when\nserializing, depending on the content of the context. If a context is present\nand contains a 'cipher' object, this is used for encryption. If it contains a\nboolean 'expose_secrets' flag set to True, secrets are dunped in plain text.\nOtherwise secrets are redacted.\n\nAdditionally, it tracks the latest exported values to enable consistent masking\neven when callable secrets fail on subsequent calls." - }, - "SecretRegistry-Output": { - "properties": { - "secret_sources": { - "additionalProperties": { - "$ref": "#/components/schemas/SecretSource-Output" + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProviderConnectionResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } }, - "type": "object", - "title": "Secret Sources" + "description": "Validation Error" } }, - "type": "object", - "title": "SecretRegistry", - "description": "Manages secrets and injects them into bash commands when needed.\n\nThe secret registry stores a mapping of secret keys to SecretSources\nthat retrieve the actual secret values. When a bash command is about to be\nexecuted, it scans the command for any secret keys and injects the corresponding\nenvironment variables.\n\nSecret sources will redact / encrypt their sensitive values as appropriate when\nserializing, depending on the content of the context. If a context is present\nand contains a 'cipher' object, this is used for encryption. If it contains a\nboolean 'expose_secrets' flag set to True, secrets are dunped in plain text.\nOtherwise secrets are redacted.\n\nAdditionally, it tracks the latest exported values to enable consistent masking\neven when callable secrets fail on subsequent calls." - }, - "SecretSource-Input": { - "oneOf": [ + "security": [ { - "$ref": "#/components/schemas/LookupSecret-Input" - }, - { - "$ref": "#/components/schemas/StaticSecret-Input" + "APIKeyHeader": [] } ], - "discriminator": { - "propertyName": "kind", - "mapping": { - "openhands__sdk__secret__secrets__LookupSecret-Input__1": "#/components/schemas/LookupSecret-Input", - "openhands__sdk__secret__secrets__StaticSecret-Input__1": "#/components/schemas/StaticSecret-Input" + "summary": "Update Provider Connection", + "tags": [ + "LLM Provider Connections" + ] + } + }, + "/api/llm/providers": { + "get": { + "description": "List all available LLM providers supported by LiteLLM.", + "operationId": "list_providers_api_llm_providers_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProvidersResponse" + } + } + }, + "description": "Successful Response" } - } - }, - "SecretSource-Output": { - "oneOf": [ - { - "$ref": "#/components/schemas/LookupSecret-Output" - }, + }, + "security": [ { - "$ref": "#/components/schemas/StaticSecret-Output" + "APIKeyHeader": [] } ], - "discriminator": { - "propertyName": "kind", - "mapping": { - "openhands__sdk__secret__secrets__LookupSecret-Output__1": "#/components/schemas/LookupSecret-Output", - "openhands__sdk__secret__secrets__StaticSecret-Output__1": "#/components/schemas/StaticSecret-Output" - } - } - }, - "SecurityAnalyzerBase-Input": { - "oneOf": [ - { - "$ref": "#/components/schemas/GraySwanAnalyzer-Input" + "summary": "List Providers", + "tags": [ + "LLM" + ] + } + }, + "/api/llm/subscription/openai/device/poll": { + "post": { + "description": "Poll a ChatGPT device-code sign-in without returning tokens.", + "operationId": "poll_openai_subscription_device_login_api_llm_subscription_openai_device_poll_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SubscriptionDevicePollRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SubscriptionStatusResponse" + } + } + }, + "description": "Successful Response" }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "security": [ { - "$ref": "#/components/schemas/LLMSecurityAnalyzer-Input" + "APIKeyHeader": [] } ], - "discriminator": { - "propertyName": "kind", - "mapping": { - "openhands__sdk__security__grayswan__analyzer__GraySwanAnalyzer-Input__1": "#/components/schemas/GraySwanAnalyzer-Input", - "openhands__sdk__security__llm_analyzer__LLMSecurityAnalyzer-Input__1": "#/components/schemas/LLMSecurityAnalyzer-Input" + "summary": "Poll Openai Subscription Device Login", + "tags": [ + "LLM" + ] + } + }, + "/api/llm/subscription/openai/device/start": { + "post": { + "description": "Start ChatGPT device-code sign-in without returning tokens.", + "operationId": "start_openai_subscription_device_login_api_llm_subscription_openai_device_start_post", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SubscriptionDeviceStartResponse" + } + } + }, + "description": "Successful Response" } - } - }, - "SecurityAnalyzerBase-Output": { - "oneOf": [ - { - "$ref": "#/components/schemas/GraySwanAnalyzer-Output" - }, + }, + "security": [ { - "$ref": "#/components/schemas/LLMSecurityAnalyzer-Output" + "APIKeyHeader": [] } ], - "discriminator": { - "propertyName": "kind", - "mapping": { - "openhands__sdk__security__grayswan__analyzer__GraySwanAnalyzer-Output__1": "#/components/schemas/GraySwanAnalyzer-Output", - "openhands__sdk__security__llm_analyzer__LLMSecurityAnalyzer-Output__1": "#/components/schemas/LLMSecurityAnalyzer-Output" + "summary": "Start Openai Subscription Device Login", + "tags": [ + "LLM" + ] + } + }, + "/api/llm/subscription/openai/logout": { + "post": { + "description": "Remove stored ChatGPT subscription credentials.", + "operationId": "logout_openai_subscription_api_llm_subscription_openai_logout_post", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SubscriptionStatusResponse" + } + } + }, + "description": "Successful Response" + } + }, + "security": [ + { + "APIKeyHeader": [] } - } - }, - "SecurityRisk": { - "type": "string", - "enum": [ - "UNKNOWN", - "LOW", - "MEDIUM", - "HIGH" ], - "title": "SecurityRisk", - "description": "Security risk levels for actions.\n\nBased on OpenHands security risk levels but adapted for agent-sdk.\nInteger values allow for easy comparison and ordering." - }, - "SendMessageRequest": { - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "system", - "assistant", - "tool" - ], - "title": "Role", - "default": "user" - }, - "content": { - "items": { - "anyOf": [ - { - "$ref": "#/components/schemas/TextContent" - }, - { - "$ref": "#/components/schemas/ImageContent" + "summary": "Logout Openai Subscription", + "tags": [ + "LLM" + ] + } + }, + "/api/llm/subscription/openai/models": { + "get": { + "description": "List models available through ChatGPT subscription authentication.", + "operationId": "list_openai_subscription_models_api_llm_subscription_openai_models_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SubscriptionModelsResponse" } - ] + } }, - "type": "array", - "title": "Content" - }, - "run": { - "type": "boolean", - "title": "Run", - "description": "Whether the agent loop should automatically run if not running", - "default": false + "description": "Successful Response" } }, - "type": "object", - "title": "SendMessageRequest", - "description": "Payload to send a message to the agent.\n\nThis is a simplified version of openhands.sdk.Message." - }, - "ServerInfo": { - "properties": { - "uptime": { - "type": "number", - "title": "Uptime" - }, - "idle_time": { - "type": "number", - "title": "Idle Time" - }, - "title": { - "type": "string", - "title": "Title", - "default": "OpenHands Agent Server" - }, - "version": { - "type": "string", - "title": "Version", - "default": "1.11.4" - }, - "docs": { - "type": "string", - "title": "Docs", - "default": "/docs" - }, - "redoc": { - "type": "string", - "title": "Redoc", - "default": "/redoc" + "security": [ + { + "APIKeyHeader": [] } - }, - "type": "object", - "required": [ - "uptime", - "idle_time" ], - "title": "ServerInfo" - }, - "SetConfirmationPolicyRequest": { - "properties": { - "policy": { - "$ref": "#/components/schemas/ConfirmationPolicyBase-Input", - "description": "The confirmation policy to set" + "summary": "List Openai Subscription Models", + "tags": [ + "LLM" + ] + } + }, + "/api/llm/subscription/openai/status": { + "get": { + "description": "Return safe ChatGPT subscription connection state without tokens.", + "operationId": "get_openai_subscription_status_api_llm_subscription_openai_status_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SubscriptionStatusResponse" + } + } + }, + "description": "Successful Response" } }, - "type": "object", - "required": [ - "policy" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "SetConfirmationPolicyRequest", - "description": "Payload to set confirmation policy for a conversation." - }, - "SetSecurityAnalyzerRequest": { - "properties": { - "security_analyzer": { - "anyOf": [ - { - "$ref": "#/components/schemas/SecurityAnalyzerBase-Input" - }, - { - "type": "null" - } - ], - "description": "The security analyzer to set" + "summary": "Get Openai Subscription Status", + "tags": [ + "LLM" + ] + } + }, + "/api/mcp/oauth/callback/{job_id}": { + "post": { + "operationId": "submit_mcp_oauth_callback_api_mcp_oauth_callback__job_id__post", + "parameters": [ + { + "in": "path", + "name": "job_id", + "required": true, + "schema": { + "title": "Job Id", + "type": "string" + } } - }, - "type": "object", - "required": [ - "security_analyzer" ], - "title": "SetSecurityAnalyzerRequest", - "description": "Payload to set security analyzer for a conversation" - }, - "Skill": { - "properties": { - "name": { - "type": "string", - "title": "Name" - }, + "requestBody": { "content": { - "type": "string", - "title": "Content" - }, - "trigger": { - "anyOf": [ - { - "oneOf": [ - { - "$ref": "#/components/schemas/KeywordTrigger" - }, - { - "$ref": "#/components/schemas/TaskTrigger" - } - ], - "discriminator": { - "propertyName": "type", - "mapping": { - "keyword": "#/components/schemas/KeywordTrigger", - "task": "#/components/schemas/TaskTrigger" - } - } - }, - { - "type": "null" - } - ], - "title": "Trigger", - "description": "Trigger determines when skill content is auto-injected. None = no auto-injection (for AgentSkills: agent reads on demand; for legacy: full content always in system prompt). KeywordTrigger = auto-inject when keywords appear in user messages. TaskTrigger = auto-inject for specific tasks, may require user input." - }, - "source": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "application/json": { + "schema": { + "$ref": "#/components/schemas/MCPOAuthCallbackRequest" } - ], - "title": "Source", - "description": "The source path or identifier of the skill. When it is None, it is treated as a programmatically defined skill." + } }, - "mcp_tools": { - "anyOf": [ - { - "additionalProperties": true, - "type": "object" - }, - { - "type": "null" + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MCPOAuthStatusResponse" + } } - ], - "title": "Mcp Tools", - "description": "MCP tools configuration for the skill (repo skills only). It should conform to the MCPConfig schema: https://gofastmcp.com/clients/client#configuration-format" - }, - "inputs": { - "items": { - "$ref": "#/components/schemas/InputMetadata" }, - "type": "array", - "title": "Inputs", - "description": "Input metadata for the skill (task skills only)" - }, - "is_agentskills_format": { - "type": "boolean", - "title": "Is Agentskills Format", - "description": "Whether this skill was loaded from a SKILL.md file following the AgentSkills standard. AgentSkills-format skills use progressive disclosure: always listed in with name, description, and location. If the skill also has triggers, content is auto-injected when triggered AND agent can read file anytime.", - "default": false + "description": "Successful Response" }, - "description": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "title": "Description", - "description": "A brief description of what the skill does and when to use it. AgentSkills standard field (max 1024 characters)." - }, - "license": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + }, + "description": "Validation Error" + } + }, + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Submit an MCP OAuth callback URL", + "tags": [ + "MCP" + ] + } + }, + "/api/mcp/oauth/start": { + "post": { + "description": "Start OAuth for a candidate MCP server and return the authorization URL.", + "operationId": "start_mcp_oauth_api_mcp_oauth_start_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MCPTestRequest" } - ], - "title": "License", - "description": "The license under which the skill is distributed. AgentSkills standard field (e.g., 'Apache-2.0', 'MIT')." + } }, - "compatibility": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MCPOAuthStartResponse" + } } - ], - "title": "Compatibility", - "description": "Environment requirements or compatibility notes for the skill. AgentSkills standard field (e.g., 'Requires git and docker')." + }, + "description": "Successful Response" }, - "metadata": { - "anyOf": [ - { - "additionalProperties": { - "type": "string" - }, - "type": "object" - }, - { - "type": "null" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "title": "Metadata", - "description": "Arbitrary key-value metadata for the skill. AgentSkills standard field for extensibility." - }, - "allowed_tools": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" + }, + "description": "Validation Error" + } + }, + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Start an MCP OAuth install probe", + "tags": [ + "MCP" + ] + } + }, + "/api/mcp/oauth/status/{job_id}": { + "get": { + "operationId": "get_mcp_oauth_status_api_mcp_oauth_status__job_id__get", + "parameters": [ + { + "in": "path", + "name": "job_id", + "required": true, + "schema": { + "title": "Job Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MCPOAuthStatusResponse" + } } - ], - "title": "Allowed Tools", - "description": "List of pre-approved tools for this skill. AgentSkills standard field (parsed from space-delimited string)." + }, + "description": "Successful Response" }, - "resources": { - "anyOf": [ - { - "$ref": "#/components/schemas/SkillResources" - }, - { - "type": "null" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "description": "Resource directories for the skill (scripts/, references/, assets/). AgentSkills standard field. Only populated for SKILL.md directory format." + }, + "description": "Validation Error" } }, - "type": "object", - "required": [ - "name", - "content" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "Skill", - "description": "A skill provides specialized knowledge or functionality.\n\nSkill behavior depends on format (is_agentskills_format) and trigger:\n\nAgentSkills format (SKILL.md files):\n- Always listed in with name, description, location\n- Agent reads full content on demand (progressive disclosure)\n- If has triggers: content is ALSO auto-injected when triggered\n\nLegacy OpenHands format:\n- With triggers: Listed in , content injected on trigger\n- Without triggers (None): Full content in , always active\n\nThis model supports both OpenHands-specific fields and AgentSkills standard\nfields (https://agentskills.io/specification) for cross-platform compatibility." - }, - "SkillInfo": { - "properties": { - "name": { - "type": "string", - "title": "Name" - }, - "type": { - "type": "string", - "enum": [ - "repo", - "knowledge", - "agentskills" - ], - "title": "Type" - }, + "summary": "Get an MCP OAuth install probe status", + "tags": [ + "MCP" + ] + } + }, + "/api/mcp/test": { + "post": { + "description": "Attempt to connect to a candidate MCP server and list its tools, without persisting any settings. Useful for validating user input in 'add MCP server' flows before storing the config. For OAuth servers, any acquired state is returned as `oauth_state` so clients can persist it under the MCP server object's `auth.state`. Optionally invokes one caller-chosen (read-only) tool via `tool_call` and reports its outcome in `tool_result`, so callers can verify credentials that are only exercised on tool invocation. Encrypted `env`/`headers` values round-tripped from settings are decrypted before the connection is attempted. Returns 200 with `ok=false` for connection / timeout failures (those are expected during validation, not server errors).", + "operationId": "test_mcp_server_api_mcp_test_post", + "requestBody": { "content": { - "type": "string", - "title": "Content" + "application/json": { + "schema": { + "$ref": "#/components/schemas/MCPTestRequest" + } + } }, - "triggers": { - "items": { - "type": "string" + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "discriminator": { + "mapping": { + "False": "#/components/schemas/MCPTestFailure", + "True": "#/components/schemas/MCPTestSuccess" + }, + "propertyName": "ok" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/MCPTestSuccess" + }, + { + "$ref": "#/components/schemas/MCPTestFailure" + } + ], + "title": "Response Test Mcp Server Api Mcp Test Post" + } + } }, - "type": "array", - "title": "Triggers" + "description": "Successful Response" }, - "source": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "title": "Source" - }, - "description": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + }, + "description": "Validation Error" + } + }, + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Test an MCP server configuration", + "tags": [ + "MCP" + ] + } + }, + "/api/meta-profiles": { + "get": { + "description": "List all saved meta-profiles and the currently active one.", + "operationId": "list_meta_profiles_api_meta_profiles_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MetaProfileListResponse" + } } - ], - "title": "Description" - }, - "is_agentskills_format": { - "type": "boolean", - "title": "Is Agentskills Format", - "default": false + }, + "description": "Successful Response" } }, - "type": "object", - "required": [ - "name", - "type", - "content" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "SkillInfo", - "description": "Skill information returned by the API." - }, - "SkillResources": { - "properties": { - "skill_root": { - "type": "string", - "title": "Skill Root", - "description": "Root directory of the skill (absolute path)" - }, - "scripts": { - "items": { + "summary": "List Meta Profiles", + "tags": [ + "Meta-profiles" + ] + } + }, + "/api/meta-profiles/{name}": { + "delete": { + "description": "Delete a meta-profile (idempotent).\n\nIf the deleted meta-profile is the active one, ``active_meta_profile`` is\ncleared.", + "operationId": "delete_meta_profile_api_meta_profiles__name__delete", + "parameters": [ + { + "in": "path", + "name": "name", + "required": true, + "schema": { + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$", + "title": "Name", "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MetaProfileMutationResponse" + } + } }, - "type": "array", - "title": "Scripts", - "description": "List of script files in scripts/ directory (relative paths)" + "description": "Successful Response" }, - "references": { - "items": { + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Delete Meta Profile", + "tags": [ + "Meta-profiles" + ] + }, + "get": { + "description": "Get a meta-profile's full configuration.", + "operationId": "get_meta_profile_api_meta_profiles__name__get", + "parameters": [ + { + "in": "path", + "name": "name", + "required": true, + "schema": { + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$", + "title": "Name", "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MetaProfileDetailResponse" + } + } }, - "type": "array", - "title": "References", - "description": "List of reference files in references/ directory (relative paths)" + "description": "Successful Response" }, - "assets": { - "items": { - "type": "string" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } }, - "type": "array", - "title": "Assets", - "description": "List of asset files in assets/ directory (relative paths)" + "description": "Validation Error" } }, - "type": "object", - "required": [ - "skill_root" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "SkillResources", - "description": "Resource directories for a skill (AgentSkills standard).\n\nPer the AgentSkills specification, skills can include:\n- scripts/: Executable scripts the agent can run\n- references/: Reference documentation and examples\n- assets/: Static assets (images, data files, etc.)" + "summary": "Get Meta Profile", + "tags": [ + "Meta-profiles" + ] }, - "SkillsRequest": { - "properties": { - "load_public": { - "type": "boolean", - "title": "Load Public", - "description": "Load public skills from OpenHands/skills repo", - "default": true - }, - "load_user": { - "type": "boolean", - "title": "Load User", - "description": "Load user skills from ~/.openhands/skills/", - "default": true - }, - "load_project": { - "type": "boolean", - "title": "Load Project", - "description": "Load project skills from workspace", - "default": true - }, - "load_org": { - "type": "boolean", - "title": "Load Org", - "description": "Load organization-level skills", - "default": true - }, - "project_dir": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "post": { + "description": "Save (create or overwrite) a meta-profile.\n\nReturns 409 if creating a new meta-profile would exceed\n``MAX_META_PROFILES``.", + "operationId": "save_meta_profile_api_meta_profiles__name__post", + "parameters": [ + { + "in": "path", + "name": "name", + "required": true, + "schema": { + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$", + "title": "Name", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MetaProfile" } - ], - "title": "Project Dir", - "description": "Workspace directory path for project skills" + } }, - "org_config": { - "anyOf": [ - { - "$ref": "#/components/schemas/OrgConfig" - }, - { - "type": "null" + "required": true + }, + "responses": { + "201": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MetaProfileMutationResponse" + } } - ], - "description": "Organization skills configuration" + }, + "description": "Successful Response" }, - "sandbox_config": { - "anyOf": [ - { - "$ref": "#/components/schemas/SandboxConfig" - }, - { - "type": "null" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "description": "Sandbox skills configuration" + }, + "description": "Validation Error" } }, - "type": "object", - "title": "SkillsRequest", - "description": "Request body for loading skills." - }, - "SkillsResponse": { - "properties": { - "skills": { - "items": { - "$ref": "#/components/schemas/SkillInfo" + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Save Meta Profile", + "tags": [ + "Meta-profiles" + ] + } + }, + "/api/meta-profiles/{name}/activate": { + "post": { + "description": "Activate a meta-profile by recording it as ``active_meta_profile``.\n\nUnlike LLM profiles, activating a meta-profile does not mutate the agent's\nLLM config — it only records which meta-profile the\n``route_task_to_model`` tool should route with. Returns 404 if the\nmeta-profile does not exist.", + "operationId": "activate_meta_profile_api_meta_profiles__name__activate_post", + "parameters": [ + { + "in": "path", + "name": "name", + "required": true, + "schema": { + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$", + "title": "Name", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ActivateMetaProfileResponse" + } + } }, - "type": "array", - "title": "Skills" + "description": "Successful Response" }, - "sources": { - "additionalProperties": { - "type": "integer" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } }, - "type": "object", - "title": "Sources", - "description": "Count of skills loaded from each source" + "description": "Validation Error" } }, - "type": "object", - "required": [ - "skills" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "SkillsResponse", - "description": "Response containing all available skills." - }, - "StartConversationRequest": { - "properties": { - "agent": { - "$ref": "#/components/schemas/AgentBase-Input" - }, - "workspace": { - "$ref": "#/components/schemas/LocalWorkspace-Input", - "description": "Working directory for agent operations and tool execution" + "summary": "Activate Meta Profile", + "tags": [ + "Meta-profiles" + ] + } + }, + "/api/plugins": { + "post": { + "description": "List locally-available plugins (enabled installed + user/project dirs).\n\nArgs:\n request: Which local sources to load.\n\nReturns:\n PluginsResponse with available plugin summaries.", + "operationId": "get_plugins_api_plugins_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PluginsRequest" + } + } }, - "conversation_id": { - "anyOf": [ - { - "type": "string", - "format": "uuid" - }, - { - "type": "null" + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PluginsResponse" + } } - ], - "title": "Conversation Id", - "description": "Optional conversation ID. If not provided, a random UUID will be generated." + }, + "description": "Successful Response" }, - "confirmation_policy": { - "$ref": "#/components/schemas/ConfirmationPolicyBase-Input", - "description": "Controls when the conversation will prompt the user before continuing. Defaults to never.", - "default": { - "kind": "NeverConfirm" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Get Plugins", + "tags": [ + "Plugins" + ] + } + }, + "/api/plugins/install": { + "post": { + "description": "Install a plugin from a git URL, GitHub shorthand, or local path.", + "operationId": "install_plugin_endpoint_api_plugins_install_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InstallPluginRequest" + } } }, - "initial_message": { - "anyOf": [ - { - "$ref": "#/components/schemas/SendMessageRequest" - }, - { - "type": "null" + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InstalledPluginResponse" + } } - ], - "description": "Initial message to pass to the LLM" + }, + "description": "Successful Response" }, - "max_iterations": { - "type": "integer", - "minimum": 1.0, - "title": "Max Iterations", - "description": "If set, the max number of iterations the agent will run before stopping. This is useful to prevent infinite loops.", - "default": 500 + "400": { + "description": "Failed to fetch plugin source" }, - "stuck_detection": { - "type": "boolean", - "title": "Stuck Detection", - "description": "If true, the conversation will use stuck detection to prevent infinite loops.", - "default": true + "409": { + "description": "Plugin already installed (use force=true)" }, - "secrets": { - "additionalProperties": { - "$ref": "#/components/schemas/SecretSource-Input" + "422": { + "description": "Invalid plugin (bad name, etc.)" + } + }, + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Install Plugin Endpoint", + "tags": [ + "Plugins" + ] + } + }, + "/api/plugins/installed": { + "get": { + "description": "List all installed plugins (enabled and disabled).", + "operationId": "list_installed_plugins_endpoint_api_plugins_installed_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InstalledPluginsListResponse" + } + } }, - "type": "object", - "title": "Secrets", - "description": "Secrets available in the conversation" - }, - "tool_module_qualnames": { - "additionalProperties": { + "description": "Successful Response" + } + }, + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "List Installed Plugins Endpoint", + "tags": [ + "Plugins" + ] + } + }, + "/api/plugins/installed/{plugin_name}": { + "delete": { + "description": "Uninstall a plugin by name.", + "operationId": "uninstall_plugin_endpoint_api_plugins_installed__plugin_name__delete", + "parameters": [ + { + "description": "Plugin name (lowercase alphanumeric, hyphens)", + "in": "path", + "name": "plugin_name", + "required": true, + "schema": { + "description": "Plugin name (lowercase alphanumeric, hyphens)", + "maxLength": 255, + "minLength": 1, + "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$", + "title": "Plugin Name", "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UninstallPluginResponse" + } + } }, - "type": "object", - "title": "Tool Module Qualnames", - "description": "Mapping of tool names to their module qualnames from the client's registry. These modules will be dynamically imported on the server to register the tools for this conversation." + "description": "Successful Response" }, - "plugins": { - "anyOf": [ - { - "items": { - "$ref": "#/components/schemas/PluginSource" - }, - "type": "array" - }, - { - "type": "null" + "404": { + "description": "Plugin not installed" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "title": "Plugins", - "description": "List of plugins to load for this conversation. Plugins are loaded and their skills/MCP config are merged into the agent. Hooks are extracted and stored for runtime execution." + }, + "description": "Validation Error" + } + }, + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Uninstall Plugin Endpoint", + "tags": [ + "Plugins" + ] + }, + "get": { + "description": "Get information about a specific installed plugin.", + "operationId": "get_installed_plugin_endpoint_api_plugins_installed__plugin_name__get", + "parameters": [ + { + "description": "Plugin name (lowercase alphanumeric, hyphens)", + "in": "path", + "name": "plugin_name", + "required": true, + "schema": { + "description": "Plugin name (lowercase alphanumeric, hyphens)", + "maxLength": 255, + "minLength": 1, + "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$", + "title": "Plugin Name", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InstalledPluginResponse" + } + } + }, + "description": "Successful Response" + }, + "404": { + "description": "Plugin not installed" }, - "hook_config": { - "anyOf": [ - { - "$ref": "#/components/schemas/HookConfig-Input" - }, - { - "type": "null" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "description": "Optional hook configuration for this conversation. Hooks are shell scripts that run at key lifecycle events (PreToolUse, PostToolUse, UserPromptSubmit, Stop, etc.). If both hook_config and plugins are provided, they are merged with explicit hooks running before plugin hooks." + }, + "description": "Validation Error" } }, - "type": "object", - "required": [ - "agent", - "workspace" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "StartConversationRequest", - "description": "Payload to create a new conversation.\n\nContains an Agent configuration along with conversation-specific options." + "summary": "Get Installed Plugin Endpoint", + "tags": [ + "Plugins" + ] }, - "StaticSecret-Input": { - "properties": { - "description": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "patch": { + "description": "Enable or disable an installed plugin.", + "operationId": "set_plugin_enabled_endpoint_api_plugins_installed__plugin_name__patch", + "parameters": [ + { + "description": "Plugin name (lowercase alphanumeric, hyphens)", + "in": "path", + "name": "plugin_name", + "required": true, + "schema": { + "description": "Plugin name (lowercase alphanumeric, hyphens)", + "maxLength": 255, + "minLength": 1, + "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$", + "title": "Plugin Name", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdatePluginStateRequest" } - ], - "title": "Description", - "description": "Optional description for this secret" + } }, - "value": { - "anyOf": [ - { - "type": "string", - "format": "password", - "writeOnly": true - }, - { - "type": "null" + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdatePluginStateResponse" + } } - ], - "title": "Value" + }, + "description": "Successful Response" }, - "kind": { - "type": "string", - "const": "StaticSecret", - "title": "Kind" + "404": { + "description": "Plugin not installed" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" } }, - "type": "object", - "title": "StaticSecret", - "description": "A secret stored locally" - }, - "StaticSecret-Output": { - "properties": { - "description": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Set Plugin Enabled Endpoint", + "tags": [ + "Plugins" + ] + } + }, + "/api/plugins/installed/{plugin_name}/refresh": { + "post": { + "description": "Refresh an installed plugin to the latest version from its source.", + "operationId": "refresh_plugin_endpoint_api_plugins_installed__plugin_name__refresh_post", + "parameters": [ + { + "description": "Plugin name (lowercase alphanumeric, hyphens)", + "in": "path", + "name": "plugin_name", + "required": true, + "schema": { + "description": "Plugin name (lowercase alphanumeric, hyphens)", + "maxLength": 255, + "minLength": 1, + "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$", + "title": "Plugin Name", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdatePluginResponse" + } } - ], - "title": "Description", - "description": "Optional description for this secret" + }, + "description": "Successful Response" }, - "value": { - "anyOf": [ - { - "type": "string", - "format": "password", - "writeOnly": true - }, - { - "type": "null" - } - ], - "title": "Value" + "404": { + "description": "Plugin not installed" }, - "kind": { - "type": "string", - "const": "StaticSecret", - "title": "Kind" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" } }, - "type": "object", - "required": [ - "kind" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "StaticSecret", - "description": "A secret stored locally" - }, - "Success": { - "properties": { - "success": { - "type": "boolean", - "title": "Success", - "default": true + "summary": "Refresh Plugin Endpoint", + "tags": [ + "Plugins" + ] + } + }, + "/api/plugins/marketplace": { + "get": { + "description": "Get the plugins marketplace catalog with installation status.\n\nReturns the true plugins (entries whose source lives under ``./plugins/``)\nfrom the OpenHands extensions repository marketplace, each with attachable\n``PluginSource`` coordinates (``source`` / ``ref`` / ``repo_path``) and an\n``installed`` flag. This enables the front-end to render a plugins\nmarketplace with install/installed state and to attach plugins to\nconversations.\n\nReturns:\n MarketplaceCatalogResponse containing the list of available plugins.", + "operationId": "get_marketplace_catalog_api_plugins_marketplace_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/openhands__agent_server__plugins_router__MarketplaceCatalogResponse" + } + } + }, + "description": "Successful Response" } }, - "type": "object", - "title": "Success" - }, - "SyncResponse": { - "properties": { - "status": { - "type": "string", - "enum": [ - "success", - "error" - ], - "title": "Status" - }, - "message": { - "type": "string", - "title": "Message" + "security": [ + { + "APIKeyHeader": [] } - }, - "type": "object", - "required": [ - "status", - "message" ], - "title": "SyncResponse", - "description": "Response from skill sync operation." - }, - "SystemPromptEvent": { - "properties": { - "id": { - "type": "string", - "title": "Id", - "description": "Unique event id (ULID/UUID)" - }, - "timestamp": { - "type": "string", - "title": "Timestamp", - "description": "Event timestamp" - }, - "source": { - "type": "string", - "enum": [ - "agent", - "user", - "environment" - ], - "title": "Source", - "default": "agent" - }, - "system_prompt": { - "$ref": "#/components/schemas/TextContent", - "description": "The system prompt text" - }, - "tools": { - "items": { - "$ref": "#/components/schemas/ToolDefinition" + "summary": "Get Marketplace Catalog", + "tags": [ + "Plugins" + ] + } + }, + "/api/profiles": { + "get": { + "description": "List all saved LLM profiles.\n\nReturns the list of profiles along with the currently active profile name,\nif one has been activated. The active_profile tracks which LLM profile\nconfiguration is currently in use.", + "operationId": "list_profiles_api_profiles_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProfileListResponse" + } + } }, - "type": "array", - "title": "Tools", - "description": "List of tools as ToolDefinition objects" - }, - "dynamic_context": { - "anyOf": [ - { - "$ref": "#/components/schemas/TextContent" - }, - { - "type": "null" + "description": "Successful Response" + } + }, + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "List Profiles", + "tags": [ + "Profiles" + ] + } + }, + "/api/profiles/{name}": { + "delete": { + "description": "Delete a saved profile (idempotent).\n\nGuarded by the agent-profile FK: returns 409 naming the referrers if any\n``AgentProfile`` still cites this LLM profile via ``llm_profile_ref``.", + "operationId": "delete_profile_api_profiles__name__delete", + "parameters": [ + { + "in": "path", + "name": "name", + "required": true, + "schema": { + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$", + "title": "Name", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProfileMutationResponse" + } } - ], - "description": "Optional dynamic per-conversation context (runtime info, repo context, secrets). When provided, this is included as a second content block in the system message (not cached)." + }, + "description": "Successful Response" }, - "kind": { - "type": "string", - "const": "SystemPromptEvent", - "title": "Kind" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" } }, - "additionalProperties": false, - "type": "object", - "required": [ - "system_prompt", - "tools", - "kind" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "SystemPromptEvent", - "description": "System prompt added by the agent.\n\nThe system prompt can optionally include dynamic context that varies between\nconversations. When ``dynamic_context`` is provided, it is included as a\nsecond content block in the same system message. Cache markers are NOT\napplied here - they are applied by ``LLM._apply_prompt_caching()`` when\ncaching is enabled, ensuring provider-specific cache control is only added\nwhen appropriate.\n\nAttributes:\n system_prompt: The static system prompt text (cacheable across conversations)\n tools: List of available tools\n dynamic_context: Optional per-conversation context (hosts, repo info, etc.)\n Sent as a second TextContent block inside the system message." + "summary": "Delete Profile", + "tags": [ + "Profiles" + ] }, - "TaskItem": { - "properties": { - "title": { - "type": "string", - "title": "Title", - "description": "A brief title for the task." - }, - "notes": { - "type": "string", - "title": "Notes", - "description": "Additional details or notes about the task.", - "default": "" + "get": { + "description": "Get a profile's configuration.\n\nUse the ``X-Expose-Secrets`` header to control secret exposure:\n- ``encrypted``: Returns cipher-encrypted values (safe for frontend clients)\n- ``plaintext``: Returns raw secret values (backend clients only!)\n- (absent): Returns nulled ``api_key`` with ``api_key_set`` indicator", + "operationId": "get_profile_api_profiles__name__get", + "parameters": [ + { + "in": "path", + "name": "name", + "required": true, + "schema": { + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$", + "title": "Name", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProfileDetailResponse" + } + } + }, + "description": "Successful Response" }, - "status": { - "type": "string", - "enum": [ - "todo", - "in_progress", - "done" - ], - "title": "Status", - "description": "The current status of the task. One of 'todo', 'in_progress', or 'done'.", - "default": "todo" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" } }, - "type": "object", - "required": [ - "title" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "TaskItem" + "summary": "Get Profile", + "tags": [ + "Profiles" + ] }, - "TaskTrackerAction": { - "properties": { - "command": { - "type": "string", - "enum": [ - "view", - "plan" - ], - "title": "Command", - "description": "The command to execute. `view` shows the current task list. `plan` creates or updates the task list based on provided requirements and progress. Always `view` the current list before making changes.", - "default": "view" + "post": { + "description": "Save an LLM configuration as a named profile.\n\nOverwrites an existing profile of the same name. Returns 409 if creating\na new profile would exceed ``MAX_PROFILES``.\n\nWhen ``OH_SECRET_KEY`` is configured, secrets are encrypted at rest.\nClients can submit cipher-encrypted secrets which will be decrypted\nserver-side before re-encrypting with the storage cipher.", + "operationId": "save_profile_api_profiles__name__post", + "parameters": [ + { + "in": "path", + "name": "name", + "required": true, + "schema": { + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$", + "title": "Name", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SaveProfileRequest" + } + } }, - "task_list": { - "items": { - "$ref": "#/components/schemas/TaskItem" + "required": true + }, + "responses": { + "201": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProfileMutationResponse" + } + } }, - "type": "array", - "title": "Task List", - "description": "The full task list. Required parameter of `plan` command." + "description": "Successful Response" }, - "kind": { - "type": "string", - "const": "TaskTrackerAction", - "title": "Kind" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" } }, - "additionalProperties": false, - "type": "object", - "required": [ - "kind" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "TaskTrackerAction", - "description": "An action where the agent writes or updates a task list for task management." - }, - "TaskTrackerObservation": { - "properties": { - "content": { - "items": { - "anyOf": [ - { - "$ref": "#/components/schemas/TextContent" - }, - { - "$ref": "#/components/schemas/ImageContent" + "summary": "Save Profile", + "tags": [ + "Profiles" + ] + } + }, + "/api/profiles/{name}/activate": { + "post": { + "description": "Activate a saved LLM profile.\n\nThis endpoint:\n1. Loads the named profile's LLM configuration\n2. Applies it to the current OpenHands agent settings (updates\n ``agent_settings.llm``); ACP settings have no LLM to update\n3. Records the profile name as the active profile for frontend tracking\n\nReturns 404 if the profile does not exist.\n\nUse ``GET /api/profiles`` to see which profile is currently active via\nthe ``active_profile`` field.", + "operationId": "activate_profile_api_profiles__name__activate_post", + "parameters": [ + { + "in": "path", + "name": "name", + "required": true, + "schema": { + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$", + "title": "Name", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ActivateProfileResponse" } - ] + } }, - "type": "array", - "title": "Content", - "description": "Content returned from the tool as a list of TextContent/ImageContent objects. When there is an error, it should be written in this field." - }, - "is_error": { - "type": "boolean", - "title": "Is Error", - "description": "Whether the observation indicates an error", - "default": false - }, - "command": { - "type": "string", - "enum": [ - "view", - "plan" - ], - "title": "Command", - "description": "The command that was executed: \"view\" or \"plan\"." + "description": "Successful Response" }, - "task_list": { - "items": { - "$ref": "#/components/schemas/TaskItem" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } }, - "type": "array", - "title": "Task List", - "description": "The current task list" - }, - "kind": { - "type": "string", - "const": "TaskTrackerObservation", - "title": "Kind" + "description": "Validation Error" } }, - "additionalProperties": false, - "type": "object", - "required": [ - "command", - "kind" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "TaskTrackerObservation", - "description": "This data class represents the result of a task tracking operation." - }, - "TaskTrackerTool": { - "properties": { - "description": { - "type": "string", - "title": "Description" + "summary": "Activate Profile", + "tags": [ + "Profiles" + ] + } + }, + "/api/profiles/{name}/rename": { + "post": { + "description": "Rename a saved profile atomically.\n\nReturns 404 if the source does not exist, or 409 if ``new_name`` already\nexists. A same-name rename is a verified no-op (still 404s if missing).\n\nIf the renamed profile is the currently active profile, the active_profile\nsetting is updated to the new name. Any ``AgentProfile.llm_profile_ref``\nciting the old name is cascaded to the new name in lock-step.", + "operationId": "rename_profile_api_profiles__name__rename_post", + "parameters": [ + { + "in": "path", + "name": "name", + "required": true, + "schema": { + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$", + "title": "Name", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RenameProfileRequest" + } + } }, - "action_type": { - "type": "string", - "title": "Action Type" + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProfileMutationResponse" + } + } + }, + "description": "Successful Response" }, - "observation_type": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Rename Profile", + "tags": [ + "Profiles" + ] + } + }, + "/api/profiles/{name}/validate": { + "post": { + "description": "Pre-flight check: fire a minimal LLM completion to catch misconfigurations.\n\nInstantiates the submitted LLM config and sends a 1-token completion to\nsurface errors like invalid model names, missing provider prefixes, bad\nbase URLs, and invalid API keys — *before* the profile is saved.\n\nTransient errors (rate limits, timeouts) are treated as non-blocking: the\nresponse is ``valid=True`` with no error, since those don't indicate a\nmisconfigured profile.", + "operationId": "validate_profile_api_profiles__name__validate_post", + "parameters": [ + { + "in": "path", + "name": "name", + "required": true, + "schema": { + "maxLength": 64, + "minLength": 1, + "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$", + "title": "Name", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ValidateProfileRequest" } - ], - "title": "Observation Type" + } }, - "annotations": { - "anyOf": [ - { - "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" - }, - { - "type": "null" + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ValidateProfileResponse" + } } - ] + }, + "description": "Successful Response" }, - "meta": { - "anyOf": [ - { - "additionalProperties": true, - "type": "object" - }, - { - "type": "null" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "title": "Meta" - }, - "kind": { - "type": "string", - "const": "TaskTrackerTool", - "title": "Kind" - }, - "title": { - "type": "string", - "title": "Title", - "readOnly": true + }, + "description": "Validation Error" } }, - "type": "object", - "required": [ - "description", - "action_type", - "kind", - "title" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "TaskTrackerTool", - "description": "A ToolDefinition subclass that automatically initializes a TaskTrackerExecutor." - }, - "TaskTrigger": { - "properties": { - "type": { - "type": "string", - "const": "task", - "title": "Type", - "default": "task" - }, - "triggers": { - "items": { - "type": "string" + "summary": "Validate Profile", + "tags": [ + "Profiles" + ] + } + }, + "/api/settings": { + "get": { + "description": "Get current settings.\n\nReturns the persisted settings including agent configuration,\nconversation settings, and whether an LLM API key is configured.\n\nUse the ``X-Expose-Secrets`` header to control secret exposure:\n- ``encrypted``: Returns cipher-encrypted values (safe for frontend clients)\n- ``plaintext``: Returns raw secret values (backend clients only!)\n- (absent): Returns redacted values (\"**********\")\n\nSecurity:\n When the server is configured with ``session_api_keys``, all endpoints\n under ``/api`` (including this one) require the ``X-Session-API-Key``\n header. When no session API keys are configured, endpoints are open.\n\n **Trust model:** All authenticated clients are treated as equally\n trusted. There is no role-based authorization for ``X-Expose-Secrets``\n modes—any authenticated client can request ``plaintext`` or\n ``encrypted`` exposure. This design assumes:\n\n - All clients sharing session API keys operate in the same trust domain\n - Network-level controls (firewalls, VPCs) restrict access to trusted\n clients only\n - Production deployments use session API keys to prevent anonymous access\n\n The ``plaintext`` mode exists for backend-to-backend communication\n (e.g., RemoteWorkspace). Frontend clients should prefer ``encrypted``\n mode for round-tripping secrets, or omit the header to receive redacted\n values.", + "operationId": "get_settings_api_settings_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SettingsResponse" + } + } }, - "type": "array", - "title": "Triggers" + "description": "Successful Response" } }, - "type": "object", - "required": [ - "triggers" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "TaskTrigger", - "description": "Trigger for task-specific skills.\n\nThese skills are activated for specific task types and can modify prompts." + "summary": "Get Settings", + "tags": [ + "Settings" + ] }, - "TerminalAction": { - "properties": { - "command": { - "type": "string", - "title": "Command", - "description": "The bash command to execute. Can be empty string to view additional logs when previous exit code is `-1`. Can be `C-c` (Ctrl+C) to interrupt the currently running process. Note: You can only execute one bash command at a time. If you need to run multiple commands sequentially, you can use `&&` or `;` to chain them together." - }, - "is_input": { - "type": "boolean", - "title": "Is Input", - "description": "If True, the command is an input to the running process. If False, the command is a bash command to be executed in the terminal. Default is False.", - "default": false - }, - "timeout": { - "anyOf": [ - { - "type": "number", - "minimum": 0.0 - }, - { - "type": "null" + "patch": { + "description": "Update settings with partial changes.\n\nAccepts ``agent_settings_diff``, ``conversation_settings_diff``,\n``misc_settings_diff``, and/or ``active_profile`` for incremental updates.\nSetting ``active_profile`` loads and applies that profile's LLM, same as\n``POST /api/profiles/{name}/activate``, unless ``agent_settings_diff.llm``\nis also given.\n\nThe three ``*_settings_diff`` fields are deep-merged; nested objects merge\nrecursively, and a ``null`` value **inside a nested map deletes that entry**\n— the \"unset\" primitive that lets a client remove a single map key without\nround-tripping the whole map. To remove one MCP server's header::\n\n PATCH /api/settings\n {\"agent_settings_diff\":\n {\"mcp_config\": {\"svc\": {\"headers\": {\"X-Old\": null}}}}}\n\nA ``null`` on a top-level *field* (e.g. ``{\"confirmation_mode\": null}``)\nis **not** an unset — it flows to model validation as before, so it still\nfails loudly rather than silently resetting the field to its default.\n\n``misc_settings_diff`` is deep-merged into the persisted ``misc_settings``\nblock. The agent-server treats ``misc_settings`` as opaque frontend-owned\ndata: nested dicts are merged recursively, lists are replaced wholesale,\nand the contents are never read or validated server-side.\n\nUses file locking to prevent concurrent updates from overwriting each other.\n\nRaises:\n HTTPException: 400 if the update payload contains invalid values.", + "operationId": "update_settings_api_settings_patch", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SettingsUpdateRequest" } - ], - "title": "Timeout", - "description": "Optional. Sets a maximum time limit (in seconds) for running the command. If the command takes longer than this limit, you\u2019ll be asked whether to continue or stop it. If you don\u2019t set a value, the command will instead pause and ask for confirmation when it produces no new output for 30 seconds. Use a higher value if the command is expected to take a long time (like installation or testing), or if it has a known fixed duration (like sleep)." + } }, - "reset": { - "type": "boolean", - "title": "Reset", - "description": "If True, reset the terminal by creating a new session. Use this only when the terminal becomes unresponsive. Note that all previously set environment variables and session state will be lost after reset. Cannot be used with is_input=True.", - "default": false + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SettingsResponse" + } + } + }, + "description": "Successful Response" }, - "kind": { - "type": "string", - "const": "TerminalAction", - "title": "Kind" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" } }, - "additionalProperties": false, - "type": "object", - "required": [ - "command", - "kind" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "TerminalAction", - "description": "Schema for bash command execution." - }, - "TerminalObservation": { - "properties": { - "content": { - "items": { - "anyOf": [ - { - "$ref": "#/components/schemas/TextContent" - }, - { - "$ref": "#/components/schemas/ImageContent" + "summary": "Update Settings", + "tags": [ + "Settings" + ] + } + }, + "/api/settings/agent-schema": { + "get": { + "description": "Return the schema used to render AgentSettings-based settings forms.", + "operationId": "get_agent_settings_schema_api_settings_agent_schema_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SettingsSchema" } - ] + } }, - "type": "array", - "title": "Content", - "description": "Content returned from the tool as a list of TextContent/ImageContent objects. When there is an error, it should be written in this field." - }, - "is_error": { - "type": "boolean", - "title": "Is Error", - "description": "Whether the observation indicates an error", - "default": false - }, - "command": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "description": "Successful Response" + } + }, + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Get Agent Settings Schema", + "tags": [ + "Settings" + ] + } + }, + "/api/settings/conversation-schema": { + "get": { + "description": "Return the schema used to render ConversationSettings-based forms.", + "operationId": "get_conversation_settings_schema_api_settings_conversation_schema_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SettingsSchema" + } } - ], - "title": "Command", - "description": "The bash command that was executed. Can be empty string if the observation is from a previous command that hit soft timeout and is not yet finished." - }, - "exit_code": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" + }, + "description": "Successful Response" + } + }, + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Get Conversation Settings Schema", + "tags": [ + "Settings" + ] + } + }, + "/api/settings/mcp/{settings_key}": { + "delete": { + "description": "Delete one existing named MCP server without altering sibling entries.", + "operationId": "delete_mcp_server_api_settings_mcp__settings_key__delete", + "parameters": [ + { + "in": "path", + "name": "settings_key", + "required": true, + "schema": { + "title": "Settings Key", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SettingsResponse" + } } - ], - "title": "Exit Code", - "description": "The exit code of the command. -1 indicates the process hit the soft timeout and is not yet finished." - }, - "timeout": { - "type": "boolean", - "title": "Timeout", - "description": "Whether the command execution timed out.", - "default": false - }, - "metadata": { - "$ref": "#/components/schemas/CmdOutputMetadata", - "description": "Additional metadata captured from PS1 after command execution." + }, + "description": "Successful Response" }, - "full_output_save_dir": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "title": "Full Output Save Dir", - "description": "Directory where full output files are saved" - }, - "kind": { - "type": "string", - "const": "TerminalObservation", - "title": "Kind" + }, + "description": "Validation Error" } }, - "additionalProperties": false, - "type": "object", - "required": [ - "command", - "kind" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "TerminalObservation", - "description": "A ToolResult that can be rendered as a CLI output." + "summary": "Delete Mcp Server", + "tags": [ + "Settings" + ] }, - "TerminalTool": { - "properties": { - "description": { - "type": "string", - "title": "Description" - }, - "action_type": { - "type": "string", - "title": "Action Type" - }, - "observation_type": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "patch": { + "description": "Sparsely update one existing named MCP server.", + "operationId": "patch_mcp_server_api_settings_mcp__settings_key__patch", + "parameters": [ + { + "in": "path", + "name": "settings_key", + "required": true, + "schema": { + "title": "Settings Key", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MCPServerPatch" } - ], - "title": "Observation Type" + } }, - "annotations": { - "anyOf": [ - { - "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" - }, - { - "type": "null" + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SettingsResponse" + } } - ] + }, + "description": "Successful Response" }, - "meta": { - "anyOf": [ - { - "additionalProperties": true, - "type": "object" - }, - { - "type": "null" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "title": "Meta" - }, - "kind": { - "type": "string", - "const": "TerminalTool", - "title": "Kind" - }, - "title": { - "type": "string", - "title": "Title", - "readOnly": true + }, + "description": "Validation Error" } }, - "type": "object", - "required": [ - "description", - "action_type", - "kind", - "title" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "TerminalTool", - "description": "A ToolDefinition subclass that automatically initializes a TerminalExecutor with auto-detection." + "summary": "Patch Mcp Server", + "tags": [ + "Settings" + ] }, - "TextContent": { - "properties": { - "cache_prompt": { - "type": "boolean", - "title": "Cache Prompt", - "default": false - }, - "type": { - "type": "string", - "const": "text", - "title": "Type", - "default": "text" - }, - "text": { - "type": "string", - "title": "Text" + "post": { + "description": "Create one named MCP server without replacing an existing map entry.", + "operationId": "create_mcp_server_api_settings_mcp__settings_key__post", + "parameters": [ + { + "in": "path", + "name": "settings_key", + "required": true, + "schema": { + "title": "Settings Key", + "type": "string" + } } - }, - "additionalProperties": false, - "type": "object", - "required": [ - "text" ], - "title": "TextContent" - }, - "ThinkAction": { - "properties": { - "thought": { - "type": "string", - "title": "Thought", - "description": "The thought to log." + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MCPServer-Input" + } + } }, - "kind": { - "type": "string", - "const": "ThinkAction", - "title": "Kind" + "required": true + }, + "responses": { + "201": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SettingsResponse" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" } }, - "additionalProperties": false, - "type": "object", - "required": [ - "thought", - "kind" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "ThinkAction", - "description": "Action for logging a thought without making any changes." - }, - "ThinkObservation": { - "properties": { - "content": { - "items": { + "summary": "Create Mcp Server", + "tags": [ + "Settings" + ] + } + }, + "/api/settings/secrets": { + "get": { + "description": "List available secret names, optionally scoped by an agent profile.", + "operationId": "list_secrets_api_settings_secrets_get", + "parameters": [ + { + "in": "query", + "name": "agent_profile_id", + "required": false, + "schema": { "anyOf": [ { - "$ref": "#/components/schemas/TextContent" + "type": "string" }, { - "$ref": "#/components/schemas/ImageContent" + "type": "null" } - ] - }, - "type": "array", - "title": "Content", - "description": "Content returned from the tool as a list of TextContent/ImageContent objects. When there is an error, it should be written in this field." - }, - "is_error": { - "type": "boolean", - "title": "Is Error", - "description": "Whether the observation indicates an error", - "default": false - }, - "kind": { - "type": "string", - "const": "ThinkObservation", - "title": "Kind" + ], + "title": "Agent Profile Id" + } } - }, - "additionalProperties": false, - "type": "object", - "required": [ - "kind" ], - "title": "ThinkObservation", - "description": "Observation returned after logging a thought.\nThe ThinkAction itself contains the thought logged so no extra\nfields are needed here." - }, - "ThinkTool": { - "properties": { - "description": { - "type": "string", - "title": "Description" - }, - "action_type": { - "type": "string", - "title": "Action Type" - }, - "observation_type": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Observation Type" - }, - "annotations": { - "anyOf": [ - { - "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" - }, - { - "type": "null" - } - ] - }, - "meta": { - "anyOf": [ - { - "additionalProperties": true, - "type": "object" - }, - { - "type": "null" + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SecretsListResponse" + } } - ], - "title": "Meta" - }, - "kind": { - "type": "string", - "const": "ThinkTool", - "title": "Kind" + }, + "description": "Successful Response" }, - "title": { - "type": "string", - "title": "Title", - "readOnly": true + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" } }, - "type": "object", - "required": [ - "description", - "action_type", - "kind", - "title" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "ThinkTool", - "description": "Tool for logging thoughts without making changes." + "summary": "List Secrets", + "tags": [ + "Settings" + ] }, - "ThinkingBlock": { - "properties": { - "type": { - "type": "string", - "const": "thinking", - "title": "Type", - "default": "thinking" + "put": { + "description": "Create or update a custom secret (upsert).\n\nRaises:\n HTTPException: 400 if secret name format is invalid, 500 if file is corrupted.", + "operationId": "create_secret_api_settings_secrets_put", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SecretCreateRequest" + } + } }, - "thinking": { - "type": "string", - "title": "Thinking", - "description": "The thinking content" + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SecretItemResponse" + } + } + }, + "description": "Successful Response" }, - "signature": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "title": "Signature", - "description": "Cryptographic signature for the thinking block" + }, + "description": "Validation Error" } }, - "type": "object", - "required": [ - "thinking" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "ThinkingBlock", - "description": "Anthropic thinking block for extended thinking feature.\n\nThis represents the raw thinking blocks returned by Anthropic models\nwhen extended thinking is enabled. These blocks must be preserved\nand passed back to the API for tool use scenarios." - }, - "TokenEvent": { - "properties": { - "id": { - "type": "string", - "title": "Id", - "description": "Unique event id (ULID/UUID)" - }, - "timestamp": { - "type": "string", - "title": "Timestamp", - "description": "Event timestamp" - }, - "source": { - "type": "string", - "enum": [ - "agent", - "user", - "environment" - ], - "title": "Source" - }, - "prompt_token_ids": { - "items": { - "type": "integer" + "summary": "Create Secret", + "tags": [ + "Settings" + ] + } + }, + "/api/settings/secrets/{name}": { + "delete": { + "description": "Delete a custom secret by name.\n\nRaises:\n HTTPException: 400 if name format is invalid, 404 if secret not found,\n 500 if file is corrupted.", + "operationId": "delete_secret_api_settings_secrets__name__delete", + "parameters": [ + { + "in": "path", + "name": "name", + "required": true, + "schema": { + "title": "Name", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "additionalProperties": { + "type": "boolean" + }, + "title": "Response Delete Secret Api Settings Secrets Name Delete", + "type": "object" + } + } }, - "type": "array", - "title": "Prompt Token Ids", - "description": "The exact prompt token IDs for this message event" + "description": "Successful Response" }, - "response_token_ids": { - "items": { - "type": "integer" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } }, - "type": "array", - "title": "Response Token Ids", - "description": "The exact response token IDs for this message event" - }, - "kind": { - "type": "string", - "const": "TokenEvent", - "title": "Kind" + "description": "Validation Error" } }, - "additionalProperties": false, - "type": "object", - "required": [ - "source", - "prompt_token_ids", - "response_token_ids", - "kind" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "TokenEvent", - "description": "Event from VLLM representing token IDs used in LLM interaction." + "summary": "Delete Secret", + "tags": [ + "Settings" + ] }, - "TokenUsage": { - "properties": { - "model": { - "type": "string", - "title": "Model", - "default": "" - }, - "prompt_tokens": { - "type": "integer", - "minimum": 0.0, - "title": "Prompt Tokens", - "description": "Prompt tokens must be non-negative", - "default": 0 - }, - "completion_tokens": { - "type": "integer", - "minimum": 0.0, - "title": "Completion Tokens", - "description": "Completion tokens must be non-negative", - "default": 0 - }, - "cache_read_tokens": { - "type": "integer", - "minimum": 0.0, - "title": "Cache Read Tokens", - "description": "Cache read tokens must be non-negative", - "default": 0 - }, - "cache_write_tokens": { - "type": "integer", - "minimum": 0.0, - "title": "Cache Write Tokens", - "description": "Cache write tokens must be non-negative", - "default": 0 - }, - "reasoning_tokens": { - "type": "integer", - "minimum": 0.0, - "title": "Reasoning Tokens", - "description": "Reasoning tokens must be non-negative", - "default": 0 - }, - "context_window": { - "type": "integer", - "minimum": 0.0, - "title": "Context Window", - "description": "Context window must be non-negative", - "default": 0 - }, - "per_turn_token": { - "type": "integer", - "minimum": 0.0, - "title": "Per Turn Token", - "description": "Per turn tokens must be non-negative", - "default": 0 + "get": { + "description": "Get a single secret value by name.\n\nReturns the raw secret value as plain text. This endpoint is designed\nto be used with LookupSecret for lazy secret resolution.\n\nRaises:\n HTTPException: 400 if name format is invalid, 404 if secret not found.", + "operationId": "get_secret_value_api_settings_secrets__name__get", + "parameters": [ + { + "in": "path", + "name": "name", + "required": true, + "schema": { + "title": "Name", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" }, - "response_id": { - "type": "string", - "title": "Response Id", - "default": "" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" } }, - "type": "object", - "title": "TokenUsage", - "description": "Metric tracking detailed token usage per completion call." - }, - "Tool-Input": { - "properties": { - "name": { - "type": "string", - "title": "Name", - "description": "Name of the tool class, e.g., 'TerminalTool'. Import it from an `openhands.tools.` subpackage.", - "examples": [ - "TerminalTool", - "FileEditorTool", - "TaskTrackerTool" - ] + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Get Secret Value", + "tags": [ + "Settings" + ] + } + }, + "/api/skills": { + "post": { + "description": "Load and merge skills from all configured sources.\n\nSkills are loaded from multiple sources and merged with the following\nprecedence (later overrides earlier for duplicate names):\n1. Sandbox skills (lowest) - Exposed URLs from sandbox\n2. Public skills - From GitHub OpenHands/extensions repository\n3. User skills - From ~/.openhands/skills/\n4. Organization skills - From {org}/.openhands or equivalent\n5. Project skills (highest) - From {workspace}/.openhands/skills/\n\nArgs:\n request: SkillsRequest containing configuration for which sources to load.\n\nReturns:\n SkillsResponse containing merged skills and source counts.", + "operationId": "get_skills_api_skills_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SkillsRequest" + } + } }, - "params": { - "additionalProperties": true, - "type": "object", - "title": "Params", - "description": "Parameters for the tool's .create() method, e.g., {'working_dir': '/app'}", - "examples": [ - { - "working_dir": "/workspace" + "required": true + }, + "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" } }, - "type": "object", - "required": [ - "name" - ], - "title": "Tool", - "description": "Defines a tool to be initialized for the agent.\n\nThis is only used in agent-sdk for type schema for server use." - }, - "ToolDefinition": { - "oneOf": [ - { - "$ref": "#/components/schemas/MCPToolDefinition" - }, - { - "$ref": "#/components/schemas/FinishTool" - }, - { - "$ref": "#/components/schemas/ThinkTool" - }, - { - "$ref": "#/components/schemas/BrowserClickTool" - }, - { - "$ref": "#/components/schemas/BrowserCloseTabTool" - }, - { - "$ref": "#/components/schemas/BrowserGetContentTool" - }, - { - "$ref": "#/components/schemas/BrowserGetStateTool" - }, - { - "$ref": "#/components/schemas/BrowserGetStorageTool" - }, - { - "$ref": "#/components/schemas/BrowserGoBackTool" - }, + "security": [ { - "$ref": "#/components/schemas/BrowserListTabsTool" + "APIKeyHeader": [] + } + ], + "summary": "Get Skills", + "tags": [ + "Skills" + ] + } + }, + "/api/skills/install": { + "post": { + "description": "Install a skill from a source.\n\nInstalls a skill from a git URL, GitHub shorthand, or local path into\nthe user's installed skills directory (~/.openhands/skills/installed/).\n\nArgs:\n request: InstallSkillRequest containing source and options.\n\nReturns:\n InstalledSkillResponse with details about the installation.\n\nRaises:\n HTTPException 409: If skill is already installed and force=False.\n HTTPException 400: If fetching the skill source fails.\n HTTPException 422: If the skill is invalid.", + "operationId": "install_skill_endpoint_api_skills_install_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InstallSkillRequest" + } + } }, - { - "$ref": "#/components/schemas/BrowserNavigateTool" + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InstalledSkillResponse" + } + } + }, + "description": "Successful Response" }, - { - "$ref": "#/components/schemas/BrowserScrollTool" + "400": { + "description": "Failed to fetch skill source" }, - { - "$ref": "#/components/schemas/BrowserSetStorageTool" + "409": { + "description": "Skill already installed (use force=true)" }, + "422": { + "description": "Invalid skill (missing SKILL.md, etc.)" + } + }, + "security": [ { - "$ref": "#/components/schemas/BrowserStartRecordingTool" - }, + "APIKeyHeader": [] + } + ], + "summary": "Install Skill Endpoint", + "tags": [ + "Skills" + ] + } + }, + "/api/skills/installed": { + "get": { + "description": "List all installed skills.\n\nReturns a list of all skills installed in the user's installed skills\ndirectory (~/.openhands/skills/installed/).\n\nReturns:\n InstalledSkillsListResponse containing list of installed skills.", + "operationId": "list_installed_skills_endpoint_api_skills_installed_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InstalledSkillsListResponse" + } + } + }, + "description": "Successful Response" + } + }, + "security": [ { - "$ref": "#/components/schemas/BrowserStopRecordingTool" - }, + "APIKeyHeader": [] + } + ], + "summary": "List Installed Skills Endpoint", + "tags": [ + "Skills" + ] + } + }, + "/api/skills/installed/{skill_name}": { + "delete": { + "description": "Uninstall a skill by name.\n\nRemoves a skill from the user's installed skills directory.\n\nArgs:\n skill_name: Name of the skill to uninstall.\n\nReturns:\n UninstallSkillResponse with uninstall message.\n\nRaises:\n HTTPException 404: If the skill is not installed.", + "operationId": "uninstall_skill_endpoint_api_skills_installed__skill_name__delete", + "parameters": [ { - "$ref": "#/components/schemas/BrowserSwitchTabTool" + "description": "Skill name (lowercase alphanumeric, hyphens)", + "in": "path", + "name": "skill_name", + "required": true, + "schema": { + "description": "Skill name (lowercase alphanumeric, hyphens)", + "maxLength": 255, + "minLength": 1, + "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$", + "title": "Skill Name", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UninstallSkillResponse" + } + } + }, + "description": "Successful Response" }, - { - "$ref": "#/components/schemas/BrowserToolSet" + "404": { + "description": "Skill not installed" }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "security": [ { - "$ref": "#/components/schemas/BrowserTypeTool" - }, + "APIKeyHeader": [] + } + ], + "summary": "Uninstall Skill Endpoint", + "tags": [ + "Skills" + ] + }, + "get": { + "description": "Get information about a specific installed skill.\n\nArgs:\n skill_name: Name of the skill to get.\n\nReturns:\n InstalledSkillResponse with skill details.\n\nRaises:\n HTTPException 404: If the skill is not installed.", + "operationId": "get_installed_skill_endpoint_api_skills_installed__skill_name__get", + "parameters": [ { - "$ref": "#/components/schemas/FileEditorTool" + "description": "Skill name (lowercase alphanumeric, hyphens)", + "in": "path", + "name": "skill_name", + "required": true, + "schema": { + "description": "Skill name (lowercase alphanumeric, hyphens)", + "maxLength": 255, + "minLength": 1, + "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$", + "title": "Skill Name", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InstalledSkillResponse" + } + } + }, + "description": "Successful Response" }, - { - "$ref": "#/components/schemas/EditTool" + "404": { + "description": "Skill not installed" }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "security": [ { - "$ref": "#/components/schemas/ListDirectoryTool" - }, + "APIKeyHeader": [] + } + ], + "summary": "Get Installed Skill Endpoint", + "tags": [ + "Skills" + ] + }, + "patch": { + "description": "Enable or disable an installed skill.\n\nArgs:\n skill_name: Name of the skill to update.\n request: UpdateSkillStateRequest with enabled state.\n\nReturns:\n UpdateSkillStateResponse indicating new state.\n\nRaises:\n HTTPException 404: If the skill is not installed.", + "operationId": "set_skill_enabled_endpoint_api_skills_installed__skill_name__patch", + "parameters": [ { - "$ref": "#/components/schemas/ReadFileTool" + "description": "Skill name (lowercase alphanumeric, hyphens)", + "in": "path", + "name": "skill_name", + "required": true, + "schema": { + "description": "Skill name (lowercase alphanumeric, hyphens)", + "maxLength": 255, + "minLength": 1, + "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$", + "title": "Skill Name", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateSkillStateRequest" + } + } }, - { - "$ref": "#/components/schemas/WriteFileTool" + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateSkillStateResponse" + } + } + }, + "description": "Successful Response" }, - { - "$ref": "#/components/schemas/GlobTool" + "404": { + "description": "Skill not installed" }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "security": [ { - "$ref": "#/components/schemas/GrepTool" - }, + "APIKeyHeader": [] + } + ], + "summary": "Set Skill Enabled Endpoint", + "tags": [ + "Skills" + ] + } + }, + "/api/skills/installed/{skill_name}/refresh": { + "post": { + "description": "Refresh an installed skill to the latest version.\n\nRe-fetches the skill from its original source and updates the installation.\n\nArgs:\n skill_name: Name of the skill to refresh.\n\nReturns:\n UpdateSkillResponse with updated skill information.\n\nRaises:\n HTTPException 404: If the skill is not installed.", + "operationId": "refresh_skill_endpoint_api_skills_installed__skill_name__refresh_post", + "parameters": [ { - "$ref": "#/components/schemas/PlanningFileEditorTool" + "description": "Skill name (lowercase alphanumeric, hyphens)", + "in": "path", + "name": "skill_name", + "required": true, + "schema": { + "description": "Skill name (lowercase alphanumeric, hyphens)", + "maxLength": 255, + "minLength": 1, + "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$", + "title": "Skill Name", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateSkillResponse" + } + } + }, + "description": "Successful Response" }, - { - "$ref": "#/components/schemas/TaskTrackerTool" + "404": { + "description": "Skill not installed" }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "security": [ { - "$ref": "#/components/schemas/TerminalTool" + "APIKeyHeader": [] } ], - "discriminator": { - "propertyName": "kind", - "mapping": { - "openhands__sdk__mcp__tool__MCPToolDefinition-Output__1": "#/components/schemas/MCPToolDefinition", - "openhands__sdk__tool__builtins__finish__FinishTool-Output__1": "#/components/schemas/FinishTool", - "openhands__sdk__tool__builtins__think__ThinkTool-Output__1": "#/components/schemas/ThinkTool", - "openhands__tools__browser_use__definition__BrowserClickTool-Output__1": "#/components/schemas/BrowserClickTool", - "openhands__tools__browser_use__definition__BrowserCloseTabTool-Output__1": "#/components/schemas/BrowserCloseTabTool", - "openhands__tools__browser_use__definition__BrowserGetContentTool-Output__1": "#/components/schemas/BrowserGetContentTool", - "openhands__tools__browser_use__definition__BrowserGetStateTool-Output__1": "#/components/schemas/BrowserGetStateTool", - "openhands__tools__browser_use__definition__BrowserGetStorageTool-Output__1": "#/components/schemas/BrowserGetStorageTool", - "openhands__tools__browser_use__definition__BrowserGoBackTool-Output__1": "#/components/schemas/BrowserGoBackTool", - "openhands__tools__browser_use__definition__BrowserListTabsTool-Output__1": "#/components/schemas/BrowserListTabsTool", - "openhands__tools__browser_use__definition__BrowserNavigateTool-Output__1": "#/components/schemas/BrowserNavigateTool", - "openhands__tools__browser_use__definition__BrowserScrollTool-Output__1": "#/components/schemas/BrowserScrollTool", - "openhands__tools__browser_use__definition__BrowserSetStorageTool-Output__1": "#/components/schemas/BrowserSetStorageTool", - "openhands__tools__browser_use__definition__BrowserStartRecordingTool-Output__1": "#/components/schemas/BrowserStartRecordingTool", - "openhands__tools__browser_use__definition__BrowserStopRecordingTool-Output__1": "#/components/schemas/BrowserStopRecordingTool", - "openhands__tools__browser_use__definition__BrowserSwitchTabTool-Output__1": "#/components/schemas/BrowserSwitchTabTool", - "openhands__tools__browser_use__definition__BrowserToolSet-Output__1": "#/components/schemas/BrowserToolSet", - "openhands__tools__browser_use__definition__BrowserTypeTool-Output__1": "#/components/schemas/BrowserTypeTool", - "openhands__tools__file_editor__definition__FileEditorTool-Output__1": "#/components/schemas/FileEditorTool", - "openhands__tools__gemini__edit__definition__EditTool-Output__1": "#/components/schemas/EditTool", - "openhands__tools__gemini__list_directory__definition__ListDirectoryTool-Output__1": "#/components/schemas/ListDirectoryTool", - "openhands__tools__gemini__read_file__definition__ReadFileTool-Output__1": "#/components/schemas/ReadFileTool", - "openhands__tools__gemini__write_file__definition__WriteFileTool-Output__1": "#/components/schemas/WriteFileTool", - "openhands__tools__glob__definition__GlobTool-Output__1": "#/components/schemas/GlobTool", - "openhands__tools__grep__definition__GrepTool-Output__1": "#/components/schemas/GrepTool", - "openhands__tools__planning_file_editor__definition__PlanningFileEditorTool-Output__1": "#/components/schemas/PlanningFileEditorTool", - "openhands__tools__task_tracker__definition__TaskTrackerTool-Output__1": "#/components/schemas/TaskTrackerTool", - "openhands__tools__terminal__definition__TerminalTool-Output__1": "#/components/schemas/TerminalTool" - } - } - }, - "UpdateConversationRequest": { - "properties": { - "title": { - "type": "string", - "maxLength": 200, - "minLength": 1, - "title": "Title", - "description": "New conversation title" + "summary": "Refresh Skill Endpoint", + "tags": [ + "Skills" + ] + } + }, + "/api/skills/marketplace": { + "get": { + "description": "Get the marketplace catalog with installation status.\n\nReturns a list of available skills from the OpenHands extensions\nrepository marketplace, along with their installation status.\n\nThis enables frontend applications to display a \"Marketplace\" tab\nwith installable skills.\n\nReturns:\n MarketplaceCatalogResponse containing list of available skills.", + "operationId": "get_marketplace_catalog_api_skills_marketplace_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/openhands__agent_server__skills_router__MarketplaceCatalogResponse" + } + } + }, + "description": "Successful Response" } }, - "type": "object", - "required": [ - "title" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "UpdateConversationRequest", - "description": "Payload to update conversation metadata." - }, - "UpdateSecretsRequest": { - "properties": { - "secrets": { - "additionalProperties": { - "$ref": "#/components/schemas/SecretSource-Input" + "summary": "Get Marketplace Catalog", + "tags": [ + "Skills" + ] + } + }, + "/api/skills/sync": { + "post": { + "description": "Force refresh of public skills from GitHub repository.\n\nThis triggers a git pull on the cached skills repository to get\nthe latest skills from the OpenHands/extensions repository.\n\nReturns:\n SyncResponse indicating success or failure.", + "operationId": "sync_skills_api_skills_sync_post", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SyncResponse" + } + } }, - "type": "object", - "title": "Secrets", - "description": "Dictionary mapping secret keys to values" + "description": "Successful Response" } }, - "type": "object", - "required": [ - "secrets" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "UpdateSecretsRequest", - "description": "Payload to update secrets in a conversation." - }, - "UserRejectObservation": { - "properties": { - "id": { - "type": "string", - "title": "Id", - "description": "Unique event id (ULID/UUID)" - }, - "timestamp": { - "type": "string", - "title": "Timestamp", - "description": "Event timestamp" - }, - "source": { - "type": "string", - "enum": [ - "agent", - "user", - "environment" - ], - "title": "Source", - "default": "environment" - }, - "tool_name": { - "type": "string", - "title": "Tool Name", - "description": "The tool name that this observation is responding to" - }, - "tool_call_id": { - "type": "string", - "title": "Tool Call Id", - "description": "The tool call id that this observation is responding to" - }, - "rejection_reason": { - "type": "string", - "title": "Rejection Reason", - "description": "Reason for rejecting the action", - "default": "User rejected the action" - }, - "rejection_source": { - "type": "string", - "enum": [ - "user", - "hook" - ], - "title": "Rejection Source", - "description": "Source of the rejection: 'user' for confirmation mode rejections, 'hook' for PreToolUse hook blocks", - "default": "user" + "summary": "Sync Skills", + "tags": [ + "Skills" + ] + } + }, + "/api/sub-agents": { + "post": { + "description": "List file-based and built-in sub-agents for the workspace.\n\nMerged first-wins by name with precedence project > user > builtin. Read-only:\nit registers nothing into the conversation registry.", + "operationId": "get_sub_agents_api_sub_agents_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SubAgentsRequest" + } + } }, - "action_id": { - "type": "string", - "title": "Action Id", - "description": "The action id that this observation is responding to" + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SubAgentsResponse" + } + } + }, + "description": "Successful Response" }, - "kind": { - "type": "string", - "const": "UserRejectObservation", - "title": "Kind" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" } }, - "additionalProperties": false, - "type": "object", - "required": [ - "tool_name", - "tool_call_id", - "action_id", - "kind" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "UserRejectObservation", - "description": "Observation when an action is rejected by user or hook.\n\nThis event is emitted when:\n- User rejects an action during confirmation mode (rejection_source=\"user\")\n- A PreToolUse hook blocks an action (rejection_source=\"hook\")" - }, - "VSCodeUrlResponse": { - "properties": { - "url": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "summary": "Get Sub Agents", + "tags": [ + "Sub Agents" + ] + } + }, + "/api/tools/": { + "get": { + "description": "List all available tools.", + "operationId": "list_available_tools_api_tools__get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "items": { + "type": "string" + }, + "title": "Response List Available Tools Api Tools Get", + "type": "array" + } } - ], - "title": "Url" + }, + "description": "Successful Response" } }, - "type": "object", - "required": [ - "url" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "VSCodeUrlResponse", - "description": "Response model for VSCode URL." - }, - "ValidationError": { - "properties": { - "loc": { - "items": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "integer" + "summary": "List Available Tools", + "tags": [ + "Tools" + ] + } + }, + "/api/tools/catalog": { + "get": { + "description": "List the tools this server offers for configuring an agent.\n\nClients offer the ``user_selectable`` entries; ``usable`` says whether the\nruntime conversations run in can run the tool.", + "operationId": "get_tool_catalog_api_tools_catalog_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ToolCatalogResponse" } - ] + } + }, + "description": "Successful Response" + } + }, + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Get Tool Catalog", + "tags": [ + "Tools" + ] + } + }, + "/api/vscode/status": { + "get": { + "description": "Get the VSCode server status.\n\nReturns:\n Dictionary with running status and enabled status", + "operationId": "get_vscode_status_api_vscode_status_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "additionalProperties": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + } + ] + }, + "title": "Response Get Vscode Status Api Vscode Status Get", + "type": "object" + } + } }, - "type": "array", - "title": "Location" - }, - "msg": { - "type": "string", - "title": "Message" - }, - "type": { - "type": "string", - "title": "Error Type" + "description": "Successful Response" } }, - "type": "object", - "required": [ - "loc", - "msg", - "type" - ], - "title": "ValidationError" - }, - "WriteFileAction": { - "properties": { - "file_path": { - "type": "string", - "title": "File Path", - "description": "The path to the file to write to." - }, - "content": { - "type": "string", - "title": "Content", - "description": "The content to write to the file." - }, - "kind": { - "type": "string", - "const": "WriteFileAction", - "title": "Kind" + "security": [ + { + "APIKeyHeader": [] } - }, - "additionalProperties": false, - "type": "object", - "required": [ - "file_path", - "content", - "kind" ], - "title": "WriteFileAction", - "description": "Schema for write file operation." - }, - "WriteFileObservation": { - "properties": { - "content": { - "items": { + "summary": "Get Vscode Status", + "tags": [ + "VSCode" + ] + } + }, + "/api/vscode/url": { + "get": { + "description": "Get the VSCode URL with authentication token.\n\nArgs:\n base_url: Base URL for the VSCode server. When omitted, the URL is\n built from the actually configured VSCode port\n (``http://localhost:{vscode_port}``), so callers that don't know\n the deployment topology get a URL that matches where the server\n really binds instead of a hardcoded ``:8001``.\n workspace_dir: Path to workspace directory\n\nReturns:\n VSCode URL with token if available, None otherwise", + "operationId": "get_vscode_url_api_vscode_url_get", + "parameters": [ + { + "in": "query", + "name": "base_url", + "required": false, + "schema": { "anyOf": [ { - "$ref": "#/components/schemas/TextContent" + "type": "string" }, { - "$ref": "#/components/schemas/ImageContent" + "type": "null" } - ] - }, - "type": "array", - "title": "Content", - "description": "Content returned from the tool as a list of TextContent/ImageContent objects. When there is an error, it should be written in this field." - }, - "is_error": { - "type": "boolean", - "title": "Is Error", - "description": "Whether the observation indicates an error", - "default": false - }, - "file_path": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "File Path", - "description": "The file path that was written." - }, - "is_new_file": { - "type": "boolean", - "title": "Is New File", - "description": "Whether a new file was created.", - "default": false - }, - "old_content": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Old Content", - "description": "The previous content of the file (if it existed)." - }, - "new_content": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "New Content", - "description": "The new content written to the file." - }, - "kind": { - "type": "string", - "const": "WriteFileObservation", - "title": "Kind" - } - }, - "additionalProperties": false, - "type": "object", - "required": [ - "kind" - ], - "title": "WriteFileObservation", - "description": "Observation from writing a file." - }, - "WriteFileTool": { - "properties": { - "description": { - "type": "string", - "title": "Description" - }, - "action_type": { - "type": "string", - "title": "Action Type" - }, - "observation_type": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Observation Type" - }, - "annotations": { - "anyOf": [ - { - "$ref": "#/components/schemas/openhands__sdk__tool__tool__ToolAnnotations" - }, - { - "type": "null" - } - ] - }, - "meta": { - "anyOf": [ - { - "additionalProperties": true, - "type": "object" - }, - { - "type": "null" - } - ], - "title": "Meta" - }, - "kind": { - "type": "string", - "const": "WriteFileTool", - "title": "Kind" + ], + "title": "Base Url" + } }, - "title": { - "type": "string", - "title": "Title", - "readOnly": true + { + "in": "query", + "name": "workspace_dir", + "required": false, + "schema": { + "default": "workspace", + "title": "Workspace Dir", + "type": "string" + } } - }, - "type": "object", - "required": [ - "description", - "action_type", - "kind", - "title" ], - "title": "WriteFileTool", - "description": "Tool for writing complete file contents." - }, - "mcp__types__Tool": { - "properties": { - "name": { - "type": "string", - "title": "Name" - }, - "title": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Title" - }, - "description": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Description" - }, - "inputSchema": { - "additionalProperties": true, - "type": "object", - "title": "Inputschema" - }, - "outputSchema": { - "anyOf": [ - { - "additionalProperties": true, - "type": "object" - }, - { - "type": "null" + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VSCodeUrlResponse" + } } - ], - "title": "Outputschema" + }, + "description": "Successful Response" }, - "icons": { - "anyOf": [ - { - "items": { - "$ref": "#/components/schemas/Icon" - }, - "type": "array" - }, - { - "type": "null" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "title": "Icons" - }, - "annotations": { - "anyOf": [ - { - "$ref": "#/components/schemas/mcp__types__ToolAnnotations" - }, - { - "type": "null" + }, + "description": "Validation Error" + } + }, + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Get Vscode Url", + "tags": [ + "VSCode" + ] + } + }, + "/api/workspaces": { + "delete": { + "description": "Remove a workspace by its absolute path.", + "operationId": "delete_workspace_api_workspaces_delete", + "parameters": [ + { + "description": "Absolute workspace path to remove", + "in": "query", + "name": "path", + "required": true, + "schema": { + "description": "Absolute workspace path to remove", + "title": "Path", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeleteResponse" + } } - ] + }, + "description": "Successful Response" }, - "_meta": { - "anyOf": [ - { - "additionalProperties": true, - "type": "object" - }, - { - "type": "null" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "title": "Meta" + }, + "description": "Validation Error" } }, - "additionalProperties": true, - "type": "object", - "required": [ - "name", - "inputSchema" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "Tool", - "description": "Definition for a tool the client can call." + "summary": "Delete Workspace", + "tags": [ + "Workspaces" + ] }, - "mcp__types__ToolAnnotations": { - "properties": { - "title": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Title" - }, - "readOnlyHint": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" + "get": { + "description": "Return the saved workspaces and workspace parents.", + "operationId": "list_workspaces_api_workspaces_get", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WorkspacesListResponse" + } } - ], - "title": "Readonlyhint" - }, - "destructiveHint": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" + }, + "description": "Successful Response" + } + }, + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "List Workspaces", + "tags": [ + "Workspaces" + ] + }, + "post": { + "description": "Append workspaces to the saved list. Idempotent — dedupes by ``path``.", + "operationId": "add_workspaces_api_workspaces_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AddWorkspacesRequest" } - ], - "title": "Destructivehint" + } }, - "idempotentHint": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WorkspacesListResponse" + } } - ], - "title": "Idempotenthint" + }, + "description": "Successful Response" }, - "openWorldHint": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ], - "title": "Openworldhint" + }, + "description": "Validation Error" } }, - "additionalProperties": true, - "type": "object", - "title": "ToolAnnotations", - "description": "Additional properties describing a Tool to clients.\n\nNOTE: all properties in ToolAnnotations are **hints**.\nThey are not guaranteed to provide a faithful description of\ntool behavior (including descriptive properties like `title`).\n\nClients should never make tool use decisions based on ToolAnnotations\nreceived from untrusted servers." - }, - "openhands__sdk__tool__spec__Tool": { - "properties": { - "name": { - "type": "string", - "title": "Name", - "description": "Name of the tool class, e.g., 'TerminalTool'. Import it from an `openhands.tools.` subpackage.", - "examples": [ - "TerminalTool", - "FileEditorTool", - "TaskTrackerTool" - ] + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Add Workspaces", + "tags": [ + "Workspaces" + ] + } + }, + "/api/workspaces/parents": { + "delete": { + "description": "Remove a workspace parent by its absolute path.", + "operationId": "delete_workspace_parent_api_workspaces_parents_delete", + "parameters": [ + { + "description": "Absolute workspace parent path to remove", + "in": "query", + "name": "path", + "required": true, + "schema": { + "description": "Absolute workspace parent path to remove", + "title": "Path", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeleteResponse" + } + } + }, + "description": "Successful Response" }, - "params": { - "additionalProperties": true, - "type": "object", - "title": "Params", - "description": "Parameters for the tool's .create() method, e.g., {'working_dir': '/app'}", - "examples": [ - { - "working_dir": "/workspace" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } } - ] + }, + "description": "Validation Error" } }, - "type": "object", - "required": [ - "name" + "security": [ + { + "APIKeyHeader": [] + } ], - "title": "Tool", - "description": "Defines a tool to be initialized for the agent.\n\nThis is only used in agent-sdk for type schema for server use." + "summary": "Delete Workspace Parent", + "tags": [ + "Workspaces" + ] }, - "openhands__sdk__tool__tool__ToolAnnotations": { - "properties": { - "title": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" + "post": { + "description": "Append workspace parents. Idempotent — dedupes by ``path``.", + "operationId": "add_workspace_parents_api_workspaces_parents_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AddWorkspaceParentsRequest" } - ], - "title": "Title", - "description": "A human-readable title for the tool." - }, - "readOnlyHint": { - "type": "boolean", - "title": "Readonlyhint", - "description": "If true, the tool does not modify its environment. Default: false", - "default": false - }, - "destructiveHint": { - "type": "boolean", - "title": "Destructivehint", - "description": "If true, the tool may perform destructive updates to its environment. If false, the tool performs only additive updates. (This property is meaningful only when `readOnlyHint == false`) Default: true", - "default": true + } }, - "idempotentHint": { - "type": "boolean", - "title": "Idempotenthint", - "description": "If true, calling the tool repeatedly with the same arguments will have no additional effect on the its environment. (This property is meaningful only when `readOnlyHint == false`) Default: false", - "default": false + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WorkspacesListResponse" + } + } + }, + "description": "Successful Response" }, - "openWorldHint": { - "type": "boolean", - "title": "Openworldhint", - "description": "If true, this tool may interact with an 'open world' of external entities. If false, the tool's domain of interaction is closed. For example, the world of a web search tool is open, whereas that of a memory tool is not. Default: true", - "default": true + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" } }, - "type": "object", - "title": "openhands.sdk.tool.tool.ToolAnnotations", - "description": "Annotations to provide hints about the tool's behavior.\n\nBased on Model Context Protocol (MCP) spec:\nhttps://github.com/modelcontextprotocol/modelcontextprotocol/blob/caf3424488b10b4a7b1f8cb634244a450a1f4400/schema/2025-06-18/schema.ts#L838" + "security": [ + { + "APIKeyHeader": [] + } + ], + "summary": "Add Workspace Parents", + "tags": [ + "Workspaces" + ] } } } -} \ No newline at end of file +}