Ana içeriğe atla
KILAVUZ

Node.js bir uygulamaya actor bağlamı nasıl eklenir

Her isteğin arkasında kimin ya da neyin olduğunu kaydeden middleware oluşturmak için adım adım bir rehber. Böylece herhangi bir şeyi zorunlu kılmadan önce gerçek trafiği inceleyebilirsiniz.

Toshendra Sharma

Yazan Toshendra SharmaKurucu ve CEO, AgentCredia · Updated November 13, 2026

Başlangıç · 9 dk okuma

Neden kurallardan önce actor bağlamıyla başlamalısınız?

Trafiklerinde AI agent'ları fark eden çoğu ekip önce bir kural yazar. User agent'ı engeller, bir challenge ekler, rate limit'i sıkılaştırır. Sorun şu ki, trafiği anlamadan önce yazılan bir kural genellikle yanlış kişileri etkiler. Meşru asistanlar engellenir, gerçek kullanıcılar challenge edilir ve asıl endişe ettiğiniz otomasyon, kendini en başta hiç tanıtmadığı için gelmeye devam eder.

Actor bağlamı, kurallardan önce gelen adımdır. Her istek için, uygulamanızın kim veya neyin hareket ettiğine dair gözlemleyebildiği şeyleri kaydedersiniz: etkileşimli bir kişi, bir AI asistanıyla çalışan bir kişi, otonom bir agent ya da henüz ayırt edemediğiniz bir şey. Bu görüşün arkasındaki kanıtı kaydedersiniz ve bunu isteğin sonucunun yanında tutarsınız. Bir iki hafta sonra, hiçbir kural şablonunun veremeyeceği bir şey elde edersiniz: kendi trafiğinizin haritası. Agent'ların sitenize gerçekten ulaşıp ulaşmadığına hâlâ karar veriyorsanız, web sitesi trafiğinin AI agent'larından gelip gelmediği nasıl anlaşılır ile başlayın.

Bu rehber, düz middleware kullanarak Node.js uygulamasında o katmanı oluşturur. Express ile çalışır ve aynı fikirler Fastify, Koa, Hono veya bir Next.js route handler'a da uygulanır.

Ne oluşturacaksınız

Sonunda şunlara sahip olacaksınız:

  1. Her istekte actor kanıtını çıkaran bir middleware.
  2. Her sonuç için belirtilmiş bir temeli olan küçük, açık bir sınıflandırma.
  3. İsteğin nasıl işlendiğini asla değiştirmeyen yapılandırılmış gözlem logları.
  4. Sonraki handler'ların okuyabilmesi için sonucu isteğe ekleme yolu.

Burada hiçbir şey bir isteği engellemez. Bu bilinçli bir tercihtir.

1. Adım: Sunucunuz gerçekten hangi kanıtları görebilir?

Bir sunucu, insanların sandığından daha azını görür. Kod yazmadan önce, edge'inizde mevcut olan sinyalleri listeleyin:

  • İstek imzaları. Bazı otomatik istemciler HTTP Message Signatures (RFC 9421) kullanarak istekleri imzalar, Signature-Input ve Signature başlıklarını gönderir ve çoğu zaman operatörün yayınladığı anahtarlara işaret eden bir Signature-Agent başlığı da ekler; bu yapı IETF Web Bot Auth taslak protokolünde anlatılır.
  • Beyan edilen kimlik. İstemciler kendilerini User-Agent başlığında, From başlığında ya da MCP client adı gibi protokol meta verileri aracılığıyla adlandırabilir. MCP client'ları, 2025-11-25 revizyonundaki initialize request içinde kendi seçtikleri bir clientInfo adı bildirir ve 2026-07-28 revizyonu client kimliğini istek başına meta veri olarak taşır. Bunlar beyanlardır ve herkes bunları kopyalayabilir.
  • Kimlik doğrulama bağlamı. İsteğin bir session cookie, bearer token ya da API key taşıyıp taşımadığı ve bunun hangi tür bir kimlik bilgisi olduğu.
  • Protokol biçimi. Accept başlıkları, istemcinin HTML mi JSON mu istediği, sayfa varlıklarını yükleyip yüklemediği ve yönlendirmeleri ile cookie'leri nasıl işlediği.
  • Uygulama beyanları. Kendi ürününüz ağın bilemeyeceği şeyleri biliyor olabilir, örneğin bir kullanıcının "AI assisted" seçeneğini seçmesi ya da bir isteğin yerleşik asistan özelliğinizden gelmesi.

