Auth for agents: the half nobody demos
Table of Contents
Almost every agent demo runs the same way: one API key, full permissions, in an environment variable. It works, it is fast, and it is the reason most of those demos never ship anywhere near real customer data.
The gap between a demo and a deployable system is mostly this.
The agent is not the principal
The single most important idea: the agent is never the identity. It acts on behalf of a person or a service account, and that principal’s permissions are what bound the action.
Get this wrong and you build a system where “what can the agent do” has one answer for everybody, which means the answer has to be “everything the most privileged user can do”. Every user then inherits the maximum blast radius.
Resolve the principal at the edge, before any tool runs. Pass it through every layer. Never let it be an argument the model supplies - a model-supplied identity is a model-controlled permission, and the model can be talked into things.
What enterprise actually asks for
The moment you sell to a company rather than a person, a specific list arrives. It is worth knowing it in advance because retrofitting is painful:
- SSO via SAML or OIDC. They will not create separate passwords. Their identity provider is the source of truth.
- SCIM provisioning. When someone leaves, access is revoked automatically. Manual deprovisioning is an audit finding.
- Roles and scoped permissions. Not everyone gets every tool.
- Audit logs. Who did what, when, and on whose behalf.
None of it is interesting engineering, all of it is mandatory, and it is a solved problem. Use an identity provider - WorkOS, Auth0, whatever fits - and spend your effort on the part that is specific to agents.
Scope tools to roles
Authentication is who. Authorisation is what, and for agents it is the more interesting half.
Scope at the tool layer, not inside the tool. A support agent’s tool list should not contain the refund tool at all. This is meaningfully stronger than including it and checking permissions on invocation, for two reasons: a tool that is absent cannot be called by mistake, and a tool that is absent does not occupy a slot in the model’s selection problem.
Deny by default. New tools are unavailable until explicitly granted to a role. The opposite - available until restricted - guarantees that the one tool someone forgot to think about is the one that causes the incident.
Bound the spend
Agents can loop, and a loop that calls a paid API is a bill. This is a genuinely new failure mode: traditional software does not usually decide to retry something three hundred times because the error message was ambiguous.
Set hard ceilings per session, per account and per day, enforced server-side. When a limit is hit, stop and surface it. Do not degrade quietly to a cheaper path - that hides the runaway and makes the diagnosis harder later.
Make actions attributable
An audit log that records “agent updated customer 4821” is insufficient. It has to record which human the agent was acting for, which session, and what triggered it.
Without that chain, you cannot answer the two questions that get asked after an incident: who authorised this, and what else did that same run touch. Those are the questions that determine blast radius, and you want to answer them in minutes.
Log the principal, the agent identity, the tool, the arguments (with secrets redacted), the result, and the approval reference if one was required.
Never put credentials in tool arguments
Tool arguments end up in transcripts. Transcripts get logged, cached and sometimes shown to users.
The server holds credentials and resolves them from the authenticated session. If a tool signature contains a token, a password or a key, the design is wrong - not the handling of it, the design.
What to read next
- Designing an MCP server - where these boundaries get enforced in practice.
- Approval gates - the control that sits on top of authorisation.
- The stack - the identity tooling behind this.