Delegated Credentials: How Agents Should Authenticate

Delegated Credentials: How Agents Should Authenticate

E
By Etzal Earth
13 min read

Authentication systems were built on an assumption that has held for decades: behind every credential there is a person, or a service that a person configured and is responsible for. The API key in an environment variable belongs to a developer. The OAuth token belongs to a user who clicked a consent screen. The service account belongs to a team.

Agents break the assumption in a specific way. The thing making the call is software, but it is not software anyone deployed with a fixed purpose. It decides at runtime which endpoints to hit, in what order, and how many times. It may have been given a goal in natural language an hour ago by someone who has never seen your documentation. It may be running unattended. It may be one of several agents a single person is operating simultaneously.

The question this raises is not technical. Issuing a token to a piece of software is well understood. The question is what the token means. When an autonomous caller reads your data, hits a rate limit, or eventually spends money, whose action was that, and who answers for it.

The identity question when the caller is not a person

Traditional access control answers three questions: who is calling, what are they allowed to do, and what did they do. Each answer assumes a stable subject.

An agent destabilises all three. Who is calling has at least three candidate answers: the model, the runtime that hosts it, and the human who set the task. What they are allowed to do is not fixed, because an agent's actions are generated rather than coded, and the set of endpoints it might touch is not known in advance. What they did is recorded, but attributing it to a responsible party requires knowing which of the three candidates to name.

The instinct is to treat the agent as a new kind of user, give it an account, and move on. That instinct is what produces the mess, and it is worth understanding why before looking at the alternative.

Why an agent account is the wrong abstraction

Create an account for an agent and you have created an identity with no one behind it.

Accounts carry obligations. Somebody agrees to the terms. Somebody is billed. Somebody is contacted when the account behaves badly. Somebody is accountable if the account is used to do something it should not have. An account whose owner is a process satisfies none of this. When it misbehaves, there is no one to talk to, and the only available remedy is to disable it.

Lifecycle is the second problem. Agents are ephemeral and numerous. A user might spawn dozens in a day and keep none of them. An account model produces either a proliferation of abandoned identities, each one a credential still valid somewhere, or a single shared account behind every agent that user ever runs, which destroys the isolation the accounts were supposed to provide.

Permission modelling is the third. Accounts accumulate permissions, because permissions are granted when needed and rarely removed. An account that has been running tasks for six months has whatever was ever required for any of them. That is tolerable for an employee whose behaviour is bounded by judgement and employment. It is not tolerable for a process whose behaviour is generated from a prompt that anyone can write.

The underlying error is treating the agent as a principal. It is not one. It is something acting on behalf of a principal, and the model that fits is not identity. It is delegation.

Delegation, where the principal stays human

Under delegation, the agent never becomes the subject of authorisation. A human or an organisation remains the principal. The agent holds a credential that says, in effect: this token acts for that principal, within these limits, until this time.

Four properties follow, and they solve the problems the account model creates.

Authority is derived, never inherent. An agent cannot do anything its principal could not do. Delegation narrows, it never widens. If the principal loses access to a dataset, every credential derived from that principal loses it too, immediately, without anyone having to remember which agents existed.

Scope is explicit and small. A delegated credential is issued for a task, not for a role. It names the endpoints, the data, the volume, and the duration. Anything outside that is refused, and the refusal is not a failure of the system, it is the system working.

Attribution survives. Every call carries both the agent identifier and the principal it acts for, so a log line answers the question that matters, which is not which process made the call but who is responsible for it having been made.

Revocation is cheap and targeted. Killing one delegated credential stops one agent. It does not lock out the human, and it does not require reissuing anything else.

What a scoped credential actually carries

The difference between a delegated credential and an API key with a shorter expiry is what is written into it. A credential worth the name carries limits that the issuing system enforces, not documentation the caller is trusted to follow.

  • The principal. The human or organisation on whose behalf the credential acts, recorded in a form that remains resolvable after the agent is gone.
  • The agent identity. Which specific instance, so that one misbehaving agent can be isolated from its siblings without touching the principal.
  • Scope of capability. The operations permitted, expressed as concretely as the API allows. Read access to one dataset is a scope. Full access to the account is not.
  • Scope of data. For a spatial platform this is often geographic or thematic: a bounding region, a set of layers, a category of records. A credential issued for a study in one city has no business reading another.
  • Quantitative limits. Requests, compute, spend. These are the limits that matter for an autonomous caller, because the failure mode is not one forbidden action, it is a million permitted ones.
  • Validity window. An expiry short enough that a leaked credential has limited value, long enough that the task can finish.
  • Revocation handle. An identifier that can be looked up and killed independently of everything else.

The quantitative limits deserve emphasis. Human misuse of a credential tends to be qualitative: someone reads a record they should not have. Agent misuse tends to be quantitative: a loop that should have run ten times runs ten thousand. Access control designed only around what is permitted, with no ceiling on how much, is not designed for this caller.

The analogies that hold, and where they stop

Two existing systems solved a version of this problem and are worth borrowing from rather than reinventing.

The corporate card is the closer analogy for spending. An employee is issued a card that draws on company funds, with a limit, a category restriction, a statement, and a cancel button. The company remains liable. The employee remains accountable. Nobody argues that the card is a person or that it should have unlimited authority because the company is solvent. Every property that makes corporate cards workable is a property a delegated agent credential needs: bounded authority, clear attribution, an itemised record, and independent cancellation.

