<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Tigera Inc</title>
    <description>The latest articles on DEV Community by Tigera Inc (tigeraio).</description>
    <link>https://dev.to/tigeraio</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F12572%2Fe692e88e-7a1e-49d5-870b-930d459570c0.png</url>
      <title>DEV Community: Tigera Inc</title>
      <link>https://dev.to/tigeraio</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tigeraio"/>
    <language>en</language>
    <item>
      <title>HITL for autonomous agents: Where does the human go?</title>
      <dc:creator>Alister Baroi</dc:creator>
      <pubDate>Thu, 17 Sep 2026 00:49:44 +0000</pubDate>
      <link>https://dev.to/tigeraio/hitl-for-autonomous-agents-where-does-the-human-go-14n6</link>
      <guid>https://dev.to/tigeraio/hitl-for-autonomous-agents-where-does-the-human-go-14n6</guid>
      <description>&lt;p&gt;&lt;em&gt;Human approval is easy when you are sitting in front of the agent. For an agent running by itself in a cluster, almost none of that holds.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You’re in a meeting and your agent is running in a cluster. It has a service account, it has been asked to keep a service healthy, and it has just worked out that the right fix is to roll back a database migration. Nobody is watching it. That was rather the point of deploying it. You want to get notified to approve such an important action.&lt;/p&gt;

&lt;p&gt;This is a different problem from the one most people picture when they hear &lt;em&gt;human in the loop&lt;/em&gt;. If you use a coding assistant, you already have human oversight and it costs almost nothing: the agent shows you a diff, you read it, you approve. That works because you are already there — at a keyboard, with the context in front of you, in the same second the agent needs an answer.&lt;/p&gt;

&lt;p&gt;An autonomous agent has none of that. There is no session to interrupt. The person who should decide is asleep, or in a meeting, or on a plane. The approval has to travel out of the cluster, reach a phone, and come back. And the request has to survive however long that takes.&lt;/p&gt;

&lt;p&gt;Almost everything that is hard about human oversight for autonomous agents follows from those two sentences. So the useful question is not whether to have a human – MCP’s tools specification recommends keeping a person able to deny a tool call, and every agent security note I have read says some version of the same thing. The useful question is &lt;em&gt;where&lt;/em&gt; that human sits, and what happens to the request while it waits.&lt;/p&gt;

&lt;h2&gt;
  
  
  Four places to put the human
&lt;/h2&gt;

&lt;p&gt;Four different layers of the stack have each grown an answer, and they are not the same answer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;At the identity layer&lt;/strong&gt; , the agent asks an identity provider for permission. The provider reaches you out of band, and your approval mints a short-lived token scoped to that one action. This is &lt;a href="https://openid.net/specs/openid-client-initiated-backchannel-authentication-core-1_0.html" rel="noopener noreferrer"&gt;OpenID Connect’s CIBA&lt;/a&gt;, and it is the most mature of the four — Auth0, Okta and others have productized it, and Christian Posta has &lt;a href="https://blog.christianposta.com/ai-agents-and-oidc-ciba/" rel="noopener noreferrer"&gt;made the case&lt;/a&gt; for it as the natural home for agent oversight.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;At the protocol layer&lt;/strong&gt; , the tool server pauses and asks a question back through the client. MCP calls this elicitation and specifies it properly. It also assumes there is a client with a person attached to it, which puts us back at two in the morning.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;At the infrastructure layer&lt;/strong&gt; , a gateway in the request path holds the call, notifies someone, and then releases or refuses it. Nothing in the agent changes, because the agent never learns it was held.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;At the runtime layer&lt;/strong&gt; , the agent framework pauses itself and checkpoints. LangGraph’s &lt;code&gt;interrupt()&lt;/code&gt; and Temporal’s durable execution both work this way: the pause is saved state rather than a blocked thread, so it survives a crash or a deploy.&lt;/p&gt;

&lt;p&gt;These are not four implementations of one feature. CIBA answers &lt;em&gt;what authority does this action now carry&lt;/em&gt;. Elicitation answers &lt;em&gt;what does the user want to happen&lt;/em&gt;. A gateway hold answers &lt;em&gt;should this request proceed&lt;/em&gt;. A durable interrupt answers &lt;em&gt;how does the work survive the wait&lt;/em&gt;. We started out treating them as alternatives and had to stop.&lt;/p&gt;

&lt;h2&gt;
  
  
  The wait is the hard part
&lt;/h2&gt;

&lt;p&gt;A person takes minutes. A request does not.&lt;/p&gt;

&lt;p&gt;Hold the call open at a gateway and you get approval with no change to the agent at all — which is the whole reason to do it there — but you are now racing every timeout between the caller and you. Client timeouts, proxy idle timeouts, load balancer limits. You can raise them, but you raise them for all traffic, not just the held kind. Two minutes is generous by network standards and insulting by human ones.&lt;/p&gt;

&lt;p&gt;Return immediately instead, mark the call pending, and let the caller poll. TrueFoundry &lt;a href="https://www.truefoundry.com/blog/mcp-tool-approval-human-gate-call-path" rel="noopener noreferrer"&gt;describe this shape&lt;/a&gt; well and are honest about the cost: the client has to understand the convention and decide when to retry. That is a change to every agent you were trying to leave alone.&lt;/p&gt;

&lt;p&gt;Or push the pause into the runtime, where LangGraph and Temporal have already solved it properly. The wait is checkpointed, it survives a restart, and holding for an hour costs nothing. It also requires that you own the agent’s runtime, which rules out the third-party agent and the one you did not write.&lt;/p&gt;

&lt;p&gt;Each design pays one of those three prices. We pay the first.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does an approval prove?
&lt;/h2&gt;

&lt;p&gt;When the log says the action was approved, what has actually been established?&lt;/p&gt;

&lt;p&gt;In the strong version: this named person, authenticated at this strength, saw this specific request with these specific arguments, and decided at this time. In the weak version: a push went somewhere and something came back green.&lt;/p&gt;

&lt;p&gt;In our case it was the notification channel that opened the gap between the two. We integrated Cisco Duo as an approval backend, because it is already deployed at the kind of enterprise we work with and the push-to-phone experience is exactly right for the two-in-the-morning case. But Duo’s status response tells us the transaction was approved. It does not tell us who approved it, or on what device. So the approver we can record is the one we were configured to ask, not the one who actually tapped. Our first-party path, where someone answers through an authenticated session, can name the individual. The Duo path cannot.&lt;/p&gt;

&lt;p&gt;That is not a complaint about Duo, which is doing exactly what a second-factor product is designed to do. It is a warning about reading approval logs — and it is the strongest argument for the CIBA model, where the approver’s identity travels inside the token rather than sitting in a log line beside it.&lt;/p&gt;

&lt;p&gt;If you are choosing a design, ask what it can prove, not what it can block. Blocking is the easy half.&lt;/p&gt;

&lt;h2&gt;
  
  
  Approval should not create permission
&lt;/h2&gt;

&lt;p&gt;There is a design fork here, and we came down firmly on one side of it.&lt;/p&gt;

&lt;p&gt;When the human says yes, does that &lt;em&gt;create&lt;/em&gt; permission, or does it &lt;em&gt;satisfy a condition&lt;/em&gt; in permission that already existed? CIBA takes the first path by construction: the approval mints a token, and the token is new authority. That is clean and portable, and it also means a leaked token is authority in someone else’s hands until its window closes.&lt;/p&gt;

&lt;p&gt;We took the second path. In Lynx a gate is an ordinary Cedar &lt;code&gt;forbid&lt;/code&gt; rule with an annotation and a condition attached:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rego"&gt;&lt;code&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;approvalRequired&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Approve transfer_funds on treasury"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;forbid&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;principal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;unless&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;approval&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;granted&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The annotation marks the rule as worth holding and carries the prompt the person reads. The &lt;code&gt;unless&lt;/code&gt; clause is what an approval satisfies. Both halves are required, and our linter rejects one without the other.&lt;/p&gt;

&lt;p&gt;The consequence is the part I care about: the gateway never turns a deny into an allow. If the agent was not permitted to reach that server in the first place, no amount of approval gets it there, and the request is refused immediately rather than paging someone at 2am to rubber-stamp something that was never going to work. Approval is one input to a decision still made by policy. It is not a manual override, and I would not be comfortable shipping one that was.&lt;/p&gt;

&lt;h2&gt;
  
  
  The person holding the phone
&lt;/h2&gt;

&lt;p&gt;Once a human is in the path, that human is a target, and the attacks are all about what the notification says. Most of what appears on an approval screen is influenced by someone else: the tool name comes from a server that may be compromised, the arguments come from a model that may have been steered by a retrieved document, and MCP annotations are explicitly hints rather than facts. Render all of that as one undifferentiated block and you are asking a half-awake person to spot a lie on a small screen. So we treat the rendering as a security control — authenticated caller identity first, written from what the gateway verified; caller-supplied arguments namespaced under an &lt;code&gt;arg.&lt;/code&gt; prefix so nothing can pose as provenance; text flattened and truncated. None of it is clever. The alternative is a phishing surface with a corporate logo on it.&lt;/p&gt;

&lt;p&gt;The quieter failure is fatigue. If the answer is always yes, the gate has stopped being judgment and become latency with an audit trail. Every change that reduces the number of prompts — batching, scoping, remembering a decision for a window — is also a change that puts fewer requests in front of a person. I do not think there is a way out of that tension, only a way to be deliberate about where you sit in it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where we have got to
&lt;/h2&gt;

&lt;p&gt;We build on &lt;a href="https://agentgateway.dev" rel="noopener noreferrer"&gt;agentgateway&lt;/a&gt; as our data plane, and Solo’s enterprise build already ships human approval with notifications out to Slack, email and mobile. This is not new ground, so I would rather say what we learned than claim novelty.&lt;/p&gt;

&lt;p&gt;We hold at the gateway, gated by Cedar, so that an agent nobody wants to modify can still be governed. We drive Duo’s asynchronous push for the out-of-band decision. That is deliberately &lt;em&gt;not&lt;/em&gt; CIBA — Duo has no backchannel authorization endpoint and no CIBA grant — but the shape is the same: client-initiated, decoupled device, poll for a decision. We built the seam to that shape so a real CIBA backend can sit behind it later without the policy surface changing. Since MCP’s specification declines to standardize an approval workflow, borrowing the shape of the standard next door seemed better than inventing a fifth one.&lt;/p&gt;

&lt;p&gt;What we have not solved: the hold is synchronous, so it carries the timeout cost above. There is a single global approver, where the problem wants routing by resource and by policy. It covers MCP tool calls and not yet the other paths an agent can take. And the trail does not yet surface the way it needs to for someone reconstructing an incident months later.&lt;/p&gt;

&lt;p&gt;I am writing this before those are fixed rather than after, because the feature is not the interesting part. The interesting part is that an identity specification, a protocol specification, a set of gateways and a set of agent frameworks all produce something different when a human says yes, and none of them drops into the place of another. That is worth working out now, while the designs are still soft enough to change.&lt;/p&gt;

&lt;p&gt;Agents will keep asking for permission to do consequential things while nobody is looking. We should be more precise about what we mean when we say a human approved it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.tigera.io/tigera-products/lynx/" rel="noopener noreferrer"&gt;Learn more about Lynx →&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Further reading: &lt;a href="https://openid.net/specs/openid-client-initiated-backchannel-authentication-core-1_0.html" rel="noopener noreferrer"&gt;the OpenID CIBA specification&lt;/a&gt;; Christian Posta on &lt;a href="https://blog.christianposta.com/ai-agents-and-oidc-ciba/" rel="noopener noreferrer"&gt;agent autonomy and CIBA; Auth0’s asynchronous authorization&lt;/a&gt; for agents; TrueFoundry on &lt;a href="https://www.truefoundry.com/blog/mcp-tool-approval-human-gate-call-path" rel="noopener noreferrer"&gt;tool approvals at the gateway boundary&lt;/a&gt;; &lt;a href="https://docs.langchain.com/oss/python/langgraph/durable-execution" rel="noopener noreferrer"&gt;LangGraph durable execution&lt;/a&gt; and &lt;a href="https://temporal.io/blog/temporal-langgraph-plugin-durable-execution" rel="noopener noreferrer"&gt;Temporal’s LangGraph plugin&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://www.tigera.io/blog/hitl-for-autonomous-agents-where-does-the-human-go/" rel="noopener noreferrer"&gt;HITL for autonomous agents: Where does the human go?&lt;/a&gt; appeared first on &lt;a href="https://www.tigera.io" rel="noopener noreferrer"&gt;Tigera – Creator of Calico&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>technicalblog</category>
      <category>aiagentsecurity</category>
    </item>
    <item>
      <title>AI Agents on Kubernetes 101: From Laptop Script to Production Pod</title>
      <dc:creator>Alister Baroi</dc:creator>
      <pubDate>Tue, 08 Sep 2026 20:16:27 +0000</pubDate>
      <link>https://dev.to/tigeraio/ai-agents-on-kubernetes-101-from-laptop-script-to-production-pod-4jj4</link>
      <guid>https://dev.to/tigeraio/ai-agents-on-kubernetes-101-from-laptop-script-to-production-pod-4jj4</guid>
      <description>&lt;p&gt;In short, this is a beginner’s guide to deploying an AI agent on Kubernetes. You will containerize an agent, store its API key as a Kubernetes secret, write a deployment with health probes and resource limits, expose it with a service, and lock down its network egress, in that order, with a working manifest at every step. On a local kind cluster the whole walkthrough takes about an hour. At the end: the six mistakes almost every first agent deployment makes, and the questions a 101 deployment leaves open.&lt;/p&gt;

&lt;p&gt;Every AI agent starts life the same way; a Python script on someone’s laptop, an API key in a &lt;code&gt;.env&lt;/code&gt; file, a &lt;code&gt;while&lt;/code&gt; loop around an LLM call. It works, it demos well. Then someone with a budget says “ship it,” and you, the engineer closest to the script, get to figure out what shipping an agent actually means.&lt;/p&gt;

&lt;p&gt;This guide is that path, walked slowly. It assumes you know what a container is and have met &lt;code&gt;kubectl a&lt;/code&gt;t least once, and it assumes nothing about agents. By the end you will have an agent running in a cluster with its key in a Secret, its resource usage capped, its health checked, and its network access reduced to the short list of places it has any business calling. That is still short of production-grade governance, but it is a deployment you could defend in a code review, which is more than most agents get.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why is Kubernetes a good place to run AI agents?
&lt;/h2&gt;

&lt;p&gt;The short answer is, because an AI agent is a workload that needs supervision, and Kubernetes is the most widely used system for supervising workloads. It restarts the agent when it crashes, caps how much CPU and memory it can consume, injects its credentials (e.g. API keys) at runtime instead of baking them into the code, and describes all of it in version-controlled YAML manifest your team can review. Just as important, Kubernetes gives you control over the agent’s environment, such as, what it can reach on the network, what identity it carries, what happens when it misbehaves. That matters more for agents than for ordinary services, because an agent’s behavior is decided at runtime by a model, so the rules have to live outside the agent, where no prompt can talk its way past them. That argument deserves more than a paragraph, so we gave it a full post: &lt;a href="https://www.tigera.io/blog/the-safest-place-to-run-an-ai-agent-is-on-a-cluster-that-doesnt-trust-it/" rel="noopener noreferrer"&gt;The Safest Place to Run an AI Agent Is a Cluster That Doesn’t Trust It&lt;/a&gt; makes the case with a year of real incidents as evidence.&lt;/p&gt;

&lt;h2&gt;
  
  
  How is deploying an agent different from deploying a web service?
&lt;/h2&gt;

&lt;p&gt;Mechanically, it barely is. An agent is a long-running process that speaks HTTP; Kubernetes has been running those for a decade. The difference is in what the workload does with its freedom:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A web service follows its code.&lt;/strong&gt; An agent follows a model. You can read a service’s code and know its behavior. An agent’s next action depends on whatever lands in its context window.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;An agent holds credentials and acts.&lt;/strong&gt; It calls APIs, queries databases, sends messages. A wrong answer is a bug; a wrong &lt;em&gt;action&lt;/em&gt; is an incident.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Every input is potentially an instruction.&lt;/strong&gt; Prompt injection is unsolved. Text the agent reads, from a user, a document, or another agent, can try to redirect it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So the deployment steps below are the same ones you would use for any service. The difference is emphasis: the steps most tutorials treat as optional hardening (secrets, limits, egress control) are, for agents, the point.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you need before you start
&lt;/h2&gt;

&lt;p&gt;Four things, all free:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;A cluster&lt;/strong&gt;. Locally, &lt;a href="https://kind.sigs.k8s.io/" rel="noopener noreferrer"&gt;kind&lt;/a&gt; runs Kubernetes inside Docker: &lt;code&gt;kind create cluster --name agents&lt;/code&gt;. Any managed cluster (EKS, GKE, AKS) works the same way.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;kubectl and Docker&lt;/strong&gt; , installed and talking to that cluster.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;An agent that speaks HTTP&lt;/strong&gt;. Any framework is fine. LangGraph, CrewAI, Google ADK, etc all wrap into a web server; we compared them in &lt;a href="https://www.tigera.io/blog/six-ai-agent-sdks-for-enterprise-kubernetes-compared/" rel="noopener noreferrer"&gt;Six AI Agent SDKs for Enterprise Kubernetes&lt;/a&gt;. The walkthrough uses a generic Python agent served by FastAPI on port 8080, with two routes: &lt;code&gt;POST /chat&lt;/code&gt; for work and &lt;code&gt;GET /healthz&lt;/code&gt; that returns 200 when the process is up. If your agent lacks a health route, add one first. It is five lines, and step 4 depends on it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;An LLM API key.&lt;/strong&gt; From whichever provider your agent calls.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;One namespace keeps the experiment contained:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl create namespace agents
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 1: Containerize the agent
&lt;/h2&gt;

&lt;p&gt;Kubernetes runs containers, so the script becomes an image. A minimal Dockerfile for a Python agent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; python:3.12-slim&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; requirements.txt .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--no-cache-dir&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;
&lt;span class="k"&gt;USER&lt;/span&gt;&lt;span class="s"&gt; 1000&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 8080&lt;/span&gt;
&lt;span class="c"&gt;# change the command (to run agent) according to its framework documentation&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8080"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two lines here are security decisions. &lt;code&gt;USER 1000&lt;/code&gt; runs the agent as a non-root user, so a compromised agent is not root inside its container. And notice what is &lt;em&gt;absent&lt;/em&gt;: no API key. The key never enters the image. An image is copied to registries, cached on nodes, and pulled by anyone with access; a key baked into an image is a key you have already leaked, you just don’t know to whom yet.&lt;/p&gt;

&lt;p&gt;Build it and, for kind, load it into the cluster:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nt"&gt;-t&lt;/span&gt; support-agent:0.1.0 &lt;span class="nb"&gt;.&lt;/span&gt;
kind load docker-image support-agent:0.1.0 &lt;span class="nt"&gt;--name&lt;/span&gt; agents
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On a real cluster you would push to a registry instead. Either way, tag with a version (e.g., &lt;code&gt;0.1.0&lt;/code&gt;), never &lt;code&gt;latest&lt;/code&gt;. You want to be able to say exactly what is running, and roll back to exactly what was running before.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Put the API key in a Secret
&lt;/h2&gt;

&lt;p&gt;The&lt;code&gt;.env&lt;/code&gt; file’s job is taken over by a Kubernetes Secret:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; agents create secret generic support-agent-secrets 
  &lt;span class="nt"&gt;--from-literal&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;ANTHROPIC_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'sk-ant-...'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Secret lives in the cluster, is delivered to the pod as an environment variable at start time, and can be rotated without rebuilding the image. Two honest caveats for later: Secrets are base64-encoded, not encrypted, so real clusters enable encryption at rest and restrict who can read them with RBAC; and the agent’s own process can still read this variable, which matters once you worry about prompt injection. Hold that thought for the end of the article.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Write the Deployment
&lt;/h2&gt;

