A branch came in for review with about sixty commits on it, every one authored by someone on the team.
He hadn't written them.
Claude Desktop had, running on his laptop, signing commits with the git identity we configured during setup.
As far as the repository was concerned, the work was his.
As far as blame, audit and every code-ownership convention we had, the work was his.
Nobody could separate the four or five decisions he had actually looked at and accepted from the fifty-odd changes the model produced while he clicked through the result to see whether it worked.
We moved the whole thing off his machine: the model runs server-side now, the working copy is provisioned per ticket in an isolated environment, and what comes back is a URL.
That solved the port conflicts and the dependency drift, which was why we did it.
It did not solve the attribution problem.
It relocated it.
Now a service account commits, and the service account is one identity shared by every run, for every person, on every ticket.
That is the shape of the thing arriving at enterprises considerably faster than most access-management programmes are ready for. a new hire, a printer, and an agent Take a new hire in their first week.
They have a unique identifier that will never belong to anyone else, a set of permissions somebody requested by name, a login trail, and an offboarding procedure that takes an afternoon.
Four things: who they are, what they can reach, what they did, and how you get rid of them.
Hiring, permissions, audit, firing.
Now the printer on the third floor.
It has an asset tag, it sits on a network segment that lets it reach the print server and nothing else, it logs every job, and you can unplug it.
Same four things.
Nobody is impressed by the printer, but the printer is fully accounted for.
Now the agent your team stood up last month to triage tickets, read the CRM and post summaries into Slack.
Who it is: it uses a key minted from a human account, probably belonging to whoever built the thing.
Every log in every downstream system records that person, not the agent.
What it can reach: whatever they could, which for an engineer with admin rights is usually everything.
What it did: indistinguishable from what the human did.
How you fire it: you rotate the key, and you find out what else breaks.
Nobody decided the agent could write to the CRM.
It inherited the permission from the account it borrowed. where the answers get uncomfortable Identity means a credential belonging to this agent and only this agent, distinguishable in every downstream system's logs from the human who deployed it and from the other eleven agents your company is running.
A name in a config file does not qualify.
Whether you can have this depends entirely on the platform.
API-native services handle it well: Anthropic, OpenAI, Stripe and others will issue a key with its own permissions and its own name, no seat required.
The business systems where most agents actually work are the problem.
Salesforce, HubSpot and most CRMs model access around seats occupied by people, so a separate identity per agent means paying for a seat or sharing a credential, and sharing is what teams choose.
Scope is what it can touch, expressed as operations rather than systems. "Read from the ticket store, write to one Slack channel, call the pricing endpoint" is a scope. "Has an API key for Salesforce" tells you nothing about what the thing can actually do.
The trade-off is real and worth stating plainly: narrow scopes break more often, and every break lands on the person who understands the permission model, which is never the person operating the agent.
Broad scopes are cheaper to run and quieter, right up until the day they aren't.
Attribution needs three facts on every action rather than one: which agent did it, which run it belonged to, and which human or system event authorised that run.
What we ended up doing was giving every run its own number, and making sure that number appeared ever