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
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.
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().
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
import { listTools } from "@monorch/ai";
const tools = listTools(); // [{ name, description }, ...]