← Blog
AI & DEVOPS·1 AĞUSTOS 2026AUG 1, 2026·10 DK OKUMA10 MIN READ

AI agent'lara internal developer platform'da kimlik vermekGiving AI agents an identity in your internal developer platform

Platformunuz, çağıranın insan olduğunu varsayarak kuruldu. Agent, bu varsayımı kıran ilk gerçek kullanıcı sınıfı — bir kullanıcının eylem genişliğine ve bir servisin sorumluluk alamazlığına aynı anda sahip. Kimliğin birimi delegasyondur: üç eksenli kota, dört parçalı audit ve varsayılan-ölümlü ortamlar bundan çıkar.

Your platform was built assuming the caller is a person. The agent is the first real user class to break that assumption — with a user's breadth of action and a service's inability to be held responsible. The unit of identity is the delegation: three-axis quotas, a four-part audit trail and default-mortal environments all follow from it.

Naylalabs · MühendislikEngineering
Snapshot: Son doğrulama: 1 Ağustos 2026. Gösterilen mekanizmalar demo repo'da çalışıyor: agent-native-ops-demo (tag v0.2.0). İddialar o repo'nun gösterdiğiyle sınırlı — kimsenin kurumsal savaş hikâyesiyle değil. Snapshot: Last verified August 1, 2026. The mechanisms shown run in the demo repo: agent-native-ops-demo (tag v0.2.0). Claims are scoped to what that repo demonstrates — not to anyone's enterprise war story.
Agent-Native Operations · 3/5. Beş bölümlük serinin 3. yazısı — 1. Stateless MCP server · 2. Tool contract'ları · 3. Agent kimliği · 4. OpenTelemetry GenAI · 5. Auto-remediation guardrail'leri Agent-Native Operations · 3/5. Part 3 of a five-part series — 1. Stateless MCP server · 2. Tool contracts · 3. Agent identity · 4. OpenTelemetry GenAI · 5. Auto-remediation guardrails

Gördüğümüz her internal developer platform aynı yazılmamış varsayımı kodluyor: bizi çağıran şey bir insan. Bakmaya başlayınca her yerde görünüyor. Klavyedeki ellere göre boyutlanmış rate limit'ler. "Hangi çalışan" sorusuna cevap veren audit loglar. HR olaylarına bağlanmış offboarding. Talep sahibinin, açık unuttuğu on iki environment'ı eninde sonunda fark edeceğini varsayan self-service akışları.

Every internal developer platform we have seen encodes the same unwritten assumption: the thing calling us is a person. It shows up everywhere once you look. Rate limits sized for hands on keyboards. Audit logs that answer "which employee". Offboarding tied to HR events. Self-service flows that assume the requester will notice, eventually, the twelve environments they left running.

Sonra bir ekip ilk production agent'ını bağlıyor ve varsayım topluca çöküyor. Agent öğlene kadar kırk deploy yapıyor. Audit log her şeyi svc-automation yaptı diyor — ki bu, "kimse yapmadı" demenin başka bir yolu. Kota sistemi ya hiç tetiklenmiyor ya da tetiklenip kimsenin bağımlılığından haberdar olmadığı bir workflow'u indiriyor.

Then a team wires up its first production agent, and the assumption fails all at once. The agent deploys forty times before lunch. The audit log says svc-automation did everything — which is another way of saying nobody did. The quota system either never fires, or fires and takes down a workflow nobody knew depended on it.

Rahatsız edici çerçeve — ve bu serinin tezi — şu: agent, platformunuzun insan olmayan ilk kullanıcısı ve o bir kullanıcı, servis değil. Bu yazı, boşluğu kapatan üç mekanizma hakkında: identity, kota, audit — artı bunların ima ettiği environment modeli. Slayt destesinden değil; serinin ilk iki yazısındaki NestJS kod tabanından, çalıştırıp ölçerek.

The uncomfortable framing — and this series' thesis — is this: the agent is your platform's first non-human user, and it is a user, not a service. This post is about the three mechanisms that close the gap: identity, quotas, audit — plus the environment model they imply. Not from a slide deck; from the same NestJS codebase as the first two posts of this series, run and measured.

01Service account yanlış soyutlama — ve herkesin uzandığı soyutlama oThe service account is the wrong abstraction — and the one everyone reaches for

Bir agent'ın platform API'lerini çağırması gerektiğinde en az dirençli yol bir service account: credential bas, scope ver, bitti. Şekli yanlış — ve uyumsuzluk kozmetik değil, yapısal:

