Data retention
Every prompt a run sends carries your task, your files, and whatever the agent read along the
way. Once the reply is back, the provider may keep a copy for days, for abuse review, or for
nothing at all, and nothing in the request tells you which. Leviath keeps a table of what each
provider keeps, reads the settings a provider exposes, and lets you ask for zero retention
everywhere. With the switch on, a model that would keep something is never sent a request. That
covers a stage's request, the run's title call, a compaction summary, lev test and the
lev doctor probe. Each is refused in the same words.
lev providers retention # what each configured provider keeps, and who controls it
lev providers retention set zero # ask everywhere; refuse a model that cannot give it
lev validate ./my-agent # says which stages the switch would refuse
lev run my-agent --task "..." # refused at spawn if a stage's model keeps anythingThe terms
Retention is how long a provider keeps a request's prompt and reply after answering. A provider that keeps nothing once the reply is returned offers zero data retention, often written ZDR. A retention of 30 days usually means an abuse-monitoring log that the provider reviews and deletes. It is separate from training: none of the shipped providers train on API traffic, whatever they keep.
Who controls it differs by provider, and that decides what Leviath can do about it:
| Control | Meaning | Providers |
|---|---|---|
| per request | A field on each request asks for it | OpenAI (store), OpenRouter (provider.zdr) |
| account setting | An API reads and writes it | Bedrock (data-retention mode) |
| agreement | A contract with the provider, which no API can read | Anthropic, OpenAI, Google |
| fixed | Nothing to set; the policy is what it is | Meshy, local models, subscription transports |
How to think about it
Zero retention is a property of a model at a provider, not of Leviath. Leviath can send the request field, set the account mode, and refuse a model that cannot give it. It cannot make a provider keep less than its floor. Three things follow.
Some models keep data whatever you ask. Claude Fable 5 and 5.1, and Claude Mythos 5 and 5.1, keep prompts and replies 30 days for safety review on every platform that serves them. On Bedrock, every OpenAI model is served only under modes that keep something. With the switch on, a stage that names one of these is refused. Name another model or turn the switch off; there is no third option.
An agreement is taken at your word. Anthropic, OpenAI and Google grant zero retention by
contract, and no API reports whether you hold one. You declare it in
[providers] zero_retention_agreements, and the provider then counts as keeping nothing. Declare
only what your organisation has signed.
A gateway keeps what its upstream keeps. OpenRouter keeps nothing itself unless you turn on prompt logging, and routes to endpoints run by other vendors. With the switch on, Leviath asks it to use only endpoints with a zero-retention policy, and refuses a model that has none rather than let OpenRouter route it elsewhere.
Bedrock, model by model
Bedrock is the one provider where retention is both an account setting and a per-model fact.
The account has a data retention mode: none keeps nothing, default leaves each model to
its own policy, and aws_review lets AWS keep flagged content up to 30 days for human review. An
account set to inherit serves each model under that model's own default, which is default
for most.
Each model also says which modes it may be served under. A model that never allows none
cannot run with zero retention on Bedrock at all, and under an account set to none Bedrock
reports it unavailable. Access is per model too: a model your account has no grant for is
unavailable whatever the mode, and Bedrock says why.
Leviath reads the account mode and the per-model list when it starts, and reads the mode again
before every spawn while zero retention is on. lev providers retention prints both. It names the
models never served under
none, and any unavailable to your account with Bedrock's reason:
bedrock zero (account setting, read from the account)
account data retention mode: none (read just now)
never served under mode none, so never with zero retention: openai.gpt-5.4, openai.gpt-5.5
unavailable to this account as things stand: anthropic.claude-fable-5 (This model is not available under data retention mode 'none'.)lev providers retention set zero sets the account mode to none as well as writing the switch.
lev providers retention bedrock <mode> sets the mode alone. While the switch is on, a running
daemon reads the mode again before every spawn, so either change is in force at once.
What the switch does
The switch is [providers] zero_retention = true in config.toml. lev providers retention set zero writes it. The setup wizard's Zero data retention row writes it too, and so does
lev setup --zero-retention true:
| Provider | With the switch on |
|---|---|
| Bedrock | Account mode set to none; a model never served under none is refused |
| OpenAI | store = false on every request; the abuse log stays unless you declare an agreement |
| OpenRouter | provider.zdr = true and data_collection = "deny"; a model with no ZDR endpoint is refused |
| Anthropic, Google, xAI | Refused unless you declare an agreement |
| Meta | Refused, the standard models and a -contributor model alike |
| local models | Nothing to do; nothing leaves the machine |
| Meshy, Codex, Grok, Claude Code | Refused; the policy is fixed |
| Every provider with a Files API | Nothing is uploaded; parts go inline, within each provider's inline limits |
Meta publishes no retention window for its standard models, so the switch refuses them. A
-contributor model is refused outright, because Meta trains on it.
A stage is judged by the model it would start on. Its fallbacks are judged the same way, and one that keeps something is dropped from failover, with a line in the stage's log saying so. Nothing is rerouted: an author who pinned a model would not see it swapped for one at another vendor.
The switch holds past the spawn too. A run's title is written by the first model in its title
chain that keeps nothing, and a blueprint whose compaction_config names a model that keeps
something is refused at spawn. Turning the switch on under a running daemon refuses the next call
of a run already going, which then ends with the reason rather than sending it.
lev validate says the same thing before a run does. A stage whose model would be refused is a
retention-not-zero error, and a fallback that would be dropped is a retention-fallback-dropped
warning, each carrying the provider's reason. The
lint reference lists both.
Files uploaded to a provider
With the switch off, a large image, PDF, video or recording is uploaded to the provider's file
storage and named by id on later requests (see Files and size limits).
That upload is kept at the provider until the run ends or the upload's lifetime passes, a day by
default. It is data the provider keeps, so the switch turns uploads off, and
[providers] file_uploads = false turns them off without the switch. Anthropic's Files API is not
eligible for zero data retention in any case.
Reading the answer
Every answer has three parts: what is kept, who controls it, and where the answer came from.
lev models show claude-sonnet-5
Retention 30 days (by agreement, documented)
Anthropic's commercial API keeps prompts and outputs up to 30 days ...documented is the table this build ships. read from the account is a setting Leviath read
live, which only Bedrock offers. requested per request is the field sent with the switch on.
declared agreement is one you wrote in the config. config override is a retention key you
set on a [model_capabilities.<model>] or [model_providers.<name>] entry, which wins over
everything else and is how you tell Leviath about a custom host it cannot know.
Proxies, gateways and Azure
Many organisations reach a provider through a gateway of their own, which holds the real key,
strips retention by contract, and wants a token or a tag of its own on every request. Point the
provider at it with <provider>_base_url, and give it what it wants with <provider>_headers.
Declare the zero retention the gateway provides as an agreement, since no API can read it:
[providers]
anthropic_base_url = "https://llm-gateway.corp.example/anthropic"
anthropic_api_key = "gateway-placeholder"
anthropic_headers = { X-Gateway-Token = "...", X-Cost-Centre = "research" }
zero_retention = true
zero_retention_agreements = ["anthropic"]Azure OpenAI is an OpenAI-compatible endpoint with its own header and its own retention terms.
Azure keeps prompts up to 30 days for abuse monitoring unless the exemption is approved for your
subscription, so retention = "zero" is yours to declare only then. zero_retention_request
tells Leviath to send it OpenAI's store = false with the switch on. It would otherwise withhold
that field from an endpoint, because a llama.cpp server would reject it:
[model_providers.azure]
kind = "openai-compatible"
base_url = "https://my-resource.openai.azure.com/openai/v1"
headers = { api-key = "..." }
serves = ["gpt-5.5"]
retention = "zero"
zero_retention_request = "openai"The exact keys are on the configuration page.
What this cannot do
It cannot read a contract, so a declared agreement is trusted. It cannot see a provider's internal logs, so the table is what each provider documents, dated on the providers page. And it cannot lower a floor: a model that retains regardless is refused under the switch, never sent. If you need a guarantee stronger than a provider's published policy, the answer is a local model, which keeps nothing because nothing leaves the machine.
The exact keys, flags and command forms are on the providers, configuration and CLI pages.