AI Atlas
EN TR
Tüm rehberler
🧰 REHBER

Bir AI Harness'ının Anatomisi: Modelin Etrafında Neler Var?

Claude Code, Codex CLI, Cursor ve Gemini CLI gibi araçlarda modelin etrafını saran katman: ajan döngüsü, araçlar, bağlam yönetimi, subagent, skill, hook, izinler, sandbox, bellek ve 70 satırın altında bir kendi harness örneği.

Agents Claude Code Context Engineering Tools

Kısa özet

Claude Code'u, Codex CLI'ı ya da Cursor'ı açtığında konuştuğun şey "çıplak" bir dil modeli değildir. Modelin etrafında onu bir ajana dönüştüren kalın bir yazılım katmanı vardır: modeli döngü içinde çağıran, araçlarını tanımlayan, bağlamını derleyip budayan, hangi komutun çalışabileceğine karar veren, oturumu kaydeden ve geri sarmana izin veren katman. Bu katmanın adı agent harness.

Kabaca bir denklem kurabiliriz:

Ajan = Model + Harness
Harness = döngü + araçlar + bağlam yönetimi + izinler/sandbox + genişletme noktaları (skill, hook, subagent, MCP) + bellek + gözlemlenebilirlik

Bu rehber harness'ı parça parça açıyor. Her bölümde önce kavramı, sonra popüler araçların o parçayı nasıl uyguladığını anlatıyoruz. Sonda dört popüler harness'ın karşılaştırma tablosu, 70 satırın altında çalışır bir "kendi harness'ını yaz" örneği ve bir seçim kontrol listesi var.

Not: Ürünlere özgü tüm bilgiler (komut adları, hook olayları, dosya adları) Ekim 2026 itibarıyla resmi dokümantasyondan kontrol edildi. Bu araçlar haftalık sürüm çıkarıyor; ayrıntılar değişebilir.

Model mi, harness mı?

Aynı modeli iki farklı harness'a koyduğunda sonuçlar çarpıcı biçimde değişebilir. Bunun nedeni modelin "zekâsının" değişmesi değil, modelin gördüğü ve yapabildiği şeylerin değişmesidir:

  • Ne görüyor? System prompt, proje talimat dosyaları, araç açıklamaları, önceki araç sonuçları. Hepsi harness'ın kararı. Modelin bağlam penceresine ne girerse model onunla düşünür.
  • Ne yapabiliyor? Dosya okuyabiliyor mu, düzenleyebiliyor mu, shell komutu çalıştırabiliyor mu, web'e çıkabiliyor mu? Araç seti harness'tan gelir.
  • Ne zaman duruyor? Kaç tur dönebileceği, ne kadar harcayabileceği, hangi durumda kullanıcıya soracağı harness'ın kurallarıdır.
  • Hata yapınca ne oluyor? Test başarısız olunca çıktı modele geri veriliyor mu, yoksa ajan "bitti" deyip duruyor mu? Hatayı modele geri besleyen döngü yine harness'ın işi.

İşin özü: model bir karar verici, harness ise o kararın uygulandığı dünya. Claude Code dokümantasyonu bu ayrımı açıkça söylüyor: izin kuralları modelin değil Claude Code'un kendisi tarafından uygulanır; CLAUDE.md'ye yazdığın talimatlar Claude'un ne denediğini etkiler ama Claude Code'un neye izin verdiğini değiştirmez.

Bu yüzden bir ajandan aldığın sonuç kötüyse, modeli değiştirmeden önce şunlara bak: bağlamda doğru bilgi var mıydı, doğru araçlar tanımlı mıydı, hatalar modele geri dönüyor muydu?

Ajan döngüsü

Her harness'ın kalbinde aynı basit döngü atar. Agent loop şöyle işler:

1. Kullanıcı mesajı + system prompt + araç tanımları → modele gönder
2. Model yanıt verir:
   a) Metin + "bitti"  → döngüden çık, yanıtı göster
   b) Bir veya daha fazla araç çağrısı → 3'e git
3. Harness her çağrıyı kontrol eder (izin var mı?), çalıştırır
4. Araç sonuçlarını konuşmaya ekle → 1'e dön

Model hiçbir zaman komutu kendisi çalıştırmaz; yalnızca "şu aracı şu argümanlarla çağırmak istiyorum" der. Anthropic API'de bu, yanıtın stop_reason: "tool_use" ile gelmesi ve içinde tool_use blokları olmasıdır. Harness aracı çalıştırır, sonucu tool_result bloğu olarak geri gönderir ve stop_reason "tool_use" olduğu sürece döngü sürer. Bu mekanizmanın API tarafına function calling deniyor.