Cloud IAM role assumption is the closer analogy for access. A workload does not hold long lived credentials. It assumes a role, receives short lived credentials scoped to that role, and the credentials expire. The role exists independently of any particular workload, the assumption is logged with the identity that performed it, and revoking the role stops every workload using it. This is delegation implemented at scale, and it has already absorbed the lessons about expiry, least privilege, and audit that agent authentication is currently rediscovering.

Where both analogies stop is autonomy. A cardholder decides to buy something and can be asked why. A workload does what its code says. An agent does neither: its actions are generated from an instruction, and the instruction may itself have come from an untrusted source. That is the genuinely new part, and it argues for tighter limits than either analogy would suggest, not looser ones, because the space of possible actions is wider and less predictable than in either prior case.

Attribution and the chain that has to hold

For an autonomous system, the audit log is not a compliance artefact. It is the only mechanism by which anyone can reconstruct what happened, because there is no operator to ask.

A useful record links four things: which agent made the call, which principal it acted for, which credential authorised it, and what the call did. The first three are the chain. Break any link and the fourth is unattributable.

Where this gets harder is nesting. Agents call other agents. An orchestrator delegates a subtask to a specialised worker, which calls a tool, which is itself an agent with its own credentials. Attribution has to survive several hops, and the failure mode is that somewhere in the chain a component substitutes its own identity for the caller's, at which point everything downstream is attributed to the intermediary.

Two rules keep the chain intact. Delegation must always narrow: a credential derived from another credential can never carry more authority than its parent, so a sub-agent cannot acquire capabilities its orchestrator lacked. And the original principal must remain visible at every hop, carried through rather than replaced, so the last service in the chain can still answer who is ultimately responsible.

Neither rule is exotic. Both are routinely broken by systems that were built one layer at a time.

Show once, store never

Anything that can retrieve a secret is a way to steal it. This is the single design decision that most reliably separates a credential system that survives an incident from one that does not.

The pattern is straightforward. When a credential is created, display it once. Store only a hash. Provide no endpoint, no support process, and no admin panel that can return the value again. If the holder loses it, they rotate.

The reason to insist on this is that a retrievable secret has a much larger attack surface than the secret itself. Every path that can read it becomes a path to compromise: the admin interface, the support tool, the backup, the log line where somebody printed it during debugging, the internal service that fetches it on behalf of a UI. Each of those paths has its own access control, and the credential is only as protected as the weakest one.

The pattern matters more for agent credentials than for human ones, because there are more of them, they are created programmatically, and they are handled by software that will happily write them anywhere. Metadata about a credential, its scope, its creation time, its last use, should be fully visible. The secret itself should exist in exactly two places: the holder's storage and nowhere.

A related discipline is worth stating plainly: a credential that appears in a request URL will end up in access logs, browser history, proxy caches, and referrer headers. Credentials belong in headers.

Rotation, designed in rather than bolted on

Rotation fails for a predictable reason. It is treated as an emergency procedure, so it is only exercised during emergencies, so it does not work when it is needed.

The functioning version has a few properties. Multiple credentials are valid at once, so a new one can be issued and adopted before the old one is withdrawn, and nothing has to be swapped atomically. Rotation is a normal operation with an ordinary interface, not a support ticket. Last use is recorded, so an old credential can be retired with confidence that nothing is still relying on it. And revocation takes effect quickly, which means checking validity rather than trusting a signature that cannot be recalled.

Short lived credentials make most of this unnecessary, which is the strongest argument for them. If a credential expires in an hour, rotation is continuous and automatic, a leak has a bounded blast radius, and the question of stale credentials never arises. The cost is that something has to be able to mint new ones, and that minting authority becomes the thing worth protecting.

For agents specifically, expiry should be bounded by the task rather than by the calendar. A credential issued for a job that takes twenty minutes has no reason to remain valid for ninety days.

Where this is heading

The current generation of agents mostly reads. The interesting problems arrive as they begin to hold budgets and transact.

Reading has bounded consequences. A misconfigured agent that reads too much wastes quota and possibly exposes data. An agent that spends does something irreversible, on behalf of someone who was not present when it happened, in a system where the counterparty may have no way to tell an agent from a person.

Several requirements follow, and they are worth building towards before they are urgent. Spending limits belong in the credential rather than in the agent's instructions, because instructions are generated text and generated text can be influenced. Certain classes of action should require confirmation from the principal regardless of the credential's scope, which means the design needs a notion of actions that delegation alone cannot authorise. Counterparties need to be able to tell that they are dealing with a delegated agent and to see the chain, because a transaction whose authorisation cannot be verified is a dispute waiting to happen. And there has to be a mechanism to unwind: an agent operating unattended will eventually do something wrong, and the recovery path cannot be improvised after the fact.

None of this requires new cryptography. It requires taking the delegation model seriously enough to encode limits in credentials rather than in prompts.

The rule to hold on to

If a single principle survives from all of this, it is that the agent is never the principal. It is always acting for someone, and that someone must be identifiable, must have consented to the scope, and must be reachable when something goes wrong.

Systems built on this principle degrade gracefully. A credential leaks, and the damage is bounded by its scope and its expiry. An agent misbehaves, and one credential dies while its principal continues working. Something goes badly wrong, and the log says who is responsible.

Systems built on agent-as-user degrade the other way. The credential that leaks is the account credential. The agent that misbehaves is the account. And when the question of responsibility is finally asked, the answer is the name of a process that no longer exists.