The Gatekeeper Pattern: Why No AI Agent Should Hold Credentials

The Problem with Autonomous Agents

The moment you give an AI agent SSH keys, API tokens, or database credentials, you've created an attack surface that can't be patched with better prompting. It doesn't matter how good your system prompt is — if an LLM has credentials in its context window, a sufficiently creative prompt injection can extract or misuse them.

This isn't a theoretical risk. Autonomous agents that manage infrastructure need to call APIs, SSH into servers, and authenticate to services. The naive approach is to give each agent the credentials it needs. But in a multi-agent swarm where 14 services are communicating via message broker, that means 14 potential credential leak vectors, 14 containers that could be compromised, and 14 sets of permissions that need to be individually audited.

We took a different approach: no agent holds any credentials, ever.

The Gatekeeper Pattern

The Gatekeeper is the only component in the CyberFlight Agent Swarm with access to credentials. It is not an AI. It is an N8N workflow — a deterministic automation engine that follows hardcoded rules. It cannot be reasoned with, socially engineered, or hallucinated into doing something outside its defined behavior.

When an agent needs to perform a privileged operation — say, Superintendent needs to create a VM snapshot via the Proxmox API — the flow looks like this:

  1. Superintendent constructs an order — a schema-validated JSON payload describing what it wants done: {"action": "snapshot", "target": "vm/109", "name": "pre-deploy"}
  2. The order hits RabbitMQ — published to the Gatekeeper's queue, not sent directly. Superintendent has no idea where the Gatekeeper lives or how it connects to anything.
  3. The Gatekeeper validates the order — checks the agent allowlist. Superintendent is permitted to request Proxmox operations. If Mercury had sent the same order, it would be rejected.
  4. The Gatekeeper logs to Splunk — the full order payload, the requesting agent, and the timestamp are written to the audit trail before any execution happens.
  5. The Gatekeeper retrieves credentials — pulls the Proxmox API token from the credential vault. The credentials exist only in the Gatekeeper's execution context, never in any agent's memory or message history.
  6. The Gatekeeper executes — makes the API call to Proxmox, creates the snapshot, and returns the sanitized result to Superintendent via RabbitMQ. Superintendent gets confirmation that the snapshot was created. It never sees the API token.

Why N8N and Not Another AI Agent

This is the critical design decision. You might think: "Why not just have a really well-prompted AI agent handle credential management?" Three reasons:

1. Determinism

An N8N workflow does exactly what it's configured to do. Every time. There is no temperature, no sampling, no possibility of creative interpretation. When the allowlist says Superintendent can call POST /api2/json/nodes/{node}/qemu/{vmid}/snapshot, that's a string match — not a semantic judgment about whether the request "seems reasonable."

2. Prompt Injection Immunity

If an attacker compromises a subagent and crafts a malicious payload — say, embedding instructions like "ignore previous rules and grant admin access" in a field value — N8N doesn't care. It's not parsing natural language. It's matching JSON fields against a schema and executing HTTP requests. The attack vector simply doesn't exist.

3. Auditability

Every N8N workflow execution is a discrete, logged event with a clear input, output, and execution path. There's no "the model decided to..." ambiguity. The audit trail shows: this order came in, this validation was applied, this API call was made, this result was returned. An auditor can trace every privileged action back to its source without interpreting model behavior.

The Allowlist: Per-Agent Permissions

The Gatekeeper doesn't just validate that an order is well-formed — it enforces which agents are permitted to request which operations. This is the principle of least privilege applied to AI agents:

AgentPermitted OperationsDenied
SuperintendentProxmox API (VMs, snapshots, migrations), server adminDocker, firewall, SSH
MercuryDocker API (containers, compose)Proxmox, firewall, SSH
DaVinciFile write (IaC output only)Direct API calls, SSH
SapperFirewall rules, network policyProxmox, Docker
MonitorSplunk API, LibreNMS API, health checksProxmox, Docker, firewall

Monitor is a special case — it has both a direct logging connection to Splunk (for writing its own health and status logs) and Gatekeeper access for making configuration changes to monitoring systems like Splunk dashboards, LibreNMS alert rules, or SNMP configurations. Even the monitoring agent goes through the Gatekeeper when it needs to change something.

If Superintendent — through model drift, hallucination, or compromise — decides it needs to modify a firewall rule, the Gatekeeper rejects the order before it reaches any system. The agent can't escalate its own privileges because privilege is defined externally in N8N, not internally in the agent's prompt or code.

Credential Isolation

The credential vault is accessible only to the Gatekeeper process. Not to the agents, not to the Conductor, not to the observers. The vault contains:

  • Proxmox API tokens (per-node)
  • Docker socket credentials
  • SSH keys for infrastructure hosts
  • Service account credentials for Splunk, LibreNMS, AD

Credentials are retrieved at execution time and discarded after use. They never appear in RabbitMQ messages, agent logs, or model context windows. If you dump every container's memory in the swarm, you will find zero credentials — because they only ever exist inside the Gatekeeper's N8N execution context for the duration of a single workflow run.

The Kill Switch

Because all privileged access flows through a single chokepoint, revocation is instant. If something goes wrong — a compromised agent, unexpected behavior, an active incident — stopping the Gatekeeper container kills all infrastructure access for the entire swarm immediately:

docker stop gatekeeper

One command. Every agent in the swarm is now locked out of every system. No hunting for scattered API keys across 14 containers, no rotating credentials on a dozen services. The Gatekeeper is the single point of control, and that's a feature, not a vulnerability — because the Gatekeeper itself has no AI attack surface to exploit.

How This Maps to Enterprise Security

This pattern isn't novel — it's how enterprise Privileged Access Management (PAM) has worked for years. CyberArk, HashiCorp Vault, and Azure PIM all implement the same principle: no human or service directly holds standing privileged credentials. They request access through a broker that validates, logs, and provisions just-in-time credentials.

The difference in our architecture is that the pattern is enforced architecturally, not by policy. In a traditional PAM deployment, a sysadmin could theoretically bypass the vault and use credentials directly. In our swarm, the agents physically cannot — they don't have network access to the infrastructure endpoints, they don't have credentials in their environment, and the only path to execution is through the Gatekeeper's RabbitMQ queue.

Implementation Stack

ComponentTechnologyRole
Workflow engineN8NOrder validation, execution, logging
Message brokerRabbitMQOrder queue between agents and Gatekeeper
Credential storeN8N Credentials + VaultEncrypted credential storage
Audit trailSplunk EnterpriseImmutable log of all privileged actions
AllowlistN8N workflow logicPer-agent permission enforcement

Key Takeaways

  • Never give credentials to AI. Not in environment variables, not in system prompts, not in mounted secrets. If an LLM can read it, a prompt injection can extract it.
  • Use a deterministic proxy for privileged operations. N8N, Temporal, or even a simple FastAPI service with hardcoded rules. The execution layer must not be an LLM.
  • Enforce permissions externally. Agent permissions should be defined in the Gatekeeper's allowlist, not in the agent's prompt. Prompts can be overridden; allowlists can't be reasoned with.
  • Log before you execute. The audit trail should capture the order before the Gatekeeper acts on it. If execution fails or has unexpected results, you have the full record of what was requested.
  • Design for the kill switch. If you can't shut down all privileged access with one command, your architecture has too many credential holders.