Her sinyalin gücü farklıdır. Doğrulanmış bir imza denetlenebilir. Bir user agent dizgesi bir iddiadır. Eksik bir cookie sadece eksiktir. Bunları ayrı tutmak, egzersizin bütün amacıdır.

2. Adım: Sonucu açıkça modelleyin

Algılama mantığını yazmadan önce actor sonucunun yapısını tanımlayın. Küçük, tipli bir model, herkesin bir sınıflandırmanın ne anlama geldiği konusunda dürüst kalmasını sağlar. Burada kullanılan dört sınıf Human, AI-assisted or agent: application trafiği için pratik bir taksonomi içinde açıklanmıştır.

TS
export type ActorClass = "human" | "human_ai" | "agent" | "unknown";
export type EvidenceBasis = "verified" | "declared" | "inferred" | "unknown";

export interface ActorEvidence {
  signaturePresent: boolean;
  signatureAgent?: string;
  declaredClient?: string;
  credentialType: "session" | "api_key" | "bearer" | "none";
  acceptsHtml: boolean;
  appDeclaredAssist: boolean;
}

export interface ActorResult {
  actor: ActorClass;
  basis: EvidenceBasis;
  reasons: string[];
  evidence: ActorEvidence;
  observedAt: string;
}

En önemli iki alan vardır. actor sınıftır. basis neden buna inandığınızı söyler. Doğrulanmış bir imzaya dayanan bir agent sonucu ile bir user agent dizgesine dayanan bir agent sonucu ikisi de "agent"tır, ancak ileride çok farklı işlem görmeyi hak ederler, bu yüzden onları asla birleştirmeyin.

3. Adım: Kanıtı middleware içinde çıkarın

Çıkarma adımı başlıkları ve istek durumunu okur. Henüz hiçbir şey kararlaştırmaz.

TS
import type { Request, Response, NextFunction } from "express";

const KNOWN_AGENT_TOKENS = ["bot", "crawler", "spider", "agent", "gpt", "claude"];

export function extractEvidence(req: Request): ActorEvidence {
  const ua = (req.get("user-agent") || "").toLowerCase();
  const auth = req.get("authorization") || "";
  const hasSession = Boolean(req.cookies?.session);

  let credentialType: ActorEvidence["credentialType"] = "none";
  if (hasSession) credentialType = "session";
  else if (auth.toLowerCase().startsWith("bearer ")) credentialType = "bearer";
  else if (req.get("x-api-key")) credentialType = "api_key";

  const declaredToken = KNOWN_AGENT_TOKENS.find((t) => ua.includes(t));

  return {
    signaturePresent: Boolean(req.get("signature") && req.get("signature-input")),
    signatureAgent: req.get("signature-agent") || undefined,
    declaredClient: declaredToken ? ua.slice(0, 200) : undefined,
    credentialType,
    acceptsHtml: (req.get("accept") || "").includes("text/html"),
    appDeclaredAssist: req.get("x-app-assist") === "1",
  };
}

Bu kod hakkında birkaç not:

  • signaturePresent yalnızca imza başlıklarının mevcut olduğunu kaydeder. Doğrulama ayrı bir adımdır ve imzalı agent isteklerini doğrulama rehberinde ele alınır.
  • User agent belirteç listesi kasıtlı olarak basittir. Bir beyan üretir, asla doğrulama üretmez.
  • x-app-assist, bir kullanıcı yerleşik AI özelliğiniz üzerinden işlem yaparken ön yüzünüzün gönderdiği şeyin yerine kullanılmıştır. Bunu gerçek mekanizmanızla değiştirin.

4. Adım: Belirtilmiş bir temelle sınıflandırın

Şimdi kanıtı bir sonuca dönüştürün. Kuralları kısa tutun, en güçlü kanıttan en zayıfa doğru sıralayın ve her zaman Unknown'a düşün.

