Tools are how the agent reaches outside its own context. Without tools, the model can write text. With tools, it can read files, run code, search the web, query a database, send a Slack message — anything you’ve given it the ability to do. This page covers what tools look like to the agent, what they look like to you, and the patterns that work.Documentation Index
Fetch the complete documentation index at: https://internal.september.wtf/llms.txt
Use this file to discover all available pages before exploring further.
Where tools come from
The agent sees three kinds of tools, but they all look the same from its point of view:- Platform tools — built into the Engine:
read_file,write_file,bash,grep,web_search, etc. Run inside the sandbox. - MCP tools — surfaced from external servers connected via the
Asset Directory. Each connected
server contributes a set of actions (e.g.
slack.send_message,gmail.read_thread). - Skills used as tools — your custom skills, registered in the Engine’s skill catalog, can be invoked as tools. Useful when you want to wrap a recurring prompt-plus-script behavior.
slack.send_message is built-in, MCP, or
a wrapped skill.
The lifecycle of one tool call
Steps 2–6 happen on the server. Step 3 only fires if the static rules say the operation needs explicit user permission — see Permissions.What a tool looks like to the model
A tool is declared with three things:What a tool call looks like in the SSE stream
error is set and output may be empty. The error
feeds back into context. The model can decide to retry, ask the user, or
give up — that’s its call, not the Engine’s.
Concurrency
The Engine runs tool calls in parallel up toCLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY (default 10). When the model
emits multiple tool calls in one block, they fire concurrently. Order in
the response is preserved.
Two implications:
- Tools must be safe to run in any order. If
tool Aandtool Bare emitted together, the Engine runs them simultaneously. If they touch the same resource, expect races. - Errors are independent. One tool failing doesn’t cancel the others. The model gets all results back together.
Defining a custom tool
You define a tool by adding an entry to the Engine’s catalog. The catalog lives atcatalog/ in the engine repo (or wherever CATALOG_DIR points).
A tool entry is a JSON file:
POST /admin/reload-catalog — no restart needed.
For MCP-served tools, you don’t define them in the catalog. The user
connects the MCP server through /assets/connect and the server’s
actions are auto-registered.
Tool descriptions: what works
The model uses the description to decide when to call the tool. A good description:- States the action plainly. “Send a Slack message to a channel.”
- Names the inputs and what they mean. “
channel: the Slack channel ID (starts withC).text: the message body, plain text or markdown.” - Names the output. “Returns the timestamp of the posted message, which can be used to thread replies.”
- Hints when to use it. “Use this to notify a team or share a quick
update. Don’t use it for direct messages — use
slack.send_dminstead.” - Hints when not to use it. Critical. The model will pick this tool over a similar one if the description is more specific about context.
- Marketing language. “Powerful tool for communication.”
- Vague. “Send a message.”
- Mismatched. Description says “send to a channel”; schema requires a user ID.
Patterns
Read-then-act
The model often reads context (grep, read_file, web_search) before
acting (write_file, bash). Give the agent both. Don’t try to limit
it to “act only” — it’ll either act blindly or refuse.
Idempotent acts where possible
Tools that the model might call twice (network flakes, retries) are safer when idempotent. Where you can’t, design for the model to read its own past output (tool_result is in context) and notice when it already
ran.
Confirm before destructive
For irreversible operations (delete, drop, send to external), let the permission system gate. Don’t try to make the model “be careful” — let it propose and the user confirm.Pitfalls
- Tool name collisions. Two tools with similar names confuse the
model. Prefix tools by namespace if the Engine has many:
git.commitvs.slack.commit_review. - Schemas that don’t match the description. The model writes against the description; the Engine validates against the schema. Keep them in sync.
- Hidden side effects. A tool that “reads a file” but also writes a log to disk surprises the model. Document side effects in the description.
- Tools that return too much data. A
web_searchthat dumps 50 KB of HTML eats context. Truncate or summarize at the tool layer.
See also
- Defining tools — full reference for the tool definition format.
- Permissions — how dangerous tool calls get gated.
- MCP connectors — the MCP surface specifically.
- Streaming events —
tool_call/tool_resultevent reference.

