Autonomous agents that call LLM APIs routinely mishandle credentials. To secure API keys AI agents use, you must stop embedding provider secrets in agent code and instead broker access through scoped, revocable tokens and a hardened runtime. The following steps take you from a leaked-key disaster to a contained, auditable credential model.
Step 1: Inventory every credential the agent can reach
Before you can secure API keys AI agents use, you need a complete map. Agents rarely touch just one LLM key; they often hold Slack tokens, database URLs, and internal service accounts. Pull these from environment, config files, and container images.
Run a scan in your repo and deployment manifests:
# find potential secrets in code (use detect-secrets, not grep alone)
pip install detect-secrets
detect-secrets scan --all-files
Load expected vars in a bootstrap script to fail fast if missing:
import os
import sys
REQUIRED = ["LLM_GATEWAY_KEY", "VAULT_ADDR", "TOOL_API_TOKEN"]
missing = [k for k in REQUIRED if not os.environ.get(k)]
if missing:
sys.exit(f"Missing env vars: {missing}")
print("Credential surface mapped:", REQUIRED)
Verify success: The scan reports zero high-entropy strings in source, and the bootstrap script prints the mapped list without exiting.
Step 2: Proxy LLM access through a key-holding gateway
Never ship a raw OpenAI or Anthropic key to an agent container. Instead, point the agent at an inference gateway that stores provider secrets server-side. For example, n4n.ai exposes one OpenAI-compatible endpoint that addresses 240+ models, with automatic fallback when a provider is rate-limited and per-token usage metering. You issue a single gateway key with your own policy, and the gateway forwards cache-control hints and routing directives without exposing upstream credentials.
Configure the agent client:
from openai import OpenAI
import os
client = OpenAI(
base_url="https://api.n4n.ai/v1", # gateway OpenAI-compatible endpoint
api_key=os.environ["LLM_GATEWAY_KEY"], # scoped, gateway-only secret
)
resp = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "Summarize the log"}],
)
The agent never sees the underlying provider key. If the agent is compromised, you revoke one gateway key, not ten provider keys.
Verify success: The call returns a completion, and your gateway usage panel shows metered tokens for that key. Revoking the key in the gateway makes the next agent call return 401.
Step 3: Mint scoped, short-lived tokens for auxiliary tools
For non-LLM services (databases, internal APIs), use a dynamic secrets backend. HashiCorp Vault can issue tokens with TTLs of minutes. The agent requests a wrapped token at startup, uses it, and the token dies automatically.
import hvac
import os
client = hvac.Client(url=os.environ["VAULT_ADDR"])
client.token = os.environ["VAULT_TOKEN"]
# issue a short-lived token for the orders service
resp = client.auth.token.create(
policies=["orders-readonly"],
ttl="10m",
explicit_max_ttl="10m",
)
tool_token = resp["auth"]["client_token"]
# pass tool_token to the agent's tool client, not a static secret
Verify success: Use the token to call the service, then wait 11 minutes and retry—Vault returns 403. The static credential never existed in the agent environment.
Step 4: Enforce least privilege with an allowlist proxy
Even with a gateway key, an agent can call any model or tool the gateway permits. Put a local sidecar proxy in front of the gateway to enforce your own allowlist. This contains blast radius if the agent is prompt-injected into calling disallowed models. To secure API keys AI agents use, you now have two layers: gateway holds provider secrets, sidecar restricts model scope.
from flask import Flask, request, jsonify
import requests
import os
app = Flask(__name__)
ALLOWED_MODELS = {"gpt-4o-mini", "claude-3-haiku"}
UPSTREAM = "https://api.n4n.ai/v1"
@app.route("/v1/chat/completions", methods=["POST"])
def proxy():
body = request.json
if body.get("model") not in ALLOWED_MODELS:
return jsonify({"error": "model not allowed"}), 403
r = requests.post(f"{UPSTREAM}/chat/completions",
json=body, headers={"Authorization": request.headers.get("Authorization")})
return jsonify(r.json()), r.status_code
if __name__ == "__main__":
app.run(port=5000)
Run this sidecar and point the agent’s base_url to http://localhost:5000. The agent only ever talks to your proxy, which forwards to the gateway.
Verify success: A request with "model": "gpt-4" returns 403 from the sidecar; "model": "gpt-4o-mini" forwards and succeeds.
Step 5: Sandbox network egress
Prompt injection can make an agent POST its context—including any key it can read—to an attacker URL. Run the agent in a container with egress limited to the proxy and Vault.
docker network create isolated-net
docker run --rm \
--network isolated-net \
-e LLM_GATEWAY_KEY \
-e VAULT_ADDR \
my-agent:latest
Add a firewall rule or proxy on isolated-net that permits only localhost:5000 and your Vault address. No direct internet.
Verify success: Exec into the container and run curl https://evil.example.com—it hangs or fails. curl http://localhost:5000/v1/chat/completions works.
Step 6: Automate rotation and revocation
Static keys rot. Wire Vault rotation or gateway key rotation into a cron job. For the gateway key:
# rotate gateway key via gateway admin API (assume standard REST)
curl -X POST https://api.n4n.ai/admin/keys/rotate \
-H "Authorization: Bearer $GATEWAY_ADMIN_KEY" \
-d '{"key_id":"agent-prod"}'
Update the agent’s secret in your orchestrator immediately after. For Vault tokens, set short TTLs and rely on automatic expiry.
Verify success: The old agent key returns 401 after rotation; the new one works. Audit log shows the rotation event.
Step 7: Scan agent output for leakage
As a last line of defense, intercept agent final responses and tool inputs for credential patterns. A simple regex catches most leaks:
import re
KEY_PATTERNS = [
r"sk-[A-Za-z0-9]{20,}", # OpenAI-style
r"AKIA[0-9A-Z]{16}", # AWS
r"hvb\.[A-Za-z0-9]{20,}", # Vault
]
def scan(text):
for p in KEY_PATTERNS:
if re.search(p, text):
raise ValueError("Possible credential leak in agent output")
Run scan() on every agent message before it leaves the trust boundary.
Verify success: Feed the function a string containing sk-1234567890abcdefghijklmn and confirm it raises; a normal summary passes.
Closing checklist
You have now taken concrete steps to secure API keys AI agents use: mapped the surface, proxied LLM calls through a gateway that holds provider secrets, issued short-lived tool tokens, enforced allowlists, sandboxed egress, rotated keys, and added leakage detection. Treat credential handling as code, not config, and the agent’s compromise stays a contained incident instead of a full breach.