What should you do when an AI agent's API key leaks?
Find the key by its name and scope. Revoke that one key. Prove the revocation by repeating a call the key could make and confirming it is refused. Issue a replacement with the same single scope. Write down what happened and who owns the new key.
A leaked key is how a ghost agent becomes an incident. The agent's builder may be gone. The key still works, and nobody is sure what it can reach. Speed matters, but proof matters more: "we revoked it" is a claim until the same call fails.
The five steps
| # | Step | Done when |
|---|---|---|
| 1 | Identify the key | You know its name and its scopes |
| 2 | Revoke that key | The revoke call returned success |
| 3 | Prove the refusal | A call that worked with the key is now refused |
| 4 | Replace it | A new key with the same single scope works for the integration |
| 5 | Record it | Owner, time, scope and reason are written down |
Rendering diagram…
1. Identify the key without exposing it again
In agent.ceo, organization API keys are listed by name and scope, never with their secret values. That is
what you want in an incident. You can see which key it is and what it can do without printing the secret
into another log. A key named after its integration, such as inventory-report, makes this step take
seconds.
2 and 3. Revoke, then prove it
The revoke is one call. The proof is the call that matters:
# Before revoking: this worked with the leaked key
curl -s -o /dev/null -w "%{http_code}\n" \
"https://api.agent.ceo/api/v1/customers/$ORG/agents" \
-H "X-API-Key: $LEAKED_KEY"
# expect 200
# After revoking: the same call must be refused
curl -s -o /dev/null -w "%{http_code}\n" \
"https://api.agent.ceo/api/v1/customers/$ORG/agents" \
-H "X-API-Key: $LEAKED_KEY"
# expect a 4xx refusal, never 200
If the second call still returns 200, the revocation did not take effect. Treat that as a new, more serious incident and escalate it. Do not close the first one.
This is the path we check on our own staging environment. A key is created with a single scope, used on its own to list agents, and shown in the key list without its value. After revoke, the same read is refused. Next to it, an invented key and the real key used against another organization must also be refused. Without those two, an endpoint that always answers 200 would make the refusal meaningless.
4. Replace with the same single scope
Issue a new key with only the scope the integration needs, and hand it to the integration through your secret store. Do not widen the scope "while you are at it". An incident is the worst moment to change what an integration is allowed to do.
5. Write it down
| Field | Example |
|---|---|
| Revoked key (name, scope) | inventory-report, read:agents |
| When revoked, when refusal proven | Two timestamps, not one |
| Replacement key (name, scope) | inventory-report-2, read:agents |
| Owner of the replacement | A named person or team |
| How it leaked | One sentence |
What makes a leak small
Most of the damage is decided before the leak. One key per integration and one scope per key turn a leak into a one-line revoke. One shared, powerful key turns it into an outage. The setup is in how to give an integration a scoped API key, and the key reference is in the API keys docs.
FAQ
What should you do first when an AI agent's API key leaks?
Revoke that one key, then prove the revocation: repeat a call the key could make and confirm it is refused. Revoking without that second call only tells you a button was pressed. Do the replacement and the write-up after the refusal is proven.
How do you limit the damage of a leaked AI agent key?
Before the leak, not after. Give each integration its own key with only the scope it needs. A leaked key that can only read agents exposes a list, not your whole organization, and revoking it breaks one integration instead of five.
Do you need to rotate every key after one leaks?
Not if each integration has its own key with one scope. Revoke the leaked key and replace it. If several integrations shared the leaked key, all of them lose access at once, which is the real reason to stop sharing keys.
Related: How to offboard an AI agent · API keys docs