ultrarouter docs
API reference

Learning

Per-call-type learning controls — status, self-serve enable, pause / resume / disable, versions, evaluations, rollback and manual promote / reject.

Per-call-type learning controls — status, self-serve enable, pause / resume / disable, versions, evaluations, rollback and manual promote / reject.

This page is GENERATED from the OpenAPI spec (openapi.yaml) — it can never drift from the served API. Set UR_BASE_URL (required: your gateway’s URL) and UR_API_KEY (an ur_sk_* key); secrets are always the $UR_API_KEY placeholder.

Preview — not on the hosted service

The data flywheel and the learning loop run on the local stack only. They are off on the invite-only hosted gateway (the learning.enabled master switch), there is no hosted MCP endpoint, and whether learning improves a given agent is not yet demonstrated. See the evidence status.

Get the learning status of a call type

GET /v1/call-types/{id}/learning

The learner’s state (off, collecting, learning, paused, disabled, unavailable, quota_exhausted, budget_exhausted) and its reason; the reflection model and whether it resolves to a workspace-owned provider; the promotion policy; the ACTIVE version (the incumbent) and the latest candidate; the running evaluation; the evidence arrived vs verified vs incorporated vs backlog; whether the next reflection will run and why; the budget / quota state; and token usage separate from cash. Dual auth: an api key (config:read to read, config:write to change) or an owner/admin session with the X-UR-Workspace header; a viewer may read only. A call type of another workspace is a 404. Requires API-key scope: config:read or config:write.

Auth: API key (Authorization: Bearer ur_sk_…).

curl -sS -X GET "$UR_BASE_URL/v1/call-types/req_0000000000000000/learning" \
  -H "Authorization: Bearer $UR_API_KEY"

Enable learning for a call type (self-serve)

POST /v1/call-types/{id}/learning/enable

Turns learning on with a reflection model, a promotion policy and a recipe. Requires the workspace’s corrections and knowledge consent (409 conflict, message corrections_consent_required if either is missing). The owner grants both through the dashboard Allow learning opt-in or the session-authenticated PUT /v1/workspaces/{id}/self-learning with {"enabled":true}; a bearer key cannot grant workspace consent. Also requires a reflection model that resolves to a WORKSPACE-OWNED offer — a custom provider or a provider the workspace stored its own key for (400 invalid_request, message reflection_model_not_workspace_owned). No staff grant is needed. A published version is a candidate. In evaluate mode it receives a randomized share of eligible episodes during comparison; only a win makes it the active version. Re-enabling updates the policy; a running evaluation keeps its frozen rule. Owner/admin session or a config:write key. Dual auth: an api key (config:read to read, config:write to change) or an owner/admin session with the X-UR-Workspace header; a viewer may read only. A call type of another workspace is a 404. Requires API-key scope: config:write.

Auth: API key (Authorization: Bearer ur_sk_…).

curl -sS -X POST "$UR_BASE_URL/v1/call-types/req_0000000000000000/learning/enable" \
  -H "Authorization: Bearer $UR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "reflection_model": "string"
  }'

Pause learning

POST /v1/call-types/{id}/learning/pause

Stops reflecting and stops evaluation decisions; the ACTIVE version keeps serving and no evaluation arm is assigned while paused. Idempotent. 409 conflict (learning_not_enabled) for a call type that was never enabled through this API. Dual auth: an api key (config:read to read, config:write to change) or an owner/admin session with the X-UR-Workspace header; a viewer may read only. A call type of another workspace is a 404. Requires API-key scope: config:write.

Auth: API key (Authorization: Bearer ur_sk_…).

curl -sS -X POST "$UR_BASE_URL/v1/call-types/req_0000000000000000/learning/pause" \
  -H "Authorization: Bearer $UR_API_KEY"

Resume learning

POST /v1/call-types/{id}/learning/resume

Resumes reflection and evaluation decisions and resets the bounded-retry counters (a learner that stopped after repeated failures or quota refusals tries again). Idempotent. Dual auth: an api key (config:read to read, config:write to change) or an owner/admin session with the X-UR-Workspace header; a viewer may read only. A call type of another workspace is a 404. Requires API-key scope: config:write.

Auth: API key (Authorization: Bearer ur_sk_…).

curl -sS -X POST "$UR_BASE_URL/v1/call-types/req_0000000000000000/learning/resume" \
  -H "Authorization: Bearer $UR_API_KEY"

Disable learning (kill switch)

POST /v1/call-types/{id}/learning/disable

Stops serving lessons and stops reflecting within one 5 s config window (the episode-memory kill switch); a running evaluation stops (stopped_manual). Versions and history are kept; enabling again resumes from the active version. Idempotent. Dual auth: an api key (config:read to read, config:write to change) or an owner/admin session with the X-UR-Workspace header; a viewer may read only. A call type of another workspace is a 404. Requires API-key scope: config:write.

Auth: API key (Authorization: Bearer ur_sk_…).

curl -sS -X POST "$UR_BASE_URL/v1/call-types/req_0000000000000000/learning/disable" \
  -H "Authorization: Bearer $UR_API_KEY"

List learned versions with their states

GET /v1/call-types/{id}/learning/versions

The immutable versions, newest first, each with its state (candidate, evaluating, active, retired, rejected, superseded), why and since when. Dual auth: an api key (config:read to read, config:write to change) or an owner/admin session with the X-UR-Workspace header; a viewer may read only. A call type of another workspace is a 404. Requires API-key scope: config:read or config:write.

Auth: API key (Authorization: Bearer ur_sk_…).

curl -sS -X GET "$UR_BASE_URL/v1/call-types/req_0000000000000000/learning/versions" \
  -H "Authorization: Bearer $UR_API_KEY"

Get one learned version

