Agent API
Agent API (Responses)
POST /v1/responses — OpenAI Responses-compatible agent surface: client tools, stored conversations, previous_response_id chaining.
Endpoint
Section titled “Endpoint”POST /v1/responses Create a responseGET /v1/responses/{response_id} Retrieve a stored responseDELETE /v1/responses/{response_id} Delete a stored response; tear down its conversation if it was the last live responseAuthorization: Bearer mb_live_*The Agent API speaks the OpenAI Responses protocol — the recommended way to build agents on Mirobody. It does everything the Answers API does (grounded answers over the Subject’s real health data, server-side tools, reasoning), plus:
- Client function tools — inject your own tools; the model hands off via
function_calloutput items (Function calling). - Stored conversations —
storedefaults totrue; chain turns withprevious_response_idor bind a durable conversation withsession_id(State & memory). - Standard
response.*streaming events (Streaming).
Because it speaks that protocol, the openai-agents SDK needs only a base-URL change:
from agents import Agent, ModelSettings, Runner, set_default_openai_client, set_tracing_disabledfrom openai import AsyncOpenAI
set_default_openai_client(AsyncOpenAI( base_url="https://api.mirobody.ai/v1", api_key="mb_live_..."))set_tracing_disabled(True) # tracing would call api.openai.com
agent = Agent(name="Health assistant", model="mirobody-flash", model_settings=ModelSettings(extra_body={"user": "alice"}))print(Runner.run_sync(agent, "How is my fasting glucose trending?").final_output)All /v1 endpoints share one base URL — pick the cluster your account uses:
https://api.mirobody.ai/v1 # Globalhttps://api.mirobody.cn/v1 # ChinaThese are the Cloud clusters. A self-hosted deployment does not expose /v1 — it serves its own /api/* routes and an /mcp endpoint, described in the Self-Host Mirobody.
Japan and EU clusters are in preparation — see Regions. Model providers and pricing can differ by region, so read GET /v1/models from the cluster you call.
Create a response
Section titled “Create a response”curl https://api.mirobody.ai/v1/responses \ -H "Authorization: Bearer $MIROBODY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "mirobody-flash", "input": "How is my fasting glucose trending?", "user": "alice" }'from openai import OpenAI
client = OpenAI(api_key="mb_live_...", base_url="https://api.mirobody.ai/v1")
resp = client.responses.create( model="mirobody-flash", input="How is my fasting glucose trending?", user="alice",)print(resp.output_text)Request body
Section titled “Request body”| Field | Type | Description |
|---|---|---|
model | string | mirobody-flash (default) or mirobody-expert. See Models. |
input | string | array | Required. A string (one user turn) or an array of items: message items ({role, content}), and — when continuing a tool handoff — function_call / function_call_output items. See Function calling. |
instructions | string | System-level instruction for this turn (prepended as a system message). |
stream | bool | true → SSE of standard response.* events. See Streaming. |
store | bool | Default true. Persist the response + conversation: 30-day TTL, or permanent when bound to a session_id. Enables previous_response_id and GET /v1/responses/{id}. |
previous_response_id | string | Continue the conversation of a stored response (server-side state — no need to resend history). 404 if the id is unknown, expired, or deleted. |
session_id | string | Mirobody extension. Binds this and future turns to a durable named conversation (never auto-expires). Generate a globally unique opaque id (for example a UUID) and never reuse it across Subjects. |
tools | array | Client function tools ({"type": "function", "name", "description", "parameters"}; the completions-nested form is also accepted) and/or remote MCP servers ({"type": "mcp", "server_label", "server_url", …} — executed server-side). Max 64; names must match [a-zA-Z0-9_-]{1,64} and may not shadow built-in tool names. See Function calling · MCP servers. |
tool_choice | string | object | "auto" (default) / "none" / "required" / a named client tool. "required" and named guarantees apply in backbone mode; the full contract (incl. the 400 cases) is there. |
mode | string | "agent" (default, full server-side agent) or "model" (backbone mode — bare inference, no server tools/state). |
builtin_tools | string | array | "auto" (default) / "none" / an allowlist of built-in tool names. Trims the server-side domain tools — see backbone mode. |
text.format | object | Structured output (json_object / json_schema). Backbone mode only — agent mode returns 400. See Structured output. |
strict | bool | When true (or header X-Mirobody-Strict: 1), an unknown top-level parameter is rejected with 400 unsupported_parameter instead of being ignored. See Strict validation. |
user | string | Tenant-isolation key → a Subject. |
Response object
Section titled “Response object”{ "id": "resp_147e9b14c172429a8b19da4be9489243", "object": "response", "created_at": 1783741077, "status": "completed", "model": "mirobody-flash", "output": [ { "type": "reasoning", "id": "rs_0", "status": "completed", "summary": [{ "type": "summary_text", "text": "..." }] }, { "type": "message", "id": "msg_0", "status": "completed", "role": "assistant", "content": [{ "type": "output_text", "text": "Your fasting glucose has trended down ..." }] } ], "output_text": "Your fasting glucose has trended down ...", "usage": { "input_tokens": 9, // YOUR visible input only "output_tokens": 5, "total_tokens": 14, "input_tokens_details": { "system_tokens": 10096, "cached_tokens": 0 }, "output_tokens_details": { "reasoning_tokens": 0 }, "billed_tokens": { "input": 20391, "output": 841, "total": 21232 } // the actual token total you're metered on }, "tool_steps": [], // Mirobody extension: server tool trace "health_records": [], // Mirobody extension: {tool, data} evidence "citations": [], // Mirobody extension: literature evidence "previous_response_id": null, "store": true, "tools": [], "error": null, "metadata": {}}The output array contains only standard OpenAI item types — reasoning, message, and (on a client-tool handoff) function_call. Official SDKs parse it as-is.
Server-side built-in tool runs are deliberately not output items. The trace rides in the top-level tool_steps extension field ({id, name, arguments, result} — the same shape as the Answers API), which SDKs safely ignore. In streaming it surfaces as the side-channel event response.mirobody_tool_call. health_records and citations carry the evidence the answer used, exactly as on the Answers API.
Usage accounting
Section titled “Usage accounting”usage.input_tokens reports the input you actually sent; the platform’s system prompt / tool-schema overhead is broken out as input_tokens_details.system_tokens. output_tokens_details.reasoning_tokens reports provider reasoning tokens. Counts are summed across every model call of the agent turn.
usage.billed_tokens ({input, output, total}) is what you’re metered on — present on both the Agent API and the Answers API. Applying the catalog’s standard input/output rates gives an estimate; prompt-cache discounts can make actual metered cost lower.
Retrieve a stored response
Section titled “Retrieve a stored response”curl https://api.mirobody.ai/v1/responses/resp_147e9b14... \ -H "Authorization: Bearer $MIROBODY_API_KEY"Returns the stored response object. Only store=true responses are retrievable; expired (30-day TTL) or deleted responses return 404.
Delete a stored response
Section titled “Delete a stored response”curl -X DELETE https://api.mirobody.ai/v1/responses/resp_147e9b14... \ -H "Authorization: Bearer $MIROBODY_API_KEY"{ "id": "resp_147e9b14...", "object": "response.deleted", "deleted": true }If it was the last live response of its conversation, the whole conversation is torn down too — its history and any conversation-derived memory. That makes this the self-service right-to-be-forgotten lever for stored conversations.
State model
Section titled “State model”store and retention are orthogonal — one governs the conversation, the other governs the data plane:
| Knob | Applies to | Values | Governs |
|---|---|---|---|
store | POST /v1/responses | true (default) / false | Whether the response object + conversation thread persist: store=true keeps them 30 days (or permanently when bound to a session_id), enabling previous_response_id chaining and GET /v1/responses/{id}. store=false keeps nothing after the reply. |
retention | POST /v1/data, POST /v1/files, POST /v1/standardize (store=true) | permanent (alias persistent) / 1d / 6h / 2h / 1h / session | How long the health records / files you write live in the Subject’s store. Time grains auto-delete (hard-capped ≤ 24h); session binds records to a session_id and DELETE /v1/sessions/{id} purges them. |
retention governs explicit data-plane writes; it does not govern a stored conversation. A stored conversation can also produce health records and memories from its content — delete those with DELETE /v1/data, or erase the Subject. store=false conversations produce none.
Full details — TTLs, chaining semantics, stateless replay, and the cross-session memory that store=true feeds — in State & memory.
Strict validation
Section titled “Strict validation”By default the surface is lenient (compatibility-first) — an unknown top-level parameter is ignored. Set strict: true in the body or send the header X-Mirobody-Strict: 1 to make it a hard 400 unsupported_parameter instead, with param pointing at the first offending key. Both surfaces (/v1/responses and /v1/chat/completions) honor it. Turn it on while integrating to catch typos and misplaced fields early.
curl https://api.mirobody.ai/v1/responses \ -H "Authorization: Bearer $MIROBODY_API_KEY" \ -H "Content-Type: application/json" \ -H "X-Mirobody-Strict: 1" \ -d '{"model":"mirobody-flash","input":"hi","bogus_param":1,"user":"alice"}'# → 400 {"error":{"code":"unsupported_parameter","param":"bogus_param", ...}}Errors
Section titled “Errors”Standard error envelope. Surface-specific cases:
| HTTP | When |
|---|---|
400 | Missing/empty input; invalid tools (bad name, reserved name, duplicate, > 64, unsupported type, unreachable MCP server); unsupported tool_choice (see the contract); text.format on agent mode; mode:"model" with previous_response_id/session_id/MCP tools; unknown builtin_tools name; unknown top-level param under strict; malformed handoff continuation (see Function calling) |
404 | Unknown / expired / deleted previous_response_id or response_id |
429 | rate_limit_exceeded (per-key rate limit) or insufficient_quota (monthly account cap) — see Rate Limits & Quota |
502 | Upstream agent error — transient; retry with backoff. In backbone mode provider errors are classified (400 / 429 / 502) rather than a blanket 502. |
See also
Section titled “See also”- Function Calling — declaring client tools and continuing after a handoff.
- State & Memory —
store, session state and cross-session memory. - Streaming — the
response.*event sequence. - Backbone Mode — turning this endpoint into a bare inference backend.