Skip to content

Tools overview

How tools are registered, config-gated, and assembled into the agent registry, plus i18n descriptions.

Tools are the callable capabilities Revka exposes to the LLM during agentic loops — shell execution, file editing, web fetch, cron scheduling, code-agent delegation, MCP bridging, and roughly ninety more. This page explains how a tool is registered, how the registry is assembled at startup, how individual tools are gated by config, and how their descriptions are localized.

Read this page when you want to understand why a tool is or isn’t available to your agent, or how to turn one on. For the behavior and parameters of specific tools, see the tool reference pages linked at the bottom.

Every tool implements a common Tool trait with three stable parts:

  • a name (e.g. shell, web_fetch) — the identifier the model uses to call it,
  • a JSON parameter schema describing its arguments, and
  • an async execute method that runs the tool and returns a result.

At startup Revka builds a registry — a Vec of boxed tools — and hands it to the agent loop. The model sees each tool’s name, description, and parameter schema; when it emits a tool call, the loop dispatches to the matching tool’s execute. Security-policy enforcement is injected into each tool at construction time, so autonomy level, command allowlists, and path boundaries are applied uniformly rather than re-checked per call site.

Two registry builders exist:

  • default_tools — the minimal registry (no config, no runtime integrations).
  • all_tools_with_runtime — the full registry used in production, which starts from the always-on core and then conditionally adds tools based on your config.

The minimal registry contains exactly 7 tools, all filesystem and code primitives:

ToolPurpose
shellExecute a shell command in the workspace
file_readRead a file with line numbers (offset/limit, inline PDF text)
file_writeWrite (overwrite) a file in the workspace
file_editReplace the first exact-match string in a file
glob_searchList files matching a glob pattern
content_searchSearch file contents by regex (ripgrep with grep fallback)
semantic_code_searchToken-efficient code search (Semble → ripgrep → literal)

This set is what you get with no integrations enabled. It is also the baseline that the full registry builds on.

all_tools_with_runtime is the registry Revka actually runs. It begins with an always-registered core — the seven minimal tools plus a set of tools that have no enable flag — and then appends everything else conditionally. The always-on core additionally includes the cron tools (cron_add, cron_list, cron_remove, cron_update, cron_run, cron_runs), schedule, git_operations, pushover, calculator, weather, canvas, model_routing_config, model_switch, proxy_config, and llm_task (registered whenever a provider is configured).

Everything beyond that core — browser, HTTP, web search, SOP execution, code-agent delegation, swarms, productivity integrations, hardware, and MCP bridging — is config-gated: it appears in the registry only when you turn it on.

Config gating is how the full registry decides what to include. For each optional tool, the builder checks a flag (and any required credentials) before pushing the tool into the registry. The common pattern is an enabled boolean under the tool’s config section:

[browser]
enabled = true
allowed_domains = ["docs.example.com"]
[http_request]
enabled = true
allowed_domains = ["api.example.com"]
[web_fetch]
enabled = true
[web_search]
enabled = true
provider = "brave"

With those set, browser/browser_open, http_request, web_fetch, and web_search_tool are registered. Leave a section out (or set enabled = false) and the tool simply never appears — the model has no way to call a tool that isn’t in the registry.

Gating has a few important wrinkles:

  • Credentials are part of the gate. Some tools are enabled and require a key. For example, notion.enabled = true still skips registration (with a warning) if neither notion.api_key nor the NOTION_API_KEY env var is set. The same applies to jira (token + base_url + email).
  • Runtime capability is part of the gate. Tools that shell out — such as browser_delegate — are skipped (with a warning) when the active runtime doesn’t allow shell access, even if enabled = true.
  • Config selects variants, not just on/off. A flag can change which tool registers. With skills.prompt_injection_mode = "compact", the read_skill tool is added so the model can pull full skill text on demand; in full mode it isn’t.
  • Presence-based gating. Some tools key off the existence of a config block rather than an enabled flag — delegate registers when at least one [agents.<name>] block exists, and swarm registers when at least one [swarms.<name>] block exists.

A quick map of common gates (see the per-tool pages for the full list):

Tool(s)Gate
browser, browser_openbrowser.enabled = true
browser_delegatebrowser_delegate.enabled = true + shell access
text_browsertext_browser.enabled = true
http_requesthttp_request.enabled = true
web_fetchweb_fetch.enabled = true
web_search_toolweb_search.enabled = true
notion, jira, linkedin, etc.section enabled = true + credentials
cloud_ops, cloud_patternscloud_ops.enabled = true
sop_*sop.sops_dir configured
delegateone or more [agents.<name>]
swarmone or more [swarms.<name>]
read_skillskills.prompt_injection_mode = "compact"
external MCP tools[mcp] enabled = true + [[mcp.servers]]

The shell tool is always present, but its execution behavior is tunable through the [shell_tool] section:

[shell_tool]
timeout_secs = 60
KeyTypeDefaultMeaning
timeout_secsinteger60Maximum wall-clock time a single shell command may run before it is killed

Beyond [shell_tool], the shell tool’s output is capped at 1 MB, and its environment is sanitized to a safe allowlist (PATH, HOME, TERM, and similar). Scripts that depend on custom environment variables must either add them to security.shell_env_passthrough or pass them inline on the command. The command argument runs the command; the optional approved boolean (default false) explicitly approves medium/high-risk commands in supervised mode.

What the shell tool is allowed to do — command allowlists, path boundaries, risk gating, and approval — is governed separately by the [autonomy] security policy, not by [shell_tool]. See Policy, commands & sandboxing and the Security model.

Tool descriptions — the text the model reads to decide when to use a tool — can be localized. Locale-specific descriptions live in TOML files under tool_descriptions/, one file per locale (en.toml, de.toml, fr.toml, ja.toml, ko.toml, zh-CN.toml, and many more). Each file has a [tools] table whose keys match tool names:

tool_descriptions/en.toml
[tools]
file_read = "Read file contents with line numbers. Supports partial reading via offset and limit."
glob_search = "Search for files matching a glob pattern within the workspace."

Revka picks the active locale in this order:

  1. locale config field — if config.locale is set and non-empty, it is used directly.

  2. Environment detection — otherwise Revka detects the locale from REVKA_LOCALE, then LANG, then LC_ALL. Values are normalized (e.g. zh_CN.UTF-8zh-CN); C/POSIX are ignored.

  3. English default — if nothing resolves, the locale is en.

Loading is resilient at the key level, not just the file level:

  1. The tool name is looked up in the resolved locale file.
  2. If that file is missing the key (or the file is absent entirely), the lookup falls back to en.toml.

So a partially translated locale still works — translated tools get the localized description, and anything not yet translated falls back to English rather than going blank.

Revka searches several directories for tool_descriptions/<locale>.toml, in order:

  1. the workspace directory (for project-local overrides),
  2. the binary’s parent directory (for installed distributions), and
  3. the project root (a dev-time fallback).

Because the workspace is checked first, you can drop a customized tool_descriptions/<locale>.toml into your workspace to override the shipped descriptions for your deployment.