01 · One pipeline, three forges
Every proposal goes through one router.
Agents produce proposals without knowing the forge. A router picks
the client for each repository from your configuration. The
assistant publishes a proposal only to a repository that the
configuration positively names. It refuses anything unmatched
at publish time. The GitLab client also refuses repositories that
your configuration assigns to another forge.
The same rule holds on every forge. The assistant opens drafts and
never merges them.
02 · The usual way in
A kubeconfig, and a network path to the API server.
A tool that reads a cluster normally needs two things. The first is
a kubeconfig with long-lived credentials. The second is a route to
the API server. That route can be a public endpoint, a VPN, or an
allowlisted static egress address on the tool's side.
For a customer cluster behind a VPN, that means a firewall change
and a credential to rotate for each cluster.
03 · Through the GitLab agent
The cluster dials out. Nothing dials in.
The GitLab agent (agentk) runs inside the cluster. It
keeps an outbound connection to GitLab's agent server (KAS). The
assistant talks to the Kubernetes proxy of KAS with a GitLab token
scoped to k8s_proxy. It builds its kubeconfig in
memory.
There is no inbound port, no VPN and no kubeconfig file. You grant
access in the agent's config file in git, to a project or group that
the assistant belongs to.
04 · What it may do, in git
The assistant's cluster role is a file you review.
On GitLab CE, every proxied request runs as the agent's service
account. So the agent's RBAC (Kubernetes access rules)
is the assistant's access. The access is read-only by
contract, apart from a few narrow, separately bound extras, such as a
request for a Flux reconcile.
That RBAC file lives in your deployment repository. The assistant
checks it for drift. If the assistant itself wants to change the
file, it escalates the change to human review before it opens an
MR.
05 · Keep the path up
Two agent replicas, two zones, one disruption budget.
Both agent replicas can land on one node. Then a single spot
reclaim or drain takes the whole KAS context down. Your CI deploys
and the assistant's reads stop together. The baseline pins zone and
host spread and a PodDisruptionBudget. The chart has no value for
these settings.
06 · Review the forge itself
Branch protection, CI secrets, the runner fleet.
Three rule-based reviewers read GitLab through a
GET-only client. They check project access and branch protection.
They check the merged CI configuration of every project. They check
the runners that each project can use. No AI model (LLM) is
involved.
Sometimes the assistant's own role cannot see an endpoint. Then it
opens one "could not review" advisory. It never reports a blind
review as a clean one.
07 · GitHub In development
Draft pull requests, same rules.
The GitHub client reads repositories, pull requests and history.
It writes draft pull requests. Writing needs three things: an
explicit write token, a writable repository row and a positive
config match. Without all three, the client makes no HTTP call at
all.
The client is built and tested. It waits for its first live write.
Known gaps: it cannot mark a PR ready, and it cannot assign
reviewers.
08 · Forgejo In development
Read path proven. Draft writer built.
The assistant reads a Forgejo repository with the same reader as
GitHub. A thin dialect layer handles Forgejo's API. At the same
commit, the reader returns byte-identical files to a local clone.
If a tree is too large to page through, the reader reports it as
incomplete. It never reports it as complete.
The writer for draft pull requests is built, but it has not made a
live write yet. Forgejo marks drafts with a WIP: title
prefix. So the writer reads the PR back and closes it if it did not
come out as a draft.
09 · The proposal
A one-line CI fix, found by the forge review.
Most forge findings are issues. A committed secret needs rotating,
not a diff. One finding is mechanical: CI_DEBUG_TRACE
left on. It prints every masked variable into the job log. When the
setting appears verbatim in the project's own
.gitlab-ci.yml, you get a draft MR. The full MR is
below.