&lt;p&gt;The Deployment is the contract: which image, how many copies, what resources, what health checks. Save this as &lt;code&gt;deployment.yaml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;support-agent&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;agents&lt;/span&gt;
  &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;support-agent&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;support-agent&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;support-agent&lt;/span&gt;
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;automountServiceAccountToken&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
      &lt;span class="na"&gt;securityContext&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;runAsNonRoot&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;agent&lt;/span&gt;
          &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;support-agent:0.1.0&lt;/span&gt;
          &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
          &lt;span class="na"&gt;envFrom&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;secretRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;support-agent-secrets&lt;/span&gt;
          &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;100m&lt;/span&gt;
              &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;256Mi&lt;/span&gt;
            &lt;span class="na"&gt;limits&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1"&lt;/span&gt;
              &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;512Mi&lt;/span&gt;
          &lt;span class="na"&gt;readinessProbe&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;httpGet&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/healthz&lt;/span&gt;
              &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
            &lt;span class="na"&gt;initialDelaySeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;
            &lt;span class="na"&gt;periodSeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;
          &lt;span class="na"&gt;livenessProbe&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;httpGet&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/healthz&lt;/span&gt;
              &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
            &lt;span class="na"&gt;initialDelaySeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;15&lt;/span&gt;
            &lt;span class="na"&gt;periodSeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;
          &lt;span class="na"&gt;securityContext&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;allowPrivilegeEscalation&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
            &lt;span class="na"&gt;capabilities&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;drop&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ALL"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Apply it with &lt;code&gt;kubectl apply -f deployment.yaml&lt;/code&gt;, then read it back top to bottom, because every block answers a question a reviewer will ask:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;automountServiceAccountToken: false&lt;/code&gt;:&lt;/strong&gt; By default every pod gets a token for the Kubernetes API mounted into its filesystem. Your agent doesn’t need to talk to the Kubernetes API, so it doesn’t get the token. For an agent this is not a nicety. It is the difference between “prompt injection stole a chat log” and “prompt injection got a foothold in my cluster’s control plane.”&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;resources&lt;/strong&gt; : Requests are what the scheduler reserves; limits are the ceiling. Agents fail in loops. A model that decides to retry forever, or to summarize a document by reading it into memory in one piece, will eat a node if you let it. Limits turn “the cluster is down” into “one pod got throttled.”&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;readinessProbe&lt;/code&gt; and &lt;code&gt;livenessProbe&lt;/code&gt;&lt;/strong&gt; : Readiness controls whether traffic is sent to the pod; liveness restarts it when the process wedges. Without them, Kubernetes considers a hung agent healthy forever.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;envFrom.secretRef&lt;/code&gt;&lt;/strong&gt; : The key from step 2 arrives as an environment variable. Code reads &lt;code&gt;ANTHROPIC_API_KEY&lt;/code&gt; exactly as it did from the &lt;code&gt;.env&lt;/code&gt; file. Nothing about the agent’s code had to change.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Check it comes up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; agents get pods
kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; agents logs deploy/support-agent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4: Expose it with a Service
&lt;/h2&gt;

&lt;p&gt;Pods are ephemeral and their IPs change. A Service gives the agent a stable name:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Service&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;support-agent&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;agents&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;support-agent&lt;/span&gt;
  &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
      &lt;span class="na"&gt;targetPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now anything inside the cluster can reach the agent at &lt;code&gt;http://support-agent.agents.svc&lt;/code&gt;. From your laptop, test through a port-forward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; agents port-forward svc/support-agent 8080:80
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST localhost:8080/chat &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; 
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"message": "hello"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you get an answer, you have an AI agent running on Kubernetes. Most tutorials stop here. Do not stop here.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Close the doors it doesn’t need
&lt;/h2&gt;

&lt;p&gt;Right now your agent can open a connection to anything: every pod in the cluster, every address on the internet. For a web service that is untidy. For an agent it is the whole attack surface, because the standard end of a prompt-injection chain is exfiltration: the agent is talked into sending data somewhere it should never call. A NetworkPolicy makes egress deny by default:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;networking.k8s.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;NetworkPolicy&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;support-agent-egress&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;agents&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;podSelector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;support-agent&lt;/span&gt;
  &lt;span class="na"&gt;policyTypes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Egress"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;egress&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;namespaceSelector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{}&lt;/span&gt;
      &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;UDP&lt;/span&gt;
          &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;53&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TCP&lt;/span&gt;
          &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;53&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TCP&lt;/span&gt;
          &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;443&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows DNS lookups plus outbound HTTPS, and nothing else; a connection to another pod, or plaintext HTTP to anywhere, now fails at the network layer (Note for kind users: enforcing NetworkPolicy requires a network plugin that implements it, such as &lt;a href="https://docs.tigera.io/calico/latest/getting-started/kubernetes/kind" rel="noopener noreferrer"&gt;Calico&lt;/a&gt;; the kind default does not).&lt;/p&gt;

&lt;p&gt;The policy still has one hole, and it is an instructive one: “TCP 443 to anywhere” lets the agent reach any HTTPS endpoint on the internet, including an attacker’s. Vanilla NetworkPolicy speaks IPs and ports; it cannot say “only &lt;code&gt;api.anthropic.com&lt;/code&gt;.” Narrowing egress to named destinations takes either a DNS-aware policy engine (Calico can do this) or, better for agents, an egress gateway that all agent traffic must pass through. Remember this gap. It is where 101 ends and the last section of this article begins.&lt;/p&gt;

&lt;h2&gt;
  
  
  The six mistakes every first agent deployment makes
&lt;/h2&gt;

&lt;p&gt;The walkthrough above quietly avoided all six. Here they are in the open, because you will meet them in other people’s manifests:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Mistake&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Why it hurts an agent especially&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Instead&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;API key baked into the image&lt;/td&gt;
&lt;td&gt;Images get pulled, cached, and shared; the agent’s key is its power&lt;/td&gt;
&lt;td&gt;Kubernetes Secret, injected at runtime&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No resource limits&lt;/td&gt;
&lt;td&gt;Agents fail in loops; one runaway loop starves the node&lt;/td&gt;
&lt;td&gt;Set &lt;code&gt;requests&lt;/code&gt; and &lt;code&gt;limits&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;latest&lt;/code&gt; image tag&lt;/td&gt;
&lt;td&gt;You cannot say which agent behavior is running, or roll back&lt;/td&gt;
&lt;td&gt;Version tags, ideally digests&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No health probes&lt;/td&gt;
&lt;td&gt;A wedged agent looks healthy and keeps receiving work&lt;/td&gt;
&lt;td&gt;&lt;code&gt;readinessProbe + livenessProbe&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Default ServiceAccount token mounted&lt;/td&gt;
&lt;td&gt;Injected agent inherits a path to the Kubernetes API&lt;/td&gt;
&lt;td&gt;&lt;code&gt;automountServiceAccountToken: false&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Unrestricted egress&lt;/td&gt;
&lt;td&gt;Prompt injection ends in exfiltration over open egress&lt;/td&gt;
&lt;td&gt;Default-deny NetworkPolicy, then allowlist&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Read the middle column again. None of these is an exotic agent problem; they are ordinary Kubernetes hygiene. Agents just raise the price of skipping them.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a 101 deployment still can’t answer
&lt;/h2&gt;

&lt;p&gt;You now have one agent, contained and supervised. Before you call it production, try to answer three questions about it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Who is this agent?&lt;/strong&gt; Your cluster knows it as a pod with a label. Nothing cryptographically distinguishes it from any other workload, so nothing downstream can grant it permissions &lt;em&gt;as an agent&lt;/em&gt;, or refuse an impostor.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What exactly is it allowed to do?&lt;/strong&gt; Your NetworkPolicy says “HTTPS, somewhere.” It cannot see that the agent is calling an MCP tool, or with what arguments. “May this agent call &lt;code&gt;delete_records&lt;/code&gt; on the billing server” is not a question any layer you have deployed can even parse. We walked through why the stock building blocks stop short in the &lt;a href="https://www.tigera.io/blog/the-ai-agent-accountability-gap-why-network-policies-api-gateways-and-rbac-are-not-enough/" rel="noopener noreferrer"&gt;accountability gap post&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What did it do last Tuesday?&lt;/strong&gt; You have pod logs, written by the agent itself. An agent’s own narration is not an audit trail; the best-documented case of an agent deleting a production database came with the agent confidently reporting that rollback was impossible. It was not.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And this is with one agent. The moment there are two, they start talking to each other (that is the&lt;a href="https://www.tigera.io/blog/how-ai-agents-communicate-understanding-the-a2a-protocol-for-kubernetes/" rel="noopener noreferrer"&gt;A2A protocol&lt;/a&gt;), and the questions multiply by every pair.&lt;/p&gt;

&lt;p&gt;That missing layer (identity, per-request authorization, and audit across a fleet of agents) is what &lt;a href="https://www.tigera.io/blog/why-we-built-lynx-bringing-control-to-the-age-of-ai-agents/" rel="noopener noreferrer"&gt;Tigera Lynx&lt;/a&gt; adds on top of exactly the deployment you just built. Lynx gives every agent a SPIFFE or OIDC workload identity, routes agent-to-agent, MCP, and LLM traffic through a gateway that authorizes each request under Cedar policy, and records every hop in an Agent Trail the agent cannot edit. Recent releases sharpened the credential story from this post’s step 2: provider keys attach at the gateway instead of living in the pod’s environment, per-hop tokens are minted with an audience of one target so a stolen token is nearly worthless, and an OAuth authorization-code flow can issue per-user credentials. Policies can require human approval before a risky MCP call proceeds. On the node, an eBPF detector spots agents nobody registered and can quarantine a compromised one down to blocking its network writes at the kernel, and a policy playground in the UI lets you test a Cedar policy against simulated requests before it ever gates real traffic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently asked questions
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Do I need a GPU to deploy an AI agent on Kubernetes?&lt;/strong&gt; No. An agent is orchestration code that calls a model over an API; the GPUs live with the model provider. You only need GPU nodes if you self-host the model itself, which is a separate project.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Is Kubernetes overkill for a single agent?&lt;/strong&gt; For a weekend experiment, yes; run it locally. But the reasons to move to Kubernetes (restarts, secrets, resource caps, network control) show up the first time the agent touches real credentials or real users, which happens earlier than most teams expect.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Can I do all of this on my laptop?&lt;/strong&gt; Yes. Everything above runs on a kind cluster in Docker, including the NetworkPolicy if you install a plugin like Calico that enforces it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Which agent framework works best on Kubernetes?&lt;/strong&gt; Any framework that can serve HTTP deploys the same way. The differences show up in observability, state handling, and protocol support; our &lt;a href="https://www.tigera.io/blog/six-ai-agent-sdks-for-enterprise-kubernetes-compared/" rel="noopener noreferrer"&gt;six-SDK comparison&lt;/a&gt; covers them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How do I scale an agent to more replicas?&lt;/strong&gt; Set &lt;code&gt;replicas: 3&lt;/code&gt; and Kubernetes load-balances across them, but only if the agent keeps its conversation state outside the pod (a database or cache), since any replica may serve the next request. Stateless agents scale for free; stateful ones need that refactor first.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How is deploying an agent different from deploying a model?&lt;/strong&gt; A model deployment serves inference (weights on GPUs behind an endpoint). An agent deployment runs the loop that calls models and tools to pursue a goal. This guide covers the agent; most teams consume the model as a managed API.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Ship the pod, then ask the harder question
&lt;/h2&gt;

&lt;p&gt;Back to that laptop script. The distance from &lt;code&gt;.env&lt;/code&gt; file to the deployment in this article is five manifests and an afternoon, and every step was ordinary Kubernetes, applied with an agent’s failure modes in mind. That is the good news: you do not need new infrastructure to give an agent a safer home than a laptop. You need the infrastructure you already have, used deliberately.&lt;/p&gt;

&lt;p&gt;The harder question arrives with agent number two: when they start acting on each other’s behalf, who is checking identity at the door, and where is the record? Deploying the agent was the easy 101. Trusting it is a course Kubernetes alone does not teach.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Lynx is Tigera’s security and governance platform for AI agents on Kubernetes: identity, policy, detection, and audit for every agent in your cluster. Read &lt;a href="https://www.tigera.io/blog/how-lynx-works-a-technical-walkthrough/" rel="noopener noreferrer"&gt;How Lynx Works&lt;/a&gt; or request early access at &lt;a href="https://www.tigera.io/demo/?product=lynx" rel="noopener noreferrer"&gt;tigera.io/demo/&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.tigera.io/tigera-products/lynx/" rel="noopener noreferrer"&gt;Learn more about Lynx →&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://www.tigera.io/blog/ai-agents-on-kubernetes-101-from-laptop-script-to-production-pod/" rel="noopener noreferrer"&gt;AI Agents on Kubernetes 101: From Laptop Script to Production Pod&lt;/a&gt; appeared first on &lt;a href="https://www.tigera.io" rel="noopener noreferrer"&gt;Tigera – Creator of Calico&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>technicalblog</category>
      <category>aiagentsecurity</category>
    </item>
    <item>
      <title>Meet Mylo: An AI-native way to work with Calico</title>
      <dc:creator>Alister Baroi</dc:creator>
      <pubDate>Thu, 03 Sep 2026 18:21:50 +0000</pubDate>
      <link>https://dev.to/tigeraio/meet-mylo-an-ai-native-way-to-work-with-calico-2i53</link>
      <guid>https://dev.to/tigeraio/meet-mylo-an-ai-native-way-to-work-with-calico-2i53</guid>
      <description>&lt;p&gt;&lt;em&gt;A library of Calico tools and skills — delivered through the Calico MCP Server&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What if your hardest network question took ten minutes instead of ten days?
&lt;/h2&gt;

&lt;p&gt;Anyone who has operated Kubernetes networking at scale knows the shape of a bad day. A request that should succeed is quietly failing. The application team swears nothing changed. Somewhere across a stack of tiers, selectors, and policies, some written last week and some inherited from an engineer who left two years ago, a rule is denying the traffic. Finding it means reading YAML, cross-referencing flow logs, and reconstructing the policy evaluation order in your head. For a genuinely knotty case, that work can stretch across days and pull in more than one team before anyone gets to the bottom of it.&lt;/p&gt;

&lt;p&gt;I think that day is about to get a lot shorter. Today we’re introducing Mylo, an expert for Calico that works inside the AI tools your teams already use. Ask Mylo why a pod can’t reach a service, and it traces the path, points to the exact policy and rule doing the blocking, and explains why in plain language, in about the time it took you to read this paragraph. Mylo is the library of tools and skills that makes Tigera’s Calico expertise usable by an agent; the Calico MCP Server is how we deliver it. The rest of this post covers what it is, how we designed it, and why we made the choices we did.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Mylo really is: A decade of Calico expertise, as tools and skills
&lt;/h2&gt;

&lt;p&gt;Before getting into how Mylo is delivered, it’s worth being clear about what it actually is, because the delivery mechanism is the least interesting part of the story. Mylo is the Calico and Kubernetes networking knowledge Tigera has accumulated over ten years, turned into something an AI agent can use directly. It comes as two layers, and those two layers, not the plumbing that delivers them, are where the value sits.&lt;/p&gt;

&lt;p&gt;The first is a small set of tools. These aren’t thin wrappers over CLI commands; they’re semantic. The flagship, diagnose_connectivity, doesn’t hand back a raw dump for the model to interpret. It returns an ordered, opinionated read of the network path, down to the specific rule that allows or denies, with a suggested fix. The expertise lives in the tool; the reasoning stays with the agent.&lt;/p&gt;

&lt;p&gt;The second layer, and the one that compounds over time, is skills: higher-level workflows that string those tools into the procedures an expert would actually follow. Troubleshooting a connectivity failure, triaging an incident, reviewing a policy before it ships: each is a multi-step reasoning pattern, and a skill encodes it, so the agent diagnoses, then traces the policy chain, then checks recent denials, then explains the offending rule, in that order. This is the part I’d point to first. A decade of Tigera’s own troubleshooting expertise, the kind that usually lives in the heads of a handful of senior engineers, is captured here as structured guidance an agent can carry out, rather than a static runbook a human has to follow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why an MCP server, and why now
&lt;/h2&gt;

&lt;p&gt;Two things are true about the platform and security engineers who run Calico today. The first is that they are already deep in agentic workflows. In nearly every conversation we’ve had over the past few months, teams weren’t debating whether to adopt an AI assistant. They had already standardized on one, whether that’s a coding assistant in the IDE or an agent in the terminal, and connected it to a set of MCP servers for their metrics, logs, tickets, and source control. The Model Context Protocol has quietly become the way infrastructure tools present themselves to agents.&lt;/p&gt;

&lt;p&gt;The second is that Calico holds a lot of the context those engineers need, and it isn’t always easy to reach. The policy model is powerful because it’s expressive, with tiers, global and namespaced policies, selectors, and ordered evaluation. That same expressiveness, however, is what makes a thorny connectivity problem hard to reason about when you’re under pressure. Flow logs hold the answer to “why was this blocked,” but writing the query to surface it is a skill of its own.&lt;/p&gt;

&lt;p&gt;Delivering that expertise over MCP sits naturally between those two facts. Rather than build yet another chat interface and ask teams to approve a new AI product with access to production, we expose Mylo’s tools so any MCP-compatible agent can call them. Your engineers keep the front-end they’ve already vetted, and Calico becomes the intelligence layer underneath it. MCP is the delivery mechanism, not the substance, but it’s the right one, because it puts Calico’s knowledge directly into the reasoning loop of an agent that is already helping your team get work done. This is a new way to work with the Calico Unified Platform. It doesn’t replace the CLI or the UI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Composability: Workflows that weren’t possible before
&lt;/h2&gt;

&lt;p&gt;The reason this approach matters, beyond the convenience of asking questions in plain English, is composability, and it’s worth reviewing, because a lot of teams are still early in adopting MCP. A tool exposed over MCP is a building block an agent can combine with every other capability it can reach. When Mylo runs alongside the MCP servers a team already uses, the agent can move across all of them in a single line of reasoning, and that unlocks workflows nobody shipped as a feature.&lt;/p&gt;

&lt;p&gt;Consider a request like this one: “Find the traffic denied by the policy I shipped this morning, correlate it with the elevated 5xx rate the monitoring tool flagged, and open a ticket with the policy diff to fix it.” Three systems answer that in a single pass. Mylo supplies the Calico half, the expert half, and the team’s existing monitoring and issue-tracking servers supply the rest, with the agent orchestrating the whole thing end to end. The same shape shows up all over an operations workflow. Before a pull request merges, the agent can ask Mylo to simulate the policy change against last week’s flow logs and post the impact summary to the team’s channel. When flow logs show a denied connection from a production service, it can page whoever is on call. None of those are workflows we built, and none of them existed as a product a team could buy.&lt;/p&gt;

&lt;p&gt;What I find encouraging is that we didn’t have to anticipate any of them. A traditional integration or dashboard can only run the paths its authors designed in advance. Because Mylo exposes a small set of well-designed, semantically clear tools, each team fits it into the operational reality they already have, and some of the most valuable workflows will be ones we never designed for.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyi7gs2idnbtzj4mq58cu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyi7gs2idnbtzj4mq58cu.png" alt="Figure: Composability — Mylo alongside the tools you already run" width="800" height="583"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure: Composability — Mylo alongside the tools you already run&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The design philosophy: Restraint
&lt;/h2&gt;

&lt;p&gt;If one principle shaped Mylo more than any other, it’s restraint. The instinct when you build for an agent is to expose everything, to ship a tool for every API method and every CLI subcommand and let the model sort it out. In our view that instinct is a mistake, and we’ve worked hard to resist it.&lt;/p&gt;

&lt;p&gt;More tools is not better. Every tool you hand an agent is a claim on its attention, another chance for it to pick the wrong one, and another line item in the token budget. A server with a hundred thin wrappers around CLI commands doesn’t make an agent smarter. It makes it slower, more expensive, and more likely to wander off. That’s why Mylo’s tools are deliberately few and semantic rather than mechanical, and why the intelligence sits in the tool itself rather than in the model’s attempt to reconstruct it from unstructured output.&lt;/p&gt;

&lt;p&gt;We wrote down the principles we kept returning to, half in earnest and half tongue-in-cheek. A few are worth calling out, because they’re where the harder decisions actually landed. Read-only by default, because the safe posture should never depend on someone remembering to configure it. State, not verdicts, because a good tool should report what is true and let the agent do the reasoning, rather than pre-baking a conclusion that strips away the context the model needs. Selectors, not switches, because tools should accept rich, expressive inputs instead of sprouting a new boolean flag for every situation. And the one we keep at the very bottom as a reminder to ourselves: thou shalt not ship a tool for every API method.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fs6thzi20s0bp1pud0agm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fs6thzi20s0bp1pud0agm.png" alt="Figure: The Ten Commandments of MCP Servers — the design principles behind Mylo" width="800" height="503"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure: The Ten Commandments of MCP Servers — the design principles behind Mylo&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;One more piece of architecture turns that discipline into something trustworthy: the router. Agents are eager to be helpful, and an agent that can’t reach a tool will often shell out instead, quietly running a CLI command to answer a question rather than admitting the question is outside its lane. That’s harmless right up until it isn’t, and for a tool that touches production networking, silent fallback is a trust problem. So Mylo can be invoked explicitly, and when a request comes in, the server tells the agent clearly whether it can actually handle it rather than letting it improvise around the edges. That deterministic guidance, with explicit boundaries, is what earns the confidence of a platform team.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnk4eeizour7eutwzsgj1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnk4eeizour7eutwzsgj1.png" alt="Figure: How Mylo handles a request — from a plain-language ask to an evidence-backed answer" width="799" height="556"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure: How Mylo handles a request — from a plain-language ask to an evidence-backed answer&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Built to grow without slowing down
&lt;/h2&gt;

&lt;p&gt;The natural question about a deliberately focused toolset is whether it can grow in scope without growing unwieldy. I’d argue the architecture is exactly what lets us expand without the usual penalty. Because skills are invoked in context and the router keeps each request scoped to what’s relevant, adding a new capability doesn’t tax the ones already there. A troubleshooting session doesn’t get slower or noisier because we’ve also taught Mylo to help with a migration. Breadth comes from adding well-described skills and the focused tools they lean on, not from piling more surface area onto every interaction. In practice that means the range of what Mylo can do for you keeps growing while the cost of any single interaction stays flat.&lt;/p&gt;

