Blog'a Dön
AI AgentsAutonomous AITool UsePlanning

AI Agent'lar: Gerçekte İşe Yarayan Ne, Yaramayan Ne?

AI agent'lara sahadan bir bakış — ReAct, Plan-and-Execute gibi mimari yaklaşımlar, tool use, memory sistemleri, multi-agent orchestration ve kimsenin pek konuşmadığı sınırlamalar.

Yayınlanma 2026-02-05|11 dk

Bir Agent'ı Agent Yapan Şey Ne?

Açıkçası "AI agent" terimi son dönemin en suistimal edilen kavramlarından biri oldu. Herkes her şeye agent diyor. Ama özüne bakarsanız, bir agent aslında basit bir şey: çevresini gözlemleyen, ne yapması gerektiğine karar veren, harekete geçen, sonucu kontrol eden ve iş bitene kadar bu döngüyü tekrarlayan bir sistem. Bu, tek bir soruya tek bir cevap verip işi bitiren chatbot'lardan temelden farklı.

Gerçek bir agent'ı süslü bir API wrapper'ından ayıran üç temel özellik var. Birincisi, otonomi: sistem her adımda sizin yönlendirmenizi beklemeden kendi kararını veriyor. İkincisi, tool use: agent gerektiğinde arama motorlarına, veritabanlarına, code interpreter'lara, API'lere uzanabiliyor. Üçüncüsü, planning: büyük bir hedefi küçük parçalara ayırıyor ve yeni bilgiler geldikçe planını güncelliyor. Bunlardan biri bile eksikse, elinizde olan bir chain, bir pipeline ya da tool erişimi olan bir asistan. Agent değil.

Bu ayrım kılı kırk yarmak değil. Sistemi nasıl kurduğunuz, test ettiğiniz ve debug ettiğiniz, hangi kategoride olduğunuza göre kökten değişiyor.

Agent'ı tanımlayan altındaki model değil, çalıştırdığı döngü. GPT-4 seviyesinde bir model tek bir soruyu yanıtlıyorsa — agent değil. Daha küçük bir model gözlem ve eylem arasında döngü kurarak bir işi bitiriyorsa — işte o agent.

Gerçekten Önemli Olan Mimari Yaklaşımlar

Agent geliştirmek için birkaç farklı mimari yaklaşım var. Her birinin güvenilirlik, hız ve karmaşıklık arasında farklı trade-off'ları var. Doğru yaklaşımı seçmek projenizi yapabilir de yıkabilir de. Gelin üç büyük yaklaşıma bakalım.

ReAct (Reason + Act)

ReAct, agent mimarilerinin temel taşı. Reasoning ve action'ı tek bir döngüde birleştiriyor: düşün, bir eylem seç, çalıştır, sonuca bak, tekrarla. Model yeterli bilgiye sahip olduğuna karar verene kadar devam ediyor. ReAct'in güzelliği basitliğinde — kurması kolay, debug etmesi kolay (modelin düşünce sürecini birebir okuyabiliyorsunuz) ve on adımın altındaki görevlerde gayet iyi çalışıyor.

Ama bir sorun var: ReAct sadece bir adım ileriye bakıyor. Birçok alt görev arasında koordinasyon gerektiren karmaşık işlerde, agent ana hedeften sapıp alakasız şeyler yapmaya başlayabiliyor. Hata kurtarma da zayıf. Bir tool call patlarsa, modelin yapısal bir backtracking mekanizması olmadan kendi kendine çözüm bulması gerekiyor.

Plan-and-Execute

Plan-and-Execute farklı bir yaklaşım izliyor: planlama ve yürütmeyi iki ayrı aşamaya bölüyor. Bir planner model baştan yapılandırılmış bir adım adım plan çıkarıyor, bir executor model de her adımı sırayla uyguluyor. Her adım tamamlandıktan sonra planner kalan adımları öğrendiklerine göre güncelleyebiliyor. Daha tutarlı çok adımlı davranış elde ediyorsunuz ve bir şey çalışmadan önce tüm planı görebiliyorsunuz — debug ve monitoring için çok değerli.

Dezavantajı ne? Daha fazla latency, daha fazla token. Planlama aşaması başta bir ekstra LLM çağrısı ekliyor, potansiyel olarak her execution adımından sonra da. Ayrıca görevin önceden parçalanabileceğini varsayıyor — hedefin kendisinin belirsiz olduğu keşif amaçlı görevlerde bu varsayım tutmayabiliyor.

LATS, Monte Carlo Tree Search fikirlerini agent dünyasına taşıyor. Tek bir yol izlemek yerine birden fazla dalı paralel olarak keşfediyor, ara durumları puanlıyor (genellikle başka bir LLM çağrısıyla) ve bir dal çıkmaz gibi görünürse geri dönüyor. İlk hamlenin belirsiz olduğu görevlerde — karmaşık coding problemleri, multi-hop araştırma soruları gibi — sonuçları ciddi şekilde iyileştiriyor.

