Infrastructure as Code (IaC) made infrastructure a versioned, testable, and reproducible software artifact. AI agents are reaching a similar point.
Agents as Code (AaC) is the practice of defining an agent - its model, prompts, tools, knowledge, permissions, policies, and expected behavior - as a versioned, testable, deployable, and observable artifact.
The key idea: Infrastructure as Code manages desired state. Agents as Code manages desired behavior.
Most production agents are not there yet. They live in a chat window, a laptop, or a framework dropped into a Pod. When something goes wrong, there is no owned run to inspect, no declared identity for who invoked it, and no least-privilege boundary for what it could reach. Further on, we’ll take a look at what it takes to make Agents as Code real on Kubernetes - and how far a platform can go today before “behavior” becomes something you can reconcile the way you reconcile replicas.
Putting an agent configuration in Git is useful. It is also incomplete. Most teams stop at something closer to Agent Configuration as Code: a single file, a prompt, a model name, maybe a tool list.
A more complete definition looks less like one YAML blob and more like a small software package:

evals/ matters disproportionately. It describes not only what the agent is, but how we expect it to behave. Without that, version control can prove you shipped a prompt. It cannot prove the agent did what you meant.
The key idea is that making agents operational means supporting a full engineering lifecycle: definition, version control, evals, deployment, orchestration, runs, observability, and eventually behavioral reconciliation.
There is a tempting shortcut: run an agent framework inside a Pod and call it cloud-native. That gives you scheduling. It does not give you an API for composition, ownership of run artifacts, or a Day-2 loop for identity, access, delivery, and cleanup.
A stronger model treats agent work the way Kubernetes already treats serious workloads. An operator pattern earns its keep when you need the same five things any cluster platform needs:
In other words: desired composition and task continuously become an actual Job or session and an observed status.
You can sketch that as a simplified resource (illustrative, not a shipped API). Imagine a procurement agent that may search a catalog, but must not create a purchase request without confirmation:

That sketch is useful for the mental model. Production systems usually do better when they compose an agent run from smaller, reusable objects rather than stuffing everything into one mega Agent CRD – especially if you want swappable providers, reusable knowledge, and least-privilege access that is explicit rather than implied.
At Alteus, we build that layer as Pilot: a Kubernetes-native control plane for AI agent work. Externally, people may say “Agents as Code.” For Pilot, the more precise phrase is agent infrastructure as code.
That means declaring, versioning, and reconciling everything required to run an agent safely in production – who may invoke it, what it is allowed to be, which runtime and knowledge it uses, what it may reach, where results go – not only the prompt text. Desired behavior (evals, policy compliance over time) is a natural next layer. Pilot’s present tense is the infrastructure that makes that possible: declared composition → standard workspace → observable task.
For the procurement agent, that composition is not one mega YAML. It is reusable cluster objects: a PilotClient for who may invoke, a PilotContext for the defaults, a PilotProvider for the runtime image, a PilotSkill for the behavior pack, PilotAssets for catalogs or policies, PilotAccess for any external reach, PilotDelivery for where the purchase request lands, and a PilotTask for the actual run.
Pilot is a multi-CRD operator. The mental model is closer to the Prometheus Operator – compose a system from CRDs; the operator wires the runtime – than to a long-lived stateful app kept healthy forever.

Swap the provider image and API key without changing how tasks, skills, assets, and deliveries are composed. The contract that makes that possible is a fixed filesystem every provider and sidecar shares.
Three layout choices carry most of the weight:
Modes follow from that contract: job runs skill + prompt to completion; interactive keeps a session alive under TTL.
A task cannot use the Kubernetes API, exec into pods, read logs, clone private repos, or reach external systems unless that is explicitly configured. If Agents as Code only versions prompts, it can still ship an agent that can do anything the cluster can do. Infrastructure as code for agents has to make reachability declarative.
A Kubernetes-native architecture separates three concerns:

In Pilot today, a procurement run happens roughly like this: compose the context in Git or via API; a caller creates a PilotTask; the operator resolves defaults, creates an owned Job with /workspace and /provider/api_key, and lets the provider read skill, prompt, and assets from disk. Status updates on the Task; deliveries push results; a workspace PVC keeps the tree inspectable after exit.
Every execution should leave more than a log line. In Pilot, PilotTask is the run. The operator owns an agent Job, maps Job status to task phase, and can attach a workspace PVC so the tree survives for debug, fork, or re-run.
After the procurement agent finishes, you should be able to answer: which context and skill ran, what prompt and catalog it saw, whether it called create-purchase-request, whether confirmation was required, where the result was delivered, and what the Task phase was. That lives on the CRs and under /workspace – session trails, delivery status, materialized assets – not in a chat history on someone’s laptop.
That gives two forms of auditability:
Monitoring starts with reconcile health, Job phase, tokens, and delivery success or failure – and can grow toward richer trajectory and policy checks. The run is an object, not a log afterthought.
Kubernetes continuously compares desired state with actual state. Agents introduce another possibility: desired behavior versus observed behavior.
desired replicas = 3
actual replicas = 2
→ reconcile
desired: confirmation before purchase request = required
observed: compliance = 99.3%
→ behavioral drift?
This is fundamentally harder because agent behavior is probabilistic. Behavior must be evaluated through policy checks, evals, trajectory analysis, statistical monitoring, and sometimes human feedback.
A Kubernetes-native agent platform can therefore run two loops:

Unlike normal Kubernetes reconciliation, behavioral drift should not silently self-modify the agent in production. A safer loop is:

Pilot today covers the left loop – Job/session lifecycle and status – plus the artifact trail that makes the right loop possible later. Deeper trajectory analysis, evals, and behavioral drift response are a direction on top of runs-as-artifacts, not a shipped Pilot feature.
Terms like Agents as Code, Agent as Code, and declarative agents already exist. The interesting step is to move beyond “put agents in Git” toward an engineering lifecycle that connects:

Pilot answers a slightly sharper production question first:
Can AI agent work be operated like other cloud-native workloads – declared, composed, permissioned, executed on a standard workspace, observed, and delivered – without tying the platform to one vendor agent?
Yes – by making agent infrastructure (APIs + filesystem contract + run lifecycle) a Kubernetes concern, and keeping the provider a swappable image behind that contract.
That is also the business case, not only the architecture. Audit and compliance need a trail of what was declared and what actually ran. Least privilege means a procurement agent cannot wander the cluster or the network unless that reach was reviewed as config. Provider independence means swapping the agent image does not rewrite callers, skills, or deliveries. Reproducible workspaces mean a stuck or disputed run can be forked and inspected instead of reconstructed from memory.
We are building toward schedules and watchers that spawn tasks, stronger access enforcement, fork/continue as a normal loop, and deeper observability of trajectories (and later evals / behavioral drift). Those extend the same spirit: agent work as engineered cluster workloads, not chat left on someone’s laptop.
Kubernetes gave us continuous reconciliation between desired state and actual state. Agents as Code asks whether we can build an engineering model for reconciling desired behavior with observed behavior.
Today, the honest foundation is agent infrastructure as code: composition, permissions, runtime layout, and runs you can audit. Behavior reconciliation sits on top of that foundation. Without first-class runs, “desired behavior” is a slogan. With them, it becomes an engineering problem you can actually work on.

Emil Calofir is the Head of AI at eSolutions, where he leads the integration of AI solutions across a range of projects, with a strong focus on Generative AI and building practical, scalable capabilities that support business needs. With a software architecture background and broad industry exposure, he helps teams translate complex requirements into robust, production-ready systems.