Durma koşulları

Döngünün nasıl bittiği en az nasıl başladığı kadar önemlidir:

Durma nedeni Ne olur
Model araç çağırmadan metin döndürdü Normal bitiş, görev tamamlandı kabul edilir
Tur limiti doldu Sonsuz döngüye karşı emniyet kemeri
Bütçe limiti doldu Maliyet tavanı aşıldı
Kullanıcı kesti (Esc / Ctrl+C) İnsan müdahalesi
Bir hook "dur" dedi Deterministik kural devreye girdi

SDK'lar bu limitleri parametre olarak verir. Claude Agent SDK (Python) max_turns (en fazla ajan turu, yani araç kullanımı gidiş-dönüşü) ve max_budget_usd (istemci tarafı maliyet tahmini bu değere ulaşınca sorguyu durdurur) seçeneklerini sunar. OpenAI Agents SDK'da döngü, model istenen tipte bir metin çıktısı üretip hiç araç çağrısı yapmadığında biter; max_turns aşılırsa MaxTurnsExceeded hatası fırlatılır.

Pratik ipucu: Otomasyonda (CI, cron) çalışan her ajana mutlaka bir tur ve/veya bütçe limiti koy. Etkileşimli kullanımda bu limiti sen olursun; gözetimsiz çalışmada başka hiçbir şey yoktur.

Araçlar: ajanın elleri

Bir harness'ın araç seti neredeyse her zaman aynı çekirdekten oluşur:

Araç ailesi Tipik isimler Ne işe yarar
Okuma Read, Glob, Grep Dosya okumak, dosya bulmak, içerikte aramak
Yazma Edit, Write, apply_patch Dosyayı değiştirmek ya da oluşturmak
Shell Bash, terminal Test, build, git, paket yöneticisi
Web WebSearch, WebFetch Dokümantasyon, güncel bilgi
Planlama todo/task listeleri Uzun görevlerde ilerlemeyi takip
Delegasyon Task/Agent Subagent başlatmak

MCP: araç setini dışarıdan genişletmek

Yerleşik araçlar yetmediğinde MCP (Model Context Protocol) devreye girer. Bir MCP sunucusu GitHub, veritabanı, Sentry ya da tarayıcı gibi bir hizmeti araç olarak sunar; harness bu araçları modelin araç listesine ekler. Bugün dört büyük harness'ın hepsi MCP destekliyor: Claude Code, Codex CLI (~/.codex/config.toml içinde [mcp_servers.<isim>] tablosu ya da codex mcp add), Cursor (mcp.json) ve Gemini CLI (/mcp komutu). Hazır sunucular için MCP Server Kataloğu'na, kendininkini yazmak için Kendi MCP Sunucunu Yaz rehberine bak.

Araç açıklamaları da birer prompt'tur

Model bir aracı yalnızca adı, açıklaması ve parametre şeması üzerinden tanır. Yani araç açıklaması modelin okuduğu bir talimattır. İki pratik sonucu var:

  1. Kötü açıklama = yanlış kullanım. "Dosya okur" yerine "Proje kökü içindeki bir UTF-8 metin dosyasını okur; yol proje köküne göre göreli verilmeli" yazmak, modelin yanlış yol denemesini ciddi oranda azaltır.
  2. Her araç bağlam yer. 40 araçlı üç MCP sunucusu bağladığında, her istekte o 120 aracın tanımı modele gönderilir. Kullanmadığın sunucuları kapat; bazı harness'lar (Claude Code gibi) bir aracı izin kuralıyla tamamen reddettiğinde onu bağlamdan da çıkarır.

Bağlam mühendisliği ve bağlam yönetimi

Context engineering, modelin bağlam penceresine her turda ne gireceğine karar verme disiplinidir. Prompt mühendisliği tek bir mesajı iyileştirir; bağlam mühendisliği yüzlerce turluk bir oturum boyunca pencerenin içeriğini yönetir.

Bir harness'ın her istekte modele gönderdiği tipik paket:

[system prompt]            ← harness'ın kendi talimatları
[araç tanımları]           ← yerleşik + MCP araçları
[proje talimat dosyaları]  ← CLAUDE.md / AGENTS.md / GEMINI.md
[skill açıklamaları]       ← yalnızca ad + açıklama
[konuşma geçmişi]          ← mesajlar + araç çağrıları + araç sonuçları

System prompt

Harness'ın kendi system prompt'u modele kim olduğunu, araçları nasıl kullanacağını, ne zaman soracağını anlatır. Çoğu zaman göremezsin ama ajanın "karakterinin" büyük kısmı buradan gelir. Kendi ajanını yazıyorsan System Prompt Rehberi iyi bir başlangıç.

