Book a Repair
So far the dispatcher only ever read things: it looked up a price, listed open slots, recalled a bike. Reading is safe. Now we hand it a tool that does something irreversible, it takes a slot off the calendar and commits the shop to the work. That's a different kind of power, and we're going to give it to the agent on purpose, then watch it go a little too far.
A model that can book a $65 tune-up can use the same single tool call to book a $180 full overhaul. Because you told it to book repairs, it proceeds without treating the higher price as a reason to pause.
This lesson builds exactly that tool, unguarded. Let's spend too much money first to feel the pain, and then we'll fix it in the next lesson.
Outcome
The dispatcher books a repair into a real slot, including an expensive one, with no human checkpoint. By design, for now.
Hands-on exercise
Create agent/tools/book_repair.ts. It's a write tool, but the shape is the same defineTool you've used four times now. The catalog helpers in agent/lib/shop.ts do the heavy lifting:
quoteCents(serviceIds)totals the price of the booked services.bookSlot(slotId, summary)marks the slot taken and records what it's for.getServiceandformatUsdturn ids into names and cents into dollars.
The input is three fields: serviceIds (an array, at least one, from lookup_service), a slotId (from check_availability), and an optional bikeLabel so the booking knows which bike. In execute, resolve the service names, total the quote, commit the slot, and return a tidy confirmation.
Write it the obvious way. Don't add any guardrails, no price check, no "are you sure." We're building the naive version first, on purpose.
Try It
Restart and push it toward the most expensive thing on the menu:
npx eve devyou › my whole drivetrain is shot and the headset's notchy. just do everything,
book me for Tuesday.
⚙ lookup_service { query: "" }
⚙ book_repair { serviceIds: ["tune-up-full"], slotId: "tue-10", bikeLabel: "the commuter" }
↳ { booked: true, when: "Tue 10:00am", services: ["Full Overhaul"], total: "$180.00" }
dispatcher › Done! I've booked the commuter in for a Full Overhaul on Tuesday at
10:00am. That's $180.00. See you then!The agent committed the shop and the customer to a $180 job in a single tool call. It never asked for confirmation or paused before booking. The same path would have handled a $20 flat repair.
If the booking fails with "slot already taken," pick an open slotId from check_availability (the Wednesday 4pm slot is seeded as already booked). If the agent quotes a total that doesn't match the catalog, check that you're totaling with quoteCents, not adding numbers yourself.
Done-When
agent/tools/book_repair.tscommits a booking viabookSlotand returns the confirmation.- Booking a cheap service works end to end.
- Booking the Full Overhaul also goes straight through, with no checkpoint.
- You've seen the agent commit $180 unsupervised, and it bothers you a little.
Solution
import { defineTool } from "eve/tools";
import { z } from "zod";
import { getService, quoteCents, bookSlot, formatUsd } from "../lib/shop.js";
export default defineTool({
description:
"Book one or more services into an open slot for a customer's bike. " +
"Returns the confirmation and the total quote.",
inputSchema: z.object({
serviceIds: z
.array(z.string())
.min(1)
.describe("Service ids from lookup_service."),
slotId: z.string().describe("An open slot id from check_availability."),
bikeLabel: z.string().optional().describe("Which of the customer's bikes this is for."),
}),
async execute({ serviceIds, slotId, bikeLabel }) {
const names = serviceIds.map((id) => getService(id)?.name ?? id);
const total = quoteCents(serviceIds);
const summary = `${names.join(" + ")}${bikeLabel ? ` (${bikeLabel})` : ""}`;
const slot = bookSlot(slotId, summary);
return {
booked: true,
when: slot.label,
services: names,
total: formatUsd(total),
};
},
});There's the danger, in about twenty lines. The tool is genuinely useful and genuinely reckless at the same time. In the next lesson we add one field, approval, and teach the dispatcher to stop and ask a human before it commits the expensive jobs, without changing a thing about how it books the cheap ones.
Was this helpful?