Skip to content
The Agent Factory

Agents

A labelled issue, a Slack thread, your coding agent or RunLore starts a task; a scoper bounds it, a tester writes its contract, the implementer checks its work in the sandbox, a judge reads it against its checks, and a reviewer gives its verdict. A maintainer’s approval merges; link fixes and their reverts merge on their own (when a pull request merges). Runs are metered, capped, resumed after a reclaim and stopped by the kill switch; people follow and approve in rooms. What is available, what is experimental and what comes next are on the status page.

What it is

The LLM platform serves models; the Agent Factory puts them to work. A maintainer labels an issue, and agents (an implementer, then a reviewer) work it on their own branch in a gVisor sandbox. They open a pull request, and the factory narrates each step on the issue. Humans steer through GitHub reviews, or by joining the agents’ room. Only policy-defined low-risk changes merge themselves; everything else merges on a maintainer’s approval.

The Agent Factory is a bundle of open-source tools: Maku, agentgateway, OpenHands, gVisor, octo-sts, RunLore, Kueue and others. Maku is one component of it: the factory controller, the rooms, the harness and bridge, the Slack app and the maku CLI.

Which alternatives were considered, and why these choices? See Alternatives considered.

New here? The ideas in two minutes

TermIn plain words
AgentA language model in a loop: it reads a task, runs tools (shell, git, file edits, queries), looks at the result and decides the next step, until the task is done or its budget runs out
HarnessThe program that runs that loop inside the sandbox. Here it is OpenHands, wrapped by a small agent-run entrypoint that clones the repository, starts the conversation and prints a step log
RunOne agent, one role, one task, one branch, with a deadline. Declared as an AgentRun object in Kubernetes
RoleWhat a run is allowed to do. An implementer pushes to its own agent/<id> branch and opens a PR; a tester writes failing tests, which the harness signs and pushes; a reviewer or triager only reads and reports to the room, which posts a reviewer’s verdict on the PR
SandboxThe pod a run lives in, isolated by gVisor (a user-space kernel), with no long-lived credential and a network policy that denies everything not named
Run identityA token issued for that run only. Every call to a model or a tool carries it, and the run exchanges it for a short-lived GitHub token, so every action is attributed to the run that made it
agent-routerThe gateway every agent call goes through, an agentgateway Gateway (ADR-0053): it checks the run’s token, meters its tokens and routes to the model
RoomA shared, append-only log of a task: what each agent did, what humans said, the handoffs between roles. Humans watch it live, post into it, steer the running agent and approve its actions
FactoryThe controller that turns a labelled issue into runs, narrates progress on the issue, meters each run’s tokens and owns the kill switch
Merge gateThe rule that decides which agent PRs may merge themselves: only low-risk classes, only with green CI. Any other PR merges on a maintainer’s approval of its current head
ClassA kind of change the factory recognises, such as “link fixes only”. Roles and auto-merge are switched on per class
Live, shadowA live class merges by itself when every check holds; a shadow class is decided and recorded, but a human merges
TierA run’s size: its model, deadline and token budget (tiers)
TemplateWhich roles a task runs, for example solo (the implementer) or pair (the implementer and a reviewer) (templates)
Hand-offThe factory stops and asks a human for one action, in one comment on the issue
BreakerPauses a live class after a revert or a regression, until enough clean merges follow
DrillA revert made on purpose to test the revert path, labelled so the breaker does not count it

The agent in the loop is not a trusted component. Every control sits outside the sandbox:

  • network policy;
  • per-run identity;
  • scoped, short-lived GitHub tokens;
  • branch and tag rulesets;
  • token budgets;
  • the merge gate.

Architecture

At a glance

