Agentic tools
The AI chat runs as a multi-step agent loop: the model can call tools, read the
results, and continue reasoning before it answers. The loop is capped at 5
steps per turn (stepCountIs(5)), and tool results stream back to the client
as they resolve.
Built-in tools
The tool registry lives at lib/ai/tools/index.ts. Two tools ship with the AI
chat layer itself:
| Tool | Source | What it does |
|---|---|---|
calculator | lib/ai/tools/calculator.ts | Evaluates basic arithmetic (+ - * / % ^ and parentheses). |
data-fetch | lib/ai/tools/data-fetch.ts | Fetches the text of a public web page to summarize or answer questions about. |
Selecting the agentic tool calling feature at scaffold time adds one more:
| Tool | Source | What it does |
|---|---|---|
web_search | lib/ai/tools/web-search.ts | Searches the web through one of three interchangeable backends. |
When tools are active
Tools are only passed to the model when both conditions hold:
ENABLE_TOOLSistrue— a template-admin switch inlib/ai/config.ts. Set it tofalseto run plain chat with no tools.- The workspace’s plan allows tools —
features.toolsinplans.ts(off on Free, on for Pro and Team).
When tools are off, the chat still works — it just answers without calling them.
Web search backend
Pick a backend by setting its API key in .env.local:
| Backend | Key |
|---|---|
| Tavily | TAVILY_API_KEY |
| Exa | EXA_API_KEY |
| Firecrawl | FIRECRAWL_API_KEY |
The tool source lives at lib/ai/tools/web-search.ts.
Adding your own tool
- Create a file under
lib/ai/tools/defining the tool — a name, a Zod parameter schema, and anexecutefunction. - Register it in the tool registry.
- The chat agent loop picks it up; the model can now call it.
Keep tools tenant-aware — if a tool touches workspace data, scope it by the
active tenant_id just like any other query.