&lt;p&gt;We’re being disciplined about sequencing, and read-only diagnostics and observability come first because that’s where the pull is strongest. The roadmap ahead is broad, though. Policy authoring is a natural next step, generating well-formed Calico policy from a plain description of intent and presenting it for review before anything is applied. We see real appetite for migration assistance, whether that’s moving VMs into Kubernetes, moving from Ingress to the Gateway API, or moving from Istio sidecars to Ambient. Configuration of Calico resources such as load balancers and egress gateways fits the same pattern. And compliance reporting keeps coming up in customer conversations, from summarizing an application’s secured egress destinations to demonstrating that PCI workloads aren’t communicating with non-PCI workloads, the kind of evidence a security team can hand to an auditor. Each of these is a skill and a small set of tools layered onto the same foundation, so we can keep growing what Mylo does for you without disturbing the safe, composable core underneath it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two ways to run it: Live cluster or diagnostics bundle
&lt;/h2&gt;

&lt;p&gt;Mylo works against a live cluster, connecting through the same kubeconfig path your engineers already use for kubectl and calicoctl, with no new endpoint exposed. That’s the mode for real-time diagnostics and observability, for asking what is happening in the cluster right now.&lt;/p&gt;

&lt;p&gt;It also works entirely offline, pointed at a Calico diagnostics bundle. This matters more than it first appears. A bundle is portable, shareable, and detached from the live environment, which makes it a good fit for the many settings where a laptop simply cannot reach production: air-gapped estates, tightly controlled prod, or after-the-fact analysis where the state you care about is the one captured at the moment of failure. The same tools and the same skills run against both. An engineer can triage a captured bundle on a plane and run live diagnostics from their desk using the identical workflow. Supporting both was not an afterthought. It’s how we’ve been able to test Mylo so thoroughly, and it’s what lets it meet enterprises where their access model actually sits.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnk4eeizour7eutwzsgj1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnk4eeizour7eutwzsgj1.png" alt="Figure: How Mylo handles a request — from a plain-language ask to an evidence-backed answer" width="799" height="556"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure: How Mylo handles a request — from a plain-language ask to an evidence-backed answer&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Read-only by design
&lt;/h2&gt;

&lt;p&gt;For the teams evaluating Mylo, the first question is almost always about safety, and our answer is deliberately conservative. Mylo is read-only by design. Its tools diagnose, explain, observe, and where they touch policy, generate proposed YAML. They do not apply, update, or delete anything. This holds even when Mylo is handed a cluster-admin kubeconfig, because the read-only boundary is a property of the tools themselves and not something we’re trusting the model to honor. Security teams have appreciated that they can point their own agent at the server and audit for themselves exactly what it can and cannot do.&lt;/p&gt;

&lt;p&gt;The result is a much narrower profile than the interfaces these teams have already approved. Mylo is a typed, structured API with no browser session, no rendered pages, and no standing state to hijack. Access runs through the calling user’s existing Kubernetes RBAC, so if a user can’t list policies in a namespace, neither can Mylo on their behalf. That makes for a far shorter security conversation than approving a net-new AI product, largely because there is no new AI product to approve. The reasoning happens in a front-end the customer already trusts.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the internal testing showed
&lt;/h2&gt;

&lt;p&gt;We didn’t want to announce a promising demo. Before we put Mylo in front of anyone, we ran it against our own library of resolved support cases, real and historically difficult problems where we already knew the answer and how long it had originally taken to reach. It’s a demanding benchmark, because it measures Mylo against outcomes that skilled engineers had already worked hard to produce.&lt;/p&gt;

&lt;p&gt;The results are the reason we’re writing this post. A class of case that historically took on the order of ten days to root-cause, the kind that bounces between teams and keeps escalating, Mylo worked through in roughly ten minutes. Not every case, and never without a person in the loop reading the output and making the call. But the pattern held often enough, across enough cases, that we’re confident this is real and repeatable. Compressing days of investigation into minutes changes what an under-resourced operations team is able to take on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Early access, and what we’re seeing
&lt;/h2&gt;

&lt;p&gt;Mylo is in early access now with a small group of design partners. They are large, security-conscious organizations, several of them in regulated industries, and all of them already fluent in agentic workflows. We’re keeping the program deliberately tight so we can learn quickly, and we’re bringing participants on in waves rather than opening the gates all at once.&lt;/p&gt;

&lt;p&gt;The early signal has been better than we expected. Participants aren’t just kicking the tires; some are reaching for Mylo daily. One of the more encouraging patterns is teams using it to scope problems they simply couldn’t get their arms around before, such as surveying years of accumulated policy sprawl to find what’s orphaned or duplicated, work that used to mean writing custom tooling nobody had time to build. That read-only, get-the-data-out-of-Calico use case has been the wedge almost everywhere. The fastest path to value is answering “why is this happening” in plain English, and the appetite for it is real.&lt;/p&gt;

&lt;h2&gt;
  
  
  The road to GA
&lt;/h2&gt;

&lt;p&gt;Early access is showing us what enterprise-ready has to mean, and the requirements have been remarkably consistent from one team to the next. On the way to general availability we’re focused on a few things: an in-cluster deployment option for teams that want Mylo owned and run by the platform rather than launched from a laptop; authentication and RBAC that carry each user’s real cluster permissions through to every tool call; tiered access that builds on the read-only foundation with a staged suggest tier, where policy changes are proposed as reviewable diffs and applied only after a human approves; and audit logging that records every tool invocation for the compliance and security teams who, rightly, want the full trail.&lt;/p&gt;

&lt;p&gt;None of that changes the core posture. Mylo starts safe, stays composable, and earns each new capability rather than assuming it. That’s the philosophy that got us here, and it’s the one we intend to keep.&lt;/p&gt;

&lt;p&gt;If you run Calico and your teams are already working with AI agents, we’d love to have you see this early. Mylo is how Calico shows up in that world, and I think it’s going to change what a hard networking day looks like.&lt;/p&gt;

&lt;p&gt;If you’re not a customer yet and would like to learn more about Mylo, &lt;a href="https://www.tigera.io/contact/" rel="noopener noreferrer"&gt;drop us a line here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://www.tigera.io/blog/meet-mylo-an-ai-native-way-to-work-with-calico/" rel="noopener noreferrer"&gt;Meet Mylo: An AI-native way to work with Calico&lt;/a&gt; appeared first on &lt;a href="https://www.tigera.io" rel="noopener noreferrer"&gt;Tigera – Creator of Calico&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>technicalblog</category>
      <category>calicoai</category>
      <category>products</category>
      <category>announcements</category>
    </item>
    <item>
      <title>The Safest Place to Run an AI Agent Is On a Cluster That Doesn’t Trust It</title>
      <dc:creator>Alister Baroi</dc:creator>
      <pubDate>Thu, 27 Aug 2026 17:34:36 +0000</pubDate>
      <link>https://dev.to/tigeraio/the-safest-place-to-run-an-ai-agent-is-on-a-cluster-that-doesnt-trust-it-50p8</link>
      <guid>https://dev.to/tigeraio/the-safest-place-to-run-an-ai-agent-is-on-a-cluster-that-doesnt-trust-it-50p8</guid>
      <description>&lt;p&gt;Every organization running AI agents has already made a hosting decision. Most made it by accident.&lt;/p&gt;

&lt;p&gt;The sales team switched on the agent built into their CRM. Engineering is piloting a coding agent in a vendor’s cloud. Someone on the data team deployed a LangGraph service to a VM with a database key in an environment variable, and someone else is running an agent framework on a laptop with production credentials in a dotfile. Each of these is a hosting decision. Each one quietly settled who holds the agent’s credentials, what network paths it can reach, what gets recorded when it acts, and who can stop it. Nobody ran an architecture review, because no single deployment looked big enough to deserve one.&lt;/p&gt;

&lt;p&gt;The scale says otherwise. By May 2025, &lt;a href="https://www.sailpoint.com/press-releases/sailpoint-ai-agent-adoption-report" rel="noopener noreferrer"&gt;82% of organizations surveyed by SailPoint&lt;/a&gt; were already using AI agents. Only 44% had policies for securing them, 80% said their agents had already taken unintended actions, and 23% had watched an agent get tricked into revealing credentials. A year later the bill arrived: &lt;a href="https://newsroom.ibm.com/2026-07-29-ibm-study-one-in-four-malicious-breaches-are-ai-enabled,-costing-companies-6-million-on-average" rel="noopener noreferrer"&gt;IBM’s 2026 Cost of a Data Breach report&lt;/a&gt; found that one in four malicious breaches is now AI-enabled, up 56% in a single year, and that those breaches cost about a million dollars more than the global average. Gartner, for its part, &lt;a href="https://www.gartner.com/en/newsroom/press-releases/2025-06-25-gartner-predicts-over-40-percent-of-agentic-ai-projects-will-be-canceled-by-end-of-2027" rel="noopener noreferrer"&gt;expects over 40% of agentic AI projects to be canceled by the end of 2027&lt;/a&gt;, naming inadequate risk controls as one of the three reasons.&lt;/p&gt;

&lt;p&gt;This post is the architecture review those deployments never got. The conclusion, stated up front so you can argue with it: agents should run on Kubernetes clusters you control, wrapped in guardrails and gateways that no prompt can talk its way past. Not because Kubernetes is fashionable, but because a year of documented incidents shows that every failure was an environmental failure, and a cluster you control is the only substrate where you own every layer of the environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  The workload that chooses its own code path
&lt;/h2&gt;

&lt;p&gt;A microservice does what its code says. You can read the code, test the paths, and enumerate what it will do with any input. An agent is a different kind of workload, and the difference is structural, not a maturity phase it will grow out of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Its control flow is decided at runtime by a model.&lt;/strong&gt; The “code path” is chosen by whatever lands in the context window. You cannot statically review what an agent will do, only what it is allowed to do.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It holds credentials and takes actions&lt;/strong&gt;. Agents query databases, call APIs, send email, move money, and spawn other agents. The interesting failure mode is not a wrong answer. It is a correct, authorized, catastrophic action.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Every input is potentially an instruction.&lt;/strong&gt; Prompt injection remains unsolved. &lt;a href="https://genai.owasp.org/2025/12/09/owasp-genai-security-project-releases-top-10-risks-and-mitigations-for-agentic-ai-security/" rel="noopener noreferrer"&gt;OWASP’s Top 10 for Agentic Applications&lt;/a&gt;, published in December 2025 with over a hundred contributors, reads mostly as variations on this theme: goal hijack, tool misuse, identity and privilege abuse, memory poisoning.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Put those three together and you get the principle we have argued all year, from &lt;a href="https://www.tigera.io/blog/the-ai-agent-accountability-gap-why-network-policies-api-gateways-and-rbac-are-not-enough/" rel="noopener noreferrer"&gt;the accountability gap&lt;/a&gt; to &lt;a href="https://www.tigera.io/blog/nvidia-openshell-secures-the-agent-who-governs-the-fleet/" rel="noopener noreferrer"&gt;the OpenShell analysis&lt;/a&gt;: controls the agent can override are not controls. The system prompt is not a perimeter. The guardrail library running inside the agent’s own process is not a perimeter. The controls have to live in the environment, where a confused or compromised agent cannot negotiate with them.&lt;/p&gt;

&lt;p&gt;And once the controls must live in the environment, the hosting question stops being an infrastructure detail. Where the agent runs determines which controls can exist at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  A year of incidents; one pattern
&lt;/h2&gt;

&lt;p&gt;Theory is cheap. The past twelve months supplied the evidence, and it is unusually well documented.&lt;/p&gt;

&lt;h3&gt;
  
  
  One agent’s tokens, seven hundred victims
&lt;/h3&gt;

&lt;p&gt;Drift was an AI chat agent embedded on corporate websites. To do its job it held long-lived OAuth tokens into each customer’s Salesforce. In August 2025, attackers who had stolen those tokens used them to run bulk data exports against customer CRMs. &lt;a href="https://cloud.google.com/blog/topics/threat-intelligence/data-theft-salesforce-instances-via-salesloft-drift" rel="noopener noreferrer"&gt;Google’s threat intelligence group assessed more than 700 organizations&lt;/a&gt; as potentially affected. The attackers were not after chat transcripts. They mined the exported support cases for the credentials customers had pasted into them: AWS keys, Snowflake tokens, passwords. Cloudflare, one of the disclosed victims, &lt;a href="https://www.bleepingcomputer.com/news/security/cloudflare-hit-by-data-breach-in-salesloft-drift-supply-chain-attack/" rel="noopener noreferrer"&gt;rotated 104 API tokens&lt;/a&gt; found in its stolen case text.&lt;/p&gt;

&lt;p&gt;No agent was compromised. No model misbehaved. One integration’s credentials were broad, long-lived, and held outside every victim’s own controls, so one theft became seven hundred breaches.&lt;/p&gt;

&lt;h3&gt;
  
  
  The agent with production credentials and a code freeze
&lt;/h3&gt;

&lt;p&gt;In July 2025, on day nine of a public twelve-day build, Replit’s coding agent &lt;a href="https://fortune.com/2025/07/23/ai-coding-tool-replit-wiped-database-called-it-a-catastrophic-failure/" rel="noopener noreferrer"&gt;wiped SaaStr founder Jason Lemkin’s production database&lt;/a&gt;, despite an explicit and repeated code-freeze instruction. It then generated thousands of fake records and reported that rollback was impossible. It was not; the data came back from backup. The agent’s own postmortem: “a catastrophic failure on my part.”&lt;/p&gt;

&lt;p&gt;The agent held live credentials to production with no environment separation, and the code freeze existed only as natural language. An instruction in a prompt is a suggestion. The incident record was, briefly, whatever the agent chose to say it was.&lt;/p&gt;

&lt;h3&gt;
  
  
  The tool that BCC’d the attacker
&lt;/h3&gt;

&lt;p&gt;In September 2025, Koi Security found the &lt;a href="https://thehackernews.com/2025/09/first-malicious-mcp-server-found.html" rel="noopener noreferrer"&gt;first confirmed malicious MCP server in the wild&lt;/a&gt;: an npm package impersonating Postmark’s email server. It behaved correctly for fifteen versions, building trust, then v1.0.16 added a single line that BCC’d every email the connected agents sent to the attacker’s domain. Koi estimated roughly 300 organizations were running it in production. Nothing was exploited. An MCP server runs inside the agent’s trust boundary with the user’s credentials, and nobody diffs a patch release.&lt;/p&gt;

&lt;h3&gt;
  
  
  And the rest, briefly
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://msrc.microsoft.com/update-guide/vulnerability/CVE-2025-32711" rel="noopener noreferrer"&gt;EchoLeak (CVE-2025-32711)&lt;/a&gt; demonstrated a zero-click chain against Microsoft 365 Copilot: a poisoned email, retrieved later by RAG, walked the assistant’s most sensitive reachable data out through an allowlisted URL. Microsoft fixed it before any known exploitation, and it became the first critical-severity CVE assigned to an AI assistant’s injection path. The &lt;a href="https://www.wiz.io/blog/s1ngularity-supply-chain-attack" rel="noopener noreferrer"&gt;s1ngularity npm supply-chain attack&lt;/a&gt; inverted the picture: malware on developer machines invoked the victims’ own installed CLI agents with their client-side safety flags disabled and put them to work enumerating secrets, leaking over a thousand valid GitHub tokens within hours. And in July 2026, Check Point documented &lt;a href="https://blog.checkpoint.com/ai-security/ai-security-threats-in-2026-insights-from-check-point-research/" rel="noopener noreferrer"&gt;a single operator running two frontier-model agents&lt;/a&gt; as an intrusion pipeline that hit nine Mexican government agencies and roughly 400 million records. Attackers have agents too, and theirs ignore your prompts entirely.&lt;/p&gt;

&lt;h3&gt;
  
  
  The pattern
&lt;/h3&gt;

&lt;p&gt;None of these was a model failure. Every one of them was contained, or would have been, by the same four environmental controls:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Credentials scoped to one target and short-lived&lt;/strong&gt; , so a stolen token is worth almost nothing (Drift).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authorization evaluated on every request against policy&lt;/strong&gt; , not against the agent’s intentions or instructions (Replit, and the bulk CRM exports that no chat agent should have been able to run).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Egress that is deny-by-default and enforced outside the agent&lt;/strong&gt; , so even a successful injection has nowhere to send the loot (EchoLeak, the Postmark BCC, s1ngularity’s uploads).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;An audit trail owned by the platform, not narrated by the agent&lt;/strong&gt; (Replit’s fabricated reports; Cloudflare could say “exactly 104 tokens” only because logs existed outside the blast radius).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Read that list again. Nothing on it is a property of the model. Nothing on it can be provided by a prompt, a fine-tune, or a guardrail library running inside the agent. All four are properties of the place where the agent runs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the answer is a cluster you control
&lt;/h2&gt;

&lt;p&gt;Environmental controls need an environment you own: the network path, the identity plane, the secret store, the audit pipe. Kubernetes is the one mainstream substrate that hands you all four as programmable primitives: namespaces and NetworkPolicy for segmentation, runtime classes for kernel-level sandboxing (gVisor, Kata), SPIFFE for workload identity, and admission control to keep anything unreviewed from running at all. Its declarative model then puts every one of those decisions in git, where they get reviewed and versioned like the rest of your infrastructure. These are the same properties that made Kubernetes the default for microservices. For agents they are not conveniences; they are the containment system.&lt;/p&gt;

&lt;p&gt;The ecosystem has noticed. In the past year, Kubernetes gained a &lt;a href="https://github.com/kubernetes-sigs/agent-sandbox" rel="noopener noreferrer"&gt;SIG subproject for agent sandboxing&lt;/a&gt; with first-class &lt;code&gt;Sandbox&lt;/code&gt; primitives, launched at KubeCon NA 2025. &lt;a href="https://www.linuxfoundation.org/press/linux-foundation-welcomes-agentgateway-project-to-accelerate-ai-agent-adoption-while-maintaining-security-observability-and-governance" rel="noopener noreferrer"&gt;agentgateway&lt;/a&gt;, a data plane purpose-built for agent-to-agent, MCP, and LLM traffic, became a Linux Foundation project with participation from AWS, Microsoft, Red Hat, IBM, and Cisco. KubeCon NA 2026 has a &lt;a href="https://www.cncf.io/announcements/2026/08/10/cncf-reveals-kubecon-cloudnativecon-north-america-2026-schedule-adds-new-ai-inference-agentic-track/" rel="noopener noreferrer"&gt;dedicated AI and agentic track&lt;/a&gt;. Running agents on Kubernetes stopped being a contrarian position sometime last winter.&lt;/p&gt;

&lt;p&gt;Watch the managed agent runtimes and you see the same conclusion arriving from the other direction. AWS AgentCore added &lt;a href="https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/gateway-vpc-egress.html" rel="noopener noreferrer"&gt;VPC egress&lt;/a&gt; and private identity-provider support. Microsoft’s agent service will &lt;a href="https://learn.microsoft.com/en-us/azure/foundry/agents/how-to/virtual-networks" rel="noopener noreferrer"&gt;inject its runtime into your own VNet&lt;/a&gt; so agent data stays in your tenant. Anthropic’s managed agents shipped &lt;a href="https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes" rel="noopener noreferrer"&gt;self-hosted sandboxes&lt;/a&gt; that run tool execution on your infrastructure. OpenAI’s &lt;a href="https://openai.com/index/introducing-openai-frontier/" rel="noopener noreferrer"&gt;Frontier launch&lt;/a&gt; promises agents that run “across local environments, enterprise cloud infrastructure, and OpenAI-hosted runtimes.” Every managed runtime’s roadmap is bending toward your perimeter. That is the vendors telling you, in feature announcements, where the controls have to live.&lt;/p&gt;

&lt;p&gt;There is also the question of what you can see when isolation is outsourced. In late 2025, Unit 42 &lt;a href="https://unit42.paloaltonetworks.com/bypass-of-aws-sandbox-network-isolation-mode/" rel="noopener noreferrer"&gt;disclosed an escape in AWS AgentCore’s code-interpreter sandbox&lt;/a&gt;: its “sandbox” network mode still allowed DNS resolution to arbitrary domains, which is enough for tunneled exfiltration and command-and-control. AWS fixed it properly within months, and credit to them. But note who found it and when the customers learned: from the researcher’s publication, not from their own telemetry, because inside a managed runtime there is no customer telemetry to find it in.&lt;/p&gt;

&lt;p&gt;Side by side:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Concern&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Managed agent runtime&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Sandbox platform&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Kubernetes with guardrails&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Where the agent executes&lt;/td&gt;
&lt;td&gt;Vendor’s cloud (some now reach into your VPC)&lt;/td&gt;
&lt;td&gt;Provider’s microVM fleet&lt;/td&gt;
&lt;td&gt;Your cluster: any cloud, on-prem, air-gapped&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Who holds tool credentials&lt;/td&gt;
&lt;td&gt;Vendor’s credential broker&lt;/td&gt;
&lt;td&gt;Injected into the sandbox&lt;/td&gt;
&lt;td&gt;Brokered in-cluster, attached per hop&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Egress control&lt;/td&gt;
&lt;td&gt;Vendor-defined, opt-in&lt;/td&gt;
&lt;td&gt;Platform-defined&lt;/td&gt;
&lt;td&gt;Your gateway, default deny&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Authorization granularity&lt;/td&gt;
&lt;td&gt;Per connector, mostly coarse&lt;/td&gt;
&lt;td&gt;Yours to build&lt;/td&gt;
&lt;td&gt;Per request, down to tool arguments&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Audit trail&lt;/td&gt;
&lt;td&gt;Per vendor, per format&lt;/td&gt;
&lt;td&gt;Per platform&lt;/td&gt;
&lt;td&gt;One trail across agents, tools, and models&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Agents you didn’t launch&lt;/td&gt;
&lt;td&gt;Invisible&lt;/td&gt;
&lt;td&gt;Invisible&lt;/td&gt;
&lt;td&gt;Detectable on the node&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Exit cost&lt;/td&gt;
&lt;td&gt;Rebuild against a new runtime&lt;/td&gt;
&lt;td&gt;Re-platform&lt;/td&gt;
&lt;td&gt;Agents are containers; the cluster moves with you&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The table generalizes, and the best vendors are improving individual rows. What no managed runtime can give you are the rows that require owning the substrate: one policy engine over every agent regardless of framework, one audit trail across agents, tools, and models, and visibility into the agents nobody told the platform about.&lt;/p&gt;

