34 KiB
API Reference
managed-agents exposes a local-first JSON API under /v1. The Dashboard, the
TypeScript SDK, and external automation all use the same resource model: agents,
sessions, environments, credential vaults, memory stores, files, skills, API
keys, and runtime operations.
The API is intentionally close to Claude Managed Agents while remaining local and inspectable. Resource metadata is stored in SQLite, uploaded assets live under the runtime data directory, and session timelines are persisted as replayable events.
Interactive Reference
Open Settings > API reference in the Dashboard for an in-product reference page
modeled after platform API docs:
- endpoint navigation grouped by resource
- method/path headers for each operation
- header, query, body, and return field descriptions
- copyable
curlexamples generated from the active runtime base URL - TypeScript SDK and Skill upload examples
Use this page when integrating a local runtime into scripts, CI jobs, desktop apps, or an internal control plane. It reflects the server you are connected to, including whether bearer authentication is currently enabled.
Runtime Contract
The local server exposes the Dashboard and API from the same origin:
Dashboard: http://127.0.0.1:3000/dashboard
API: http://127.0.0.1:3000/v1
All timestamps are RFC 3339 strings. Identifiers are opaque tagged ids such as
agent_..., sess_..., env_..., skill_..., and memstore_...; clients
should not infer meaning from their length or suffix.
CMA Compatibility Headers and Authentication
Authentication is disabled by default for local development. It is enabled when
at least one API key exists. Keys can be supplied through
MANAGED_AGENTS_API_KEY or created through /v1/api-keys.
CMA clients may authenticate with either header when authentication is enabled:
x-api-key: ma_local_example
Authorization: Bearer ma_local_example
Use exactly one credential scheme per request. A request carrying both
Authorization and x-api-key is rejected with 401 authentication_error,
even if the values match; this prevents credential-source ambiguity at proxy
and middleware boundaries.
Requests using x-api-key, or either Anthropic compatibility header, are
admitted before CMA route handlers run. They must include:
anthropic-version: 2023-06-01
Normal CMA resources require the managed-agents beta:
anthropic-beta: managed-agents-2026-04-01
Memory-store resources (/v1/memory_stores and descendants) instead require:
anthropic-beta: agent-memory-2026-07-22
Do not combine that beta with managed-agents-2026-04-01 on a memory-store
request: admission rejects the pair with 400 invalid_request. The documented
read-only exception, GET /v1/memory_stores/{id}/memories, accepts either of
those two betas when sent alone.
anthropic-beta accepts comma-separated identifiers; the required identifier
must appear in the list. Missing, malformed, or unsupported compatibility
headers return 400 with the standard invalid_request error envelope before
route business logic executes. Runtime extension endpoints under /v1/x do not
use CMA header admission.
Existing bearer callers that omit the CMA compatibility headers remain supported
unchanged. A bearer request that sends either compatibility header is validated
by the same CMA policy. Raw API keys are never returned from list or retrieve
responses. A newly created managed key returns secret_key once; store it
before discarding the response.
Pagination and Errors
Collection responses:
{
"data": [],
"has_more": false,
"first_id": null,
"last_id": null
}
Error responses:
{
"error": {
"type": "invalid_request",
"message": "name is required"
}
}
Common error types are invalid_request, not_found, conflict,
not_available, and internal_error.
API Keys
API keys control bearer-token authentication for the local runtime. Managed keys
are stored in SQLite as SHA-256 hashes. Keys from config or environment variables
are shown as read-only config_env records.
| Method | Path | Purpose |
|---|---|---|
GET |
/v1/api-keys |
List managed and configured API keys. |
POST |
/v1/api-keys |
Create a managed API key. |
DELETE |
/v1/api-keys/{key_id} |
Delete a managed API key. |
Create a key:
curl -X POST http://127.0.0.1:3000/v1/api-keys \
-H "Content-Type: application/json" \
-d '{ "name": "Local Console" }'
Create response:
{
"id": "key_abc123",
"type": "api_key",
"name": "Local Console",
"source": "managed",
"key_prefix": "ma_abc123...wxyz",
"status": "active",
"created_at": "2026-07-12T00:00:00.000Z",
"updated_at": "2026-07-12T00:00:00.000Z",
"last_used_at": null,
"archived_at": null,
"secret_key": "ma_full_secret_returned_once"
}
List response entries omit secret_key:
{
"id": "key_abc123",
"type": "api_key",
"name": "Local Console",
"source": "managed",
"key_prefix": "ma_abc123...wxyz",
"status": "active",
"last_used_at": "2026-07-12T00:01:00.000Z"
}
Agents
Agents are SQLite-backed runtime resources. Optional YAML files in the configured agents directory can seed a workspace, but creates and updates are persisted in the local database.
Agent ids are object identifiers. Seeded YAML agents use deterministic ids on
import; API and Console-created agents receive server-generated agent_... ids.
Names are display fields and do not need to be unique.
| Method | Path | Purpose |
|---|---|---|
GET |
/v1/agents |
List loaded agents. |
POST |
/v1/agents |
Create an agent resource. |
GET |
/v1/agents/{agent_id} |
Retrieve an agent. |
PUT |
/v1/agents/{agent_id} |
Save a new agent version. |
GET |
/v1/agents/{agent_id}/versions |
List versions known to the local store. |
POST |
/v1/agents/{agent_id}/archive |
Archive an agent. |
Create an agent:
curl -X POST http://127.0.0.1:3000/v1/agents \
-H "Content-Type: application/json" \
-d '{
"name": "assistant",
"description": "Helps with development tasks.",
"model": "default",
"system": "You are a helpful assistant.",
"mcp_servers": [],
"tools": [{ "type": "agent_toolset_20260401" }],
"skills": [],
"metadata": {}
}'
Agent response:
{
"id": "agent_01JAbcdefghijklmnopqrstuvw",
"type": "agent",
"name": "assistant",
"description": "Helps with development tasks.",
"model": "default",
"status": "active",
"version": 1,
"created_at": "2026-07-12T00:00:00.000Z",
"updated_at": "2026-07-12T00:00:00.000Z",
"archived_at": null
}
Update an agent with optimistic version checking:
curl -X PUT http://127.0.0.1:3000/v1/agents/agent_abc123 \
-H "Content-Type: application/json" \
-d '{
"name": "assistant",
"description": "Updated instructions.",
"model": "default",
"system": "You are a helpful assistant. Prefer concise answers.",
"tools": [{ "type": "agent_toolset_20260401" }],
"skills": [],
"expected_version": 1
}'
When expected_version is present and does not match the current agent
version, the API returns 409 conflict. Each successful create/update writes an
immutable snapshot returned by /v1/agents/{agent_id}/versions.
Sessions
Sessions run an agent in an environment and persist a resumable event log.
| Method | Path | Purpose |
|---|---|---|
GET |
/v1/sessions |
List sessions. |
POST |
/v1/sessions |
Create a session. |
GET |
/v1/sessions/{session_id} |
Retrieve a session. |
POST |
/v1/sessions/{session_id}/messages |
Send a user message and optionally stream. |
POST |
/v1/sessions/{session_id}/events |
Append user events. |
GET |
/v1/sessions/{session_id}/events |
List persisted events. |
GET |
/v1/sessions/{session_id}/events/stream |
Stream live events with SSE. |
POST |
/v1/sessions/{session_id}/stop |
Stop a session. |
DELETE |
/v1/sessions/{session_id} |
Delete a session from active listings. |
Create a session:
curl -X POST http://127.0.0.1:3000/v1/sessions \
-H "Content-Type: application/json" \
-d '{
"agent": "agent_assistant",
"environment_id": "env_default",
"title": "Local test",
"resources": [],
"vault_ids": [],
"metadata": { "source": "docs" }
}'
Pin a session to an immutable agent version snapshot:
{
"agent": {
"id": "agent_abc123",
"type": "agent",
"version": 1
},
"environment_id": "env_default",
"title": "Replay version 1"
}
When agent.version is supplied, the runtime stores that agent definition
snapshot on the session. Later edits to the agent do not change the pinned
session's prompt, tools, or skills.
Supported session resources:
[
{
"type": "file",
"file_id": "file_abc123",
"mount_path": "/uploads/input.txt"
},
{
"type": "github_repository",
"url": "https://github.com/owner/repo",
"authorization_token": "ghp_example",
"checkout": "main",
"mount_path": "/workspace/repo"
},
{
"type": "memory_store",
"memory_store_id": "memstore_abc123",
"access": "read_write",
"instructions": "Use this for durable project notes."
}
]
Only user.* events can be appended by clients:
curl -X POST http://127.0.0.1:3000/v1/sessions/SESSION_ID/events \
-H "Content-Type: application/json" \
-d '{
"events": [
{
"type": "user.message",
"content": [{ "type": "text", "text": "Hello" }]
}
]
}'
Tool confirmation and client-side custom tool result events are also appended through the same endpoint:
{
"events": [
{
"type": "user.tool_confirmation",
"tool_use_id": "toolu_abc123",
"result": "allow"
},
{
"type": "user.custom_tool_result",
"custom_tool_use_id": "customu_abc123",
"content": [{ "type": "text", "text": "Result returned by an external client-side tool." }]
}
]
}
The runtime currently supports the event protocol and Console/SDK result submission. First-class custom tool registration and discovery is still a planned extension point; until then, clients should treat custom tool use ids as opaque ids emitted by the session event stream.
Send and stream a message:
curl -N -X POST http://127.0.0.1:3000/v1/sessions/SESSION_ID/messages \
-H "Content-Type: application/json" \
-d '{"content": "Hello", "stream": true}'
Resume the event stream:
curl -N http://127.0.0.1:3000/v1/sessions/SESSION_ID/events/stream \
-H "Last-Event-ID: 42"
Event ordering and metadata
Persisted event responses include an append-only per-session seq and optional
metadata. The same envelope is used by GET /events and the resumable event
tail. SSE uses the numeric seq as its id; send the highest contiguous value
received as Last-Event-ID to replay only later durable events. Transient
agent.message_stream_* events have seq: 0, are not replayed, and must not
advance that cursor.
Model-derived events may include model_used, tokens_in, tokens_out,
stop_reason, and duration_ms. Token fields on event projections provide
local attribution only; session usage is recorded once per model request and
is the source for aggregate token totals.
Approval-gated tool_use blocks include requires_confirmation: true and a
confirmation_group_id. The corresponding user.tool_confirmation event
stores its target and decision in event metadata. The session stays in
requires_action until every tool use in that group has a paired result. The
session response exposes that state as status: "requires_action"; the
matching session.status_idle event carries metadata with
stop_reason.type: "requires_action", pending event_ids, and
action_type: "tool_confirmation" for protocol compatibility.
Session event records may include optional execution metadata when available:
model_used, tokens_in, tokens_out, stop_reason, and duration_ms.
Clients should treat absent fields as unknown and preserve the event's existing
append-only ordering and SSE resume semantics.
Files
Files can be uploaded once and mounted into sessions.
| Method | Path | Purpose |
|---|---|---|
GET |
/v1/files |
List active files. |
POST |
/v1/files |
Upload a file. |
GET |
/v1/files/{file_id} |
Retrieve file metadata and preview. |
GET |
/v1/files/{file_id}/content |
Download file content. |
DELETE |
/v1/files/{file_id} |
Archive a file. |
Multipart upload:
curl -X POST http://127.0.0.1:3000/v1/files \
-F "file=@notes.txt"
JSON upload:
curl -X POST http://127.0.0.1:3000/v1/files \
-H "Content-Type: application/json" \
-d '{
"name": "notes.txt",
"media_type": "text/plain",
"content": "hello",
"encoding": "utf8"
}'
The per-file upload limit is 10 MB.
Session Artifacts
Artifacts are generated outputs associated with a session. They use the same
local artifact storage backend as uploaded files, but are listed under the
session instead of /v1/files.
| Method | Path | Purpose |
|---|---|---|
GET |
/v1/sessions/{session_id}/artifacts |
List generated artifacts for a session. |
POST |
/v1/sessions/{session_id}/artifacts |
Record a generated artifact. |
GET |
/v1/sessions/{session_id}/artifacts/{artifact_id}/content |
Download artifact content. |
Artifact paths must start with /artifacts/:
curl -X POST http://127.0.0.1:3000/v1/sessions/SESSION_ID/artifacts \
-H "Content-Type: application/json" \
-d '{
"path": "/artifacts/report.md",
"name": "report.md",
"media_type": "text/markdown",
"content": "# Run report\n\nGenerated locally."
}'
Text, Markdown, JSON, YAML, HTML, and SVG artifacts include inline previews in metadata responses. Raw storage paths are never returned.
Skills
Skills are reusable instruction packages. See Skills for package format and upload rules.
| Method | Path | Purpose |
|---|---|---|
GET |
/v1/skills |
List skills. |
POST |
/v1/skills |
Upload a skill package. |
GET |
/v1/skills/{skill_id} |
Retrieve a skill. |
DELETE |
/v1/skills/{skill_id} |
Delete a custom skill. |
List query parameters:
| Parameter | Purpose |
|---|---|
limit |
Page size, maximum 100. |
page |
Cursor from next_page. |
source |
custom or anthropic. |
Upload:
zip -r code-review-assistant.zip code-review-assistant
curl -X POST http://127.0.0.1:3000/v1/skills \
-F "files=@code-review-assistant.zip"
Skill list responses include next_page in addition to the common page fields.
Environments
Environments describe where sessions run.
Environment names are human-readable labels and do not need to be unique. Use
the returned env_... id when creating sessions or updating an environment.
| Method | Path | Purpose |
|---|---|---|
GET |
/v1/environments |
List environments. |
POST |
/v1/environments |
Create an environment. |
GET |
/v1/environments/{environment_id} |
Retrieve an environment. |
PUT |
/v1/environments/{environment_id} |
Update an environment. |
POST |
/v1/environments/{environment_id}/archive |
Archive an environment. |
GET |
/v1/environments/{environment_id}/worker-keys |
List self-hosted worker keys without raw secrets. |
POST |
/v1/environments/{environment_id}/worker-keys |
Generate a worker key. The raw key is returned once. |
POST |
/v1/environments/{environment_id}/worker-keys/{key_id}/revoke |
Revoke a worker key. |
GET |
/v1/environments/{environment_id}/work-items |
Inspect recent self-hosted queue items and status counts. |
Create:
curl -X POST http://127.0.0.1:3000/v1/environments \
-H "Content-Type: application/json" \
-d '{
"name": "local-dev",
"description": "Local development environment",
"hosting_type": "local",
"sandbox_provider": "local",
"network": {
"type": "limited",
"allow_mcp_server_network_access": false,
"allow_package_manager_network_access": true,
"allowed_hosts": []
},
"packages": []
}'
Worker keys and work queues are advanced self-hosted controls. They are not needed for the default local runtime.
Generate a self-hosted worker key:
curl -X POST http://127.0.0.1:3000/v1/environments/ENV_ID/worker-keys \
-H "Content-Type: application/json" \
-d '{"name":"fde-laptop"}'
Responses include secret_key only on creation. Later list/detail responses
return key_prefix, status, timestamps, and metadata only.
Run a local worker:
export MANAGED_AGENTS_ENVIRONMENT_KEY='mawk_...'
managed-agents worker poll \
--environment-id ENV_ID \
--workdir /path/to/worker/root
Worker polling is scoped by the environment key when supplied. The worker can
execute exec, read, write, and list work items inside --workdir.
Credential Vaults
Credential vaults group secrets that sessions can attach by id.
Vault names are human-readable labels and do not need to be unique. Use the
returned vlt_... id when attaching a vault to a session.
| Method | Path | Purpose |
|---|---|---|
GET |
/v1/credential-vaults |
List vaults. |
POST |
/v1/credential-vaults |
Create a vault. |
GET |
/v1/credential-vaults/{vault_id} |
Retrieve a vault. |
POST |
/v1/credential-vaults/{vault_id}/archive |
Archive a vault. |
GET |
/v1/credential-vaults/{vault_id}/credentials |
List credentials. |
POST |
/v1/credential-vaults/{vault_id}/credentials |
Add a credential. |
POST |
/v1/credential-vaults/{vault_id}/credentials/{credential_id}/rotate |
Replace the encrypted secret value. |
POST |
/v1/credential-vaults/{vault_id}/credentials/{credential_id}/mark-used |
Mark a credential as used and append an audit event. |
GET |
/v1/credential-vaults/{vault_id}/credentials/{credential_id}/audit |
List credential audit events. |
POST |
/v1/credential-vaults/{vault_id}/credentials/{credential_id}/archive |
Archive a credential. |
DELETE |
/v1/credential-vaults/{vault_id}/credentials/{credential_id} |
Delete a credential. |
Credential auth_type values:
mcp_oauthbearer_tokenenvironment_variable
Add a credential:
curl -X POST http://127.0.0.1:3000/v1/credential-vaults/VAULT_ID/credentials \
-H "Content-Type: application/json" \
-d '{
"name": "github-token",
"auth_type": "environment_variable",
"variable_name": "GITHUB_TOKEN",
"value": "ghp_example",
"network": {
"type": "limited",
"allowed_hosts": ["api.github.com"]
},
"injection_locations": ["request_headers"]
}'
Secret values are encrypted at rest. Responses return value_hint, not the raw
secret.
Rotate a credential:
curl -X POST http://127.0.0.1:3000/v1/credential-vaults/VAULT_ID/credentials/CREDENTIAL_ID/rotate \
-H "Content-Type: application/json" \
-d '{
"value": "new-secret-value",
"actor": "operator",
"metadata": { "reason": "scheduled rotation" }
}'
Runtime code can use the internal resolveSessionCredentialInjections helper to
resolve scoped credentials for a session. The helper decrypts only inside the
runtime process, updates last_used_at, and appends a credential audit event.
Memory Stores
Memory stores persist named memory entries that can be mounted into sessions. Memory store names are human-readable labels and do not need to be unique.
| Method | Path | Purpose |
|---|---|---|
GET |
/v1/memory_stores |
List memory stores. |
POST |
/v1/memory_stores |
Create a memory store. |
GET |
/v1/memory_stores/{store_id} |
Retrieve a memory store. |
POST |
/v1/memory_stores/{store_id}/archive |
Archive a memory store. |
GET |
/v1/memory_stores/{store_id}/memories |
List memories. |
POST |
/v1/memory_stores/{store_id}/memories |
Add a memory. |
PUT |
/v1/memory_stores/{store_id}/memories/{memory_id} |
Update a memory. |
DELETE |
/v1/memory_stores/{store_id}/memories/{memory_id} |
Delete a memory. |
Create a memory:
curl -X POST http://127.0.0.1:3000/v1/memory_stores/STORE_ID/memories \
-H "Content-Type: application/json" \
-d '{
"path": "/notes/release",
"content": "Keep release notes concise."
}'
Memory paths must start with / and must not end with /.
Operations
Operations APIs persist local control-plane definitions for callbacks, scheduled runs, and run-quality checks. The current runtime stores these resources, exposes them through the API, and includes manual validation actions for webhook test delivery, scheduled run-now, and deterministic outcome evaluation. Automatic webhook dispatch and cron scheduling remain planned background workers.
Webhooks
| Method | Path | Purpose |
|---|---|---|
GET |
/v1/webhooks |
List webhook subscriptions. |
POST |
/v1/webhooks |
Create a webhook subscription. |
GET |
/v1/webhooks/{webhook_id} |
Retrieve a webhook subscription. |
PUT |
/v1/webhooks/{webhook_id} |
Update a webhook subscription. |
POST |
/v1/webhooks/{webhook_id}/archive |
Archive a webhook subscription. |
GET |
/v1/webhooks/{webhook_id}/deliveries |
List webhook delivery records. |
POST |
/v1/webhooks/{webhook_id}/test |
Record a signed test delivery without requiring an external network call. |
POST |
/v1/webhooks/dispatch |
Dispatch an event to matching active webhooks. |
POST |
/v1/webhooks/retry-due |
Retry failed deliveries whose retry time has arrived. |
curl -X POST http://127.0.0.1:3000/v1/webhooks \
-H "Content-Type: application/json" \
-d '{
"name": "Session events",
"url": "https://example.com/managed-agents/webhook",
"events": ["session.status_running", "session.status_terminated"]
}'
Delivery responses include a signature field using the sha256=... format.
Failed dispatches are stored as pending_retry until their next retry time or
as failed after the maximum attempts.
Scheduled Deployments
| Method | Path | Purpose |
|---|---|---|
GET |
/v1/scheduled-deployments |
List scheduled deployment plans. |
POST |
/v1/scheduled-deployments |
Create a scheduled deployment plan. |
GET |
/v1/scheduled-deployments/{schedule_id} |
Retrieve a scheduled deployment plan. |
PUT |
/v1/scheduled-deployments/{schedule_id} |
Update a scheduled deployment plan. |
POST |
/v1/scheduled-deployments/{schedule_id}/archive |
Archive a scheduled deployment plan. |
GET |
/v1/scheduled-deployments/{schedule_id}/runs |
List schedule run records. |
POST |
/v1/scheduled-deployments/{schedule_id}/run |
Manually trigger a schedule and create a session. |
POST |
/v1/scheduled-deployments/run-due |
Run all active schedules whose next_run_at is due. |
curl -X POST http://127.0.0.1:3000/v1/scheduled-deployments \
-H "Content-Type: application/json" \
-d '{
"name": "Morning smoke",
"agent_id": "agent_...",
"environment_id": "env_...",
"cron": "0 9 * * 1",
"payload": {
"title": "Daily FDE smoke"
}
}'
Manual and due runs create a session with schedule metadata and store a
scheduled_deployment_run record. The local cron runner computes next_run_at
in UTC for standard five-field cron expressions using *, comma lists, ranges,
and step values.
Outcomes
| Method | Path | Purpose |
|---|---|---|
GET |
/v1/outcomes |
List outcome definitions. |
POST |
/v1/outcomes |
Create an outcome definition. |
GET |
/v1/outcomes/{outcome_id} |
Retrieve an outcome definition. |
PUT |
/v1/outcomes/{outcome_id} |
Update an outcome definition. |
POST |
/v1/outcomes/{outcome_id}/archive |
Archive an outcome definition. |
GET |
/v1/sessions/{session_id}/outcomes |
List recorded session outcome evaluations. |
POST |
/v1/sessions/{session_id}/outcomes |
Record a session outcome evaluation. |
POST |
/v1/sessions/{session_id}/outcomes/evaluate |
Run the built-in deterministic transcript evaluator for an outcome. |
curl -X POST http://127.0.0.1:3000/v1/outcomes \
-H "Content-Type: application/json" \
-d '{
"name": "Release readiness",
"objective": "The agent should produce a concise release-readiness summary.",
"criteria": ["Mentions tests", "Mentions risks"]
}'
Outcome definitions accept pass_threshold from 0 to 1. The local
deterministic evaluator records passed when the transcript score meets the
threshold, inconclusive for partial matches below the threshold, and failed
when no criteria match.
curl -X POST http://127.0.0.1:3000/v1/sessions/SESSION_ID/outcomes \
-H "Content-Type: application/json" \
-d '{
"outcome_id": "out_...",
"status": "passed",
"score": 0.92,
"summary": "The run met release-readiness criteria."
}'
The built-in evaluator is deterministic and local: it compares outcome criteria
against persisted session event text, records a score, and stores the result in
session_outcomes.
curl -X POST http://127.0.0.1:3000/v1/sessions/SESSION_ID/outcomes/evaluate \
-H "Content-Type: application/json" \
-d '{
"outcome_id": "out_..."
}'
Runtime Extension Endpoints
Extension endpoints expose local runtime operations.
| Method | Path | Purpose |
|---|---|---|
GET |
/v1/x/health |
Health check. |
GET |
/v1/x/runtime |
Runtime status. |
GET |
/v1/x/capabilities |
Truthful inventory of locally executable built-in capabilities. |
GET |
/v1/x/workspace |
Workspace paths and metadata. |
GET |
/v1/x/settings |
Read the versioned Settings V2 runtime document. |
POST |
/v1/x/settings/validate |
Validate a complete Settings V2 document without saving. |
POST |
/v1/x/settings/test |
Test one settings area without saving. |
PUT |
/v1/x/settings |
Save a validated Settings V2 document. |
GET |
/v1/x/templates |
Built-in agent templates. |
POST |
/v1/x/reload |
Reload file-backed agents. |
POST |
/v1/x/restart |
Restart the local runtime process when the server was started through the CLI. |
GET |
/v1/x/logs?limit=200&level=info&q=term |
Recent in-process structured runtime logs. |
GET |
/v1/x/metrics |
Prometheus metrics, when enabled. |
GET |
/v1/x/metrics/summary |
JSON runtime summary for Dashboard monitoring and SDK helpers. |
GET |
/v1/x/mcp/status?session_id=... |
MCP connection status for a session. |
POST |
/v1/x/worker/claim |
Self-hosted sandbox worker claims pending tool-execution work. |
POST |
/v1/x/worker/complete |
Self-hosted sandbox worker reports completed or failed work. |
GET /v1/x/runtime returns runtime-safe introspection data. Model entries expose
configuration metadata only:
{
"type": "runtime",
"status": "running",
"models": [
{
"name": "local",
"provider": "openai",
"model": "gpt-4o",
"api_key_state": "configured",
"base_url_state": "not_set"
}
],
"auth_enabled": true
}
GET /v1/x/capabilities is the source of truth for built-in tool availability.
It returns stable capability records with a status and, when unavailable, a
human-readable reason:
{
"type": "capability_inventory",
"capabilities": [
{ "id": "read", "kind": "tool", "status": "available" },
{
"id": "web_fetch",
"kind": "tool",
"status": "unavailable",
"reason": "No safe executable implementation is available in this runtime."
}
]
}
Agent create/update and session creation reject enabled unavailable capabilities
with 400 unsupported_capability before an agent or session is persisted. In
particular, web_fetch and web_search cannot reach model or tool execution
until safe runtime implementations exist.
The runtime never returns raw API keys or resolved secret values to the Console.
Settings V2 is the source of truth for model vendor, loop engine, storage, memory, and sandbox configuration. Responses include both the saved document and the effective document currently used by the process. Response excerpt:
{
"schema_version": 1,
"revision": 2,
"effective_revision": 1,
"saved_config": {
"schema_version": 1,
"model": {
"vendor": "openai",
"base_url": "https://api.openai.com/v1",
"api_key": "********",
"options": {}
}
},
"effective_config": {},
"restart_required": true,
"activation_status": "pending",
"activation_errors": [],
"diagnostics": {
"metadata": {
"path": ".managed-agents/data.db",
"health": "ok"
}
},
"secret_states": {
"model": {
"api_key": "configured"
}
},
"adapters": {
"loop_engine": [
{
"id": "builtin",
"label": "Default",
"status": "available",
"restart_policy": "runtime",
"options_schema": {
"type": "object",
"properties": {
"default_max_steps": {
"type": "integer",
"minimum": 1,
"maximum": 1000,
"default": 25
}
},
"additionalProperties": true
}
}
]
}
}
Secret-looking adapter option keys, including api_key, access_key,
secret, token, password, and credential, are always masked in public
settings responses.
Adapter descriptors include backend-owned options_schema metadata for
adapter-specific options.
The Dashboard validates a changed candidate before enabling save, and API
clients should follow the same sequence: GET /v1/x/settings, edit the complete
document, POST /v1/x/settings/validate, optionally POST /v1/x/settings/test,
then PUT /v1/x/settings with the current revision. A successful save updates
saved_config and sets restart_required when the running process still uses
the older effective_config. The next CLI-managed restart promotes the last
valid saved revision to effective_config. If a saved row is corrupted outside
the API, startup keeps the last valid effective document instead of activating
the bad candidate and returns activation_status: "failed" with
activation_errors on subsequent settings reads until the saved document is
repaired.
Validate a candidate document:
curl -X POST http://127.0.0.1:3000/v1/x/settings/validate \
-H "Content-Type: application/json" \
-d @settings.json
Test one area without saving:
curl -X POST http://127.0.0.1:3000/v1/x/settings/test \
-H "Content-Type: application/json" \
-d '{
"area": "storage.artifacts",
"config": {
"provider": "local",
"options": {
"base_path": "files"
}
}
}'
Model tests apply the same credential validation used by validate and save.
Other area tests are scoped to their adapter so local storage, memory, and
sandbox diagnostics can run before a model API key has been configured.
Those scoped checks still validate credentials that belong to the tested area.
Docker sandbox checks currently skip live daemon/image validation. Remote
sandbox checks require the worker API URL and key, then call
/v1/x/health on that remote worker API.
Save the complete document with optimistic concurrency:
curl -X PUT http://127.0.0.1:3000/v1/x/settings \
-H "Content-Type: application/json" \
-d '{
"revision": 2,
"config": {
"schema_version": 1,
"model": {
"vendor": "openai",
"api_key": "${OPENAI_API_KEY}",
"options": {}
},
"loop_engine": {
"provider": "builtin",
"options": {
"default_max_steps": 25
}
},
"storage": {
"metadata": {
"provider": "sqlite",
"options": {}
},
"artifacts": {
"provider": "local",
"options": {
"base_path": "files"
}
}
},
"memory": {
"enabled": true,
"provider": "sqlite",
"options": {}
},
"sandbox": {
"provider": "local",
"options": {
"timeout_seconds": 300
}
}
}
}'
Literal secrets are encrypted at rest. API responses return masked placeholders
and secret_states; they never return plaintext or ciphertext.
Successful saves emit a runtime_settings_saved structured log with only the
old revision, new revision, changed JSON paths, and restart flag. Secret values
and internal managed-secret references are not logged.
GET /v1/x/logs returns a standard page envelope with the most recent log
entries captured by the current process. level is a minimum severity filter
(debug, info, warn, or error), and q searches the rendered log line.
The in-memory buffer is intended for local operations and is reset when the
runtime restarts.
POST /v1/x/restart schedules a local runtime restart and returns:
{
"restarting": true,
"status": "scheduled"
}
Embedded test servers or custom hosts that do not provide a restart hook return
501 unsupported. When available, restart stops accepting requests, drains the
session manager, closes SQLite, and starts a new process with the same command
line arguments.
Pi lifecycle status boundary
When loop_engine.provider is pi, the API may expose cancelled,
timed_out, or cleanup_pending rather than collapsing every child-process
outcome into failed or terminated. cleanup_pending is fail-closed: the
runtime has not proved that the process tree released the workspace, so it does
not clean up or accept a new turn. A live cross-runtime Pi session-file owner
returns a retryable pi_session_busy error. Resume refusal, corrupt headers,
path/schema mismatch, and missing SQLite continuity proof are visible errors;
they never silently start a second Pi history.
Pi-native tool events are trajectory records only. They do not carry Harness
requires_confirmation, do not run through the builtin ToolResolver, and do
not receive Harness local path confinement or an Allow/Deny card. Docker and
Kubernetes Pi transport, RPC, and a Pi-to-Harness approval bridge are not part
of this local demo.