When an agent needs to call platform APIs, the path of least resistance is a service account: mint credentials, grant scopes, done. It is the wrong shape — and the mismatch is structural, not cosmetic:

Service accountİnsan kullanıcıHuman userAgent
Eylem alanıScope of actionDar, sabitNarrow, fixedGeniş, muhakemeyle sınırlıBroad, judgment-boundedGeniş, prompt'la sınırlıBroad, prompt-bounded
Zaman içinde davranışBehavior over timeStatik, öngörülebilirStatic, predictableDeğişken, kendini frenlerVariable, self-limitingDeğişken, kendini frenlemezVariable, not self-limiting
Kimin adına eylerActs on behalf ofKendiItselfKendiItselfHer seferinde başkasınınSomeone else, every time
Hesap verebilirlikAccountabilitySahip ekipOwning teamKişinin kendisiThe personSiz kurmazsanız tanımsızUndefined unless you build it

Service account sabit bir sözleşmedir: bu workload şu üç işi yapar. Agent ise bir delegasyondur: bir insan (ya da tetikleyen bir sistem) bir sonuç istedi ve agent adımları doğaçlıyor. O doğaçlamaya statik bir servis credential'ı verirseniz iki dünyanın en kötüsünü alırsınız — kullanıcı kadar erişimli, workload kadar anonim bir çağıran. Bu arıza ne varsayımsal ne egzotik: bir şeylerin ters gittiği gün, audit loglarınızdaki 4.000 satırlık svc-automation.

A service account is a fixed contract: this workload does these three things. An agent is a delegation: some human (or triggering system) asked for an outcome, and the agent is improvising the steps. Give that improvisation a static service credential and you get the worst of both worlds — a caller with user-like reach and workload-like anonymity. The failure is neither hypothetical nor exotic: it is svc-automation, 4,000 times, in your audit log on the day something goes wrong.

platformun iki kullanıcısıthe platform's two users
İnsan geliştirici
Human developer
muhakeme · utanç · offboarding
judgment · shame · offboarding
AI agent
prompt · makine temposu · delegasyon
prompt · machine cadence · delegation
kendi adınaas itself
on behalf of: melih@…
PLATFORM YÜZEYLERİ — hepsi insan varsayımıyla kuruldu
PLATFORM SURFACES — all built on the human assumption
identityquotaauditenvironmentsself-service
agent = kullanıcı genişliği + servis anonimliği (kurmazsanız) agent = a user's reach + a service's anonymity (unless you build it)
Şekil 1. Aynı yüzeyler, iki farklı kullanıcı sınıfı: insan kendi adına eyler; agent her zaman birinin adına eyler — platformun tanıması gereken şey de tam olarak o delegasyon. Figure 1. Same surfaces, two user classes: the human acts as itself; the agent always acts on someone's behalf — and that delegation is exactly what the platform needs to recognize.

02Identity: birim, agent değil delegasyondurIdentity: the unit is the delegation, not the agent

Çözüm, neyi kimlik saydığınızla başlıyor. "Agent" değil (fazla kaba — hangi koşu? kimin adına?) ve "kullanıcı" da değil (yanlış — bu eylemleri kullanıcı yapmadı). Her şeyi çalıştıran birim delegasyon: bu agent, bu koşuda, bu principal adına. Demo repo'da agent kaynaklı her istek üç claim taşıyor ve platform, herhangi biri eksik olan isteği reddediyor:

The fix starts with what you consider the identity. Not "the agent" (too coarse — which run? on whose behalf?) and not "the user" (false — the user did not take these actions). The unit that makes everything work is the delegation: this agent, this run, acting for this principal. In the demo repo, every agent-originated request carries three claims, and the platform rejects any request missing one:

agent-delegation.ts
// Kimliğin birimi: "bu agent, bu koşuda, bu principal adına".// The unit of identity: "this agent, on this run, on behalf of this principal".
export interface AgentDelegation {
  agentId: string;    // agent deployment'ının stabil kimliği// stable identity of the agent deployment
  runId: string;      // koşu başına benzersiz — audit'in pivot alanı// unique per run — the pivot field for audit
  onBehalfOf: string; // yetkisi kullanılan insan/sistem principal'ı// the human/system principal whose authority is being used
}

// Delegasyon zinciri eksik bir istek "anonim" değildir; geçersizdir.// A request with a broken delegation chain is not "anonymous"; it is invalid.
const d = extractDelegation(ctx); // imzalı token claim'lerinden — asla body'den// from signed token claims — never from the body
if (!d) return {
  isError: true,
  structuredContent: {
    code: 'incomplete_delegation',
    retryable: false,
    recovery: 'Credential içine agentId, runId ve onBehalfOf claim\'lerini ekleyin.',
  },
};

