← Terug naar blog
AI Strategie
10 februari 2026

AI-agents met tool use: van prompt naar productie

Een praktische gids om agents te bouwen die echt iets doen — niet alleen tekst genereren
Aron Heesakkers
Aron HeesakkersFullstack Developer & AI Engineer

Het verschil tussen een chatbot en een agent is één regel: een agent mag iets doen. Niet alleen antwoorden, maar de database raadplegen, een dienst toewijzen, een betaling controleren, een mail versturen. Dat noemen we tool use. Het is het onderdeel waardoor LLM's overstappen van interessante speeltjes naar productiesoftware.

Bij Boomer bouwen we tool-use agents die elke dag draaien voor klanten in horeca, events en zorg. In deze post: hoe je er één opzet zonder dat je over een half jaar vastloopt in een doolhof aan prompts en edge cases.

Wat tool use eigenlijk is

Tool use is simpel in concept. Je geeft een LLM (Claude, GPT-4, Gemini) een lijst met functies die hij mag aanroepen, met hun parameters en een beschrijving. De LLM beslist op basis van de gebruikersinput welke functie hij wil uitvoeren, en met welke argumenten. Jouw code voert de functie uit, geeft het resultaat terug aan de LLM, en de LLM gebruikt dat resultaat om verder te redeneren of een antwoord te formuleren.

In Anthropic's API ziet dat er ongeveer zo uit:

const tools = [
  {
    name: "get_employee_availability",
    description:
      "Haal de beschikbaarheid op voor een medewerker tussen twee data.",
    input_schema: {
      type: "object",
      properties: {
        employee_id: { type: "string" },
        from: { type: "string", format: "date" },
        to: { type: "string", format: "date" },
      },
      required: ["employee_id", "from", "to"],
    },
  },
];

const response = await anthropic.messages.create({
  model: "claude-sonnet-4-5",
  max_tokens: 1024,
  tools,
  messages: [{ role: "user", content: "Is Lisa zaterdag vrij?" }],
});

De LLM antwoordt niet met tekst, maar met een tool_use block: "roep get_employee_availability aan met employee_id=lisa-vd-berg, from=2026-05-16, to=2026-05-17". Jij voert dat uit en geeft het resultaat terug. De LLM ziet het resultaat en zegt nu pas iets terug tegen de gebruiker — bijvoorbeeld "Ja, Lisa is zaterdag de hele dag beschikbaar".

Dat is alles. De magie zit niet in een nieuw framework, maar in dat je de LLM laat redeneren over welke functie hij nodig heeft. De rest is gewone software.

Waarom we geen agent-framework gebruiken

Er bestaan een handvol agent-frameworks (LangChain, CrewAI, AutoGen, Mastra). Wij gebruiken ze niet. De redenen zijn dezelfde redenen waarom we geen ORM gebruiken in PostgreSQL-gedreven backends: de abstractie kost meer dan ze oplevert.

Wat een framework je geeft:

  • Tool-definities op één plek
  • Een loop die tool_usetool_result afhandelt
  • Logging, retries, soms streaming

Wat een framework je kost:

  • Versie-lock op een externe library voor iets dat 200 regels TypeScript is
  • Abstracties die niet matchen met jouw datamodel (bijvoorbeeld een eigen "memory"-concept terwijl jij gewoon een conversaties-tabel in Postgres hebt)
  • Debugging via vier lagen ineens, in plaats van één

Voor agents die in productie moeten draaien — niet voor een hackathon-demo — schrijf je de loop liever zelf. De Anthropic SDK en OpenAI SDK ondersteunen tool use rechtstreeks, en de loop is in essentie:

while (true) {
  const response = await client.messages.create({ ... });
  if (response.stop_reason === "end_turn") return response;
  if (response.stop_reason === "tool_use") {
    const results = await Promise.all(
      response.content
        .filter((b) => b.type === "tool_use")
        .map((b) => executeTool(b.name, b.input)),
    );
    messages.push({ role: "assistant", content: response.content });
    messages.push({ role: "user", content: results });
  }
}

Dat is het. Voeg observability toe (welke tools werden aangeroepen, hoe lang duurde elk, wat kostte het) en je hebt een productie-agent.

Drie valkuilen die je gegarandeerd raakt

1. Het model verzint tool-argumenten

De LLM krijgt een gesprek en moet bedenken welke argumenten ze meegeeft. Soms verzint hij dingen — een employee_id die niet bestaat, een datum in het verleden, een bedrag in de verkeerde valuta.

