Turning an agent into an API is one of the most useful things a team can do. Suddenly the agent can be called from a backend service, a workflow tool, a spreadsheet script or another agent. It also means the agent has a front door, and API keys are the lock. Most key leaks are not dramatic hacks. They are keys pasted into a ticket, committed to a repository or shared between three services. Good design makes those mistakes cheap.
Principle 1: Make keys recognizable
Give keys a fixed prefix and a fixed length. A prefix such as bhk_ lets secret scanners in code hosts and CI tools spot a leaked key immediately, and it tells a person reading a log exactly what they are looking at. BeansHost keys are bhk_ followed by 32 characters.
Principle 2: Store only a hash
Treat keys like passwords. Show the full key once, at creation, and store only a hash such as SHA-256. If your database is ever exposed, the hashes cannot be used to call anything. The trade-off is intentional: a lost key is replaced, never recovered.
Principle 3: Scope by action
A key should allow only what its holder needs. For agents, two scopes cover most needs:
| Scope | Allows | Give it to |
|---|---|---|
| Invoke agents (agents:invoke) | Calling an agent's endpoint | Applications that use the agent |
| Report runs (executions:report) | Recording runs that happened elsewhere | The agent itself, when it is called directly |
Principle 4: Scope by resource
Action scopes say what a key can do. Resource limits say where. A key handed to a partner integration should call one agent, not every agent in your organization. In BeansHost, keys created from an agent's API panel are limited to that agent. Any call to a different agent answers 403 api_key_agent_mismatch before anything else is looked up. Keys created in Settings can cover an organization or a project when you need broader access.
Principle 5: Expire by default
A key that never expires is a key nobody remembers to rotate. Offer sensible defaults such as 30 days, 90 days or one year, and reserve keys with no expiry for cases with a clear owner and a rotation plan.
Principle 6: Rotate without downtime
- Create a new key with the same scope and limits.
- Deploy it to the calling application alongside the old one.
- Switch traffic to the new key and confirm calls succeed.
- Revoke the old key.
- Check the audit log to confirm the old key is no longer used.
Principle 7: Keep keys out of code
Read keys from the environment, never from source files. Every example the BeansHost console generates follows this rule, in curl, JavaScript and Python.
const response = await fetch(
`https://app.beanshost.com/api/v1/runtime/agents/${AGENT_ID}/invoke?environment=production`,
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.BEANSHOST_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ message: "Hello" }),
},
);
const result = await response.json();Principle 8: Never forward the caller's key
The gateway that checks the key should not pass it on to the agent. The agent does not need it, and every extra place a key travels is another place it can leak. BeansHost strips caller credentials before forwarding the request body to the agent.
Summary
- Recognizable prefix and fixed length.
- Shown once, stored as a hash.
- Scoped by action and by resource.
- Expiry by default, rotation as routine.
- Read from the environment, never forwarded downstream.
- Every key event recorded.
Read the full agent API reference for request formats and error codes, or see the wider security checklist for AI agents.



