Documentation v1.0.9

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 (/channeladmin in the TUI; /admin-channel was removed)

Where things deliberately do not live

中文