Du har kanskje prøvd ut noen av de nyere verktøyene for KI-assistert koding, og opplevd at språkmodellene ser ut til å kunne editere og kjøre koden din, utføre kommandoer i shellet ditt, kanskje også endre databasen eller deploye til skyen? Eller du kan hente interne data eller realtidsdata. Og aksessere lokalt utstyr som 3D-printeren eller hjemmeautomasjon, lese mail og private dokumenter, bestille varer, og utføre arbeidsflyter som er sammensatt av flere slike verktøykall. Alt gjennom å ha en dialog med din eksisterende KI-assistent.
Velkommen til verktøykall (eng: function calling eller tool use). Dette er en teknikk som mange språkmodeller har blitt opplært til. Om du sier til språkmodellen hvilke verktøy som kan kalles, så vil språkmodellen foreslå at man gjør et slikt kall om den finner det nødvendig.
Språkmodellen kan jo ikke kan utføre noe på egen hånd. Den kan bare generere tekst (eller riktigere, tokens, som kan oversettes til tekst eller bilder og andre media). Så språkmodellen bare foreslår at et kall kan gjøres, mens det er din KI-assistent som faktisk utfører dette kallet.
Jeg vil vise hvordan verktøykall fungerer på API-nivå. Dette er nyttig om du skal lage din egen KI_assistent. I neste blogginnlegg ser jeg nærmere på hvordan du enkelt kan gjøre bruk av verktøykall i eksisterende KI-assistenter ved hjelp av standarden MCP.
¶Tilstandsløs chatting med en språkmodell
Før vi ser på verktøykall i detalj, la oss se på en enkel prat med en språkmodell. Vi vil se at den er tilstandsløs, og at det skapes en illusjon av tilstand ved å sende hele dialogen så langt til språkmodellen hver gang.

