← All posts

Credentials

Scoped tokens vs. raw API keys: stop handing agents the keys to everything

When you paste a raw API key into an agent's environment, you are not granting access to a task. You are granting access to everything that key can do, for as long as the key lives, to anything that can read the runtime. The agent only needed to read a report. The key it now holds can also delete the project.

That gap — between what the task needs and what the credential allows — is where most agent risk lives. Scoped tokens close it.

The problem with raw keys in agent runtimes

  • They over-grant by default. Most API keys are coarse. "Read analytics" and "change billing" often ride on the same key.
  • They leak by sitting still. A key in a prompt, a local MCP config, or an env var is one log line, one screenshot, or one injected instruction away from exposure.
  • They are painful to rotate. When a key spreads across machines and configs, revoking it means hunting down every copy — so teams delay, and stale keys pile up.
  • They erase identity. If five workers share one key, your logs show the key, not which worker did what.

What "scoped token" actually means

A scoped token is a credential minted for a specific worker and a specific set of allowed actions — and, critically, it is not the underlying SaaS secret. The agent holds a token that says "this worker, this role." The real OAuth grants, PATs, and refresh tokens stay on the server. The token is the boarding pass; the passport never leaves the safe.

Concretely, a good scoped token gives you:

  • Least privilege — only the tools and actions the role needs are reachable through it.
  • Server-side custody — raw credentials never appear in prompts, configs, or runtimes, so there is nothing valuable to leak from the agent side.
  • Cheap revocation — disable one worker's token without rotating the shared upstream secret or touching other workers.
  • Real identity — every call is attributable to a worker and role, not an anonymous key.

Allow-all vs. allow-only-this

The deepest difference is the default. A raw key is deny nothing: it permits every action in its scope until something external stops it. A scoped token through a policy layer is permit only this: the call is refused unless the worker's role explicitly allows it. For a deterministic script, allow-all is merely risky. For a non-deterministic agent that can be steered by its inputs, allow-all is the whole problem.

The agent should carry a key to its own task — not a master key it happens not to use yet.

A practical migration

Moving off raw keys does not require rewriting your agents. A workable order:

  • Inventory every place an agent currently holds a raw key, and the real scope each key carries.
  • Move the secrets server-side, behind a layer that issues per-worker tokens.
  • Define roles by task — what each worker actually needs to read and write — and scope tokens to them.
  • Point your MCP clients at the layer with their worker tokens; the agent code stays the same, it just sees fewer, safer tools.
  • Rotate out the old raw keys and watch the audit log to confirm nothing depended on the over-grant.

The endpoint is simple to state: no agent runtime holds a credential broader than the job in front of it. Grantry exists to make that the default rather than the exception.


Grantry

Keep credentials server-side. Give each worker one scoped token.

Start for free

Questions first? Email [email protected].