You assign a task in one sentence. An agent reads your repo, writes a plan, makes the changes, runs the tests, fixes what broke, reviews its own diff, and opens a pull request. You review the PR like you would a junior’s. That is the promise of Devin, and of Cursor’s background agents, and it is not hype — it works.
Here is what bothered me. My source code gets cloned onto their machines. The work is metered per task, so the tool gets expensive exactly when it is useful. And the agent is a black box I configure but do not control — it does not know my conventions, my review checklist, my definition of done.
So over a few evenings I built the same thing on my own hardware, on the Claude Max subscription I was already paying for. I call it Origin, and it runs inside the self-hosted agent workspace I use with my team. This post is the architecture — the whole thing — because once you see it, you realize an autonomous engineer is not a moonshot. It is an orchestration layer over parts you probably already have.
The uncomfortable truth: it is mostly plumbing
I drew the entire system before writing a line of new code. Here it is:
flowchart LR
U["me / a teammate"] -->|"assign · or label an issue"| O["Origin surface"]
O --> ORC["orchestrator"]
ORC --> BR["Claude Agent SDK"]
BR --> WS["isolated repo clone"]
WS -->|"push branch + PR"| GH["GitHub"]
ORC -->|"run the tests"| TST["test runner"]
ORC -->|"verify the diff"| RV["auto-review"]
BR -.->|"plan · tool · diff · test · pr events"| O
GH -.->|"issue label / PR comment"| ORCNow look at what each box really is:
- The executor is a library. The Claude Agent SDK gives you the autonomous loop with real tools — a persistent shell, a file editor, git, web search, MCP servers. You point it at a directory and it reads, edits, and runs commands until the task is done. This is the genuinely hard part, and someone else wrote it.
- The git lifecycle is a shell script. Clone, branch, commit, push, open a PR. There is no AI in that,
and you want none — deterministic git means a hallucination can never push to
main. - GitHub is already an API.
ghopens the PR. Tests run with the repo’s own command. Review runs with whatever reviewer you already trust.
Roughly 70% of an autonomous engineer is infrastructure that already exists. When I mapped mine:
| Capability | Status | What it actually is |
|---|---|---|
| Autonomous executor (shell · edit · git · web) | Had it | Claude Agent SDK |
| Clone → branch → commit → push → PR | Had it | a shell wrapper |
| GitHub identity per user | Had it | gh + a token |
| Run the repo’s tests | Had it | the repo’s own command |
| Claim-verifying diff review | Had it | a reviewer agent |
| Live streaming of the work | Had it | the SDK event stream |
| Kill switch & approval gate | Had it | a stop flag |
| Run state machine + event log | New | two small tables |
| Isolated workspace + limits | New | a worker + worktrees |
| Plan → build → test → review → PR loop | New | the orchestrator |
| The UI (board · session · diff) | New | one tab |
The new work was small: a run record, an orchestration loop, and a UI to watch it. The agent brings the judgment. Everything around it is ordinary software I fully control. That framing is the whole unlock.
The loop that turns a demo into a colleague
A single “do the thing” agent call is a party trick. The thing you would actually let near a real repo is a state machine with checkpoints:
flowchart LR
Q([task]) --> P[Plan]
P -->|"⚑ approve plan"| B[Build]
B --> T[Test]
T -->|fail| B
T -->|pass| R[Review]
R --> S[Ship]
S -->|"⚑ approve push"| PR([Pull request])- Plan — read the codebase, break the goal into a checklist with explicit acceptance criteria.
- Build — implement in an isolated clone, streaming every command so I can watch it think.
- Test — run the suite. On failure, feed the output back and fix. Bounded to a few rounds so it cannot loop forever.
- Review — run a claim-verifying reviewer over its own diff before it dares ask me.
- Ship — push a work branch, open a PR with a written summary. It never merges to
main.
Two stages carry an optional human gate: approve the plan before a single line is written, and approve before anything is pushed. The default posture is the most important design decision I made:
Origin is a colleague who opens pull requests. It is not a bot with commit access to
main.
That sentence is the difference between autonomy I trust and autonomy I fear. I get the leverage of an agent that works while I am in meetings, and I keep the one thing that matters — the merge button.
Two tables and a handful of endpoints
The whole state lives in two tables. A run is a durable record; its events are an append-only log, so the session view rebuilds perfectly on reload and every action is auditable.
runs id · title · goal · repo · base_branch · work_branch
status (queued→planning→building→testing→reviewing→awaiting_push→done / blocked / failed)
plan · pr_url · budget · cost · approval_mode · member
run_events id · run_id · seq · kind (status·plan·tool·text·diff·test·pr·error) · payload
// append-only · redacted · drives the live UI and the audit trail
Everything the UI shows and everything the auditor needs is a projection of that event log.
The build, in six phases
I shipped it in dependency order. P0–P1 was a working MVP in about a week — assign a task, get a PR. Through P4 is the bar before anyone else touches it.
| Phase | Delivers | Effort |
|---|---|---|
| P0 Data model & surface | Run record, event log, an empty board on real endpoints | ~1–2 days |
| P1 Repo execution | Clone → agent edits in the repo → push → PR | ~2–3 days |
| P2 The loop & gates | Plan → test-fix → review, plan/push gates, steering | ~3–4 days |
| P3 Live session UI | Board + plan, streaming activity, diff, tests, PR | ~3–5 days |
| P4 Hardening | Isolation, secrets, guardrails, budget, audit | ~1–2 weeks |
| P5 Team integration | Issue-label & PR-comment triggers, per-project config | ~3–5 days |
The 90% nobody demos: making it safe
Every flashy autonomous-agent video stops at “look, it opened a PR.” The gap between that video and a tool your team uses every day is entirely in the unglamorous safety work. This is where I spent most of the time:
| Control | What it does |
|---|---|
| Isolation | Each run gets its own worktree under an unprivileged sandbox user, in CPU/memory/time limits |
| Scoped secrets | The GitHub token is injected into one run’s env, never persisted or logged; logs redacted |
| Guardrails | Work-branch only, no --force, a destructive-command denylist, a path allowlist |
| Secret-leak scan | The diff is scanned for keys before any push; a .gitignore assertion keeps .env out |
| Hard budget | A per-run dollar cap that stops at the ceiling, cost streaming live |
| Audit | Every shell command, tool call, and git op logged immutably — who, which repo, what |
An agent with a shell and your token is powerful and dangerous. You treat the token like plutonium. None of this shows well in a demo, and all of it is the reason I would point this at a codebase that pays salaries.
Why owning it wins
Self-hosting buys three things the hosted products structurally cannot:
- My code never leaves my machines. No third party holds the repo.
- The cost is a subscription, not a meter. Origin runs through my Claude Max plan. There is no per-task counter ticking up precisely when the tool proves useful.
- It works to my standards. My conventions, my PR checklist, my definition of done — because I wrote the harness. It reuses the same skills, budgets, and knowledge base my agents already share.
And because it lives in my own workspace, it composes: label an issue and a run spawns itself; comment on a PR and it fixes the thing. The autonomous engineer becomes part of the workflow instead of a separate portal I have to visit.
The takeaway for other tech leads
An autonomous engineer is not a product you are forced to rent. It is an orchestration pattern:
A capable agent SDK, running inside an isolated clone of your repo, wrapped in a deterministic git lifecycle and a plan-build-test-review-ship loop, with human gates and hard guardrails.
Buy the hosted version if the trade-offs suit you — it is a real product and it is good. But if you have private code, a fixed budget, and opinions about how your software gets written, know that the same capability is a weekend of orchestration on top of tools you already run. The leverage is enormous. The keys stay in your pocket.
That is the whole point.