This episode covers secure agent deployment: choosing a cloud or edge target, managing secrets with external storage, setting up network policies and service authentication, and ensuring HTTPS and secure webhook endpoints in production.

In episode 11 you secured the inside of the agent: restricting tool access, storing API keys safely, and building an audit trail with policy enforcement. Now the problem shifts: the agent that used to live on a local machine must move to the cloud or edge, and there it becomes part of infrastructure that anyone could attack. Episode 12 takes you from "a correct agent" to "a correct agent that is also secure in production".
Here is the roadmap for this episode: choosing a cloud or edge deployment target, managing secrets with external storage, setting up network policies and service authentication, and then ensuring HTTPS and secure webhook endpoints.
Before arranging security, first decide where the agent lives. This choice determines the attack surface:
What matters is not which one is "most secure", but which one fits your workload. An agent holding patient data clearly must not be placed on someone else's edge device without strict sandboxing; a product recommendation agent is actually comfortable at the edge because latency is critical.
Whatever the target, one principle still applies: run the agent as a non-root user, inside a container that has no excessive privileges.
FROM node:22-alpine AS runtime
WORKDIR /app
COPY out ./out
COPY package.json bun.lock ./
RUN bun install --production
USER node
EXPOSE 3000
CMD ["bun", "run", "start"]With USER node, the agent process has no permission to write to system directories. If the container is compromised, the attacker does not immediately have root access to the host. Build and test the image locally first before pushing it to the registry with docker build -t agent-image ..
The lesson from episode 11: never put the actual secret values in code or in the image. Those values must come from the environment at runtime. But in production, putting everything in environment variables is also not enough — anyone who can open the container can read them.
Use external secrets storage and injection at deploy time:
external-secrets to synchronize secrets from a vault into the cluster.The template you commit to the repository only stores the variable names:
HERMES_AGENT_ID=agent-checkout
LLM_API_KEY=
DATABASE_URL=
WEBHOOK_SECRET=
OBSERVABILITY_TOKEN=When the container runs, the values are filled in by the orchestrator or init process. Rotation also becomes much easier: change the value in the vault, restart the agent, no code changes. For the secrets the agent uses to call LLM providers, also consider scoped keys — tokens that may only call one endpoint and have their own quota.
Warning
Never build secrets into the image, including as build args. The image can sit in the registry for months, and baked-in secrets will leak to anyone with access to the registry.
An agent in production must not be able to chat with everyone. Limit who can call it, and where it may go.
Network policies in Kubernetes govern the direction and destination of traffic. Example: the agent may only egress to port 443 (HTTPS) and is forbidden from reaching internal IPs:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: agent-egress
spec:
podSelector:
matchLabels:
app: hermes-agent
policyTypes: ["Egress"]
egress:
- to:
- ipBlock:
cidr: 0.0.0.0/0
except:
- 10.0.0.0/8
- 192.168.0.0/16
- 169.254.0.0/16
ports:
- port: 443
protocol: TCPThis also blocks SSRF: if the agent has a tool that fetches URLs, it cannot sneak into the metadata service (169.254.169.254) because link-local IPs are in the exception list.
Service authentication ensures the caller is genuinely authorized. Two common layers:
Never leave the agent openly exposed on the internal network just because "it is safe inside the VPC". One compromised container is enough to hit the whole cluster.
All traffic in and out of the agent must be encrypted. HTTPS is no longer optional; plain HTTP means anyone on the network can read the agent's conversation — including prompts that may contain user data.
Two things to pay attention to:
If you receive traffic from the internet, also use an origin allowlist and a body size limit to block suspicious requests before they reach the agent:
ingress:
tls:
enabled: true
rateLimit: 100
windowSeconds: 60
allowedOrigins:
- https://app.example.com
maxBodyBytes: 1048576Agents are often the receiving side of webhooks — for example, events from a payment gateway or CI. A webhook can be called by anyone who knows the URL, so you must prove the sender is genuine. The standard: an HMAC signature in the header, computed from the raw body and a shared secret.
import crypto from "node:crypto";
export function verifyWebhook(rawBody, signature, secret) {
const expected = crypto
.createHmac("sha256", secret)
.update(rawBody)
.digest("hex");
const a = Buffer.from(signature ?? "");
const b = Buffer.from(expected);
return a.length === b.length && crypto.timingSafeEqual(a, b);
}Important point: verification must be done on the raw body before JSON parsing, because parsing changes the string representation and the signature will no longer match. Use timingSafeEqual for the comparison — not plain === — so an attacker cannot guess the secret through a timing attack. Also make sure webhook events are idempotent: reprocessing the same event must not duplicate its effects.
Info
If your webhook provider sends many events, also store the eventId and reject duplicate events. This prevents double effects when the provider retries because of a timeout.
Episode 12 brought your agent out of the laptop and into real infrastructure. You chose between cloud and edge based on your needs, run the agent as a non-root user, moved secrets to external storage, restricted egress and callers with network policies and service authentication, enforced HTTPS, and protected the webhook endpoint with secure HMAC verification.
Key takeaways:
timingSafeEqual.In the next episode 13 we turn to the user side: User Authentication & Persona — multi-user scenarios, per-user agent behavior, persona and role-based access, and user data privacy. See you there!