Erste Schritte
Anleitung: Agenten mit Tool Calling
Bauen Sie eine Agenten-Schleife mit parallelen Tool-Aufrufen, Schrittlimit, strukturierter Ausgabe und Kostenkontrolle über die api14-API.
Ein Agent ist eine Schleife: Das Modell liest die Unterhaltung und entscheidet, ein oder mehrere Ihrer Tools aufzurufen, Sie führen sie aus und senden die Ergebnisse zurück, und das Modell macht weiter, bis es antworten kann. api14 unterstützt dies mit dem OpenAI-tools-Format bei jedem Modell mit Tool-Unterstützung, sodass derselbe Code mit OpenAI, Anthropic, Google und anderen Anbietern funktioniert, indem Sie die Modell-ID ändern.
Diese Anleitung baut einen kleinen Agenten mit Schrittlimit, paralleler Tool-Ausführung, strukturierter Endantwort und Kostenkontrolle. Der Code verwendet das offizielle Paket openai mit der Base URL https://api14.com/api/v1.
Tools definieren
Jedes Tool besteht aus einem Namen, einer Beschreibung, die das Modell liest, und einem JSON Schema für seine Argumente. Halten Sie die Beschreibungen konkret; sie sind die einzige Dokumentation des Modells.
import json, os
from openai import OpenAI
client = OpenAI(base_url="https://api14.com/api/v1", api_key=os.environ["API14_API_KEY"])
def search_orders(customer_email: str) -> list:
return [{"id": "A-1001", "status": "shipped"}] # Ihre Datenbankabfrage
def get_shipment(order_id: str) -> dict:
return {"order_id": order_id, "carrier": "UPS", "eta": "2026-10-09"} # Ihr API-Aufruf
TOOLS = {"search_orders": search_orders, "get_shipment": get_shipment}
tools = [
{"type": "function", "function": {
"name": "search_orders",
"description": "List a customer's orders with their status.",
"parameters": {"type": "object", "properties": {"customer_email": {"type": "string"}},
"required": ["customer_email"]},
}},
{"type": "function", "function": {
"name": "get_shipment",
"description": "Carrier and estimated delivery date for one order.",
"parameters": {"type": "object", "properties": {"order_id": {"type": "string"}},
"required": ["order_id"]},
}},
]
Die Schleife mit Schrittlimit
Jede Iteration ist eine eigene abgerechnete Anfrage, begrenzen Sie daher immer die Anzahl der Schritte. Geben Sie Tool-Fehler als Inhalt an das Modell zurück, statt abzustürzen; Modelle erholen sich meist, indem sie die Argumente korrigieren.
MAX_STEPS = 8
def run_tool(call):
try:
args = json.loads(call.function.arguments)
result = TOOLS[call.function.name](**args)
except Exception as e: # ungültiges JSON, unbekanntes Tool oder Ihre Funktion ist fehlgeschlagen
result = {"error": str(e)}
return {"role": "tool", "tool_call_id": call.id, "content": json.dumps(result)}
def agent(task, model="openai/gpt-5-mini"):
messages = [
{"role": "system", "content": "You are a support agent. Use tools to look things up. Be brief."},
{"role": "user", "content": task},
]
spent = 0.0
for step in range(MAX_STEPS):
r = client.chat.completions.create(model=model, messages=messages, tools=tools, max_tokens=1000)
spent += r.usage.cost
msg = r.choices[0].message
if not msg.tool_calls:
return msg.content, spent
messages.append(msg)
messages.extend(run_tool(call) for call in msg.tool_calls)
raise RuntimeError(f"No answer after {MAX_STEPS} steps (spent ${spent:.4f})")
print(agent("Where is my order? My email is ada@example.com"))
Senden Sie tools mit jeder Anfrage in der Schleife. Viele Anbieter lehnen eine tool-Nachricht ab, wenn die Anfrage keine Tool-Definitionen enthält.
Parallele Tool-Aufrufe
Mit parallel_tool_calls (wo unterstützt standardmäßig aktiv) kann ein Modell in einem Zug mehrere Aufrufe anfordern, zum Beispiel get_shipment für drei Bestellungen. Führen Sie sie parallel aus und hängen Sie pro Aufruf eine tool-Nachricht in beliebiger Reihenfolge an; tool_call_id verknüpft jedes Ergebnis mit seinem Aufruf. In Node:
import OpenAI from "openai";
const client = new OpenAI({ baseURL: "https://api14.com/api/v1", apiKey: process.env.API14_API_KEY });
const MAX_STEPS = 8;
async function agent(messages, tools, impl, model = "openai/gpt-5-mini") {
for (let step = 0; step < MAX_STEPS; step++) {
const res = await client.chat.completions.create({ model, messages, tools, max_tokens: 1000 });
const msg = res.choices[0].message;
if (!msg.tool_calls?.length) return msg.content;
messages.push(msg);
const results = await Promise.all(msg.tool_calls.map(async (call) => {
let content;
try {
content = JSON.stringify(await impl[call.function.name](JSON.parse(call.function.arguments)));
} catch (err) {
content = JSON.stringify({ error: String(err) });
}
return { role: "tool", tool_call_id: call.id, content };
}));
messages.push(...results);
}
throw new Error(`No answer after ${MAX_STEPS} steps`);
}
Wenn Ihre Tools Seiteneffekte haben, die in Reihenfolge geschehen müssen (erst anlegen, dann aktualisieren), setzen Sie parallel_tool_calls: false, damit das Modell pro Zug nur einen Aufruf anfordert.
Strukturierte Endausgabe
Wenn die Antwort des Agenten in anderen Code einfließt, fordern Sie JSON an, das einem Schema entspricht. Ein einfaches, portables Muster ist ein zusätzlicher Aufruf nach der Schleife, wenn die Fakten gesammelt sind (messages ist hier die Unterhaltung aus der Schleife; geben Sie sie aus agent() zusammen mit der Antwort zurück):
schema = {
"type": "object",
"properties": {
"order_id": {"type": "string"},
"status": {"type": "string", "enum": ["processing", "shipped", "delivered", "unknown"]},
"eta": {"type": ["string", "null"]},
"reply": {"type": "string"},
},
"required": ["order_id", "status", "eta", "reply"],
"additionalProperties": False,
}
final = client.chat.completions.create(
model="openai/gpt-5-mini",
messages=messages + [{"role": "user", "content": "Summarize the result for our ticket system."}],
tools=tools,
tool_choice="none",
response_format={"type": "json_schema", "json_schema": {"name": "ticket", "strict": True, "schema": schema}},
)
ticket = json.loads(final.choices[0].message.content)
tool_choice: "none" behält tools in der Anfrage (nötig, weil der Verlauf Tool-Nachrichten enthält) und verhindert zugleich weitere Aufrufe. Validieren Sie das geparste JSON immer. Siehe Strukturierte Ausgaben.
Ein Modell auswählen
- Fähigkeit: Das Modell muss
toolsinsupported_parametersaufführen. Prüfen Sie es mitGET /models, siehe Modelle. Für den letzten Schritt suchen Sie nachstructured_outputsoderresponse_format. - Routing: Fügen Sie
provider: { "require_parameters": true }hinzu (in Python überextra_body), damit Anfragen nur an Anbieter gehen, die jeden von Ihnen gesendeten Parameter unterstützen. Siehe Provider-Routing. - Größe: Kleine Modelle wie
openai/gpt-5-minibewältigen einige gut beschriebene Tools zuverlässig und günstig. Wechseln Sie zu einem größeren Modell, wenn der Agent viele Tools hat, lange mehrstufige Pläne braucht oder ständig das falsche Tool wählt. - Mit Ihren Tools testen: Lassen Sie dieselben 20 bis 50 echten Aufgaben mit zwei oder drei Kandidatenmodellen laufen und vergleichen Sie Erfolgsquote, Schritte pro Aufgabe und gesamtes
usage.cost.
curl -s "https://api14.com/api/v1/models?category=text" \
| jq -r '.data[] | select(.supported_parameters | index("tools")) | "\(.id) \(.pricing.prompt)"'
Kosten kontrollieren
Ein Agent kann für eine Aufgabe viele Anfragen stellen, und die gesamte Unterhaltung wird bei jedem Schritt erneut gesendet. Begrenzen Sie die Ausgaben auf mehreren Ebenen:
- Schrittlimit (
MAX_STEPS) undmax_tokenspro Anfrage, wie oben. - Budget pro Aufgabe: Summieren Sie
usage.costüber die Schritte und stoppen Sie, wenn Ihr Schwellenwert überschritten ist. - Kurze Tool-Ergebnisse: Geben Sie nur die Felder zurück, die das Modell braucht. Große Tool-Ausgaben werden bei jedem späteren Schritt als Eingabe-Tokens bezahlt.
- Tägliches USD-Limit pro Schlüssel: Erstellen Sie unter API-Schlüssel einen eigenen Schlüssel für den Agenten und setzen Sie ein Tageslimit. Ist es erreicht, liefern Anfragen bis zum nächsten UTC-Tag
429 daily_limit_reached; behandeln Sie diesen Code, indem Sie den Agenten stoppen, nicht durch Wiederholen. - Modell-Allowlist: Beschränken Sie den Schlüssel auf die getesteten Modelle; alles andere liefert
403 model_not_allowed. - Prompt Caching: Halten Sie System-Prompt und Tool-Definitionen identisch und in jeder Anfrage am Anfang, damit die Rabatte für zwischengespeicherte Präfixe greifen. Siehe Prompt Caching.
Siehe Tool Calling, Rate Limits und Fehler.