Secrets, identity and who the agent really is
Every agent action happens as somebody. Getting that somebody right is the difference between an audit trail and a shrug.
In 60 seconds
Secrets, identity and who the agent really is
Every agent action happens as somebody. Getting that somebody right is the difference between an audit trail and a shrug.
Rule one: the model never sees a secret
- "Here is the API key: sk-... Use it to call the service."
- Secrets pasted into the system prompt.
- Environment variables the agent's code can read and print.
- One long-lived key shared by every agent.
- The model calls
send_invoice(id); the tool holds the key. - Secrets live in a vault, fetched by tool code at call time.
- Short-lived tokens, minted per run, expiring in minutes.
- A separate identity per agent, per environment.
Rule two: agents are identities, not accounts
| Question | Bad answer | Good answer |
|---|---|---|
| Who did this? | svc-ai-prod | agent:support-triage on behalf of user:4471 |
| What can it do? | Whatever the service account can | A scoped role listing exact permissions |
| How long? | Forever | 15 minutes, then re-issued |
| How do we stop it? | Rotate a shared key and break everything | Revoke one identity in one action |
| Which version acted? | Unknown | Recorded: agent version, model, prompt hash |
Rule three: every action carries the end user
A practical secrets checklist
- No secrets in prompts, ever. Grep your prompt templates for
key,token,passwordtoday. - No long-lived credentials in an agent's environment.
- One identity per agent per environment; never share across dev and prod.
- Short expiry, automatic rotation, one-click revocation.
- Secret scanning on model output and on logs, because logs leak too.
- An owner named for every credential the agent can use.
Watch and read more
Lab
A secret your model literally cannot leak, because it never sees it.
The problem
send_invoice(order_id) and the tool fetches a short-lived credential and makes the call. Then try to make the agent reveal the key.# BEFORE β the key is in the prompt, one injection from a query string
SYSTEM = f"You are an assistant. Use API key {API_KEY} to call the billing service."
# AFTER β the model names an action; the tool holds the credential
def send_invoice(order_id: str) -> str:
token = vault.issue("billing", ttl_seconds=300) # minted per call
return billing.post(f"/invoices/{order_id}", token=token)You are done when
Hard questions
Try to answer before you reveal. If you can answer these, you understood the lesson.
Q1An error message from the billing service includes the token. Where does it end up, and what do you change?Reveal
Q2Design the identity model for an agent acting for many users, so that one compromise does not expose everyone.Reveal
Questions people ask
What if a tool genuinely needs the user's own credentials?
Use delegated authorisation β OAuth-style β so the user grants a scoped token that your code holds and the model never reads. The model triggers the action; the token stays out of context.
Should agents have their own accounts in every system?
Yes, with the narrowest role that works. It costs a little setup and it is what makes your audit log answer questions instead of raising them.
How short should tokens be?
Shorter than a run. Minutes, not days. If a token outlives the task, a leak outlives the task too.
What about agents that need to act while nobody is logged in?
Then the agent's own identity is the actor, and its permissions must be scoped assuming no human will notice for hours. Overnight autonomy and broad permissions is the combination that produces morning surprises.
Lesson test
5 questions. Get 3 right (60%) to pass and complete this lesson.
Sign in with your phone number to take the test and save your progress