One day, ten pull requests, one release
At 08:45, pathmc had one way to answer a causal question. By 15:00, it had a second estimator, a shared interpretation layer, four documentation pages, a threefold CI speedup, and a new release. Nine pull requests had landed, and the whole thing cost $32.44 in model inference.
The agents kept working while I reviewed their output, handled the decisions that required domain expertise, and even had lunch cooked for me. The result is now available in the pathmc documentation. This is the story of how that day unfolded, and what I learned about making AI-assisted engineering move quickly without handing over the important decisions.
The feature
pathmc is a Bayesian causal inference library. Until this morning it had exactly one way of answering a causal question: build a structural causal model, encode the full data-generating process as a system of equations, and reason about interventions by surgically replacing nodes in that system with do(). That approach is powerful and principled. It is also a big ask. You have to be willing to write down the whole mechanism.
Most people doing applied causal work don’t start there. They start from a DAG, identify a backdoor adjustment set, fit an outcome regression conditioning on that set, and read off the effect by contrasting predictions under different treatment values. That is the language of the potential outcomes literature, of dowhy, of marginaleffects. It is what a large fraction of practitioners already know.
Today pathmc grew that second estimation approach natively: an AdjustmentModel that takes a DAG and an adjustment set, fits a Bayesian outcome regression, and exposes backdoor-identified estimands. Alongside it, a shared interpret layer containing predictions, comparisons, and slopes works identically whether you came in through the SCM door or the adjustment door, so the two estimators produce comparable output on the same problem.
That is not a feature. That’s a second front door to the library, plus the plumbing that makes both doors lead to the same room. The estimand semantics have to be right, the identification has to be enforced rather than assumed, and the docs have to teach a user which door to walk through and why. Getting all of that from an idea to a merged, documented, released state between breakfast and the school run is the thing this post is about.
The process
Starting from a plan, not a prompt
The day did not begin with “implement regression adjustment.” It began with about an hour of hard conversation with what I came to think of as the orchestrator agent, Grok 4.6 High Fast, held in one long-lived session, given the birds-eye view and never asked to write production code.
The output of that hour was a real design, decomposed into six child issues: construction and fit, the interpret API, a docs retcon, two new concept pages, and a figure-first gallery.
That hour was mostly Q&A. What is the public API? Does AdjustmentModel share a base class with PathModel or just an interface? What exactly does comparisons mean when the estimator is an outcome regression rather than an SCM? Which of these can proceed in parallel and which are genuinely blocked?
I want to be blunt about why this worked, because it is the load-bearing part of the whole day: I already understood the causal concepts. I was not learning backdoor adjustment from an agent. I was making API and scope decisions in a domain I know well, at the speed I can make them, which is fast. Every one of those decisions became a constraint that the worker agents could not get wrong, because it was written down in an issue before any of them started.
The decomposition mattered as much as the design. Six issues with explicit dependency structure meant that at any moment I could see which work was unblocked, and unblocked work mapped one-to-one onto an agent I could launch.
Worker agents in parallel worktrees
Implementation went to a different model, Composer 2.5, with one agent per issue, each in its own git worktree, running locally and in parallel.
The loop each agent ran was fixed:
- Implement the issue.
- Open a PR.
- A sub-agent reviews the PR and comments on it.
- The original agent addresses the review comments and reports what it changed.
- Repeat from step 3 until the reviewer is satisfied, capped at three rounds.
The first wave produced an AdjustmentModel for backdoor outcome regression and a shared interpret query layer on PathModel. Both converged after a handful of review rounds.
The self-review loop is the part I would recommend to anyone without reservation. It is fully automated, it needs no supervision, and it works. The code that arrived at my review gate had already been through two or three rounds of adversarial critique by an agent with no ego investment in the original implementation. I was reviewing second or third drafts, not first drafts. The quality difference is not subtle, and the cost of those extra rounds is rounding error against the cost of me reading a bad diff.
Once the first wave landed, three more agents went out in parallel, followed by a final agent handling the remaining documentation work.
The side quest that paid for itself
Somewhere in the first wave, CI became the bottleneck. Recent successful runs were taking 32 to 34 minutes, so I put one agent on diagnosis while the feature work continued. PyTensor compile time pointed to parallelizing the suite with pytest-xdist, cutting the full job to 11.7 minutes.
That detour bought back time on every subsequent pull request. Fixing your own tooling mid-task stops being a distraction when the main work continues in parallel.
Docs as a first-class deliverable
Four of the six child issues were docs. That was deliberate. A second estimation approach that nobody can find their way into is not shipped.
The docs work produced:
- A concepts page comparing SCM and regression adjustment on one shared problem, so the reader sees two estimators answer the same question rather than two disconnected tutorials.
- A retcon pass updating the existing estimation-approaches and comparison pages, and the internal skill, to acknowledge that adjustment is now native rather than something you hand-roll.
- A concepts page for predictions, comparisons and slopes.
- A figure-first interpret gallery.
This is where my time went, and where the day slowed down. I read every page manually. The SCM-vs-adjustment page (/user-guide/scm-vs-adjustment.html) was very good on the first pass, and I suspect a private skill encoding how I want causal material explained deserves much of the credit there. The estimation-approaches page was good but not right, so I had the orchestrator introduce one DAG with a graphviz figure, then illustrate both estimators on it.
The predictions/comparisons/slopes page I was not happy with. It did not match my vision. So another agent produced a figure-first gallery. Much better.
Note the pattern. I did not open an editor and fix the docs. I read them, articulated what was wrong relative to a vision I hold, and let the orchestrator turn that into a scoped issue that a worker agent could close. My contribution was taste, expressed as an issue.
Velocity in this phase was visibly lower than in the implementation phase, and that is not a failure. Manual docs review and housekeeping are the steps where a human is actually required, and they are the steps that cannot be parallelized away. By the last docs review my brain was flagging and I got myself a coffee, which is roughly the honest signal that you have hit the end of a productive day.
Wrapping up
Final checks, including every new public method and function present in the API reference, the version bump, and the changelog, went to the orchestrator, because after seven hours it is the only participant with the whole picture in one context. That became the release wrap-up.
The docs go live on merge. The functionality does not reach users until a release, so 0.3.0 gets cut and the day is done.
What it cost
| tokens | spend | |
|---|---|---|
composer-2.5 (workers) |
49.1M | $11.56 |
cursor-grok-4.6-high-fast (orchestrator) |
35.9M | $20.88 |
| total | 85.0M | $32.44 |
Caveat on the orchestrator line: Grok 4.6 High Fast shipped yesterday and is currently at 50% off, so the real-world number is roughly double.
Call it $32 of inference and six and a quarter hours of my attention for a second estimation approach, a shared interpret layer, four documentation pages, a 3× CI speedup and a release.
The token split is the interesting number. The orchestrator burned 42% of the tokens without writing production code. Planning, decomposition, scope arbitration and final housekeeping are not overhead you optimize away; they are where the leverage is. The workers were cheap precisely because the thinking had already been done.
Lessons
Domain expertise is the multiplier, not the model. I moved fast because I know causal inference. Every scope question, every API judgement, every “no, that’s not what a comparison means here” landed in seconds rather than in a research detour. Agents make an expert dramatically faster. I have no evidence they make a novice into an expert, and today is not that experiment.
Plan in one long-lived context, implement in many short ones. The orchestrator held the design and dependency graph all day. The workers each held exactly one issue. Neither could have done the other’s job: a worker with the whole picture loses focus, an orchestrator that writes code loses the plot.
The idea existed; the morning turned it into work packages. The core concept was already developed before today. What the first hour actually produced was the translation from concept to six independently-executable issues with an explicit dependency order. That translation is the skill. Handing an agent “add regression adjustment” would have produced a mess.
Automated review is free quality, adopt it immediately. A reviewer sub-agent commenting on the PR, the implementer addressing the comments, capped at three rounds, no human in the loop. Fully automated, and it worked every time. Everything reaching my review gate was a second or third draft.
Fix your tooling mid-flight. A 32-minute CI cycle would have capped the whole day. Fixing it cost one parallel agent and bought back time on every subsequent PR. Because the fix ran in parallel with the feature work, it cost almost nothing in wall clock.
Taste is expressed as issues, not as edits. Three separate times I read generated docs, disliked something specific, and converted that into a filed issue instead of a manual edit. That kept me operating at the level where I add value and kept the agents doing the typing.
The manual bits were exactly the bits I’d automate next. Two things ate my day and neither was interesting: waiting for CI to finish, and resolving merge conflicts. Both are highly automatable and I would structure them differently next time: a proper merge queue, agents that rebase and resolve their own conflicts without me shuttling worktrees around. This bit me repeatedly, since a workflow built on many parallel branches merged in sequence generates conflicts by construction.
But I’m not handing over the merge button yet. Review is automated, implementation is automated, conflict resolution should be automated. Merging to main stays mine. That is not a technical limitation, it is where I currently want the human gate to sit, and the honest version of an agentic workflow post says which gates you kept, not just which ones you removed.