← Back to honi.dev

Tools

Give your agent the ability to take actions and access external data through type-safe tool definitions.

tool() API

TypeScript
1import { tool } from 'honidev'
2
3function tool(config: ToolConfig): Tool

ToolConfig

FieldTypeDescription
descriptionstringHuman-readable description sent to the LLM
inputZodSchemaZod schema defining the tool's input parameters
run(input, ctx) => Promise<any>Async handler that executes when the tool is called

Zod Schema Input

Tools use Zod schemas to define their input. Honi automatically converts these schemas to JSON Schema for LLM function calling.

TypeScript
1import { z } from 'zod'
2
3// Simple string input
4z.object({ query: z.string() })
5
6// Complex input with validation
7z.object({
8 lat: z.number().min(-90).max(90),
9 lon: z.number().min(-180).max(180),
10 units: z.enum(['metric', 'imperial']).optional()
11})

Handler Signature

The run function receives the validated input and a context object:

TypeScript
1type ToolHandler = (
2 input: z.infer<typeof schema>,
3 ctx: { env: Env; sessionId: string }
4) => Promise<any>

The ctx.env object gives you access to all Cloudflare bindings (D1, KV, R2, etc.). The return value is serialized to JSON and sent back to the LLM.

How Tools Map to LLM Function Calling

When you define tools, Honi:

  1. Converts each Zod schema to JSON Schema at startup
  2. Sends tool definitions alongside your messages to the LLM
  3. When the LLM requests a tool call, Honi validates the input against the Zod schema
  4. Executes the run handler with the validated input
  5. Returns the result to the LLM for the next turn

This loop continues until the LLM responds with a text message instead of a tool call.

Examples

Search Tool

TypeScript
1const search = tool({
2 description: 'Search the knowledge base for relevant articles',
3 input: z.object({
4 query: z.string().describe('Search query'),
5 limit: z.number().default(5)
6 }),
7 async run({ query, limit }, ctx) {
8 const results = await ctx.env.VECTORIZE.query(query, { topK: limit })
9 return results.matches
10 }
11})

Calculator Tool

TypeScript
1const calculator = tool({
2 description: 'Perform basic arithmetic calculations',
3 input: z.object({
4 expression: z.string().describe('Math expression, e.g. "2 + 2"')
5 }),
6 async run({ expression }) {
7 const result = Function(`"use strict"; return (${expression})`)()
8 return { expression, result }
9 }
10})