Built-in Tools
File operations
| Tool | Description |
|---|---|
read_files |
Batched read of one or more files (files: [{path, offset, limit}]); text, PDF, DOCX, PPTX, CSV/TSV, or image. Reads the whole file by default (1 MB cap); offset/limit page through larger files. Must be called before patch_file. Sensitive file guard: SSH keys, .pem, .key, .env always require confirmation regardless of sudo or allowlist |
write_file |
Create a file that does not exist yet, or deliberately replace one wholesale. Any edit to an existing file belongs in patch_file |
patch_file |
Targeted edit via a targets array — each target is a replace (old_string/new_string[, replace_all][, row]) or a pure insert (insert_string/row); row-bearing targets apply highest-row-first so line numbers stay valid |
list_files |
Batched directory listing (dirs: [{dir, recursive}]); returns a JSON object mapping each requested dir to its entries |
glob_files |
Batched glob pattern search (queries: [{dir, pattern}]); matches merged and deduplicated. Catch-all patterns (**/*) are rejected — every pattern must carry a literal |
search_files |
Batched RE2 regex search inside file contents (queries: [{dir, pattern, file_pattern}]); matches merged and deduplicated |
open_file |
Open a file with the OS default application (play a video, view an image, open a PDF viewer). Replaces run_command open/xdg-open, which the sandbox cannot reach. 15 s cap |
Web (read-only, concurrent)
| Tool | Description |
|---|---|
fetch_page |
Fetch a web page (readability + 4xx/5xx skip cache via ToriiDB); same_session=true for login-required sites, save=true persists to a local file. 90 s cap |
search_web |
DuckDuckGo search; cdp=true forces a browser fetch (auto-enabled on 202). 90 s cap |
search_google_news |
Google News RSS; empty results escalate the window (1 h → 24 h → 7 d) before falling back to search_web |
HTTP
| Tool | Concurrent | Description |
|---|---|---|
send_http_request |
✓ | Raw HTTP request (GET/POST/PUT/PATCH/DELETE, optional multipart upload), returns status + headers + body. Built-in SSRF guard (DNS-resolved against loopback / private / link-local); bypass specific hosts via net_white_list |
download_file |
✓ | Download a binary file to local disk (tar.gz, images, archives); for JSON/HTML use send_http_request or fetch_page(save=true). 10 min cap |
Media
| Tool | Concurrent | Description |
|---|---|---|
transcribe_media |
✓ | Local audio / video transcription via Gemini (ogg, oga, opus, mp3, wav, m4a, flac, aac, mp4, mov, webm, mpeg, 3gp). For inbound voice messages the transcript is the instruction to follow. 5 min cap. (gemini credential needed) |
Image generation is currently unavailable — the generate_image tool, /image2 command, and enable_image2 flag were removed while the router integration is redesigned.
Utility
| Tool | Concurrent | Description |
|---|---|---|
calculate |
✓ | Batch expression evaluator (arithmetic, unit conversion, currency arithmetic). Returns {expression: result}; a failed expression returns an error string instead of failing the whole call |
Agent orchestration
| Tool | Description |
|---|---|
list_subagent_sessions |
List named (non-temp) sessions reusable as a subagent, each with its role. Called before delegating a single subtask |
invoke_subagent |
Spawn a subagent in its own session (in-process, no HTTP); name empty means a temp session. At most 3 legs run concurrently — a 4th queues while its own timeout runs, so wide fan-outs dispatch in batches of 3. Results carry a [subagent · <model> · session=<id> · usage: in=X out=Y cached=Z] prefix that rolls up into parent-session usage. Timeout MaxSubagentTimeoutMin (30 min) |
Interactive
| Tool | Description |
|---|---|
ask_user |
Free-text / single-select / multi-select / secret masked input prompts; execution pauses and resumes in a new turn with full context. Routes through the pending registry when a listener is active, else falls back to stdin (CLI) or non-interactive guidance |
store_secret |
Captures a value via masked input and writes directly to keychain — the value never enters the LLM context, history, or logs. Schema does not accept a value parameter; the agent only sees name + description. Max 2 rounds per tool per turn |
write_todo |
Live task checklist the user watches in real time. The entire ordered list is resent on every call (state is replaced, not merged); exactly one step stays in_progress |
install_dependence |
Install a missing system binary cross-platform (TUI/CLI only). Skips if already in PATH. Sandbox blocks sudo, so this tool bypasses it. Language-level packages (pip/npm/cargo/gem) → output command for the user to run manually |
Memory
| Tool | Description |
|---|---|
search_chat_history |
Search this session's past messages; mode=keyword for exact match, mode=semantic for meaning-based match |
remember_error |
Persist a tool-error record (resolved / failed / abandoned) to cross-session memory. Fire-and-forget |
search_error_history |
Cross-session search over error memory; results are authoritative — resolved → apply, failed/abandoned → avoid |
read_error |
Fetch a prior error record by hash (used when a tool returns no data: {hash}) |
RAG
External-document RAG via the KuraDB child process. Tools are per-turn dynamically excluded when ~/.config/kuradb/endpoint is absent — the LLM never sees them when KuraDB is off.
| Tool | Description |
|---|---|
list_rag |
List available KuraDB databases (e.g. notes, inbox, code); skipped when the database name is already known |
search_rag |
Search a database via KuraDB's unified /api/search (keyword + semantic together by default); mode=keyword for exact strings, mode=semantic for natural-language queries. 15 s cap |
When search_rag is loaded, the system prompt forces the first wave of tool calls for any information query to be list_rag + search_rag. External web/search tools become secondary (gap-filling), not fallback or substitute.
Channel
Cross-session push tools. Each gates on both the telegram_enabled / discord_enabled config flag and keychain credential presence. Platform formatting rules are embedded in the channel system prompts, not fetched through a tool.
| Tool | Description |
|---|---|
list_chatbot |
List authorized chats for the specified platform (platform=telegram or platform=discord) |
send_to_chatbot |
Send a formatted message to an authorized chat by target_id. Telegram: HTML + transient client. Discord: markdown + transient client |
Output markers (channel-specific behavior)
Output text from any tool or LLM response is post-processed for these markers:
| Marker | Behavior |
|---|---|
[SEND_FILE:<path>] |
Channel runtime auto-attaches the file (Telegram → photo/document split by ext, Discord → unified SendFiles batched 10/msg) |
[SEND_VOICE:<text>] |
Telegram only. Synthesizes via Gemini TTS, sends as OGG voice. The upload fires async (go func with context.WithoutCancel); reply text returns immediately. Failure → slog.Error + chat notify (never silent) |
Marker regex + dedupe + os.Stat filtering lives in internal/utils/utils.go; the voice marker regex lives in internal/runtime/chatbot/chatbot.go.
Discovery & reasoning rules
| Tool | Description |
|---|---|
search_tools |
Search the tool registry by keyword (or select:<name> for exact activation) and inject the matching schemas |
list_tools |
List registered tools by name + one-line description (read-only, no schema injection); mcp=true narrows to MCP-exposed tools |
run_skill |
Load a named skill's reference material into the current turn; the result is advisory |
reasoning_guide |
Fetch the full rule set for one topic — tool_generate, tool_error, rag_web, market_analysis, targeted_read, ask_user, subagent_dispatch, write_todo, html_render. Replaces the former per-topic guide tools |
Skill & tool variants (always-allowed write_file variants)
| Tool | Description |
|---|---|
write_skill |
Create or fully rewrite a file under ~/.config/agenvoy/skills/ |
patch_skill |
Exact string replacement inside a skill file |
remove_skill |
Move a skill directory to .Trash/ (recoverable via restore_revision) |
write_tool |
Write a tool file — tag=json|script under the script-tool directory, tag=api a single JSON under the API-tool directory |
patch_tool |
Exact string replacement inside a tool file (tool.json, script.py, or API tool JSON) |
test_tool |
Run a script tool's script.py with JSON input inside the sandbox — the verification step after write_tool / patch_tool |
remove_tool |
Move a script tool directory to .Trash/ |
All variants are always-allowed and scoped to their respective directories. Every write/patch/remove auto-commits to the corresponding git repo (skills or tools).
Revision history
Scope is limited to Agenvoy's own storage under ~/.config/agenvoy — never the user's project repository.
| Tool | Description |
|---|---|
list_revisions |
List revision history of the skill or tool storage; used to find a target revision or verify auto-commits landed |
restore_revision |
Hard-reset the skill or tool storage to an earlier revision; run list_revisions first |
System
| Tool | Description |
|---|---|
run_command |
Execute a binary with argv (argv-only schema, sandbox-wrapped via go-pkg/sandbox); ['cd', '<path>'] is special-cased and mutates Executor.WorkDir after verifying the path. Shell features need an explicit ['sh','-c','...'], whose script is parsed and validated command-by-command — every binary must be a bare command name on the allowlist, rm and dynamic commands are rejected outright. Commands on the read-only list (git status, ls, cat, pwd, …) skip the confirm gate |
Scheduler
| Tool | Description |
|---|---|
add_schedule |
Bind an existing scheduler skill to a one-shot fire time (target=task) or a 5-field cron expression (target=cron). Task time formats: +5m (relative), HH:MM (today), YYYY-MM-DD HH:MM, or RFC3339. Internal to the scheduler-skill-creator flow — hand-made skill_name values fail because every scheduler skill carries a generated hash suffix |
patch_schedule |
Reschedule by skill_name and target; changes only the time/expression, leaves the bound SKILL body untouched |
remove_schedule |
Cancel by skill_name and target; the bound scheduler skill dir is moved to .Trash/ |
list_schedule |
List tasks and/or crons in the current session. target accepts task, cron, or all (default) |
scheduler-skill-creator is the high-level skill that creates a scheduler skill body and calls add_schedule to bind it. New recurring / one-shot requests should activate that skill, not call the low-level tools directly.
The daemon-side runtime watches ~/.config/agenvoy/{tasks,crons}.json with fsnotify and hot-reloads on Write / Create / Rename. Past-due tasks are auto-fired and removed on startup or reload; fire executes via runtime.SetRunner → in-process subagent over the scheduler skill body (always-allow context).
TUI surfaces /cron, /task (add / remove / edit), and /sched-<name> (manual trigger of an existing scheduler skill body) for managing schedules.