Custom tools
A custom tool turns any shell command into something the agent can
call. No TypeScript needed. Add a block under custom_tools: in
config.yaml, save, and the new tool is available on the next message
(hot reload).
Anatomy
custom_tools:
hn_top:
description: Fetch top Hacker News stories.
command: |
curl -s 'https://hacker-news.firebaseio.com/v0/topstories.json' \
| jq -r '.[0:{{limit}}][]' \
| while read -r id; do
curl -s "https://hacker-news.firebaseio.com/v0/item/${id}.json"
done \
| jq -rs '.[] | "\(.title // empty)\n\(.url // empty)\n"'
parameters:
limit:
type: integer
description: Number of stories to fetch.
default: 5
That's it. The agent now has a tool named hn_top that takes limit,
runs the shell command, and returns stdout.
TAI wraps the YAML block as a Tool and registers it the same way as
the built-ins. {{limit}} in the command is substituted with the
argument value before the shell runs.
Adding the tool to an agent
By default a custom tool is available but not in any agent's allowlist. Add it to the agents that should be allowed to call it:
agents:
researcher:
tools: [web_search, web_fetch, hn_top, memory]
If an agent's tools: is omitted or empty, all enabled tools (custom
included) are available.
Parameter types
parameters:
query:
type: string
description: The search term.
limit:
type: integer
description: Max results.
default: 10
recent_only:
type: boolean
description: Filter to recent items.
default: false
tags:
type: array
items: { type: string }
description: Tags to filter by.
List required parameters under required: [...]. Anything not in
required with a default: is substituted when the agent omits the
argument.
Working examples
The repo's
config.example.yaml
ships a handful of small custom tools to crib from: hn_top, weather,
git_log, ip_info, uptime, current_datetime.
Security
Custom tools run with the privileges of the agent process. Don't
include unsubstituted user input in commands. The {{}} substitution
shell-escapes arguments. Direct string concatenation in the YAML body
is unsafe.
For stronger isolation, run TAI in a sandbox (see Architecture → Sandboxes) or restrict the agent's tool list.
When YAML isn't enough
YAML custom tools are right for "wrap a shell command." If you need:
- Stateful tools (talk to an SDK, hold a connection)
- Tools that share types with TAI's runtime
- Tools that call other tools or query the runtime
…write a TypeScript tool. See Extending in code.
For sharing tools across projects or with the community, see Plugins.