We build API Stronghold, so we use it. That sounds obvious, but it’s worth saying out loud: we run the same setup we recommend to customers.
Our primary AI agent is an OpenClaw instance. It runs in Telegram, monitors Reddit and HN for relevant discussions, manages our blog pipeline, and touches a half-dozen external APIs in a single session. It’s useful. It’s also a credential management problem we ignored for too long.
For months, those API keys lived in the config file. Then we started writing content about blast radius and attacker windows, and we had a slightly uncomfortable realization: we were describing our own setup.
What the Agent Setup Looks Like
OpenClaw runs in Docker, connected to Telegram via the bot API. It has a collection of skills, each making calls to external services:
- Anthropic API for all LLM inference
- Google Analytics (GA4) for blog performance reporting
- Reddit API for opportunity scanning in relevant subreddits
- HN Algolia API for Hacker News search (public, no key required)
- GitHub and Bitbucket for repo operations and commit automation
- Gemini API via the nano-banana-pro skill for blog header image generation
Before API Stronghold, the setup was straightforward in a bad way. Keys lived in openclaw.json or a .env file. They loaded at startup. From that point on, they were available in the agent’s environment for the entire session, however long that ran.
A typical interactive session runs four to six hours. During that window, the agent might scan Reddit, read a few HN threads, fetch a web page, and process several tool responses from external APIs. Any of those responses could contain a prompt injection. The attacker’s window, if they got one, was the full session with every key loaded.
We knew this theoretically. We kept meaning to fix it. It took writing a blog post about attacker windows to actually push us to act.
How We Use API Stronghold Now
The core change is where keys live and how they’re accessed.
Keys are stored in the API Stronghold vault with zero-knowledge encryption. They never touch the agent’s environment as plaintext. Instead, the agent gets a session token at startup via the proxy:
api-stronghold-cli proxy start --config agent-sessions.json
That command starts a local proxy and issues session tokens scoped to specific providers. The agent talks to the proxy; the proxy talks to the real API. The key never passes through the agent context.
We split the sessions by task type. This took some thought to get right.
The agent’s LLM calls go through a session scoped only to Anthropic. That session gets a TTL of eight hours, matching typical daily usage. When the Reddit scanning skill runs, it uses a separate session scoped to the Reddit API only. That session gets a shorter TTL, around two hours, since scans are batch jobs that complete and stop.
Analytics reporting uses its own session, scoped to the GA service account. Blog image generation has its own session for the Gemini API. GitHub operations get their own session too.
The config looks roughly like this:
{
"sessions": [
{
"name": "llm",
"provider": "anthropic",
"ttl": "8h"
},
{
"name": "analytics",
"provider": "google-service-account",
"ttl": "2h"
},
{
"name": "reddit",
"provider": "reddit",
"ttl": "2h"
},
{
"name": "image-gen",
"provider": "google-gemini",
"ttl": "1h"
}
]
}
When the agent is doing a Reddit scan, it holds a valid Reddit session token. It doesn’t have access to the Anthropic key for that task. If a subreddit post contains an injection, the attacker gets a phantom token valid for one provider, expiring in two hours. The blast radius is a single Reddit session, not the full environment.
What Changed After
The immediate win was simpler than we expected: we stopped treating “what if a tool response contains an injection” as a credential leak risk. It’s still a concern for other reasons, but credential theft through injection stopped being the scenario we lose sleep over.
A successful injection now yields a phantom token. That token is scoped to one provider, expires in hours, and gets logged. We’d know about it.
The audit trail surfaced something we didn’t anticipate. We could see per-session usage, which meant we could see exactly how many Anthropic calls the agent made during specific task types. Turns out the agent was making more inference calls than we realized during blog research sessions. Not alarming, but we wouldn’t have noticed without per-session analytics. We adjusted some prompts and brought it down.
Onboarding a new API key is one command now instead of editing config files and restarting the agent. That’s not a security win exactly, but it removed a friction point that caused us to delay adding keys properly.
What We’d Do Differently
We waited too long to split sessions per task type. We started with one broad session covering multiple providers, which was better than a .env file but still not right. Moving to per-provider sessions required some refactoring of how the agent initializes its skills at startup. Worth it, but easier to design that way from the start.
Sub-tokens would have helped earlier for the interactive Telegram sessions. The agent handles arbitrary user requests during those sessions, which means the task scope is unpredictable. Sub-tokens let you issue narrower tokens derived from a parent session, so you can give individual tool calls minimum-necessary access. That feature just shipped; we’re mid-migration now.
One tradeoff worth mentioning: the proxy adds a local hop to every API call. For LLM inference, the overhead is negligible, around 2ms per request. For tight loops or high-frequency API calls, that’s worth measuring. It hasn’t mattered for our workload, but we didn’t want to leave it unsaid.
If Your Keys Are in a Config File
You’re in the same position we were. The config file approach works until it doesn’t, and you usually find out at the worst time.
The setup takes about 15 minutes: install the CLI, move your keys to the vault, configure sessions per provider, update your startup script to use the proxy. The hard part is thinking through your session boundaries, which mostly means listing which skills need which keys and for how long.
If you want to try it: https://www.apistronghold.com. Free tier available.