İki tasarım noktası değerin çoğunu taşıyor. Birincisi, efektif izin bir kesişimdir: agent'ın grant'i bir tavan ("bu agent staging'e deploy edebilir"), delege eden principal'ın izni fiilen kullanabileceği alan ("…ama yalnızca Melih'in deploy edebildiği servislere"). Principal'larının hiçbirinde olmayan yetkiyi biriktiren bir agent, confused-deputy problemini fazladan adımla yeniden inşa etmenin yoludur. İkincisi, delegasyon doğrulanmış credential'da taşınır, request body'de değil: onBehalfOf, agent'ın doldurduğu bir JSON alanıysa kurgudur. Bu da doğrudan MCP tarafındaki two-hop token hikâyesine bağlanır: delegasyon zinciri, hop 2'nin koruması gereken şeydir, soyması gereken değil.

Two design points carry most of the value. First, effective permission is an intersection: the agent's grant is a ceiling ("this agent may deploy to staging"), the delegating principal's permission is what it can actually exercise ("…but only for services Melih can deploy"). An agent accumulating authority beyond any of its principals is how you rebuild the confused-deputy problem with extra steps. Second, the delegation rides in verified credentials, not request bodies: if onBehalfOf is a JSON field the agent fills in, it is fiction. This connects directly to the two-hop token story on the MCP side: the delegation chain is what hop 2 must preserve, not strip.

Güvenlik sektörünün "non-human identity" ürün kategorisiyle bağdaşma sorusu gelirse: çoğunlukla rekabet etmiyor. O kategori makine credential'larını keşfetmek ve döndürmekle ilgili. Buradaki ise atıf semantiği — binadaki her credential kusursuz döndürülse bile var olmaya devam eden bir platform meselesi.

If the security industry's "non-human identity" product category comes to mind: this mostly does not compete with it. That category is about discovering and rotating machine credentials. This is about attribution semantics — a platform concern that exists even if every credential in the building is perfectly rotated.

03Kota: insan kendini frenler; agent prompt'unun peşinden uçuruma giderQuotas: humans self-limit; agents follow their prompt off a cliff

İnsanlara dönük rate limit'ler çoğunlukla körelmiş bir nezakettir — insanlar sıkılır, yemeğe gider, tıklamayı bırakır. Agent'lar bırakmaz. Retry döngüsündeki ya da hedefi ince bir şekilde yanlış olan bir agent, API'nizi tamamen meşru credential'larla, makine temposunda çalıştırır. (O retry döngüsünün suçlusunun kendi protokolünüz olup olmadığı contract yazısının konusu — burada sadece bir çalışma koşulu.) Mekanizma: kotalar credential'a değil, delegasyona bağlanır — üç eksende birden:

Human-facing rate limits are mostly vestigial politeness — people get bored, go to lunch, stop clicking. Agents do not. An agent in a retry loop, or with a subtly wrong goal, exercises your API at machine cadence while holding legitimate credentials. (Whether that retry loop is your own protocol's fault is the contract post's question — here it is simply an operating condition.) The mechanism: quotas attach to the delegation, not the credential — on three axes at once:

quota.service.ts
// Üç eksen, her zaman — her biri diğerlerinin kaçırdığı arızayı yakalar:// Three axes, always — each catches a failure the others miss:
// run = kaçak döngü · agent = fazla ısınmış deployment · principal = adalet// run = runaway loop · agent = overheated deployment · principal = fairness
const axes = [
  { axis: 'run',       key: `q:run:${d.runId}`,                          limit: cfg.perRun },
  { axis: 'agent',     key: `q:agent:${d.agentId}`,                      limit: cfg.perAgentDay },
  { axis: 'principal', key: `q:principal:${d.onBehalfOf}:${d.agentId}`,  limit: cfg.perPrincipalDay },
];
for (const a of axes) {
  const used = await redis.incr(a.key);
  if (used > a.limit) return { allowed: false, axis: a.axis, … };
}

Reddin şekli de contract'ın parçası — en sert savunacağımız detay, per-run ekseninde retryable: false: bütçesini yakan bir koşu, istatistiksel olarak planı raydan çıkmış bir koşudur; üreteceği doğru sonraki adım uyu-ve-yeniden-dene değil, insanına rapordur. Kota hatası agent'a dönük UX'tir; hata objesi bir prompt'tur.

The shape of the denial is part of the contract too — the detail we would defend hardest is retryable: false on the per-run axis: a run that burns its budget is, statistically, a run whose plan has gone wrong; its correct next step is a report to its human, not sleep-and-retry. A quota error is agent-facing UX; the error object is a prompt.

