Agent Loop
Araç kullanım döngüsü
Modelin araç çağırdığı, sonucun modele geri verildiği ve bu turların bir durma koşulu sağlanana kadar tekrarlandığı temel ajan döngüsü.
Her ajanın kalbinde basit bir döngü vardır:
1. Harness, konuşma geçmişini ve araç tanımlarını modele gönderir.
2. Model ya son cevabı yazar ya da bir (veya birkaç) araç çağrısı
üretir.
3. Harness aracı çalıştırır, sonucu tool_result olarak geçmişe ekler.
4. Başa dön.
Anthropic API'sinde bu, stop_reason alanıyla okunur: değer
tool_use ise model araç bekliyordur; end_turn ise iş bitmiştir.
Claude Code dokümantasyonu aynı döngüyü üç evreyle anlatır: bağlam
topla, eyleme geç, sonucu doğrula — gerektiği kadar tekrarla.
Fikrin akademik kökü ReAct'tir (Yao vd., 2022, “ReAct: Synergizing
Reasoning and Acting in Language Models”): model akıl yürütme adımları
ile eylemleri iç içe üretir, her eylemin gözlemi bir sonraki düşünceyi
besler. Bugünkü API'ler bunu yerleşik hale getirdi: düşünme blokları
ve tool_use blokları aynı cevapta gelir.
Döngü kendi kendine durmayabilir, bu yüzden durma koşulları şarttır: modelin işi bitirmesi, maksimum tur sayısı, token/maliyet/süre bütçesi, kurtarılamaz bir hata ya da kullanıcının araya girmesi. Unutma: API durumsuzdur; her turda tüm geçmiş yeniden gönderilir. Tur sayısı arttıkça her çağrı biraz daha büyür.
Karanlık bir odada el yordamıyla elektrik düğmesini aramak gibi. Bir adım atarsın (eylem), duvara dokunursun (gözlem), “düğme genelde kapının yanında olur” diye düşünürsün (akıl yürütme), sonraki adımı buna göre atarsın. Düğmeyi bulunca durursun.
Ama akıllı biri bir de kural koyar: “On adımda bulamazsam telefonun fenerini açarım.” İşte o kural, döngünün max turns sınırıdır.
Kullanıcı: “Testleri düzelt.” Döngü şöyle akar:
- Tur 1: Model bash("npm test") ister → harness çalıştırır →
sonuç: 3 test başarısız.
- Tur 2: Model read("src/auth.ts") ister → dosya içeriği döner.
- Tur 3: Model edit(...) ile hatayı düzeltir → “ok”.
- Tur 4: Model yine bash("npm test") → hepsi geçti.
- Tur 5: Model araç istemez, “3 testi düzelttim, sebep şuydu…”
yazar. stop_reason = end_turn → döngü biter.
Model yanlış iz sürseydi ve 25 tur boyunca aynı aracı çağırsaydı, harness'taki tur sınırı devreye girip döngüyü keserdi.
import anthropic
client = anthropic.Anthropic()
MAX_TURNS = 20
tools = [{
"name": "run_command",
"description": "Proje klasöründe bir kabuk komutu çalıştırır, çıktısını döner",
"input_schema": {
"type": "object",
"properties": {"command": {"type": "string"}},
"required": ["command"],
},
}]
messages = [{"role": "user", "content": "Testleri çalıştır ve düzelt"}]
for turn in range(MAX_TURNS):
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=16000,
tools=tools,
messages=messages,
)
# Cevabın tamamını (metin + tool_use blokları) geçmişe ekle
messages.append({"role": "assistant", "content": response.content})
if response.stop_reason != "tool_use":
break # end_turn, max_tokens, refusal… → döngüden çık
results = []
for block in response.content:
if block.type == "tool_use":
try:
output = run_tool(block.name, block.input) # senin kodun
results.append({"type": "tool_result",
"tool_use_id": block.id,
"content": output})
except Exception as err:
results.append({"type": "tool_result",
"tool_use_id": block.id,
"content": str(err),
"is_error": True})
# Tüm sonuçlar tek bir user mesajında döner
messages.append({"role": "user", "content": results})
else:
print("Tur sınırına ulaşıldı, döngü durduruldu")from agents import Agent, Runner, function_tool, MaxTurnsExceeded
@function_tool
def get_order_status(order_id: str) -> str:
"""Sipariş numarasına göre kargo durumunu döner."""
return lookup_order(order_id) # senin kodun
agent = Agent(
name="Destek",
instructions="Sipariş sorularını araçları kullanarak yanıtla.",
tools=[get_order_status],
)
try:
# max_turns varsayılanı 10'dur; aşılırsa istisna fırlatılır
result = Runner.run_sync(agent, "TR-9921 nerede?", max_turns=6)
print(result.final_output)
except MaxTurnsExceeded:
print("Ajan 6 turda bitiremedi")- Kaç adım süreceği önceden bilinmeyen görevler — hata ayıklama, araştırma, kod değişikliği
- Her adımın sonucu bir sonraki adımı belirliyorsa (gözle → karar ver → eyleme geç)
- Modelin kendi çıktısını doğrulaması gerekiyorsa — test çalıştır, sonucu oku, tekrar dene
- Kendi harness'ını yazarken — her ajan çatısının altında bu döngü vardır
- Tek araç çağrısıyla biten işler — tek tur yeter, döngü kurma
- Adımları sabit bir iş akışı — sıralı, kod kontrollü çağrılar daha öngörülebilir
- Katı gecikme sınırı olan arayüzler — her tur ayrı bir model çağrısı ve ayrı bir bekleme demek
Durma koşulu koymamak
Model sonuca ulaşamazsa aynı aracı tekrar tekrar çağırabilir. Her zaman bir tur sınırı ve mümkünse token, maliyet ya da süre bütçesi koy; sınıra takılınca kullanıcıya ne olduğunu açıkça bildir.
tool_result'ı eksik ya da dağınık göndermek
Modelin ürettiği her tool_use bloğunun karşılığında bir tool_result dönmelidir; aksi halde API isteği reddeder. Paralel çağrıların sonuçlarını tek bir user mesajında topla.
Araç hatasında döngüyü çökertmek
Araç hata verdiğinde istisnayı yutup döngüyü bitirmek yerine hatayı is_error: true ile modele geri ver. Model çoğu zaman başka bir yol dener.
Sadece metni geçmişe eklemek
Cevaptan yalnızca metni alıp geçmişe yazarsan tool_use blokları ve düşünme blokları kaybolur, bir sonraki tur bozulur. response.content'in tamamını ekle.