Ama ciddi bir maliyeti var. ReAct ya da Plan-and-Execute'a kıyasla 5x ile 20x arası daha fazla LLM çağrısından bahsediyoruz. Üstüne scoring fonksiyonu ve branching mantığı için dikkatli mühendislik gerekiyor. LATS'ı doğru sonuç almanın hız ve maliyetten çok daha önemli olduğu durumlarda kullanın.

Tool Use ve Function Calling

Tool use, bir dil modelini süslü bir metin üreticisinden gerçek dünyada iş yapabilen bir şeye dönüştüren mekanizma. Modern LLM'ler function calling'i doğal olarak destekliyor: modele mevcut tool'ların schema'sını veriyorsunuz, model ne zaman birini çağıracağına karar veriyor ve schema'ya uygun yapılandırılmış argümanlar üretiyor. Runtime fonksiyonu çalıştırıyor ve sonucu konuşmaya geri besliyor.

Pratikte tool tasarımı, model seçimi kadar önemli — belki daha da önemli. Her tool tek bir işi iyi yapmalı, net bir isim ve açıklamaya sahip olmalı. Input schema'larınızı sıkı tutun: serbest biçimli string'ler yerine enum'lar ve kısıtlı tipler kullanın ki hallucinate edilen argümanlar azalsın. Output'ları da kısa tutun — 200 token'lık bir özetin yeterli olacağı yerde 10.000 token'lık bir doküman döndürmek hem context alanını israf ediyor hem sonraki reasoning'i bulandırıyor.

python
from typing import Any
import json
import httpx

# LLM için yapılandırılmış şemalar olarak araçları tanımlayın
tools = [
    {
        "type": "function",
        "function": {
            "name": "search_knowledge_base",
            "description": "İlgili belgeler için dahili bilgi tabanını arayın. Kullanıcı şirket politikaları, prosedürler veya teknik belgeler hakkında soru sorduğunda bunu kullanın.",
            "parameters": {
                "type": "object",
                "properties": {
                    "query": {
                        "type": "string",
                        "description": "Doğal dilde arama sorgusu"
                    },
                    "max_results": {
                        "type": "integer",
                        "default": 5,
                        "description": "Döndürülecek maksimum sonuç sayısı"
                    },
                    "filters": {
                        "type": "object",
                        "properties": {
                            "category": {
                                "type": "string",
                                "enum": ["policy", "technical", "hr", "finance"]
                            },
                            "date_after": {
                                "type": "string",
                                "format": "date"
                            }
                        }
                    }
                },
                "required": ["query"]
            }
        }
    }
]

# Araç yürütmeli ajan döngüsü
async def agent_loop(client, messages: list[dict], max_iterations: int = 10):
    """Tamamlanana kadar araç çağrısıyla ajan döngüsünü çalıştırın."""
    for _ in range(max_iterations):
        response = await client.chat.completions.create(
            model="gpt-4o",
            messages=messages,
            tools=tools,
            tool_choice="auto"
        )

        message = response.choices[0].message
        messages.append(message.model_dump())

        # Araç çağrısı yoksa ajan tamamlanmıştır
        if not message.tool_calls:
            return message.content

        # Her araç çağrısını yürütün ve sonuçları ekleyin
        for tool_call in message.tool_calls:
            result = await execute_tool(
                tool_call.function.name,
                json.loads(tool_call.function.arguments)
            )
            messages.append({
                "role": "tool",
                "tool_call_id": tool_call.id,
                "content": json.dumps(result)
            })

    raise RuntimeError("Ajan maksimum yineleme sayısını aştı")

OpenAI API ile tool calling kullanan temel bir agent döngüsü

İnsanları şaşırtan bir şey var: katı schema'larla bile modeller bazen teknik olarak geçerli JSON üretiyor ama anlamsal olarak yanlış oluyor. Tarihsel bir sorgu için gelecek tarih, sıfır sonuç döndüren bir filtre değeri gibi. Model çıktısı ile gerçek tool execution arasına hafif bir validation katmanı eklemek bir sürü baş ağrısından kurtarıyor — ve modele düzeltme yapması için kullanışlı hata mesajları veriyor.

Memory Sistemleri

Memory olmadan agent'ınız tek bir context window'a sığanla sınırlı kalıyor. Kısa görevler için sorun değil ama uzun süren, birden fazla session'a yayılan ya da zamanla bilgi biriktirmesi gereken bir şey yapıyorsanız, yapılandırılmış memory şart. Pratikte üç tip kendini kanıtladı.

Kısa Süreli (Working) Memory

