The Kubernetes control plane for fleets of conformant agents.
agentctl provisions, secures, scales, and routes fleets of contract-conformant agents. Agents serve mTLS HTTPS and dial their LLM provider and MCP servers directly. Identity is the boundary — a verified client cert inbound, an AAuth-signed identity outbound. No per-node agent, no broker, no pod-resident secrets.
Rust control plane · BUSL-1.1 · the contract + SDK are Apache-2.0
apiVersion: agentctl.dev/v1alpha1
kind: Agent
metadata: { name: researcher, namespace: team-a }
spec:
image: ghcr.io/agentd-dev/agentd:1.0.0
mode: reactive
surfaces: { a2a: true } # reachable over the A2A gateway (its wake source)
model: { pool: gpt } # agent dials the pool's provider directly (AAuth, or a mounted INTELLIGENCE_TOKEN)
mcpServers: [{ name: tools, endpoint: https://…, auth: { mode: aauth } }] # dialed directly
# the operator renders a restricted-PSS pod that:
# serves https://0.0.0.0:8443/mcp (mTLS, per-workload cert)
# dials INTELLIGENCE + mcpServers directly (AAuth-signed, secret-free)
# holds no provider/tool secret · no hostPath · runAsNonRootReached over the network, bounded by identity.
Agents are reached the way Kubernetes reaches anything else — over the network, with a verified identity. The whole control surface is mTLS HTTPS, and agents act only through operator-declared MCP tools they dial directly, so there is no local execution surface. The control plane manages an agent completely while staying out of its execution layer.
Into the agent — mTLS client cert
The APIServer and A2A gateway dial the agent's https://<podIP>:8443/mcp presenting the control-plane client cert. A cert that chains to the pinned CA is Management; no cert is refused, never downgraded.
Out of the agent — signed direct dial
The agent dials its bound LLM provider and MCP servers directly over public-HTTPS egress. With AAuth it signs each request with its own workload identity, so no provider or tool secret rests on the pod; the fallback is a token mounted from a referenced Secret. No broker sits in the path.
One control plane, six planes — every capability gated default-off.
Each plane programs against the published Agent Control Contract, never a specific agent. agentd is the reference implementation, not a dependency.
Provisioning & PKI
Declare an Agent or AgentFleet; the operator renders an mTLS-serving pod and mints its identity via cert-manager — a per-workload serving cert plus the per-namespace CA. Restricted-PSS, zero credentials, live cert rotation.
Management
An aggregated APIServer exposes drain / lame-duck / cancel / pause / resume as SAR-gated verbs, forwarded direct to the agent pod as a2a.* admin JSON-RPC over mTLS. No proxy, no host socket.
Intelligence
The operator resolves the Agent's bound ModelPool and renders INTELLIGENCE=<the provider endpoint> into the pod; the agent dials the provider directly. With AAuth the dial is secret-free — identity signed per request — with an optional mounted INTELLIGENCE_TOKEN as the fallback. Budgets are harness-tracked (lifetimeTokens, maxTokens), never enforced by an in-path broker.
Tool plane (MCP)
Agents work only through operator-declared MCP tools. spec.mcpServers is an inline list of { name, endpoint, auth, tags } the agent dials directly — authenticating with AAuth, a mounted staticToken, or none. No stdio, no broker, no facade in the path.
A2A mesh
The gateway fronts each agent's public A2A surface — forwarding direct to the pod on the contract's A2A wire (bare PascalCase methods, SSE streaming), signing the Agent Card, and holding the durable task store.
Scaling
Elastic fleets by claim (Deployment + a KEDA external scaler, scale-from-zero on an off-pod backlog) or shard (StatefulSet with keyed partitioning). Exactly one replica-field writer.
Install the control plane, apply a CR.
cert-manager is the only hard prerequisite. Postgres is bundled; KEDA is optional (claim-mode autoscaling).
# cert-manager (the one hard prerequisite)
kubectl apply -f https://github.com/cert-manager/\
cert-manager/releases/latest/download/cert-manager.yaml
# the control plane
kubectl create namespace agentctl-system
helm install agentctl ./charts/agentctl -n agentctl-system
kubectl -n agentctl-system get pods # all Running
kubectl -n agentctl-system get certificate # all READYkubectl apply -f - <<'EOF'
apiVersion: agentctl.dev/v1alpha1
kind: Agent
metadata: { name: hello, namespace: team-a }
spec:
image: ghcr.io/agentd-dev/agentd:1.0.0
mode: reactive
EOF
kubectl get agents -n team-a # READY=True
# the pod serves mTLS :8443/mcp and dials its provider directly.Light data plane, negligible control plane.
Live kubectl-top readings from a running stack: a full control plane plus a reactive agent that dials an MCP tool directly, all Ready.
Point-in-time readings of one idle agent — the six Rust components together idle at ~8m / ~22 MiB; Postgres is the single largest line. Full density / throughput / latency methodology in the repo benchmarks.
The load-bearing rules.
Depend on the contract, never on an agent
agentctl consumes only the published, language-neutral Agent Control Contract. Any binary that emits a conformant manifest, serves mTLS /mcp, and dials its provider and tools directly is managed unchanged. agentd is the reference, not a dependency.
Identity is the boundary
A verified mTLS client cert into agents; an AAuth-signed identity out to providers and tools, and an attested source IP for coordination work claims. Reachability is never authority. mTLS-only — the control plane never puts a bearer on the pod.
The pod holds no power it doesn't need
No bearer, no hostPath, no privilege, and — with AAuth — no provider or tool secret: the agent signs its own dials, and the only always-present key material is its rotatable mTLS serving identity. Where a static token is unavoidable it is mounted from a referenced Secret, never brokered off-pod.
The full architecture, contract specification, and operational guides live in the repository documentation.