Built-in tool reference
Source baseline commit: e1318eca83a40b9418d873ad85c31686ea6b57d0.
67 built-in tools, in registry order, grouped by definition module. Descriptions are the complete affordance-decorated output of get_tool_definitions(); core flags and input schemas come from the same registry. This is the static catalog, not a snapshot of a running installation: backend availability, permissions and disabled-tool policy can reduce visibility. Agent limits and model/effort fields are conditioned on configuration at catalog build time. No installed extensions or externally published tools are enumerated.
Dynamic native tools are outside this static catalog: computer_session, computer_observe, and computer_act are registered separately. See the computer-use operator reference for their workflow, capability limits and consent requirements. The count above does not describe their availability in a configured running installation.
Hyprland release_confirmed may mean only a drained guardian ledger and closed local resources without a compositor ACK; it is not compositor or receiver proof.
Core marks is_core (not a permission grant). Required means the property appears in its containing object's required list; nested rows do not make an optional parent required. Constraints show enums, defaults and numeric bounds.
Regenerate from the repository checkout with python scripts/docs/generate_tool_reference.py; add --check for a read-only drift check. The explicit source baseline is stable across docs-only commits; advance it when documenting a new source baseline.
system_files
Source: src/tools/defs/system_files.py.
run_command
Core: Yes
Runs a shell command on a managed host. Returns stdout/stderr; large output has a retained preview and get_tool_output(cursor=...) continuation without re-running. On failure: 'Command failed (exit N): output'. For multi-line scripts, use run_script. For multiple hosts, use run_command_multi. Host may be omitted only when an explicit requester or runtime default host exists.
[affordances: cost=medium risk=high latency=seconds] (requires: managed host alias configured; SSH key available for non-local hosts)
| Name | Type | Required | Description |
|---|---|---|---|
host | string | No | Host alias from config (e.g. 'myserver', 'webhost') |
command | string | Yes | Shell command to execute (single line; for multi-line use run_script) |
run_script
Core: Yes
Runs a multi-line script on a managed host via temp file. Handles heredocs, code blocks, and complex quoting. Large stdout/stderr has a retained preview and get_tool_output(cursor=...) continuation without re-running. On failure: 'Script failed (exit N): output'. Interpreters: bash (default), python3, python, sh, node, ruby, perl. For single commands, use run_command. Host may be omitted only when an explicit requester or runtime default host exists.
[affordances: cost=medium risk=high latency=seconds] (requires: managed host alias configured)
| Name | Type | Required | Description |
|---|---|---|---|
host | string | No | Host alias from config |
script | string | Yes | Full script content to execute |
interpreter | string | No | Interpreter (default: bash) |
filename | string | No | Temp filename (default: auto-generated) |
run_command_multi
Core: Yes
Runs a command on multiple hosts in parallel. Returns per-host '### hostname\n```\noutput\n```'. Pass ['all'] for all hosts visible to the requester. For one host, use run_command.
[affordances: cost=high risk=high latency=seconds] (requires: managed host aliases configured)
| Name | Type | Required | Description |
|---|---|---|---|
hosts | array<string> | Yes | List of host aliases, or ['all'] for all hosts |
command | string | Yes | Shell command to execute on each host |
read_file
Core: Yes
Returns a contiguous range from a file on a managed host. start_line is one-based; lines is a count (default 200, max 1000). Numbered output is the default. Set raw=true for byte-faithful UTF-8 text in a length-framed metadata envelope carrying the exact interval, truncation state, content byte count, and continuation cursor. Consume only the framed source content. Large ranges never use head+tail truncation. To edit files, use apply_patch.
[affordances: cost=medium risk=none latency=fast] (requires: path accessible by ssh user)
| Name | Type | Required | Description |
|---|---|---|---|
host | string | Yes | Host alias from config |
path | string | Yes | Absolute path to the file |
start_line | integer | No | One-based first source line to read (default 1) Constraints: {"minimum":1,"maximum":9007199254740991} |
lines | integer | No | Number of lines to read (default 200, max 1000) Constraints: {"minimum":1,"maximum":1000} |
raw | boolean | No | Return byte-faithful UTF-8 text in a length-framed metadata envelope with explicit truncation/cursor state (default false) |
apply_patch
Core: Yes
Applies a strict, context-checked patch to text files on a managed host. The host, absolute root directory, and patch text are all required; every file path inside the patch must be relative to root. Supports *** Add File, *** Update File (optionally *** Move to), and *** Delete File sections inside one *** Begin Patch / *** End Patch envelope. Update hunks start with @@; consecutive named @@ lines before a hunk body are ordered anchors, and the complete monotonic anchor-chain plus body must match exactly once. Every hunk must contain at least one + or - line. To narrow a location, chain named @@ anchors. A context-only bare @@ block immediately followed by another @@ is treated as locating context for that following edit hunk. Add File and Move to create missing parent directories beneath root; the complete envelope is validated before any write, and multi-file application rolls back files and patch-created directories on failure. Requires a Linux host with glibc 2.28 or newer and filesystem support for renameat2(RENAME_NOREPLACE); no unsafe fallback is used.
[affordances: cost=medium risk=high latency=seconds] (requires: root writable by ssh user)
| Name | Type | Required | Description |
|---|---|---|---|
host | string | Yes | Managed host alias; no default is inferred |
root | string | Yes | Existing absolute root directory for all relative patch paths |
patch_text | string | Yes | Complete *** Begin Patch / *** End Patch envelope using relative POSIX paths |
media_scheduling
Source: src/tools/defs/media_scheduling.py.
purge_messages
Core: No
Deletes recent messages in the current Discord channel and resets conversation history. Default 100, max 500.
[affordances: cost=high risk=critical latency=seconds]
| Name | Type | Required | Description |
|---|---|---|---|
count | integer | No | Number of messages to delete (default 100, max 500) |
post_file
Core: No
Fetches a file from a managed host and posts it as a Discord attachment. Max 25MB. For generated content, use generate_file.
[affordances: cost=high risk=low latency=seconds]
| Name | Type | Required | Description |
|---|---|---|---|
host | string | Yes | Host alias from config |
path | string | Yes | Absolute path to the file on the host |
caption | string | No | Optional message to include with the file |
generate_file
Core: Yes
Creates a file (script, code, CSV, report, etc.) and posts it as a Discord attachment. For files on a host, use post_file.
[affordances: cost=medium risk=low latency=seconds]
| Name | Type | Required | Description |
|---|---|---|---|
filename | string | Yes | Filename with extension (e.g. 'containers.csv', 'report.md', 'deploy.sh') |
content | string | Yes | File content to generate |
caption | string | No | Optional message to include with the file |
schedule_task
Core: Yes
Schedules a recurring (cron), one-time (run_at), or webhook-triggered task. Use parse_time to convert natural language to run_at. Actions: 'reminder' = post message, 'check' = run_command check, 'digest' = infrastructure digest, 'workflow' = multi-step tool chain.
[affordances: cost=low risk=high latency=fast] (gotchas: workflow steps need populated tool_input with all required fields; run_at must be offset-aware ISO — use parse_time first for natural language)
| Name | Type | Required | Description |
|---|---|---|---|
description | string | Yes | Human-readable description (e.g. 'Daily disk check on server') |
cron | string | No | Cron expression for recurring tasks (e.g. '0 9 * * *' = daily 9am). Omit for one-time. |
cron_timezone | string | No | IANA timezone for the cron expression (e.g. 'America/New_York'). The task fires on that timezone's wall clock across DST. Defaults to UTC. |
run_at | string | No | Offset-aware ISO datetime for one-time tasks (e.g. '2026-03-20T09:00:00Z'). Use parse_time to convert natural language. Omit for recurring. |
trigger | object | No | Webhook trigger (AND logic). E.g. {"source": "github", "event": "push", "repo": "myproject"}. |
trigger.source | string | No | Webhook source to match Constraints: {"enum":["gitea","grafana","generic","github","gitlab"]} |
trigger.event | string | No | Event type (e.g. 'push', 'pull_request', 'alert') |
trigger.repo | string | No | Repository name substring (case-insensitive) |
trigger.alert_name | string | No | Grafana alert name substring (case-insensitive) |
action | string | Yes | 'reminder' = post message, 'check' = run_command check, 'digest' = infrastructure digest, 'workflow' = multi-step tool chain Constraints: {"enum":["reminder","check","digest","workflow"]} |
message | string | No | For reminders: the message to post |
tool_name | string | No | Tool to run for 'check' action (e.g. 'run_command') |
tool_input | object | No | Parameters for the tool (for action='check'). Alternatively use the 'command' and 'host' shortcuts below for run_command. |
report_format | string | No | Optional generic paginated Discord embed renderer for a check result. The command must emit the paginated_embed_v1 JSON contract. Constraints: {"enum":["paginated_embed_v1"]} |
command | string | No | Shortcut: shell command to run (auto-builds tool_input for run_command). Use this instead of nesting inside tool_input. |
host | string | No | Shortcut: target host (default 'localhost'). Paired with 'command' for run_command checks. |
steps | array<object> | No | Workflow steps (sequential). Each step MUST include tool_input populated with that tool's parameters. |
steps[].tool_name | string | Yes | Tool to run |
steps[].tool_input | object | Yes | REQUIRED — parameters for tool_name, e.g. {'host':'localhost','command':'ls'} for run_command |
steps[].description | string | No | Step description |
steps[].condition | string | No | Run if previous output contains this (! to negate) |
steps[].on_failure | string | No | Default: abort Constraints: {"enum":["abort","continue"]} |
list_schedules
Core: Yes
Lists all scheduled tasks with IDs, descriptions, and next run times. To delete, use delete_schedule.
[affordances: cost=low risk=none latency=fast]
No input properties.
update_schedule
Core: Yes
Updates an existing schedule by ID. Only provided fields are changed. Can change description, cron, run_at, trigger, message, tool_name, tool_input, steps, channel_id, report_format, or paused. Changing timing (cron/run_at/trigger) replaces the previous timing mode. Set paused=true to suspend a schedule without deleting it; paused=false to resume.
[affordances: cost=low risk=high latency=fast]
| Name | Type | Required | Description |
|---|---|---|---|
schedule_id | string | Yes | Schedule ID to update (from list_schedules) |
description | string | No | New description |
cron | string | No | New cron expression (replaces previous timing) |
cron_timezone | string | No | IANA timezone for the cron expression (e.g. 'America/New_York'). Defaults to UTC. |
run_at | string | No | New offset-aware ISO datetime for one-time (replaces previous timing) |
trigger | object | No | New webhook trigger (replaces previous timing) |
message | string | No | New message (for reminder actions) |
tool_name | string | No | New tool name (for check actions) |
tool_input | object | No | New tool input parameters |
report_format | string | No | Generic paginated Discord embed renderer for check output; empty string disables structured rendering. Constraints: {"enum":["paginated_embed_v1",""]} |
steps | array<object> | No | New workflow steps |
steps[].tool_name | string | Yes | — |
steps[].tool_input | object | No | — |
steps[].description | string | No | — |
channel_id | string | No | New channel ID for notifications |
paused | boolean | No | Pause (true) or resume (false) the schedule |
delete_schedule
Core: Yes
Deletes a scheduled task by ID. To list schedules first, use list_schedules.
[affordances: cost=low risk=critical latency=fast]
| Name | Type | Required | Description |
|---|---|---|---|
schedule_id | string | Yes | Schedule ID to delete |
parse_time
Core: Yes
Converts natural language time to ISO datetime (e.g. 'in 2 hours', 'tomorrow at 9am', 'next Friday at 3pm'). Uses bot timezone. For schedule_task's run_at parameter.
[affordances: cost=free risk=none latency=instant]
| Name | Type | Required | Description |
|---|---|---|---|
expression | string | Yes | Natural language time (e.g. 'in 2 hours', 'tomorrow at 9am', 'next Friday at 3pm') |
memory_skills
Source: src/tools/defs/memory_skills.py.
search_history
Core: Yes
Searches past conversation history and full channel message logs from all users. Uses keyword, semantic, and FTS matching. Returns '[date] (role): content'. For ingested docs, use search_knowledge. Large results preserve the original returned ranking and whole matches with showing/deferred counts; use get_tool_output(cursor=...) for deferred matches or an oversized match, without re-running search.
[affordances: cost=low risk=none latency=fast]
| Name | Type | Required | Description |
|---|---|---|---|
query | string | Yes | Search query |
limit | integer | No | Max results (default 10) |
memory_manage
Core: Yes
Persistent memory that survives across conversations. 'save'/'get'/'list'/'delete' notes. 'personal' = per-user, 'global' = shared with everyone.
[affordances: cost=low risk=low latency=fast]
| Name | Type | Required | Description |
|---|---|---|---|
action | string | Yes | 'save' a note, 'get' a single note by key, 'list' all notes, or 'delete' a note Constraints: {"enum":["save","get","list","delete"]} |
key | string | No | Short identifier for the note (required for save/get/delete) |
value | string | No | Content to remember (required for save) |
scope | string | No | 'personal' (default, this user only) or 'global' (shared, visible to all) Constraints: {"enum":["personal","global"]} |
search_audit
Core: Yes
Searches audit log of tool executions. Returns '[date] tool_name by user (status, Nms)'. Filterable by tool, user, host, keyword, date, status, errors, duration.
[affordances: cost=low risk=none latency=fast]
| Name | Type | Required | Description |
|---|---|---|---|
tool_name | string | No | Filter by tool name |
user | string | No | Filter by user name or ID |
host | string | No | Filter by host alias |
keyword | string | No | Free-text search across all fields |
date | string | No | Filter by date prefix (e.g. '2026-03-12') |
status | string | No | Filter by status (e.g. 'error', 'success') |
has_error | boolean | No | If true, only return entries with non-empty error fields |
min_duration_ms | integer | No | Only return entries that took at least this many milliseconds |
limit | integer | No | Max results (default 20) |
create_skill
Core: No
Creates a skill (custom tool) from Python code. Available immediately. Define: async def execute(inp: dict, context: SkillContext) -> str SkillContext methods (all async): - run_on_host(alias, cmd), read_file(host, path) - execute_tool(name, input), http_get(url), http_post(url, json=) - post_message(text), post_file(data, filename, caption) - search_knowledge(query), ingest_document(content, source), search_history(query) - remember(key, value), recall(key), schedule_task(...), get_hosts(), log(msg) See data/skills/*.template.
[affordances: risk=high]
| Name | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Skill name (lowercase, underscores only, e.g. 'check_ssl_expiry') |
code | string | Yes | Full Python source code |
edit_skill
Core: No
Replaces the code of an existing skill. Immediately reloaded after edit.
[affordances: risk=high]
| Name | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Skill name to edit |
code | string | Yes | New full Python source code |
delete_skill
Core: No
Deletes a user-created skill. Immediately removed from available tools.
[affordances: cost=low risk=critical latency=fast]
| Name | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Skill name to delete |
list_skills
Core: No
Lists all user-created skills with descriptions, status, and input schemas.
[affordances: cost=low risk=none latency=fast]
No input properties.
enable_skill
Core: No
Re-enables a disabled skill.
[affordances: cost=low risk=low latency=fast]
| Name | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Name of the skill to enable |
disable_skill
Core: No
Disables a skill without deleting it. File preserved.
[affordances: cost=low risk=low latency=fast]
| Name | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Name of the skill to disable |
install_skill
Core: No
Installs a skill from a URL. Downloads the Python file, validates it, and loads it as a new tool.
[affordances: risk=high]
| Name | Type | Required | Description |
|---|---|---|---|
url | string | Yes | URL to a Python skill file (http/https) |
export_skill
Core: No
Exports a skill as a Python file attachment for sharing.
[affordances: cost=low risk=low latency=fast]
| Name | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Name of the skill to export |
skill_status
Core: No
Shows detailed status for a skill: version, author, dependencies, config, execution stats, diagnostics.
[affordances: cost=low risk=none latency=fast]
| Name | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Name of the skill to inspect |
invoke_skill
Core: No
Executes a skill by name, passing the given input dict. Use this to run a skill you just created or edited without waiting for tool-registry cache refresh. Returns the skill's string result. Equivalent to the skill appearing as a direct tool call, but works the same turn it's created. ALWAYS pass the skill's parameters via the 'input' object — top-level fields other than 'name' are ignored. If the skill declares required fields, omitting them will return an error.
[affordances: risk=high] (requires: skill must exist and be enabled) (gotchas: pass skill arguments under input, not at top level; use list_skills first if unsure about parameter names)
| Name | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Skill name to invoke (must already be created and enabled) |
input | object | No | Input dict passed to the skill's execute() — matches the skill's declared input_schema |
tasks_knowledge
Source: src/tools/defs/tasks_knowledge.py.
delegate_task
Core: Yes
Runs a multi-step task in the background, posting progress to Discord. Steps run sequentially with conditions (substring match, ! to negate), on_failure (abort/continue), store_as ({var.name}), {prev_output} substitution. IMPORTANT: each step using run_command MUST have tool_input with 'command' key. Example step: {"tool_name": "run_command", "description": "List files", "tool_input": {"command": "ls -la /tmp"}}. Track with list_tasks, stop with cancel_task.[affordances: cost=high risk=high latency=unbounded] (gotchas: every run_command step needs tool_input.command; steps execute sequentially — use {prev_output} to chain results)
| Name | Type | Required | Description |
|---|---|---|---|
description | string | Yes | Task description |
steps | array<object> | Yes | Ordered tool calls to execute |
steps[].tool_name | string | Yes | Tool to run |
steps[].tool_input | object | No | Input parameters |
steps[].description | string | No | Step description |
steps[].condition | string | No | Run if previous output contains this (prefix ! to negate) |
steps[].on_failure | string | No | Default: abort Constraints: {"enum":["abort","continue"]} |
steps[].store_as | string | No | Save output as named variable |
list_tasks
Core: Yes
Lists background tasks. Without task_id: overview. With task_id: step-by-step details. See delegate_task, cancel_task.
[affordances: cost=low risk=none latency=fast]
| Name | Type | Required | Description |
|---|---|---|---|
task_id | string | No | Task ID for detailed results (omit for overview) |
cancel_task
Core: Yes
Cancels a running background task. Get task IDs from list_tasks.
[affordances: cost=low risk=medium latency=fast]
| Name | Type | Required | Description |
|---|---|---|---|
task_id | string | Yes | Task ID to cancel (from list_tasks) |
search_knowledge
Core: No
Searches ingested knowledge base (docs, runbooks, configs). Returns ranked '[source] (score: N) content'. Search here FIRST before web_search. To add, use ingest_document. To list, use list_knowledge. Large results preserve the original returned ranking and whole matches with showing/deferred counts; use get_tool_output(cursor=...) for deferred matches or an oversized match, without re-running search.
[affordances: cost=low risk=none latency=fast]
| Name | Type | Required | Description |
|---|---|---|---|
query | string | Yes | Search query |
limit | integer | No | Max results (default 5) |
ingest_document
Core: No
Ingests a document into the knowledge base (chunked + embedded for search). Re-ingesting same source replaces previous. For host files, use one complete, untruncated read_file raw=true response and ingest only its framed UTF-8 source content; exclude the metadata envelope, end marker, and continuation cursor; files too large for one raw read are not ingestible through this tool. Search with search_knowledge.
[affordances: cost=high risk=medium latency=seconds]
| Name | Type | Required | Description |
|---|---|---|---|
source | string | Yes | Document identifier (e.g. 'ansible/roles/apache/README.md', 'server-runbook') |
content | string | Yes | Document text content |
bulk_ingest_knowledge
Core: No
Bulk-import documents into the knowledge base. Accepts a list of items: directories or individual markdown/text files, PDF URLs, or web page URLs. Each item needs a type ('directory', 'file', 'pdf', or 'url') plus type-specific params.[affordances: cost=high risk=medium latency=minutes]
| Name | Type | Required | Description |
|---|---|---|---|
items | array<object> | Yes | Import jobs. Each object needs 'type' plus: directory → 'path' (+ optional 'pattern', default '**/*.md'); file → 'path'; pdf → 'url' (+ optional 'source'); url → 'url' (+ optional 'source') |
items[].type | string | Yes | Constraints: {"enum":["directory","file","pdf","url"]} |
items[].path | string | No | — |
items[].url | string | No | — |
items[].source | string | No | — |
items[].pattern | string | No | — |
list_knowledge
Core: No
Lists all knowledge base documents with source names and chunk counts. To search, use search_knowledge. To remove, use delete_knowledge.
[affordances: cost=low risk=none latency=fast]
No input properties.
delete_knowledge
Core: No
Removes a document from the knowledge base by source name. To list sources first, use list_knowledge.
[affordances: cost=low risk=critical latency=fast]
| Name | Type | Required | Description |
|---|---|---|---|
source | string | Yes | Source name to remove |
browser_web
Source: src/tools/defs/browser_web.py.
browser_screenshot
Core: No
Takes a screenshot of a URL (renders JavaScript) and posts to Discord. Works on dashboards, SPAs, and dynamic pages unlike fetch_url. For text, use browser_read_page.
[affordances: cost=high risk=low latency=seconds] (requires: browser enabled; installed Chromium or reachable configured CDP endpoint)
| Name | Type | Required | Description |
|---|---|---|---|
url | string | Yes | URL to screenshot |
full_page | boolean | No | Capture full scrollable page (default false = viewport only) |
wait_seconds | integer | No | Extra wait after page load for dynamic content (default 0, max 10) |
browser_read_page
Core: No
Reads a URL's text content (renders JavaScript). Returns 'Title (url)\n\ntext'. Works on SPAs/dynamic pages unlike fetch_url. Scope via CSS selector. For tables, use browser_read_table. For screenshots, use browser_screenshot. Large results have retained previews; use get_tool_output(cursor=...) without reloading the page.
[affordances: cost=high risk=low latency=seconds] (requires: browser enabled; installed Chromium or reachable configured CDP endpoint)
| Name | Type | Required | Description |
|---|---|---|---|
url | string | Yes | URL to read |
selector | string | No | CSS selector to scope extraction (e.g. '#main-content', '.results') |
wait_seconds | integer | No | Extra wait for dynamic content (default 0, max 10) |
max_chars | integer | No | Legacy direct-helper text limit (default 16000, max 32000); retained tool delivery uses the shared preview budget. |
browser_read_table
Core: No
Extracts an HTML table from a URL as markdown (| col | col |). Renders JavaScript. For text, use browser_read_page. Large tables have retained previews; use get_tool_output(cursor=...) without reloading the page.
[affordances: cost=high risk=low latency=seconds] (requires: browser enabled; installed Chromium or reachable configured CDP endpoint)
| Name | Type | Required | Description |
|---|---|---|---|
url | string | Yes | URL containing the table |
table_index | integer | No | Which table to extract (0-based, default 0 = first table) |
wait_seconds | integer | No | Extra wait for dynamic content (default 0, max 10) |
browser_click
Core: No
Navigates to a URL and clicks an element by CSS selector. Returns a confirmation summary after clicking. To fill forms, use browser_fill. To read page content after clicking, follow up with browser_read_page.
[affordances: cost=high risk=high latency=seconds] (requires: browser enabled; installed Chromium or reachable configured CDP endpoint)
| Name | Type | Required | Description |
|---|---|---|---|
url | string | Yes | URL to navigate to |
selector | string | Yes | CSS selector to click (e.g. '#login-btn', 'button.submit') |
wait_seconds | integer | No | Extra wait before clicking (default 0, max 10) |
browser_fill
Core: No
Navigates to a URL and fills a form field by CSS selector. Optionally submits by pressing Enter. To click buttons, use browser_click.
[affordances: cost=high risk=high latency=seconds] (requires: browser enabled; installed Chromium or reachable configured CDP endpoint)
| Name | Type | Required | Description |
|---|---|---|---|
url | string | Yes | URL to navigate to |
selector | string | Yes | CSS selector of the input (e.g. '#username', 'input[name=password]') |
value | string | Yes | Text to fill |
submit | boolean | No | Press Enter after filling (default false) |
browser_evaluate
Core: No
Evaluates JavaScript on a URL and returns the result. For custom scraping or interaction. Large results have retained previews; use get_tool_output(cursor=...) without re-running the expression.
[affordances: cost=high risk=high latency=seconds] (requires: browser enabled; installed Chromium or reachable configured CDP endpoint)
| Name | Type | Required | Description |
|---|---|---|---|
url | string | Yes | URL to navigate to |
expression | string | Yes | JavaScript expression (e.g. 'document.title', 'document.querySelectorAll("a").length') |
wait_seconds | integer | No | Extra wait before evaluating (default 0, max 10) |
web_search
Core: No
Searches the web via DuckDuckGo. Returns 'N. title\nurl\nsnippet' (max 10). For full content, use fetch_url or browser_read_page.
[affordances: cost=medium risk=none latency=seconds]
| Name | Type | Required | Description |
|---|---|---|---|
query | string | Yes | Search query |
max_results | integer | No | Max results (default 5, max 10) |
fetch_url
Core: No
Fetches a URL and returns text (HTML→readable text, JSON passed through). Static only — for JS-rendered pages use browser_read_page. Large results have retained previews; use get_tool_output(cursor=...) without fetching again.
[affordances: cost=medium risk=none latency=seconds]
| Name | Type | Required | Description |
|---|---|---|---|
url | string | Yes | URL to fetch |
set_permission
Core: No
Sets a Discord user's permission tier. Admin-only. Tiers: admin (full access), user (read-only), guest (chat only).
[affordances: cost=low risk=high latency=fast]
| Name | Type | Required | Description |
|---|---|---|---|
user_id | string | Yes | Discord user ID (numeric string, e.g. '123456789012345678') |
tier | string | Yes | Permission tier Constraints: {"enum":["admin","user","guest"]} |
analyze_pdf
Core: No
Extracts text from a PDF (URL or host:path). Returns markdown text; large results have retained previews and get_tool_output(cursor=...) continuation. For image-heavy PDFs, use browser_screenshot.
[affordances: cost=high risk=none latency=seconds]
| Name | Type | Required | Description |
|---|---|---|---|
url | string | No | URL to fetch PDF from |
host | string | No | Host alias for file-based PDF |
path | string | No | File path on host |
pages | string | No | Page range, e.g. '1-5' or '3' (default: all) |
channel_process_loops
Source: src/tools/defs/channel_process_loops.py.
read_channel
Core: No
Reads recent messages from the CURRENT Discord channel into your context. Returns channel history from ALL users and bots. Do NOT pass channel_id — omit it to read the channel the message came from. The returned messages are for YOUR eyes only — do NOT paste or echo them. Read, understand, then respond with your own summary, analysis, or action.
[affordances: cost=medium risk=none latency=fast]
| Name | Type | Required | Description |
|---|---|---|---|
limit | integer | No | Number of messages to read (default 10, max 100) |
channel_id | string | No | Numeric channel ID. Omit to use current channel (recommended). |
add_reaction
Core: No
Adds an emoji reaction to a message. Unicode emoji or custom format (<:name:id>).
[affordances: cost=medium risk=low latency=fast]
| Name | Type | Required | Description |
|---|---|---|---|
message_id | string | Yes | Discord message ID to react to |
emoji | string | Yes | Emoji to react with |
create_poll
Core: No
Creates a Discord native poll in the current channel. Max 10 options. Duration in hours (default 24, max 168/7 days).
[affordances: cost=medium risk=low latency=fast]
| Name | Type | Required | Description |
|---|---|---|---|
question | string | Yes | The poll question |
options | array<string> | Yes | List of answer options (max 10) |
duration_hours | integer | No | Poll duration in hours (default 24) |
multiple | boolean | No | Allow multiple selections (default false) |
manage_process
Core: Yes
Manages local or remote background processes (start/poll/write/kill/list). Start spawns a detached command on the selected managed host and returns PID. Poll defaults to newest 50 lines, with emitted/retained/shown-byte and capture-loss metadata. Offset 0, blank, null, or omitted means the newest-lines status view, not a page read. Use the preview's generation:0 cursor to read from the beginning, or offset >= 1 for a byte range. Use the returned cursor and limit (default 4000, 4-8000 UTF-8 bytes) for repeatable retained-output pages; follow cursor until truncated=false. A non-empty cursor takes precedence over offset. Reads never consume another reader's output. Local and remote capture retain at most 4 MiB. Output stays read-only for 24 hours after exit; access is rechecked on every read. Write sends stdin; Kill verifies process-group termination. Max 20 concurrent, auto-killed after 1hr. When monitoring a long-running process (build, test suite, download), poll with wait_seconds (60 is a good default) — one call waits server-side until exit or the deadline, instead of many rapid polls. Keep long-job output observable: stream stdout/stderr, or use bash with pipefail and tee to also save a log. Redirection alone hides progress. Silence is not proof of a hang; bounded slow polling is allowed until the original one-hour process deadline, not indefinitely.
[affordances: cost=low risk=high latency=unbounded]
| Name | Type | Required | Description |
|---|---|---|---|
action | string | Yes | Action to perform Constraints: {"enum":["start","poll","write","kill","list"]} |
host | string | No | Host alias (required for start) |
command | string | No | Shell command to run (required for start) |
pid | integer | No | Process ID (required for poll, write, kill) |
input_text | string | No | Text to send to stdin (required for write) |
wait_seconds | number | No | Poll only: wait up to this many seconds (0-120) for the process to exit before reporting. 0 (default) reports immediately. Exit ends the wait early. |
cursor | string | No | Poll only: opaque job-generation output cursor; a non-empty cursor takes precedence over offset; blank means no cursor. Use the preview's generation:0 cursor to read from the beginning. |
offset | integer | No | Poll only: retained-output UTF-8 byte offset (>= 1 for an explicit range). 0, blank, null, or omitted means the newest-lines status view; ignored when cursor is non-empty. Read from the beginning with the preview's generation:0 cursor. Constraints: {"minimum":0} |
limit | integer | No | Poll page maximum UTF-8 bytes (default 4000); complete envelope may reduce the page. Constraints: {"minimum":4,"maximum":8000} |
manage_list
Core: Yes
Manages named lists (grocery, todo, shopping, etc.). Created on first add. 'personal' = private, 'shared' = visible to all. Supports mark_done/mark_undone.
[affordances: cost=low risk=low latency=fast]
| Name | Type | Required | Description |
|---|---|---|---|
action | string | Yes | 'list_all' shows all lists. Other actions operate on a specific list_name. Constraints: {"enum":["add","remove","show","clear","mark_done","mark_undone","list_all"]} |
list_name | string | No | List name (e.g. 'grocery', 'todo', 'hardware store'). Required for all actions except list_all. |
items | array<string> | No | Item(s) to add, remove, or mark. |
owner | string | No | 'personal' = this user only, 'shared' = everyone (default). Only applies on first add (list creation). Constraints: {"enum":["personal","shared"]} |
analyze_image
Core: No
Analyzes an image from URL or host path. Returns text description. For web page screenshots, use browser_screenshot.
[affordances: cost=high risk=none latency=seconds]
| Name | Type | Required | Description |
|---|---|---|---|
url | string | No | URL of the image |
host | string | No | Host alias for file-based image |
path | string | No | File path on host |
prompt | string | No | What to look for (default: describe the image) |
start_loop
Core: No
Starts an autonomous loop. Each iteration triggers a full LLM reasoning cycle with all tools. Use for monitoring, game playing, event watching, periodic updates. Returns loop ID. Check with list_loops, stop with stop_loop.
[affordances: cost=very_high risk=high latency=unbounded]
| Name | Type | Required | Description |
|---|---|---|---|
goal | string | Yes | Goal for each iteration (be specific). E.g. 'Monitor disk usage, warn if above 80%' or 'Watch /tmp/events.log, summarize new entries' |
interval_seconds | integer | No | Seconds between iterations (default: 60, min: 10) |
mode | string | No | notify = report always, act = act + report, silent = act, report only if notable Constraints: {"enum":["notify","act","silent"]} |
stop_condition | string | No | Auto-stop condition, e.g. 'when disk below 50%' or 'after 5 iterations'. Evaluated each cycle. |
max_iterations | integer | No | Hard max iterations before auto-stop (default: 50) |
stop_loop
Core: No
Stops an autonomous loop by ID. Use 'all' to stop all loops. To list loops first, use list_loops.
[affordances: cost=low risk=medium latency=fast]
| Name | Type | Required | Description |
|---|---|---|---|
loop_id | string | Yes | Loop ID to stop, or 'all' |
list_loops
Core: No
Lists all autonomous loops with status, iterations, and last activity. To create, use start_loop. To stop, use stop_loop.
[affordances: cost=low risk=none latency=fast]
No input properties.
agents
Source: src/tools/defs/agents.py.
spawn_agent
Core: No
Spawns an autonomous agent for a sub-task. Runs silently in background with isolated context; it may spawn its own sub-agents up to the nesting limit. Results are NOT posted to Discord — use wait_for_agents to collect results, then deliver a cohesive summary yourself. Max 5/channel; lifetime limit for NEW agents: 14400 seconds. Budget warnings injected near iteration limit. Set 'model' to run THIS agent on a specific Codex model — gpt-6-astra (flagship: deepest reasoning for the hardest, highest-stakes work; the most expensive GPT-6 tier; rejects effort 'none'), gpt-6-sol (balanced default: complex coding and agentic work at near-Astra reliability, and cheaper than gpt-5.6-terra), gpt-6-luna (cheapest GPT-6: focused, high-volume work with a clear goal; raise effort before escalating), gpt-5.6-sol (previous generation; gpt-6-sol is stronger and cheaper, so use it only as a fallback), gpt-5.6-terra (previous-generation mid tier; costs more than gpt-6-sol, so use it only as a fallback), gpt-5.6-luna (previous-generation small tier; gpt-6-luna is stronger and cheaper, so use it only as a fallback); match the tier to the task. A model selection is required. Set 'reasoning_effort' (none/low/medium/high/xhigh/max) for THIS agent — higher is more thorough but slower/costlier. Omit to use the configured agent effort.
[affordances: cost=very_high risk=high latency=unbounded] (requires: agent tool enabled)
| Name | Type | Required | Description |
|---|---|---|---|
label | string | Yes | Short name (e.g. 'disk-audit') |
goal | string | Yes | Full task description for the agent |
model | string | Yes | Required Codex model for this agent. gpt-6-astra = flagship: deepest reasoning for the hardest, highest-stakes work; the most expensive GPT-6 tier; rejects effort 'none'; gpt-6-sol = balanced default: complex coding and agentic work at near-Astra reliability, and cheaper than gpt-5.6-terra; gpt-6-luna = cheapest GPT-6: focused, high-volume work with a clear goal; raise effort before escalating; gpt-5.6-sol = previous generation; gpt-6-sol is stronger and cheaper, so use it only as a fallback; gpt-5.6-terra = previous-generation mid tier; costs more than gpt-6-sol, so use it only as a fallback; gpt-5.6-luna = previous-generation small tier; gpt-6-luna is stronger and cheaper, so use it only as a fallback. Choose a model explicitly. |
reasoning_effort | string | No | Optional reasoning effort for this agent — higher is more thorough but slower/costlier. Omit to inherit the configured agent effort. Constraints: {"enum":["none","low","medium","high","xhigh","max"]} |
parent_id | string | No | Parent agent ID for nested spawns (optional, set automatically when spawning from within an agent) |
send_to_agent
Core: No
Queues a message to a running agent for its next safe boundary. Wakes an agent waiting for children; does not cancel ordinary tools. Acknowledges queued, not consumed. Use for instructions, data, or corrections.
[affordances: cost=low risk=high latency=fast] (requires: target agent exists and is running)
| Name | Type | Required | Description |
|---|---|---|---|
agent_id | string | Yes | Agent ID (from spawn_agent) |
message | string | Yes | Message text to inject |
list_agents
Core: No
Lists all agents with status, iteration count, and runtime. Shows running, completed, failed, and timed-out agents.
[affordances: cost=low risk=none latency=fast]
No input properties.
kill_agent
Core: No
Terminates a running agent immediately. Agent status set to 'killed'.
[affordances: cost=low risk=critical latency=fast]
| Name | Type | Required | Description |
|---|---|---|---|
agent_id | string | Yes | Agent ID to kill |
get_agent_results
Core: No
Returns the final results of a completed/failed agent. Returns result pages with UTF-8 byte length, preview, truncation flag and continuation cursor, tools used, iteration count, and runtime. Repeat with cursor for complete output. Retained after live registry cleanup. Returns 'still running' if active.
[affordances: cost=low risk=none latency=fast]
| Name | Type | Required | Description |
|---|---|---|---|
agent_id | string | Yes | Agent ID |
cursor | string | No | Continuation from previous page |
limit | integer | No | UTF-8 byte ceiling per page (default 4000, max 8000); may be smaller to fit serialized delivery budget Constraints: {"minimum":4,"maximum":8000} |
wait_for_agents
Core: No
Waits for one or more agents to complete. Essential for fan-out (spawn N agents → wait → collect results) and pipeline (spawn A → wait → spawn B with A's output) coordination patterns. Returns a snapshot for every requested agent once all finish or timeout. Returns status snapshots with up to 800 UTF-8 bytes of result preview per agent, possibly less under the aggregate budget. Use get_agent_results and follow its cursor until truncated=false for complete output. Inside an agent, a parent message interrupts the wait; children continue.
[affordances: cost=low risk=none latency=minutes]
| Name | Type | Required | Description |
|---|---|---|---|
agent_ids | array<string> | Yes | Agent IDs to wait for |
timeout | number | No | Max seconds to wait (default 300) |
integrations_email
Source: src/tools/defs/integrations_email.py.
http_probe
Core: No
Probe an HTTP/HTTPS endpoint with timing, retries, and full response capture. Useful for API debugging, health checks, and latency measurement. Runs curl on a managed host (or locally if host omitted). Returns response headers, body, status code, and timing breakdown (DNS, connect, TLS, TTFB, total).
[affordances: cost=medium risk=high latency=seconds]
| Name | Type | Required | Description |
|---|---|---|---|
url | string | Yes | URL to probe (http or https) |
host | string | No | Host alias to run curl from (omit to run locally) |
method | string | No | HTTP method (default GET) Constraints: {"enum":["GET","POST","PUT","DELETE","PATCH","HEAD","OPTIONS"]} |
headers | object | No | Request headers as key-value pairs (e.g. {"Authorization": "Bearer tok"}) |
body | string | No | Request body string (for POST/PUT/PATCH). Max 50KB. |
timeout | integer | No | Request timeout in seconds (default 30, max 120) |
follow_redirects | boolean | No | Follow HTTP redirects (default true) |
verify_ssl | boolean | No | Verify SSL certificates (default true) |
retries | integer | No | Number of retries on failure (default 0, max 5) |
retry_delay | integer | No | Delay between retries in seconds (default 1, max 30) |
generate_image
Core: No
Generates an image from a text prompt with the native OpenAI image backend and posts it to Discord. Output dimensions and aspect ratio are selected by the provider.
[affordances: cost=very_high risk=low latency=minutes] (requires: Codex provider active; native image generation enabled; usable credentials)
| Name | Type | Required | Description |
|---|---|---|---|
prompt | string | Yes | Text description of the image to generate |
validate_action
Core: Yes
Runs a bundle of validation checks after an operational change (deploy, restart, config push, migration) to confirm the system is actually healthy — not just that the preceding commands returned exit 0. Checks run concurrently on managed hosts. Never blocks; verdict is informational. Verdict: 'pass' (all OK), 'degraded' (only warn-severity failures), 'fail' (≥1 critical failure), 'error' (every check errored — likely config issue). ALWAYS call this automatically after deploys, service restarts, container replacements, compose up/down, config writes to running services, firewall changes, DNS updates, schema migrations — do not wait to be asked.
Check types:
http target=URL, expected=status code or list (default [200,201,204,301,302,307,308])
port target='host:port' or just 'port' (implies 127.0.0.1)
service target=systemd unit name, expected='active' or list of states
process target=pgrep pattern
log_absent target='unit=NAME:PATTERN' or plain regex — passes if pattern NOT found
log_present same target format — passes if pattern IS found
command target=shell command, compare='exit_zero'|'exit_nonzero'|'contains'|'not_contains'|'equals'|'regex_match'
Each check: {type, target, severity?, host?, expected?, compare?, window_seconds?, timeout_seconds?, name?}.
Severity 'critical' (default), 'warn', or 'info'. Only critical failures flip verdict to 'fail'.[affordances: cost=high risk=high latency=seconds] (requires: validation checks reference reachable hosts) (gotchas: command checks execute real commands)
| Name | Type | Required | Description |
|---|---|---|---|
bundle_name | string | No | Short label for this bundle (e.g. 'after_nginx_restart') |
default_host | string | No | Host alias used for any check without an explicit 'host'. Uses the requester's explicit default-host policy when omitted. |
grace_seconds | integer | No | Optional wait before running checks (0-60), to let services settle. |
max_parallel | integer | No | Max concurrent checks within this bundle (default 12, cap 25). Use a lower value when validating against a resource-constrained host. |
format | string | No | Output format: 'summary' (human-readable, default) or 'json' (full structured report). |
checks | array<object> | Yes | List of validation checks (max 25). |
checks[].type | string | Yes | http|port|service|process|log_absent|log_present|command |
checks[].target | string | Yes | — |
checks[].expected | any | No | Type-specific expectation (int, string, list) |
checks[].severity | string | No | critical (default) | warn | info |
checks[].host | string | No | — |
checks[].compare | string | No | — |
checks[].window_seconds | integer | No | — |
checks[].timeout_seconds | integer | No | — |
checks[].name | string | No | — |
email_send
Core: No
Send an email via SMTP. Returns the sent message ID and recipient list. Supports plain-text body, CC/BCC, reply-to, and file attachments from allowed directories.
[affordances: cost=medium risk=high latency=seconds] (requires: email.enabled; SMTP credentials configured)
| Name | Type | Required | Description |
|---|---|---|---|
to | array<string> | Yes | Recipient email addresses |
subject | string | Yes | Email subject line |
body | string | Yes | Plain-text email body |
cc | array<string> | No | CC recipients (optional) |
bcc | array<string> | No | BCC recipients (optional) |
reply_to | string | No | Reply-To address (optional) |
attachments | array<string> | No | File paths to attach (must be within allowed_attachment_dirs) |
email_search
Core: No
Search email via IMAP. On Gmail, uses native Gmail search syntax (e.g. 'from:alice newer_than:7d has:attachment subject:invoice'). On other providers, uses standard IMAP SEARCH criteria (e.g. 'FROM "alice" SINCE 01-Jun-2026'). Returns message summaries.
[affordances: cost=high risk=none latency=seconds] (requires: email.enabled; IMAP credentials configured)
| Name | Type | Required | Description |
|---|---|---|---|
query | string | Yes | Search query |
folder | string | No | Mailbox folder (default: INBOX) |
limit | integer | No | Max results to return (default: 20) |
email_read
Core: No
Read a specific email by UID. Returns full headers, plain-text body (truncated to configured limit), and attachment metadata. Use email_search or email_list_recent to find UIDs first.
[affordances: cost=medium risk=none latency=seconds] (requires: email.enabled; IMAP credentials configured)
| Name | Type | Required | Description |
|---|---|---|---|
uid | string | Yes | Message UID from search/list results |
folder | string | No | Mailbox folder (default: INBOX) |
email_list_recent
Core: No
List the most recent emails in a folder. Returns summaries with sender, subject, date, size, and flags. Use email_read for full content.
[affordances: cost=high risk=none latency=seconds] (requires: email.enabled; IMAP credentials configured)
| Name | Type | Required | Description |
|---|---|---|---|
folder | string | No | Mailbox folder (default: INBOX) |
limit | integer | No | Number of recent messages (default: 10) |
output_delivery
Source: src/tools/defs/output_delivery.py.
get_tool_output
Core: No
Read retained tool evidence without re-running its tool. Follow cursor until truncated=false. Pages are contiguous head-only; initial labelled tails are context only. Evidence expires 24 hours after capture (fixed TTL), with per-result/global quotas. Original caller, channel, tool permission and host scope are rechecked; a cursor is not permission. Binary attachments return data_base64 pages with byte offsets, MIME and SHA-256; decode each page and concatenate bytes in order. No audio understanding. For process spools use the returned manage_process retrieval arguments instead.
[affordances: cost=low risk=none latency=fast]
| Name | Type | Required | Description |
|---|---|---|---|
cursor | string | Yes | Exact cursor returned by tool output delivery. |
limit | integer | No | Maximum text/base64 characters; envelope budget may yield fewer. Constraints: {"minimum":4,"maximum":8000,"default":4000} |