Tenzro
AI

Streaming.

SSE for chat token streams and Anthropic-style rich-shape events. WebSocket subscriptions for inference channels.
STATUS
Testnet
CRATE
tenzro-node
STABILITY
Stable
TYPE
Component
01

HTTP

GET  /v1/models                  model listing with pricing, context, features
GET  /v1/models/{id}             one model by instance ID or model ID
POST /chat                       OpenAI-compatible chat completions
POST /chat-stream                Anthropic-style SSE rich-shape
POST /v1/chat/completions        OpenAI streaming SSE
POST /v1/responses               Responses typed events, no [DONE] sentinel
POST /v1/embeddings              one body, no stream
POST /v1/audio/transcriptions    one body, no stream
POST /v1/images/generations      one body after a bounded wait, no stream
GET  /v1/generation              recorded stats for one completion id, after the fact

Only the chat routes stream. /v1/embeddings and /v1/audio/transcriptions return a single body once the runtime finishes. /v1/images/generations holds the connection while a worker renders and returns a single body too; if wait_seconds lapses first it returns 504 render_timeout naming the job_id to poll, rather than a partial success. See OpenAI-compatible API for those three shapes.

02

JSON-RPC

tenzro_chat                      simple shape
tenzro_chatStream                rich shape with reasoning, tool calls
03

Usage in stream

Every stream ends with a finish_reason chunk carrying prompt_tokens / completion_tokens / total_tokens plus the extension fields cost_wei, generation_time_ms, and tokens_per_second — no opt-in needed to learn what you were billed. stream_options: {"include_usage": true} appends the OpenAI empty-choices usage chunk after it. data: [DONE] terminates the stream. Streams resume via the SSE Last-Event-ID header (<completion_id>:<seq>) against an in-memory buffer with a 300-second TTL.

POST /v1/responses streams the same generation as named events — response.created through response.output_text.delta to response.completed — each carrying a monotonic sequence_number. There is no [DONE] sentinel on that route: the terminal event is the terminator. See OpenAI-compatible API for the full event order.

04

Usage after the stream

The terminal chunk arrives after the text the caller was waiting for, so a client that stops reading at the last token never sees the counts. GET /v1/generation?id=<completion_id> resolves the completion id — the same id the Last-Event-ID cursor is built from — back to the recorded input_tokens, output_tokens, latency_ms, serving provider and cost_wei, plus whichever of cached_read_tokens, cached_write_tokens, reasoning_loops, image_tokens, audio_seconds, video_seconds, frames and pixel_steps the call actually consumed. The same read is tenzro_getGeneration over JSON-RPC. It answers 404 for an id this node has no record of, which includes a generation still in flight. See OpenAI-compatible API for the response shape.

05

Rich-shape scope

POST /chat-stream serves local weights only. A model that resolves to a network peer returns HTTP 501 stream_forward_unsupported — use the non-streaming tenzro_chat rich shape, which forwards. A provider pin naming an address other than this node's payee returns HTTP 409 provider_pin_unsupported, because serving it here would bill this node's payee for an offer the consumer scored against someone else. Simple-shape streaming forwards to peers normally and carries neither restriction.

06

WebSocket

Event bus subscriptions for inference completion, settlement, and provider status. Replay supported via since=<height>.

07

Provider failover

Last-Event-ID resume covers a dropped client connection. When the drop is on the provider leg — the gateway is proxying a network model and the serving provider dies mid-generation — the gateway continues on a different provider serving the same model without a visible restart. It captures the sampling state as it forwards tokens (messages, seed, temperature, top_p, max_tokens, and the assistant text emitted so far), then re-sends to another provider with the emitted text as a trailing assistant prefix and continue_final_message: true. The seed travels with the request so the new provider re-prefills the identical prefix and resumes sampling from the same distribution. No KV-cache bytes cross the wire. Bounded single retry: a second drop ends the stream. Pin seed for byte-identical continuation.

Related
← All docs