Insight

My AI agents can now act for a person Moi agenci AI potrafią teraz działać w imieniu osoby

The first lab gave two agents their own ID badges — but each acted only as itself. Real agents work for a specific person. If an agent issues a refund, whose identity is on the audit log, and can it touch only that customer's data? This is the next step: the identity now carries a second fact — who it is acting for. Pierwsze laboratorium dało dwóm agentom własne identyfikatory — ale każdy działał tylko jako on sam. Prawdziwi agenci pracują w imieniu konkretnej osoby. Jeśli agent robi zwrot, czyja tożsamość jest w logu audytowym i czy może dotknąć tylko danych tego klienta? To kolejny krok: tożsamość niesie teraz drugi fakt — w czyim imieniu działa.

The setup

A fictional shop, SkynarcWind Outfitters. Maya is a shopper; order-agent handles her orders and refunds; cs-agent is read-mostly customer service.

The mechanism

A tiny broker reads the Okta tokens for both the agent and Maya, checks a "may act" list, and mints a Google Cloud token scoped to only Maya's folder.

The result

The agent reaches Maya's file and is denied every other customer's. A different agent trying to act for Maya is refused — the confused deputy, shut down.

A while ago I built a small lab to learn about AI agent identity. In it, two AI agents each got their own ID badge from Okta, federated into Google Cloud with no static keys, and were held to least privilege by IAM — not by the agent "being nice". (That was the first article.)

But that lab had one big simplification: each agent acted only as itself. Real agents don't. They do work for a specific person. If an agent issues a refund, whose identity is on the audit log — the agent's, or the customer's? And can it touch only that customer's data, or everyone's?

Each agent already has its own identity — now that identity can carry a second fact: who it is acting for.

The setting

To keep it concrete I use a fictional shop, SkynarcWind Outfitters. The cast:

  • Maya — a shopper.
  • order-agent — handles orders and refunds (read + write).
  • cs-agent — customer service (read-mostly).

The goal: order-agent should be able to act on behalf of Maya — and reach only Maya's files, never another customer's.

An honest detour: Okta said "not for agents"

The standard way to do "on behalf of" is OAuth token exchange. I tried to switch it on in Okta and got a clear warning: "Token Exchange is not suited for AI Agent flows." Okta now sells a dedicated product for this (Okta for AI Agents / Cross App Access) — but it is a paid feature, and it is built for agents connecting to other apps, not my case of an agent reaching into cloud storage. On the free tier, Okta would not mint the "on behalf of" token for me.

So I built the one missing step myself — a tiny broker. This is the honest heart of the article.

The small broker (Okta is not replaced)

Okta still does its job: it logs Maya in, and it still issues the agents' identities. The broker only reads those Okta-issued tokens and enforces one rule. Here is the whole flow:

  1. Maya logs in at Okta → she gets a token.
  2. order-agent sends the broker two tokens: its own, and Maya's.
  3. The broker verifies both against Okta's public keys, checks a small "may act" list (is this agent allowed to act for this customer?), and mints a Google Cloud token scoped to only Maya's folder.
  4. order-agent uses that token: it can read Maya's file, and is denied any other customer's.

Two things I care about here:

  • Still no static keys. The broker gets its own Google Cloud identity the same keyless way the agents do (Okta → Workload Identity Federation → a service account).
  • The boundary is structural, not behavioural. Customer data lives in its own bucket that only the broker can reach. The agents have no access to it at all. So the only door to customer data is through the broker and its may act check — the agent literally cannot reach it another way.

Getting Maya a real login token on a free Okta org was, honestly, the fiddliest part: the silent headless login isn't supported on the modern engine, the app type had to change, the sign-on policy demanded MFA, and the authorization-server policy had to allow it. Undramatic plumbing — I mention it because it was most of the work.

The model does not decide who Maya is or what she owns. Okta says who everyone is; Google Cloud enforces what they can touch; the broker just carries "acting for Maya" between them.

The test

One command runs the whole thing: order-agent acting for Maya, then the same agent reaching for a different customer, then a different agent trying to act for Maya. The result:

====================================================================================
Agent Identity Lab — P2a delegation (order-agent acts on behalf of a customer)
====================================================================================
SCENARIO                                             EXPECT   RESULT
------------------------------------------------------------------------------------
OK  order-agent for Maya reads maya/order-4471.txt   allowed  allowed
      chain: agent=order-agent  [email protected]
OK  order-agent for Maya reads bob/order-5502.txt    denied   denied
      chain: agent=order-agent  [email protected]
OK  cs-agent for Maya (confused-deputy gate)         refused  refused
====================================================================================
OK: delegation scoped correctly and the confused deputy was refused.

Reading the three rows:

  • Maya's file → allowed. order-agent, acting for Maya, reads Maya's order.
  • Bob's file → denied. The same agent in the same run cannot read another customer — the token it was given only reaches Maya's folder.
  • cs-agent for Maya → refused. This is the classic confused-deputy attack: one agent trying to get another to act for it. The broker's may act check says no.

And every action carries the chain: agent = order-agent, on behalf of = Maya. The audit log finally answers the question that matters — who did this, and on whose behalf?