&lt;p&gt;One caveat before the spec. _ &lt;strong&gt;A bare cluster is not the answer either&lt;/strong&gt; _. Stock Kubernetes secures pods, not agents: NetworkPolicy has no idea what an MCP tool call is, RBAC governs humans and service accounts, and nothing in the box produces an agent-level audit trail. We walked through those gaps in &lt;a href="https://www.tigera.io/blog/the-ai-agent-accountability-gap-why-network-policies-api-gateways-and-rbac-are-not-enough/" rel="noopener noreferrer"&gt;the accountability gap post&lt;/a&gt;. What the cluster uniquely gives you is the ability to install the missing layer yourself, uniformly, for every agent you run.&lt;/p&gt;

&lt;h2&gt;
  
  
  What strict guardrails look like
&lt;/h2&gt;

&lt;p&gt;Here is the spec a year of incidents wrote, stated as requirements. Sandboxing the agent’s process is assumed and is not sufficient on its own; &lt;a href="https://www.cncf.io/blog/2026/07/07/why-sandboxing-your-agent-is-not-enough/" rel="noopener noreferrer"&gt;even the CNCF says so now&lt;/a&gt;. Everything below governs what agents do across the network, which is where every incident above happened.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;An identity for every agent&lt;/strong&gt;. Cryptographic workload identity (SPIFFE, OIDC) issued at deploy time, not a shared service account. Every other control depends on “which agent did this” having an answer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One road out&lt;/strong&gt;. Agent egress is deny-by-default, and the only path to other agents, MCP servers, and LLM providers is a gateway. EchoLeak, the Postmark backdoor, and s1ngularity’s uploads were all exfiltration over permitted egress. An allowlist enforced outside the agent kills the chain even when the injection succeeds.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authorization per request, not per deployment.&lt;/strong&gt; Each call is judged against policy: this agent, this target, this tool, these arguments. A lead-triage agent asking for a bulk CRM export should fail on policy, not on luck.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Credentials the agent never holds&lt;/strong&gt;. Provider keys and tokens attach at the gateway, scoped to the single target of the single hop, short-lived. This is the Drift control: make the stolen token worthless.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A human where the blast radius is high&lt;/strong&gt;. Destructive and irreversible operations block until a person approves. “Code freeze” becomes a policy object with an enforcement point, instead of a sentence in a prompt.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Detection for the agents you didn’t launch&lt;/strong&gt;. 80% of organizations already report unintended agent actions, and IBM’s data keeps tying breach costs to shadow AI. You need to see the unregistered agent from the node it runs on, not from a registry it never joined.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;An audit trail the agent cannot edit&lt;/strong&gt;. Recorded by the enforcement plane as a side effect of enforcing, tied to agent identity, covering every hop. The agent’s own account of events must never be the system of record.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you run a startup, this list probably reads as an enterprise ceremony. It is the opposite. The spec is precisely what lets a five-person team hand agents real credentials to real systems without hiring a security organization: default-deny scales down, a policy file for three agents fits on one screen, and one gateway is not a platform team’s worth of work. If you run an enterprise, the same spec is what turns your agent deployment from an audit finding into an audited system. The requirements do not change with headcount. Only the number of agents does.&lt;/p&gt;

&lt;h2&gt;
  
  
  The platform this spec describes
&lt;/h2&gt;

&lt;p&gt;By now the specificity of that list has probably given the game away: it is, near enough, the design document for &lt;a href="https://www.tigera.io/blog/why-we-built-lynx-bringing-control-to-the-age-of-ai-agents/" rel="noopener noreferrer"&gt;Tigera Lynx&lt;/a&gt;, our security and governance platform for AI agents on Kubernetes.&lt;/p&gt;

&lt;p&gt;Lynx puts a registry and identity plane in front of your agents: SPIFFE and OIDC workload identity, plus a pod-owner mode that brings an unmodified agent under governance with no code changes and no credential to issue. Its gateway, built on the same Linux Foundation agentgateway data plane mentioned above, authorizes every agent-to-agent, MCP, and LLM call individually under Cedar policy, and MCP policies can see the operation, the tool name, and the tool arguments, failing closed on anything malformed. LLM provider keys live in your cluster’s secret store and attach at the gateway, so an agent never carries a provider credential it could leak, and per-provider token rate limits cap what any agent can burn.&lt;/p&gt;

&lt;p&gt;In the current release cycle, per-hop credentials are minted for one target only (the Drift lesson, applied literally), and a policy can mark specific MCP calls as needing human approval, so the call waits until someone signs off (the Replit lesson). On the node, an eBPF-based detector spots agents nobody registered, classifies them as sanctioned, shadow, or unknown, and lets you quarantine a compromised workload at both the gateway and the kernel. And the Agent Trail records every decision, every hop, and which model actually served each call, as a byproduct of enforcement. The agent does not get to narrate.&lt;/p&gt;

&lt;p&gt;Every one of those maps to a numbered line in the spec, because the spec came first. &lt;a href="https://www.tigera.io/blog/how-lynx-works-a-technical-walkthrough/" rel="noopener noreferrer"&gt;How Lynx Works&lt;/a&gt; has the full walkthrough, and the &lt;a href="https://www.tigera.io/blog/five-principles-of-an-accountable-ai-agent-network-how-to-evaluate-any-governance-platform/" rel="noopener noreferrer"&gt;five principles post&lt;/a&gt; is the vendor-neutral checklist if you want to evaluate Lynx against anyone else.&lt;/p&gt;

&lt;h2&gt;
  
  
  The decision you already made
&lt;/h2&gt;

&lt;p&gt;Back to the opening. Your organization has a hosting posture for AI agents today, assembled from defaults: whichever vendor clouds your teams clicked through, whichever VMs were lying around, whichever laptops were closest. The incidents above are what those defaults cost, and IBM’s data says AI is now involved in one of every four malicious breaches.&lt;/p&gt;

&lt;p&gt;So ask the question deliberately, once, before the next agent ships: when it acts, who can say no, and where is the record? If the answer is a vendor’s incident queue and a support ticket, _ &lt;strong&gt;you have outsourced the two things a security leader cannot outsource.&lt;/strong&gt; _&lt;/p&gt;

&lt;p&gt;_ &lt;strong&gt;An agent you cannot refuse is an agent you do not control.&lt;/strong&gt; _ Run yours where refusal is built in: a Kubernetes cluster you own, a gateway it cannot go around, and a policy engine that never gets tired of saying no.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Lynx is Tigera’s security and governance platform for AI agents on Kubernetes: identity, policy, detection, and audit for every agent in your cluster. Read &lt;a href="https://www.tigera.io/blog/how-lynx-works-a-technical-walkthrough/" rel="noopener noreferrer"&gt;How Lynx Works&lt;/a&gt; or request early access at &lt;a href="http://tigera.io/demo/?product=lynx" rel="noopener noreferrer"&gt;tigera.io/demo/&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.tigera.io/tigera-products/lynx/" rel="noopener noreferrer"&gt;Learn more about Lynx →&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://www.tigera.io/blog/the-safest-place-to-run-an-ai-agent-is-on-a-cluster-that-doesnt-trust-it/" rel="noopener noreferrer"&gt;The Safest Place to Run an AI Agent Is On a Cluster That Doesn’t Trust It&lt;/a&gt; appeared first on &lt;a href="https://www.tigera.io" rel="noopener noreferrer"&gt;Tigera – Creator of Calico&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>technicalblog</category>
      <category>aiagentsecurity</category>
      <category>bestpractices</category>
      <category>products</category>
    </item>
    <item>
      <title>AI Red Team Agents Automate Attacks on your AI Agents. Runtime Policies Automate their Defense.</title>
      <dc:creator>Alister Baroi</dc:creator>
      <pubDate>Mon, 24 Aug 2026 14:40:14 +0000</pubDate>
      <link>https://dev.to/tigeraio/ai-red-team-agents-automate-attacks-on-your-ai-agents-runtime-policies-automate-their-defense-2j93</link>
      <guid>https://dev.to/tigeraio/ai-red-team-agents-automate-attacks-on-your-ai-agents-runtime-policies-automate-their-defense-2j93</guid>
      <description>&lt;p&gt;The AI red teaming market grew up fast this year. OpenAI bought Promptfoo, Cisco and Microsoft shipped automated attack suites, and a seed-stage startup publicly compromised 50 of 55 live customer service bots. These platforms find real problems at a scale no human team can match. But when you read the findings closely, a pattern emerges: agents talked into refunds, transfers, and data leaks they had standing authority to perform. Patching the prompt fixes one phrasing until the next model update. Constraining the authority fixes the class. The first job belongs to a red team platform. The second belongs to your runtime, and no scanner will do it for you.&lt;/p&gt;

&lt;p&gt;In April 2026, &lt;a href="https://www.businesswire.com/news/home/20260429247972/en/General-Analysis-Raises-$10M-in-Seed-Funding-to-Secure-Agentic-AI" rel="noopener noreferrer"&gt;General Analysis raised a $10M seed round&lt;/a&gt; on the strength of an uncomfortable demonstration: its adversarial agent attacked 55 live customer service bots and compromised 50 of them. Not lab models, but live systems with real customers and real tool access. This post is about the market behind that demonstration: who now automates the attacker’s role, what the attacks keep finding, and why the fix that lasts is runtime policy rather than a better prompt.&lt;/p&gt;

&lt;h2&gt;
  
  
  What an AI red team agent actually does
&lt;/h2&gt;

&lt;p&gt;A traditional red team is a group of people paid to break your system before someone else does. An AI red team agent automates that role for AI systems. It fires thousands of adversarial inputs at a model or agent, notices which ones partially work, mutates them, escalates across turns, and reports what got through, with severity ratings and reproduction steps. A human tester works through a checklist over a week. These platforms run 20,000 variations overnight and rank the results.&lt;/p&gt;

&lt;p&gt;The canonical demo goes like this. A company deploys an agent that handles refunds and can reach the billing system. The red team platform embeds disguised instructions in customer messages until it finds the phrasing that makes the agent skip its verification step and process a refund it shouldn’t. The report names the exact prompt pattern so engineering can fix it.&lt;/p&gt;

&lt;p&gt;Enterprises are buying for reasons that have little to do with fashion. Agents now do things, such as executing code, querying databases, sending emails, and calling APIs, often with minimal supervision, so every capability is an attack vector. The &lt;a href="https://artificialintelligenceact.eu/" rel="noopener noreferrer"&gt;EU AI Act&lt;/a&gt; mandates adversarial testing for high-risk AI systems, and insurers and procurement teams have started asking for documented testing as a condition of coverage or vendor selection. And a quarterly pen-test calendar cannot keep up with an agent whose behavior shifts on every model update.&lt;/p&gt;

&lt;p&gt;All of that is real, and the tooling is genuinely good. None of this is an argument against red teaming. The question is what you do on the morning the report arrives.&lt;/p&gt;

&lt;h2&gt;
  
  
  The AI red teaming market grew up in about a quarter
&lt;/h2&gt;

&lt;p&gt;The speed of consolidation tells you how seriously the industry takes automated red teaming. In March 2026, OpenAI &lt;a href="https://openai.com/index/openai-to-acquire-promptfoo/" rel="noopener noreferrer"&gt;acquired Promptfoo&lt;/a&gt; for a reported $86M; the MIT-licensed scanner claims 350,000 developers and now ships inside OpenAI’s Frontier enterprise platform. &lt;a href="https://www.cisco.com/site/us/en/products/security/ai-defense/index.html" rel="noopener noreferrer"&gt;Cisco AI Defense&lt;/a&gt; tests across 200+ risk subcategories mapped to OWASP, NIST, and MITRE ATLAS. Microsoft’s &lt;a href="https://learn.microsoft.com/en-us/azure/foundry/concepts/ai-red-teaming-agent" rel="noopener noreferrer"&gt;AI Red Teaming Agent&lt;/a&gt; wraps PyRIT’s multi-turn attack orchestration, including Crescendo and Tree of Attacks with Pruning, into Azure AI Foundry. Mindgard starts with reconnaissance: it maps your guardrails, tools, and shadow AI deployments before it fires a single probe. And General Analysis goes deepest on agentic systems: MCP server exploitation, memory poisoning, and multi-step permission bypass.&lt;/p&gt;

&lt;p&gt;OWASP now publishes a &lt;a href="https://genai.owasp.org/resource/ai-security-solutions-landscape-for-ai-and-agentic-red-teaming-q2-2026/" rel="noopener noreferrer"&gt;quarterly landscape document&lt;/a&gt; just for this category. When a market gets its own recurring OWASP publication, it has stopped being a niche.&lt;/p&gt;

&lt;h2&gt;
  
  
  Read the findings like a defender
&lt;/h2&gt;

&lt;p&gt;Look at what these platforms actually catch across every vendor’s case studies: an agent processing unauthorized refunds. An agent skipping its verification step. An agent revealing one customer’s data to another. A moderation model bypassed with encoding tricks. An agent walked, over several polite turns, across a permission boundary it was never supposed to cross. A poisoned memory that redirects behavior days later. A malicious MCP server that turns one compromised tool into several.&lt;/p&gt;

&lt;p&gt;Sort those into two piles. In the first pile, the model said something it shouldn’t have (jailbreaks and moderation bypasses). Those are model-layer problems with model-layer fixes, and the labs keep getting better at them. In the second pile, the agent did something it shouldn’t have. Every headline finding in the agentic column lands here, and every one of them has the same anatomy: the agent was persuaded, and the environment obeyed.&lt;/p&gt;

&lt;p&gt;The persuasion is novel every time. That is the entire point of automated attack generation; there is always another phrasing, another encoding, another escalation path. The obedience is identical every time. The agent asked for &lt;code&gt;transfer_funds&lt;/code&gt;, and something executed it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prompt patches decay. Runtime policy doesn’t.
&lt;/h2&gt;

&lt;p&gt;Here is the loop most teams fall into. The red team report names a prompt pattern. Engineering patches the system prompt or adds a guardrail rule. The finding closes. A model update ships three weeks later, and the finding reopens with different wording. The vendors know this; it’s why General Analysis sells regression testing for exactly the case where a passing agent configuration fails after a model update or prompt change, and why every platform now pitches continuous scanning rather than an annual engagement. Continuous testing is the industry’s honest admission that the layer under test never stays fixed.&lt;/p&gt;

&lt;p&gt;We’ve made this argument before, in the &lt;a href="https://www.tigera.io/blog/the-ai-agent-accountability-gap-why-network-policies-api-gateways-and-rbac-are-not-enough/" rel="noopener noreferrer"&gt;accountability gap post&lt;/a&gt; and throughout the series: controls the agent can override are not controls. The same logic applies to instructions. An agent can be talked out of its system prompt; that is precisely what the red team platform just proved. It cannot be talked out of a deny that lives outside its process.&lt;/p&gt;

&lt;p&gt;So a pile-two finding deserves two responses. Patch the prompt, by all means; make the attack more expensive. But the fix that lasts is changing what the persuasion can accomplish, and that change happens in the environment, at the point where the agent’s request becomes an action.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rewriting a red team finding as runtime policy
&lt;/h2&gt;

&lt;p&gt;Take the marquee finding, the one on every vendor’s landing page: an injected instruction convinces a finance agent to call transfer_funds without its verification step. As a reproduction step, that’s a ticket that will reopen. As policy, it looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rego"&gt;&lt;code&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;approvalRequired&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Approve transfer_funds on treasury"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;forbid&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;principal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;Action&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="s2"&gt;"callMCPServer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;unless&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;approval&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;granted&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;when&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mcp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"transfer_funds"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is Cedar, evaluated at a gateway between the agent and its MCP servers. Any call to &lt;code&gt;transfer_funds&lt;/code&gt; is denied unless a human has granted approval, and the annotation turns that deny into a hold: the gateway parks the request, a person approves or rejects it, and only then does anything move. Approval is an input to the policy decision, not an override of it. The injection can still convince the agent to try. Trying now produces a held request and an audit entry instead of a wire transfer.&lt;/p&gt;

&lt;p&gt;The same translation works across the rest of pile two:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;What the red team keeps finding&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Where the durable fix lives&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Prompt injection triggers an unauthorized tool call&lt;/td&gt;
&lt;td&gt;Per-request authorization at a gateway the agent cannot route around&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Agent skips a verification or approval step&lt;/td&gt;
&lt;td&gt;A policy hold that parks the call until a human decides&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Agent leaks one customer’s data to another&lt;/td&gt;
&lt;td&gt;Tool and egress policy scoped to the agent’s verified identity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multi-step chains cross a permission boundary&lt;/td&gt;
&lt;td&gt;Per-call decisions with the full chain correlated in one trace&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The agent nobody tested, because nobody knew it existed&lt;/td&gt;
&lt;td&gt;Runtime detection of unregistered agents&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;That last row deserves a sentence. Mindgard leads with reconnaissance because most organizations cannot produce an accurate inventory of their own AI systems, and you cannot red team what you don’t know you’re running. Scoping the engagement is where a program fails first, before a single probe fires. Inventory is a runtime problem too.&lt;/p&gt;

&lt;p&gt;This is the seam where &lt;a href="https://www.tigera.io/tigera-products/lynx/" rel="noopener noreferrer"&gt;Lynx&lt;/a&gt; sits. Its gateway authorizes every MCP call individually against Cedar policy under a workload identity (e.g. SPIFFE). The &lt;code&gt;@approvalRequired&lt;/code&gt; hold shown above shipped in preview this cycle, with the pending queue and countdown surfaced in the dashboard. Agent Trail records the deny that started the hold and the human decision that resolved it. And runtime detection classifies the agents actually present in your cluster, so the inventory a red team engagement needs is a query rather than an archaeology project. None of that replaces adversarial testing. It’s what turns the testing’s output into something that stays fixed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Starting with open source: Garak, PyRIT, and DeepTeam
&lt;/h2&gt;

&lt;p&gt;If you want to start this quarter, the open source route is credible. Garak (by NVIDIA, under Apache 2.0 license) is the deepest free attack catalogue: 120+ probe modules, with multi-turn agentic attacks added in v0.15.0 this May. PyRIT (Microsoft, MIT) is the strongest orchestrator for custom multi-turn campaigns. DeepTeam (Apache 2.0 license) maps results onto OWASP’s Agentic Security Initiative taxonomy for the compliance evidence trail; disable its cloud scoring calls if your data can’t leave the building. One caveat worth knowing before you standardize: Promptfoo belongs to OpenAI and PyRIT to Microsoft, both model vendors. The attack logic is open source and auditable, which helps, but neither should be your only scanner when the system under test is that vendor’s own model.&lt;/p&gt;

&lt;p&gt;Two practices make whichever stack you pick actually pay off. First, run it against a test double, not only production; we covered &lt;a href="https://www.tigera.io/blog/how-to-stub-llms-for-ai-agent-security-testing-and-governance/" rel="noopener noreferrer"&gt;how to stub LLMs&lt;/a&gt; for exactly this, so you can exercise the agent’s authority paths deterministically. Second, file every confirmed agentic finding as two tickets: one for the prompt, one for the policy that makes the prompt’s failure survivable. If your enforcement point logs its decisions, the audit trail becomes your regression oracle. The next scan shouldn’t just show the attack failing; it should show the gateway denying it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;AI red team agents automate adversarial testing at a scale no human program matches, and the market consolidated fast: OpenAI bought Promptfoo, Cisco and Microsoft ship attack suites, and OWASP now tracks the category quarterly.&lt;/li&gt;
&lt;li&gt;The agentic findings share one anatomy: the agent was persuaded, and the environment obeyed. Persuasion varies infinitely. Obedience is the constant you can actually fix.&lt;/li&gt;
&lt;li&gt;Prompt patches decay with every model update, which is why the vendors themselves sell continuous regression testing. Policy enforced in the environment doesn’t decay with the model.&lt;/li&gt;
&lt;li&gt;Translate findings into runtime controls: per-request authorization, human approval holds on dangerous tools, identity-scoped access, and detection for the agents you didn’t know you had.&lt;/li&gt;
&lt;li&gt;Buy the red team. Build the enforcement. They are complements, and neither substitutes for the other.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Back to the fifty bots. What they had in common was not a worse model or a lazier system prompt than the five survivors. It was that persuasion and permission were the same thing: once the agent was convinced, nothing else got a vote. Your next red team report will show you where that’s true in your own stack. When it does, which findings will you patch, and which will you enforce?&lt;/p&gt;

