Başlarken
Rehber: araç çağıran ajanlar
Adım sınırı, paralel araç çalıştırma, yapılandırılmış nihai yanıt ve maliyet kontrolleriyle küçük bir tool-calling ajanı kurun; Python ve Node örnekleriyle.
Ajan bir döngüdür: model konuşmayı okur, araçlarınızdan birini veya birkaçını çağırmaya karar verir, siz bunları çalıştırıp sonuçları geri gönderirsiniz ve model yanıt verebilene kadar devam eder. api14, araç destekli her modelde OpenAI tools formatıyla bunu destekler; bu yüzden model kimliğini değiştirerek aynı kod OpenAI, Anthropic, Google ve diğer sağlayıcılarla çalışır.
Bu rehber; adım sınırı, paralel araç çalıştırma, yapılandırılmış nihai yanıt ve maliyet kontrolleri olan küçük bir ajan kurar. Kod, https://api14.com/api/v1 base URL'iyle resmi openai paketini kullanır.
Araçları tanımlama
Her araç bir ad, modelin okuduğu bir açıklama ve argümanları için bir JSON Schema'dan oluşur. Açıklamaları spesifik tutun; modelin tek dokümantasyonu onlardır.
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"}] # your database query
def get_shipment(order_id: str) -> dict:
return {"order_id": order_id, "carrier": "UPS", "eta": "2026-10-09"} # your API call
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"]},
}},
]
Adım sınırlı döngü
Her yineleme ayrı bir faturalandırılan istektir; bu yüzden adım sayısını her zaman sınırlayın. Araç hatalarını çökmek yerine modele içerik olarak döndürün; modeller genellikle argümanları düzelterek toparlar.
MAX_STEPS = 8
def run_tool(call):
try:
args = json.loads(call.function.arguments)
result = TOOLS[call.function.name](**args)
except Exception as e: # bad JSON, unknown tool, or your function failed
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"))
Döngüdeki her istekte tools gönderin. Birçok sağlayıcı, istekte araç tanımları yoksa bir tool mesajını reddeder.
Paralel araç çağrıları
parallel_tool_calls ile (desteklenen yerlerde varsayılan olarak açıktır) model tek turda birkaç çağrı isteyebilir; örneğin üç sipariş için get_shipment. Bunları eşzamanlı çalıştırın ve her çağrı için herhangi bir sırada bir tool mesajı ekleyin; tool_call_id her sonucu çağrısına bağlar. Node'da:
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`);
}
Araçlarınızın sırayla gerçekleşmesi gereken yan etkileri varsa (önce oluştur, sonra güncelle) parallel_tool_calls: false ayarlayın; böylece model her turda tek çağrı ister.
Yapılandırılmış nihai çıktı
Ajanın yanıtı başka bir koda girdi oluyorsa, bir şemaya uyan JSON isteyin. Basit ve taşınabilir bir desen, döngü bilgileri topladıktan sonra tek bir ek çağrı yapmaktır (buradaki messages, döngüdeki konuşmadır; bunu agent() fonksiyonundan yanıtla birlikte döndürün):
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", tools alanını istekte tutar (geçmiş araç mesajları içerdiği için gereklidir) ve yeni çağrıları engeller. Ayrıştırılan JSON'u her zaman doğrulayın. Bkz. Structured outputs.
Model seçimi
- Yetenek: modelin
supported_parametersalanındatoolsbulunmalıdır.GET /modelsile kontrol edin, bkz. Modeller. Son adım içinstructured_outputsveyaresponse_formatarayın. - Yönlendirme: isteklerin yalnızca gönderdiğiniz her parametreyi destekleyen sağlayıcılara gitmesi için
provider: { "require_parameters": true }ekleyin (Python'daextra_bodyile). Bkz. Sağlayıcı yönlendirme. - Boyut:
openai/gpt-5-minigibi küçük modeller, iyi tanımlanmış birkaç aracı güvenilir ve ucuz biçimde yönetir. Ajanın çok sayıda aracı, uzun çok adımlı planları varsa veya sürekli yanlış aracı seçiyorsa daha büyük bir modele geçin. - Araçlarınızla test edin: aynı 20 ila 50 gerçek görevi iki veya üç aday modelde çalıştırın ve başarı oranını, görev başına adım sayısını ve toplam
usage.costdeğerini karşılaştırın.
curl -s "https://api14.com/api/v1/models?category=text" \
| jq -r '.data[] | select(.supported_parameters | index("tools")) | "\(.id) \(.pricing.prompt)"'
Maliyeti kontrol etme
Bir ajan tek görev için çok sayıda istek yapabilir ve tüm konuşma her adımda yeniden gönderilir. Harcamayı birkaç düzeyde sınırlayın:
- Yukarıdaki gibi adım sınırı (
MAX_STEPS) ve istek başınamax_tokens. - Görev başına bütçe: adımlar boyunca
usage.costdeğerlerini toplayın ve eşiğinizi aştığında durun. - Kısa araç sonuçları: yalnızca modelin ihtiyaç duyduğu alanları döndürün. Büyük araç çıktıları sonraki her adımda girdi token'ı olarak ödenir.
- Anahtar başına günlük USD limiti: API anahtarları sayfasında ajan için özel bir anahtar oluşturun ve günlük limit koyun. Limite ulaşıldığında istekler bir sonraki UTC gününe kadar
429 daily_limit_reacheddöndürür; bu kodu yeniden deneyerek değil, ajanı durdurarak ele alın. - Model izin listesi: anahtarı test ettiğiniz modellerle sınırlayın; diğer her şey
403 model_not_alloweddöndürür. - Prompt caching: önbelleğe alınmış önek indirimlerinin geçerli olması için sistem prompt'unu ve araç tanımlarını her istekte aynı ve en başta tutun. Bkz. Prompt caching.
Bkz. Tool calling, Hız limitleri ve Hatalar.