Çalıştırdık. Runaway senaryosu: kendi sonucunu yanlış okuyup aynı işi tekrar deneyen bir agent taklidi — aynı runId ile 500 ardışık provision_environment çağrısı (scripts/runaway-demo.mjs, ~370 istek/sn):

We ran it. The runaway scenario: an agent misreading its own result and re-attempting the same work — 500 sequential provision_environment calls under one runId (scripts/runaway-demo.mjs, ~370 req/s):

KoşuRunNiyetIntentsİzinAllowedRedDeniedİlk redFirst denial
Per-run kota açık (limit 15)Per-run quota on (limit 15)5001548516. istek (~40 ms)request #16 (~40 ms)
Per-run kota kapalıPer-run quota off50048515486. istek — principal/gün ekseni (500) yakaladırequest #486 — caught by the principal/day axis (500)

İkinci satır planlamadığımız bir kanıt: per-run eksenini bilerek kapattık ve runaway 485 ortam yaratmayı başardı — ta ki üçüncü eksen (principal/gün) 486. istekte devreye girene kadar. Üç eksenin gerekçesi tam olarak bu: bir savunmayı kapatırsanız (ya da bir bug delerse), diğerleri farklı bir açıdan yakalar. Tek eksenli kota, tek arıza noktalı kota demektir.

The second row is evidence we did not plan: we deliberately disabled the per-run axis, and the runaway managed to create 485 environments — until the third axis (principal/day) tripped at request #486. That is exactly the case for three axes: disable one defense (or let a bug pierce it), and the others catch from a different angle. A single-axis quota is a single point of failure.

04Audit: "bunu kim yaptı" dört parçalı bir soruya dönüşürAudit: "who did this" becomes a four-part question

İnsanlar için kurulmuş bir audit kaydı kim, ne, ne zaman sorusuna cevap verir. Agent eylemlerinde "kim" dört alana patlar. Aşağıdaki satırlar üretilmiş örnek değil — yukarıdaki kotalı koşunun audit kuyruğundan, kelimesi kelimesine:

An audit record built for humans answers who, what, when. For agent actions, "who" explodes into four fields. The lines below are not a mock-up — they are verbatim from the quota-on run's audit queue above:

audit kuyruğu — runaway koşusunun son satırları (gerçek çıktı)audit queue — last lines of the runaway run (real output)
{"ts":"2026-08-01T08:05:35.416Z","actor":{"type":"agent","agentId":"deploy-agent","runId":"r_7c41e2"},
 "onBehalfOf":"melih@naylalabs.com","action":"environment.create",
 "input_digest":"sha256:a97c9c7a2909…","outcome":"allowed","quota":{"remaining":0}}
{"ts":"2026-08-01T08:05:35.418Z","actor":{"type":"agent","agentId":"deploy-agent","runId":"r_7c41e2"},
 "onBehalfOf":"melih@naylalabs.com","action":"environment.create",
 "input_digest":"sha256:a97c9c7a2909…","outcome":"denied","quota":{"axis":"run","remaining":0}}
{"ts":"2026-08-01T08:05:35.420Z","actor":{"type":"agent","agentId":"deploy-agent","runId":"r_7c41e2"},
 "onBehalfOf":"melih@naylalabs.com","action":"environment.create",
 "input_digest":"sha256:a97c9c7a2909…","outcome":"denied","quota":{"axis":"run","remaining":0}}

Sonradan acıyı azaltan üç not. Pivot, runId: incident review'ın gerçekten sorduğu soru "r_7c41e2 koşusunun yaptığı her şeyi sırasıyla göster"dir; loglarınız buna tek sorguda cevap veremiyorsa elinizdeki audit değil, telemetridir. Girdileri digest'leyin: agent girdileri prompt içerir, prompt'lar kullanıcı ne yazdıysa onu — hash'leyin, payload'ı scope'lu bir store'a bırakın. Trace bağlantısı: audit olduğunu söyler, nedenini trace söyler; iki görünümü dikişlemek serinin observability yazısının işi.

Three notes that save pain later. The pivot is runId: the question incident review actually asks is "show me everything run r_7c41e2 did, in order"; if your logs cannot answer that in one query, you have telemetry, not audit. Digest the inputs: agent inputs contain prompts, and prompts contain whatever users typed — hash them, keep payloads in a scoped store. The trace join: audit says that it happened; the trace says why — stitching the two views is this series' observability post's job.