One task, end to end. A maintainer labels an issue; the factory starts a sandboxed agent run and opens a room; every call the agent makes goes through the gateway under the run’s own identity; the agent pushes an agent/** branch and opens a PR; a human review decides the merge.

The Agent Factory at a glance: one task, end to end. A maintainer labels a GitHub issue. The factory controller, maku-factory, turns the issue into a task, starts an agent run and opens a room on maku-broker. The run is a gVisor sandbox holding the coding agent, OpenHands. The maintainer watches and steers through the room, which exchanges events and steering with the run. Every call the agent makes goes through the agent gateway, agentgateway, with per-run identity and budgets, to the models (Z.ai GLM, Kimi and Mistral for public work, Claude for internal work), the MCP tools, and octo-sts for a GitHub token limited to agent/** branches. The agent pushes a branch and opens a PR on GitHub, where the maintainer’s review decides the merge. Traces, logs and metrics go to the Victoria stack and Grafana

Source: docs/architecture/agent-factory-overview.drawio.

In detail

The diagram below shows the target architecture, the whole programme once built. Its legend marks how far each box had got; where it and the status page disagree, the status page wins.

The Agent Factory’s target architecture. Triggers: a GitHub repository (the factory/ready and factory/stop labels; a PR review asking for changes), RunLore as an agent-to-agent client through POST /v1/tasks and signed webhooks, with its fix verdict, the task agent:run CLI, a developer in a browser who can also approve an agent action, the maku CLI, and a Slack thread where maku-slack drafts an issue and a maintainer’s check mark files it. The factory controller, maku-factory, turns a labelled issue into a task: intake and narration from a fixed template, then the Task controller, which starts one implementer per task, opens a room and runs the run meter, with a kill switch beside it. Around it: the reviewer pair and the revise flow, the run roles (scoper, tester with its test contract, implementer with search, completion judge, reviewer and splitter) switched on per class, and Kueue admission. The merge gate (policy-bot and a merger App) merges link fixes and their reverts, and judges other classes in shadow; the kill switch is the stop ConfigMap, the factory/stop label or a label on the control issue. Rooms: a web UI behind oauth2-proxy and ZITADEL SSO, maku-broker and its append-only CNPG log, with steering, room tools, verdicts, approval cards and forks from the web view or maku fork. The runtime turns an AgentRun claim, through Crossplane, into a default-deny CiliumNetworkPolicy, projected tokens and a gVisor Sandbox pod holding the maku-bridge sidecar, the maku-harness running OpenHands and an Envoy identity-proxy, on a GKE Sandbox pool on GKE or a Karpenter AL2023 pool on EKS. The proxy sends every call with a per-run JWT to agentgateway (Gateway agent-router in namespace agent-gateway, listeners public :8080, internal :8081 and sts :8082), which routes to Z.ai GLM-5.3, Moonshot Kimi K3.1 Pro and Mistral Medium 3.5 and Small 4 for public data only, the Anthropic API direct for internal data with a gateway-held key, Bedrock and Vertex AI optional per cloud, the MCP federation agent-mcp (flux-operator-mcp, mcp-victoriametrics, mcp-victorialogs and the room-broker’s room_* tools), and, behind the sts listener, octo-sts, which mints a token for the agents’ GitHub App, confined by rulesets to agent/** branches and no tags. The agent-ratelimit server enforces the budgets B1 per run, B2 fleet and B6 Anthropic on Valkey, refusing with 429 agent_budget_exhausted; model tiers follow the data class. The maku-bridge streams events to the broker over TLS with a room token, and the broker posts verdicts on the PR. Spans go through the agent-traces-collector to VictoriaTraces, step logs to VictoriaLogs, and access logs, gen_ai metrics and AgentRun state to VictoriaMetrics, all shown on the agent-run and agent-fleet Grafana dashboards. The same manifests deploy to GKE and EKS

Source: docs/architecture/agent-factory.drawio.

The parts

PartWhat it covers
RuntimeThe gVisor sandbox on each cloud, per-run identity, octo-sts, the branch and tag rulesets, network policy
Harness tuningWhich knob moves cost, time and quality; measuring a change; failure modes and recipes
Harness referenceEvery setting of a run, from the factory’s tiers to the OpenHands loop, with its value and status
RoomsThe broker’s append-only log, the bridge, the web view, steering, room tools, approvals
FactoryIntake, triage, teams, revise and the kill switch
RolesEvery role and a task’s life
The merge gateWhen a pull request merges by itself, approve-to-merge, the hand-off
Run auto-merge safelyTaking a class live, the breaker, drills and recovery
SlackHand work to the factory from a Slack thread
RunLoreAgent to agent: an incident in, a verified fix out
ProvidersKimi and Mistral for public work, switched on per class
GatewaysThe agent gateway: per-run identity, models, MCP tools, token exchange
ObservabilityPer-run traces, step logs, gen_ai metrics, AgentRun state, dashboards
User guideWhat a developer does with it

Everything that runs on the cluster is open source. The external services are GitHub and the model providers.

More than one repository

The factory can serve several repositories. Nothing in it is tied to one repository: the agents' App, the trust policies and the rulesets live in the repository they protect, and every token audience names its repository. Adding another needs:

  1. The agents’ GitHub App installed on it, and the factory’s App for narration.
  2. The octo-sts trust policies for the roles it allows, in that repository.
  3. The agent/** branch ruleset and the tag ruleset applied to it.
  4. Two platform changes: its four audiences added to the gateway’s token-exchange listener (at most eight per listener), and a factory intake that polls more than one repository.

Runs are per repository: a task never spans two.

Design documents