Response Contract
Fields every successful LatentKit runtime response guarantees.
LatentKit normalizes successful runtime responses before returning them to your application. Log these fields on every production request.
{
"id": "req_abc123",
"provider": "anthropic",
"model": "claude-sonnet-4-6",
"policy_version_id": "pol_v_xyz789",
"content": "Done.",
"tool_calls": [],
"content_blocks": [{ "type": "text", "text": "Done." }],
"usage": {
"input_tokens": 1234,
"output_tokens": 567,
"total_tokens": 1801
},
"cost_usd": 0.0123,
"lk_requested_purpose": "extraction",
"lk_applied_purpose": "extraction",
"lk_purpose_source": "request",
"determinism": {
"seed_requested": null,
"seed_honored": false,
"provider_supports_seed": true
}
}Guaranteed fields
| Field | Description |
|---|---|
id | LatentKit request ID. Same value as request_id and the X-LK-Request-ID response header. |
provider | Upstream backend that answered, such as openai, anthropic, xai, mistral, or openrouter. |
model | Resolved provider model identifier used for this request. |
policy_version_id | Published routing policy version that handled the request. |
usage | Normalized token usage. input_tokens and output_tokens are always present; modality-specific fields (cached, image, reasoning tokens, audio seconds, audio characters, and video output units) may be zero or absent. |
cost_usd | Computed request cost in USD. BYOK and Platform Access may use different billing sources. |
determinism | Seed forwarding result — see Determinism. |
lk_requested_purpose | The purpose the request asked for, or null if it sent none. |
lk_applied_purpose | The purpose that actually ran, or null when the app's default route ran. |
lk_purpose_source | Why that route ran. One of request, default_no_purpose, purpose_unknown, purpose_no_capable_route. |
Responses also include latency metadata (total_ms, and first_token_ms for streaming-capable providers) useful for performance dashboards.
LatentKit also returns legacy top-level usage aliases such as input_tokens, output_tokens, and total_tokens for compatibility. New integrations should prefer usage.
Non-token billing units
Not every endpoint bills in tokens. Audio and video routes report zero tokens and
carry their own unit instead, so total_tokens: 0 next to a non-zero cost_usd
is expected rather than a missing value:
| Endpoint | Billing unit | usage field |
|---|---|---|
/v1/chat, /v1/complete, /v1/vision, /v1/embed | Tokens | input_tokens, output_tokens |
/v1/speech | Characters of input text | audio_output_characters |
/v1/transcription, /v1/translation | Seconds of submitted audio | audio_seconds |
/v1/video | Seconds, or generations | video_output_seconds, video_output_count |
Read cost_usd rather than deriving cost from token counts if your integration
handles more than one modality.
Compatibility for strict parsers. Purpose metadata is additive: existing requests
keep their prior routing behavior, but successful runtime responses include the three
lk_*_purpose fields and /v1/me includes purposes. Configure strict JSON decoders
to accept these fields before upgrading a pinned response schema.
Tool and content output
tool_calls is always normalized to OpenAI-style function calls when the model produces tool use. content_blocks contains provider-normalized output blocks when available. Plain text is still available as content.
Purpose routing
These three fields are present on every response, including cache hits, failover
responses, and streamed responses, whether or not the request sent a purpose.
lk_purpose_source | Meaning | What ran |
|---|---|---|
request | The requested purpose resolved | That purpose's route |
default_no_purpose | The request sent no purpose | The app's assigned route |
purpose_unknown | The purpose is not configured for this app, or is disabled | The app's assigned route |
purpose_no_capable_route | The bound route has no model that can serve this endpoint | The app's assigned route |
lk_applied_purpose is null in every case except request, so one comparison detects
a silent fallback:
response = client.chat.create(
messages=[{"role": "user", "content": document}],
purpose="extraction",
)
if response.get("lk_applied_purpose") != "extraction":
logger.warning("purpose degraded: %s", response.get("lk_purpose_source"))An unconfigured purpose is not an error — the request succeeds on the default route. Read
the labels your workspace configured from
/v1/me rather than hardcoding one. See
Purposes.
Debugging
When behavior changes, compare provider, model, policy_version_id, and
lk_applied_purpose across requests before changing application code. Routing, model
health, policy edits, and a retagged purpose can all affect output.