Oplossing: niet meer hopen, maar valideren. Wrap elke tool-execute in een schema-validator (Zod, Valibot, of gewoon TypeScript runtime checks). Bij een validatiefout geef je de LLM een duidelijke foutmelding terug — niet een 500. De LLM is goed in herstellen als hij weet wat er misging.

const { success, data, error } = AvailabilitySchema.safeParse(input);
if (!success) {
  return { is_error: true, content: `Invalid input: ${error.message}` };
}

2. De agent loopt eindeloos

Zonder limiet kan een agent in een loop terechtkomen waarbij hij telkens dezelfde tool aanroept met kleine variaties. Vooral bij ambiguë requests gebeurt dat.

Oplossing: zet een hard limit op het aantal tool-rondes (5–10 is een redelijk startpunt) en log waarom je afbreekt. Geef in de afbreker-melding aan de LLM mee dat hij nu een mens moet betrekken of een eindstand moet geven. Niet stilletjes terug naar de gebruiker met een leeg antwoord.

3. Tools die niet idempotent zijn

get_employee_availability aanroepen is veilig — je kunt het tien keer doen en niks gebeurt. send_whatsapp_message is niet veilig. Als de LLM die per ongeluk twee keer aanroept, krijgt je gebruiker twee berichten.

Oplossing: scheid lees-tools en schrijf-tools in je hoofd en in je code. Lees-tools mogen vrij worden aangeroepen. Schrijf-tools krijgen een idempotency-key (UUID v7, of een deterministische hash van de inhoud) en je server checkt of dezelfde key al verwerkt is. Geef bij een duplicate gewoon het oorspronkelijke resultaat terug, zonder de schrijfactie nogmaals uit te voeren.

Wat je nooit aan de LLM moet overlaten

Niet alle beslissingen horen bij het taalmodel. Bewaar de scherpe randen voor je eigen code:

  • Autorisatie: of een gebruiker iets mag doen, beslis jij — niet de LLM. Voor elke tool: check of de huidige gebruiker geautoriseerd is voor die actie, op die resource, op dat moment. Doe dat in je server, niet in de prompt.
  • Bedrag-gates: betalingen of transacties boven een drempel? Geef de LLM een tool die een approval aanvraagt, niet een tool die direct betaalt.
  • Persoonsgegevens: laat de LLM een ID opvragen, geen volledige profielen. PII hoort niet onnodig in een prompt.

De juiste mentaliteit: de LLM is een slimme stagiair die mag voorstellen wat er moet gebeuren. Jouw server is de manager die uiteindelijk de knop indrukt — en die kent de regels.

Wanneer je geen agent nodig hebt

Tot slot: niet elke AI-feature is een agent. Als je input bekend is en je output bekend is (bijvoorbeeld: classificeer een bericht in 3 categorieën, vertaal een tekst, extract velden uit een PDF), dan is een simpele LLM-call met gestructureerde output (JSON mode of Anthropic's tool_choice) genoeg. Agent-loops zijn overkill voor lineaire taken.

Een agent verdient zijn complexiteit wanneer:

  • De LLM moet beslissen welke stappen er nodig zijn (multi-turn redenering)
  • De stappen afhankelijk zijn van tussenresultaten
  • Er meerdere geldige paden zijn naar het antwoord

Daaronder: gewoon een prompt en een check. Veel sneller, veel goedkoper, veel makkelijker te debuggen.

Samenvatting

Tool use is volwassen technologie geworden. Claude en GPT zijn er goed in, de SDK's ondersteunen het netjes, en je hoeft geen framework te kopen om het werkend te krijgen. Wat je wel nodig hebt: gedisciplineerde input-validatie, een loop-limiet, idempotente schrijfacties, autorisatie in je eigen code, en een nuchtere afweging of een agent überhaupt het juiste antwoord is.

We bouwen deze agents bij Boomer in TypeScript op een PostgreSQL-basis. Geen frameworks, geen abstracties die we zelf niet onderhouden — gewoon code die je kunt lezen en aanpassen op het moment dat productie iets onverwachts doet. En dat doet productie altijd.

Als je een specifiek probleem hebt waar je twijfelt of een agent het juiste antwoord is: stuur ons een bericht. We zeggen het eerlijk als een gewone API-call goedkoper is.


Project bespreken?

Heb je een use case waar je over twijfelt?

We praten graag over of een AI-aanpak past — en zeggen het eerlijk als het beter zonder kan. Vaste prijs, afgesproken scope.
Plan een gesprek
Probeer AI