Skip to main content

Ops API

The Kaizen application-administrator surface, mounted at /api/ops.

The gate​

Every ops route requires the validated platform identity envelope plus either the trusted Kamiwaza Platform Admin role or owner authority in the current workroom. Platform administrators retain the complete operator surface. Workroom owners receive the same Kaizen App Admin controls without gaining platform-wide inventory authority.

The backend checks this authority on every route. Frontend redirects are only convenience; removing one does not grant access. Ops actions use the WEB_ADMIN audit actor so configuration changes remain attributable.

Models​

GET /api/ops/models
PUT /api/ops/models/chat
PUT /api/ops/models/embedding
PUT /api/ops/models/reranker
GET /api/ops/setup

Roles, not names. Assigning the embedding role to a deployment that does not serve embeddings is the most common misconfiguration — see Models & embeddings.

GET /api/ops/setup returns one entry per surface it judges, each with a status and prose an operator can act on. The tasks entry is the one that usually needs explaining: Tasks can be switched on in this deployment and still be closed, because the platform has not issued the deployment's workload assertion or registered its workload roles. That entry says exactly that, and marks itself attention rather than complete — it is not a launch prerequisite, so a deployment without Tasks is still ready. Only the diagnostic's own name informs the copy; no platform URL, claim, or token appears in it.

The sandbox-egress entry is a projection of the effective outbound scope, not a copy of SANDBOX_EGRESS_MODE: it states the mode in force, the enforced ports, and the destination classes denied in every mode, and it reports isolation with the missing prerequisite whenever the configured mode cannot be enforced. Like the tasks entry it carries classes and switches only — never a configured host, range, registry, proxy address, or key.

Connectors​

Kamiwaza-brokered connectors, discovered at runtime:

GET /api/ops/kamiwaza-connectors
PUT /api/ops/kamiwaza-connectors/{connector_id}
POST /api/ops/kamiwaza-connectors/{connector_id}/rag-actions/{action_id}

Kaizen-managed connector configurations:

GET /api/ops/connectors
POST /api/ops/connectors | /connectors/adopt
GET /api/ops/connectors/{name}
PUT /api/ops/connectors/{name}
DELETE /api/ops/connectors/{name}
POST /api/ops/connectors/{name}/enable | /disable | /resync

Nothing here enumerates connector types. Discovery is dynamic; adding a static catalog would reintroduce release coupling.

Tools​

GET /api/ops/kamiwaza-tools
PUT /api/ops/kamiwaza-tools
PUT /api/ops/kamiwaza-tools/{tool_name}

Enabling a tool makes it available to be granted. It does not grant it. GET /api/ops/kamiwaza-tools returns the current hidden selection-setting version even though that internal selector is omitted from the general settings list. Send that value as expected_version on a PUT. A stale value returns 409 version_conflict; a successful write advances the version used by the next read.

The list combines authenticated Kamiwaza Core OpenAPI operations, MCP Guard tools, the closed direct-SDK adapters, and—when separately enabled—external schema sources. The response authors the complete root/source/surface hierarchy; the frontend does not infer families from display names. A bulk PUT may contain the returned root selector, source selector, surface selector, or exact tool name. Root and source selectors are hard ceilings and a true value only permits narrower selections; it does not grant descendants. A surface true value admits newly published operations under that same Core tag, SDK surface, MCP server, or external source automatically, while an exact false entry remains an exception. The Admin UI implements a parent switch as one CAS-protected bulk PUT with cascade: true and exactly one returned parent selector. The server resolves the authenticated subtree. Enabling clears stored endpoint exceptions inside that subtree and records its surface selectors, while disabling records the parent ceiling. This makes every effective child checkbox follow the parent without a request or stored policy proportional to the endpoint count. Calls without cascade keep the composable selector semantics for other clients. The SDK source selector is kamiwaza_source:sdk, and its child SDK surface preserves the closed adapters' prior default until explicitly disabled. Discovery and writes require the admin role, but the resulting operation still executes later as the initiating member and is authorized again by Kamiwaza.

The root selector is kamiwaza. Source families use stable returned selectors; the external source ceiling is external_schema. Each registered external API is a surface with an external_source:{uuid} selector, management has its own surface selector, and each endpoint has an exact ext_* name. A false ancestor is a hard ceiling over exact true entries. This policy controls tool availability but does not enable network access: the independent external-capability flag and sandbox-egress policy must also admit the request.

Packages​

GET /api/ops/packages
POST /api/ops/packages
GET /api/ops/packages/{id}
POST /api/ops/packages/{id}/upgrade | /disable
DELETE /api/ops/packages/{id}

Agents​

