Course · Lesson 5 of 30
API Keys
Noob · 7 min read
An API key is a bearer credential: whoever holds the string is you, as far as the provider can tell. Every request it authorizes lands on your bill or acts with your permissions. Agentic coding raises the stakes twice over: you hold more keys (model providers, MCP servers, deploy targets — lesson 7 multiplies these), and you've invited a tireless automated process to work inside the same filesystem where those keys live. This lesson is the hygiene that lets you stop thinking about keys, the agent-specific hazards standard advice misses, and the budget discipline that keeps a bug from becoming an invoice.
The baseline, done right once
Environment, not code. Keys live in environment variables or an
untracked .env; code reads process.env.ANTHROPIC_API_KEY. One place
per machine. The moment a key appears as a string literal anywhere
else — source, config, fixture, script — you've created a second copy
with its own leak path.
.gitignore before the key exists. Add .env* in the same commit
that creates the project, before there's anything to protect.
Ordering matters because git history is forever: a key committed once
is compromised even if deleted a minute later — clones, forks, mirrors,
reflogs, and scrapers all saw it, and automated harvesters find fresh
keys on public GitHub within minutes of a push. Which yields the
non-negotiable rule: if a key touches git history, revoke it. Not
"scrub history" (you can't scrub the copies), not "assess the risk."
Revoke, reissue, move on — five minutes, zero debate.
One key per purpose. Separate keys for dev, CI, and production; separate keys per deployed service. This isn't bureaucracy — it's blast-radius design, and it's what makes incidents boring: when a key leaks, you know what leaked from where (the key's identity tells you), and revoking kills one thing instead of everything. It also makes the usage logs legible: a spike on the CI key means something specific.
Least privilege. Where providers offer scopes, take the minimum. A CI key that can only open pull requests cannot force-push main no matter what goes wrong upstream of it — and "what goes wrong upstream" now includes a confused or manipulated agent (lesson 26), which makes scoping a structural defense, not paperwork.
What changes when an agent is in the loop
Agents echo what they read. An agent debugging your app may cat a
config, print the environment, or paste a request dump — and now the
key is in the conversation transcript, which may be logged, cached, or
synced somewhere with far weaker protections than your .env. Layered
defenses, cheapest first:
- Keep secrets in files agents have no reason to open, and say so:
a CLAUDE.md line — "never print the contents of
.envor any credential; refer to keys by variable name only" — genuinely works (lesson 8). - Then make it true regardless of compliance: a PreToolUse hook that
blocks reads of
.env*and friends (lesson 15). Advice for the 99% case, enforcement for the 1% — you'll meet this pairing throughout the course; this is its cleanest example.
Agents commit enthusiastically. The agent that just wired an
integration test may helpfully commit "everything needed to run it" —
including the scratch file with a live key. Defenses in depth:
.gitignore (passive), a secret-scanning pre-commit hook such as
gitleaks (active — and agents trip pre-commit hooks exactly like humans
do, which is the point), and reviewing agent commits with the same eye
you'd give a fast new contractor (lesson 6).
Agent platforms concentrate keys. An MCP configuration wiring five servers is five credentials in one file. Treat the config itself as a secret; prefer env-var references over inline strings where supported; and remember each server is code running with those credentials — trust accordingly (lessons 7, 26).
Spending keys need budgets, not vigilance
A model key is a spending credential attached to a process that issues requests faster than you can watch. Every runaway pattern in this course — the retry loop, the agent re-reading a huge file each turn (lesson 2), the scheduled job that never halts (lesson 17), the CI pipeline running on every push (lesson 28), the agent tree spawning agents (lesson 29) — is a small mistake multiplied at machine speed. Three controls, in order of importance:
- Hard caps at the provider. Anthropic and every serious provider support spend limits per key or workspace. Set them before the first autonomous run — a cap converts a runaway into an error message, which is the entire difference between an anecdote and an incident.
- Pre-flight refusal, not post-hoc reporting. The useful budget check happens before the request: estimate the cost (lesson 3 — calibrated, because an overestimating gate refuses work it could afford), compare to the declared budget, refuse if over. A report that arrives after the spend is an autopsy. Make refusal the default shape of every cost control you build; lessons 17, 28, and 29 all reuse this exact shape, and it composes — per-request, per-run, per-batch, per-tree.
- Alerts as backstop. Billing alerts at 50% and 80% of expected spend catch the failure modes you didn't foresee — which, by definition, are the ones your other controls missed.
One subtle sizing rule for budgets: set them from measured typical usage plus honest headroom, not from fear. A budget at 10x typical never fires and protects nothing; a budget at 1.05x typical fires weekly and trains you to ignore it. 2–3x typical is the zone where a trigger means something.
The incident you should rehearse
Someday a key leaks anyway — a screen share, a log aggregator, a paste. The response is mechanical, in strict order: revoke (immediately, before investigating — investigation with a live leaked key is investigation during an active breach), rotate (issue the replacement; update the one place each consumer reads it — which is where one-key-per-purpose pays: you know exactly which consumers), review (provider usage logs for the exposure window; billing anomalies; for non-model keys, audit what the key could touch), learn (which control was missing — the answer is almost always "shared purpose" or "excess scope").
Do a rehearsal once, deliberately, on a key that doesn't matter: revoke it, rotate it, confirm the consumer recovers. Rehearsed rotation takes four minutes. Unrehearsed rotation happens during an incident, at night, in a hurry — and hurried credential work is how one incident becomes two.
A personal teaching project, in development. The registry it builds is a teaching artifact and is not an assurance opinion about any issuer. Not affiliated with or endorsed by any employer, or by any vendor whose tools it describes. Where a unit depends on a specific flag or path, it names the version it was verified against. All units.