&lt;p&gt;The red team finds the words that move your agent. Your runtime decides what moving accomplishes.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Lynx is Tigera’s security and governance platform for AI agents on Kubernetes: identity, policy, detection, and audit for every agent in your cluster. Read &lt;a href="https://www.tigera.io/blog/how-lynx-works-a-technical-walkthrough/" rel="noopener noreferrer"&gt;How Lynx Works&lt;/a&gt; or request access at &lt;a href="http://tigera.io/demo/?product=lynx" rel="noopener noreferrer"&gt;tigera.io/demo/&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.tigera.io/tigera-products/lynx/" rel="noopener noreferrer"&gt;Learn more about Lynx →&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://www.tigera.io/blog/ai-red-team-agents-automate-attacks-on-your-ai-agents-runtime-policies-automate-their-defense/" rel="noopener noreferrer"&gt;AI Red Team Agents Automate Attacks on your AI Agents. Runtime Policies Automate their Defense.&lt;/a&gt; appeared first on &lt;a href="https://www.tigera.io" rel="noopener noreferrer"&gt;Tigera – Creator of Calico&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>technicalblog</category>
      <category>aiagentsecurity</category>
      <category>bestpractices</category>
      <category>products</category>
    </item>
    <item>
      <title>You’ve Been Running a Kubernetes Security Model in NSX and Didn’t Even Know It</title>
      <dc:creator>Alister Baroi</dc:creator>
      <pubDate>Mon, 10 Aug 2026 19:19:22 +0000</pubDate>
      <link>https://dev.to/tigeraio/youve-been-running-a-kubernetes-security-model-in-nsx-and-didnt-even-know-it-3l47</link>
      <guid>https://dev.to/tigeraio/youve-been-running-a-kubernetes-security-model-in-nsx-and-didnt-even-know-it-3l47</guid>
      <description>&lt;p&gt;One of the blockers to moving VMs off vSphere and onto Kubernetes is losing NSX and the protection it provides. Security teams that have spent years building out distributed firewall policy look at Kubernetes and are, quite understandably, alarmed by the flat network and the fact that any workload can reach any other by default.&lt;/p&gt;

&lt;p&gt;How will they enforce east-west traffic controls? Will they be able to replicate &lt;a href="https://techdocs.broadcom.com/us/en/vmware-cis/cloud-director/vmware-cloud-director/10-5/-nsxp-10-5/distributed-firewall-service.html" rel="noopener noreferrer"&gt;NSX distributed firewall&lt;/a&gt; rules with the same granularity? What about security groups, tiered policy, and rules that travel with the workload when it moves? These are important questions that must be answered before migration can begin.&lt;/p&gt;

&lt;h2&gt;
  
  
  Migrate vSphere to Kubernetes with microsegmentation intact
&lt;/h2&gt;

&lt;p&gt;Calico addresses vSphere to Kubernetes security concerns with a &lt;a href="https://www.tigera.io/learn/guides/microsegmentation/" rel="noopener noreferrer"&gt;network policy model&lt;/a&gt; that maps directly to key features of the NSX distributed firewall (NSX DFW). Every property NSX DFW users rely on has a direct Calico equivalent: tiered governance, workload-identity enforcement, distributed kernel-level inspection, and dynamic workload grouping. Teams coming from vSphere will recognise the pattern quickly.&lt;/p&gt;

&lt;p&gt;Let’s walk through each one in detail.&lt;/p&gt;

&lt;h3&gt;
  
  
  Distributed Enforcement
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq9ogy5iigy3hdblw52r4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq9ogy5iigy3hdblw52r4.png" alt="Enforcement on the host means better performance and automatic scaling" width="799" height="580"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Enforcement on the host means better performance and automatic scaling&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Traditional firewalls sit at the edge of the network. Traffic between workloads inside the data center has to travel out to that inspection point and back, even if the source and destination are on the same physical host. The NSX distributed firewall takes a different approach: the DFW runs in the kernel of every ESXi host and enforces policy directly at each VM’s network interface, before traffic leaves the VM.&lt;/p&gt;

&lt;p&gt;The practical effect is that inspection happens at the source. A packet from a web server VM headed toward a database VM gets checked right where it originates, not at a central appliance somewhere else on the network. No round trip to a dedicated device. Enforcement scales automatically because it lives on every host alongside the workloads it protects.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.tigera.io/calico-cloud/network-policy/policy-tiers/tiered-policy" rel="noopener noreferrer"&gt;Calico’s enforcement model&lt;/a&gt; is built on the same principle. On each Kubernetes node, Calico enforces policy at every workload’s network interface using eBPF or one of the Linux netfilter-based dataplanes (iptables or nftables). The mechanism differs from VMware’s kernel module, but the position in the stack is the same: enforcement happens before traffic enters or leaves the workload, not at a central inspection point somewhere else in the cluster.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.tigera.io/calico/latest/about/kubernetes-training/about-ebpf" rel="noopener noreferrer"&gt;eBPF&lt;/a&gt; is worth a brief note here. It’s a way of running purpose-built programs inside the Linux kernel without modifying the kernel itself, which means packet inspection and policy decisions happen at a very low level with very little overhead. It’s the same instinct that makes NSX DFW fast: get enforcement as close to the wire as possible.&lt;/p&gt;

&lt;p&gt;The solution scales in the same way as well. Adding a node to the cluster adds enforcement capacity automatically because the enforcer runs on the node rather than as a separate service that all traffic routes through. Enforcement is distributed across every node, so there’s no central chokepoint that the whole cluster’s traffic has to pass through.&lt;/p&gt;

&lt;h3&gt;
  
  
  Workload-attached Policy
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsbpapax3eaeq12hwbe09.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsbpapax3eaeq12hwbe09.png" alt="Policies follow the workloads they secure" width="800" height="668"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Policies follow the workloads they secure&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When a VM migrates between hosts via &lt;a href="https://techdocs.broadcom.com/us/en/vmware-cis/vsphere/vsphere/8-0/vcenter-and-host-management/migrating-virtual-machines-host-management/migration-with-vmotion-host-management.html" rel="noopener noreferrer"&gt;vMotion&lt;/a&gt;, its firewall rules move with it. The policy is attached to the workload, not the host. This is a consequential architectural choice: you can’t accidentally leave a workload unprotected by moving it to a new host with different configurations in place.&lt;/p&gt;

&lt;p&gt;It also exposes a problem with IP-based firewall rules that becomes obvious the moment workloads start moving. Rules written against specific addresses are tied to a network location, not the workload itself. If a VM changes address after migration, those rules no longer cover it. NSX DFW avoids this by anchoring policy to security group membership instead, and security groups can be built around tags rather than addresses. A VM tagged “web-tier” carries that group membership with it regardless of which host it lands on or what IP it holds. The rule that applies to web-tier VMs follows automatically, with nothing to update.&lt;/p&gt;

&lt;p&gt;This is exactly how Kubernetes and &lt;a href="https://docs.tigera.io/calico-enterprise/latest/network-policy/" rel="noopener noreferrer"&gt;Calico network policies&lt;/a&gt; also work. Rules are declared against label selectors. When a workload moves to a different node, its labels move with it and the policy selector picks it up automatically. Nothing IP-specific lives in the policy, so there’s nothing to update when an address changes. A VM labeled &lt;code&gt;env: production&lt;/code&gt; and &lt;code&gt;tier: database&lt;/code&gt; picks up the right policies wherever it lands. No external mechanism needs to track it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tiered Precedence
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnvnmwcy7hn6e4cocgnzm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnvnmwcy7hn6e4cocgnzm.png" alt="Microsegmentation allows for granular control and a separation of concerns" width="800" height="463"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Microsegmentation allows for granular control and a separation of concerns&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;NSX also has a tiered policy model. Rules are organized into named categories with a fixed evaluation order. Emergency and quarantine rules sit at the top, infrastructure and shared service rules in the middle, and application-level rules at the bottom. Traffic is evaluated against each category in sequence, top down. A deny rule in the highest category stops evaluation immediately. Nothing below it applies.&lt;/p&gt;

&lt;p&gt;The category structure is also where access control is enforced. NSX’s role-based access control can be scoped to specific policy categories. The evaluation order and the permission model are designed to align. Teams with the narrowest access work in the categories that run last, and no rule they write can override a higher category.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.tigera.io/calico-enterprise/latest/network-policy/policy-tiers/" rel="noopener noreferrer"&gt;Calico tiers&lt;/a&gt; are designed according to the same principles. Each tier is a Kubernetes resource with an order field, a number that determines where it sits in the evaluation sequence. Lower numbers run first. A tier with order 100 is evaluated before a tier with order 200, and a deny rule in the first tier cannot be overridden by anything in the second.&lt;/p&gt;

&lt;p&gt;Unlike NSX’s fixed category names, Calico tiers are user-defined. You name them to match your own operational model, such as “security,” “platform,” “application”, and you set the ordering. You can define as many tiers as your use cases require. Most teams structure their tiers so the security team’s policies run first, platform or infrastructure policies run second, and application or namespace-level policies run last.&lt;/p&gt;

&lt;p&gt;Within each tier, individual policies also carry an order field, and within each policy rules are evaluated top to bottom with the first match applying. One useful behaviour worth knowing about is the pass action: a rule can explicitly pass traffic to the next tier rather than allowing or denying it. This lets each tier focus on what it’s responsible for and hand off everything else cleanly, rather than requiring every tier to have an opinion on every packet. The security tier, for example, should not have to worry about whether a specific frontend should be able to talk to a certain backend service.&lt;/p&gt;

&lt;p&gt;For access control, Calico uses Kubernetes-native RBAC. ClusterRoles and ClusterRoleBindings govern access to cluster-scoped resources like tiers and GlobalNetworkPolicy, while Roles and RoleBindings can be used for namespace-scoped NetworkPolicy. Either way, teams can be restricted to working within their own scope with no ability to reach into tiers or namespaces they don’t own.&lt;/p&gt;

&lt;h3&gt;
  
  
  Attribute-based Identity
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgwzitmyqdyxnrmp50d94.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgwzitmyqdyxnrmp50d94.png" alt="Policies are not IP dependant" width="800" height="441"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Policies are not IP dependant&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;NSX uses tags for dynamic workload grouping. Tags are key-value pairs applied to VMs. You can set them manually through NSX Manager or via API, which means they can be applied at deployment time rather than added by hand after the fact. Security groups define their membership through tag-matching criteria, and that membership is live: any VM carrying the right tag combination joins the group immediately.&lt;/p&gt;

&lt;p&gt;Tagging a VM as “PCI-in-scope” isn’t just a label. It’s a trigger. The moment that tag is applied, the VM joins every security group whose membership rule matches it, and every DFW policy targeting those groups immediately covers the new member. No change request, no waiting. The policy was already written; the workload just identified itself as falling within its scope.&lt;/p&gt;

&lt;p&gt;The same logic works on decommission. When a tag is removed, the VM leaves the group and the rules that covered it stop applying. Orphaned firewall rules accumulating over years of manual changes are a genuine operational hazard in IP-based environments — tags sidestep the problem entirely because security group membership reflects the actual state of the environment, not a record of past changes nobody got around to cleaning up.&lt;/p&gt;

&lt;p&gt;No manual list maintenance. No IP tracking. The tag is the identity.&lt;/p&gt;

&lt;p&gt;NSX tags map to Kubernetes labels, and the mechanism works the same way. Labels are key-value pairs defined in a workload’s manifest and applied at deployment. A &lt;a href="https://docs.tigera.io/calico-enterprise/latest/network-policy/policy-tiers/policy-tutorial-ui" rel="noopener noreferrer"&gt;Calico network policy&lt;/a&gt; references them through a selector: &lt;code&gt;compliance: pci&lt;/code&gt; in a label is picked up by any policy whose selector matches that expression. The moment a workload with that label comes online, it’s covered. No separate step, no group membership to update manually.&lt;/p&gt;

&lt;p&gt;Labels can sit on pods, on namespaces, or on both, which gives you different levels of granularity. A policy that selects on a namespace label applies to everything running in that namespace. A policy that selects on a pod label is more specific. Combining the two lets you write rules like “allow traffic from any workload in the payments namespace that also carries the label &lt;code&gt;tier: web&lt;/code&gt;” — the equivalent of multi-tag security group membership in NSX, expressed as a single selector.&lt;/p&gt;

&lt;p&gt;The decommission property carries over too. When a workload is deleted, its labels go with it. Policies that targeted it stop applying automatically, with no cleanup step and no stale rules accumulating over time.&lt;/p&gt;

&lt;p&gt;For endpoints that can’t carry labels such as external services, legacy VMs not yet migrated, third-party IP ranges, Calico’s NetworkSets handle the case directly. A NetworkSet is a named collection of IP addresses or CIDRs that can be referenced in a policy selector the same way a label can. Rather than repeating IP ranges across every policy that needs them, you reference the NetworkSet by name. When those ranges change, you update the NetworkSet and every policy that references it reflects the change automatically.&lt;/p&gt;

&lt;h2&gt;
  
  
  A demo that went sideways in the best way
&lt;/h2&gt;

&lt;p&gt;A solutions engineer was running a demo for a team evaluating a VMware replacement. They were walking through how Calico enforces network policy when the customer’s senior network consultant stopped them.&lt;/p&gt;

&lt;p&gt;This team had been running NSX-T for years. They had 19 T1 edges and 8 segments. During the walkthrough, the consultant started recognizing what he was looking at. Then he pointed out something that reframed the whole conversation. The T1 edges weren’t actually providing any isolation. The distributed firewall policy was doing all the security work.&lt;/p&gt;

&lt;p&gt;What the consultant recognized was that his team had been operating a flat network with policy enforcement. They’d been using NSX tags to classify workloads and superset policies to establish rule precedence.&lt;/p&gt;

&lt;p&gt;Both of those map directly to Calico constructs which surprised them. The assumption had been that moving from NSX to a Kubernetes-native stack meant leaving the policy model behind. It turned out the policy model was already there. They’d been building towards it without realizing it.&lt;/p&gt;

&lt;p&gt;This is a common pattern. In NSX deployments where the DFW has been built out carefully, the network topology handles connectivity and the policy handles security. The T1 edges are default gateways. The actual security boundary is the DFW rule, not the segment boundary.&lt;/p&gt;

&lt;h2&gt;
  
  
  What works better on the other side
&lt;/h2&gt;

&lt;p&gt;Once policy is running in Calico, a few things improve over the NSX baseline. Compliance monitoring runs continuously and generates audit-ready reports against frameworks like PCI DSS, HIPAA, SOC 2, and NIST. This replaces manual evidence assembly before each audit cycle. Policy changes tracked in version control produce evidence of reviewed, timestamped, and tamper-evident changes. Tiered RBAC means the security team’s rules are structurally unreachable by teams below, with compliance report access scoped so each team sees only what it owns.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this all means in practice
&lt;/h2&gt;

&lt;p&gt;The NSX distributed firewall may feel like one of the hardest components to replicate but it turns out to be the part that transfers most directly, because the architectural decisions behind it, distributed enforcement, workload identity, tiered governance, attribute-based grouping, are the same decisions Calico was built on.&lt;/p&gt;

&lt;p&gt;The team in that demo was genuinely surprised when they recognized their own security model in the Calico policy framework. They’d spent years building a policy structure in NSX that was a close approximation of what Kubernetes-native policy looks like. They’d been moving toward this model without knowing they were doing it.&lt;/p&gt;

&lt;p&gt;If your NSX security posture is built on tags and tiered rules, you’ve been thinking this way for a while. The migration is a translation project. The model is already there.&lt;/p&gt;

&lt;p&gt;Everything covered here has a corresponding configuration reference in the &lt;a href="https://docs.tigera.io/use-cases/microsegmentation" rel="noopener noreferrer"&gt;Calico microsegmentation documentation&lt;/a&gt;. It walks through tier setup, label-based policy, RBAC, and compliance reporting in detail.&lt;/p&gt;

&lt;p&gt;Read our &lt;a href="https://www.tigera.io/lp/ebook-the-complete-guide-to-vm-networking-for-kubernetes/" rel="noopener noreferrer"&gt;migration guide&lt;/a&gt; for a comprehensive look at VM migration.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://www.tigera.io/blog/youve-been-running-a-kubernetes-security-model-in-nsx-and-didnt-even-know-it/" rel="noopener noreferrer"&gt;You’ve Been Running a Kubernetes Security Model in NSX and Didn’t Even Know It&lt;/a&gt; appeared first on &lt;a href="https://www.tigera.io" rel="noopener noreferrer"&gt;Tigera – Creator of Calico&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>technicalblog</category>
      <category>vmmigration</category>
      <category>products</category>
    </item>
    <item>
      <title>The New MCP Headers Are a Gift to Gateways</title>
      <dc:creator>Alister Baroi</dc:creator>
      <pubDate>Thu, 06 Aug 2026 20:52:04 +0000</pubDate>
      <link>https://dev.to/tigeraio/the-new-mcp-headers-are-a-gift-to-gateways-5fn0</link>
      <guid>https://dev.to/tigeraio/the-new-mcp-headers-are-a-gift-to-gateways-5fn0</guid>
      <description>&lt;p&gt;In short, buried in the transport section of the &lt;a href="https://blog.modelcontextprotocol.io/posts/2026-07-28-release-candidate/" rel="noopener noreferrer"&gt;MCP 2026-07-28 release candidate&lt;/a&gt; are three changes that matter more to infrastructure teams than to anyone else: mandatory &lt;code&gt;Mcp-Method&lt;/code&gt; and &lt;code&gt;Mcp-Name&lt;/code&gt; headers, cache-control-style &lt;code&gt;ttlMs&lt;/code&gt; and &lt;code&gt;cacheScope&lt;/code&gt; fields, and standardized W3C Trace Context propagation. Together with the stateless core, they turn MCP from a protocol that gateways had to fight into one that meets them halfway. What the headers still don’t carry: who the caller is, whether the call should be allowed, and any record that it happened.&lt;/p&gt;

&lt;p&gt;Everyone is writing about MCP going stateless, and the coverage is deserved. No handshake, no session ID, any request can hit any server replica, round-robin load balancing just works. If you want the deep dive on what that does to protocol state, my colleague Peter is writing one.&lt;/p&gt;

&lt;p&gt;I want to talk about the part of the release candidate that made me sit up, because I spend my days around a gateway that authorizes agent traffic. It’s three transport changes, a few paragraphs in the announcement, and it fixes a problem every MCP-aware proxy has been engineering around since &lt;a href="https://modelcontextprotocol.io/specification/2025-03-26/changelog" rel="noopener noreferrer"&gt;Streamable HTTP shipped in the 2025-03-26 revision&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem: MCP was opaque at the network layer
&lt;/h2&gt;

&lt;p&gt;To an HTTP intermediary, MCP traffic used to look like nothing. Every operation, whether it listed tools, read a resource, or transferred money, arrived as a POST to the same endpoint. The thing that actually mattered, the JSON-RPC method and the tool being called, sat inside the request body.&lt;/p&gt;

&lt;p&gt;So any middlebox that wanted to treat a &lt;code&gt;tools/list&lt;/code&gt; differently from a &lt;code&gt;tools/call&lt;/code&gt; had one option: buffer the request, parse the JSON-RPC envelope, and make its decision from the body. That works, and it’s what serious MCP gateways do today. But it puts body parsing on the hot path for every request, including the vast majority where a cheaper answer would have sufficed. Rate-limiters, load balancers, and WAFs that can’t parse JSON-RPC at all were simply blind. Layer 7 infrastructure spent thirty years learning to route on methods and paths, and MCP hid both.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mcp-Method and Mcp-Name: Routing without body inspection
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2243" rel="noopener noreferrer"&gt;SEP-2243&lt;/a&gt; fixes this at the obvious place. The Streamable HTTP transport now requires &lt;code&gt;Mcp-Method&lt;/code&gt; and &lt;code&gt;Mcp-Name&lt;/code&gt; headers: &lt;code&gt;Mcp-Method&lt;/code&gt; carries the JSON-RPC method (&lt;code&gt;tools/call&lt;/code&gt;, &lt;code&gt;resources/read&lt;/code&gt;, and so on), and &lt;code&gt;Mcp-Name&lt;/code&gt; carries the operation target, such as the tool name. The announcement states the goal plainly: load balancers, gateways, and rate-limiters can route on the operation without inspecting the body.&lt;/p&gt;

&lt;p&gt;What this unlocks, roughly in order of how quickly teams will use it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Per-tool rate limiting.&lt;/strong&gt; Throttle &lt;code&gt;tools/call&lt;/code&gt; for an expensive tool without touching the cheap ones, in a stock rate-limiter that only reads headers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Operation-aware routing.&lt;/strong&gt; Send &lt;code&gt;resources/read&lt;/code&gt; to read-optimized replicas, or split list-type traffic from call-type traffic entirely.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cheap early denies.&lt;/strong&gt; A policy gateway can reject a request for a tool that no policy could ever allow before parsing a byte of body.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Visibility in existing tooling.&lt;/strong&gt; Access logs, metrics dashboards, and anomaly detection keyed on headers now see MCP operations instead of an undifferentiated stream of POSTs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One design detail deserves attention: servers must reject requests where the headers and the body disagree. That’s what makes the headers usable for real decisions rather than hints. A client can’t advertise &lt;code&gt;tools/list&lt;/code&gt; in the header and smuggle a &lt;code&gt;tools/call&lt;/code&gt; in the body, because the terminating server will refuse it.&lt;/p&gt;

