Skip to content

Repository files navigation

AI agent subsystem

Run autonomous coding agents as first-class Kubernetes resources. Describe the work, pick a runtime, launch a run — a reconciling controller does the rest. Kubernetes stays the single source of truth: a run is a resource, and its result lives on the resource's status.

This is a clean-sheet, standalone rebuild of an internal subsystem, written in D as a statically linked dub monorepo with no runtime dependencies.

📖 Documentation: https://re-cinq.github.io/ai-agent-subsystem/

Install

You need a Kubernetes cluster (v1.27+), kubectl, and permission to create cluster-scoped resources. One apply stands the whole subsystem up in its own ai-agents namespace — CRDs, RBAC, NetworkPolicy and the controller — with both images pinned to the cosign-signed digests that release built:

kubectl apply -f https://github.com/re-cinq/ai-agent-subsystem/releases/latest/download/install.yaml

Verify the controller is up and reconciling:

kubectl -n ai-agents get deploy,pods
kubectl -n ai-agents logs deploy/agent-controller

Agents call a model provider, so before a run can succeed create an agent-secrets Secret in the ai-agents namespace and reference its keys from your recipe — see the install guide.

With the controller running, define your first recipe from the examples/.

Build your own images

Not needed to install — the published images are public. Do this only when your cluster must pull from a private or air-gapped registry. You need Docker (with Buildx); both images build from the repo root — build them, tag for your registry, and push:

REGISTRY=your-registry.example.com/your-project   # a registry your cluster can pull from
TAG=v0.10.3

docker build -f deploy/Dockerfile.controller       -t "$REGISTRY/ai-agent-controller:$TAG" .
docker build -f scripts/container/Dockerfile.agent -t "$REGISTRY/ai-agent:$TAG"            .

docker push "$REGISTRY/ai-agent-controller:$TAG"
docker push "$REGISTRY/ai-agent:$TAG"

Point the manifests at your images. The controller image is set via the kustomize images: override in deploy/kustomization.yaml; the agent runtime the controller injects into each run pod is the AGENT_IMAGE env in deploy/controller.yaml:

( cd deploy && kustomize edit set image ghcr.io/re-cinq/ai-agent-controller="$REGISTRY/ai-agent-controller:$TAG" )
# then set AGENT_IMAGE in deploy/controller.yaml to "$REGISTRY/ai-agent:$TAG"

If your registry needs credentials to pull, create an image pull secret in the ai-agents namespace and reference it from the controller Deployment (and the injected run pods). Then apply the kustomization instead of the release artifact:

kubectl apply -k deploy

See the install guide for more detail.

The model

Three Custom Resources reference each other in a chain:

flowchart LR
    AD["AgentDefinition<br/>the recipe"] -->|agentDefRef| ST["Station<br/>the runtime"]
    ST -->|stationRef| AG["Agent<br/>one run"]
    AG -->|controller creates + owns| JB["Job → Pod"]
Loading
  • AgentDefinition — the recipe: prompt template, model, allowed tools, permissions, output sinks.
  • Station — the runtime: a Pod template plus a recipe reference and run-history limits.
  • Agent — one run: a Station reference, parameters, and a lifecycle status.

The controller watches Agents, builds a Job per run, supervises it, patches the Agent's status, and prunes old runs. The agent toolchain is injected into the run Pod, so Stations only need a glibc-based base image.

Architecture

A single dub monorepo (every package under packages/) producing three runtime binaries and a shared library, statically linked with LDC, plus crdgen/tsgen codegen tools:

flowchart TB
    CORE[["agentcore — shared library"]]
    CTRL["controller — binary"]
    INIT["initializer — init-container binary"]
    SUP["supervisor — binary"]
    CORE --> CTRL
    CORE --> INIT
    CORE --> SUP
    CTRL <-->|watch / create / patch| K8S[("Kubernetes API")]
    INIT -->|provisions| POD["Agent Pod"]
    SUP -->|runs inside| POD
Loading
  • agentcore — CRD types, Kubernetes client, the pure reconcile state machine, prompt templating, and the Job builder.
  • controller — the operator: reconciles Agents into Jobs and back.
  • initializer — the init container: clones repos and installs the agent CLI before the run.
  • supervisor — runs inside the Job Pod, supervises the agent process, and streams its output.
  • crdgen / tsgen — dev/CI tools that generate deploy/crds and the @re-cinq/agent-contracts TypeScript types from the annotated agentcore structs.

Repository layout

ai-agent-subsystem/
├── README.md
├── dub.json       # root: subPackages
├── packages/      # agentcore (lib) + controller, supervisor, initializer (apps); crdgen, tsgen, mockagent, itest (tooling/tests)
├── deploy/        # CRDs (generated), RBAC, controller manifest
├── scripts/       # drift checks, integration-test runners, container builds
└── website/       # documentation site (Astro Starlight)

Documentation site

The docs live in website/ and deploy to GitHub Pages on every push to main.

cd website
npm install
npm run dev      # local preview at http://localhost:4321/
npm run build    # production build

Requires Node.js 22+.

Contributing

CONTRIBUTING.md covers the toolchain, the make targets for building and testing, the integration-test tiers, and how the generated CRDs and TypeScript contracts stay in sync. The building guide on the docs site goes deeper.

Status

Active development. The controller, supervisor, initializer, and the agentcore library are implemented and covered by unit + integration tests, and tagged releases publish signed, SBOM'd images plus a one-command install.yaml. The CRD APIs are v1alpha1 (pre-GA) and may still change. See the roadmap for direction.

Releases

Cut a release by bumping the npm package to the version you are about to tag, then pushing the tag:

(cd packages/agent-contracts && npm version 0.11.0 --no-git-tag-version)  # in the release PR
git tag v0.11.0 && git push origin v0.11.0

The bump is part of the release PR, not the tag: @re-cinq/agent-contracts publishes the version committed in its package.json. scripts/check-contracts-version.sh runs on the tag and fails the publish if the two disagree, rather than letting npm reject a duplicate version quietly.

The Publish images workflow builds, pushes, and cosign-signs the controller and agent images for the tag (each with an SPDX SBOM and SLSA provenance attestation). It then renders deploy/ to a single digest-pinned install.yaml and attaches it to the GitHub Release — the artifact end users install with one command:

kubectl apply -f https://github.com/re-cinq/ai-agent-subsystem/releases/latest/download/install.yaml

Finally it opens a PR that pins deploy/ and the install page's cosign-verify example to the exact signed digests (sourced from the build, not a mutable tag), so main and kubectl apply -k deploy never ship a floating :latest. The local equivalent is scripts/pin-image-digests.sh.

License

Apache-2.0.

About

Run autonomous coding agents as first-class Kubernetes resources.

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages