BLOG · TEKNİK SEO
05 AĞUSTOS 2026 · 8 dk okuma

Sitemizi Yapay Zeka Ajanlarına Hazır Hale Getirirken Öğrendiklerimiz

Bir vaka analizi: auth.md, DNS-AID ve Markdown Negotiation ile web sitemizi %100 "agent-ready" hale getirirken yaptığımız hatalar ve adım adım çözümler.

Web tarafında son bir yılın en somut değişimi şu: siteler artık sadece insanlar için değil, insanların yerine gezinen, form dolduran, API çağıran yapay zeka ajanları için de tasarlanmak zorunda. Bu yeni disipline kimi "Agentic Web" diyor, kimi "Generative Engine Optimization" (GEO). İsmi ne olursa olsun, sonuç aynı: bir ajan sitenize geldiğinde onu doğru şekilde karşılayıp karşılamadığınız artık ölçülebilir bir metrik.

Biz de bunu kendi altyapımızda test etmeye karar verdik. Hedef basitti: WorkOS'un yayınladığı isitagentready.com kriterlerine göre sitemizi %100 "agent-ready" hale getirmek. Sonuç, birkaç saat süren HTTP header'ları, DNS kayıtları ve protokol tartışmalarının ardından geldi: tüm testlerden yeşil ışıkla geçtik. Ama oraya varmadan önce üç ayrı yerde takıldık, ve her takılma noktası aslında bir öğrenme fırsatıydı.

Bu yazıda domain adını ve kişisel verileri anonimleştirerek (example.com üzerinden) tüm süreci, yaptığımız hataları ve nihai çözümleri paylaşıyorum. Siz aynı yola çıkacaksanız, bu hataları tekrar etmenize gerek yok.

Kısa Özet: Bir web sitesinin "agent-ready" olması üç teknik katmanın doğru kurulmasına bağlıdır: ajanlara HTML yerine Markdown sunan içerik pazarlığı (Content Negotiation), ajanların kimlik doğrulayıp kayıt olabildiği bir agentic auth akışı (auth.md ve agent_auth şeması), ve ajanların protokolleri DNS seviyesinde keşfedebildiği, DNSSEC ile imzalanmış bir DNS-AID yapılandırması.

Ajan Dünyasının Üç Ana Sütunu

İşe koyulmadan önce, "agent-ready" olmanın aslında tek bir kontrol listesi değil, üç ayrı problem alanının toplamı olduğunu fark ettik.

SütunÇözdüğü ProblemKullanılan Mekanizma
Content NegotiationAjanlar devasa HTML'i işlerken token israf etmesinAccept: text/markdown header kontrolü
Agentic AuthAjanlar insan müdahalesi olmadan kayıt olup kimlik doğrulayabilsinauth.md + agent_auth şeması
DNS-AID & DNSSECAjanlar sitenin desteklediği protokolleri (MCP, A2A) DNS seviyesinde bulabilsin, bulduğu bilgiye güvenebilsinSVCB/HTTPS kayıtları + DNSSEC

Üçü de birbirinden bağımsız görünüyor ama aslında ortak bir mantığı paylaşıyorlar: ajanlara, insanlara sunduğunuzdan farklı bir "arayüz" sunmanız gerekiyor ve bu arayüzün her katmanı (HTTP, uygulama, DNS) kendi doğrulama mekanizmasına sahip.

Bu üç sütun neden ayrı ayrı ele alınmalı? Çünkü her biri farklı bir katmanda çalışıyor: Content Negotiation uygulama katmanında, agentic auth yetkilendirme katmanında, DNS-AID ise altyapı katmanında çözülüyor. Birini atlayıp diğerini yapmak, ajan için yarım bir deneyim bırakıyor.

Bir netlik payı vermek gerekiyor: bu üçü bizim için en çok zaman alan ve en fazla hata verdiğimiz kısımlardı, ama isitagentready.com'un gerçek kapsamı bundan daha geniş. Denetim aracı toplamda dört ana kategoride onlarca ayrı kontrol yapıyor:

Kategoriİçerdiği Kontroller
Discoverabilityrobots.txt, sitemap.xml, Link header'ları (RFC 8288), DNS-AID
ContentMarkdown Negotiation
Bot Access Controlrobots.txt'te AI bot kuralları, Content Signals, Web Bot Auth (request signing)
API, Auth, MCP & Skill DiscoveryAPI Catalog (RFC 9727), OAuth/OIDC discovery, OAuth Protected Resource, auth.md, MCP Server Card, Agent Skills index, WebMCP

(Ayrıca e-ticaret siteleri için opsiyonel bir "Commerce" kategorisi var; x402, MPP, UCP, ACP gibi ajan-native ödeme protokollerini kontrol ediyor. Bizim gibi bir hizmet sitesinde bu kategori "Not checked" olarak geçiyor, puanı etkilemiyor.)

robots.txt, sitemap, API Catalog, MCP Server Card, Agent Skills index gibi kalemler bizde baştan doğru kurulmuştu ya da nispeten sorunsuz geçti; bu yazıda anlattığımız üç sütun sıkıntı çıkaran kısımlar olduğu için öne çıkıyor.

A. Content Negotiation: Kolay Görünen Ama Tuzak Barındıran Kısım

İlk bakışta en basit problem buydu: bir ajan Accept: text/markdown header'ıyla istek attığında, siteniz HTML yerine Markdown dönmeli.

Neden önemli? Bir HTML sayfası; navigasyon, script, stil tanımları ve dekoratif elemanlarla dolu. Bir ajan için bunların neredeyse hiçbiri anlam taşımıyor, sadece token bütçesini tüketiyor. Markdown'a çevrilmiş aynı sayfa, çoğu durumda orijinal boyutunun çok altında kalıyor.

Çözümü edge katmanında (bizim durumumuzda bir Cloudflare Worker) kurduk. Gelen isteğin Accept header'ını kontrol eden, eşleşme varsa Content-Type: text/markdown; charset=utf-8 ve içeriğin token büyüklüğünü belirten X-Markdown-Tokens header'ını dönen bir mantık yazdık.

Buradaki asıl tuzak neydi? İlk versiyonumuz her sayfa için aynı statik özeti dönüyordu. Yani bir ajan blog yazımızı Markdown olarak isteseydi, o yazının içeriği yerine ana sayfanın tanıtım metnini alıyordu. Denetim aracı sadece ana sayfayı test ettiği için bu ilk hâliyle bile "geçiyor" görünüyordu, ama gerçek bir ajan için işlevsizdi.

Doğru çözümü kurarken, edge worker'ın içinde HTMLRewriter tabanlı bir dönüşüm katmanı yazdık: her text/markdown isteğinde origin'den o path'in gerçek HTML'ini çekiyor, sonra bunu satır satır işleyip navigasyon/script/stil bloklarını temizliyor, h1-h6, p, a, strong, blockquote, li gibi etiketleri ilgili Markdown syntax'ına çeviriyor, sayfanın <title> ve meta description'ından bir YAML frontmatter üretip başa ekliyor, JSON-LD yapılandırılmış verisini de sona fenced bir kod bloğu olarak taşıyorduk. Sonuçta gerçek X-Markdown-Tokens değeri de içerik uzunluğuna göre hesaplanan bir sayı oldu, sabit bir placeholder değil.

