Docs
Configuration
avni.toml, environment variables, the budget.
One file, avni.toml. Secrets are never written in it: a value like "env:GROQ_API_KEY" is read from the environment when core starts, and a missing one is named in the error.
A complete example
This is the production file from deploy/avni.example.toml. Replace the two <verify: ...> ids with current ones from your provider's docs.
[core]
listen = "127.0.0.1:7444"
# dev_token = "env:AVNI_DEV_TOKEN" # optional shared token for dev tools
[auth] # device pairing: allows listening beyond loopback
state_dir = "/var/lib/avni/auth"
[budget]
daily_usd = 0.50
monthly_usd = 5.00
ledger_file = "/var/lib/avni/ledger.jsonl"
[memory]
db_file = "/var/lib/avni/memory.db"
[obs]
trace_file = "/var/lib/avni/turns.jsonl"
[stt]
chain = ["stt"]
timeout_ms = 2500
[stt.providers.stt]
kind = "openai_transcribe"
base_url = "https://api.groq.com/openai/v1"
model = "<verify: a current Whisper model id>"
api_key = "env:GROQ_API_KEY"
[llm]
ttft_timeout_ms = 3000
system = "You are Avni, a voice assistant. Reply in one or two short spoken sentences."
[llm.tiers.t1]
chain = ["chat"]
[llm.providers.chat]
kind = "openai_chat"
base_url = "https://api.groq.com/openai/v1"
model = "<verify: a current fast chat model id>"
api_key = "env:GROQ_API_KEY"What each section does
| Section | What it controls |
|---|---|
[core] | Where core listens. Beyond loopback it needs [auth] or dev_token, or it refuses to start. |
[auth] | Turns on device pairing and says where the paired devices are kept. |
[budget] | A daily and monthly spending cap in US dollars (UTC days and months). Needs ledger_file, so a restart cannot reset the total. Over the cap, paid providers are skipped and free ones keep working. |
[memory] | The SQLite file for what you ask Avni to remember. Leave it out to switch memory off. |
[obs] | One JSON line per turn with stage timings and cost. |
[agent] | Optional. Lets the model call tools (today calculate and current_time). Each call is checked before it runs, and anything risky is refused. Adds prompt tokens to every request, so it is off unless you add this section. The step limit is llm.tiers.t1.max_steps. Anything that needs your OK (a tool rated T2) is read back and runs only on a clear yes or a tap on Yes; confirm_timeout_ms sets how long it waits. |
[mcp.servers.*] | Optional, needs [agent]. Connects to an MCP tool server (a program, or an HTTP address) and offers the tools you list under it, each with a risk tier you write yourself. The server's own hints are ignored and unlisted tools are not offered. A server that cannot start is logged and skipped. |
[stt] and [llm] | The providers, and the order they are tried in. If the first fails, the next is used. Each provider is a name you choose; the phone's Models page lists those names. |
Environment variables
| Variable | Meaning |
|---|---|
GROQ_API_KEY | Whatever env:NAME your config names. This is the usual one. |
AVNI_LISTEN | Overrides core.listen (the same as --listen). It is checked against the same rule: beyond loopback needs auth. |
AVNI_DEV_TOKEN | The shared token, if the config uses env:AVNI_DEV_TOKEN. |
AVNI_PORT | Port for scripts/dev-core.sh (or --port). |
RUST_LOG | Log level, info by default. |
Where the files go
The ledger, memory, paired devices and turn log all live in one directory (/var/lib/avni in the deploy setup). Back it up; it is small.
avni-cli memory --file /var/lib/avni/memory.db list # what Avni remembers
avni-cli memory --file /var/lib/avni/memory.db export # everything, as JSON
avni-cli memory --file /var/lib/avni/memory.db forget "my sister"This works without the voice loop. Stop the service first, or work on a copy.