{"openapi":"3.1.0","info":{"title":"Code API","version":"1.0.0","description":"REST API exposing the actions of the Code product. Authenticate with a Kavaro API key as a bearer token."},"servers":[{"url":"https://kavaro.ai"}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"http","scheme":"bearer","description":"A Kavaro API key (user- or organization-scoped)."}}},"security":[{"ApiKeyAuth":[]}],"paths":{"/api/rest/actions/list_instances":{"post":{"operationId":"list_instances","summary":"List instances","description":"List the organization's remote coding hosts with id, name, status (pairing/online/offline), host, kavaro-code daemon version, the coding agents installed on each, number of active sessions and when the agent was last seen.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["instances:view"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{},"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/get_instance":{"post":{"operationId":"get_instance","summary":"Inspect instance","description":"Get one instance with its daemon/host details, the coding agents it can run (with versions and readiness), GitHub CLI status, configured roots (directories/repositories with git info) and active sessions. Never returns tokens.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["instances:view"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"instanceId":{"type":"string","description":"The instance to inspect"}},"required":["instanceId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/list_directories":{"post":{"operationId":"list_directories","summary":"List directories","description":"List the directories/repositories the instance's agent exposes (its roots, and for a folder root its child projects), each with whether it is a git repository, its branch and remote. Live from the agent when online, else the last snapshot.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["instances:view"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"instanceId":{"type":"string","description":"The instance"}},"required":["instanceId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/browse_directory":{"post":{"operationId":"browse_directory","summary":"Browse directory","description":"List the sub-directories of a directory on the instance (must be under one of its roots), each with git info.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["instances:view"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"instanceId":{"type":"string"},"path":{"type":"string","description":"Absolute path on the host, under one of the instance's roots"}},"required":["instanceId","path"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/list_github_repos":{"post":{"operationId":"list_github_repos","summary":"List GitHub repositories","description":"List the GitHub repositories the host's `gh` CLI account can access (name, private flag, default branch). Empty with a reason when gh is not installed or not logged in.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["instances:view"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"instanceId":{"type":"string"},"query":{"description":"Filter by owner/name substring","type":"string"},"limit":{"type":"integer","exclusiveMinimum":0,"maximum":500}},"required":["instanceId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/list_models":{"post":{"operationId":"list_models","summary":"List models","description":"List the AI providers and models an agent kind on the instance can use, plus its default model. Defaults to the host's default agent kind.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["instances:view"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"instanceId":{"type":"string"},"agentKind":{"type":"string","enum":["opencode","claude_code","codex"]}},"required":["instanceId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/list_agent_kinds":{"post":{"operationId":"list_agent_kinds","summary":"List coding agents","description":"List the coding agents this host can run (opencode, claude_code, codex) with, for each: whether it is installed, its version, whether it is authenticated, any blocking problems, and what it can do (fork, revert, sub-agents, questions, shell, diff…).","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["instances:view"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"instanceId":{"type":"string"}},"required":["instanceId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/list_sessions":{"post":{"operationId":"list_sessions","summary":"List sessions","description":"List coding sessions started from Kavaro, newest first, with id, instance, title, agent kind, directory, worktree branch, status (active/detached/error/ended/cleanup_failed), cost and who started it.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["sessions:view"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"instanceId":{"description":"Only sessions on this instance","type":"string"},"status":{"type":"string","enum":["active","detached","error","ended","cleanup_failed"]},"limit":{"description":"Defaults to 50","type":"integer","exclusiveMinimum":0,"maximum":200}},"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/get_session_summary":{"post":{"operationId":"get_session_summary","summary":"Inspect session","description":"Get one session: its Kavaro row plus the live daemon session record (title, status, model, usage) and the agent's capabilities, when the host is online.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["sessions:view"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"sessionId":{"type":"string","description":"The Kavaro session id"}},"required":["sessionId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/list_exposures":{"post":{"operationId":"list_exposures","summary":"List direct-access exposures","description":"List the active (non-expired, non-revoked) direct-access exposures of an instance: scope (whole instance or one session), who created it, when it expires and when it was last used.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["sessions:view"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"instanceId":{"type":"string"}},"required":["instanceId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/list_agent_identities":{"post":{"operationId":"list_agent_identities","summary":"Linked agent accounts","description":"Which coding-agent accounts (Claude Code, Codex) are linked on an instance for the calling user: whether each is authenticated, which account, the plan, and when the login expires and must be renewed. Never returns credentials.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["instances:view"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"instanceId":{"type":"string","description":"The instance"},"all":{"description":"Include every user's identities on this host, not just your own (requires instances:edit)","type":"boolean"}},"required":["instanceId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/start_agent_login":{"post":{"operationId":"start_agent_login","summary":"Link an agent account","description":"Start linking your own Claude Code or Codex subscription on an instance. Returns an authorization URL plus how the login finishes: 'paste_code' (Claude) hands you a code in the browser which you pass to submit_agent_login, while 'device_code' (Codex) also returns a short userCode to type into the page and then completes on the host by itself — watch it with poll_agent_login. Logins expire (Claude: about 30 days) and are renewed by running this again.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["instances:view"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"instanceId":{"type":"string","description":"The instance to link the account on"},"kind":{"type":"string","enum":["claude_code","codex"],"description":"Which coding agent to link"},"email":{"description":"Pre-fills the email on the login page","type":"string"}},"required":["instanceId","kind"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/poll_agent_login":{"post":{"operationId":"poll_agent_login","summary":"Check a login in progress","description":"Where a login started with start_agent_login has got to. Needed for the 'device_code' flow, where nothing is sent back to the host and it finishes on its own once the person has entered the code. Returns done/error and, once finished, the linked account.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["instances:view"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"loginId":{"type":"string"}},"required":["loginId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/submit_agent_login":{"post":{"operationId":"submit_agent_login","summary":"Finish linking an agent account","description":"Finish a login started with start_agent_login by handing over the code the browser gave you. Returns the linked account and when it expires.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["instances:view"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"loginId":{"type":"string"},"code":{"type":"string","minLength":1,"maxLength":4096,"description":"The code from the browser"}},"required":["loginId","code"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/unlink_agent_identity":{"post":{"operationId":"unlink_agent_identity","summary":"Unlink an agent account","description":"Remove your linked coding-agent account from an instance. Deletes that account's configuration directory on the host, including its stored credentials and local transcripts.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["instances:view"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"instanceId":{"type":"string"},"kind":{"type":"string","enum":["claude_code","codex"]}},"required":["instanceId","kind"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/create_instance":{"post":{"operationId":"create_instance","summary":"Add instance","description":"Register a new remote OpenCode instance. Returns the instance plus a ONE-TIME pairing token and the single install command to run on the host (valid 15 minutes). Show the command to the user verbatim.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["instances:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80,"description":"A name for the host, e.g. 'Build box'"}},"required":["name"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/regenerate_pairing_token":{"post":{"operationId":"regenerate_pairing_token","summary":"New pairing token","description":"Issue a fresh one-time pairing token + install command for an instance whose previous token expired or was lost. Revokes the old pairing token (an already-paired agent keeps working).","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["instances:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"instanceId":{"type":"string"}},"required":["instanceId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/update_instance":{"post":{"operationId":"update_instance","summary":"Rename instance","description":"Rename an instance.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["instances:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"instanceId":{"type":"string"},"name":{"type":"string","minLength":1,"maxLength":80}},"required":["instanceId","name"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/delete_instance":{"post":{"operationId":"delete_instance","summary":"Remove instance","description":"Remove an instance: revokes its agent token (a connected agent is told to stop and forget its credentials), deletes its session records and exposures. Does not touch files on the host.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["instances:delete"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"instanceId":{"type":"string"}},"required":["instanceId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/clone_repository":{"post":{"operationId":"clone_repository","summary":"Clone repository","description":"Clone a repository into a folder root on the instance using the host's own credentials (`gh repo clone` for a GitHub owner/name, else `git clone <url>`). Returns the new directory with its git info.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["instances:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"instanceId":{"type":"string"},"rootPath":{"type":"string","description":"A folder root on the instance to clone into"},"repo":{"description":"GitHub owner/name, e.g. acme/api","type":"string"},"url":{"description":"Any git clone URL (when not a GitHub repo)","type":"string"},"name":{"description":"Directory name; defaults to the repository name","type":"string"}},"required":["instanceId","rootPath"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/restart_opencode":{"post":{"operationId":"restart_opencode","summary":"Restart OpenCode","description":"Restart the managed OpenCode server on the instance (running sessions are interrupted).","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["settings:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"instanceId":{"type":"string"}},"required":["instanceId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/update_opencode":{"post":{"operationId":"update_opencode","summary":"Update OpenCode","description":"Ask the agent to update OpenCode to the latest release on the host.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["settings:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"instanceId":{"type":"string"}},"required":["instanceId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/update_agent":{"post":{"operationId":"update_agent","summary":"Update agent","description":"Ask the agent to self-update to the version this server publishes now (it restarts itself; OpenCode sessions keep running).","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["settings:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"instanceId":{"type":"string"}},"required":["instanceId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/install_agent_kind":{"post":{"operationId":"install_agent_kind","summary":"Install coding agent","description":"Ask the host to install a coding agent (Claude Code or Codex) — a pinned npm install into the agent's own directory, not the host's global npm, and never run implicitly when a session starts. OpenCode uses restart_opencode/update_opencode instead; installing it here reports 'not applicable'.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["settings:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"instanceId":{"type":"string"},"kind":{"type":"string","enum":["opencode","claude_code","codex"]}},"required":["instanceId","kind"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/update_agent_kind":{"post":{"operationId":"update_agent_kind","summary":"Update coding agent","description":"Re-run the pinned install for a coding agent kind (Claude Code or Codex) so the host picks up the version this server currently ships. OpenCode uses restart_opencode/update_opencode instead.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["settings:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"instanceId":{"type":"string"},"kind":{"type":"string","enum":["opencode","claude_code","codex"]}},"required":["instanceId","kind"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/restart_agent_kind":{"post":{"operationId":"restart_agent_kind","summary":"Restart coding agent","description":"Detach every session currently attached to this agent kind so each respawns fresh on its next prompt (their running turns are interrupted; native conversations and session records are untouched).","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["settings:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"instanceId":{"type":"string"},"kind":{"type":"string","enum":["opencode","claude_code","codex"]}},"required":["instanceId","kind"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/set_fallback_chain":{"post":{"operationId":"set_fallback_chain","summary":"Set agent fallback chain","description":"Configure this instance's agent-kind fallback chain (#1305): an ordered list of {kind, providerId?, modelId?} a session falls through to when the preferred kind is over its usage quota or unavailable, plus the utilization threshold (percent) that trips it. Pass an empty chain to disable fallback. Applies to sessions started on this host; does not affect running turns.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["settings:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"instanceId":{"type":"string"},"chain":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["opencode","claude_code","codex"]},"providerId":{"anyOf":[{"type":"string"},{"type":"null"}]},"modelId":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["kind"],"additionalProperties":false},"description":"Ordered fallback entries; the first is the preferred kind"},"threshold":{"description":"Utilization percent that trips fallback (default 90)","type":"integer","minimum":1,"maximum":100}},"required":["instanceId","chain"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/list_scheduled_prompts":{"post":{"operationId":"list_scheduled_prompts","summary":"List scheduled prompts","description":"List the organization's scheduled prompts: prompt, agent kind/model, target directory, ordered instance priority list, frequency, next run time, enabled/status, last run and how many sessions each has spawned.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["sessions:view"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{},"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/create_scheduled_prompt":{"post":{"operationId":"create_scheduled_prompt","summary":"Create scheduled prompt","description":"Schedule a prompt to run later or on a repeating schedule. It fires via the cron sweep and starts a NEW session seeded with the prompt on the chosen agent kind/model, on the first reachable host from `instanceIds` (falling through if one is down), then applying the host's agent-kind fallback chain. Give exactly one target: `directory` (an existing repository on the host — each run gets its own git worktree) OR `cloneRepo`/`cloneUrl` (a repository cloned fresh into a session-owned directory on every run). frequency 'never' runs it exactly once. Returns the schedule.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["sessions:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"name":{"type":"string","maxLength":120},"prompt":{"type":"string","minLength":1,"description":"The prompt text the session is seeded with"},"directory":{"description":"Existing repository/directory on the host (a root or child project); each run gets its own git worktree. Omit when using cloneRepo/cloneUrl.","anyOf":[{"type":"string"},{"type":"null"}]},"cloneRepo":{"description":"GitHub owner/name to clone fresh each run (via the host's gh CLI). Alternative to `directory`.","anyOf":[{"type":"string"},{"type":"null"}]},"cloneUrl":{"description":"Any git clone URL to clone fresh each run. Alternative to `directory`.","anyOf":[{"type":"string"},{"type":"null"}]},"instanceIds":{"minItems":1,"type":"array","items":{"type":"string"},"description":"Ordered host priority list; the fire runs on the first reachable one"},"agentKind":{"description":"Preferred coding agent (defaults to the host's default kind)","type":"string","enum":["opencode","claude_code","codex"]},"providerId":{"type":"string"},"modelId":{"type":"string"},"useWorktree":{"description":"Create a git worktree for each fired session (default true for git repos)","type":"boolean"},"fallbackChain":{"description":"Per-schedule agent-kind fallback chain override; defaults to the instance's","type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["opencode","claude_code","codex"]},"providerId":{"anyOf":[{"type":"string"},{"type":"null"}]},"modelId":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["kind"],"additionalProperties":false}},"frequency":{"type":"string","enum":["never","hourly","daily","weekly","monthly"],"description":"never (once) | hourly | daily | weekly | monthly"},"startAt":{"type":"string","description":"ISO 8601 time of the first run"}},"required":["prompt","instanceIds","frequency","startAt"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/update_scheduled_prompt":{"post":{"operationId":"update_scheduled_prompt","summary":"Update scheduled prompt","description":"Edit a scheduled prompt (any of: name, prompt, target (directory OR cloneRepo/cloneUrl), host list, agent kind/model, worktree flag, fallback chain, frequency, start time). Setting a clone target clears `directory` and vice versa. Recomputes the next run time when the timing changes.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["sessions:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"scheduleId":{"type":"string"},"name":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}]},"prompt":{"type":"string","minLength":1},"directory":{"anyOf":[{"type":"string"},{"type":"null"}]},"cloneRepo":{"anyOf":[{"type":"string"},{"type":"null"}]},"cloneUrl":{"anyOf":[{"type":"string"},{"type":"null"}]},"instanceIds":{"minItems":1,"type":"array","items":{"type":"string"}},"agentKind":{"anyOf":[{"type":"string","enum":["opencode","claude_code","codex"]},{"type":"null"}]},"providerId":{"anyOf":[{"type":"string"},{"type":"null"}]},"modelId":{"anyOf":[{"type":"string"},{"type":"null"}]},"useWorktree":{"type":"boolean"},"fallbackChain":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["opencode","claude_code","codex"]},"providerId":{"anyOf":[{"type":"string"},{"type":"null"}]},"modelId":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["kind"],"additionalProperties":false}},{"type":"null"}]},"frequency":{"type":"string","enum":["never","hourly","daily","weekly","monthly"]},"startAt":{"type":"string"}},"required":["scheduleId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/set_scheduled_prompt_enabled":{"post":{"operationId":"set_scheduled_prompt_enabled","summary":"Enable/disable scheduled prompt","description":"Pause (disable) or resume (enable) a scheduled prompt without deleting it. A disabled schedule never fires; re-enabling recomputes its next run time.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["sessions:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"scheduleId":{"type":"string"},"enabled":{"type":"boolean"}},"required":["scheduleId","enabled"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/delete_scheduled_prompt":{"post":{"operationId":"delete_scheduled_prompt","summary":"Delete scheduled prompt","description":"Delete a scheduled prompt. Sessions it already spawned are kept.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["sessions:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"scheduleId":{"type":"string"}},"required":["scheduleId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/start_session":{"post":{"operationId":"start_session","summary":"Start session","description":"Start a new coding-agent session on an instance. Give either `directory` (one of the host's roots or a child project) OR `clone` to check a repository out into an agent-owned, session-specific directory and run there (the way to open any repo on a host that is not itself sitting in a git repo). When the directory is a git repository a dedicated worktree + branch is created (unless useWorktree is false); a cloned session runs directly in its checkout. Returns the Kavaro session (open it at /sessions/:id).","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["sessions:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"instanceId":{"type":"string"},"directory":{"description":"Absolute path of the repository/directory on the host (omit when using `clone`)","type":"string"},"title":{"description":"Optional session title","type":"string","maxLength":200},"useWorktree":{"description":"Create a git worktree for the session (default true for git repositories)","type":"boolean"},"agentKind":{"description":"Which coding agent to run (opencode, claude_code, codex). Defaults to the host's own default.","type":"string","enum":["opencode","claude_code","codex"]},"providerId":{"description":"Pin the session's model provider (e.g. 'anthropic'); defaults to the agent's own default.","type":"string"},"modelId":{"description":"Pin the session's model id within `providerId`; defaults to the agent's own default.","type":"string"},"options":{"description":"Model parameters to pin on the session, option id → value (e.g. {\"effort\":\"high\",\"fast\":\"on\"} for Claude Code, {\"variant\":\"high\"} for OpenCode). Valid ids/values come from list_agent_kinds (`options`, or a model's `variants`).","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}},"clone":{"description":"Clone a repo into a session-owned directory and run there instead of using `directory`","type":"object","properties":{"repo":{"description":"GitHub owner/name, e.g. acme/api (uses the host's gh CLI)","type":"string"},"url":{"description":"Any git clone URL (when not a GitHub repo)","type":"string"},"name":{"description":"Directory name; defaults to the repository name","type":"string"}},"additionalProperties":false}},"required":["instanceId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/end_session":{"post":{"operationId":"end_session","summary":"End session","description":"End a session: aborts any running turn, disposes of the agent's own session, force-removes the session's git worktree and branch on the host (uncommitted changes in the worktree are discarded, and commits on the branch are lost unless it was pushed — use push_session first to keep them), and archives the session record.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["sessions:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"sessionId":{"type":"string"}},"required":["sessionId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/delete_session":{"post":{"operationId":"delete_session","summary":"Delete session","description":"Permanently delete one or more sessions and remove them from the list. Pass `sessionIds` to delete several in ONE call (preferred whenever the user wants to clean up more than one — never loop single calls); `sessionId` still works for exactly one. A session that is still running is ended first (turn aborted, worktree/clone removed on the host), then its record is deleted (this also removes its pending requests). Each id is handled independently: the result lists `deleted` ids and `failed` ids with their reason, and the call only errors when nothing could be deleted. Use end_session to finish a session but keep it as a record.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["sessions:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"sessionId":{"description":"Exactly one session to delete.","type":"string"},"sessionIds":{"description":"Several sessions to delete in one call (bulk clean-up).","minItems":1,"maxItems":100,"type":"array","items":{"type":"string","minLength":1}}},"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/send_prompt":{"post":{"operationId":"send_prompt","summary":"Send prompt","description":"Send a prompt to a session's coding agent. Returns as soon as the turn is accepted, never when it finishes; the turn streams into the session view. Optionally pick a model (providerID/modelID from list_models) or a mode/sub-agent (e.g. build/plan).","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["sessions:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"sessionId":{"type":"string"},"text":{"type":"string","minLength":1},"model":{"type":"object","properties":{"providerID":{"type":"string"},"modelID":{"type":"string"}},"required":["providerID","modelID"],"additionalProperties":false},"options":{"description":"Model parameters for this and later prompts, option id → value (effort, fast, OpenCode variant) — see start_session.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}},"agent":{"type":"string"},"attachments":{"type":"array","items":{"type":"object","properties":{"fileId":{"type":"string"},"url":{"type":"string"},"mime":{"type":"string"},"filename":{"type":"string"}},"required":["mime"],"additionalProperties":false}}},"required":["sessionId","text"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/abort_session":{"post":{"operationId":"abort_session","summary":"Abort turn","description":"Stop the turn currently running in a session.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["sessions:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"sessionId":{"type":"string"}},"required":["sessionId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/fork_session":{"post":{"operationId":"fork_session","summary":"Continue with a different agent","description":"Fork a session to continue the same work under a different coding agent (or the same one). The target kind must be one this host reports available/authenticated. mode 'full' carries the whole prior transcript as context; 'compress' summarizes it first and seeds the new session with the summary (cheaper for long sessions). Creates a NEW session linked to the original (which is left untouched); returns it (open at /sessions/:id).","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["sessions:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"sessionId":{"type":"string","description":"The session to fork from"},"agentKind":{"type":"string","enum":["opencode","claude_code","codex"],"description":"Which coding agent the new session should run"},"mode":{"description":"full = carry the whole transcript (default); compress = summarize it first and seed with the summary","type":"string","enum":["full","compress"]}},"required":["sessionId","agentKind"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/list_pending_requests":{"post":{"operationId":"list_pending_requests","summary":"Pending agent requests","description":"Everything an agent has stopped and asked a human about: permission requests it is blocked on and questions it asked, with which session and host they belong to and whether they can still be answered. Note this shows what an agent CHOSE to ask about — not every action it takes.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["sessions:view"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"sessionId":{"description":"Only this session's requests","type":"string"},"instanceId":{"description":"Only this host's requests","type":"string"},"scope":{"description":"Defaults to pending","type":"string","enum":["pending","resolved","all"]},"limit":{"type":"integer","exclusiveMinimum":0,"maximum":200}},"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/answer_permission":{"post":{"operationId":"answer_permission","summary":"Answer a permission request","description":"Answer a permission request an agent is blocked on: allow it once, always allow it (remembering the pattern where the agent supports that), or reject it. Returns `{status}` — `answered`, `already_resolved` when somebody (or the host TUI) got there first, or `undeliverable` when the decision was recorded but could not reach the host.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["sessions:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"requestId":{"type":"string","description":"The pending request id from list_pending_requests or the inbox"},"answer":{"type":"string","enum":["once","always","reject"]}},"required":["requestId","answer"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/answer_question":{"post":{"operationId":"answer_question","summary":"Answer a question","description":"Answer (or dismiss) a question an agent asked. `answers` holds one array of chosen option labels per question, in order.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["sessions:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"requestId":{"type":"string","description":"The pending request id from list_pending_requests or the inbox"},"answers":{"type":"array","items":{"type":"array","items":{"type":"string"}}},"reject":{"description":"Dismiss the question instead of answering it","type":"boolean"}},"required":["requestId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/rename_session":{"post":{"operationId":"rename_session","summary":"Rename session","description":"Rename a session. The title is Kavaro's own, so this works even for agent kinds with no native rename and while the host is offline.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["sessions:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"sessionId":{"type":"string"},"title":{"type":"string","minLength":1,"maxLength":200}},"required":["sessionId","title"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/get_session_diff":{"post":{"operationId":"get_session_diff","summary":"Session file changes","description":"The files a session has changed, with per-file added/removed line counts — native for OpenCode, derived with `git diff` of the session's worktree for the other agent kinds.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["sessions:view"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"sessionId":{"type":"string"}},"required":["sessionId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/push_session":{"post":{"operationId":"push_session","summary":"Push / open pull request","description":"Keep a session's work: push its branch (kavaro-code/…) to the repository's `origin` and, when that remote is GitHub, open a pull request (or return the one already open) using the host's GitHub CLI. Only COMMITTED work is pushed — uncommitted changes are counted in `uncommittedChanges`, never committed for you (ask the agent to commit first). Use this before end_session when the user wants to keep the work: ending a session deletes its worktree and branch. Returns the branch, `pullRequestUrl` (or `pullRequestError` saying why there is none) and a `compareUrl` fallback.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["sessions:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"sessionId":{"type":"string"},"openPr":{"description":"Open a pull request when the remote is GitHub (default true)","type":"boolean"},"title":{"description":"Pull request title (defaults to the session title)","type":"string","maxLength":200},"body":{"description":"Pull request description","type":"string","maxLength":20000}},"required":["sessionId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/revert_session":{"post":{"operationId":"revert_session","summary":"Undo to a message","description":"Undo a session back to the given message, discarding the changes made after it. Only offered by agent kinds whose capabilities report `revert`.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["sessions:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"sessionId":{"type":"string"},"messageId":{"type":"string"},"partId":{"type":"string"}},"required":["sessionId","messageId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/summarize_session":{"post":{"operationId":"summarize_session","summary":"Compact the context","description":"Summarize a session's history so the conversation fits back inside the model's context window. OpenCode sessions only.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["sessions:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"sessionId":{"type":"string"}},"required":["sessionId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/run_shell":{"post":{"operationId":"run_shell","summary":"Run shell command","description":"Run a shell command directly in a session's working directory, bypassing the model. Only offered by agent kinds whose capabilities report `shell`. Returns as soon as the command is accepted; its output streams into the session view. Runs arbitrary code on the host — audited, but the command text itself is never recorded.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["sessions:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"sessionId":{"type":"string"},"command":{"type":"string","minLength":1},"agent":{"description":"Which sub-agent/mode runs it; defaults to the session's own","type":"string"}},"required":["sessionId","command"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/run_command":{"post":{"operationId":"run_command","summary":"Run command","description":"Run one of the agent's own slash commands in a session (from its command catalog), bypassing the model. Only offered by agent kinds whose capabilities report `commands`. Returns as soon as it is accepted; its output streams into the session view.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["sessions:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"sessionId":{"type":"string"},"command":{"type":"string","minLength":1,"description":"The command's name, without the leading /"},"arguments":{"type":"string"},"agent":{"type":"string"}},"required":["sessionId","command"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/create_exposure":{"post":{"operationId":"create_exposure","summary":"Create direct access","description":"Mint a time-boxed public endpoint so the user's own OpenCode TUI (`opencode attach`) or web/desktop app can connect to the instance — or to just one session. Returns the URL, username and a ONE-TIME password plus the attach command. Expires after ttlMinutes (60, 480 or 1440) and can be revoked any time.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["sessions:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"instanceId":{"type":"string"},"sessionId":{"description":"Scope the access to this Kavaro session only","type":"string"},"ttlMinutes":{"description":"Lifetime in minutes: 60 (default), 480 or 1440","type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["instanceId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/revoke_exposure":{"post":{"operationId":"revoke_exposure","summary":"Revoke direct access","description":"Revoke a direct-access exposure immediately; connected TUI/web clients get 401 on their next request.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["sessions:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"exposureId":{"type":"string"}},"required":["exposureId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/get_config_profile":{"post":{"operationId":"get_config_profile","summary":"Get central configuration","description":"Get the organization's central agent configuration: its MCP servers, instruction documents ('memory'), sub-agent definitions, model policy, drift policy and version, plus the names (never the values) of its secrets and which entries use them. This is the configuration pushed to every paired host.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["config:view"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{},"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/list_mcp_servers":{"post":{"operationId":"list_mcp_servers","summary":"List MCP servers","description":"List the MCP servers defined centrally for this organization: key, transport, command/url, which agent kinds they apply to, and which secret environment variables they reference (names only).","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["config:view"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{},"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/list_instruction_docs":{"post":{"operationId":"list_instruction_docs","summary":"List instruction documents","description":"List the organization's instruction documents ('memory') that are pushed into every agent's native instruction store: key, title, which agent kinds get them, and whether they are enabled.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["config:view"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{},"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/get_config_status":{"post":{"operationId":"get_config_status","summary":"Configuration rollout status","description":"How the central configuration has landed on each paired host: the profile version the host applied versus the current version, per-agent-kind state (applied / pending / drift / error / unsupported), whether a restart is still required for it to take effect, and any readiness notes.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["config:view"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"instanceId":{"description":"Only this instance; omit for every instance","type":"string"}},"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/update_config_profile":{"post":{"operationId":"update_config_profile","summary":"Update configuration settings","description":"Rename the configuration profile or change its drift policy. `report` (the default) records a hand edit to a Kavaro-managed key as drift and leaves the host's file alone; `overwrite` restores Kavaro's value on the next apply. Prefer `report` — Kavaro is a control plane, not config police.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["config:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120},"description":{"type":"string","maxLength":500},"driftPolicy":{"type":"string","enum":["report","overwrite"]}},"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/create_mcp_server":{"post":{"operationId":"create_mcp_server","summary":"Add MCP server","description":"Define an MCP server centrally, once, for every paired host — translated into each agent's native shape (opencode `mcp`, Claude Code `.mcp.json`, Codex `[mcp_servers.*]`). Use `stdio` with a command, or `http` with a url. Secrets are NEVER written into a config file: create them with set_config_secret and name them in `secretEnvVars` / `bearerTokenEnvVar`, which become an environment indirection.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["config:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"name":{"type":"string","maxLength":120},"description":{"type":"string","maxLength":500},"enabled":{"type":"boolean"},"transport":{"type":"string","enum":["stdio","http"]},"command":{"type":"string","maxLength":500},"args":{"type":"array","items":{"type":"string"}},"url":{"type":"string","maxLength":1000},"headers":{"description":"Static, NON-SECRET headers. Never put a token here — define a secret and reference it.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}},"env":{"description":"Static, NON-SECRET environment. Never put a token here — define a secret and reference it.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}},"secretEnvVars":{"description":"Names of secrets to inject; the config file only ever gets an indirection","type":"array","items":{"type":"string","pattern":"^[A-Z_][A-Z0-9_]*$"}},"bearerTokenEnvVar":{"type":"string","pattern":"^[A-Z_][A-Z0-9_]*$"},"agentKinds":{"description":"Restrict to these agent kinds; omit for every kind the host runs","type":"array","items":{"type":"string","enum":["opencode","claude_code","codex"]}},"timeoutMs":{"type":"integer","exclusiveMinimum":0,"maximum":600000},"key":{"type":"string","pattern":"^[a-z0-9][a-z0-9_-]{0,63}$","description":"Stable slug used as the native config key, e.g. 'linear'"}},"required":["transport","key"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/read_host_mcp_servers":{"post":{"operationId":"read_host_mcp_servers","summary":"Read MCP servers from hosts","description":"Read the MCP servers the coding agents on the organization's paired hosts ALREADY have in their own configuration (OpenCode opencode.json; Claude Code ~/.claude.json at user AND project-local scope plus each known project's .mcp.json; Codex config.toml plus trusted projects' .codex/config.toml), grouped by server with where each was found — to adopt them centrally with import_host_mcp_servers. Read-only, and values are never returned: environment variables and headers come back as NAMES. `existing` marks keys already defined centrally; `conflicting` marks a key hosts define differently. `appBound` lists entries that are built into the app they were found in (claude.ai connectors, Codex/ChatGPT apps, app-bundled binaries) — seen, but not importable, because they cannot run in another agent. Offline hosts are listed but not read.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["config:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"instanceId":{"description":"Only this host (default: every paired host)","type":"string"}},"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/import_host_mcp_servers":{"post":{"operationId":"import_host_mcp_servers","summary":"Import MCP servers from hosts","description":"Adopt MCP servers the hosts already have (from read_host_mcp_servers) as central definitions, by key. Each env var / bearer token becomes a secret REFERENCE. With `importSecrets: true` (org owners only — requires secrets:edit) the hosts' stored values are read over the authenticated tunnel and sealed straight into the write-only secret store on the server: they never appear in this result or anywhere else, and a secret that already has a central value is kept, not rotated. The result names which secrets were filled, kept, or still need a value.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["config:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"keys":{"minItems":1,"type":"array","items":{"type":"string","pattern":"^[a-z0-9][a-z0-9_-]{0,63}$"},"description":"Central keys as listed by read_host_mcp_servers"},"instanceId":{"description":"Only read this host (default: every online host)","type":"string"},"importSecrets":{"description":"Also import the hosts' secret values (owner-only, write-only store)","type":"boolean"}},"required":["keys"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/update_mcp_server":{"post":{"operationId":"update_mcp_server","summary":"Update MCP server","description":"Change a centrally-defined MCP server. Only the fields you pass are changed. Bumps the configuration version so every assigned host re-applies.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["config:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"serverId":{"type":"string","description":"The MCP server row id"},"name":{"type":"string","maxLength":120},"description":{"type":"string","maxLength":500},"enabled":{"type":"boolean"},"transport":{"type":"string","enum":["stdio","http"]},"command":{"type":"string","maxLength":500},"args":{"type":"array","items":{"type":"string"}},"url":{"type":"string","maxLength":1000},"headers":{"description":"Static, NON-SECRET headers. Never put a token here — define a secret and reference it.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}},"env":{"description":"Static, NON-SECRET environment. Never put a token here — define a secret and reference it.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}},"secretEnvVars":{"description":"Names of secrets to inject; the config file only ever gets an indirection","type":"array","items":{"type":"string","pattern":"^[A-Z_][A-Z0-9_]*$"}},"bearerTokenEnvVar":{"type":"string","pattern":"^[A-Z_][A-Z0-9_]*$"},"agentKinds":{"description":"Restrict to these agent kinds; omit for every kind the host runs","type":"array","items":{"type":"string","enum":["opencode","claude_code","codex"]}},"timeoutMs":{"type":"integer","exclusiveMinimum":0,"maximum":600000}},"required":["serverId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/delete_mcp_server":{"post":{"operationId":"delete_mcp_server","summary":"Remove MCP server","description":"Remove a centrally-defined MCP server. On the next apply every host drops it from its native configuration (the ownership manifest records exactly which key was ours).","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["config:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"serverId":{"type":"string"}},"required":["serverId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/provision_kavaro_mcp":{"post":{"operationId":"provision_kavaro_mcp","summary":"Give agents Code's own tools","description":"Turn Kavaro's own MCP endpoint on (or off) for the coding agents on every paired machine. It exposes ONE product and only one — Code itself, the product that manages those agents. Products are isolated: no agent on somebody's laptop is ever handed tools that reach accounting, geometra or any other product's data, and there is no setting that widens it. Turning it on mints one organization API key, stored as a write-only secret. IMPORTANT: an API key always acts as a PERSON — every action an agent takes through it is attributed in the audit trail to the user who turned it on. By default the agents get READ access only; `sessionControl` additionally lets them start, drive and stop sessions on your machines, which means an agent can start another agent — leave it off unless that is what you want. Pass enabled=false to remove the entry and revoke the key.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["config:edit","secrets:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"enabled":{"type":"boolean","description":"Whether the agents may reach Code's tools at all. false removes the entry and revokes the key."},"sessionControl":{"description":"Also allow starting, driving and stopping sessions on hosts (an agent can then start another agent). Defaults to false.","type":"boolean"},"rotate":{"description":"Mint a new key and revoke the previous one","type":"boolean"}},"required":["enabled"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/set_model_policy":{"post":{"operationId":"set_model_policy","summary":"Set model policy","description":"Set the default model (and, for opencode, the cheap 'small' model used for titles and summaries) that every host should use, plus providers to switch off. The policy selects from what each HOST has already authenticated — Kavaro ships no provider credentials and never proxies model traffic. `allowedModels` is advisory: centrally restricting the selectable set is weak on opencode, pin-only on Codex and impossible on Claude Code, and is reported as a note rather than promised as enforcement.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["config:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"defaultModel":{"anyOf":[{"type":"object","properties":{"providerId":{"type":"string"},"modelId":{"type":"string"}},"required":["providerId","modelId"],"additionalProperties":false},{"type":"null"}]},"smallModel":{"anyOf":[{"type":"object","properties":{"providerId":{"type":"string"},"modelId":{"type":"string"}},"required":["providerId","modelId"],"additionalProperties":false},{"type":"null"}]},"disabledProviders":{"type":"array","items":{"type":"string"}},"allowedModels":{"description":"Advisory allow-list of 'providerId/modelId' strings","type":"array","items":{"type":"string"}}},"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/upsert_instruction_doc":{"post":{"operationId":"upsert_instruction_doc","summary":"Save instruction document","description":"Create or replace an organization instruction document — the central 'memory' pushed into each agent's own instruction store (an `instructions` glob on opencode, an @import on Claude Code, an inlined managed block on Codex). One-way by design: an agent's own accumulated memory is never mirrored back into Kavaro.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["config:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"key":{"type":"string","pattern":"^[a-z0-9][a-z0-9_-]{0,63}$","description":"Stable slug used as the file name, e.g. 'house-style'"},"title":{"type":"string","minLength":1,"maxLength":200},"body":{"type":"string","minLength":1,"maxLength":100000,"description":"Markdown instructions the agents read"},"enabled":{"type":"boolean"},"agentKinds":{"type":"array","items":{"type":"string","enum":["opencode","claude_code","codex"]}}},"required":["key","title","body"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/delete_instruction_doc":{"post":{"operationId":"delete_instruction_doc","summary":"Remove instruction document","description":"Remove an organization instruction document. On the next apply it is deleted from every host — the ownership manifest records the file as ours, so removal is exact.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["config:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"key":{"type":"string","pattern":"^[a-z0-9][a-z0-9_-]{0,63}$"}},"required":["key"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/upsert_agent_definition":{"post":{"operationId":"upsert_agent_definition","summary":"Save sub-agent","description":"Create or replace a central sub-agent definition — a named specialist (reviewer, migration writer, …) with its own prompt, optional model pin and optional tool list, pushed to every paired host. Translated into opencode's `agent` configuration and a Claude Code `agents/<key>.md` file. Codex has no sub-agent mechanism, so definitions targeted at it are reported as unsupported rather than silently dropped.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["config:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"key":{"type":"string","pattern":"^[a-z0-9][a-z0-9_-]{0,63}$","description":"Stable slug used as the native key and file name, e.g. 'reviewer'"},"name":{"type":"string","minLength":1,"maxLength":120},"description":{"type":"string","minLength":1,"maxLength":500,"description":"When the agent should hand work to this sub-agent"},"prompt":{"type":"string","minLength":1,"maxLength":100000,"description":"The sub-agent's system prompt"},"mode":{"type":"string","enum":["subagent","primary","all"]},"model":{"description":"Optional model pin — 'providerId/modelId' for opencode, a bare id for Claude Code","anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"tools":{"description":"Tool names the sub-agent may use; omit for the agent's default set","anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}]},"enabled":{"type":"boolean"},"agentKinds":{"type":"array","items":{"type":"string","enum":["opencode","claude_code","codex"]}}},"required":["key","name","description","prompt"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/delete_agent_definition":{"post":{"operationId":"delete_agent_definition","summary":"Remove sub-agent","description":"Remove a central sub-agent definition. On the next apply every host deletes exactly the file or key Kavaro wrote for it.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["config:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"key":{"type":"string","pattern":"^[a-z0-9][a-z0-9_-]{0,63}$"}},"required":["key"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/set_config_secret":{"post":{"operationId":"set_config_secret","summary":"Set configuration secret","description":"Store (or rotate) the value of one environment variable that MCP servers may reference. The value is encrypted at rest, never readable again through any surface — the UI and this action's result show only a short hint — never written into a config file, and travels only inside the authenticated config push, landing in a 0600 file on the host that is injected into the agent's child processes.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["secrets:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"key":{"type":"string","pattern":"^[A-Z_][A-Z0-9_]*$","description":"The environment variable name, e.g. LINEAR_API_KEY"},"value":{"type":"string","minLength":1,"description":"The secret value. Write-only — it can never be read back."}},"required":["key","value"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/delete_config_secret":{"post":{"operationId":"delete_config_secret","summary":"Remove configuration secret","description":"Delete a stored configuration secret. On the next apply every host removes the variable from its 0600 secrets file.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["secrets:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"key":{"type":"string","pattern":"^[A-Z_][A-Z0-9_]*$"}},"required":["key"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/apply_config":{"post":{"operationId":"apply_config","summary":"Apply configuration","description":"Push the current central configuration to a paired host (or to every online host) and report what landed. Files are written atomically and recorded in an ownership manifest, so a later removal is exact. A changed MCP or model set needs the agent to reload: with no active sessions the host restarts its agent by itself, otherwise it reports 'restart required' and never interrupts running work.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["config:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"instanceId":{"description":"The host to push to; omit to push to every online host","type":"string"},"restart":{"description":"Ask the host to restart the agent afterwards even if sessions are active (it will still refuse to kill a running session)","type":"boolean"}},"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}}}}