Skip to content
Tone is open sourcestar us on GitHub to follow along

concepts

Tools

Letting your agent take action — make API calls, read data, write to your systems.

A tool is a TypeScript function the agent can call mid-conversation. Tools are how agents do anything beyond talking.

Defining a tool

import { defineTool } from 'tone/tools';
import { z } from 'zod';
 
export const bookAppointment = defineTool({
  name: 'book_appointment',
  description: 'Book an appointment at a confirmed time.',
  schema: z.object({
    customer_id: z.string(),
    starts_at: z.string().datetime(),
  }),
  handler: async ({ customer_id, starts_at }) => {
    return await calendar.book({ customer_id, starts_at });
  },
});

Three pieces matter:

  • Name and description: how the LLM decides whether to call this tool.
  • Schema: validated input; the LLM is forced to pass typed args.
  • Handler: your code. Anything you can do in Node, you can do here.

Latency

Tool handlers are part of the turn budget. Aim for p95 < 300ms. If your handler is slower than that, the conversation feels sluggish.

For genuinely slow operations (booking against a third-party API, sending emails), use the deferred-tool pattern — return immediately with a token and queue the actual work.

Permissions and safety

Tools run with your service's permissions. The LLM cannot escalate beyond what the handler explicitly does. If a tool only reads, it can only read. If it writes, you're responsible for idempotency.

Registry

Tools are registered globally and referenced by name in agent YAML:

agents:
  - id: scheduler
    tools:
      - check_availability
      - book_appointment

You can register the same tool with multiple agents. Each agent gets its own view, but the handler runs once per call.