GET /api/ops/agents
GET /api/ops/agents/proposals
POST /api/ops/agents/proposals/agent/{id}/approve
POST /api/ops/agents/proposals/package/{id}/approve
POST /api/ops/agents/proposals/{kind}/{id}/reject
POST /api/ops/agents/{id}/enable | /disable | /rollback
GET|PUT /api/ops/agents/{id}/definition
GET /api/ops/agents/{id}/versions
GET /api/ops/agents/{id}/versions/{a}/diff/{b}

Note the asymmetry with the member surface: a member creates a private agent without approval, but publishing to all members is an ops action.

Settings and effective config​

GET /api/ops/settings
PUT /api/ops/settings/{key}
DELETE /api/ops/settings/{key}
GET /api/ops/effective-config
POST /api/ops/effective-config/diff

effective-config is the right way to answer "what is this deployment actually set to?" — reading environment variables off a running container misses config-store overrides.

Secret values are never disclosed by these endpoints. Configuration carrying a secret is declared with password metadata in the manifest and is redacted in responses. A setting response with nullable: true accepts JSON null as an explicit disabled override; deleting its override instead restores the environment or packaged default.

Metrics​

GET /api/ops/metrics
GET /api/ops/usage?days=7|30|90
GET /api/ops/usage/members?days=7|30|90

The response is a content-free six-hour command-center snapshot. It combines durable LLM, task, connector, and audit aggregates with process-local request and sandbox instruments. Every family carries full, partial, or unavailable coverage, and a missing producer returns value: null rather than a synthetic zero. The route accepts no member identifier or arbitrary query and requires Kaizen App Admin authority like every other ops route.

The top-level usage object carries deployment-wide model calls, input, output, and cache-read tokens plus at most five top_models rows ordered by call count. Each row includes the bounded model deployment name, call share, success ratio, and token totals. It never includes a member, agent, task, conversation, prompt, source, or model output. Model names on this JSON surface are display dimensions for administrators, not metric labels for Prometheus or OTLP.

The route is backed by a 30-second process-local single-flight cache. Refreshes use at most two concurrent read-only ledger queries with statement and lock timeouts plus a two-second end-to-end deadline, so multiple polling administrators cannot multiply database work. The task source restricts its scan to the six-hour window and currently live states; concurrent partial indexes support both paths without blocking ledger writes during deployment.

This JSON surface is for the Kaizen admin screen. Monitoring systems should scrape /metrics or enable the OTLP mirror instead of polling this route.

The separate /usage response is an aggregate-only product-operations view. Its activity denominator is a message or steering input, not authentication, presence, or background work. It returns UTC DAU/WAU/MAU, stickiness, new/returning counts, conversations, completion and first-value measures, D1/D7/D30 retention, daily activity, per-active-user token distributions, feature outcomes, and generation/embedding model mix. The only accepted range is a reviewed 7, 30, or 90 day preset.

The service groups by internal principals to calculate unique counts and token percentiles, but never serializes a principal or per-user row. Prompts, answers, conversations, tool arguments, emails, and model outputs are absent. System/background model calls are excluded from user-attributed consumption. The four source queries are read-only, deadline-bounded, and limited to two concurrent statements; each preset shares a 60-second single-flight cache.

The separate /usage/members response is the content-free per-member view. It returns at most 100 rows containing a display name, an opaque 12-character server-derived key, active days, conversations, inputs, completion ratio, and model calls plus input/output/cache-read token totals. It never returns the platform subject, requester id, email, prompt, answer, conversation id, source activity, or tool arguments. Email-shaped display values are replaced by the opaque fallback label.

This route has the same fail-closed Kaizen App Admin gate, but is kept separate from the anonymous aggregate contract so each disclosure can emit admin.usage.members.viewed. The audit payload contains only the selected window, returned member count, and availability. The browser does not poll the member endpoint continuously; the response has the same 60-second cache as the selected window.

A2A​

GET /api/ops/a2a
POST /api/ops/a2a/validate
PUT /api/ops/a2a/flags/{flag}
PUT /api/ops/a2a/public-base-url
PUT /api/ops/a2a/shared-secret
PUT /api/ops/a2a/inbound-agents

Run validate before relying on a configuration change. A2A is a proof of concept intended for isolated deployments.

GET /api/ops/a2a returns a versions map keyed by the settings A2A owns. Each entry is the config store's current version for that key, or null while the key still carries its deployment value. The mappings, public address, and capability secret are internal selectors omitted from the general settings list, and this map is the only read path for their versions. Send the value for the key you are writing as expected_version; a stale value returns 409 version_conflict, and a successful write advances the version the next status read reports.

What the ops surface is not​

It configures the deployment. It is not a window into member content — no ops route returns another member's chats, documents, or tasks.

Holding the admin role grants configuration authority, not read access. If a proposed ops endpoint would return member content, that is a design smell worth resolving before it ships.