# Agentic AI: Tool Use, Planner Loops ve Production Agent Mimarisi
"Yapay zeka bir şeyi çözebilir" ile "yapay zeka bir şeyi yapabilir" arasındaki fark — işte bu fark agentic AI'ı tanımlıyor. 2023'te bir araştırma konsepti olan LLM agent'ları, 2026'da ciddi production sistemlerinde çalışıyor: müşteri destek süreçlerini otomasyon altına alıyor, kod tabanlarında bug fix yapıyor, veri pipeline'larını yönetiyor. Ama bu güç beraberinde karmaşıklık getiriyor. Bir agent nasıl tasarlanır? Hangi framework seçilir? Hata durumlarını nasıl idare edersin? Latency ve maliyet nasıl optimize edilir? Bu yazı, teoriden production gerçekliğine uzanan tam bir rehber.
💡 Pro Tip: Agent mimarisi tasarlarken önce "en az agent gerekli" prensibiyle başla. Tek bir akıllı prompt ile çözülebilen her şeyi agent'a taşıma — karmaşıklık ve hata yüzeyini artırır.
İçindekiler
- LLM Agent Nedir? Temel Bileşenler
- Tool Use ve Function Calling Spec'leri
- Temel Agent Pattern'leri
- Memory Yönetimi: Kısa ve Uzun Vadeli
- Framework Karşılaştırması: LangGraph, AutoGen, CrewAI
- Multi-Agent Koordinasyonu
- Error Recovery ve Güvenilirlik
- Observability ve Debugging
- Gerçek Production Örneği: Müşteri Destek Agent'ı
- Sonuç ve Karar Rehberi
LLM Agent Nedir? Temel Bileşenler
Klasik LLM: soru → cevap. Tek adım, tek yön.
LLM Agent: hedef → plan → araç kullan → gözlemle → plan güncelle → araç kullan → ... → sonuç. Çok adımlı, döngüsel, kendi kendini yönlendiren.
Bir agent'ın 4 temel bileşeni var:
typescript
1interface AgentArchitecture {2 // 1. LLM — "beyin": karar veren, planlayan, akıl yürüten3 brain: LLMClient;4 5 // 2. Tools — "eller": dünyayla etkileşim araçları6 tools: Map; 7 8 // 3. Memory — "hafıza": kısa ve uzun vadeli bilgi depolama9 memory: {10 shortTerm: ConversationHistory; // mevcut görev bağlamı11 longTerm: VectorMemory; // kalıcı bilgi deposu12 };13 14 // 4. Planning — "koordinatör": hangi araç, ne zaman, hangi sırada15 planner: PlanningStrategy;16}17 18interface Tool {19 name: string;20 description: string; // LLM bu açıklamayı okuyarak aracı seçiyor21 parameters: JSONSchema;22 execute: (params: unknown) => Promise; 23}Tool Use ve Function Calling Spec'leri
Her major AI sağlayıcısının function calling spec'i var. Format farklı ama konsept aynı: modele "şu araçlar mevcut" diyorsun, model cevap yerine araç çağrısı dönebiliyor.
OpenAI Function Calling
python
1import openai2import json3 4client = openai.OpenAI()5 6tools = [7 {8 "type": "function",9 "function": {10 "name": "search_database",11 "description": "Ürün veritabanında arama yap. Fiyat, stok ve ürün detayları döner.",12 "parameters": {13 "type": "object",14 "properties": {15 "query": {16 "type": "string",17 "description": "Arama sorgusu"18 },19 "category": {20 "type": "string",21 "enum": ["elektronik", "giyim", "gıda"],22 "description": "Ürün kategorisi (opsiyonel)"23 },24 "max_price": {25 "type": "number",26 "description": "Maksimum fiyat (TL)"27 }28 },29 "required": ["query"]30 }31 }32 }33]34 35response = client.chat.completions.create(36 model="gpt-4.7",37 messages=[38 {"role": "user", "content": "1000 TL altında en iyi kablosuz kulaklıkları göster"}39 ],40 tools=tools,41 tool_choice="auto"42)43 44message = response.choices[0].message45if message.tool_calls:46 for call in message.tool_calls:47 fn_name = call.function.name48 fn_args = json.loads(call.function.arguments)49 result = execute_tool(fn_name, fn_args)Anthropic Tool Use
python
1import anthropic2 3client = anthropic.Anthropic()4 5tools = [6 {7 "name": "get_weather",8 "description": "Belirtilen şehir için güncel hava durumu bilgisi al",9 "input_schema": {10 "type": "object",11 "properties": {12 "city": {13 "type": "string",14 "description": "Şehir adı"15 },16 "unit": {17 "type": "string",18 "enum": ["celsius", "fahrenheit"],19 "default": "celsius"20 }21 },22 "required": ["city"]23 }24 }25]26 27response = client.messages.create(28 model="claude-opus-4-7",29 max_tokens=1024,30 tools=tools,31 messages=[32 {"role": "user", "content": "İstanbul'da bugün hava nasıl?"}33 ]34)35 36for block in response.content:37 if block.type == "tool_use":38 result = execute_tool(block.name, block.input)39 # Sonucu modele geri gönder40 continue_response = client.messages.create(41 model="claude-opus-4-7",42 max_tokens=1024,43 tools=tools,44 messages=[45 {"role": "user", "content": "İstanbul'da bugün hava nasıl?"},46 {"role": "assistant", "content": response.content},47 {"role": "user", "content": [48 {"type": "tool_result", "tool_use_id": block.id, "content": str(result)}49 ]}50 ]51 )Paralel Tool Çağrısı
2026'da hem OpenAI hem de Anthropic paralel tool çağrısını destekliyor:
typescript
1async function executeParallelTools(2 toolCalls: ToolCall[],3 tools: Map 4): Promise { 5 // Paralel çalıştır — latency düşer6 return Promise.all(7 toolCalls.map(async (call) => {8 const tool = tools.get(call.name);9 if (!tool) throw new Error(`Tool not found: ${call.name}`);10 11 try {12 const result = await tool.execute(call.params);13 return { id: call.id, success: true, result };14 } catch (error) {15 return { id: call.id, success: false, error: String(error) };16 }17 })18 );19}Temel Agent Pattern'leri
Plan-and-Execute
Önce bir plan üret, sonra adım adım uygula. Planı en başta yapmak, sonradan değiştirmekten daha verimli.
python
1class PlanAndExecuteAgent:2 def __init__(self, llm, tools):3 self.llm = llm4 self.tools = tools5 6 async def run(self, task: str) -> str:7 # 1. Görev analizi ve plan üretimi8 plan = await self.create_plan(task)9 10 results = []11 for step in plan['steps']:12 result = await self.execute_step(step, results)13 results.append(result)14 15 # Gerekirse planı güncelle16 if result.get('needs_replan'):17 plan = await self.replan(task, plan, results)18 19 return await self.synthesize(task, results)20 21 async def create_plan(self, task: str) -> dict:22 prompt = f"""Görevi alt adımlara böl. Her adım bağımsız çalıştırılabilmeli.23 24GÖREV: {task}25MEVCUT ARAÇLAR: {list(self.tools.keys())}26 27JSON döndür:28{{"steps": [{{"id": 1, "description": "...", "tool": "...", "depends_on": []}}]}}"""29 response = await self.llm.complete(prompt)30 return json.loads(response)Reflexion Pattern
Shinn et al. 2023'ten. Model görev başarısız olunca hatayı analiz eder ve "refleksiyon" üretir. Bu refleksiyon sonraki denemeye eklenir.
python
1class ReflexionAgent:2 def __init__(self, llm, tools, max_trials: int = 3):3 self.llm = llm4 self.tools = tools5 self.max_trials = max_trials6 7 async def run(self, task: str) -> str:8 reflections: list[str] = []9 10 for trial in range(self.max_trials):11 result = await self.attempt(task, reflections)12 13 if result['success']:14 return result['output']15 16 reflection = await self.reflect(task, result)17 reflections.append(reflection)18 19 raise RuntimeError(f"Görev {self.max_trials} denemede çözülemedi")20 21 async def reflect(self, task: str, result: dict) -> str:22 prompt = f"""Görev başarısız oldu. Neyi yanlış yaptın?23 24GÖREV: {task}25ALINAN HATA: {result.get('error')}26YAPILAN EYLEMLER: {result.get('actions')}27 28Kısa, spesifik analiz yaz (max 100 kelime):"""29 return await self.llm.complete(prompt)Memory Yönetimi: Kısa ve Uzun Vadeli
Kısa Vadeli Bellek
Mevcut konuşma/görev geçmişi. Token limitleri nedeniyle yönetim gerektirir.
typescript
1class ConversationMemory {2 private messages: Message[] = [];3 private readonly maxTokens: number;4 5 constructor(maxTokens = 8000) {6 this.maxTokens = maxTokens;7 }8 9 add(message: Message): void {10 this.messages.push(message);11 this.enforceLimit();12 }13 14 private async enforceLimit(): Promise { 15 const currentTokens = this.estimateTokenCount();16 17 if (currentTokens > this.maxTokens * 0.8) {18 // Eski mesajları özetle — son 4'ü koru19 const toSummarize = this.messages.slice(0, -4);20 const summary = await this.summarize(toSummarize);21 22 this.messages = [23 { role: 'system', content: `Önceki konuşma özeti: ${summary}` },24 ...this.messages.slice(-4)25 ];26 }27 }28 29 private estimateTokenCount(): number {30 return this.messages.reduce((total, m) => total + m.content.length / 4, 0);31 }32}Uzun Vadeli Bellek (Semantic Memory)
python
1class SemanticMemory:2 def __init__(self, vector_db, embedder):3 self.db = vector_db4 self.embedder = embedder5 6 async def store(self, key: str, content: str, metadata: dict = {}):7 embedding = await self.embedder.embed(content)8 await self.db.upsert({9 "id": key,10 "vector": embedding,11 "metadata": {"content": content, **metadata}12 })13 14 async def recall(self, query: str, k: int = 5) -> list[str]:15 query_vec = await self.embedder.embed(query)16 results = await self.db.search(query_vec, k)17 return [r.metadata["content"] for r in results]18 19 async def build_context_block(self, query: str) -> str:20 memories = await self.recall(query)21 if not memories:22 return ""23 lines = "24".join(f"- {m}" for m in memories)25 return f"26 27İlgili geçmiş bilgi:28{lines}"Framework Karşılaştırması: LangGraph, AutoGen, CrewAI
LangGraph
LangChain ekibinin geliştirdiği, state machine tabanlı agent framework. DAG yapısında agent akışları modelleniyor.
Güçlü yönleri:
- Karmaşık, dallanmalı iş akışları
- Durumun açıkça modellenmesi
- LangSmith ile built-in observability
Zayıf yönleri:
- LangChain bağımlılığı, öğrenme eğrisi yüksek
- Basit kullanım için fazla karmaşık
AutoGen (Microsoft)
Multi-agent konuşmalar için tasarlandı. Agent'lar birbirleriyle sohbet ediyor.
python
1import autogen2 3config_list = [{"model": "gpt-4.7", "api_key": "YOUR_KEY"}]4 5planner = autogen.AssistantAgent(6 name="Planner",7 system_message="Görevleri alt adımlara böl ve koordine et.",8 llm_config={"config_list": config_list}9)10 11coder = autogen.AssistantAgent(12 name="Coder",13 system_message="Python kodu yaz ve çalıştır.",14 llm_config={"config_list": config_list}15)16 17critic = autogen.AssistantAgent(18 name="Critic",19 system_message="Kodu gözden geçir, hata ve iyileştirme öner.",20 llm_config={"config_list": config_list}21)22 23user_proxy = autogen.UserProxyAgent(24 name="UserProxy",25 human_input_mode="NEVER",26 code_execution_config={"work_dir": "coding"}27)28 29group_chat = autogen.GroupChat(30 agents=[planner, coder, critic, user_proxy],31 messages=[],32 max_round=1033)34manager = autogen.GroupChatManager(groupchat=group_chat, llm_config={"config_list": config_list})CrewAI
Role-based multi-agent framework. Her agent bir "rol" üstleniyor. Öğrenme eğrisi düşük, ama production stability henüz beta seviyesinde.
Özellik | LangGraph | AutoGen | CrewAI |
|---|---|---|---|
Öğrenme eğrisi | Yüksek | Orta | Düşük |
Karmaşık iş akışları | Excellent | İyi | Orta |
Multi-agent kolay | Orta | Excellent | Excellent |
Production stability | İyi | Beta | Beta |
Observability | Excellent | Orta | Sınırlı |
Multi-Agent Koordinasyonu
Orchestrator-Worker Pattern
typescript
1class MultiAgentOrchestrator {2 private workers = new Map(); 3 4 register(role: string, agent: WorkerAgent): void {5 this.workers.set(role, agent);6 }7 8 async executeTask(task: ComplexTask): Promise { 9 const subTasks = await this.decompose(task);10 11 // Bağımsız görevleri paralel çalıştır12 const results = new Map(); 13 const groups = this.groupByDependency(subTasks);14 15 for (const group of groups) {16 const groupResults = await Promise.all(17 group.map((st) => {18 const worker = this.workers.get(st.requiredRole);19 if (!worker) throw new Error(`No worker for role: ${st.requiredRole}`);20 return worker.execute(st, results);21 })22 );23 groupResults.forEach((r, i) => results.set(group[i].id, r));24 }25 26 return this.synthesize(task, results);27 }28}Error Recovery ve Güvenilirlik
Hata Kategorileri ve Stratejiler
typescript
1const enum AgentErrorType {2 ToolTimeout = 'TOOL_TIMEOUT',3 ToolRateLimit = 'TOOL_RATE_LIMIT',4 ContextOverflow = 'LLM_CONTEXT_OVERFLOW',5 ToolExecutionError = 'TOOL_EXECUTION_ERROR',6 PlanningFailure = 'PLANNING_FAILURE',7 MaxIterations = 'MAX_ITERATIONS_EXCEEDED',8}9 10interface RetryStrategy {11 retry: boolean;12 maxRetries?: number;13 backoffMs?: number;14 exponential?: boolean;15 action?: 'COMPRESS_CONTEXT' | 'REPLAN';16 escalate?: boolean;17}18 19const ERROR_STRATEGIES: Record = { 20 [AgentErrorType.ToolTimeout]: { retry: true, maxRetries: 3, backoffMs: 1000, exponential: true },21 [AgentErrorType.ToolRateLimit]: { retry: true, maxRetries: 5, backoffMs: 5000, exponential: true },22 [AgentErrorType.ContextOverflow]: { retry: true, maxRetries: 1, action: 'COMPRESS_CONTEXT', backoffMs: 0 },23 [AgentErrorType.PlanningFailure]: { retry: true, maxRetries: 2, action: 'REPLAN', backoffMs: 0 },24 [AgentErrorType.MaxIterations]: { retry: false, escalate: true },25 [AgentErrorType.ToolExecutionError]: { retry: true, maxRetries: 2, backoffMs: 500, exponential: false },26};Circuit Breaker Pattern
python
1import time2 3class CircuitBreaker:4 def __init__(self, failure_threshold: int = 5, recovery_timeout: int = 60):5 self.failure_threshold = failure_threshold6 self.recovery_timeout = recovery_timeout7 self.failure_count = 08 self.last_failure_time: float | None = None9 self.state = "CLOSED" # CLOSED, OPEN, HALF_OPEN10 11 async def call(self, func, *args, **kwargs):12 if self.state == "OPEN":13 elapsed = time.time() - (self.last_failure_time or 0)14 if elapsed > self.recovery_timeout:15 self.state = "HALF_OPEN"16 else:17 raise RuntimeError("Circuit breaker OPEN — araç geçici olarak devre dışı")18 19 try:20 result = await func(*args, **kwargs)21 self._on_success()22 return result23 except Exception as exc:24 self._on_failure()25 raise26 27 def _on_success(self):28 self.failure_count = 029 self.state = "CLOSED"30 31 def _on_failure(self):32 self.failure_count += 133 self.last_failure_time = time.time()34 if self.failure_count >= self.failure_threshold:35 self.state = "OPEN"Observability ve Debugging
Agent'ları debug etmek klasik uygulamalardan çok daha karmaşık. Çok adımlı, dallanabilir, araç çağrıları olan sistemlerde sorun tespiti zordur.
Temel Tracing
python
1import structlog2import time3 4logger = structlog.get_logger()5 6class ObservableAgent:7 async def execute_step(self, step: dict) -> dict:8 step_id = step['id']9 step_type = step['type']10 11 logger.info("agent_step_start", step_id=step_id, step_type=step_type)12 start_time = time.time()13 14 try:15 result = await self._run_step(step)16 duration_ms = (time.time() - start_time) * 100017 18 logger.info(19 "agent_step_complete",20 step_id=step_id,21 duration_ms=round(duration_ms, 1),22 success=True23 )24 return result25 26 except Exception as exc:27 logger.error(28 "agent_step_failed",29 step_id=step_id,30 error=str(exc),31 duration_ms=round((time.time() - start_time) * 1000, 1)32 )33 raiseGerçek Production Örneği: Müşteri Destek Agent'ı
Bir e-ticaret şirketinin tier-1 müşteri destek sürecini ele alalım. Günde ~2000 bilet, %70'i şu konularda: sipariş durumu, iade talebi, ürün bilgisi.
Mimari
typescript
1const customerSupportAgent = {2 model: "claude-opus-4-7",3 maxIterations: 8,4 5 tools: [6 {7 name: "get_order_status",8 description: "Müşterinin sipariş durumunu ve kargo bilgisini döner",9 parameters: {10 order_id: { type: "string", required: true },11 customer_email: { type: "string", required: false }12 }13 },14 {15 name: "initiate_return",16 description: "İade talebi başlatır ve iade talimatları döner",17 parameters: {18 order_id: { type: "string", required: true },19 reason: {20 type: "string",21 enum: ["defective", "wrong_item", "not_as_described", "change_of_mind"]22 }23 }24 },25 {26 name: "search_product_info",27 description: "Ürün özellikleri, stok durumu ve fiyat bilgisi",28 parameters: {29 query: { type: "string", required: true }30 }31 },32 {33 name: "escalate_to_human",34 description: "Karmaşık veya hassas durumları insan temsilciye aktar",35 parameters: {36 reason: { type: "string" },37 priority: { type: "string", enum: ["low", "medium", "high", "urgent"] },38 summary: { type: "string" }39 }40 }41 ],42 43 systemPrompt: `Sen [Şirket] müşteri destek asistanısın.44Nazik, çözüm odaklı ve verimli ol.45Müşteri bilgilerini doğrulamadan hassas işlem yapma.46Çözüm bulamazsan insan temsilciye eskalasyon yap.`47};3 Aylık Production Sonuçları
Metrik | Agent | Önceki (Manuel) | İyileşme |
|---|---|---|---|
Ortalama çözüm süresi | 2.3 dakika | 18 dakika | 7.8x hız |
İlk temas çözüm oranı | %74 | %58 | +16 puan |
Müşteri memnuniyeti | 4.1/5 | 3.8/5 | +8% |
Eskalasyon oranı | %26 | %42 | -38% |
Maliyet/bilet | $0.38 | $3.20 | 8.4x tasarruf |
ALTIN İPUCU
Bu yazının en değerli bilgisi
Bu ipucu, yazının en önemli çıkarımını içeriyor.
Easter Egg
Gizli bir bilgi buldun!
Bu bölümde gizli bir bilgi var. Keşfetmek ister misin?
Okuyucu Ödülü
Agent geliştirmeye başlarken harcayabileceğin en değerli zaman: **LangSmith veya Arize Phoenix ile ilk 50 çağrını trace et ve incele.** Deneyimler gösteriyor ki uygulayıcıların %90'ı "agent karmaşık planlama yaptı" sandığı şeyin aslında tek bir tool çağrısıyla çözülebilecek bir görev olduğunu fark ediyor. Bu analiz, mimarini basitleştirmene ve maliyeti dramatik ölçüde düşürmene yardımcı olur.
Sonuç
Agentic AI 2026'da olgunluktan üretime geçiş döneminde. Araçlar hazır, pattern'ler test edilmiş, maliyet makul hale geldi. Ama başarılı production sistemleri mutlaka şu özelliklere sahip:
- Minimal karmaşıklık: Agent'ı yalnızca gerekli olduğunda kullan
- Kapsamlı observability: Her adımı logla, trace et
- Sağlam hata yönetimi: Circuit breaker, retry, eskalasyon
- Açık state tracking: Modelin "aklında" bir şey tutmasını bekleme
Paralel multi-agent sistemler için Claude Multi-Agent Teams yazısına, MCP ile araç entegrasyonu için MCP Protocol yazısına bakabilirsin.

