Run Kilo Code on Stav
Add Stav as a custom provider in Kilo Code's config file, pick a model that runs on EU compute, and know which features were tested.
Kilo Code is an open-source coding agent. It runs as a terminal CLI, a VS Code extension and a JetBrains plugin, all on one config file. It can send its model traffic to any OpenAI-compatible endpoint, so it runs on Stav with configuration only.
Point it at Stav and every turn is billed to your Stav credits, shows up in your request log, and follows your workspace policy. Pick a model that is not a Claude or OpenAI model and the work runs where that model's Inference Provider runs — for example in France.
Tested with the Kilo Code CLI 7.8.8 on macOS. The VS Code and JetBrains dialogs write the same config file but were not tested.
Before you start
- A Stav API key. See Authentication.
- Kilo Code installed. CLI:
npm install -g @kilocode/cli. See the Kilo Code CLI docs.
Set it up
Put the key in your shell and add a stav provider to the global config file, ~/.config/kilo/kilo.jsonc:
export STAV_API_KEY="sk_stav_live_..."
{
"$schema": "https://app.kilo.ai/config.json",
"model": "stav/zai-org/glm-5-2",
"provider": {
"stav": {
"npm": "@ai-sdk/openai-compatible",
"name": "Stav",
"options": {
"apiKey": "{env:STAV_API_KEY}",
"baseURL": "https://api.stav.ai/v1"
},
"models": {
"zai-org/glm-5-2": {
"name": "GLM-5.2",
"limit": { "context": 1000000, "output": 16384 }
},
"auto": {
"name": "Smart Router",
"limit": { "context": 128000, "output": 8192 }
}
}
}
}
}
- Write the base URL with
/v1. Kilo Code adds/chat/completionsitself. {env:STAV_API_KEY}is only resolved in the global file. A project-levelkilo.jsoncignores it, on purpose, so a repository cannot read your key. Keep the provider in the global file.- Kilo Code does not fetch Stav's model list for a custom provider. Every model you want in the picker needs its own entry under
models, with itslimit. The model page in the Stav catalogue shows the context window and max output. - A model is addressed as
stav/<model>, sostav/zai-org/glm-5-2on the command line and in the picker.
In VS Code or JetBrains: Settings → Providers → Custom provider. Provider ID stav, Provider API OpenAI Compatible, Base URL https://api.stav.ai/v1, your key, then add the models. This writes the same provider.stav block.
Run a turn:
kilo run "Reply with the words: hello from stav"
Pick a model
Any chat model in the Stav catalogue works, by its full slug. Add it under models first.
| Model value | What happens |
|---|---|
An open-weights model, such as zai-org/glm-5-2 | Stav translates each request to the provider and the answer back. Tested end to end: served in France by Scaleway |
auto | Your workspace's default Router picks a model for each request. It follows the Router's rules, so it can pick a US-served model unless your policy blocks that. In our test it picked a model served in the US |
A named Router, such as @workspace/router | That Router's rules decide. Tested with a Router that requires EEA compute: served in France |
A Claude or OpenAI model, such as anthropic/claude-haiku-5-5 | Forwarded to that provider. You get Stav's logging, spend limits and key controls — not EU compute |
A named model can be served by more than one Inference Provider, and they are not all in the EU. In our test one turn on zai-org/glm-5-2 was served from Finland or France by a different provider than the rest. To keep every request in Europe, set a sovereignty floor or a compute region for your workspace. See Keep traffic sovereign.
Switch models for one run with kilo run -m stav/auto "...", or in the TUI with /models.
What works
Tested on zai-org/glm-5-2:
| Feature | Result |
|---|---|
| Streaming | Works |
| Tool calls (read, edit, run commands) | Works. Kilo Code sends 23 tools and tool_choice: "auto" on every turn |
| A full agent task (fix a bug, run the file) | Works |
| Session title generation | Goes through Stav too, on the same model |
Reasoning level (--variant high, needs "reasoning": true on the model entry) | Sent as reasoning_effort. On a model with no levels, Stav answers X-Stav-Reasoning-Effort: fixed and the turn runs |
Model picker from Stav's /v1/models | Not supported for a custom provider — list the models in the config |
| Image input, embeddings, prompt caching | Not tested |
A Claude model gets the request translated to Anthropic's Messages API. We tested one streamed turn on anthropic/claude-haiku-5-5.
Tips
- Set
limitto the model's real numbers. Kilo Code useslimit.outputasmax_tokenson every request andlimit.contextto decide when to compact. The model page in the catalogue shows both. autohas no fixed limits. Give it alimitthat fits the smallest model your Router may pick. Stav lowersmax_tokensto the serving endpoint's cap and names it inX-Stav-Clamped-Params.- Kilo Code sends
content: nullon assistant turns that only call tools. Some strict endpoints reject that. Stav accepts it, so the agent loop runs. - Some traffic does not go through Stav. Kilo Code checks for updates and can send telemetry to Kilo. Only model traffic goes to
api.stav.ai. - The key never goes in a project file. Even
{env:...}is ignored there. Use the global file orKILO_CONFIG.
Troubleshooting
| What you see | Cause | Fix |
|---|---|---|
Error: Invalid or revoked API key. | The key is wrong, revoked or expired | Create a new key in Your workspace → Connect → API keys and update STAV_API_KEY |
Error: Not Found | The base URL has no /v1, so Kilo Code calls /chat/completions on the host | Use https://api.stav.ai/v1 |
Error: Not Found: {"detail": "Not Found", ...} | The base URL ends in /v1/v1 | Use https://api.stav.ai/v1 |
| The model is not in the picker | Custom providers do not fetch the model list | Add the model under provider.stav.models |
| The key is ignored in a project | {env:...} only resolves in the global config | Move the provider block to ~/.config/kilo/kilo.jsonc |
For Stav's error codes, see Errors.
Check it worked
Open Your workspace → Monitor → Request log. Each turn is one row, with the model, Inference Provider, country and cost. A short task is usually 3–5 rows. See Request log and prompt capture.