Vi spør først om hvem som samlet Norge til ett rike, og får svaret Harald Hårfagre. Oppfølgingsspørsmålet “Hvilket år?” må, for å beholde kontekstet, sende hele dialogen igjen, slik:
POST https://api.openai.com/v1/responses HTTP/1.1
Content-Type: application/json
Authorization: Bearer $OPENAI_API_KEY
{
"model": "gpt-4o-mini",
"input": [
{"role": "system", "content": "You are a helpful assistant. Svar kort."}
{"role": "user", "content": "Hvem samlet Norge til ett rike?"}
{"role": "assistant", "content": "Harald Hårfagre"}
{"role": "user", "content": "Hvilket år?"}
]
}
Og svaret er, som forventet, at Harald Hårfagres samlet Norge til ett rike i 872, pakket inn i litt JSON:
{
"output": [
{
"id": "msg_67b73f697ba4819183a15cc17d011509",
"type": "message",
"role": "assistant",
"content": [
{
"type": "output_text",
"text": "Harald hårfagre samlet Norge til ett rike i år 872",
"annotations": []
}
]
}
]
}
Det er så klart mulig å pakke dette inn i et api med en sesjonsnøkkel og la det se ut som språkmodellen har tilstand. Om du spionerer på nettverkstrafikken til ChatGPT eller DeepSeek så vil du se at de bruker sesjonsnøkler og bare sender inkrementelle endringer i chatten. Men bak kulissene er språkmodellen tilstandsløs. Den tar i mot tekst og produserer tekst.
¶Verktøykall
Tilbake til verktøykall. Som vi nevnte overfor, kan ikke en språkmodell utføre noe på egen hånd. Den bare leverer tekst. Det som skjer er at språkmodellen – hvis den finner det nødvendig – returner en JSON-string som er et forslag om at du utfører et slikt kall. Og det du som oppgir hvilke verktøykall som du vil støtte.
Vi lister altså opp verktøykall vi ønsker å støtte sammen med prompten. For å ta et enkelt (og mye brukt) eksempel, anta at vi har en lokal funksjon, get_weather, som gir oss temperatur på et sted, og vi vil at modellen skal foreslå at denne kalles om nødvendig:
POST https://api.openai.com/v1/responses HTTP/1.1
Content-Type: application/json
Authorization: Bearer $OPENAI_API_KEY
{
"model": "gpt-4o-mini",
"tools": [
{
"type": "function",
"name": "get_weather",
"description": "Get current temperature for a given location.",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "City and country e.g. Bogotá, Colombia"
}
},
"required": ["location"],
"additionalProperties": false
}
}
],
"input": [
{"role": "system", "content": "You are a helpful assistant. Svar kort."}
{"role": "user", "content": "Hvordan er været i Hammerfest?"}
]
}
Her ser man at tools: ramser opp alle verktøy som vi vil at språkmodellen skal kunne benytte. tools[].description: er vesentlig for å tipse språkmodellen om når et verktøykall kan være nødvendig. Like viktig er tools[].parameters. Dette er et JSON-Schema som beskriver verktøyet sine parametre, sånn at språkmodellen kan bygge opp et korrekt verktøykall. Ikke glem beskrivelsen til hver parameter! Uten dette vil ikke språkmodellen klare å angi riktige parametere.
Hvis språkmodellen finner ut at et verktøykall kan være lurt å utføre, vil den i stedet for å returnere et ‘normalt’ svar med tekst, heller returnere et forslag til verktøykall:
{
"output": [
{
"type": "function_call",
"id": "fc_12345xyz",
"call_id": "call_12345xyz",
"name": "get_weather",
"arguments": "{\"location\":\"Hammerfest\"}"
}
]
}
Og nå er det opp til oss, eller KI-assistenten vår, å kalle denne funksjonen. Dette kan være en funksjon som KI-assistenten har innebygget, så som lesing og skriving av filer, eller en funksjon som vi implementerer og forteller KI-assistenten vår om.
KI-assistenten vår kaller altså funksjonen lokalt, sannsynlighvis etter å ha spurt oss om lov først, og får svaret “14 grader celcius”. Den sender deretter dette svaret tilbake til språkmodellen sammen med opprinnelig prompt. (Den tar med listen over tilgjengelige verktøy nå også, siden det kan jo hende vi trenger å vite temperaturen i flere byer):
POST https://api.openai.com/v1/responses HTTP/1.1
Content-Type: application/json
Authorization: Bearer $OPENAI_API_KEY
{
"model": "gpt-4o-mini",
"tools": [
{
"type": "function",
"name": "get_weather",
"description": "Get current temperature for a given location.",
"parameters": "... (her er det samme JSON-Schema som over)"
}
],
"input": [
{"role": "system", "content": "You are a helpful assistant. Svar kort"},
{"role": "user", "content": "Hvordan er været i Hammerfest?"},
{
"type": "function_call_output",
"call_id": "call_12345xyz",
"output": "{\"temperatur\": 14, \"enhet\": \"celsius\"}"
}
]
}
Nå har språkmodellen all informasjonen den trenger: det opprinnelige spørsmålet og resultatet fra verktøykallet. Den vil da generere et endelig, menneskelig lesbart svar:
{
"output": [
{
"id": "msg_67b73f697ba4819183a15cc17d01150a",
"type": "message",
"role": "assistant",
"content": [
{
"type": "output_text",
"text": "Været i Hammerfest er 14 grader celsius."
}
]
}
]
}
Her er en enkel sekvensmodell som viser hvordan verktøykall skjer:

¶Støtte for verktøykall
De tre store aktørene – OpenAI, Google og Anthropic – har alle god støtte for verktøykall i sine modeller. Konseptet er det samme, men det er små, men viktige forskjeller i API-implementasjonen. Du vil sannsynligvis ikke trenge å forholde deg til disse API-ene om du ikke skal lage din egen KI-assistent, men heller bruke en standard for for å plugge inn dine verktøy i en eksisterende KI-assistent, se nedenfor. Nyere versjoner av en rekke open source-modeller, som LLAMA 3, Mistral og Gemma 3, støtter også verktøykall. Disse modellene bruker ofte rammeverk som LangChain eller LlamaIndex, som tilbyr et standardisert grensesnitt for verktøykall.
¶Standardisering
Måten å implementere verktøykall som er angitt over har én klar ulempe. Hver ny KI-assistent må implementere disse, og ta høyde for forskjeller i verktøykall-implementasjoner i de forskjellige språkmodellene.
Heldigvis har det kommet standarder som gjør at du kan gjøre implementasjonen én gang og la disse dynamisk plugge seg inn i KI-assistentene kun via konfigurasjon. En viktig standard for dette kalles MCP, Model Context Protocol. Den ble publisert av Anthropic i november 2024, og har etter hvert fått bred støtte hos KI-assistenter. Det finnes også andre lignende standarder, A2A, Agent to Agent fra Google og ACP, Agent Communication Protocol fra IBM.
I øyeblikket ser det ut som om MCP har mest moment, og i neste blogginnlegg vil jeg se nærmere på denne.