Skip to content

Inference ​

Read-only listing of the inference lifecycle log — one row per chat or embedding call processed by the gateway. Every row carries the model, adapter, status, token counts, latency, and a request / response excerpt; this is the operator surface that the 02 — Inspect inferences how-to and the bw infer ls CLI wrap.

The router lives at packages/observability/admin_routes.py. Pydantic models: InferenceLogEntry (list view) and InferenceLogDetail (detail view, includes excerpts).

Endpoints ​

MethodPathAuthSummary
GET/admin/inferenceBearerPaginated list with filters.
GET/admin/inference/{log_id}BearerFull InferenceLogDetail for one row.

GET /admin/inference ​

Query parameters (all optional):

ParamTypeNotes
limitint (1–500)Default 50.
offsetint (≥0)Default 0.
model_idstringExact match.
adapter_idstringExact match.
statusenumOne of succeeded, failed, cancelled, blocked.
sinceISO-8601Inclusive UTC lower bound on ts.
untilISO-8601Inclusive UTC upper bound on ts.

Filters compose with AND. Workspace is taken from the bearer principal. Rows are ordered by ts DESC.

Response shape:

json
{
  "entries": [
    {
      "id": "log_01HF…",
      "workspace_id": "default",
      "model_id": "llama3.2:3b",
      "adapter_id": null,
      "status": "succeeded",
      "prompt_tokens": 41,
      "completion_tokens": 22,
      "latency_ms": 412,
      "ts": "2026-05-01T12:00:00Z"
    }
  ],
  "total": 1,
  "limit": 50,
  "offset": 0
}

total is the unpaginated row count for the given filters.

bash
curl -H "Authorization: Bearer $BIGWAVE_ADMIN_TOKEN" \
  "http://localhost:8000/admin/inference?status=blocked&since=2026-04-01T00:00:00Z"

GET /admin/inference/{log_id} ​

Returns the same row as the list, plus the prompt/response excerpts captured at log time. Returns 404 when the row does not exist or belongs to a different workspace — cross-tenant lookups MUST NOT leak existence (the router enforces this directly).

bash
curl -H "Authorization: Bearer $BIGWAVE_ADMIN_TOKEN" \
  http://localhost:8000/admin/inference/log_01HF...

Operator notes ​

  • Workspace fence. Both routes resolve the workspace from the bearer principal; the {log_id} path segment alone never identifies a row. See workspace fence.
  • Status semantics. succeeded is the happy path; blocked rows are guardrail-rejected requests (see Guardrails policy) and carry zero token counts so they contribute nothing to /admin/cost. failed covers backend errors (engine OOM, upstream timeouts).
  • Cross-layer correlation. Audit rows (/admin/audit) carry an inference_log_id when the audited action followed a logged call, letting incident response pivot from "who did what" to "what model did". Schema added in migration 0016_cross_layer_correlation.
  • Excerpts. The detail view includes redacted request / response bodies; the list view does not. Excerpt size is bounded by BIGWAVE_INFERENCE_LOG_MAX_BYTES (see the configuration reference).
  • Shadow rows. When shadow mode is active, a parallel row with shadow_of = <primary_log_id> is emitted; both rows are visible here.
  • 503 causes. app.state.inference_log_repo is wired in lifespan; routes return 503 with "InferenceLogRepository not initialised" when missing.

Dual-licensed: MIT OR Apache-2.0