GET /v1/call-types/{id}/learning/versions/{version_id}

The version’s active lessons, how many retired, the evidence it was learned from, the body-free reflection receipt (hashes and token counts) and every recorded state transition. Dual auth: an api key (config:read to read, config:write to change) or an owner/admin session with the X-UR-Workspace header; a viewer may read only. A call type of another workspace is a 404. Requires API-key scope: config:read or config:write.

Auth: API key (Authorization: Bearer ur_sk_…).

curl -sS -X GET "$UR_BASE_URL/v1/call-types/req_0000000000000000/learning/versions/{version_id}" \
  -H "Authorization: Bearer $UR_API_KEY"

Roll back to an earlier version

POST /v1/call-types/{id}/learning/rollback

Points the active version at an EARLIER immutable version (version_id, or the version active immediately before the current one) so it serves exactly that version’s lessons again. A running evaluation stops. 409 conflict (no_rollback_target / rollback_target_not_earlier) when there is nothing to roll back to. Dual auth: an api key (config:read to read, config:write to change) or an owner/admin session with the X-UR-Workspace header; a viewer may read only. A call type of another workspace is a 404. Requires API-key scope: config:write.

Auth: API key (Authorization: Bearer ur_sk_…).

curl -sS -X POST "$UR_BASE_URL/v1/call-types/req_0000000000000000/learning/rollback" \
  -H "Authorization: Bearer $UR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "version_id": "string"
  }'

Promote a version to active (manual decision)

POST /v1/call-types/{id}/learning/versions/{version_id}/promote

An owner/admin (or config:write key) decision: the version becomes the active version now; a running evaluation stops. 409 conflict (version_already_active) when it already is. Dual auth: an api key (config:read to read, config:write to change) or an owner/admin session with the X-UR-Workspace header; a viewer may read only. A call type of another workspace is a 404. Requires API-key scope: config:write.

Auth: API key (Authorization: Bearer ur_sk_…).

curl -sS -X POST "$UR_BASE_URL/v1/call-types/req_0000000000000000/learning/versions/{version_id}/promote" \
  -H "Authorization: Bearer $UR_API_KEY"

Reject a candidate (manual decision)

POST /v1/call-types/{id}/learning/versions/{version_id}/reject

An owner/admin (or config:write key) decision: the candidate is never activated by the system; its running evaluation stops. 409 conflict (version_active) for the active version — roll back instead. Idempotent. Dual auth: an api key (config:read to read, config:write to change) or an owner/admin session with the X-UR-Workspace header; a viewer may read only. A call type of another workspace is a 404. Requires API-key scope: config:write.

Auth: API key (Authorization: Bearer ur_sk_…).

curl -sS -X POST "$UR_BASE_URL/v1/call-types/req_0000000000000000/learning/versions/{version_id}/reject" \
  -H "Authorization: Bearer $UR_API_KEY"

List evaluations

GET /v1/call-types/{id}/learning/evaluations

Every evaluation, newest first: the frozen rule and its hash, each arm’s verified / pass / unknown episodes, the one-sided interval on the success difference, and the decision with its reason. Under lpr2, enrollment closes before outcomes are inspected; the frozen episodes remain selected while their outcomes are awaited. Missing outcomes cannot produce a promotion. Historical lpr1 results retain their original rule. Dual auth: an api key (config:read to read, config:write to change) or an owner/admin session with the X-UR-Workspace header; a viewer may read only. A call type of another workspace is a 404. Requires API-key scope: config:read or config:write.

Auth: API key (Authorization: Bearer ur_sk_…).

curl -sS -X GET "$UR_BASE_URL/v1/call-types/req_0000000000000000/learning/evaluations" \
  -H "Authorization: Bearer $UR_API_KEY"

Get the tool documentation the learner reads

GET /v1/call-types/{id}/learning/tool-documentation

The call type’s customer-supplied tool documentation as stored: per tool its name, schema fingerprint, parameter names and documented constants (never description prose), plus the set’s etd1_ digest. Empty (tool_count 0, digest null) when none is stored. Dual auth: an api key (config:read to read, config:write to change) or an owner/admin session with the X-UR-Workspace header; a viewer may read only. A call type of another workspace is a 404. Requires API-key scope: config:read or config:write.

Auth: API key (Authorization: Bearer ur_sk_…).

curl -sS -X GET "$UR_BASE_URL/v1/call-types/req_0000000000000000/learning/tool-documentation" \
  -H "Authorization: Bearer $UR_API_KEY"

Replace the tool documentation the learner reads

PUT /v1/call-types/{id}/learning/tool-documentation

For agents whose tools are not sent as native tools[] (a code-style api.<name>(…) protocol): up to 256 OpenAI-style function specs (unique names; body at most 1 MiB). Each is stored as a bounded summary — name, schema fingerprint, parameter names and the constants it documents (enum / const / default / a number or quoted token its description states); description prose is never stored. When learning admits a lesson (elv2), such a constant is admissible only in a lesson that names the documenting tool. Replaces any stored set; an empty tools list clears it; the same set again is a no-op (changed: false). Erased with the learning data when corrections consent is revoked. 400 invalid_request (tool_documentation_too_large, tool_documentation_invalid (<reason>)). Dual auth: an api key (config:read to read, config:write to change) or an owner/admin session with the X-UR-Workspace header; a viewer may read only. A call type of another workspace is a 404. Requires API-key scope: config:write.

Auth: API key (Authorization: Bearer ur_sk_…).

curl -sS -X PUT "$UR_BASE_URL/v1/call-types/req_0000000000000000/learning/tool-documentation" \
  -H "Authorization: Bearer $UR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "tools": [
      {
        "type": "function",
        "function": {
          "name": "string"
        }
      }
    ]
  }'