Providers & API
Zod has no backend of its own. It talks directly from your browser to any OpenAI-compatible endpoint, giving you hub-first chat UI on top of the provider you choose — and full control over streaming, retries, rate limits, and timeouts.
Any OpenAI-compatible endpoint
Zod works with anything that speaks the OpenAI /v1/chat/completions format. Configure as many providers as you like and pick a default and a fallback.
Provider configuration
Providers are edited as live YAML in Settings → Providers. Each provider has a name, base URL, API key, model, and an enabled flag:
providers:
- name : OpenRouter
baseUrl : https://openrouter.ai/api/v1
apiKey : sk-or-v1-REPLACE-ME-00000000000000
model : openrouter/free
enabled : true
Default & fallback
Pick a default provider in Settings → General. Optionally choose a fallback provider: if the primary provider fails, Zod transparently retries on the fallback so a failed provider never stops the conversation.
Streaming & resilience
The provider engine is built for real-world use, with each behavior configurable from Settings.
Streaming (SSE)
Server-sent events are parsed token by token with onToken callbacks.
Retries with exponential backoff
Retries wait 500ms * attempt and only trigger on retryable failures (429, 5xx, timeouts, network).
Rate limiting (RPM)
A sliding 60-second window honors your configured requests-per-minute limit.
Timeout (AbortController)
An AbortController aborts after the configured timeout and converts it into a friendly error.
Request tuning
All request behavior is tuned from Settings → General:
| Setting | Options | Default |
|---|---|---|
| Timeout | 30s – 300s | 120s |
| Retries | 0 – 10 | 3 |
| Rate limit (RPM) | Unlimited / 60 / 120 / 300 | Unlimited |
| Request logging | On / off | Off |
Model autocomplete
The Providers editor fetches real models from each provider's /models endpoint and autocompletes the model field — so you never have to guess model IDs.
How requests are built
buildMessagesForChat flattens a session's user and assistant messages into the OpenAI message shape. Attached files are embedded as ### File: blocks inside the user content:
[
{ "role": "user", "content": "Summarize the attached file." },
{ "role": "assistant", "content": "Sure — here is the summary." },
{
"role": "user",
"content": "Here is the file you need:\n\n### File: report.md\n# Q3 results\nRevenue was up 12%...",
}
]
The request is sent with all built-in tool schemas (plus custom and MCP tools), and tool calls are parsed from both normal and streaming responses — accumulating streamed function arguments across chunks.