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.
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özlemlenebilirlikBu 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önModel 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:
- 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.
- 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 odaklangibi talimatla elle de tetiklenebilir. Proje kökündekiCLAUDE.mdcompaction'dan sonra diskten yeniden okunup tekrar eklenir. - Codex CLI'da
/compact, Gemini CLI'da/compressaynı işi yapar. - Hook'larla compaction'ın öncesine bağlanabilirsin: Claude Code'da
PreCompact/PostCompact, Codex'tePreCompact/PostCompact, Gemini CLI'daPreCompress, Cursor'dapreCompact.
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şikExplore(salt okunur, kod tabanı keşfi) ve plan modunda araştırma yapanPlansubagent'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ırBö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 vemkdir/mvgibi 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) vebypassPermissions. 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,/policieskomutları 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.
/sandboxile açılıp kapatılır. - Codex CLI: macOS, Linux ve Windows için yerleşik sandbox;
codex sandbox macos|linux|windowskomutuyla bir komutun sandbox'ta nasıl davrandığını test edebilirsin. - Gemini CLI: macOS'ta
sandbox-exec(Seatbelt) ya da Docker/Podman konteyneri;-s/--sandboxbayrağı,GEMINI_SANDBOXortam değişkeni ya dasettings.jsonile 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:
- Elle yazılan talimat dosyaları (
CLAUDE.md,AGENTS.md,GEMINI.md): sen yazarsın, her oturumda yüklenir. Kesin kurallar burada olmalı. - Ajanın kendi tuttuğu notlar:
- Claude Code auto memory: Claude, proje başına
~/.claude/projects/<proje>/memory/dizinine notlar yazar. DizindekiMEMORY.mdbir 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./memoryile göz atabilir, düzenleyebilirsin. - Codex Memories: Yerel Codex istemcileri ayrı bir yerel bellek deposu kullanır;
/memoriesile 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/memoriesaltındaki dosyalar üzerinde işlem ister, depolamayı senin uygulaman yapar. Kendi ajanını yazıyorsan bellek katmanını bununla kurabilirsin.
- Claude Code auto memory: Claude, proje başına
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;/restoredosyaları ve konuşmayı geri yükler, ayrıca/rewindkomutu 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,pytestgibi güvenli komutlar sorulmadan),rm -rfgibi 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:
messageslistesini her turdan sonra JSONL'e yaz,resp.usageile 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 daCLAUDE.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
- Agent Harness — kavramın kısa tanımı.
- Agent Loop ve Function Calling — döngünün API tarafı.
- Context Engineering ve Context Compaction — bağlamı yönetmenin teorisi.
- Subagent, Agent Skills, Agent Hooks — harness'ın genişletme noktaları.
- Agent Sandbox, Prompt Injection, Human-in-the-loop — güvenlik katmanı.
- Agent Memory ve AI Agent — büyük resim.
- Claude Skills Rehberi, MCP Server Kataloğu, Kendi MCP Sunucunu Yaz, Token Azaltma Teknikleri, System Prompt Rehberi.