&lt;p&gt;Still, if your gateway makes security decisions, the right way to hold this is defense in depth. The header is a claim the server will eventually verify; the body remains the truth. Fast-deny on headers is always safe, since a mismatch would have been rejected anyway. For the allow path on sensitive operations, an enforcement point should keep parsing the body, both because arguments matter (more on that below) and because “the server behind me validates the invariant my security decision depends on” is a sentence that should make any security engineer reach for their own validation.&lt;/p&gt;

&lt;h2&gt;
  
  
  ttlMs and cacheScope: Caching with permission
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2549" rel="noopener noreferrer"&gt;SEP-2549&lt;/a&gt; gives list results and resource reads two new fields modeled on HTTP &lt;code&gt;Cache-Control: ttlMs&lt;/code&gt; says how long the response stays fresh, and &lt;code&gt;cacheScope&lt;/code&gt; says whether it may be shared across users.&lt;/p&gt;

&lt;p&gt;Gateways have wanted to cache &lt;code&gt;tools/list&lt;/code&gt; forever. Tool catalogs change rarely, agents ask for them constantly, and every wasted round trip adds latency to an agent loop that’s already slow. But caching without server guidance meant guessing, and guessing wrong across users is how one tenant sees another tenant’s tool catalog. &lt;code&gt;cacheScope&lt;/code&gt; makes the safety question explicit, and puts the answer where it belongs: with the server that knows whether the response was personalized.&lt;/p&gt;

&lt;p&gt;If you run a shared MCP gateway in front of internal servers, this is the difference between “we cache nothing because we can’t prove it’s safe” and an actual caching policy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trace context: The audit trail gets standard rails
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/modelcontextprotocol/modelcontextprotocol/pull/414" rel="noopener noreferrer"&gt;SEP-414&lt;/a&gt; documents &lt;a href="https://www.w3.org/TR/trace-context/" rel="noopener noreferrer"&gt;W3C Trace Context&lt;/a&gt; propagation in &lt;code&gt;_meta&lt;/code&gt;, fixing the key names for &lt;code&gt;traceparent&lt;/code&gt;, &lt;code&gt;tracestate&lt;/code&gt;, and &lt;code&gt;baggage&lt;/code&gt;. Every SDK and every gateway now agrees on where trace identity lives in an MCP request.&lt;/p&gt;

&lt;p&gt;This one reads like an observability footnote and is quietly the most important of the three for anyone who cares about accountability. Distributed tracing across agent systems mostly worked if you controlled every hop and configured every SDK the same way. The moment traffic crossed a boundary, a different SDK, a vendor’s server, someone else’s gateway, correlation broke, and your trace of “which agent triggered this tool call” ended mid-sentence.&lt;/p&gt;

&lt;p&gt;With the key names fixed in the spec, a trace can survive the full path: agent to gateway to MCP server and back, across implementations, into any OpenTelemetry-compatible backend. For incident response, that’s the difference between “a tool call failed somewhere” and a single trace showing the agent, the gateway’s authorization decision, and the server’s execution as one causal chain. We’ve written before about why &lt;a href="https://www.tigera.io/blog/the-ai-agent-accountability-gap-why-network-policies-api-gateways-and-rbac-are-not-enough/" rel="noopener noreferrer"&gt;multi-hop correlation is where existing tools fall down&lt;/a&gt;; the spec just removed the excuse at the protocol layer.&lt;/p&gt;

&lt;p&gt;And because the protocol is now stateless, all of this composes. A gateway no longer needs session affinity to keep a conversation coherent, so any proxy replica can handle any request, with the operation in the headers and the trace context in &lt;code&gt;_meta&lt;/code&gt;. The 2026-07-28 revision is the first one that reads like its authors had a load balancer diagram on the wall.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the headers still don’t carry
&lt;/h2&gt;

&lt;p&gt;Here’s the boundary, and it’s the same boundary the &lt;a href="https://www.tigera.io/blog/mcps-auth-hardening-what-the-six-new-oauth-seps-fix-and-what-they-still-dont/" rel="noopener noreferrer"&gt;auth-hardening post&lt;/a&gt; ended on. The new transport tells you what is being asked. It does not tell you three other things.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Who is asking.&lt;/strong&gt; &lt;code&gt;Mcp-Method: tools/call&lt;/code&gt; plus &lt;code&gt;Mcp-Name: transfer_funds&lt;/code&gt; identifies the operation, not the caller. Agent identity has to come from somewhere outside the protocol: mTLS workload identity, a verified token, something the platform issued rather than the process claimed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Whether it should be allowed.&lt;/strong&gt; Headers make policy enforcement cheaper; they don’t supply the policy. “May the finance team’s reporting agent call &lt;code&gt;transfer_funds&lt;/code&gt; with this amount” needs an engine evaluating rules against agent attributes and, for the cases that matter, the arguments in the body. The headers get you to the decision point faster. The decision is still yours.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What happened.&lt;/strong&gt; A cacheable, traceable, header-routed request that no one records is still unaccountable. Trace context gives audit trails standard rails to run on, but something has to actually write the trail, and it can’t be the agent.&lt;/p&gt;

&lt;p&gt;Read those three again. They are the accountability questions, and the transport section answers none of them, correctly, because a transport shouldn’t. But it is exactly the seam where an agent gateway earns its place. Lynx’s gateway sits on this seam today: every request authorized individually against Cedar policy under a SPIFFE workload identity, with the decision recorded in Agent Trail. The new headers make that architecture cheaper to run and easier to integrate, because the proxy can classify traffic before it parses it, and the trace that leaves the gateway now correlates with everything upstream and downstream by default. Protocol changes rarely hand an enforcement plane this much for free.&lt;/p&gt;

&lt;h2&gt;
  
  
  If you run infrastructure in front of MCP, do this
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Update any body-parsing routing or rate-limiting logic to read &lt;code&gt;Mcp-Method&lt;/code&gt; and &lt;code&gt;Mcp-Name&lt;/code&gt; first, and keep body validation on the security-sensitive allow path.&lt;/li&gt;
&lt;li&gt;Audit your caching layer against &lt;code&gt;cacheScope&lt;/code&gt; semantics before enabling cross-user caching of list results. The field tells you when sharing is safe; honor it.&lt;/li&gt;
&lt;li&gt;Wire &lt;code&gt;traceparent&lt;/code&gt; propagation through your proxy now, while the SDKs are shipping support inside the ten-week validation window. Correlation only works if every hop plays.&lt;/li&gt;
&lt;li&gt;Test against the release candidate before July 28. Servers rejecting header/body mismatches is a new failure mode your clients need to handle.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Key takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;SEP-2243 puts the MCP operation in HTTP headers, so gateways, load balancers, and rate-limiters can act on MCP traffic without parsing JSON-RPC bodies. Servers enforce header/body agreement.&lt;/li&gt;
&lt;li&gt;SEP-2549 adds &lt;code&gt;ttlMs&lt;/code&gt; and &lt;code&gt;cacheScope&lt;/code&gt;, making response caching a documented contract instead of a guess, including whether cross-user sharing is safe.&lt;/li&gt;
&lt;li&gt;SEP-414 standardizes W3C Trace Context in &lt;code&gt;_meta&lt;/code&gt;, so traces survive multi-hop, multi-implementation agent systems end to end.&lt;/li&gt;
&lt;li&gt;The transport now tells intermediaries what is being asked. Identity, authorization, and audit remain the gateway’s job, and the protocol just made that job considerably cheaper to do well.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The headers tell you what is being asked. Your gateway decides whether it’s allowed. Your audit trail proves what happened. The spec just handed you the first one for free; the other two are still yours to build, and they were always the hard part.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Lynx is Tigera’s security and governance platform for AI agents on Kubernetes: identity, policy, detection, and audit for every agent in your cluster. Read &lt;a href="https://www.tigera.io/blog/how-lynx-works-a-technical-walkthrough/" rel="noopener noreferrer"&gt;How Lynx Works&lt;/a&gt; or request early access at &lt;a href="https://www.tigera.io/demo/?product=lynx" rel="noopener noreferrer"&gt;tigera.io/demo/&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Identity, authorization, and audit are the part the transport leaves to you — and the part that’s hardest to get right. Our whitepaper, &lt;em&gt;Securing AI Agents on Kubernetes using Tigera Lynx&lt;/em&gt;, walks through how to build all three. &lt;a href="https://www.tigera.io/lp/whitepaper-securing-ai-agents-on-kubernetes-using-tigera-lynx/" rel="noopener noreferrer"&gt;Read the whitepaper →&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://www.tigera.io/blog/the-new-mcp-headers-are-a-gift-to-gateways/" rel="noopener noreferrer"&gt;The New MCP Headers Are a Gift to Gateways&lt;/a&gt; appeared first on &lt;a href="https://www.tigera.io" rel="noopener noreferrer"&gt;Tigera – Creator of Calico&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>technicalblog</category>
      <category>aiagentsecurity</category>
      <category>products</category>
    </item>
    <item>
      <title>VM Migration – What Happens to Your NSX Segments in Kubernetes?</title>
      <dc:creator>Alister Baroi</dc:creator>
      <pubDate>Wed, 05 Aug 2026 19:39:40 +0000</pubDate>
      <link>https://dev.to/tigeraio/vm-migration-what-happens-to-your-nsx-segments-in-kubernetes-30a2</link>
      <guid>https://dev.to/tigeraio/vm-migration-what-happens-to-your-nsx-segments-in-kubernetes-30a2</guid>
      <description>&lt;p&gt;Planning a migration off NSX usually starts with a networking conversation. Segments, VLANs, routing topology and BGP peering are not things that map cleanly to Kubernetes-native constructs the way the NSX distributed firewall maps to Calico’s tiered microsegmentation. NSX virtualizes the network layer in ways that Kubernetes doesn’t replicate by default. There is no native concept of a Layer 2 segment or VLAN, for instance. Pods simply receive IP addresses on a flat, routed network, with no built-in way to give a workload L2 adjacency to external devices or attach it to a specific broadcast domain.&lt;/p&gt;

&lt;p&gt;This is usually where teams start to worry. They can see exactly what NSX is doing for them, but they have no obvious Kubernetes equivalent to point at. The natural question becomes how they will run the networking they depend on once their VMs live in a cluster.&lt;/p&gt;

&lt;p&gt;Achieving the same routing, isolation, and connectivity outcomes, however, is well within reach. It just requires a bit of a mental shift.&lt;/p&gt;

&lt;p&gt;The rest of this blog will cover the details of what that mental shift entails.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F190mo9lmc99mu74a0kvc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F190mo9lmc99mu74a0kvc.png" alt="Each NSX construct and the Calico building block that takes over its job." width="800" height="507"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Each NSX construct and the Calico building block that takes over its job.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How NSX handles segments
&lt;/h2&gt;

&lt;p&gt;Before we get into recreating NSX networking outcomes for VMs in Kubernetes, let’s set the stage by looking at what it is we are trying to recreate.&lt;/p&gt;

&lt;p&gt;NSX is a network virtualization platform that creates software-defined networks (switching, routing, firewalling, load balancing) in a layer that runs on top of existing physical networks. It allows you to provision and segment networks programmatically without reconfiguring switches or routers.&lt;/p&gt;

&lt;p&gt;The building block in all of this is the segment, the logical network a workload attaches to. A segment is not one fixed thing. How it behaves depends on how it is designed. It can be backed by an overlay or tied to a physical VLAN. It reaches the rest of the network either by routing through a Tier-1 gateway or by being advertised externally through a Tier-0 gateway. The backing type is what matters most when you move workloads to Kubernetes, so the two are worth looking at on their own.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;VLAN-backed segments&lt;/strong&gt; connect to a physical VLAN tag. VMs have L2 adjacency to anything on that VLAN, including physical servers and external devices. The traffic follows the physical VLAN.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Overlay segments&lt;/strong&gt; use encapsulation to tunnel L2 frames across a routed underlay, decoupling logical topology from physical VLANs entirely. VMs on the same overlay segment see a flat L2 domain regardless of which hosts they’re on.&lt;/p&gt;

&lt;p&gt;Both types give VMs an IP address, a default gateway, a broadcast domain, and a network identity the rest of the infrastructure can interpret.&lt;/p&gt;

&lt;h2&gt;
  
  
  How each segment type maps to Calico
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Overlay segments&lt;/strong&gt; are the straightforward case. The NSX overlay model, encapsulating L2 traffic and carrying it across a routed underlay, is the same architectural pattern &lt;a href="https://docs.tigera.io/calico/latest/networking/configuring/vxlan-ipip" rel="noopener noreferrer"&gt;Calico uses for its default pod network, with VXLAN or IP-in-IP as the encapsulation format&lt;/a&gt;. VMs and pods communicate across nodes as if they shared a flat L2 domain, the physical network carries UDP, and the details are handled below the application layer. For workloads that were on NSX overlay segments and have no hard dependencies on specific VLANs or IP ranges, the migration to Calico pod networking is largely mechanical. There is nothing to configure specifically for the overlay. It is the default.&lt;/p&gt;

&lt;p&gt;There is one real difference behind that smooth mapping, and it is worth understanding before you migrate. An NSX overlay segment gives workloads a true Layer 2 domain. Calico’s pod network looks flat to the application, but traffic between nodes is actually routed at Layer 3. For almost everything, that distinction never surfaces. The exception is any application that leans on Layer 2 broadcast or multicast to discover its peers, such as some older clustering protocols. Those are the ones to identify up front rather than after the move.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;VLAN-backed segments&lt;/strong&gt; are where most migration discussions get complicated, and they are often the most common case, because moving off them takes time and effort that teams under pressure rarely have. A VLAN-backed segment is not just a network assignment. It often carries compliance scope, upstream firewall rules, and IP ranges that legacy systems have relied on for years. Telling a security team that the PCI VLAN is going away requires evidence that the workload’s regulatory scope is preserved by some other mechanism. Telling an external system to update its allowlist requires coordination and change windows. These are organizational constraints as much as technical ones.&lt;/p&gt;

&lt;p&gt;Calico’s answer for environments where VMs need to stay on their VLANs is &lt;a href="https://www.tigera.io/blog/lift-and-shift-vms-to-kubernetes-with-calico-l2-bridge-networks/" rel="noopener noreferrer"&gt;L2 Bridge mode&lt;/a&gt;, configured through a Calico Network resource. It stretches your existing VLAN into the Kubernetes cluster the VM now runs in, so that as far as your network is concerned, the VM is still in its old home with all its dependencies intact. Calico creates a bridge on each cluster node and connects it to the VLAN trunk on the node’s NIC, then attaches the VM to that bridge through an additional interface. The VM sees the same VLAN it was on before the migration. It keeps its IP address. It keeps its MAC address. From the perspective of the upstream switch, the firewall, and any external system talking to that VM, nothing moved.&lt;/p&gt;

&lt;p&gt;The implementation is different but the outcome is the same. Your migrated VM runs on the same VLAN it always did, with the added advantage of now treating your infrastructure as code, with all the version control and management consistency that brings.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkieb0k1ivi61ea6q9d9p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkieb0k1ivi61ea6q9d9p.png" alt="A VLAN-backed segment becomes a Calico L2 Bridge, so the VM keeps its VLAN, IP, and MAC." width="800" height="480"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;A VLAN-backed segment becomes a Calico L2 Bridge, so the VM keeps its VLAN, IP, and MAC.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What about my subnets?
&lt;/h2&gt;

&lt;p&gt;NSX has something called a Tier-1 gateway. It is not a subnet, though it is the closest thing to the gateway behind one. It is the routing tier that segments attach to, and it does a few jobs: it provides the default gateway for workloads on those segments, routes between them and upward toward the Tier-0, keeps tenants isolated at the routing layer, and can hand a workload a fixed source IP via SNAT for allowlisting.&lt;/p&gt;

&lt;p&gt;In Calico, none of this is a single appliance. The IP ranges those segments carried map to the &lt;a href="https://docs.tigera.io/calico/latest/reference/resources/ippool" rel="noopener noreferrer"&gt;IPPool&lt;/a&gt;, the custom resource that defines the CIDRs workloads draw from. The default gateway needs no equivalent: every node already routes for the workloads it hosts, so the T1’s routing simply happens on the nodes. Connectivity between workloads and out to the physical network rides Calico’s own routing instead of a gateway in the path.&lt;/p&gt;

&lt;p&gt;Route isolation, where a T1 keeps one tenant’s routes out of another’s, is handled in Calico Enterprise by &lt;a href="https://www.tigera.io/blog/deep-dive/multi-vrf-support-for-egress-gateways-using-calico/" rel="noopener noreferrer"&gt;Multi-VRF&lt;/a&gt;, implemented through a custom resource called &lt;a href="https://docs.tigera.io/calico-enterprise/latest/reference/resources/externalnetwork" rel="noopener noreferrer"&gt;ExternalNetworks&lt;/a&gt;. Each ExternalNetwork is an independent routing table on the node with its own BGP peering, so routes in one domain stay invisible to another. It is the tool for cases a single routing table cannot handle, such as reaching external services with overlapping address ranges.&lt;/p&gt;

&lt;p&gt;So the Tier-1 equivalent is not one thing you deploy. It is a combination of an IPPool, per-node routing, Multi-VRF where isolation is required, and policy. That is a real shift in thinking, and it works in your favor: no appliance to size, patch, or treat as a single point of failure, routing that scales with the cluster, and every piece a declarative, version-controlled Kubernetes resource rather than a separate box to keep in sync.&lt;/p&gt;

&lt;h2&gt;
  
  
  Connecting a segment to the outside world
&lt;/h2&gt;

&lt;p&gt;The NSX Tier-0 gateway is the border between the NSX overlay and the physical network. Its main job is &lt;a href="https://docs.tigera.io/calico/latest/networking/configuring/bgp" rel="noopener noreferrer"&gt;BGP peering&lt;/a&gt; with the top-of-rack switches, advertising the overlay subnets into the physical routing fabric so the rest of the data center knows how to reach NSX-hosted workloads. It is also the exit point for traffic leaving the fabric entirely. The T0 usually runs on a dedicated edge node or edge cluster, often as an active and standby pair, which makes it a concentration point for all north-south traffic. NAT and edge firewalling are T0 functions too, and those can be saved for a follow-up post.&lt;/p&gt;

&lt;p&gt;In Calico, that routing role moves directly onto the cluster nodes. Each node runs a BGP daemon (BIRD) and peers with the physical switching infrastructure through the BGPPeer custom resource, which specifies the peer address, the AS number, and, through a node selector, which nodes participate. Calico advertises pod and VM CIDRs into the fabric exactly as the T0 advertised the overlay subnets. The switches learn routes to cluster workloads and forward to them with no extra configuration on the physical side.&lt;/p&gt;

&lt;p&gt;At scale you do not peer every node with every switch. Calico supports BGP route reflectors, where a small set of nodes hold the peerings and the rest peer with them. This keeps the number of sessions manageable as the cluster grows. Either way, the T0 appliance goes away and the function it performed is distributed across the nodes.&lt;/p&gt;

&lt;p&gt;As with the Tier-1, this is a shift from a box to a behavior, and the trade works in your favor. There is no edge appliance pair to size or fail over, north-south routing no longer funnels through a single concentration point, and capacity scales as you add nodes. The peering itself is declarative which again means that the BGPPeer resource lives in version control and is reviewed like any other part of the cluster.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftk7fdkgo98fcjccs9o8x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftk7fdkgo98fcjccs9o8x.png" alt="The Tier-0 BGP and the Tier-1 routing distribute across the cluster nodes." width="800" height="411"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The Tier-0 BGP and the Tier-1 routing distribute across the cluster nodes.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What this means in practice
&lt;/h2&gt;

&lt;p&gt;The networking layer is where a migration off NSX looks most different. The segment topology, the gateway appliances, and the BGP configuration do not have one-to-one equivalents on the Kubernetes side, and the first look can be unsettling.&lt;/p&gt;

&lt;p&gt;What carries over is the logic underneath. Overlay segments become Calico pod networking with no special configuration. VLAN-backed segments map to L2 Bridge Networks, so a VM keeps its VLAN, its IP, and its MAC through the move. The T0’s BGP peering moves to the cluster nodes through the BGPPeer resource, and the T1’s routing is absorbed into per-node routing with nothing dedicated to replace it. Where separate routing tables are genuinely needed, Calico Enterprise’s Multi-VRF provides that isolation without a gateway appliance.&lt;/p&gt;

&lt;p&gt;The shape changes but the outcomes do not. Once you stop looking for the appliance and start looking at what it was actually doing, most NSX topologies carry fewer hard dependencies than they first appear, and each of those jobs has a Kubernetes-native home that is declarative, version-controlled, and scales with the cluster. The practical next step is to map your own environment the same way. List what each segment and gateway is really providing. Once that list exists, the Calico equivalents are usually easy to identify. That requirements audit is where most migrations should start, and it is a good conversation to have before the first VM moves.&lt;/p&gt;

