Shirube

Documentation

Agents and tools

A tool is a function the model may call — described in language, constrained with Zod, executed asynchronously.

What a tool is

A tool is a function the model may call. You describe it in language the model can understand (name + description), constrain arguments with Zod, and implement execute.

Shirube turns the Zod schema into JSON Schema for function calling, parses the model’s arguments, validates them, then runs execute. Async is fine (your database, HTTP, MCP).

Use tools when the agent must not invent: inventory, weather, refunds, search, calendars.

Do not use a tool for pure reasoning (“summarize this paragraph”) — that is just the model.

Defining a tool

search.ts
import { tool } from "shirube-ai";
import { z } from "zod";

const search = tool({
  name: "search_docs",
  description: "Search the help center. Pass the user question, not keywords only.",
  parameters: z.object({
    query: z.string().min(2),
  }),
  execute: async ({ input, context }) => {
    return helpCenter.search(input.query, { userId: context.userId });
  },
});

Attach with .tools([search]) or .tool(search). The return value is JSON-stringified for the model. Typed input follows your Zod schema.

context includes runId, userId, sessionId, and the agent name — useful for logging and tenancy.

Errors

SituationWhat happens
Unknown tool name / Zod failToolError — the run can fail that call
execute throwsLoop continues; model sees {"error":"..."} and can retry or apologize
Duplicate tool namesThrown when building the registry

Human approval

For irreversible actions (refund, delete, wire), set requireApproval: true.

refund.ts
const refund = tool({
  name: "refund",
  description: "Refund an order. Only after the customer confirms the order id.",
  parameters: z.object({ orderId: z.string() }),
  requireApproval: true,
  execute: async ({ input }) => payments.refund(input.orderId),
});

await agent.run("Refund order_9", {
  approval: async ({ tool, arguments: args, runId }) => {
    if (tool !== "refund") return true;
    return currentUser.canRefund;
  },
});
Fail closed

If you omit approval, approval-required tools are denied. The model gets an error payload and should not pretend the refund succeeded.

You can also attach tool-level guardrails (inputGuardrails / outputGuardrails on the tool) for extra checks on arguments or results.

The agent loop (tools)

Until a final text answer:

  1. Model may return one or more tool calls.
  2. Each call is guardrailed → optionally approved → executed.
  3. Results are appended as tool messages.
  4. Repeat, until maxTurns (default 10) or timeout (default 120s).

That is the whole “agent”: a loop you own, not a black box.