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.