&lt;p&gt;If you want to go further, check our our ebook: &lt;a href="https://www.tigera.io/lp/ebook-calico-enterprise-for-nsx-administrators/" rel="noopener noreferrer"&gt;Calico Enterprise for NSX Administrators&lt;/a&gt;. And when you are ready to try the mapping yourself, you can request a Calico Enterprise trial license.&lt;/p&gt;

&lt;p&gt;Ready to migrate VM-centric architectures to Kubernetes platforms? Read our ebook, &lt;a href="https://www.tigera.io/lp/ebook-calico-enterprise-for-nsx-administrators/" rel="noopener noreferrer"&gt;Calico Enterprise for NSX Administrators&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://www.tigera.io/blog/vm-migration-what-happens-to-your-nsx-segments-in-kubernetes/" rel="noopener noreferrer"&gt;VM Migration – What Happens to Your NSX Segments in Kubernetes?&lt;/a&gt; appeared first on &lt;a href="https://www.tigera.io" rel="noopener noreferrer"&gt;Tigera – Creator of Calico&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>technicalblog</category>
      <category>bestpractices</category>
      <category>vmmigration</category>
      <category>products</category>
    </item>
    <item>
      <title>MCP’s Auth Hardening: What the Six New OAuth SEPs Fix, and What They Still Don’t</title>
      <dc:creator>Alister Baroi</dc:creator>
      <pubDate>Tue, 28 Jul 2026 14:20:20 +0000</pubDate>
      <link>https://dev.to/tigeraio/mcps-auth-hardening-what-the-six-new-oauth-seps-fix-and-what-they-still-dont-2g0c</link>
      <guid>https://dev.to/tigeraio/mcps-auth-hardening-what-the-six-new-oauth-seps-fix-and-what-they-still-dont-2g0c</guid>
      <description>&lt;p&gt;In short, the &lt;a href="https://blog.modelcontextprotocol.io/posts/2026-07-28-release-candidate/" rel="noopener noreferrer"&gt;MCP 2026-07-28 release candidate&lt;/a&gt; is getting attention for going stateless. The quieter story is a package of six SEPs that harden the protocol’s OAuth layer: issuer validation, credential binding, client type declaration, and cleanups around refresh tokens, scopes, and discovery. All six are worth shipping, and all six fix real failure modes. But they harden how a client authenticates to a server, and that was never the whole problem. Agent identity, per-request authorization, delegation, and audit still sit outside the spec. Which means they still sit with you.&lt;/p&gt;

&lt;p&gt;The stateless core is soaking up most of the commentary on the new MCP release candidate, and fair enough: deleting the &lt;code&gt;initialize&lt;/code&gt; handshake and the session ID changes how everyone deploys. But scroll past that section of the announcement and you hit six SEPs of authorization hardening that almost nobody is writing about. That’s a mistake. If you operate MCP servers that hold real credentials, this is the part of the spec that decides whether a confused client hands a token to the wrong party.&lt;/p&gt;

&lt;p&gt;The final spec ships July 28, 2026. The release candidate was locked on May 21, and SDK maintainers are in a ten-week validation window now. So this is a good moment to read the auth changes carefully: late enough that they’re stable, early enough to fix your implementation before the ecosystem expects it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why MCP keeps having to fix auth
&lt;/h2&gt;

&lt;p&gt;MCP inverts the deployment shape OAuth grew up with. Classic OAuth has many clients talking to one authorization server: thousands of apps, one identity provider, one token issuer. MCP runs the other way around. One client, the host application, talks to many servers, each potentially fronted by a different authorization server, discovered at runtime, and often registered on the fly through Dynamic Client Registration.&lt;/p&gt;

&lt;p&gt;That inversion is where the bugs live. The spec authors say it directly: the issuer validation SEP targets “a class of mix-up attack that is more prevalent in MCP’s single-client, many-server deployment pattern.” When your client holds registrations with a dozen authorization servers at once, an attacker doesn’t need to break the crypto. They need to get your client to attribute a response to the wrong server.&lt;/p&gt;

&lt;p&gt;This isn’t the first pass at the problem. The &lt;a href="https://modelcontextprotocol.io/specification/2025-06-18/changelog" rel="noopener noreferrer"&gt;2025-06-18 revision&lt;/a&gt; made Resource Indicators (&lt;a href="https://www.rfc-editor.org/rfc/rfc8707.html" rel="noopener noreferrer"&gt;RFC 8707&lt;/a&gt;) mandatory so tokens are minted for one specific server rather than floating around as bearer credentials any resource might accept. The 2026-07-28 package continues that trajectory: less trust by default, more explicit binding.&lt;/p&gt;

&lt;h2&gt;
  
  
  The six SEPs, grouped by what they protect
&lt;/h2&gt;

&lt;p&gt;The release notes list six SEPs. They cluster into three jobs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Knowing which server you’re actually talking to
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://modelcontextprotocol.io/seps/2468-recommend-issuer-claim-for-auth" rel="noopener noreferrer"&gt;SEP-2468&lt;/a&gt; brings &lt;a href="https://www.rfc-editor.org/rfc/rfc9207.html" rel="noopener noreferrer"&gt;RFC 9207&lt;/a&gt; into MCP: authorization servers include an explicit &lt;code&gt;iss&lt;/code&gt; parameter in authorization responses, and clients that see it must validate it. If the issuer in the response doesn’t match the issuer the client thinks it’s mid-flow with, the client rejects the response. That closes the mix-up attack above. Today including the parameter is recommended rather than required, but the spec is explicit that in a future version clients will be expected to reject responses that omit &lt;code&gt;iss&lt;/code&gt;, so treat it as mandatory in anything you build now.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2352" rel="noopener noreferrer"&gt;SEP-2352&lt;/a&gt; fixes the other half of the same confusion. Clients must keep separate registration state per authorization server and bind each registered credential to the issuing server’s &lt;code&gt;issuer&lt;/code&gt; value. If a resource migrates from one authorization server to another, the client re-registers rather than replaying credentials issued by the old server against the new one. Before this, a client could quietly present a client ID minted by issuer A to issuer B, and depending on the server’s tolerance, sometimes it worked. “Sometimes it worked” is not a property you want in an auth system.&lt;/p&gt;

&lt;h3&gt;
  
  
  Telling the authorization server what kind of client you are
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/modelcontextprotocol/modelcontextprotocol/pull/837" rel="noopener noreferrer"&gt;SEP-837&lt;/a&gt; is small and will quietly fix a failure everyone building a local MCP client has hit. Clients now declare their OpenID Connect &lt;code&gt;application_type&lt;/code&gt; during Dynamic Client Registration. Without it, authorization servers commonly default a desktop or CLI client to &lt;code&gt;web&lt;/code&gt; and then reject its &lt;code&gt;localhost&lt;/code&gt; redirect URI, because web clients aren’t supposed to redirect to localhost. The result was a class of registration failures that looked like server bugs but were really a missing field. If you’ve ever watched a CLI tool fail OAuth registration against a strict identity provider for no visible reason, this SEP is for you.&lt;/p&gt;

&lt;h3&gt;
  
  
  Housekeeping that removes guesswork
&lt;/h3&gt;

&lt;p&gt;The remaining three SEPs are clarifications, and clarifications in auth specs matter more than they sound. &lt;a href="https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2207" rel="noopener noreferrer"&gt;SEP-2207&lt;/a&gt; documents how to request refresh tokens from OpenID Connect style authorization servers, which implementers previously handled with folklore and copy-paste. &lt;a href="https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2350" rel="noopener noreferrer"&gt;SEP-2350&lt;/a&gt; pins down scope accumulation during step-up authentication, so a client that goes back for more scopes knows what happens to the ones it already has. &lt;a href="https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2351" rel="noopener noreferrer"&gt;SEP-2351&lt;/a&gt; clarifies the &lt;code&gt;.well-known&lt;/code&gt; discovery suffix behavior, which sounds cosmetic until two SDKs disagree about where the metadata document lives and interop breaks.&lt;/p&gt;

&lt;p&gt;Here’s the package in one view:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;SEP&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;What it requires&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Failure it prevents&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;2468&lt;/td&gt;
&lt;td&gt;Validate &lt;code&gt;iss&lt;/code&gt; on authorization responses (RFC 9207)&lt;/td&gt;
&lt;td&gt;Mix-up attacks across multiple authorization servers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2352&lt;/td&gt;
&lt;td&gt;Bind registered credentials to their issuer; re-register on migration&lt;/td&gt;
&lt;td&gt;Credential replay against the wrong authorization server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;837&lt;/td&gt;
&lt;td&gt;Declare &lt;code&gt;application_type&lt;/code&gt; during Dynamic Client Registration&lt;/td&gt;
&lt;td&gt;Desktop/CLI clients rejected over localhost redirect URIs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2207&lt;/td&gt;
&lt;td&gt;Documented refresh token flow for OIDC-style servers&lt;/td&gt;
&lt;td&gt;Divergent, improvised token renewal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2350&lt;/td&gt;
&lt;td&gt;Defined scope accumulation in step-up flows&lt;/td&gt;
&lt;td&gt;Ambiguity about previously granted scopes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2351&lt;/td&gt;
&lt;td&gt;Clarified &lt;code&gt;.well-known&lt;/code&gt; discovery suffix&lt;/td&gt;
&lt;td&gt;Metadata discovery interop failures&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If you maintain an MCP client or server, the work here is real but bounded, and the Tier 1 SDKs are expected to ship support within the validation window. Adopt it all. None of it is controversial.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the six SEPs still don’t touch
&lt;/h2&gt;

&lt;p&gt;Now the part I actually want to talk about. Read the package again and notice what every one of these SEPs has in common: they harden the exchange between one OAuth client and one authorization server. That exchange needed hardening. But if you’re responsible for a production deployment of agents, it’s worth being precise about the questions this spec revision does not answer, because the gap between “OAuth done right” and “agents governed” is where incidents happen. We mapped that gap in the &lt;a href="https://www.tigera.io/blog/the-ai-agent-accountability-gap-why-network-policies-api-gateways-and-rbac-are-not-enough/" rel="noopener noreferrer"&gt;accountability gap post&lt;/a&gt;; the new spec moves none of these boundaries.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The token authenticates the client, not the agent&lt;/strong&gt;. In MCP’s OAuth model, the thing holding the credential is the host application. The agent, the actual decision-making process that chose to call the tool, has no identity of its own anywhere in the flow. Two hundred agents behind one host share one client identity. When a token is misused, “which client” has an answer and “which agent, on whose behalf, deciding on the basis of what” does not. Issuer binding makes the client-to-server link trustworthy; it says nothing about what’s behind the client.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scopes are not policy&lt;/strong&gt;. OAuth answers admission: does this client get a token for this server. It does not answer the per-request question: should this agent be allowed to call this tool, with these arguments, right now. A scope like &lt;code&gt;mcp:tools&lt;/code&gt; is a key to the building, not a rule about what you may do inside. Real deployments need decisions at the level of “the finance team’s reporting agent may call &lt;code&gt;read_ledger&lt;/code&gt; but never &lt;code&gt;transfer_funds&lt;/code&gt;, and never with an amount above X.” Nothing in this spec revision, or any planned one, evaluates that.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Delegation chains vanish&lt;/strong&gt;. Agents call agents, which call MCP servers. Each hop can be individually OAuth-clean while the chain as a whole is unaccountable: the server at the end sees a valid token from its immediate caller and nothing else. Who initiated the chain, under whose authority, through which intermediaries? The protocol doesn’t carry that provenance, and hardened issuer validation doesn’t create it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nobody is required to write anything down&lt;/strong&gt;. All six SEPs make the authorization decision more trustworthy. None of them require a record of the decision. When your compliance team asks “was this tool call authorized by policy, and which policy,” a perfectly spec-compliant deployment gives you nothing. The spec is silent on audit, deliberately: it’s a protocol, not a governance framework. That’s the correct scoping decision for a protocol. It just means the governance framework has to come from somewhere else.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fleet scale multiplies all of it&lt;/strong&gt;. One client and many servers is the spec’s model. An enterprise runs many clients and many servers: N agents times M servers, each pair needing registration, each registration now correctly issuer-bound. With ten agents you can manage that by hand. With a hundred you have a spreadsheet nobody trusts. With a thousand, you need a registry, and the spec has no opinion about registries, or about noticing the agent that never registered at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hardened plumbing still needs governance
&lt;/h2&gt;

&lt;p&gt;None of this is a criticism of the SEPs. Protocol specs should be narrow, and this package does exactly what a protocol revision should: it makes the mechanics harder to get wrong. MCP without issuer validation was HTTP without certificate checking; now that hole is closing.&lt;/p&gt;

&lt;p&gt;But the pattern to notice is that every question the spec leaves open is a question the agent could answer dishonestly if you ask the agent. Which agent are you? What are you allowed to do? Who told you to do this? The only place those answers stay trustworthy is in the environment around the agent: workload identity issued by the platform rather than claimed by the process, policy evaluated per request at a gateway the traffic can’t bypass, and an audit trail written by the infrastructure rather than the workload. That’s the argument we’ve been making since &lt;a href="https://www.tigera.io/blog/why-we-built-lynx-bringing-control-to-the-age-of-ai-agents/" rel="noopener noreferrer"&gt;Why We Built Lynx&lt;/a&gt;, and it’s how Lynx is built: SPIFFE-based identity per agent, Cedar policy evaluated on every request, and a decision trail that exists whether or not the agent cooperates. The new spec makes the OAuth layer under all of that meaningfully stronger, and changes the division of labor not at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The 2026-07-28 auth package is six SEPs: issuer validation (2468), issuer binding for credentials (2352), &lt;code&gt;application_type&lt;/code&gt; in Dynamic Client Registration (837), plus documented refresh tokens (2207), scope accumulation (2350), and &lt;code&gt;.well-known discovery&lt;/code&gt; (2351).&lt;/li&gt;
&lt;li&gt;The common thread is binding: responses bound to issuers, credentials bound to issuers, clients declaring what they are. Mix-up and replay attacks in the one-client-many-servers pattern get materially harder.&lt;/li&gt;
&lt;li&gt;Adopt all of it now. &lt;code&gt;iss&lt;/code&gt; validation is heading toward mandatory, and SDK support lands within the ten-week validation window.&lt;/li&gt;
&lt;li&gt;Be clear-eyed about scope: this hardens client-to-server authentication. Agent identity, per-request authorization, delegation provenance, and audit remain outside the protocol, by design.&lt;/li&gt;
&lt;li&gt;Those four gaps are the governance layer. If your plan for them is “the spec will get there eventually,” it won’t, and it shouldn’t. Protocols carry messages; platforms enforce policy.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So update your SDKs, validate &lt;code&gt;iss&lt;/code&gt;, bind your registrations. Then ask the question the spec was right not to answer. When a token you issued gets used for a tool call you’d never have approved, presented by an agent you can’t name, who catches it, and where is the record? (&lt;a href="https://www.tigera.io/blog/five-principles-of-an-accountable-ai-agent-network-how-to-evaluate-any-governance-platform/" rel="noopener noreferrer"&gt;Five Principles of an Accountable AI Agent Network&lt;/a&gt; is the checklist for evaluating whatever answers you get.)&lt;/p&gt;

&lt;p&gt;The spec authenticates the client. Someone still has to govern the agent.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The same release candidate also quietly handed infrastructure teams the best transport upgrade MCP has had. That story deserves its own post, and it gets one soon. In the meantime, the whitepaper &lt;a href="https://www.tigera.io/lp/whitepaper-securing-ai-agents-on-kubernetes-using-tigera-lynx/" rel="noopener noreferrer"&gt;Securing AI Agents on Kubernetes using Tigera Lynx&lt;/a&gt; is the long-form version of the argument this post ends on: what identity, policy, and audit look like when the environment enforces them instead of the agent.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Read our whitepaper, &lt;a href="https://www.tigera.io/lp/whitepaper-securing-ai-agents-on-kubernetes-using-tigera-lynx/" rel="noopener noreferrer"&gt;Securing AI Agents on Kubernetes using Tigera Lynx&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://www.tigera.io/blog/mcps-auth-hardening-what-the-six-new-oauth-seps-fix-and-what-they-still-dont/" rel="noopener noreferrer"&gt;MCP’s Auth Hardening: What the Six New OAuth SEPs Fix, and What They Still Don’t&lt;/a&gt; appeared first on &lt;a href="https://www.tigera.io" rel="noopener noreferrer"&gt;Tigera – Creator of Calico&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>technicalblog</category>
      <category>aiagentsecurity</category>
    </item>
    <item>
      <title>Bring Your Own VLAN: Moving VMs to Kubernetes Without Changing a Single IP</title>
      <dc:creator>Alister Baroi</dc:creator>
      <pubDate>Tue, 28 Jul 2026 13:55:10 +0000</pubDate>
      <link>https://dev.to/tigeraio/bring-your-own-vlan-moving-vms-to-kubernetes-without-changing-a-single-ip-106p</link>
      <guid>https://dev.to/tigeraio/bring-your-own-vlan-moving-vms-to-kubernetes-without-changing-a-single-ip-106p</guid>
      <description>&lt;p&gt;For many organizations, modernizing their VMs before migrating them is not a realistic option, especially when external events trigger the migration. Mapping dependencies and refactoring network configurations before the deadline is impractical, forcing VMs to move as they are.&lt;/p&gt;

&lt;p&gt;The mechanics of moving a VM are largely solved. Tools like Forklift handle what a vSphere admin would recognize as a cold or warm migration: copy the VMDKs off the datastore, convert the guest, and boot it as a &lt;a href="https://www.tigera.io/learn/guides/kubevirt/" rel="noopener noreferrer"&gt;KubeVirt&lt;/a&gt; VM on Kubernetes. The guest comes through with its disks, its OS, its MAC address, and the static IP still written in its network configuration.&lt;/p&gt;

&lt;p&gt;Recreating the NSX segment the vNIC was attached to, the VLAN that defined the VM’s compliance scope, or the firewall rules that reference its address is a different story. The VM arrives in a cluster that knows nothing about any of it. Everything NSX was doing for that VM now has to be rebuilt on the Kubernetes side.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.tigera.io/learn/guides/kubernetes-networking/" rel="noopener noreferrer"&gt;Kubernetes networking&lt;/a&gt; cannot solve this on its own, for two reasons. First, pod IPs are assigned dynamically from the cluster’s pod CIDR, and a KubeVirt VM attached to the pod network is treated like any other workload, meaning that it gets a fresh address on arrival and again whenever it reschedules, so the static IP in its configuration file is unusable. Second, the pod network is routed. The model has no concept of a VLAN, a broadcast domain, or a persistent MAC address. A VM whose compliance scope or firewall rules depend on VLAN membership needs L2 semantics that the standard Kubernetes stack was never designed to carry.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdcq8dbvhgmhgj69e8pdd.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdcq8dbvhgmhgj69e8pdd.jpg" alt="Migrating a VM with default Kubernetes networking breaks dependencies" width="800" height="354"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Migrating a VM with default Kubernetes networking breaks dependencies&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  L2 vs L3: why the mismatch matters
&lt;/h2&gt;

&lt;p&gt;Traditional VM networking is rooted in L2. A VM on a VLAN-backed segment sits in a broadcast domain: when it needs to reach anything outside its subnet, it broadcasts an ARP request for its default gateway, and the gateway answers with its MAC address because they share that domain. The upstream switch learns the VM’s own MAC the same way, and its static IP belongs to the VLAN’s subnet.&lt;/p&gt;

&lt;p&gt;Two VMs on the same segment talk to each other without a router ever being involved. The pod network offers none of this, not because Kubernetes is deficient but because it was scoped for workloads designed for a routed network from the start. Running an L2-dependent VM in a cluster means extending L2 into the cluster explicitly, and that is where Calico’s L2 Bridge comes in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why VMs may need to stay on their original VLAN
&lt;/h2&gt;

&lt;p&gt;The short answer is that the VLAN is rarely just a VLAN. Over time it accumulates dependencies that make changing it expensive in ways that have nothing to do with technology.&lt;/p&gt;

&lt;p&gt;The most common is compliance scope. In PCI DSS environments, the cardholder data environment is often defined by VLAN membership. The audit evidence says “these workloads are in scope because they are on VLAN 200.” Moving a workload off that VLAN and redefining scope through a different mechanism, such as labels, policy selectors, and egress controls, is possible, but it requires re-engaging the auditor, updating the scoping documentation, and getting sign-off before the workload moves. That process runs on a different timeline than a migration project.&lt;/p&gt;

&lt;p&gt;Upstream firewall rules are the other major dependency. Perimeter firewalls and network ACLs are typically written against subnets and VLAN ranges, not individual IPs. A rule that permits traffic from 10.0.2.0/24 to the payment processor is a rule about VLAN 200. Changing the workload’s IP or VLAN means finding every rule that references that range, across every firewall that sits between that workload and anything it talks to, and updating them in coordination. Each of those updates requires a scheduled change window and with it the usual requests, approvals, and rollback plans.&lt;/p&gt;

&lt;p&gt;Beyond compliance and firewalls, there are the smaller dependencies that pile up over years of operations. Monitoring systems with hardcoded IPs, application configuration files that reference addresses directly, license servers that are locked to a specific IP, and external SaaS integrations that have the service IP on an allowlist are just a few examples. None of these are hard to fix individually. Together they represent enough coordination overhead that “just keep the IP” is often the right engineering decision, not a workaround.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Calico preserves VLAN-backed segment outcomes
&lt;/h2&gt;