05Environment'lar: varsayılan-ölümlü — çünkü agent utanç duymazEnvironments: default-mortal — because agents feel no shame

Self-service environment'lar, bir insanın staging-copy-7'nin hâlâ çalıştığını eninde sonunda fark etmesi etrafında tasarlandı. Agent'lar environment'ı bir plan adımı olarak yaratır ve "eninde sonunda" diye bir kavramları yoktur. Demo repo'nun politikası tek kural: agent'ın yarattığı kaynak, TTL ile doğar. provision_environment'ın döndürdüğü her ortam yaratılışta expiresAt taşır; uzatma, kota sayan explicit bir eylemdir. İnsanlar ölümsüz kaynak yaratabilir; delegasyonlar yaratamaz. Platformun kaynak grafiğini mille dolmaktan koruyan şey dashboard değil, bu asimetridir. (Bu, API'lerinizin planın ortasında bir ortamın buharlaşmasını tolere etmesini de gerektirir — handle expiry'nin tanımlı bir hata olması gibi.)

Self-service environments were designed around a human noticing, eventually, that staging-copy-7 is still running. Agents create environments as a plan step and have no concept of "eventually". The demo repo's policy is one rule: agent-created resources are born with a TTL. Every environment returned by provision_environment carries expiresAt at creation; extension is an explicit, quota-counted action. Humans may create immortal resources; delegations may not. What keeps the platform's resource graph from silting up is not a dashboard but that asymmetry. (It also requires your APIs to tolerate an environment vanishing mid-plan — much like handle expiry being a defined error.)

06Serinin kalanı bu tabloda nerede duruyorWhere the rest of the series stands on this

Agent-Native Operations'taki diğer her yazı, bu mekanizmalardan birinin yakın çekimi:

Every other post in Agent-Native Operations is one of these mechanisms, zoomed in:

07Sık sorulanlarFAQ

Bu, fazladan adımlı OAuth on-behalf-of akışı değil mi?
Token mekaniği örtüşüyor; semantik örtüşmüyor. OBO "bu çağrı geçebilir mi" sorusuna cevap verir. Delegasyon modeli ayrıca "bu koşu toplamda ne kadar yapabilir" ve "yaptığını nasıl yeniden kurarız" sorularına da cevap verir — kota ve audit; token akışları bunları tek başına vermez.

Isn't this just OAuth on-behalf-of with extra steps?
The token mechanics overlap; the semantics don't. OBO answers "may this call proceed". The delegation model also answers "how much may this run do in total" and "how do we reconstruct what it did" — quota and audit, which token flows alone don't give you.

Bunun için yeni bir IdP mi lazım?
Demo repo bunu sıradan claim'ler ve Redis sayaçlarıyla yapıyor — runaway deneyindeki her sayı o kadar. Gerçekten yeni olan şey altyapı değil, politika: kesişimli scope, üç eksenli bütçe, varsayılan TTL. Alışverişe çıkmadan önce oradan başlayın.

Do I need a new IdP for this?
The demo repo does it with ordinary claims and Redis counters — every number in the runaway experiment is just that. What's genuinely new is policy, not infrastructure: intersection scoping, three-axis budgets, default TTLs. Start there before shopping.

Başka agent'ların tetiklediği agent'lar?
Delegasyonu zincirleyin: onBehalfOf orijinal insan/sistem principal'ına sabit kalır; agentId/runId mevcut halkayı tanımlar. Yetki zincir boyunca hep kesişerek iner, asla birikmez. İkiden derin zincirlerde gerçekten temkinli olun — atıf, ancak her halkadaki disiplininiz kadar iyidir.

What about agents triggered by other agents?
Chain the delegation: onBehalfOf stays pinned to the original human/system principal while agentId/runId describe the current hop. Authority intersects down the chain, never accumulates. Be genuinely cautious past two hops — attribution is only as good as your discipline at every link.

Demo başka neyi basitleştiriyor?
İki şeyi, bilerek: delegasyon claim'leri deneylerde header'dan okunuyor (production'da imzalı token claim'i olmalı — repo'da not düşülü) ve kesişimli scope değerlendirmesi implemente edilmiş değil, tasarım kuralı olarak anlatıldı. Kota, audit ve TTL mekanizmaları ise bire bir çalışan kod.

What else does the demo simplify?
Two things, deliberately: delegation claims are read from headers in the experiments (production should use signed token claims — noted in the repo), and intersection scoping is described as a design rule rather than implemented. The quota, audit and TTL mechanisms are working code, verbatim.

08Changelog

AI AgentsPlatform EngineeringIdentityKotaQuotasAudit