Engineering story · Agent Swarm

A coding agent that never holds the keys

A sandboxed agent on a local open-source model that edits, tests and proposes changes without a repository credential

3 min readAgent SwarmRustDocker
Two agents · one credential · held by only one
Throwaway container Worker local open-weight model
edittestpush branch
Long-lived Gatekeeper holds the repository credential, checks the request, opens the merge request
Main branch Humans review no path from the worker
Everything a developer does up to proposing a change, and not the one thing that matters
0credentials in the worker
  • 0agent commits or merge requests against the main repository
  • 2full runs through edit, test, commit, push and merge request
  • 1failing-test run that stopped without pushing, scored as a pass

A coding agent running on a local open-source model edited code in a throwaway container, ran the tests, committed, pushed, and a merge request appeared for human review. The agent never held the repository credential and had no path to the main branch. A second, long-lived agent checked the request and opened the merge request on its behalf.

The challenge

Autonomous coding agents are useful in proportion to what they can touch, and dangerous in the same proportion. The usual compromise hands the agent a scoped token and hopes. I wanted a design where the worker could do everything a developer does up to the point of proposing a change, and could not do the one thing that matters: write to the repository everyone depends on.

Constraints

A local open-weight model served through vLLM on my own hardware, with no frontier API in the loop. A throwaway container, destroyed after the run. Humans review every change.

My approach

Split the job. The worker agent edits, tests and pushes to its own branch. A separate gatekeeper agent, long-lived, checks the worker's request and opens the merge request. The worker never holds the repository credential.

Worker
Gatekeeper
Repository credential
Worker to main branch
edit, test, push its own branchaskschecksmerge req.

What I built

Coder and gatekeeper personas with distinct tool grants.

A path by which the worker asks the gatekeeper to act on a finished branch.

Difficult decisions

A narrow scripted task for acceptance.

An impressive open-ended demo would have proved less.

The acceptance task was small and exact, so the security property got tested instead of the model's cleverness.

Counting a failing-test run as a success. One run's tests failed. The agent stopped without pushing. That is the correct behaviour and it was scored as a pass.

Results

Acceptance runs on an internal test repository:

Run 1
edittestcommitpushmerge req.
Run 2
edittestcommitpushmerge req.
Run 3
edittestcommitpushmerge req.
merge requests opened by the gatekeeper in runs 1 and 2run 3: tests failed, nothing pushed

Technologies used

Rust · Docker · Redis Streams · Open-weight local models on vLLM · GitLab API

What this demonstrates

Least-privilege design for autonomous coding agents, proven with an honest scope, on a local model.