§03 · Building agents

Agent

An Agent declares a runtime, a goal, a model, the skills it can use, and when it wakes up. The operator runs one pod per Agent.

An Agent is a Kubernetes object describing a coding or automation agent. The operator runs one pod per Agent (the agentlet plus the runtime CLI), resolves its model credentials, provisions its skills, and fires runs on a schedule or on demand.

Create an agent

There are two ways to create one.

From the dashboard. On the Agents page, or a deployment's detail, click Create agent. Choose the deployment to run it in (it must be online), give it a lowercase DNS-style name, pick a runtime, and write its goal. For OpenCode that's all you need, it runs on a free, keyless model. Claude Code and Codex also need a model provider. Exo creates the agent in your cluster for you, no YAML.

The Create agent dialog: name, runtime (OpenCode keyless free model), goal, capability toggles, skills, and target deployment
Create agent from the dashboard: name it, pick a runtime and the deployment to run it in, and give it a goal. OpenCode uses a free, keyless model; the capability toggles decide whether you can attach a shell and whether it runs on its own.

As a Kubernetes object. For GitOps, or anything the form doesn't cover, declare the Agent resource below and apply it with kubectl or your CD tool. The operator reconciles it the same way, so both paths land in the same place.

A sample Agent

agent.yaml· yaml
1apiVersion: autonomic.sh/v1alpha1
2kind: Agent
3metadata:
4 name: triage-bot
5 namespace: adaptive
6 labels:
7 autonomic.sh/agentgroup: support-team
8 env: prod
9spec:
10 runtime: ClaudeCode
11 displayName: Issue triage
12 phase: Active
13 goal:
14 inline: |
15 Triage incoming GitHub issues: fetch new ones hourly, label, assign.
16 model:
17 name: claude-opus-4-8
18 provider: anthropic
19 provider:
20 name: anthropic-prod
21 type: anthropic
22 gateway:
23 name: shared-gateway
24 wakeup:
25 enabled: true
26 mode: schedule
27 schedule: "0 * * * *"
28 bootstrap:
29 skills:
30 - triage-runbook
31 mcps:
32 - linear
33 policies:
34 - safe-shell-baseline

Fields

  • runtime: the agent CLI that runs in the pod. Picks the image (see Runtimes).
  • displayName: a cosmetic name shown in place of name, which is immutable. Rename freely without touching the resource identity.
  • labels on the metadata are matched by locally scoped runtime policies, so labelling an agent env: prod is enough to bring the production guardrails with it.
  • phase: Active or Paused, defaulting to Paused. Review the resolved status, then set Active to arm.
  • goal: inline text or a configMapKeyRef.
  • model: the model binding (name plus a family provider like anthropic or openai).
  • provider: the platform-managed provider the credentials come from. name pins a specific integration record; type (anthropic, openai, …) picks that kind's tenant default when name is omitted, so you don't store a key per agent.
  • agentToken: an escape hatch. A Secret ref holding the runtime's own API key (mapped to its token env var) for when you aren't using a platform-managed provider.

Capabilities

What an agent may do is described by three independent flags rather than a single mode. All default off, so a new agent is both connectable and runnable:

  • disableShell: no interactive session. Nobody can attach a terminal to it.
  • disableRun: no runs. The Run button disappears, and webhooks and schedules will not fire it.
  • injectGoals: the goal is injected into the session rather than left for the agent to pick up — the deterministic playbook shape.
  • allowUserContext: a Run offers a box for free-text context that applies to that run only.

Runtimes

spec.runtime picks the coding-agent CLI the operator runs in the pod: ClaudeCode, Codex, Gemini, Pi, or OpenCode. Which provider each resolves, per-runtime examples, and image pinning live on Runtimes.

What you can attach

Most of an agent's power comes from what it is wired to. Each of these is editable after creation, from the dashboard or the resource:

AttachmentFieldWhat it gives the agent
Skillsbootstrap.skillsReusable instruction bundles, materialised into the runtime's instruction files at session start — an edited skill is live on the next run, no redeploy.
MCP serversbootstrap.mcpsRemote tool servers. The URL and credentials are rendered into the runtime's MCP config at connect time, never stored in the resource.
Policiesbootstrap.policiesRuntime guardrails the agent is bound by, enforced at the control plane and inside the pod.
Memoriesbootstrap.memoriesDurable versioned context, read at session start and written back.
File systemsfilesystemsPersistent volumes mounted into the pod, shared across agents and surviving restarts.
GatewaygatewayRoute model traffic through an LLM gateway for metering and budgets instead of direct provider keys.
Web agentswebAgentRefsA browser the agent can drive, over MCP.
SchedulewakeupFire runs on cron, a phrase, or once at a fixed time.

Templates

A configuration worth repeating can be saved as an agent template: runtime, goal, capability flags, provider, skills, policies, MCP servers, and web-agent bindings, minus the name. Creating an agent from a template fills in everything you do not override — including from the API and CLI, not just the modal. Templates are tenant-scoped records, not Kubernetes objects.

Pause, restart, delete

  • Pause sets spec.phase: Paused: the resident pod is torn down and scheduled wakeups stop. Resuming brings it back. This is the safe stop.
  • Restart deletes the resident pod and lets the reconciler recreate it — pod specs are immutable, so recreating is the restart. In-flight runs are separate pods and are left alone.
  • Delete removes the agent; owner references tear down its pod, run config, and secrets. Force delete also purges the dashboard row when the deployment is offline or the operator is unresponsive.

Status

kubectl get agents surfaces two status columns the controller writes: .status.phase and .status.ready. The rest of .status is free-form (the CRD preserves unknown fields), so the reconciler can add detail without a schema bump. Run kubectl describe agent <name> to read the full object when a run won't fire.