API Endpoints
此内容尚不支持你的语言。
Every endpoint requires the x-api-key: <api_key> header unless noted. JSON request and response bodies. Errors follow the shape in REST API → Errors.
Agents
Section titled “Agents”GET /v1/agents
Section titled “GET /v1/agents”List all agents in the tenant. Query params: archived (bool), limit, cursor.
POST /v1/agents
Section titled “POST /v1/agents”Create an agent. Body: AgentConfig minus the platform-assigned fields (id, version, timestamps).
GET /v1/agents/:id
Section titled “GET /v1/agents/:id”Get a single agent’s current version.
GET /v1/agents/:id/versions
Section titled “GET /v1/agents/:id/versions”List all versions of an agent.
GET /v1/agents/:id/versions/:version
Section titled “GET /v1/agents/:id/versions/:version”Get a specific historical version.
PATCH /v1/agents/:id
Section titled “PATCH /v1/agents/:id”Update an agent. Bumps version. Body: partial AgentConfig.
DELETE /v1/agents/:id
Section titled “DELETE /v1/agents/:id”Archive an agent (soft delete; sessions retain pinned version).
Sessions
Section titled “Sessions”POST /v1/sessions
Section titled “POST /v1/sessions”Create a session. Returns SessionMeta.
{ "agent": "agent_...", "environment_id": "env_...", "title": "optional"}Post the first user turn afterwards via POST /v1/sessions/:id/messages (one-shot, streams reply) or POST /v1/sessions/:id/events (fire-and-forget; pair with a separate SSE consumer).
Session budgets
Section titled “Session budgets”A session may carry the official budget {"budget": {"type": "limit", "max_list_cost": {"amount": "500", "currency": "USD"}}} (amount in whole USD cents, as an integer string).
- Active only when both are configured: the session has
max_list_costand its model card haspricing(see Model Cards). If either is missing the budget is inactive — nobudget_reached, no error — and the session’susage.list_costis absent (Console shows “unpriced”). list_cost= Σ per model request (input_tokens × input_per_mtok + output_tokens × output_per_mtok + cache_read_input_tokens × cache_read_per_mtok + cache_creation_input_tokens × cache_write_per_mtok) / 1M, rounded to the cent.- The gate runs before every model request; the request that crosses the cap completes. At the cap the session emits
session.thread_status_idle→session.usage→session.status_idle, each withstop_reason: {"type": "budget_reached"}(requires_actionoutranks it). - While paused, only settle events are accepted (
user.tool_confirmation,user.tool_result,user.custom_tool_result,user.interrupt);user.messagereturns 400. An interrupt is accepted and ignored. PATCH /v1/sessions/:idwithbudget: the budget is create-only (adding one to a session without a budget → 400); a newmax_list_costmust be greater than the exact consumed list cost (else 400budget.max_list_cost must be greater than the session's consumed list cost);budget: nullremoves it (one-way). Every budget change emitssession.updated; one that lifts abudget_reachedpause resumes the work automatically.- Upstream provider 429/quota errors are not budgets: they surface as
session.error/retries_exhausted.
GET /v1/sessions
Section titled “GET /v1/sessions”List sessions. Query: agent_id, status, limit, cursor.
GET /v1/sessions/:id
Section titled “GET /v1/sessions/:id”Get session metadata + status.
GET /v1/sessions/:id/events
Section titled “GET /v1/sessions/:id/events”JSON-paginated event log. Query: limit (1–1000, default 100), order (asc|desc), after_seq. Returns { data: SessionEvent[], has_more, next_page }.
Pass Accept: text/event-stream to switch to the SSE variant (or call /v1/sessions/:id/events/stream directly). Default behavior is Anthropic-spec-aligned: no history replay, only the spec event union (third-party @anthropic-ai/sdk parses cleanly). Two opt-ins:
?include=chunks— admit OMA extension events (token chunks, lifecycle,system.user_message_*,session.warning, extra spans likeaux.model_call)?replay=1(orLast-Event-ID: <seq>header) — replay persisted history before tailing
See REST API → Stream session events for the full event tables.
GET /v1/sessions/:id/log
Section titled “GET /v1/sessions/:id/log”Full event log as a JSON array (non-streaming).
GET /v1/sessions/:id/outputs
Section titled “GET /v1/sessions/:id/outputs”OpenMA extension that lists durable files deliberately written beneath
/mnt/session/outputs. Returns { data, has_more: false }. It is available
on the Node entrypoint and on Cloudflare when FILES_BUCKET is configured.
This is not currently a generated @anthropic-ai/sdk method, so call it with
ordinary HTTP and include anthropic-beta: managed-agents-2026-04-01.
GET /v1/sessions/:id/outputs/:filename
Section titled “GET /v1/sessions/:id/outputs/:filename”Streams one durable output. Filenames are a single path segment; parent or nested traversal is rejected. The Session is resolved in the authenticated workspace before the backing filesystem or object store is read.
POST /v1/sessions/:id/messages
Section titled “POST /v1/sessions/:id/messages”Chatbot one-shot: post a user turn AND stream the response in one HTTP call. Body: { "content": string | ContentBlock[] }. Returns text/event-stream and auto-closes when the turn finishes (session.status_idle). For the fire-and-forget variant (when you already have a separate SSE consumer open), POST to /v1/sessions/:id/events instead with the user.message wrapped in {events:[...]} — returns 202.
POST /v1/sessions/:id/cancel
Section titled “POST /v1/sessions/:id/cancel”Cancel a running session.
DELETE /v1/sessions/:id
Section titled “DELETE /v1/sessions/:id”Soft-delete a session.
Environments
Section titled “Environments”GET /v1/environments
Section titled “GET /v1/environments”List environment templates.
POST /v1/environments
Section titled “POST /v1/environments”Create an environment. Body: EnvironmentConfig.
GET /v1/environments/:id
Section titled “GET /v1/environments/:id”Get one.
PATCH /v1/environments/:id
Section titled “PATCH /v1/environments/:id”Update.
DELETE /v1/environments/:id
Section titled “DELETE /v1/environments/:id”Delete (only if no agents reference it).
Skills
Section titled “Skills”GET /v1/skills
Section titled “GET /v1/skills”List custom + built-in skills.
POST /v1/skills
Section titled “POST /v1/skills”Upload a custom skill. multipart/form-data with id, display_title, description, and one or more files.
GET /v1/skills/:id
Section titled “GET /v1/skills/:id”Get metadata.
GET /v1/skills/:id/files/:filename
Section titled “GET /v1/skills/:id/files/:filename”Download a skill file.
DELETE /v1/skills/:id
Section titled “DELETE /v1/skills/:id”Delete (built-in skills can’t be deleted).
Vaults
Section titled “Vaults”GET /v1/vaults
Section titled “GET /v1/vaults”List. Returned objects never include the secret material.
POST /v1/vaults
Section titled “POST /v1/vaults”Create. Body includes the secret; subsequent reads will not.
PATCH /v1/vaults/:id
Section titled “PATCH /v1/vaults/:id”Update — including rotating the secret.
DELETE /v1/vaults/:id
Section titled “DELETE /v1/vaults/:id”Delete.
cap_cli credentials (OpenMA extension)
Section titled “cap_cli credentials (OpenMA extension)”POST /v1/vaults/:id/credentials also accepts auth.type: "cap_cli". This is an OpenMA extension, not part of the Anthropic Managed Agents API, so the Anthropic SDK does not type it.
{ "display_name": "GitHub CLI", "auth": { "type": "cap_cli", "cli_id": "gh", "token": "gho_...", "refresh_token": "ghr_...", "expires_at": "2026-09-01T00:00:00Z" }}cli_id must name a builtin CLI spec (gh, glab, aws, gcloud, kubectl, …); anything else is a 400. refresh_token, expires_at and extras are optional. token, refresh_token and extras are write-only: responses carry only type, cli_id and expires_at. cli_id cannot change on update. mcp_oauth_validate refuses cap_cli credentials with a 400.
In a session, the egress proxy injects the newest active cap_cli credential for the CLI whose spec claims the request host, and refreshes it on 401 when the spec has a device flow and a refresh_token is stored. The sandbox only gets the spec’s placeholder environment (for example GITHUB_TOKEN=__cap_managed__), never the token. Injection needs a credential egress proxy. Self-hosted Node does not have one yet: Node managed sessions do not inject cap_cli credentials, or MCP credentials into direct sandbox traffic, until the sandbox layer implements CredentialEgressPort. There, cap_cli credentials are stored but not injected; mcp_oauth and static_bearer credentials still reach MCP servers through the Node MCP proxy.
POST /v1/oma/vaults/:id/cap_cli_device_flow (OpenMA extension)
Section titled “POST /v1/oma/vaults/:id/cap_cli_device_flow (OpenMA extension)”Starts an OAuth device authorization (RFC 8628) for a CLI with { "cli_id": "gh" }. The response has user_code, verification_uri, interval_seconds, expires_at and an opaque flow_token.
POST /v1/oma/vaults/:id/cap_cli_device_flow/poll (OpenMA extension)
Section titled “POST /v1/oma/vaults/:id/cap_cli_device_flow/poll (OpenMA extension)”Polls with { "flow_token": "..." }. status is pending, slow_down (with a new interval_seconds and flow_token to use from then on), expired, denied, error, or ready with the credential_id of the new cap_cli credential. On ready, older active cap_cli credentials for the same CLI in that vault are archived.
Memory Stores
Section titled “Memory Stores”GET /v1/memory_stores
Section titled “GET /v1/memory_stores”List per agent.
POST /v1/memory_stores
Section titled “POST /v1/memory_stores”Create.
GET /v1/memory_stores/:id/entries
Section titled “GET /v1/memory_stores/:id/entries”List recent entries.
POST /v1/memory_stores/:id/search
Section titled “POST /v1/memory_stores/:id/search”Semantic search. Body: { "query": "...", "limit": 10 }.
DELETE /v1/memory_stores/:id
Section titled “DELETE /v1/memory_stores/:id”Delete the store and its index.
POST /v1/files
Section titled “POST /v1/files”Upload. multipart/form-data with session_id and file.
GET /v1/files/:id
Section titled “GET /v1/files/:id”Download.
DELETE /v1/files/:id
Section titled “DELETE /v1/files/:id”Delete.
Model Cards
Section titled “Model Cards”Model cards may carry list pricing (USD per 1M tokens, decimal strings with ≤6 decimals) used to compute a session’s list_cost:
{ "pricing": { "version": 1, "currency": "USD", "effective_at": "2026-11-01T00:00:00Z", "input_per_mtok": "3", "output_per_mtok": "15", "cache_read_per_mtok": "0.30", "cache_write_per_mtok": "3.75" }}input_per_mtok and output_per_mtok are required; cache prices default to the input price. pricing: null on update clears it. Pricing has no budget — budgets live on sessions, and are enforced only when the card is priced.
Model Cards are the tenant-scoped executable model registry. A card binds a
stable handle (model_id) to a Pi provider, its wire-level model id, endpoint,
metadata, and encrypted credential. Keys are AES-256-GCM-encrypted at rest
under PLATFORM_ROOT_SECRET; list/retrieve responses surface only the preview.
The two model catalogs
Section titled “The two model catalogs”| Endpoint | Shape and purpose |
|---|---|
GET /v1/models / GET /v1/models/:id | Official Managed Agents Model resources. Lists active Model Cards the tenant can execute. Display name, token limits, image/thinking/effort and strict-output capabilities are conservatively projected from Pi metadata. Provider credentials never appear. |
POST /v1/oma/models/list | OMA setup helper. Body { "provider": "deepseek" } returns Pi’s built-in catalog for that provider. The SDK-first path does not send provider credentials. Optional api_key is a deprecated 0.x compatibility path for Anthropic/OpenAI live discovery. |
An unknown custom provider has no discoverable catalog. Create its Model Card
directly with base_url and pi_config.api.
GET /v1/oma/model_cards
Section titled “GET /v1/oma/model_cards”List configured model cards.
POST /v1/oma/model_cards
Section titled “POST /v1/oma/model_cards”Add a model card. Runs a 6-second capability probe so a bad key fails loudly. Body:
{ "model_id": "deepseek-fast", "provider": "deepseek", "model": "deepseek-v4-flash", "custom_headers": { "x-extra": "..." }, "api_key": "sk-...", "pi_config": { "reasoning": true }}provider is an open Pi provider id, not an OpenMA enum. Pi built-ins include
anthropic, openai, deepseek, openrouter, google, minimax, and more.
Legacy aliases ant, oai, ant-compatible, and oai-compatible remain
accepted. model_id is the handle used in the official Agent model:
{ "model": { "id": "deepseek-fast", "effort": { "type": "high" }, "speed": "standard", "inference_geo": "us" }}These controls belong to the Agent version, not the Model Card. A Session pins an Agent version and inherits them:
| Field | Runtime mapping |
|---|---|
effort | Pi thinkingLevel. Pi normalizes a requested level to the nearest level the resolved model supports. |
speed: "standard" | Leaves Pi/provider defaults unchanged. |
speed: "fast" | Anthropic fast mode (speed: fast plus its beta header), or OpenAI priority service tier. Other Pi APIs return an explicit unsupported error. |
inference_geo | Validated, stored, versioned, and returned; currently ignored by runtime routing. |
pi_config accepts Pi’s serializable Model metadata (name, api,
reasoning, thinkingLevelMap, input, cost, contextWindow, maxTokens,
samplingParams, headers, and compat). It cannot override card identity,
provider, wire model, endpoint, or credential. Custom providers must specify
pi_config.api so Pi can select a protocol implementation.
Create returns a probe result. The current bounded live probe covers the
legacy Anthropic/OpenAI protocols. {"ok":null,"reason":"unsupported_provider"}
means the probe was skipped; it is not a Pi runtime rejection.
POST /v1/oma/model_cards/:id
Section titled “POST /v1/oma/model_cards/:id”Rotate the api_key, base_url, headers, or default model. Body shape matches POST. In-flight sessions keep the cached key until next credential resolve.
DELETE /v1/oma/model_cards/:id
Section titled “DELETE /v1/oma/model_cards/:id”Delete.
GET /v1/oma/model_cards/:id/key (internal — agent worker only)
Section titled “GET /v1/oma/model_cards/:id/key (internal — agent worker only)”Returns cleartext credentials for the agent worker. Not exposed publicly.
Integrations
Section titled “Integrations”GET /v1/oma/integrations
Section titled “GET /v1/oma/integrations”List shipped + active integrations.
GET /v1/oma/integrations/:id/install
Section titled “GET /v1/oma/integrations/:id/install”Start the OAuth flow for the integration. Returns a redirect URL.
POST /v1/oma/integrations/:id/uninstall
Section titled “POST /v1/oma/integrations/:id/uninstall”Revoke the install.
GET /v1/oma/integrations/:id/publications
Section titled “GET /v1/oma/integrations/:id/publications”List publications (which agents serve which workspaces).
POST /v1/oma/integrations/:id/publications
Section titled “POST /v1/oma/integrations/:id/publications”Create a publication.
DELETE /v1/oma/integrations/:id/publications/:pub_id
Section titled “DELETE /v1/oma/integrations/:id/publications/:pub_id”Delete a publication.
GET /v1/oma/evals
Section titled “GET /v1/oma/evals”List eval runs.
POST /v1/oma/evals
Section titled “POST /v1/oma/evals”Start an eval.
GET /v1/oma/evals/:id
Section titled “GET /v1/oma/evals/:id”Get an eval’s results.
API Keys
Section titled “API Keys”GET /v1/oma/api_keys
Section titled “GET /v1/oma/api_keys”List your keys (the actual key value is not returned).
POST /v1/oma/api_keys
Section titled “POST /v1/oma/api_keys”Create. Body: { "name": "..." }. Returns the key once — store it now.
DELETE /v1/oma/api_keys/:id
Section titled “DELETE /v1/oma/api_keys/:id”Revoke.
MCP OAuth (OpenMA extension, Console use)
Section titled “MCP OAuth (OpenMA extension, Console use)”POST /v1/oma/oauth/authorize
Section titled “POST /v1/oma/oauth/authorize”Starts browser OAuth 2.1 (Authorization Code + PKCE) for an MCP server. JSON body: mcp_server_url and vault_id (required); credential_id (re-authorize an mcp_oauth credential for the same MCP server), redirect_uri (where the browser returns), client_id / client_secret (pin an OAuth client). Returns { "authorization_url": "..." }; open a blank popup during the click, then navigate it to that URL after the POST completes. Secrets must not be sent in query parameters. redirect_uri must use this service’s origin or an origin configured in the comma-separated CONSOLE_ORIGINS setting (same on Cloudflare and Node). The authorization server is discovered from the MCP server’s metadata (RFC 9728, RFC 8414). The client comes from dynamic registration or, for providers that do not support it, from <PROVIDER>_OAUTH_CLIENT_ID / _SECRET (GITHUB, FEISHU, LARK, ASANA, CLICKUP, SLACK); without one the answer is 501 with setup instructions. The in-flight flow travels sealed in the OAuth state (10 minutes), bound to the workspace and authenticated user.
GET /v1/oma/oauth/callback
Section titled “GET /v1/oma/oauth/callback”Exchanges the code and stores a managed mcp_oauth credential in the vault, with refresh metadata when the provider issued a refresh token. Older active mcp_oauth credentials for the same MCP server in that vault, and the re-authorized one, are archived. Archival failures return an error instead of reporting success. The popup page notifies only the validated Console origin (postMessage, plus BroadcastChannel("openma-oauth") when same-origin) and closes, or navigates back when no notification transport is available. Error responses contain fixed reasons rather than upstream bodies or internal URLs. The MCP and egress proxies refresh the credential on 401.
CLI MCP OAuth
Section titled “CLI MCP OAuth”oma connect <server|url> --vault <id> uses POST /v1/oma/oauth/cli/authorize with the same required JSON fields, without redirect_uri. The response includes authorization_url, flow_id, claim_token, expires_at and interval_seconds. Only open authorization_url in the browser; never include the API key, client secret or claim token in a URL. The provider still redirects to the service’s registered /v1/oma/oauth/callback, so existing preset clients do not need loopback redirect registration.
Poll POST /v1/oma/oauth/cli/result with { "flow_id": "...", "claim_token": "..." } and the original x-api-key. Results are pending, failed, or ready with only credential_id, never access/refresh tokens. Flows expire after 10 minutes and terminal results are consumed once. Claims are bound to the workspace, initiating user (when the key has one), original API key hash and independent claim secret. The browser does not need a Console cookie: only the sealed CLI discriminator plus the matching pending flow can complete the public callback; Console states continue to require their original authenticated user and allowed origin.
Health
Section titled “Health”GET /healthz
Section titled “GET /healthz”Returns {"ok": true}. Unauthenticated.