Bu aslında tek bir agent çalışması içindeki konuşma geçmişi ve not defteri — LLM'ye ilettiğiniz mesaj listesi. Ana zorluk context window yönetimi: konuşma büyüdükçe eski mesajları özetleyip çıkarmanız ya da atmanız gerekiyor ki token limitlerinin içinde kalasınız. Eski turn'lerin periyodik özetlemesiyle sliding window en yaygın yaklaşım ve çoğu durum için gayet iyi çalışıyor.

Uzun Süreli (Semantic) Memory

Uzun süreli memory session'lar arasında kalıcı, genelde arkasında bir vector database var. Her görevden sonra agent önemli bilgileri, kararları ve sonuçları çıkarıp embedding olarak saklıyor. İlgili bir görev geldiğinde o anıları çekip prompt'a enjekte ediyor. Bu sayede agent modeli yeniden eğitmeden deneyimlerinden öğrenebiliyor. Zor kısım bakım — düzgün deduplication ve relevance filtering yapmazsanız memory store zamanla gürültüyle doluyor ve retrieval kalitesi düşüyor.

Episodic Memory

Episodic memory geçmiş çalışmaların tam izini tutuyor — baştan sona her düşünce, eylem ve gözlem. Agent benzer bir görevle karşılaştığında ilgili episode'ları çekip few-shot example olarak kullanıyor. Özellikle başarı ve başarısızlık kalıpları net olan görevlerde çok etkili, çünkü agent hem neyin işe yaradığını hem neyin yaramadığını öğrenebiliyor.

python
from dataclasses import dataclass, field
from datetime import datetime

@dataclass
class MemoryEntry:
    content: str
    embedding: list[float]
    timestamp: datetime
    source: str  # "conversation", "tool_result", "reflection"
    importance: float = 0.5  # 0.0 ile 1.0 arası, ajan tarafından belirlenir
    access_count: int = 0

class AgentMemory:
    """Kısa süreli ve uzun süreli depolamayı birleştiren hibrit bellek sistemi."""

    def __init__(self, vector_store, max_short_term: int = 20):
        self.short_term: list[dict] = []
        self.vector_store = vector_store
        self.max_short_term = max_short_term

    def add_to_short_term(self, message: dict):
        self.short_term.append(message)
        if len(self.short_term) > self.max_short_term:
            self._summarize_and_archive()

    async def retrieve_relevant(self, query: str, k: int = 5) -> list[MemoryEntry]:
        """Bir sorgu için en ilgili uzun süreli anıları alın."""
        results = await self.vector_store.similarity_search(query, k=k)
        # Son erişilen ve yüksek önemli anıları artırın
        scored = []
        for entry in results:
            recency = 1.0 / (1.0 + (datetime.now() - entry.timestamp).days)
            score = 0.5 * entry.importance + 0.3 * recency + 0.2 * entry.access_count / 100
            entry.access_count += 1
            scored.append((score, entry))
        scored.sort(key=lambda x: x[0], reverse=True)
        return [entry for _, entry in scored[:k]]

    def _summarize_and_archive(self):
        """En eski kısa süreli mesajları özetleyin ve uzun süreli belleğe taşıyın."""
        to_archive = self.short_term[:5]
        self.short_term = self.short_term[5:]
        # Üretimde, arşivlemeden önce özetlemek için LLM'yi çağırın
        for msg in to_archive:
            self.vector_store.add(msg["content"], source="conversation")

Kısa süreli konuşma geçmişi ile uzun süreli vector-backed retrieval'ı birleştiren hibrit memory sistemi

Multi-Agent Orchestration

Görevler yeterince karmaşıklaştığında tek bir agent tutarlılığı korumakta zorlanmaya başlıyor. Multi-agent orchestration işi özelleşmiş agent'lara dağıtarak bu sorunu çözüyor — her birinin kendi tool'ları, system prompt'u ve uzmanlık alanı var. İki ana yaklaşım görüyorsunuz: bir koordinatör agent'ın worker'lara iş dağıttığı supervisor mimarisi ve agent'ların ortak kanallar üzerinden doğrudan konuştuğu peer-to-peer yapılar.

Production sistemler için supervisor pattern en sağlam seçenek. Üst düzey bir agent kullanıcı isteğini alıyor, alt görevlere bölüyor, her birini bir uzman agent'a yönlendiriyor, sonuçları topluyor ve nihai yanıtı oluşturuyor. Her uzman bağımsız olarak test edilebiliyor, versiyonlanabiliyor ve optimize edilebiliyor. Birinde arıza olursa supervisor tekrar deneyebiliyor, yedek bir agent'a yönlendirebiliyor ya da kısmi sonuç döndürebiliyor — tüm sistem çökmüyor.