TS
export async function classify(
  evidence: ActorEvidence,
  verifySignature: () => Promise<boolean>,
): Promise<ActorResult> {
  const reasons: string[] = [];
  const observedAt = new Date().toISOString();

  if (evidence.signaturePresent && (await verifySignature())) {
    reasons.push("request signature validated");
    return { actor: "agent", basis: "verified", reasons, evidence, observedAt };
  }

  if (evidence.appDeclaredAssist) {
    reasons.push("application reported its built-in assistant");
    return { actor: "human_ai", basis: "declared", reasons, evidence, observedAt };
  }

  if (evidence.declaredClient) {
    reasons.push("client declared itself as automated");
    return { actor: "agent", basis: "declared", reasons, evidence, observedAt };
  }

  if (evidence.credentialType === "session" && evidence.acceptsHtml) {
    reasons.push("interactive browser session");
    return { actor: "human", basis: "inferred", reasons, evidence, observedAt };
  }

  reasons.push("insufficient evidence");
  return { actor: "unknown", basis: "unknown", reasons, evidence, observedAt };
}

Bunun ne yapmadığına dikkat edin. Bir beyanı asla doğrulamaya yükseltmez. Etkileşimli bir sinyal olmayan bir isteğe Human atamaz. Ayırt edemediğinde Unknown der. Unknown geçerli ve yararlı bir yanıttır ve görünürlüğünüzün tam olarak nerede bittiğini söyler. Bu konuyu Unknown neden AI trafiği için geçerli bir sonuçtur bölümünde ayrıntılı olarak ele alıyoruz.

5. Adım: Gözlem modunda bağlayın

Middleware'ı erken bağlayın, sonucu isteğe ekleyin ve loglayın. Bunun üzerine dallanma yapmayın.

TS
import express from "express";
import cookieParser from "cookie-parser";

const app = express();
app.use(cookieParser());

app.use(async (req, res, next) => {
  try {
    const evidence = extractEvidence(req);
    const result = await classify(evidence, async () => false);
    res.locals.actor = result;

    res.on("finish", () => {
      logActor({
        route: req.route?.path ?? req.path,
        method: req.method,
        status: res.statusCode,
        actor: result.actor,
        basis: result.basis,
        reasons: result.reasons,
      });
    });
  } catch {
    res.locals.actor = undefined;
  }
  next();
});

Bunu güvenli kılan üç ayrıntı vardır:

  1. try bloğu, algılamadaki bir hatanın hiçbir zaman yanıtı etkilememesini garanti eder. Gözlem fail open olmalıdır.
  2. Loglama finish üzerinde gerçekleşir, böylece gerçek durum kodunu yakalar ve daha sonra sınıflandırmaları sonuçlarla karşılaştırabilirsiniz.
  3. verifySignature, gerçek doğrulamayı uygulayana kadar false olarak stub edilmiş durumdadır. Bu, imzalı istekleri declared ya da unknown kovalarına yerleştirir ve onların değerini olduğundan yüksek göstermeyi önler.

6. Adım: Sadece hata ayıklama için değil, analiz için loglayın

Toplanabilir loglar yazın. İstek başına yapılandırılmış bir satır yeterlidir.

TS
function logActor(entry: Record<string, unknown>) {
  process.stdout.write(JSON.stringify({ type: "actor_observation", ...entry }) + "\n");
}

Bu loglardan kişisel verileri uzak tutun. Route'a, sınıfa, temele, nedenlere ve sonuca ihtiyacınız var. Trafik karışımınızı anlamak için tam IP adreslerine, ham cookie'lere ya da request body'lere ihtiyacınız yok. Korelasyon için herhangi bir tanımlayıcı tutarsanız, bunu dönen bir tuz ile hash'leyin ve kısa bir saklama süresi belirleyin.

7. Adım: Hareket etmeden önce veriyi okuyun

