Tools
Tools are server-side functions the model may call during a conversation: look up an order, check a price, fetch the weather. You describe the arguments with a Zod schema; askdare validates every call before your code runs.
// tools.ts
import { defineTool } from '@boldare/askdare';
import { z } from 'zod';
export const orderStatus = defineTool({
name: 'get_order_status',
description: 'Status of an order by its number. Use it when the visitor asks about an order.',
input: z.object({
orderNumber: z.string().regex(/^\d{6}$/).describe('Six-digit order number'),
}),
execute: async ({ orderNumber }, { signal }) => {
const response = await fetch(`https://shop.example.com/api/orders/${orderNumber}`, { signal });
if (!response.ok) return { error: 'No such order.' };
const order = (await response.json()) as { status: string };
return { orderNumber, status: order.status };
},
});// askdare.config.ts
defineBot({
// …
tools: [orderStatus],
});How a call works
- The model decides to call a tool and proposes arguments.
- askdare validates them with your schema. Invalid arguments go back to the model as an error, and
executedoesn't run. executeruns on your server, with a timeout (timeoutMs, 10 seconds by default). Several calls in one step run in parallel.- Whatever
executereturns goes back to the model as JSON. Return{ error: '…' }for failures the model should explain; a thrown error reaches the model as a generic failure. - The visitor sees only a short status ("Using get_order_status…"), never the arguments or the result.
A bot makes at most limits.maxSteps model calls per message (default 5); the last one must answer in words.
Rules
- Every field is required. OpenAI's strict mode demands it: use
.nullable()instead of.optional().defineToolfails at startup otherwise. - Describe well. The model picks tools by
descriptionand fills fields by their.describe(). - Never trust the model with identity. The model can be talked into anything, so a tool must not take user IDs, emails or permissions from its arguments. The second argument of
executeholds what askdare verified:botId,visitorId(pseudonymous, created by the server),locale,identity(the signed-in user, when your site identifies them) and an abortsignal. - Read-only, for now. Tools that change data (place an order, send an email) need the visitor's confirmation, which askdare doesn't offer yet. Keep tools to lookups.
- Keep results small. Return the fields the model needs. Large results cost input tokens on every later message.
- Keep it under about 20 tools per bot. More tools make the model slower and less accurate.
The demo site has two working examples in site/tools.ts.