Agentic Engineering
How I ship production software as a team of one, by engineering the system around the AI agents instead of prompting harder.
A production SaaS in a privacy-sensitive consumer domain: regulated user data, strict multi-tenant isolation, and real AI spend on every generation call. The interesting part is not that AI wrote code. It’s the operating system around the agents: 13 executable process commands, 3 specialized subagents, 4 lifecycle hooks, a written loop-engineering doctrine, and an audit practice that measures the machine.
The infrastructure
The agents ship into real production machinery, not a sandbox. Before any process doctrine, the substrate: a typed monorepo, a CI gate no PR can skip, per-branch preview deploys, and tracing on every AI call: the infrastructure a funded team would stand up, operated by one person.
Every PR runs typecheck, lint, migration checks, and the full suite: ~395 test files across unit, integration, E2E, and pgTAP. Every branch gets its own preview deploy; green CI is a precondition, and the human merge is the only manual step between a ticket and production.
Error tracking scrubbed of end-user PII by written rule. Every AI generation call is traced with token counts and per-call cost attribution, the ledger the July audit was built on. Alerts are tuned to page a team of one, not a rotation.
Postgres with row-level security enabled on every table, 83 migrations in. Agents build in isolated git worktrees that never touch each other's state; scheduled jobs handle retention and purge unattended.
The problem
One person cannot review every line, remember every decision, or babysit every CI run, and an ungoverned agent fails in predictable ways: it expands scope quietly, lets quality decay behind green-looking output, burns unbounded spend, and forgets everything between sessions.
“Move fast” and “never leak user data” had to hold at the same time, with no second engineer as a safety net.
What does an engineering organization look like when the headcount is one human and the rest is agents?
The operating system
Every ticket enters through a single gate: /ticket AIP-XXX loads the Linear issue and applies a canonical Definition of Ready before any code is written. Every ticket gets a verdict: only Ready proceeds. The same bar is applied read-only by the autonomous loop, so tightening it once propagates everywhere.
Goal, testable ACs, out-of-scope, definition of done, no hidden decision
An AC is vague: "make it work" is not an acceptance criterion
A required section of the spec is absent
The ticket hides a product or security choice an agent must never make silently
Custom TDD implementation: worktree, red to green
A heavier plugin-based rigor track for risky work
A discovery spike that ships a design doc instead of code
The endpoints are deliberately human: an agent never merges, and never invokes its own reviewer. The loop parks at the merge boundary. A post-deploy validation stage is the next planned gate.
Guardrails as code
No end-user PII in error tracking or analytics. Collect the coarsest data the feature can work with, by written rule. Every deletion of user-owned data writes an audit_log row in the same request handler.
Every new table enables RLS with explicit policies. no-unscoped-tenant-read statically fails CI on any tenant read not provably scoped to the authenticated tenant, including request-derived values laundered through local variables. Every tenant-owned route ships a two-tenant negative test.
"Stop": [
{ "hooks": [
{ "command":
"$CLAUDE_PROJECT_DIR/.claude/hooks/
typecheck-lint-stop.sh" },
{ "command":
"$CLAUDE_PROJECT_DIR/.claude/hooks/
codex-review-reminder-stop.sh" }
]}
]Loop engineering
“Run it in a loop” hides several different tools. The repo’s loop-engineering doctrine names them and matches each to a job: a recursive goal plus a find-work → act → verify → remember → stop cycle.
ScheduleWakeup) watching checks/babysit-prs (keep one PR green); /epic/epic, the backlog goal-loopHand it a Linear parent issue: it enumerates the work, topo-sorts by dependency, pressure-tests every AC, flags duplicate or fragmented tickets, and presents one checkpoint for human approval, then executes ticket-by-ticket in background worktree agents, waking only on external state, under a hard budget: maxCostUsd, wall-clock hours, 3 attempts per obstacle, then escalate. Written boundaries: never merge, never self-invoke review, never wake-poll work the harness already tracks.
Working in parallel
Loops decide when to repeat; a second axis decides when to run concurrently: read, implement, review, multi-ticket, batch. Work fans out only when the slices share no mutable state. Plans tag each slice with its file footprint at planning time, writers get isolated git worktrees, and every fan-out ends in a verify/merge stage. N agent outputs never ship unreconciled.
An early 4-way implement fan-out collided on one shared file. The lesson: test independence at the file level, not the ticket level. The /epic sequencer now checks this automatically, serializing overlapping tickets through merge.
Measuring the machine
In July I audited my own agent usage: a retro where the subject is the workflow itself. Parallelism was already the norm (124 of 145 dispatches, 85%, in parallel clusters) and worktree hygiene held: 42 enters, 52 exits, no leaks. But three gaps were invisible until measured:
agent calls overrode the default (most expensive) model
of PRs got the guardrails review fan-out, because it was optional
inline Linear API calls bloating the main session's context with ticket bodies it never needed again
The audit ends with re-measure targets and a date
Compounding memory
The effect is compound interest: the same mistake is structurally hard to make twice, and every new session starts smarter than the last one ended.
What generalized
Artifact library