n4nAI

How to secure API keys used by autonomous AI agents

Practical steps to secure API keys AI agents use: scoped tokens, gateway proxying, secret rotation, and isolation to block prompt-injection theft.

n4n Team3 min read706 words

Audio narration

Coming soon — every post will get a voice note here.

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.

Tagsapi-keysai-agent-securitycredentialssecurity

Written by

n4n Team

The team building n4n — a single OpenAI-compatible API in front of 240+ models, with automatic fallback, load balancing and pay-per-token metering.

More from n4n Team →

All ai agent security & prompt injection defense posts →