M. Semih Babacan

My agents are all logging in as me

Every agent I run authenticates with a human's credentials or a shared service account. The audit log records the wrong actor, and I don't think I'm unusual.

Mehmet Semih Babacan
Mehmet Semih Babacan

AI Technical Product Manager

March 6, 20268 min read10 views
My agents are all logging in as me

I tried to count the agents touching my own systems last month. Honest answer: I don't think I got them all. There's the one that reads supplier feeds and writes prices. There's the one that buys stock when an order lands, with real money. There's whatever I spun up in a terminal on a Tuesday to reconcile two tables and never turned off.

Not one of them has an identity. They authenticate as me, or as a service account I created years ago and have never rotated. If a person worked that way in my company, borrowing my login, moving money, leaving no record of who did what, I would call it an incident. When my own code does it I call it automation and go to lunch.

Counting is the first thing that goes wrong

You can't inventory what was never registered. Agents don't get provisioned. They get written. Somebody needs a task done, wires up a loop with a model in it, hands it a token that already works, and ships. There's no form, no approval, no directory entry, nothing that shows up in a quarterly access review because there's nothing to review.

That's not a discipline problem. It's what happens when creating a new actor in your system costs one line of config and creating a new identity costs a ticket, a security review and two weeks.

So the population grows and the register doesn't. My own count was a guess. I'd bet most counts are guesses.

The second-order effect is worse than the missing list. Offboarding works because a person maps to a set of accounts, and revoking the person revokes the set. An agent that runs on my credential inherits my access silently, which means it also inherits every grant I ever picked up and never gave back. The day I leave, either it dies with my account and something in production stops, or somebody keeps the account alive for it. The second one is the easy choice, and it's the one that gets made.

The log records me, not the agent

Here's the part I find genuinely uncomfortable, and it's the whole post in one picture.

The agent row is the problem. It presents a human's session token, so the log attributes its actions to the human. Two actors, one name.

Every access-control system I've worked with answers one question: who did this. The answer has to be a principal that exists in the directory. When an agent presents my token, the honest answer to "who did this" is "semih", and that answer is wrong in a way nothing downstream can detect. Not the SIEM, not the review, not me reading the log six weeks later trying to work out why a price changed at 3am.

Rotating that credential doesn't help. Rotation changes the secret. It doesn't split the actor.

We only ever built two kinds of principal

The reason this keeps happening is architectural, and it's older than any of the current models. Identity infrastructure was designed around two shapes:

  • a human, who gets SSO, MFA, role-based access, and a session that dies
  • a service, which gets a key, a narrow scope, and a rotation schedule

Both are well understood because both are predictable. A human is slow, present, and can be asked "are you sure". A service does exactly one thing forever and never surprises you.

An agent is neither, and that's not a philosophical point. It's operational. It won't answer an MFA prompt at 3am. It has no judgement about whether a request is appropriate. But it also isn't a fixed-function service, because it decides what to touch and in what order, and it chains actions that nobody wrote down in advance.

There's no primitive for that. So it gets stuffed into whichever of the two boxes has a working credential nearby, which is almost always the human one.

A service can't be talked into anything

The difference that actually matters to me is instructability. My price worker does what its code says. You cannot persuade it. There's no text anywhere in the world that makes it place an order.

An agent's inputs are instructions and data at the same time, and it can't reliably tell which is which. A ticket body, a supplier's product description, a page it fetched, another agent's output: any of it can carry something that reads like a command. That's not a bug someone will patch. It's the property that makes agents useful.

Put that next to the identity gap and the shape of the risk gets clear. An entity that can be influenced by whatever it reads is holding a credential that was scoped for an entity that can't. The scope was sized for the wrong threat.

A scope is a bet about behaviour. When I granted my old shared account write access across three systems, the bet was that the code holding it does what the code says. That bet is still good for the price worker. It is not good for an agent whose next action depends on a paragraph of text a stranger wrote, and I never went back and re-priced it. Nobody does. The permission was granted once, for a threat model that quietly stopped applying.

What I do about it now

None of this is a product recommendation. It's the four things I changed after I drew that diagram, in the order I changed them, cheapest first.

  1. Give every agent its own credential

    One agent, one service account, its own name. No sharing, no borrowing mine. This alone is boring and it fixes the log: the actor column finally says something true.

  2. Scope it to the job, then take things away

    I start from what the agent needs for the one task and grant that. Then I remove one permission and see what breaks. The one that never breaks was never needed.

  3. Give it an expiry

    A credential with no end date outlives the reason it existed. The Tuesday-afternoon agent I mentioned is exactly the case. If its key had died in seven days I would never have had to remember it.

  4. Cap the blast radius in money and volume

    Permissions answer what it can touch. They don't answer how much. My buying agent has a spend ceiling and a per-run item cap, and both are enforced outside the agent, because a limit the agent can reason about is a limit it can be argued out of.

Step one is mostly a config change. This is what it looked like for one worker:

before
# shared account, created 2019, never rotated
SERVICE_ACCOUNT=ops-automation@example
SCOPES=datastore.user,secretmanager.admin,storage.admin
EXPIRES=never
SPEND_LIMIT=
after
# one agent, one identity
SERVICE_ACCOUNT=agent-price-sync@example
SCOPES=datastore.user
EXPIRES=7d
SPEND_LIMIT=0
Same worker, two identities. The second one shows up in the log as itself.

The buying agent got its own account with a real spend limit and nothing else. Two accounts, two names in the log, two different things I can revoke at 3am without stopping the other one.

An agent without an identity isn't an employee. It's an intruder I invited in.

the line I keep coming back to

The uncomfortable part is the direction of travel

The reason I'm writing this rather than quietly fixing my own config: my count was a guess in a system where I wrote every agent myself. That's the easy case.

Soon it won't just be mine. Vendors are shipping agents into products I already pay for. Customers will point agents at my API and I will have no way to tell those calls from a person's. My own teams will add agents faster than anyone writes them down, because writing them down is the slow path and shipping is the fast one.

The pattern rhymes with shadow IT, but it's worse in one specific way. Shadow IT was people using tools nobody approved. This is approved tools being used by actors nobody can name, with credentials that belong to someone else.

And the ordering is nasty. The faster a company adopts, the bigger the ungoverned surface, and none of it shows up as a problem until it does. Speed without identity isn't an advantage. It's a bill with a delay on it.

Going in, I thought this was a governance topic, the kind of thing a policy document handles. It isn't. It's a missing primitive, and until there's a real one, the only honest move is to stop pretending an agent is a person or a script and give it a name of its own.

What I still don't know: whether per-agent service accounts hold up at a hundred agents, or whether I'm just doing manual IAM until something better exists. Ask me in a year.

Related: Get Shit Done: The Anti-Enterprise AI Workflow.