Proje bellek dosyaları

Her harness, depoya koyduğun bir markdown dosyasını otomatik olarak bağlama ekler:

Harness Dosya Davranış
Claude Code CLAUDE.md (./, ./.claude/, ~/.claude/, CLAUDE.local.md) Çalışma dizini ve üstündekiler açılışta yüklenir; alt dizinlerdekiler Claude o dizindeki dosyaları okudukça yüklenir. Hiç CLAUDE.md yoksa AGENTS.md okunur (v2.1.277+).
Codex CLI AGENTS.md, AGENTS.override.md Önce ~/.codex, sonra proje kökünden çalışma dizinine kadar her dizinde en fazla bir dosya; birleşik boyut varsayılan 32 KiB (project_doc_max_bytes) ile sınırlı.
Gemini CLI GEMINI.md Global (~/.gemini/GEMINI.md), çalışma alanı ve "just-in-time": bir araç bir dizine eriştiğinde o dizindeki GEMINI.md taranır. /memory show birleşik içeriği gösterir.
Cursor .cursor/rules/*.mdc, AGENTS.md Kurallar description, globs, alwaysApply frontmatter'ı ile; AGENTS.md kök ve alt dizinlerde desteklenir.

Bu dosyalar her turda bağlamdadır, yani her satırının bir maliyeti var. Claude Code dokümantasyonu 200 satırı aşan dosyaların daha fazla bağlam tükettiğini ve talimatlara uyumu düşürebileceğini söylüyor. Kural: dosyaya modelin koddan çıkaramayacağı şeyleri yaz (tuzaklar, gerekçeler, varsayılandan farklı kurallar); dizin ağacını ve bağımlılık listesini değil.

Compaction: geçmişi özetlemek

Uzun bir oturum eninde sonunda pencereyi doldurur. Context compaction eski konuşmayı bir özetle değiştirerek yer açar:

  • Claude Code bağlam sınırına yaklaşınca otomatik compaction yapar; /compact Kod örneklerine ve API kullanımına odaklan gibi talimatla elle de tetiklenebilir. Proje kökündeki CLAUDE.md compaction'dan sonra diskten yeniden okunup tekrar eklenir.
  • Codex CLI'da /compact, Gemini CLI'da /compress aynı işi yapar.
  • Hook'larla compaction'ın öncesine bağlanabilirsin: Claude Code'da PreCompact/PostCompact, Codex'te PreCompact/PostCompact, Gemini CLI'da PreCompress, Cursor'da preCompact.

Compaction kayıplıdır: özet, ayrıntıları atar. Bu yüzden önemli kararları dosyaya yazdırmak (plan dosyası, notlar) compaction'a güvenmekten daha sağlamdır.

Araç sonucu temizleme

Bağlamı en hızlı dolduran şey araç sonuçlarıdır: 3000 satırlık bir log, bir dosyanın tamamı, arama sonuçları. Model bunları bir kez işledikten sonra çoğu zaman tekrar görmesi gerekmez. Anthropic API bunun için context editing sunuyor: clear_tool_uses_20250919 stratejisi bağlam belirlediğin eşiği aştığında eski araç sonuçlarını temizler (beta, context-management-2025-06-27 başlığı ile). Kendi harness'ında daha basitini yapabilirsin: araç çıktısını kırp, yalnızca son N satırı ya da ilk N karakteri döndür.

Bağlam bütçesi

Bağlamı bir bütçe gibi düşün. Her kalem yer kaplar: system prompt, araç tanımları, talimat dosyaları, skill listesi, geçmiş. Codex bunu somut biçimde yapıyor: başlangıçtaki skill listesi bağlam penceresinin en fazla %2'sini (bilinmiyorsa 8.000 karakter) kullanabilir; fazlası kısaltılır. Token tasarrufu teknikleri için Token Azaltma Teknikleri rehberine bak.

Subagent'lar ve paralellik

Subagent, ana ajanın bir alt görevi devrettiği, kendi bağlam penceresinde çalışan ayrı bir ajandır. Asıl faydası paralellikten çok bağlam izolasyonudur: subagent 50 dosya okuyup 200 satır arama sonucu tarar, ana konuşmaya yalnızca özeti döner.

Bugün dört harness'ın hepsinde var:

  • Claude Code: .claude/agents/ (proje) ve ~/.claude/agents/ (kullanıcı) altında markdown dosyalarıyla tanımlanır; her birinin kendi system prompt'u, araç erişimi ve izinleri olur. Yerleşik Explore (salt okunur, kod tabanı keşfi) ve plan modunda araştırma yapan Plan subagent'ları gelir.
  • Codex CLI: "üç subagent başlat, biri güvenlik, biri test eksikleri, biri bakım kolaylığı için" gibi doğrudan isteklerle paralel çalışma başlatılır.
  • Gemini CLI: .gemini/agents/*.md (proje) ve ~/.gemini/agents/*.md (kullanıcı); subagent ayrı bir bağlam döngüsünde çalışır.
  • Cursor: Her subagent kendi bağlam penceresinde çalışır ve sonucu ana ajana döndürür; bağlam yoğun işler için üç yerleşik subagent bulunur.

Ne zaman kullanmalı: Çıktısı uzun ama sonucu kısa olan işler (kod tabanında arama, log analizi, bağımsız araştırma kolları), birbirinden bağımsız paralel kontroller (güvenlik/test/stil incelemesi).

Ne zaman kullanmamalı: Sık geri bildirim gerektiren işler, aynı bağlamı paylaşan aşamalar (plan → uygulama → test), küçük hedefli değişiklikler. Subagent sıfırdan başlar ve bağlam toplaması zaman alır; ayrıca her subagent kendi token'ını harcar.

Skill'ler: talep üzerine talimat

Agent skills, bir klasör + SKILL.md dosyasından oluşan, isteğe bağlı olarak script ve referans dosyaları içeren talimat paketleridir. Anahtar fikir progressive disclosure (kademeli açılım):

Açılışta:       yalnızca ad + açıklama bağlamda   (birkaç düzine token)
Gerektiğinde:   SKILL.md'nin tamamı yüklenir      (yüzlerce-binlerce token)
Daha da gerekirse: skill klasöründeki ek dosyalar okunur / script'ler çalıştırılır

Böylece 50 skill kurulu olsa bile bağlam şişmez; model yalnızca ihtiyaç duyduğunu açar. Format açık bir standarda dayanıyor (agentskills.io) ve Claude Code, Codex CLI, Gemini CLI (activate_skill aracıyla) ve Cursor tarafından destekleniyor.

Claude Code'da iki faydalı frontmatter alanı var:


---

name: deploy
description: Uygulamayı production'a deploy eder
disable-model-invocation: true   # Claude kendi başına çağıramaz, sadece sen /deploy yazarsın

---

disable-model-invocation: true, yan etkisi olan iş akışları (deploy, commit, Slack mesajı) için önemli: kodun "hazır göründüğü" için ajanın kendi kendine deploy etmesini istemezsin. Tersine user-invocable: false skill'i yalnızca modelin kullanabileceği arka plan bilgisine çevirir.

Skill yazmaya giriş için Claude Skills Rehberi'ne bak.

Hook'lar: deterministik otomasyon

Talimat dosyasına "her düzenlemeden sonra lint çalıştır" yazmak bir ricadır; model bazen unutur. Agent hooks ise bir garantidir: harness yaşam döngüsünün belirli anlarında senin script'ini her seferinde çalıştırır.

Harness Araç öncesi Araç sonrası Diğer önemli olaylar
Claude Code PreToolUse PostToolUse SessionStart, UserPromptSubmit, PermissionRequest, Stop, SubagentStart/SubagentStop, PreCompact, SessionEnd
Codex CLI PreToolUse PostToolUse SessionStart, UserPromptSubmit, PermissionRequest, Stop, SubagentStart/SubagentStop, PreCompact/PostCompact
Gemini CLI BeforeTool AfterTool SessionStart, BeforeAgent/AfterAgent, BeforeModel/AfterModel, BeforeToolSelection, PreCompress
Cursor beforeShellExecution, beforeMCPExecution afterShellExecution, afterFileEdit sessionStart, beforeSubmitPrompt, preCompact, stop

Örnek: Claude Code'da her Edit/Write sonrası lint çalıştırmak (.claude/settings.json):

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          { "type": "command", "command": "/path/to/lint-check.sh" }
        ]
      }
    ]
  }
}

Claude Code'da hook script'i JSON girdiyi stdin'den alır; çıkış kodu 2 ile çıkarsa eylem engellenir ve stderr modele geri bildirim olarak gider. PreToolUse hook'u JSON çıktıda permissionDecision (allow/deny/ask/defer) döndürerek izin kararını da verebilir. Handler türleri yalnızca shell komutu değil: command, http, mcp_tool, prompt (tek turluk model değerlendirmesi) ve deneysel agent.

Dikkat edilmesi gereken bir fark: Cursor'da beforeShellExecution/beforeMCPExecution hook'u çökerse, zaman aşımına uğrarsa ya da 2 dışında sıfırdan farklı bir kodla çıkarsa varsayılan olarak eylemin geçmesine izin verilir (fail open). Güvenlik kritik hook'larda failClosed: true ayarla.

Tipik kullanımlar: formatter/linter çalıştırmak, rm -rf ya da git push --force gibi komutları engellemek, .env okunmasını engellemek, oturum başında bağlam enjekte etmek (git durumu, açık issue'lar), ajan bitince bildirim göndermek, her araç çağrısını denetim log'una yazmak.

Güvenlik: izinler, sandbox ve onay modları

Bir kodlama ajanı senin kullanıcı hesabınla shell komutu çalıştırır. Harness'ın en kritik görevi, modelin isteği ile gerçek dünya arasında bir kapı olmaktır. Bu kapının üç katmanı var:

1. İzin kuralları ve onay modları

Hangi aracın sorulmadan, hangisinin onayla çalışacağını belirler; kapının yanında duran human-in-the-loop sensin.

  • Claude Code izin modları: default (her aracın ilk kullanımında sorar), acceptEdits (çalışma dizinindeki dosya düzenlemelerini ve mkdir/mv gibi yaygın dosya komutlarını otomatik kabul eder), plan (yalnızca okur ve keşfeder, kaynak dosyaları düzenlemez), auto (rutin sorular yok; komutlar çalışmadan önce bir arka plan sınıflandırıcısı isteğinle uyumunu kontrol eder), dontAsk (normalde soracak her çağrıyı reddeder) ve bypassPermissions. Kurallar deny → ask → allow sırasıyla değerlendirilir; geniş bir deny kuralı, daha spesifik bir allow kuralını ezer.
  • Codex CLI iki ayrı eksen kullanır: sandbox modu (read-only, workspace-write) ve onay politikası (on-request, never). Varsayılan "Auto" ön ayarı workspace-write + on-request: çalışma alanında okur, düzenler, komut çalıştırır; çalışma alanı dışına yazmak ya da ağa çıkmak onay ister. --dangerously-bypass-approvals-and-sandbox (takma adı --yolo) hem sandbox'ı hem onayları kapatır.
  • Cursor "Run Modes" kullanır: Auto-review (allowlist'teki çağrılar hemen çalışır, diğer shell komutları mümkünse sandbox'ta, sandbox'a girmeyenler bir sınıflandırıcıya gider) ve Allowlist (yalnızca listedekiler onaysız çalışır). Cursor dokümantasyonu Auto-review'ın bir güvenlik sınırı olmadığını açıkça belirtiyor.
  • Gemini CLI'da /permissions, /policies komutları ve plan modu var.

2. OS seviyesinde sandbox

İzin kuralları "hangi araç" sorusunu cevaplar; agent sandbox ise "araç çalışınca neye dokunabilir" sorusunu. Sandbox, işletim sisteminin uyguladığı bir sınırdır; model ne kadar ikna edici olursa olsun aşamaz.

  • Claude Code: Bash aracı macOS'ta Seatbelt, Linux ve WSL2'de bubblewrap ile sandbox'lanır. Ağ trafiği, alan adı allowlist'ini kontrol eden bir proxy'den geçer. /sandbox ile açılıp kapatılır.
  • Codex CLI: macOS, Linux ve Windows için yerleşik sandbox; codex sandbox macos|linux|windows komutuyla bir komutun sandbox'ta nasıl davrandığını test edebilirsin.
  • Gemini CLI: macOS'ta sandbox-exec (Seatbelt) ya da Docker/Podman konteyneri; -s/--sandbox bayrağı, GEMINI_SANDBOX ortam değişkeni ya da settings.json ile açılır.
  • Cursor: Terminal komutları dosya ve ağ erişimini kısıtlayan bir sandbox'ta çalıştırılabilir; sandbox kısıtına takılan komut sandbox dışında yeniden denenebilir ve bu deneme sınıflandırıcıdan geçer.

3. Prompt injection: neden bu kadar önemli

Prompt injection, modelin okuduğu içeriğe gömülmüş talimatlardır: bir README'deki gizli satır, bir web sayfasındaki beyaz-üstüne-beyaz metin, bir issue yorumu, bir MCP aracının döndürdüğü veri. Model bunları kullanıcı talimatından güvenilir biçimde ayıramaz.

Bir ajan aynı anda (1) özel verine erişebiliyor, (2) güvenilmeyen içerik okuyor ve (3) dışarıya veri gönderebiliyorsa (ağ, git push, e-posta), saldırgan için kapı açıktır. Simon Willison bu üçlüye "lethal trifecta" diyor. Savunma modelde değil harness'tadır:

  • Ağı sandbox'la kısıtla, alan adı allowlist'i kullan.
  • Güvenilmeyen içerik okuyan oturumlarda yazma/gönderme araçlarını kapat ya da onaya bağla.
  • Yabancı kaynaklı MCP sunucusu ve skill kurmadan önce kodunu/SKILL.md'sini oku.
  • Kritik kontrolleri talimat dosyasına değil hook'a ve deny kuralına koy. Ayrıntı için Guardrails.

Oturumlar arası bellek

Her oturum boş bir bağlam penceresiyle başlar. Agent memory, önceki oturumlardan öğrenilenleri bir sonrakine taşıma mekanizmasıdır. İki tür var:

  1. Elle yazılan talimat dosyaları (CLAUDE.md, AGENTS.md, GEMINI.md): sen yazarsın, her oturumda yüklenir. Kesin kurallar burada olmalı.
  2. Ajanın kendi tuttuğu notlar:
    • Claude Code auto memory: Claude, proje başına ~/.claude/projects/<proje>/memory/ dizinine notlar yazar. Dizindeki MEMORY.md bir indekstir; ilk 200 satırı ya da ilk 25 KB'ı (hangisi önce gelirse) her oturum başında yüklenir. Konu dosyaları başlangıçta yüklenmez, gerektiğinde okunur; burada da progressive disclosure var. /memory ile göz atabilir, düzenleyebilirsin.
    • Codex Memories: Yerel Codex istemcileri ayrı bir yerel bellek deposu kullanır; /memories ile mevcut sohbetin belleği kullanıp kullanmayacağını ya da gelecekteki belleklere girdi olup olmayacağını seçersin. OpenAI'ın kendi tavsiyesi: zorunlu kuralları AGENTS.md'de tut, belleği yalnızca yardımcı bir hatırlama katmanı olarak gör.
    • Gemini CLI: Kalıcı notlar için bir memory aracı ve deneysel "Auto Memory" özelliği.
    • Anthropic API memory tool (memory_20250818): İstemci tarafında çalışır. Claude /memories altındaki dosyalar üzerinde işlem ister, depolamayı senin uygulaman yapar. Kendi ajanını yazıyorsan bellek katmanını bununla kurabilirsin.

Bellek ile RAG aynı şey değildir: RAG dış bir bilgi tabanından arama yapar; ajan belleği ajanın kendi deneyiminden (hangi testin kırılgan olduğu, kullanıcının hangi tercihi bildirdiği) oluşur.

Gözlemlenebilirlik: transcript, maliyet, checkpoint

Ajanın ne yaptığını göremiyorsan ona güvenemezsin. İyi bir harness üç şey sunar:

Transcript

Claude Code her oturumun tam kaydını ~/.claude/projects/<proje>/<oturum>.jsonl dosyasına yazar: her mesaj, her araç çağrısı, her araç sonucu. Bu kayıtlar şifrelenmez; bir araç .env okursa ya da bir komut bir sırrı yazdırırsa, o değer transcript'e de yazılır. Codex'te /resume kayıtlı bir sohbete döner, /fork mevcut sohbeti dallandırır. Gemini CLI'da /resume (takma adı /chat) oturum tarayıcısını açar. OpenAI Agents SDK ise çalıştırmaları trace olarak kaydeder; trace_include_sensitive_data ile araç girdi/çıktılarının trace'e girip girmeyeceğini ayarlarsın.

Maliyet ve token takibi

Token tüketimi bağlam boyutuyla ölçeklenir: büyük bağlam, her mesajda daha fazla token demektir. Claude Code'da /usage (takma adı /cost) oturum maliyetini ve plan kullanımını, Codex'te /status token kullanımını ve kalan bağlam kapasitesini, Gemini CLI'da /stats oturum istatistiklerini gösterir.

Checkpoint ve geri sarma

Ajan yanlış yola saparsa geri dönebilmelisin:

  • Claude Code: Turu başlatan her prompt'tan önce otomatik checkpoint alınır; /rewind (takma adları /checkpoint, /undo) kodu ve/veya konuşmayı geri sarar. Önemli sınır: Bash komutlarıyla değiştirilen dosyalar (ör. rm, mv, script çıktıları) checkpoint'e girmez; yalnızca dosya düzenleme araçlarının değişiklikleri izlenir.
  • Gemini CLI: Dosya değiştiren bir aracı onayladığında ~/.gemini/history/<proje_hash> altındaki gölge bir git deposuna snapshot alınır; /restore dosyaları ve konuşmayı geri yükler, ayrıca /rewind komutu var.
  • Cursor: Ajan önemli değişikliklerden önce otomatik checkpoint alır; sohbet zaman çizelgesinden geri yüklenebilir.

Checkpoint'ler oturum seviyesinde hızlı kurtarma içindir; git'in yerini tutmaz. Ajanı temiz bir çalışma ağacında başlat, sık commit et.

Popüler harness'lar karşılaştırması

Aşağıdaki tablo yalnızca resmi dokümantasyonda doğrulanmış bilgileri içeriyor; doğrulayamadığım hücreler "—" ile işaretli. "—" özelliğin olmadığı anlamına gelmez, yalnızca doğrulanmadığı anlamına gelir.

Bileşen Claude Code Codex CLI Gemini CLI Cursor
Proje talimat dosyası CLAUDE.md (yoksa AGENTS.md) AGENTS.md, AGENTS.override.md GEMINI.md .cursor/rules/*.mdc, AGENTS.md
MCP Var Var (config.toml) Var (/mcp) Var (mcp.json)
Hook'lar Var (PreToolUse vb.) Var (PreToolUse vb.) Var (BeforeTool vb.) Var (beforeShellExecution vb.)
Skill'ler (SKILL.md) Var Var Var Var
Subagent Var (.claude/agents/) Var Var (.gemini/agents/) Var
İzin/onay modeli 6 izin modu + allow/ask/deny kuralları Sandbox modu + onay politikası /permissions, /policies, plan modu Run Modes (Auto-review, Allowlist)
OS sandbox Seatbelt (macOS), bubblewrap (Linux/WSL2) Yerleşik (macOS/Linux/Windows) Seatbelt, Docker/Podman Terminal komutları için var
Manuel compaction /compact (+ otomatik) /compact /compress —
Checkpoint / geri sarma /rewind — /restore, /rewind Checkpoint'ler
Oturumlar arası bellek Auto memory (MEMORY.md) Memories (/memories) Memory aracı, Auto Memory (deneysel) —
Kullanım takibi /usage (/cost) /status /stats —

Gemini CLI notu: Google, Gemini CLI'ı yeni Antigravity CLI'a taşıdı. Bireysel ve ücretsiz kullanıcılar için Gemini CLI 18 Haziran 2026'da istek almayı bıraktı; kurumsal müşterilerin erişimi sürüyor. Google'a göre Antigravity CLI; Agent Skills, Hooks, Subagents ve Extensions (artık "Antigravity plugins") özelliklerini koruyor ancak başlangıçta 1:1 özellik eşliği yok. Tablodaki Gemini CLI sütunu Gemini CLI dokümantasyonunu yansıtıyor.

Kendi harness'ını yaz: 70 satırın altında

Bir harness'ın özünü anlamanın en iyi yolu en küçüğünü yazmak. Aşağıdaki Python script'i Anthropic SDK ile şunları yapıyor: ajan döngüsü, iki araç (read_file, run_command), bir izin kontrolü (yol kaçışı engeli + her shell komutu için kullanıcı onayı), tur limiti ve araç çıktısı kırpma.

pip install anthropic
export ANTHROPIC_API_KEY=...
import pathlib
import subprocess
import anthropic

client = anthropic.Anthropic()  # ANTHROPIC_API_KEY ortam değişkeninden okunur
MODEL = "claude-sonnet-5-5"
ROOT = pathlib.Path.cwd().resolve()
MAX_TURNS = 20      # sonsuz döngüye karşı emniyet kemeri
MAX_OUT = 20_000    # bağlam bütçesi: tek araç sonucu en fazla bu kadar karakter

TOOLS = [
    {
        "name": "read_file",
        "description": "Proje kökü içindeki bir UTF-8 metin dosyasını okur. Yolu proje köküne göre göreli ver.",
        "input_schema": {"type": "object", "properties": {"path": {"type": "string"}}, "required": ["path"]},
    },
    {
        "name": "run_command",
        "description": "Proje kökünde bir shell komutu çalıştırır, stdout+stderr döndürür. Her çağrı kullanıcı onayı gerektirir.",
        "input_schema": {"type": "object", "properties": {"command": {"type": "string"}}, "required": ["command"]},
    },
]

def allowed(name: str, args: dict) -> bool:
    """İzin kontrolü: kararı model değil harness verir."""
    if name == "read_file":
        return (ROOT / args["path"]).resolve().is_relative_to(ROOT)  # ../../ kaçışını engelle
    if name == "run_command":
        return input(f"\n`{args['command']}` çalıştırılsın mı? [e/H] ").strip().lower() == "e"
    return False

def execute(name: str, args: dict) -> str:
    if name == "read_file":
        return (ROOT / args["path"]).read_text()[:MAX_OUT]
    out = subprocess.run(args["command"], shell=True, cwd=ROOT, capture_output=True, text=True, timeout=120)
    return (out.stdout + out.stderr)[-MAX_OUT:] or "(çıktı yok)"

def run(task: str) -> str:
    messages = [{"role": "user", "content": task}]
    for _ in range(MAX_TURNS):
        resp = client.messages.create(
            model=MODEL,
            max_tokens=4096,
            system="Dikkatli bir kodlama ajanısın. Değiştirmeden önce oku, işin bitince kısa bir özet ver.",
            tools=TOOLS,
            messages=messages,
        )
        messages.append({"role": "assistant", "content": resp.content})
        if resp.stop_reason != "tool_use":  # araç çağrısı yok → görev bitti
            return "".join(b.text for b in resp.content if b.type == "text")
        results = []
        for block in resp.content:
            if block.type != "tool_use":
                continue
            if not allowed(block.name, block.input):
                content, is_error = "İzin reddedildi (kullanıcı/politika).", True
            else:
                try:
                    content, is_error = execute(block.name, block.input), False
                except Exception as e:  # hatayı modele geri besle, döngüyü kırma
                    content, is_error = f"Hata: {e}", True
            results.append({"type": "tool_result", "tool_use_id": block.id, "content": content, "is_error": is_error})
        messages.append({"role": "user", "content": results})
    return "Durdu: tur limitine ulaşıldı."

if __name__ == "__main__":
    print(run("Bu projedeki testleri çalıştır ve başarısız olanları özetle."))

Bu kısa kodda bir harness'ın iskeleti var. Gerçek bir harness'a dönüştürmek için eklemen gerekenler bu rehberin bölümleriyle birebir örtüşüyor:

  • Bağlam yönetimi: Geçmiş büyüdükçe eski tool_result'ları kırp ya da özetle (veya API'nin context editing özelliğini kullan).
  • Proje talimatları: Açılışta AGENTS.md'yi okuyup system prompt'a ekle.
  • Daha iyi izinler: Onay yerine allowlist (git status, pytest gibi güvenli komutlar sorulmadan), rm -rf gibi kalıplar için deny listesi.
  • Sandbox: run_command'ı bir konteynerde ya da OS sandbox'ında çalıştır.
  • Hook noktaları: execute öncesi ve sonrası çağrılan fonksiyon listeleri.
  • Gözlemlenebilirlik: messages listesini her turdan sonra JSONL'e yaz, resp.usage ile token say.

Hazır bir harness'ı kütüphane olarak kullanmak istersen Claude Agent SDK (Claude Code'un altyapısı; araçlar, izin modları, hook'lar, subagent'lar, max_turns, max_budget_usd, can_use_tool geri çağrısı hazır gelir) ya da OpenAI Agents SDK (döngü, max_turns, guardrail'lar, tracing) iyi başlangıç noktaları.

Harness seçme ve yapılandırma kontrol listesi

Yeni bir harness denerken ya da mevcut kurulumunu gözden geçirirken:

Döngü ve limitler

  • Gözetimsiz çalıştırmalarda tur ve/veya bütçe limiti tanımlı mı?
  • Başarısız test/komut çıktısı modele geri dönüyor mu?

Bağlam

  • Proje talimat dosyası var mı, kısa mı (yaklaşık 200 satırın altında), yalnızca koddan çıkarılamayan bilgileri mi içeriyor?
  • Birden fazla araç kullanıyorsan tek bir AGENTS.md'yi paylaşıyor musun (ya da CLAUDE.md'den import ediyor musun)?
  • Kullanmadığın MCP sunucuları kapalı mı?
  • Uzun oturumlarda compaction davranışını biliyor musun; önemli kararlar dosyaya yazılıyor mu?

Güvenlik

  • Varsayılan izin/onay modu ne? Hangi komutlar sorulmadan çalışıyor?
  • OS sandbox açık mı? Ağ erişimi allowlist'le sınırlı mı?
  • .env, SSH anahtarları ve bulut kimlik bilgileri deny kurallarında mı?
  • Güvenilmeyen içerik (web, issue, üçüncü taraf MCP) okuyan oturumlarda dışarı veri gönderme yolları kapalı mı?
  • Kurduğun skill'lerin ve MCP sunucularının içeriğini okudun mu?

Genişletilebilirlik

  • "Her seferinde olmalı" dediğin kurallar talimat dosyasında değil hook'ta mı?
  • Uzun araştırma işleri subagent'a devrediliyor mu?
  • Tekrarlayan iş akışları skill olarak paketlendi mi?

Gözlemlenebilirlik

  • Transcript'ler nerede tutuluyor, içlerine sır sızabilir mi?
  • Token/maliyet takibini nereden yapıyorsun?
  • Geri sarma neyi kapsıyor, neyi kapsamıyor (ör. Bash ile yapılan değişiklikler)?

Devamı için