Configuration
File layout
~/.config/agenvoy/
├── config.json Main config — models, priority, tiers, routing roles, channel flags, reply language, output dir, limits, policy overrides
├── daemon.log Daemon log
├── runtime.uid Server-mode singleton record
├── mcp.json Global MCP servers
├── tasks.json One-shot scheduled tasks
├── crons.json Recurring cron tasks
├── allow_skill Global skill always-allow list (one name per line)
├── allow_tool Global tool auto-approve list (one pattern per line, `prefix*` allowed)
├── .telegram / .discord Authorized chat IDs (one per line, written after OTP success)
├── .store/
│ ├── history.db SQLite — session, message_meta, note + FTS5, messages + FTS5, action_history, file_history, usage
│ ├── db_0 ... db_3 ToriiDB — tool and quota cache, chat vectors, error memory, online markers
│ └── temp/ Removed files moved aside with a timestamp suffix
├── prompts/ Session prompt rules (.md, surfaced through /v1/rules)
├── skills/ Skill storage (git-versioned)
│ ├── .system/ Bundled skills
│ ├── scheduler/ Scheduler skill dirs (<short>-<hash8>/SKILL.md)
│ └── .Trash/ Removed skills (recoverable from .Trash)
├── tools/ Tool storage (git-versioned)
│ ├── api/ API tools (single JSON each)
│ ├── script/ Script tools (tool.json + script.py)
│ ├── .system/ Bundled tools
│ └── .extension/{api,script}/ Extension-installed tools
├── vendor/ Web dashboard's third-party assets, downloaded at daemon startup and served at /vendor/*
├── knowledge/ Legacy notes, read once to migrate into the SQLite note table
├── download/ Inbound chat attachments and downloaded files (.Trash/ inside); default output dir when ~/Downloads is missing
└── sessions/
├── .Trash/ Removed sessions
└── <sid>/
├── history.json Recent conversation, delta-appended
├── summary.json Rolling summary
├── .summary_cursor Incremental summary cursor
├── action.log Tool call audit trail — [ts][window_hash][kind][task_hash] body
├── .cmd_history Per-session TUI input history
└── pending/ Pending ask_user / confirm metadata, one JSON per task hash
<project-root>/.config/agenvoy/ Project-scoped tools and skills
├── tools/{api,script}/
└── skills/
<project-root>/.agenvoy/allow_skill Project-scoped skill always-allow list (union with global)
<project-root>/.agenvoy/allow_list Project-scoped tool allow list
config.json
Model, routing, and channel settings:
| Key | Description |
|---|---|
models |
Registered models as "<provider>@<model>" strings; the order is the fallback priority |
model_tag |
{model: tier} with tiers S A B C pass; written as {} when missing |
dispatcher_model / summary_model |
Dispatcher and summary roles |
image_generator / stt_model / tts_model |
Image provider endpoint and audio models |
compats |
Custom OpenAI-compatible endpoints, [{provider, url}] |
keys |
Names of credentials stored in the keychain (never the values) |
telegram_enabled / discord_enabled |
Channel flags; telegram_username / discord_username are filled in by the daemon |
admin_channel |
Verification-code relay target |
reply_lang |
Reply language, default "auto" (match the user). Accepts a code from configs/jsons/reply_lang.json (en, zh-TW, zh-HK, zh-CN, ja, ko, es, fr, de, pt, it, ru, vi, th, id, ar) or any language name |
output_dir |
Where files made for the user land when no location is named; default "" means ~/Downloads, or ~/.config/agenvoy/download when that folder does not exist. ~ is expanded; an unusable path falls back to the default |
reply_lang and output_dir are set from /config in the TUI or GET / POST /v1/config/system and /v1/config/output_dir; /config also toggles Startup on login (/v1/config/startup). The separate startup, reply-language, and output-dir TUI commands were removed; use /config. The daemon watches config.json and reloads the agent registry and Telegram / Discord on every write.
Beyond model and channel settings, config.json carries the runtime limits and optional policy overrides. Missing limit fields, reply_lang, output_dir, and model_tag are filled with defaults and written back on startup.
| Key | Default | Description |
|---|---|---|
limits.max_tool_iterations |
128 |
Maximum tool iterations per run |
limits.agent_send_timeout_seconds |
600 |
Model-request timeout |
limits.max_history_messages |
24 |
Recent history messages retained |
limits.max_history_bytes |
5242880 |
History-size ceiling |
Package defaults that are not read from config.json:
| Constant | Default | Description |
|---|---|---|
MaxSessionTasks |
NumCPU × 4 |
Concurrent tasks per session; further tasks queue rather than fail |
MaxSubagentTimeoutMin |
30 |
Subagent timeout in minutes |
MaxResumeWaitMin |
60 |
How long a pending resume waits for answers |
The daemon port is not configurable: 17989 is a package constant, and a limits.port entry is ignored.
Policy keys in config.json. The first two merge with values embedded in the binary (user entries add to, never replace, the defaults); the rest exist only as user config:
| Key | Embedded source | Purpose |
|---|---|---|
sensitive_path |
configs/jsons/sensitive_path.json |
Credential and key-material paths — reachable only after a password-backed per-session grant. Buckets: dirs, files, prefixes, extensions |
read_only_command |
configs/jsons/read_only_command.json |
Commands that skip the confirm gate (git status, ls, cat, ...) |
denied_command |
— | Binaries run_command refuses outright, inside sh -c too |
denied_path |
— | Paths permanently off limits for reads and writes; no prompt can approve them. Entries must be absolute or start with ~/; the filesystem root is refused |
net_white_list |
— | Hosts exempt from the http_request SSRF guard |
Three keys are no longer read and produce a startup warning if present: sensitive_map (renamed sensitive_path), white_list (removed — commands run unless listed in denied_command), and path_white_list (removed — paths outside $HOME are approved per session).
v0.35.0 dropped the last pre-v0.28.9 compatibility paths: limits.max_skill_iterations (superseded by limits.max_tool_iterations) and planner_model (superseded by dispatcher_model, and deleted from config.json on the next save) are no longer honoured, and the legacy api_tools/ / script_tools/ directories are no longer read — tools live under tools/api/ and tools/script/.
There are no environment variables for runtime limits — env-based overrides were removed; config.json is the only knob.
Project configs
configs/
├── jsons/
│ ├── sensitive_path.json Credential / key-material paths
│ ├── exclude_list.json Listing/walking exclude paths
│ ├── read_only_command.json Commands that skip confirmation
│ ├── local_compat.json Built-in local endpoints (Ollama, llama.cpp)
│ ├── reply_lang.json Reply-language codes and labels
│ └── tui_tools.json TUI-only tools and skills
└── prompts/ System prompt templates, reasoning guides, channel prompts
Provider and model catalogs no longer ship in the repository — model lists are fetched live from each provider's API.
Session persona
Session configuration lives in the session table of ~/.config/agenvoy/.store/history.db, not in per-session files: name, self_id, model (auto by default), reasoning, rule (the persona body), plus the chat binding (chat_id, guild_id, channel_id, user_id). self_id is normalized to lowercase and accepts up to 32 ASCII letters, digits, _, or -; non-empty values must be unique.
The persona body is rendered into the system prompt's ## Bot Persona block on every turn. Edit it from the TUI with /bot, or through GET / POST /v1/session/:id.
At daemon startup, legacy per-session bot.json, bot.md, config.json, status.json, usage.log and summary.meta.json are migrated into SQLite and are no longer written. The state table itself was dropped in v0.35.3 — a session's live state is now a ToriiDB online marker, not a stored row.
Permission mode
The active permission mode (single-confirm vs always-allow) is decided by entry point:
| Entry | Mode |
|---|---|
| TUI | single-confirm, toggled per session with Shift+Tab |
POST /v1/send |
single-confirm; confirms are answered through the web dashboard. The allow_all request field was removed |
POST /v1/chat/completions |
always-allow |
| Telegram | single-confirm (confirm gate uses a Telegram inline-keyboard select) |
| Discord | single-confirm (confirm gate uses a Discord select menu) |
| Resumed pending task | Keeps the mode stored with the task |
| Subagent | Inherits parent ctx |
The mode is rendered into the system prompt under ## Permission Mode. Commands on the read-only list skip the gate in every mode.
MCP config
One file: ~/.config/agenvoy/mcp.json. The session-scoped layer was removed. See the MCP Client page for the full schema and ${VAR} expansion behavior.
KuraDB
There is no kuradb_enabled flag and no /v1/kuradb endpoint. KuraDB is registered like any other MCP server — one entry in mcp.json — and its tools arrive under mcp__kura__*. The /kuradb TUI wizard was removed in v0.35.0: install it yourself with kuradb.sh (it needs a real TTY for sudo) and register it through /mcp.
| Key | Location |
|---|---|
kura server entry |
~/.config/agenvoy/mcp.json |
OPENAI_API_KEY |
keychain (agenvoy service) — shared with semantic search |
| Binary | kura on PATH (/usr/local/bin/kura) |
| KuraDB's own config / data | ~/.config/kuradb/, managed entirely by KuraDB |
Telegram / Discord enablement
| Key | Location |
|---|---|
telegram_enabled / discord_enabled |
config.json |
TELEGRAM_TOKEN / DISCORD_TOKEN |
keychain (agenvoy service) |
| Authorized chat IDs | ~/.config/agenvoy/.telegram, ~/.config/agenvoy/.discord (written after 6-digit OTP verification succeeds) |
| Verification-code relay target | admin_channel in config.json (/channel → admin in the TUI; /admin-channel was removed) |
Where things deliberately do not live
- Provider API keys — never in
config.json; always in keychain - MCP credentials — use
${VAR}placeholders inmcp.jsonand keep values in env vars - Secrets captured by
store_secret— keychain only; never in LLM context, history,action.log, or tool args - Session config and persona — in the SQLite
sessiontable under.store/, not per-session JSON files - Session history —
history.jsonfor the hot window, mirrored into ToriiDB and SQLite under.store/ - Operator notes — the SQLite
notetable under.store/, never~/.config/agenvoy/knowledge/; that directory is only read once, to migrate old notes in - Tool call results — in-memory dedupe per run plus a 30-minute ToriiDB cache for
fetch_page,search_web, andhttp_requestGETcalls; nothing else persists across restarts