İkinci ve daha sinsi bir tuzağa da düştük: worker route'u. Kod tamamen doğru olmasına rağmen, ana sayfa hâlâ düz HTML dönüyordu. Sebep, worker'ın Cloudflare üzerindeki route tanımının yalnızca example.com/* (www'suz apex) olmasıydı; www.example.com/* için ayrı bir route eklenmemişti. Apex'e gelen istek worker'a uğrayıp www'ya yönleniyordu, ama www'ya düştüğünde artık hiçbir worker devrede olmadığı için istek doğrudan statik siteye gidiyor, markdown mantığı hiç çalışmıyordu. Route listesine www.example.com/* girişini eklemek sorunu çözdü. Bu, "kod doğru ama route yanlış" tipi hataların ne kadar sinsi olabileceğinin iyi bir örneği; curl ile aldığımız yanıt header'larında (Content-Type, X-Markdown-Tokens, Vary header'larının tamamen yokluğu) worker'ın isteği hiç görmediğini anlamamızı sağladı.

Content Negotiation olmadan bir ajan sitenizi yine de okuyabilir mi? Evet, ama HTML'i kendi tarafında ayrıştırmak zorunda kalır, bu da hem daha fazla token hem daha fazla hata payı demektir.

B. auth.md ve Agentic Auth: En Çok Zaman Alan Kısım

Burası gerçek mücadelenin başladığı yerdi.

İlk yaklaşımımız klasik OAuth2 "Client Credentials" akışıydı: sabit bir client ID/secret çifti, standart token endpoint. Bize göre bu, onlarca yıldır kullanılan, kanıtlanmış bir yöntemdi. Denetim aracı ise ısrarla iki hata veriyordu: "Missing or unsafe skill URL" ve "No complete standalone registration flow found".

Buradaki fark şuydu: klasik OAuth, önceden bilinen, insan tarafından kaydedilmiş bir istemciyi varsayıyor. Bir ajan ise sitenize ilk kez geldiğinde önceden kayıtlı değil. Kendi kendine, insan müdahalesi olmadan kayıt olabilmesi gerekiyor. Bu da bambaşka bir akış demek: discover → register → (gerekirse claim) → exchange → use → revoke.

Ne Değiştirdik

1. /.well-known/oauth-authorization-server içine agent_auth bloğu ekledik. Bu blok, klasik OAuth metadata'sının üzerine binen, ajanlara özel bir uzantı: skill (auth.md'nin adresi), register_uri, claim_endpoint, identity_types_supported gibi alanlar içeriyor.

2. Üç farklı kayıt yöntemini destekledik: anonymous (kimlik bilgisi olmadan), service_auth (kullanıcı e-postasıyla, claim ceremony gerektirir), identity_assertion (mevcut bir oturumu bu servise bağlayarak). Ajan, hangi kimlik materyaline sahipse ona göre birini seçiyor.

3. Kök dizine bir auth.md belgesi koyduk. Bu dosya, bir ajanın adım adım (discover'dan revoke'a kadar) izlemesi gereken talimatları düz metin olarak anlatıyor; YAML metadata'sı değil, gerçek bir prosedür.

Aşağıdaki tablo, klasik OAuth ile agentic auth arasındaki temel farkı özetliyor:

Klasik OAuth (Client Credentials)Agentic Auth
İstemciÖnceden kayıtlı, sabit ID/secretKendi kendine kayıt olur
Kimlik doğrulamaStatik secretAnonim / e-posta / oturum devri (identity assertion)
Talimat kaynağıAPI dokümantasyonu (insan okur)auth.md (ajan doğrudan okur ve uygular)
Devreye almaManuel, geliştirici kaydıOtomatik, discovery ile

Karşılaştığımız bir diğer sorun: Cloudflare önbelleği. Kodu doğru yazmamıza rağmen, denetim aracı bir süre eski sonuçları göstermeye devam etti. Sebep basitti: edge cache, worker deploy edilmeden önceki yanıtı hâlâ saklıyordu. Kodunuz doğru olsa bile, test etmeden önce önbelleği (Purge Everything) temizlemeyi unutmayın – bu, saatlerce "neden çalışmıyor" diye debug etmemizi engelleyebilecek bir adımdı.

Üçüncü bir kırılma noktası, domain tutarlılığıydı. Sitemizi www'lu adrese (canonical) taşırken, /.well-known/oauth-protected-resource içindeki resource alanı hâlâ www'suz adresi gösteriyordu. Denetim aracı buna "origin mismatch" diyordu: metadata dosyasının kendisi, sunulduğu adresle uyuşmuyordu. Aynı hata auth.md içindeki claim_url/revocation_url gibi alanlarda da tekrarlandı; bazı URL'ler www'lu, bazıları değildi. Çözüm iki parçalıydı: (1) worker'ın en başına, hangi path'e gelirse gelsin apex domain'i www'ya 301 ile yönlendiren bir host-kontrolü ekledik, böylece hangi adresten girilirse girilsin tek bir kanonik origin'den yanıt dönüyor; (2) tüm metadata dosyalarındaki (protected resource, authorization server, auth.md) URL'leri tek tek tarayıp aynı domain'e sabitledik.

Bu tutarlılık meselesinin en ince hâli, sondaki / karakteriydi. oauth-protected-resource içindeki authorization_servers alanı ile oauth-authorization-server içindeki issuer alanının birebir aynı string olması bekleniyor; biri sonunda / ile bitip diğeri bitmediğinde bile test "Issuer Mismatch" diye patlıyor. Görünüşte kozmetik bir fark, ama RFC 8414'ün metadata URL'sini issuer'dan türetme mantığı tam da bu slash'e dayandığı için, tek bir karakterlik tutarsızlık bütün zinciri kırabiliyor.

Dördüncü nokta ise şema/alan adı uyumuydu. agent_auth bloğunu ilk yazdığımızda kendi isimlendirmemizi kullanmıştık: supported_identity_types, claim_url, revocation_url gibi. Ama denetim aracının beklediği spesifikasyon farklı alan adları arıyordu: identity_types_supported, claim_endpoint, skill (auth.md'nin adresine işaret eden bir alan, bizde hiç yoktu). Veri aslında doğruydu, sadece yanlış anahtar isimleriyle taşınıyordu; bu da bize spesifikasyona birebir uyumun, "aynı bilgiyi farklı şekilde ifade etmek"ten neden farklı olduğunu gösterdi.

Bu arada sadece statik dosyalar sunmakla yetinmedik. Tarayıcı tarafında navigator.modelContext üzerinden bir WebMCP tanımı da ekledik; yani sayfa yüklendiğinde ajanın doğrudan çağırabileceği, gerçek bir fonksiyonu (imperative API) kayıt ediyoruz. Denetim aracı bunu "1 active tool" olarak görüp raporluyor. Fark şu: .well-known dosyaları ve auth.md ajana "nasıl bağlanacağını ve kimlik doğrulayacağını" anlatıyor, WebMCP ise ajana sayfanın içinde doğrudan çalıştırabileceği bir eylem sunuyor; statik keşif katmanının üstüne, çalışma zamanında etkileşim katmanı ekliyor.

auth.md içine hassas bilgi (gerçek client secret gibi) koymalı mıyım? Hayır. auth.md sadece akışı anlatan bir prosedür dokümanı; gerçek kimlik bilgileri hiçbir zaman bu dosyada yer almamalı, sadece endpoint adresleri ve desteklenen yöntemler orada bulunur.

C. DNS-AID, SVCB Kayıtları ve DNSSEC Zinciri

Üçüncü katman, ajanların sitenizin hangi protokolleri (MCP, A2A gibi) desteklediğini DNS seviyesinde keşfedebilmesiydi.

Bunun için SVCB (ServiceMode) kayıtları oluşturduk; her protokol için ayrı bir kayıt olacak şekilde (_mcp._agents.example.com, _a2a._agents.example.com gibi), alpn ve hedef parametreleriyle birlikte.

Mimarideki ince bir detay: Serverless/edge altyapılarda sabit bir IP adresi (ipv4hint) vermek yerine, TargetName olarak doğrudan domain'in kendisini gösterdik. Bu kayıtları Cloudflare'de eklerken Proxy durumunu "DNS Only" (gri bulut) yaptık; çünkü proxied (turuncu bulut) modda Cloudflare'in kendi edge'i devreye girip SVCB kaydının işaret ettiği gerçek hedefi değiştirebiliyor, bu da ajanın doğrudan bağlantısını bozuyor.

DNSSEC kırmızı çizgiydi. SVCB ve TLSA kayıtlarının bir anlam ifade etmesi için, bu kayıtların kriptografik olarak doğrulanabilir olması gerekiyordu. DNSSEC olmadan, yol üzerindeki bir saldırgan teorik olarak sahte SVCB kaydı enjekte edebilir; ajan hangi sunucuya bağlandığından emin olamaz. Cloudflare üzerinde DNSSEC'i açtık, ardından alan adı kayıt firmamıza (registrar) çıkan DS (Delegation Signer) kaydını işleyerek güven zincirini tamamladık.

DNSSEC olmadan SVCB kayıtları hiç işe yaramaz mı? Kayıtlar teknik olarak çözümlenir ve okunabilir, ama denetim araçları (ve dikkatli ajanlar) bunları "doğrulanmamış" olarak işaretler; güven zinciri eksik kalır.

Bu Süreci Yönetecek Geliştiricilere Tavsiyeler

Sürecin sonunda, bizim için en değerli çıkarımlar şunlar oldu:

Eski kalıplardan sıyrılın. Ajanlar klasik web kullanıcıları gibi davranmıyor. Standart API dokümantasyonu ve klasik OAuth akışları yerine, ajan-odaklı standartları (auth.md, agent card şemaları) benimsemek gerekiyor.

Edge computing kullanın. Header kontrolü, yönlendirme ve discovery JSON'larının hepsini serverless edge katmanında (bizim durumumuzda Cloudflare Workers) yönetmek, hem esneklik hem de hız kazandırıyor; origin sunucunuzu değiştirmeden bu davranışları ekleyebiliyorsunuz.

Önbellek yanılsamasına düşmeyin. Bir test hata verdiğinde, önce kodunuzu değil, edge cache ve CDN katmanının güncel olup olmadığını kontrol edin.

Güvenliği ihmal etmeyin. Ajanların sitenizi keşfetmesi tek başına yeterli değil; DNSSEC gibi mekanizmalarla bu keşfin doğrulanabilir, ortadaki adam saldırılarına karşı dayanıklı olması gerekiyor.

Kapanış: Sıra Sizde

Geleceğin web siteleri sadece ekranı olan insanlar için değil, ekranı olmayan yapay zeka ajanları için de tasarlanıyor. Bu üç katman (content negotiation, agentic auth, DNS-AID) bugün için makul bir başlangıç noktası, ama standart hâlâ hızla evriliyor; birkaç ay sonra yeni gereksinimler eklenebilir.

Siz de kendi sitenizin şu anki durumunu görmek isterseniz:

npx isitagentready yourdomain.com

komutuyla hızlıca test edebilirsiniz. Sürecin herhangi bir adımında takıldığınız bir yer olursa, yorumlarda konuşalım.

← Tüm yazılara dön