Write tools
wardrik.tool({ name: "find_order", description: "The order a Stripe payment intent paid for: items, address, dates.", input: z.object({ payment_intent: z.string().describe("As pi_123") }), readOnly: true, run: ({ payment_intent }) => orders.byPaymentIntent(payment_intent),});| Key | |
|---|---|
name |
1 to 55 letters, digits, _ and - |
description |
the description sent to the model |
title |
a display name |
input |
a zod object schema for the arguments; .describe() documents a field for the model |
readOnly |
the tool changes nothing, so it never needs approval |
idempotent |
the tool is safe to call twice with the same arguments |
run |
the function; receives the arguments and { agent, run, idempotencyKey, signal, cost } |
- Add
workers/*to an agent'stools. The model seesworkers__find_order. - In a policy, it's
workers/find_order.
Results and errors
Section titled “Results and errors”Return an object or a string. Return only what the model needs, since every token counts.
Throw to fail the call. Write an error message the model can act on:
run: async ({ order_id }) => { const order = await orders.find(order_id); if (!order) throw new Error(`No order ${order_id}. Order IDs look like ord_1234.`); return { id: order.id, status: order.status };},The calling agent
Section titled “The calling agent”agent is the calling agent's ID. Wardrik sets it, not the model. Use it to scope data:
run: (_args, { agent }) => db.orders.where({ agent }),Call cost with a paid API's cost in US dollars. It's added to the agent's
budget:
run: async ({ email }, { cost }) => { const found = await enrich.lookup(email); cost(0.01); return found;},Retries
Section titled “Retries”idempotencyKey is the same on every attempt of a call. Pass it to the API, and mark the tool
idempotent:
wardrik.tool({ name: "refund_order", description: "Refund an order in full.", input: z.object({ orderId: z.string() }), idempotent: true, run: ({ orderId }, { idempotencyKey }) => stripe.refunds.create({ payment_intent: orderId }, { idempotencyKey }),});- Only
idempotentorreadOnlytools are retried. See Durable runs. - For an API without idempotency keys, store each key's result and return it on a repeat.
Details
Section titled “Details”signalaborts when the call is stopped or times out. Pass it tofetch.- A call times out after 60 seconds.
runin the context is the turn's ID, the same as in its events.- Calling
costtwice adds both amounts. - A tool with an invalid name, or an
inputthat isn't an object schema, is skipped.