Skip to main content

Tools

Een tool is een benoemde actie die de AI kan aanroepen, met getypeerde invoer — bijv. send_email(to, subject, body). Tools worden gedeclareerd in de tools.ts van een skill en, voor tools die je app aanbiedt, ondersteund door een HTTP-route in een van je componenten. Deze pagina is de bron van waarheid voor het tool-contract; Skills behandelt waar tools.ts zich bevindt.

Een tool declareren

Elk item in tools.ts heeft een provider-veilige name, een vriendelijke displayName, een description, een Zod input-schema, en een target die aangeeft wat Kazzle aanroept.

Targets

target is het herbruikbare adres voor een tool of vereiste-actie-knop. Een directe AI-tool-aanroep en een knopklik kunnen hetzelfde target-object gebruiken, dus beide voeren dezelfde code uit. HTTP-targets gebruiken dezelfde aanvraagvelden:
Er zijn geen impliciete aanvraagstandaards. Als je handler de onbewerkte tool-invoer als JSON moet ontvangen, schrijf je body: '${input}'.

Referenties

Kazzle lost referenties op in HTTP-target query-, headers-, body- en url-velden vóór verzending:
  • ${input} — de hele tool-invoer, of de hele knop-invoer.
  • ${input.path} — een geneste waarde uit de invoer.
  • ${env.NAME} — een benoemde omgevingsvariabele uit de gedeclareerde env.collection + env.environment van de eigenaar-app-component.
Resolutie is eenmalig. Als een referentie ontbreekt of onbekend is, mislukt de tool in plaats van een lege waarde in te vullen. Gebruik $${input.name} wanneer je letterlijke ${input.name}-tekst nodig hebt.

Handler-aanvraag

Voor een app-target voeg je de overeenkomende route toe in de target-component. Met body: '${input}' stuurt Kazzle de getypeerde invoer als JSON-body:
app-targets ontvangen ook: App-targets kunnen Authorization niet instellen via headers; Kazzle bezit die header. Lees de context met toolContext(req) uit @kazzle/app/tools wanneer de handler thread vs Tools API moet onderscheiden. Een tool gedeclareerd zonder overeenkomende route doet niets nuttigs — voeg beide samen toe. tools.json wordt niet ondersteund; de app-compiler mislukt als deze er een vindt.

Handler-respons

Retourneer platte tekst, of JSON met maximaal drie kanalen:
  • content — het platte resultaat dat de AI leest (gevoerd naar het model). Vereist.
  • markdown — optioneel. Een korte rich-text-samenvatting weergegeven in de tool-kaart (react-markdown; onbewerkte HTML wordt ontsnapt). Goed voor een zin, een kleine lijst, een inline-link. Een bloot relatief pad wordt weergegeven als dode voorgeformateerde tekst — links moeten absoluut zijn.
  • embedUrl — optioneel. Een absolute URL die je app aanbiedt; de kaart geeft deze weer in een sandbox-iframe. Dit is hoe je een echte, volledige-breedte-UI toont — een verbindingsscherm, een dashboard, een grafiek. Je app host en bezit de pagina, dus deze kan volledig interactief zijn tegen je eigen backend, cookies en OAuth. Niets wordt naar de drive geschreven.
embedUrl wint van markdown wanneer beide zijn ingesteld. Behoud altijd een betekenisvolle content — dat is wat de AI leest.

Vereiste actie

Een app-tool kan de thread pauzeren wanneer deze een gebruikers- (of apparaat-)actie nodig heeft. Retourneer type: 'action_required' met een kaarttitel en knoppen. Alleen geldig wanneer toolContext(req).source === 'thread' — over de Tools API (source: 'api'), retourneer in plaats daarvan een normale domeinenfout.
Kazzle slaat de kaart op bij de tool-aanroep en hervat via /chat/resume nadat een knop is ingedrukt. Overeenkomende clients zien de auteurknoppen; niet-overeenkomende clients zien nog steeds Overslaan/Annuleren plus “Doorgaan op ”. Een knop zonder target dient zijn input in als het tool-resultaat. Een knop met een target voert eerst dat target uit, en gebruikt vervolgens het target-resultaat als het tool-resultaat.

Rich UI — een app-gehoste pagina insluiten

Wanneer het resultaat van een tool visueel of interactief is (een verbindingsscherm, een grafiek, een samenvattingsdashboard), dien je de pagina vanuit een van je componenten en retourneer je de absolute URL als embedUrl. Bouw de URL op uit de geïnjecteerde component-URL — nooit een relatief pad.
De pagina wordt uitgevoerd in een cross-origin iframe (zijn eigen oorsprong, cookies en scripts). Om de kaart in grootte aan te passen, post je de hoogte naar de parent — de kaart luistert hiernaar en past de grootte aan (begrensd tot 70% van de viewport):
Geef de voorkeur aan embedUrl boven het uitzenden van HTML-strings: je app dient al pagina’s, de UI blijft interactief en versioned met je code, en er worden geen per-aanroep-artefacten ergens geschreven.