Knowing who the agent is answers the wrong question

Authentication answers "is this really the agent it claims to be." That question, fully solved, still leaves the dangerous one open: given that it really is that agent, what should it be allowed to do for this specific task, right now? A standing API key with broad scope answers authentication perfectly and capability scoping not at all -- every request made with that key can do everything the key can do, whether or not the current task needs it.

This gap matters more for agents than for traditional services because an agent's actions are chosen by a model at runtime rather than by a fixed code path a human wrote and reviewed in advance. A traditional service's call to a database is a line of code someone read in a PR; an agent's call to the same database is a decision the model made a moment ago, and the permission boundary is the only thing standing between "the model made a reasonable choice" and "the model made a mistake with the blast radius of whatever the credential allows."

Advertisement

Authentication and capability scoping are separate questions

Treat them as two independent controls, not one. Authentication is typically static for the life of an agent's deployment -- it proves identity once, at connection time, and doesn't change task to task. Capability scoping should be dynamic and task-scoped -- computed fresh for each unit of work, granting exactly what that unit of work needs and nothing accumulated from previous tasks or left over "just in case" a future task needs it.

The practical test for whether a system actually separates the two: can you answer "what is this agent allowed to do right now" without also answering "what is this agent allowed to do in general"? If the two questions have the same answer, the system has authentication but no capability scoping -- the agent's standing identity is its permission set, and every task runs with the union of everything the agent might ever need rather than what this task specifically needs.

Advertisement

Least-privilege, per-task credentials

The mechanism that makes dynamic scoping practical is issuing a fresh, narrowly-scoped, short-lived credential per task rather than handing every task the same standing key. Concretely: a credential minted at task-start time, scoped to exactly the resources that task's plan touches, expiring shortly after the task completes (or on a short fixed TTL if the task's duration is unpredictable) rather than living indefinitely.

Standing broad key (wrong default for an agent):
  scope: full database admin, all tables, no expiry
  used by: every task this agent ever runs

Per-task minted credential (target):
  scope: UPDATE on orders WHERE id = 4471, expires in 10 min
  used by: exactly one task -- "update the shipping address on order 4471"
  revoked: automatically, on expiry, whether the task succeeded or not

This costs something real -- a credential-minting step in the task-setup path, and infrastructure that can actually issue narrowly-scoped, short-lived grants rather than only ever handing out the same static key. That cost buys the property that matters: a credential leaked, logged accidentally, or misused by a hallucinated tool call can only do what that one task needed, for the window that task needed it, not what the agent could theoretically ever do.