Normal haftalık desenleri görmek için gözlem modunda yeterince uzun süre çalıştırın. Ardından birkaç soruyu yanıtlayın:

  • Hangi route'lar agent'ları çekiyor? Dokümantasyon, katalog ve arama endpoint'leri genellikle bunu yapar. Hesap ve ödeme akışları genellikle yapmamalıdır.
  • Agent sonuçlarının ne kadarı verified, ne kadarı declared? Bu oran, politika yazarken kimliğe ne kadar güvenle dayanabileceğinizi söyler.
  • Unknown nerede yoğunlaşıyor? Bir route üzerinde yüksek Unknown oranı, orada bir sinyal eksik olduğu anlamına gelir; örneğin ön yüz kodunuzu hiç çalıştırmayan bir sayfa.
  • Sonuçlar sınıfa göre farklılaşıyor mu? Sınıflar arasında hata oranlarını, dönüşüm adımlarını ya da kötüye kullanım raporlarını karşılaştırın. Gerçek politika fikirleri buradan gelir.

Yanıtlar sizi çoğu zaman şaşırtır. Ekipler, "bot problemi"nin büyük bir kısmının aslında yapılandırılmış bir endpoint olsa onu memnuniyetle kullanacak meşru otomasyon olduğunu sıkça görür.

8. Adım: Sonucu uygulamanızın geri kalanına açın

Veri akmaya başladıktan sonra, handler'ların res.locals.actor değerini zorlayıcı olmayan kullanımlar için okumasına izin verin: analitik etiketleri, yanıt biçimi seçimi veya bir destek kaydının AI-assisted bir oturumdan geldiğini kaydetmek gibi. Bu kullanımlar, kimsenin erişiminin kesilmesi riski olmadan deneyimi iyileştirir.

TS
app.get("/docs/:page", (req, res) => {
  const actor = res.locals.actor as ActorResult | undefined;
  if (actor?.actor === "agent" && req.accepts("text/markdown")) {
    return res.type("text/markdown").send(renderMarkdown(req.params.page));
  }
  return res.render("doc", { page: req.params.page });
});

Challenge'lar, rate limit'ler ya da step-up kontrolleri gibi enforcement, ancak yanlış pozitifleri ölçtükten sonra gelir. Actor farkındalıklı politikaların kademeli olarak devreye alınması rehberi bu süreci kapsar.

Hangi hatalardan kaçınmalısınız?

  • User agent'ı kimlik olarak görmek. Değiştirilmesi en kolay başlıktır. Bunu bir beyan olarak kaydedin. AI operatörleri de bunu söyler: Anthropic'in barındırdığı tarayıcı agent'ı için rehberinde, herkesin aynı User-Agent başlığını gönderebileceği belirtilir ve trafiği gerçek kabul etmeden önce yayınlanan IP adreslerinin kontrol edilmesi önerilir.
  • Varsayılanı Human yapmak. Kodunuz bot sinyalleri bulamadığında Human diyorsa, Human sayılarınız şişer ve politikalarınız yanlış trafiğe güvenir.
  • Sınıf ile temeli karıştırmak. Her zaman ikisini de saklayın. Sadece "Agent" gösteren bir gösterge paneli, doğrulanmış bir operatör ile kopyalanmış bir dizge arasındaki farkı gizler.
  • Gözlem sırasında engellemek. Geçici bir engel bile ölçümlerinizi geçersiz kılar, çünkü engellenen istemciler davranışlarını değiştirir.

Proof of Actor burada nereye oturur?

Yukarıdaki middleware sağlam bir başlangıçtır ve temel modeli gösterir: önce kanıt, her sonuç için açık bir temel, Unknown görünür halde tutulur ve kararlar uygulamanıza bırakılır. Proof of Actor, aynı model üzerine server, edge, browser ve MCP bağlamlarında daha geniş sinyal kapsamı ve Detect, Understand ve Route yapmanızı güvenle sağlayan analizlerle inşa edilir.

Bunu üretimde çalışan bir uygulamada daha ileri taşımak için yardıma ihtiyacınız varsa, erken erişim için başvurun. Tam karar akışını görmek için Proof of Actor nasıl çalışır bölümünü okuyun.

Kaynaklar

Bizimle geliştirin.

Proof of Actor founding developer program'a katılın.

Önce konuşmak mı istersiniz? Kurucularla konuşun