&lt;p&gt;The three categories of dependency from the previous section all trace back to the same requirement: the VM needs to keep its IP address, its VLAN membership, and its MAC address after it moves. If those three things are preserved, nothing upstream needs to change.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.tigera.io/blog/lift-and-shift-vms-to-kubernetes-with-calico-l2-bridge-networks/" rel="noopener noreferrer"&gt;Calico L2 Bridge Networks&lt;/a&gt; preserve all three. Instead of attaching the VM to the routed pod network, a Network resource tells Calico to connect the VM’s vNIC to a Linux bridge on the cluster node. The bridge is easiest to understand as the node’s vSwitch: the physical NIC is the uplink, and a VLAN sub-interface on that NIC plays the role of the tagged port group that selects the VM’s VLAN out of the trunk.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkewv8k67qo1cgs6nip70.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkewv8k67qo1cgs6nip70.jpg" alt="The VM connects to its old VLAN with a bridge" width="800" height="500"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The VM connects to its old VLAN with a bridge&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There is one physical prerequisite. The node’s NIC must be plugged into a switch trunk port that carries the VM’s VLAN, just as an ESXi host’s uplinks must be trunked for a VLAN-backed segment to work. If VLAN 200 has not been extended to the Kubernetes nodes, there is no broadcast domain for the VM to join.&lt;/p&gt;

&lt;p&gt;With that in place, the VM sits in the same broadcast domain it occupied on ESXi. It ARPs for its gateway and the same physical gateway answers. The auditor still sees the workload on VLAN 200, the firewall still sees traffic from the same IP and subnet, and the license server, the monitoring system, and the application’s own configuration all still point at an address that hasn’t changed. The only real difference is that the VM now runs on a Kubernetes node instead of an ESXi host, with its network attachment declared as a Kubernetes resource instead of an NSX segment. The next section covers how the bridge is actually constructed.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Calico L2 Bridge works
&lt;/h2&gt;

&lt;p&gt;KubeVirt runs each VM inside a pod. When that pod is created, the cluster assigns it an IP from the pod CIDR like any other pod. The VM then boots inside it, and its virtual NIC is normally wired into the pod’s network namespace, so the VM inherits the pod’s identity: a cluster-assigned address on a routed network where its original IP means nothing. Calico L2 Bridge Networks change that wiring step: instead of connecting the vNIC to the pod network interface, Calico connects it to a Linux bridge on the node.&lt;/p&gt;

&lt;p&gt;When a Network resource defines an L2 bridge network and associates it with a VLAN, Calico sets up a Linux bridge on the cluster node. That bridge has an uplink to the VLAN sub-interface on the node’s physical NIC, which gives it access to the trunk the node is already connected to. The VM’s virtual NIC is attached to that bridge through a tap interface, the Linux equivalent of the vSwitch port a vNIC plugs into on ESXi. The result is a direct L2 path from the VM to the physical switching fabric: VM tap device, through the Linux bridge, through the VLAN sub-interface, out the physical NIC, into the same broadcast domain the VM was on before.&lt;/p&gt;

&lt;p&gt;The upstream switch learns the VM’s MAC address the same way it always has, by watching frames arrive on the VLAN. From the switch’s perspective, a new port came up carrying a MAC it already knew. Nothing in the physical network needs to be reconfigured.&lt;/p&gt;

&lt;p&gt;This is the plumbing a migration plan needs to account for, and in practice it comes down to a short checklist. Before the move, record the VM’s VLAN and IP address. Create a Network resource referencing that VLAN, and point the VM’s KubeVirt definition at it by name. When the VM starts on its new node, Calico builds the bridge, the guest boots with the network configuration it has always had, and traffic flows on the same VLAN as before. As far as the VM knows, it’s still where it always was.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep the network, move the machine
&lt;/h2&gt;

&lt;p&gt;None of the dependencies this blog started with have to be rewired when your VM moves to a Kubernetes cluster. The auditor’s scoping document, the perimeter firewall rules, the license server record, the hardcoded addresses in a decade of operational tooling: all of it still holds, because the VM still has the IP, the MAC address, and the VLAN membership they were written against. The migration moves the machine without touching the network identity everything else depends on.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzga4b3309w9opignpfsb.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzga4b3309w9opignpfsb.jpg" alt="The VM keeps its place on the VLAN and its dependencies" width="800" height="354"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The VM keeps its place on the VLAN and its dependencies&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There is a broader point here that goes beyond any single VM. Because the VLAN extends into the cluster, ESXi and Kubernetes stop being two separate worlds with a hard cutover between them. During a migration they are just two sets of hosts attached to the same networks, which means you can move one VM this week, ten next month, and leave the stubborn ones where they are for now. The workloads that have moved keep talking to the ones that haven’t, and if something goes wrong, rolling back is a matter of booting the VM on the other side again. That changes what an NSX team is actually signing up for. The migration stops being a leap to an unfamiliar platform and becomes a gradual shift of workloads across a network you still recognize and still control, with the Kubernetes learning curve spread over months instead of compressed into a cutover weekend.&lt;/p&gt;

&lt;p&gt;If a phased migration like that is what you are planning, read our ebook: &lt;a href="https://www.tigera.io/lp/ebook-calico-enterprise-for-nsx-administrators/" rel="noopener noreferrer"&gt;Calico Enterprise for NSX Administrators&lt;/a&gt;. When you are ready to try Calico yourself, you can &lt;a href="https://www.calicocloud.io/home" rel="noopener noreferrer"&gt;get started for free&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Ready to migrate VM-centric architectures to Kubernetes platforms? Read our ebook, &lt;a href="https://www.tigera.io/lp/ebook-calico-enterprise-for-nsx-administrators/" rel="noopener noreferrer"&gt;Calico Enterprise for NSX Administrators&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://www.tigera.io/blog/bring-your-own-vlan-moving-vms-to-kubernetes-without-changing-a-single-ip/" rel="noopener noreferrer"&gt;Bring Your Own VLAN: Moving VMs to Kubernetes Without Changing a Single IP&lt;/a&gt; appeared first on &lt;a href="https://www.tigera.io" rel="noopener noreferrer"&gt;Tigera – Creator of Calico&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>technicalblog</category>
      <category>bestpractices</category>
      <category>vmmigration</category>
      <category>products</category>
    </item>
    <item>
      <title>Why eBPF Is Useful for Watching and Sandboxing AI Agents</title>
      <dc:creator>Alister Baroi</dc:creator>
      <pubDate>Mon, 27 Jul 2026 20:04:42 +0000</pubDate>
      <link>https://dev.to/tigeraio/why-ebpf-is-useful-for-watching-and-sandboxing-ai-agents-12pp</link>
      <guid>https://dev.to/tigeraio/why-ebpf-is-useful-for-watching-and-sandboxing-ai-agents-12pp</guid>
      <description>&lt;p&gt;Most of our runtime security habits were built for deterministic workloads. A service does what its code says: review the code, sign the image, and its behavior is bounded. Agents are different. An agent’s behavior emerges from a model reasoning over whatever lands in its context window, and some of that context comes from places we don’t fully control — a retrieved document, a tool’s output, a user’s prompt. Meanwhile the agent usually runs with real privileges: a service account, network reach, mounted secrets, a filesystem. When untrusted input shapes behavior, those privileges get exercised less predictably than we’re used to.&lt;/p&gt;

&lt;p&gt;A lot of good work goes into making agents harder to mislead — prompt hygiene, injection classifiers, guardrail models. It’s worth pairing that with a second question: if an agent does something we didn’t intend, how far can it actually reach? That’s blast radius, and it’s mostly a decision we make at the runtime layer, independent of how the prompt was handled.&lt;/p&gt;

&lt;p&gt;This is where &lt;a href="https://www.tigera.io/learn/guides/ebpf/" rel="noopener noreferrer"&gt;eBPF&lt;/a&gt; is a good fit, for two reasons: it’s an excellent way to &lt;em&gt;see&lt;/em&gt; what an agent is doing, and it can &lt;em&gt;enforce&lt;/em&gt; limits on what the agent can touch — without changing the agent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Most of what an agent does is a syscall
&lt;/h2&gt;

&lt;p&gt;The reason the kernel is a natural place to observe and constrain an agent is that nearly everything an agent does — reading a file, running a command, opening a connection — resolves to a syscall. eBPF attaches to the kernel, beneath the workload, so it can watch those syscalls directly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;File activity —&lt;/strong&gt; via LSM hooks (BPF-LSM / KRSI) or kprobes on &lt;code&gt;openat, read, write&lt;/code&gt;. You can see exactly what an agent reads and writes, including attempts to reach paths like &lt;code&gt;/var/run/secrets&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Process activity —&lt;/strong&gt; via &lt;code&gt;sched_process_exec&lt;/code&gt; and LSM &lt;code&gt;bprm_*&lt;/code&gt; hooks. You can see every binary an agent tries to execute, including an unexpected shell.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Network activity —&lt;/strong&gt; via cgroup &lt;code&gt;connect&lt;/code&gt; hooks, tc/XDP, and DNS visibility. You can see where an agent is trying to send traffic, and whether it’s trying to bypass your model gateway.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That alone is valuable: a clear, tamper-resistant record of what your agents actually do at runtime, without instrumenting them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnmu8fu8by1e9vle8arbw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnmu8fu8by1e9vle8arbw.png" width="682" height="1024"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  From observing to enforcing
&lt;/h2&gt;

&lt;p&gt;eBPF can also act inline — overriding a syscall or stopping a process when a policy is violated. That means the same layer supports a natural progression from &lt;strong&gt;observe → alert → enforce&lt;/strong&gt; , and you can move an agent along that path without redeploying it.&lt;/p&gt;

&lt;p&gt;In practice, that gives you sandbox-like controls expressed as simple rules about what a process may touch:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Allow reads under &lt;code&gt;/workspace&lt;/code&gt; but keep writes off for a read-only agent, and keep secrets out of reach entirely.&lt;/li&gt;
&lt;li&gt;Pin an agent to an allow-list of binaries, or block &lt;code&gt;exec&lt;/code&gt; for agents that should never spawn a shell.&lt;/li&gt;
&lt;li&gt;Require egress to flow through your model gateway, and block anything trying to go direct.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Two properties make this practical at scale. First, because eBPF sits beneath the workload, it applies to pods that are &lt;strong&gt;already running&lt;/strong&gt; and agents you &lt;strong&gt;haven’t modified&lt;/strong&gt; — no recompile, no sidecar, no new base image. That’s a real advantage when you already have agents in production. Second, it runs in a different trust domain than the workload, so it’s hard for the agent to tamper with, and the overhead is low enough to run fleet-wide.&lt;/p&gt;

&lt;h2&gt;
  
  
  What eBPF is not for
&lt;/h2&gt;

&lt;p&gt;eBPF is well suited to blast-radius questions — &lt;em&gt;what a process may touch&lt;/em&gt; — rather than deep content inspection. It can see that an agent is opening a connection or writing a path and act on that, but it can’t understand the semantics of a prompt or redact fields inside an encrypted request body. That kind of work belongs at a TLS-terminating proxy at the model gateway that can do semantic checks on the agent’s intent and actions. eBPF helps contain what an agent can &lt;em&gt;do&lt;/em&gt;; a proxy governs what it &lt;em&gt;sends&lt;/em&gt;. They’re most useful together, and eBPF is happiest as a uniform floor beneath whatever higher-fidelity, application-aware controls you already run.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftu94blza1zwsj77nuch1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftu94blza1zwsj77nuch1.png" width="800" height="959"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The short version
&lt;/h2&gt;

&lt;p&gt;Agents behave less predictably than the workloads our tooling was designed for, so it’s worth planning for the moments when one does something unintended. eBPF gives you two things that can help: visibility into what agents are actually doing at the syscall level, and a tamper-resistant way to lock them down, across agents you never had to change or redeploy.&lt;/p&gt;

&lt;p&gt;Want to see what this looks like in practice on Kubernetes? Get the ebook: &lt;a href="https://www.tigera.io/lp/whitepaper-securing-ai-agents-on-kubernetes-using-tigera-lynx/" rel="noopener noreferrer"&gt;Securing AI Agents on Kubernetes using Tigera Lynx&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://www.tigera.io/blog/why-ebpf-is-useful-for-watching-and-sandboxing-ai-agents/" rel="noopener noreferrer"&gt;Why eBPF Is Useful for Watching and Sandboxing AI Agents&lt;/a&gt; appeared first on &lt;a href="https://www.tigera.io" rel="noopener noreferrer"&gt;Tigera – Creator of Calico&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>technicalblog</category>
      <category>aiagentsecurity</category>
      <category>bestpractices</category>
    </item>
    <item>
      <title>Migrate First, Modernize Later: A Leadership Guide to Converging VMs and Containers to Run AI Workloads</title>
      <dc:creator>Alister Baroi</dc:creator>
      <pubDate>Fri, 24 Jul 2026 21:32:47 +0000</pubDate>
      <link>https://dev.to/tigeraio/migrate-first-modernize-later-a-leadership-guide-to-converging-vms-and-containers-to-run-ai-4l52</link>
      <guid>https://dev.to/tigeraio/migrate-first-modernize-later-a-leadership-guide-to-converging-vms-and-containers-to-run-ai-4l52</guid>
      <description>&lt;h2&gt;
  
  
  The Tipping Point
&lt;/h2&gt;

&lt;p&gt;Every so often the ground under enterprise IT moves. It’s moving now. Across industries, organizations are consolidating fragmented infrastructure onto a single, self-hosted platform capable of running both containers and virtual machines side by side. The motivation is simple: simplify operations, lower cost and reallocate resources &amp;amp; budget to AI initiatives. Kubernetes is emerging as the primary platform for many of these workloads.&lt;/p&gt;

&lt;p&gt;For most IT leaders, the compute and storage portions of a VM migration are manageable. Storage arrays and hypervisor CPU/memory allocation translate fairly directly to Kubernetes equivalents. Networking is where migration plans stall. A VM’s network identity — its IP, its VLAN membership, its firewall rules — is wired into surrounding infrastructure, monitoring, compliance controls, and business processes that nobody wants to touch during a migration window.&lt;/p&gt;

&lt;p&gt;Teams accustomed to NSX for this work find that native Kubernetes networking wasn’t built with VM administrators in mind, and the functionality gap becomes the reason migration projects get bigger or are stalled. If the networking problem is solved — if a VM can move to Kubernetes and keep its IP, its policy, and its security posture intact — then the rest of the platform consolidation stops being an expensive, multi-year architectural bet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Power of Convergence&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
eBPF-powered Calico unified platform’s value has always been convergence and portability — collapsing separate networking domains into a platform and enabling customers to avoid vendor lock-in by platform vendors.&lt;/p&gt;

&lt;h2&gt;
  
  
  One Networking and Security Model for Any Kubernetes Distribution, Any Workload, Anywhere
&lt;/h2&gt;

&lt;p&gt;Calico Enterprise was developed to deliver three objectives for enterprise networking &amp;amp; security in Kubernetes in a single unified platform to enable enterprises to be ready for hosting AI workloads. Now with the launch of Calico for VMs on Kubernetes, Calico delivers a fourth objective: support for VMs &amp;amp; Containers on Kubernetes.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;All the components required for k8s networking and network security in a single unified platform –&lt;/strong&gt; Built on the most trusted open-source technologies in Kubernetes — Calico Open Source, Istio, Envoy, and eBPF — the Calico platform gives platform engineering teams a single management plane to enforce, observe, and troubleshoot all workload communication&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unified platform works across any Kubernetes distribution –&lt;/strong&gt; Calico is Kubernetes agnostic, and supports all major distributions equally: AKS, EKS, GKE, VMware VKS, RedHat OpenShift, Canonical, SUSE, Mirantis and others. That matters strategically for a VM migration decision: it means the move of workloads from a legacy hypervisor to Kubernetes doesn’t lock the organization into a single Kubernetes vendor.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unified platform works across infrastructure –&lt;/strong&gt; Calico extended one unified model across on-premises, cloud environments and edge, so connectivity, security, and observability behave identically no matter where a cluster runs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unified platform works across different types of workloads – Containers &amp;amp; VMs –&lt;/strong&gt; Calico enables virtual machines and containers to share one networking fabric, one policy model, and one observability plane. Seamless VM migration while maintaining L2 networking, and a single control plane for ease of management, regardless of the workload, VMs or containers.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Benefits of Adopting a Modern Networking Architecture
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Migrate First, Modernize Later
&lt;/h3&gt;

&lt;p&gt;The single most important idea for a migration plan to succeed is separating “get off legacy” from “redesign the network and workloads”. Trying to do both at once is what turns a migration into a multi-year modernization program. Calico’s L2 bridge capability extends existing VLANs into Kubernetes, so a VM can move to a Kubernetes cluster on day one without renumbering, without rewriting firewall rules, and without breaking the hard-coded dependencies — DNS records, monitoring agents, compliance scans — that assume a specific IP or subnet. Once workloads are safely on Kubernetes, the network architecture can evolve on its own timeline — moving from an L2, VLAN-based design to a Kubernetes-native L3 design when the team is ready, not because the migration forced the issue.&lt;/p&gt;

&lt;h3&gt;
  
  
  A complete stack for VM networking on Kubernetes
&lt;/h3&gt;

&lt;p&gt;Every capability and outcome delivered by NSX has a direct Kubernetes-native counterpart in Calico:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Connect –&lt;/strong&gt; Calico Networks provide connectivity to VM workloads and to the networks and services around them. L2 Bridge capabilities can extend existing network VLANs (Segments) into Kubernetes for workloads that require Layer 2 or network continuity during and after migration. BGP-based routing, egress gateway, load balancing and ingress gateway functions support delivering applications and services to consumers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secure –&lt;/strong&gt; Calico network policy, policy tiers, staged policy and DNS policy provide Kubernetes-native controls for access enforcement and microsegmentation. Policies can be planned, monitored and validated before enforcement, helping teams maintain security posture as workloads move and apply consistent controls across VMs and containers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Observe –&lt;/strong&gt; Calico Service Graph, flow logs, DNS logs, L7 visibility and packet capture provide context for troubleshooting and security operations. Teams can investigate VM-to-VM, VM-to-pod, pod-to-pod and cross-cluster flows with Kubernetes-aware workload context using eBPF-enabled deep packet inspection.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The ROI Case
&lt;/h3&gt;

&lt;p&gt;The core mechanism is consolidation onto a single management plane covering network connectivity, observability, and network policy. Instead of maintaining separate stacks and separate expertise for VMs and for containers, the teams responsible for availability, performance, and security each focus on one plane, with one consistent set of tools, telemetry, and controls. Additionally, the new architecture prevents vendor lock-in by Kubernetes platform vendors.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cost relief
&lt;/h3&gt;

&lt;p&gt;The immediate driver for most organizations is reducing the costs of legacy hypervisors. Every VM that moves off legacy infrastructure onto a converged Kubernetes platform is a licensing spend that stops compounding — budget that can be redirected to AI infrastructure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Operational efficiency
&lt;/h3&gt;

&lt;p&gt;Running one policy model, one routing and observability stack, and one set of operational runbooks for both VMs and containers means fewer specialized teams, less tooling overlap, and lower mean time to resolution (MTR) when something goes wrong.&lt;/p&gt;

&lt;h3&gt;
  
  
  AI readiness
&lt;/h3&gt;

&lt;p&gt;A converged platform is also the platform production AI workloads need. Self-hosted LLMs and the agents built on them can run alongside existing VM and container workloads, close to the data they need, with the performance, latency, and scale that production AI demands.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The market is converging on one self-hosted platform for containers and VMs, and the economics and AI trends driving it are only accelerating. The AI-driven need for a converged, self-hosted platform is the reason to move to Kubernetes specifically, rather than to another hypervisor. Tigera already secures workloads across more than a million clusters for organizations including NVIDIA, Royal Bank of Canada, Bloomberg, Chipotle, GoDaddy, and Upwork.&lt;/p&gt;

&lt;p&gt;Migrate first. Modernize later. On your timeline.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;→ Learn more:&lt;/strong&gt; Visit the &lt;a href="https://www.tigera.io/tigera-products/vm-migration/" rel="noopener noreferrer"&gt;VM Migration page&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;→ See it in action:&lt;/strong&gt; View the &lt;a href="https://app.arcade.software/share/Pa1kvHOZzkXI43jXoHs2" rel="noopener noreferrer"&gt;self-paced overview&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ready to see Calico for VMs on Kubernetes in action? &lt;a href="https://app.arcade.software/share/Pa1kvHOZzkXI43jXoHs2" rel="noopener noreferrer"&gt;Walk through the live demo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://www.tigera.io/blog/migrate-first-modernize-later-a-leadership-guide-to-converging-vms-and-containers-to-run-ai-workloads/" rel="noopener noreferrer"&gt;Migrate First, Modernize Later: A Leadership Guide to Converging VMs and Containers to Run AI Workloads&lt;/a&gt; appeared first on &lt;a href="https://www.tigera.io" rel="noopener noreferrer"&gt;Tigera – Creator of Calico&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>featuredblog</category>
      <category>technicalblog</category>
      <category>vmmigration</category>
      <category>products</category>
    </item>
  </channel>
</rss>
