D· AI-utvecklareagenter-verktyg· ca 45 min· grundläggande — ändras sällan· verifierad 2026-09-20
Bygg en enkel agent med ett verktyg
Kunna låta en modell anropa en funktion och använda svaret.
Förkunskaper
Intuition
En språkmodell kan inte slå upp dagens datum, räkna exakt, eller läsa din kalender. Men den kan säga att den vill göra det — och sedan är det din kod som gör jobbet.
Loopen har fyra steg:
1. Du beskriver vilka verktyg som finns
2. Modellen svarar: "anropa vader(stad='Malmö')"
3. DIN KOD kör funktionen och får svaret 14
4. Du skickar tillbaka svaret; modellen formulerar det slutliga svaret
Steg 3 är det viktiga: modellen kör ingenting. Den producerar bara ett textsvar som säger vad den vill ska hända. Din kod bestämmer om det ska ske.
Det är både en begränsning och hela säkerhetsmodellen — du kan alltid neka, validera eller fråga användaren först.
Kod
import json
# 1. Verktygen — vanliga Python-funktioner
def vader(stad: str) -> dict:
data = {"Malmö": 14, "Kiruna": -3, "Göteborg": 11}
if stad not in data:
return {"fel": f"okänd stad '{stad}'. Välj mellan: {sorted(data)}"}
return {"stad": stad, "grader": data[stad]}
def rakna(uttryck: str) -> dict:
if not set(uttryck) <= set("0123456789+-*/(). "):
return {"fel": "uttrycket får bara innehålla siffror och + - * / ( )"}
try:
return {"svar": eval(uttryck, {"__builtins__": {}}, {})}
except Exception as e:
return {"fel": f"kunde inte räkna ut: {type(e).__name__}"}
VERKTYG = {"vader": vader, "rakna": rakna}
SPEC = [
{"type": "function", "function": {
"name": "vader", "description": "Temperaturen i en svensk stad just nu, i grader Celsius.",
"parameters": {"type": "object", "required": ["stad"], "additionalProperties": False,
"properties": {"stad": {"type": "string", "enum": ["Malmö", "Kiruna", "Göteborg"],
"description": "Stadens namn"}}}}},
{"type": "function", "function": {
"name": "rakna", "description": "Räknar ut ett aritmetiskt uttryck exakt.",
"parameters": {"type": "object", "required": ["uttryck"], "additionalProperties": False,
"properties": {"uttryck": {"type": "string", "description": "T.ex. '17 * 23'"}}}}},
]
def kor(llm, fraga, max_varv=5):
meddelanden = [{"role": "user", "content": fraga}]
for _ in range(max_varv): # max_varv skyddar mot loopar
svar = llm(meddelanden, tools=SPEC)
meddelanden.append(svar)
if not svar.get("tool_calls"):
return svar["content"]
for anrop in svar["tool_calls"]:
namn = anrop["function"]["name"]
try:
args = json.loads(anrop["function"]["arguments"])
except json.JSONDecodeError:
resultat = {"fel": "argumenten var inte giltig JSON"}
else:
fn = VERKTYG.get(namn)
resultat = fn(**args) if fn else {"fel": f"okänt verktyg '{namn}'"}
meddelanden.append({"role": "tool", "tool_call_id": anrop["id"],
"content": json.dumps(resultat, ensure_ascii=False)})
return "Nådde maxantalet steg utan att bli klar."
# print(kor(llm, "Hur varmt är det i Malmö, och vad är 17 gånger 23?"))
# "Det är 14 grader i Malmö, och 17 gånger 23 är 391."
Fyra detaljer som gör skillnaden mellan en leksak och något som håller:
max_varv— utan tak kan modellen fastna i en loop som anropar samma verktyg om och om igen.- Fel som resultat, inte undantag —
{"fel": "okänd stad ..."}skickas tillbaka så att modellen kan rätta sig i nästa varv. enumi schemat — då kan modellen inte hitta på städer.- Begränsad
eval— teckenkontrollen och tomma__builtins__gör att uttrycket inte kan köra godtycklig kod. (I ett skarpt system använder man en riktig uttrycksparser i stället.)
Behärskning innebär
- Låter modellen anropa en funktion
- Hanterar svaret och felaktiga anrop
- Förklarar loopen anrop → resultat → svar
Logga in för att göra övningarna och bygga upp din behärskning.
Källor
- Anthropic — Tool use — dokumentation, fri läsning
- Python-dokumentationen (PSF-licens) — PSF
- JSON Schema — fri läsning