Peer-to-peer mimariler teoride harika görünüyor — daha esnek, daha dinamik. Pratikte? Koordinasyon kabusu. Merkezi bir koordinatör olmadan agent'lar sonsuz delegation döngüsüne girebiliyor, çelişkili output'lar üretebiliyor ya da birbirini beklerken kilitlenebiliyor. Sonunda o kadar çok guardrail eklemeniz gerekiyor — mesaj limitleri, timeout'lar, conflict resolution — ki aslında ekstra adımlarla supervisor pattern'ı yeniden icat etmiş oluyorsunuz.

Warning

Multi-agent sistemler hem maliyetinizi hem hata modlarınızı katlar. İkinci bir agent eklemeden önce kendinize ciddi ciddi sorun: daha iyi tool'lar ve daha detaylı bir prompt ile tek bir agent bu işi halledemez mi? İşi gören en basit mimari neredeyse her zaman doğru tercihtir.

Kimsenin Pek Konuşmadığı Sınırlamalar

Demo'lar etkileyici. Gerçek dünya... daha karışık. En büyük sorun güvenilirlik. En iyi modeller bile reasoning hataları yapıyor, tool argümanlarını hallucinate ediyor, bazen talimatları düpedüz görmezden geliyor. Düşündürücü bir hesap: her adımın %95 başarı oranına sahip olduğu on adımlık bir görevde, tüm görevi hatasız bitirme olasılığınız sadece %60. Yirmi adıma çıkınca? %36'nın altı. Bu matematik acımasız.

Bir de latency var. Her agent adımı en az bir LLM çağrısı demek, tool sonuçlarını işlemeyi de eklerseniz genelde iki ya da üç. Çağrı başına 1-3 saniye tipik API response süresiyle on adımlık bir iş akışı uçtan uca kolayca 20-30 saniye sürüyor. Saniyenin altında yanıt bekleyen kullanıcılar bunu interaktif kullanımda tolere etmiyor — bu da agent'ları gerçek zamanlı etkileşimden çok arka plan görev modeline itiyor.

Maliyet de hızla birikiyor. Tool sonuçlarını biriktiren uzun süreli agent'lar görev başına kolayca 100.000+ token tüketebiliyor. Güncel API fiyatlarıyla tek bir karmaşık görev birkaç dolara mal olabiliyor. Yüksek değerli enterprise iş akışları için sorun değil ama ölçekte tüketici uygulamaları için başlamadan bitiyor.

Evaluation hâlâ açık bir problem. Geleneksel yazılım testi deterministik davranış varsayıyor ama agent'lar doğası gereği stochastic — aynı input farklı çalışmalarda farklı eylem dizileri üretebiliyor. Bu güvenilir regression testi yazmayı gerçekten zorlaştırıyor. Bulduğumuz en iyi yaklaşım sonuç bazlı değerlendirme (agent doğru cevabı buldu mu?) ile trajectory seviyesinde metrikler — adım sayısı, tool kullanım kalıpları, reasoning kalitesi — birleştirmek.

Bir de güvenlik var — odadaki fil. Tool erişimi olan bir agent tanımı gereği gerçek dünyada gerçek eylemler gerçekleştirebilen bir sistem. Tool sonuçlarındaki kötü niyetli içeriğin agent'ı istenmeyen eylemlere yönlendirdiği prompt injection saldırıları ciddi bir tehdit. Defense in depth — input sanitization, output validation, tool erişimi için least privilege, yüksek etkili eylemler için human-in-the-loop — opsiyonel değil. Production deployment için olmazsa olmaz.

Temel Çıkarımlar

  1. Agent'ı tanımlayan altındaki model değil, döngüsü — otonomi, tool use ve planning.
  2. ReAct basit görevler için biçilmiş kaftan. Plan-and-Execute çok adımlı iş akışlarında parlıyor. LATS doğruluğun hız ve maliyetten önemli olduğu durumlarda devreye giriyor.
  3. Tool tasarımı model seçimi kadar kritik. Net schema'lar, sıkı validation ve kısa output'lar agent'larınızı çok daha güvenilir yapıyor.
  4. Memory sistemleri — kısa süreli, uzun süreli ve episodic — uzun süreli ve çok session'lı yeteneklerin kilidini açıyor ama dikkatli bakım yapmazsanız gürültüyle doluyor.
  5. Multi-agent orchestration güçlü ama gerçek karmaşıklık ekliyor. Supervisor pattern production için en savaş-test'li yaklaşım.
  6. Güvenilirlik, latency, maliyet ve güvenlik sert kısıtlar. Bunların etrafında inşa etmek — yokmuş gibi davranmak yerine — production sistemleri gösterişli demo'lardan ayırıyor.
  7. Agent'ları sonuçlara göre değerlendirin, trajectory'lere göre değil. Stochastic davranış paradigmanın bir özelliği, ezilmesi gereken bir bug değil.