Customers bucket with maya/ and bob/ folders
The customers bucket, partitioned per customer — maya/ and bob/ folders. Delegation scopes an agent to exactly one of these.
Customers bucket Permissions — only sa-delegation-broker
The same bucket's Permissions — the only principal is sa-delegation-broker (Storage Object Admin). The agents have no binding here at all; the broker is the only way in.
Okta applications: broker, sentinel, storefront, agents
The non-human identities in Okta — delegation-broker, the storefront login app that mints Maya's token, and the agents (plus sentinel, from the next article).
GCP Workload Identity pool okta-pool
…and in Google Cloud they federate through the okta-pool Workload Identity pool — the badges become cloud access with no static keys.

What I learned

  • Delegation is a chain of custody. "Who authorized this?" deserves a real, logged answer — not a shrug.
  • The confused deputy is real. Without a may act check, one agent can quietly borrow another's power. The defense is a rule, not good manners.
  • The managed products exist now (Okta's Cross App Access, and others). I built the mechanism myself to understand it — a smaller, honest promise, and a pointer to where the production path would go.
  • Structural beats behavioural. The agents can't reach customer data at all; a scoped, checked delegation is the only door.

And here's the thread to the next step: now every action carries "acting for Maya". That attribution is exactly what makes the next phase possible — if every action is attributable, I can finally watch for the one that shouldn't have happened, and shut it down. That's the next article: detect & respond.

This is still a private learning lab, not a product. If you work on non-human identity, agent security, or delegation, I'd genuinely like your critique — including the sharp kind.

—A Skynarc learning project on non-human identity.

Układ

Fikcyjny sklep SkynarcWind Outfitters. Maya to klientka; order-agent obsługuje jej zamówienia i zwroty; cs-agent to obsługa klienta, głównie do odczytu.

Mechanizm

Mały broker czyta tokeny Okty — agenta i Mai — sprawdza listę „may act" i wydaje token Google Cloud ograniczony tylko do folderu Mai.

Wynik

Agent sięga do pliku Mai i dostaje odmowę dla każdego innego klienta. Inny agent próbujący działać w imieniu Mai zostaje odrzucony — zdezorientowany zastępca, zatrzymany.

Jakiś czas temu zbudowałem małe laboratorium, żeby nauczyć się o tożsamości agentów AI. Dwaj agenci AI dostali własne identyfikatory z Okta, federowali się do Google Cloud bez statycznych kluczy i byli ograniczeni do najmniejszych uprawnień przez IAM — a nie przez to, że agent „jest grzeczny". (To był pierwszy artykuł.)

Ale tamto laboratorium miało jedno duże uproszczenie: każdy agent działał tylko jako on sam. Prawdziwi agenci tak nie robią. Wykonują pracę w imieniu konkretnej osoby. Jeśli agent robi zwrot pieniędzy, czyja tożsamość jest w logu audytowym — agenta czy klienta? I czy może dotknąć tylko danych tego klienta, czy wszystkich?

Każdy agent ma już własną tożsamość — teraz ta tożsamość może nieść drugi fakt: w czyim imieniu działa.

Sceneria

Żeby było konkretnie, używam fikcyjnego sklepu SkynarcWind Outfitters. Obsada:

  • Maya — klientka.
  • order-agent — obsługuje zamówienia i zwroty (odczyt + zapis).
  • cs-agent — obsługa klienta (głównie odczyt).

Cel: order-agent powinien móc działać w imieniu Mai — i sięgać tylko do plików Mai, nigdy innego klienta.

Szczera dygresja: Okta powiedziała „nie dla agentów"

Standardowy sposób na „w imieniu" to wymiana tokenów OAuth. Próbowałem włączyć to w Okcie i dostałem jasne ostrzeżenie: „Token Exchange nie jest odpowiedni dla przepływów agentów AI." Okta sprzedaje teraz dedykowany produkt do tego (Okta for AI Agents / Cross App Access) — ale to funkcja płatna i zbudowana dla agentów łączących się z innymi aplikacjami, a nie dla mojego przypadku, gdzie agent sięga do magazynu w chmurze. Na darmowym planie Okta nie wygeneruje dla mnie tokenu „w imieniu".

Więc zbudowałem ten jeden brakujący krok sam — mały broker. To jest szczere sedno artykułu.

Mały broker (Okta nie jest zastąpiona)

Okta nadal robi swoje: loguje Maję i nadal wydaje tożsamości agentów. Broker tylko czyta te tokeny wydane przez Oktę i egzekwuje jedną zasadę. Oto cały przepływ:

  1. Maya loguje się w Okcie → dostaje token.
  2. order-agent wysyła brokerowi dwa tokeny: swój i Mai.
  3. Broker weryfikuje oba za pomocą publicznych kluczy Okty, sprawdza małą listę „may act" (czy ten agent może działać w imieniu tego klienta?) i wydaje token Google Cloud ograniczony tylko do folderu Mai.
  4. order-agent używa tego tokenu: może odczytać plik Mai i dostaje odmowę na plik dowolnego innego klienta.

Dwie rzeczy, na których mi zależy:

  • Nadal żadnych statycznych kluczy. Broker zdobywa własną tożsamość Google Cloud tak samo bezkluczowo jak agenci (Okta → Workload Identity Federation → konto serwisowe).
  • Granica jest strukturalna, nie behawioralna. Dane klientów są w osobnym buckecie, do którego dostęp ma tylko broker. Agenci nie mają do niego dostępu w ogóle. Więc jedyne drzwi do danych klientów prowadzą przez brokera i jego sprawdzenie may act — agent dosłownie nie może sięgnąć do nich inaczej.

Zdobycie dla Mai prawdziwego tokenu logowania na darmowej organizacji Okta było, szczerze, najbardziej upierdliwą częścią: ciche logowanie bez przeglądarki nie jest wspierane w nowym silniku, typ aplikacji trzeba było zmienić, polityka logowania wymagała MFA, a polityka serwera autoryzacji musiała na to pozwolić. Nieefektowna hydraulika — wspominam o niej, bo to była większość pracy.

Model nie decyduje, kim jest Maya ani co posiada. Okta mówi, kim wszyscy są; Google Cloud egzekwuje, czego mogą dotknąć; broker tylko przenosi „działa w imieniu Mai" między nimi.

Test

Jedno polecenie uruchamia całość: order-agent działający w imieniu Mai, potem ten sam agent sięgający do innego klienta, potem inny agent próbujący działać w imieniu Mai. Wynik:

====================================================================================
Agent Identity Lab — P2a delegation (order-agent acts on behalf of a customer)
====================================================================================
SCENARIO                                             EXPECT   RESULT
------------------------------------------------------------------------------------
OK  order-agent for Maya reads maya/order-4471.txt   allowed  allowed
      chain: agent=order-agent  [email protected]
OK  order-agent for Maya reads bob/order-5502.txt    denied   denied
      chain: agent=order-agent  [email protected]
OK  cs-agent for Maya (confused-deputy gate)         refused  refused
====================================================================================
OK: delegation scoped correctly and the confused deputy was refused.

Odczytanie trzech wierszy:

  • Plik Mai → dozwolone. order-agent, działając w imieniu Mai, czyta zamówienie Mai.
  • Plik Boba → odmowa. Ten sam agent w tym samym uruchomieniu nie może odczytać innego klienta — token, który dostał, sięga tylko do folderu Mai.
  • cs-agent w imieniu Mai → odrzucone. To klasyczny atak „zdezorientowanego zastępcy" (confused deputy): jeden agent próbuje nakłonić drugiego, by działał w jego imieniu. Sprawdzenie may act brokera mówi „nie".

I każda akcja niesie łańcuch: agent = order-agent, w imieniu = Maya. Log audytowy w końcu odpowiada na pytanie, które się liczy — kto to zrobił i w czyim imieniu?

Bucket klientów z folderami maya/ i bob/
Bucket klientów, podzielony per klient — foldery maya/ i bob/. Delegacja ogranicza agenta dokładnie do jednego z nich.
Permissions bucketa klientów — tylko sa-delegation-broker
Zakładka Permissions tego samego bucketa — jedynym principalem jest sa-delegation-broker (Storage Object Admin). Agenci nie mają tu żadnego powiązania; broker to jedyne wejście.
Aplikacje Okta: broker, sentinel, sklep, agenci
Tożsamości nieludzkie w Okcie — delegation-broker, aplikacja logowania sklepu wydająca token Mai, oraz agenci (i sentinel, z następnego artykułu).
Pula Workload Identity okta-pool w GCP
…a w Google Cloud federują się przez pulę Workload Identity okta-pool — identyfikatory stają się dostępem do chmury bez statycznych kluczy.

Czego się nauczyłem

  • Delegacja to łańcuch odpowiedzialności. „Kto to autoryzował?" zasługuje na prawdziwą, zalogowaną odpowiedź — nie wzruszenie ramion.
  • Zdezorientowany zastępca jest realny. Bez sprawdzenia may act jeden agent może po cichu pożyczyć moc innego. Obroną jest zasada, nie dobre maniery.
  • Produkty zarządzane już istnieją (Cross App Access Okty i inne). Zbudowałem mechanizm sam, żeby go zrozumieć — mniejsza, szczera obietnica i wskazówka, dokąd prowadzi droga produkcyjna.
  • Struktura bije zachowanie. Agenci nie mogą sięgnąć do danych klientów w ogóle; ograniczona, sprawdzona delegacja to jedyne drzwi.

A oto nić do następnego kroku: teraz każda akcja niesie „działa w imieniu Mai". Ta atrybucja to dokładnie to, co umożliwia następną fazę — jeśli każda akcja jest przypisywalna, mogę w końcu obserwować tę, która nie powinna się zdarzyć, i ją zablokować. To następny artykuł: wykrywanie i reakcja.

To wciąż prywatne laboratorium do nauki, nie produkt. Jeśli pracujesz z tożsamościami nieludzkimi, bezpieczeństwem agentów albo delegacją, naprawdę chciałbym poznać Twoją krytykę — także tę ostrą.

—Projekt edukacyjny Skynarc o tożsamości nieludzkiej.

← Back to Insights