Tools

Define tools with Zod. Monorch compiles to schema IR, registers in Rust, and prepares each call with authorization and parse before your execute callback runs.

Define

lookup-order.ts
import { tool, callTool } from "@monorch/ai";
import { z } from "zod";

export const lookupOrder = tool({
  name: "lookup_order",
  description: "Fetch an order by id",
  input: z.object({ orderId: z.string().min(1) }),
  permission: { type: "roles", roles: ["agent"] },
  execute: async ({ orderId }, { caller }) => {
    return db.orders.find(orderId);
  },
});

// Manual invoke (same prepare path agents use)
const value = await callTool("lookup_order", { orderId: "ord_9" }, { roles: ["agent"] });

Permissions & caller

Permission is allow, deny, or roles. The agent loop calls callTool with { roles: ["agent"] } unless you invoke tools yourself. Denied or invalid input fails prepare and never reaches execute.

ToolCaller also accepts optional subject (user/tenant id). Rust authorization keys off roles; subject is forwarded into execute for audit and app-level checks. Failures use TOOL_PREPARE_FAILED — see Errors & failure modes.

caller.ts
await callTool(
  "lookup_order",
  { orderId: "ord_9" },
  { roles: ["agent"], subject: "user_42" },
);

// inside execute:
execute: async (input, { caller }) => {
  audit.log({ tool: "lookup_order", subject: caller.subject });
  return db.orders.find(input.orderId);
}

Schema IR

Zod objects, strings, numbers, booleans, arrays, enums, optionals, and unions map through zodToIr. String email / uuid / url / regex and number int are enforced in Rust. refine / transform throw SCHEMA_UNSUPPORTED. Duplicate tool names fail unless you pass tool(def, { replace: true }).

JSON Schema without Zod

When you already have JSON Schema (MCP, OpenAPI), use jsonSchemaToIr + toolWithIr. The Zod input field is typing only — prefer z.object().passthrough().

tool-with-ir.ts
import { jsonSchemaToIr, toolWithIr } from "@monorch/ai";
import { z } from "zod";

const inputIr = jsonSchemaToIr({
  type: "object",
  properties: { orderId: { type: "string" } },
  required: ["orderId"],
  additionalProperties: false,
});

toolWithIr({
  name: "lookup_order_ir",
  description: "Same prepare path; schema from IR",
  input: z.object({}).passthrough(),
  inputIr,
  permission: { type: "roles", roles: ["agent"] },
  execute: async (args) => db.orders.find(String((args as { orderId: string }).orderId)),
});

Listing

list.ts
import { listTools } from "@monorch/ai";

const tools = listTools(); // [{ name, description }, ...]

FAQ