Posted on ::

When I first came across the term software factory in discussions about coding agents, I assumed it meant writing a task and handing it to an agent. The agent would gather the context, write the code, run the tests, open a pull request, and perhaps even deploy it. It sounded like a new, agentic way of building software.

Then I saw Dex Horthy’s diagram, and it changed how I understood the term. I realised I had been a part of software factories for years. The task tracker, repository, pull request, CI system, deployment process, monitoring, incident response, and users were already connected. A factory was not a new thing that used agents. It was the system I was already using to turn a problem into a change in a running product.

An agent changes one part of that system. It may take on more of the implementation, testing, investigation, or operational work, but it does not create the queues, hand-offs, or feedback loops around that work. Those were already there. I just had not been calling them a software factory.

I have also been thinking about this in practical terms. What would it take to build a small software factory for my own projects, with agents helping me prototype ideas, build them, maintain them, and investigate problems once they are running? Looking at the whole system seems more useful than starting with a particular agent or tool.

Reading Donella Meadows’s Thinking in Systems helped me make sense of this. One lesson I took from it is that a system’s behaviour comes from how its parts interact, not from the parts themselves, and that pushing harder on one part rarely fixes the system. CI is just one machine in the factory. The factory is the whole system: people and components connected by flows of work and information, operating towards some purpose.

Here is the diagram that changed my view of it. It shows the software factory around implementation: users, product managers, engineers, pull requests, tests, deployments, monitoring, incidents, and feature requests.

Dex Horthy’s “A Software Factory Circa 2022” diagram, showing product decisions, implementation, pull requests, testing, deployment, monitoring, users, incidents, and feedback loops.

Dex Horthy, “Why Software Factories Fail”.

What I find useful about the diagram is that it does not stop at deployment. It shows how information from users and production feeds back into what gets built next.

Two connected loops

Before seeing Dex’s diagram, I would probably have described software delivery as a series of separate pipelines. A product decision became a task, the task became code, the code passed its checks, and the change was deployed. That work would lead to the next task or another change, but I thought of those as separate pieces of work.

The diagram gave me a different way to look at something I already understood. It made the connection explicit. What happens after deployment feeds back into the next decision. I had always been part of that process. I just had not thought of it as a loop, or seen all of its parts as one software factory.

The first loop is the delivery loop: a decision becomes a change, the change is built, reviewed, tested, and deployed. The second starts with the product rather than the code. Users, monitoring, incidents, and feature requests produce information that feeds back into the next decision.

I sketched the two connected loops together as a single flow below. Production is not the end of the process. It is one of the places where we find out what the change actually did.

Two connected software factory loops showing delivery and product feedback from users and production. Two connected software factory loops showing delivery and product feedback from users and production.

These loops meet when somebody decides what to build next. The delivery loop asks, “Can we change the software safely?” The product loop asks, “Is this the change we should make?”

Those are separate questions. A team can get very good at shipping the wrong thing. It can also understand the product problem clearly and still be unable to deliver a safe change without a long queue of manual work.

What the factory produces

Seeing the work as two loops changed what I thought the factory was producing. The obvious output is a deployable artefact: a change to the software that can be released to users. But the factory also produces information.

  • Did the change solve the problem?
  • Did it create a new failure mode?
  • Did users understand it?
  • Did it make the system harder to operate?
  • What should we change next?

That information comes from different parts of the factory. Tests tell us about behaviours we thought to check. Static analysis finds certain classes of mistake. A review can expose a confusing design or a missing operational detail. Monitoring tells us what happened after deployment. Users tell us whether the change was useful in the first place.

None of these signals answers the whole question. A green build does not mean that users are happy. A successful deployment does not mean that the system is healthy. A passing unit test does not mean that the change belongs in the product.

That was the part I had missed when I thought of a software factory as an agent processing a task. I was focused on the change it produced, rather than the information the wider system produced about that change.

The factory is useful when those signals make it back to the people deciding what to do next.

That was my original mistake when I thought software factories were mainly about agents. I was thinking about how an agent could produce a change, but not about how the wider system would tell it whether the change was useful, safe, or worth keeping.

What changes when an agent joins?

The question is not simply how much code an agent can write. It is what happens to the rest of the factory when an agent takes on part of the work.

Dex’s agentic diagram helped me see that the change may be local. An agent can replace or expand the implementation step, but the rest of the factory still has to review, test, deploy, and observe the change.

Dex Horthy’s agentic software factory diagram, showing an agent replacing the human implementation step while review, testing, deployment, and production feedback remain in the loop.

Dex Horthy, “Why Software Factories Fail”.

That seems obvious when written down, but it is easy to forget when an agent produces a working pull request quickly. The pull request is only where the change enters the rest of the factory. It is not the end of the work.

A diagram published by The Pragmatic Engineer illustrates a more elaborate version, based on interviews about OpenAI’s internal system:

The Pragmatic Engineer’s reported agentic software factory, showing context gathering, automated build and test, specialist review, risk-based deployment, production monitoring, performance feedback, and incident response.

The OpenAI example pushes further. It suggests that agents can remain involved after the merge, gathering production context, watching for regressions, and helping with incidents.

I find that interesting, but I do not see it as a reference architecture to copy. It raises a more practical question for me: which parts of that loop would actually help a small project, and which would only add another layer of machinery?

This is reporting about one company’s internal setup, not a reference architecture for every team. Here is a generic version of that flow:

An agentic software factory in which a human defines the outcome, an agent builds and tests the change, risk determines the review path, and production feedback returns to the backlog. An agentic software factory in which a human defines the outcome, an agent builds and tests the change, risk determines the review path, and production feedback returns to the backlog.

In the generic flow, an agent gathers context from the code, documentation, and internal tools, writes a change, and keeps fixing issues until the build and the checks pass. Specialist review agents inspect the result, and a risk classification decides whether it follows an automated path or needs human review.

In the system described by The Pragmatic Engineer, the loop continues after the merge. An agent helps roll the change out to production, watches the relevant signals, and can create monitoring dashboards for the change. A performance system looks for regressions and proposes fixes. An incident-response bot gathers context and suggests mitigations when something goes wrong.

Dex’s response is to turn the lights back on, not to abandon automation. If agents make implementation much faster, review becomes the next bottleneck. Removing human review can increase throughput for a while, but it also removes one of the few places where somebody might notice that a change is making the system harder to understand or modify. In the second part of his series, he argues for moving human judgement earlier in the process: agree the product requirements, system architecture, and shape of the program before asking an agent to implement it, then work in small vertical slices that can be checked as they are built.

Agents as participants

That is a much more ambitious factory than “ask an agent to write some code”. It gives agents access to the context around the code, lets them act on feedback from the build and review systems, and keeps them involved after deployment.

If an agent can reach the wider factory only through a human at a terminal, the human becomes the integration layer. They have to notice a failed CI job, collect the logs or metrics, decide what is relevant, and bring that context back to the agent. This makes each loop slower and means the agent sees only the part of the problem the human thought to provide. An agent connected to the factory can query those systems itself: inspecting CI results, reading production logs, comparing metrics, and gathering the context it needs before proposing what to do next.

That connection does not require unrestricted access or permission to act autonomously. Access can be read-only and limited to the systems relevant to the task, with human approval still required for consequential actions.

An agentic software factory does not need to be fully automated. A person might start an agent manually, mark a feature request as ready for an agent to pick up, or route a failed build, production regression, or incident directly to one. How an agent gets kicked off, manually or automatically, is a design choice, not part of the definition. What matters is that the agent takes part in the factory’s flows of work and information: it can gather the relevant context, act within its permissions, and respond to the results of its work rather than merely suggest the next line of code.

For businesses already experimenting with coding agents, I think the next step is to optimise the software factory around them. It is not simply a matter of giving every developer an agent. Businesses need to look at their existing software factory and decide how it should work when agents become participants: which queues they can take work from, what context and tools they can access, how their output is checked, and where people need to approve an action. Most software delivery systems have been built around human teams, so adding agents means reconsidering those interfaces and hand-offs rather than dropping a coding tool into an otherwise unchanged process.

Human boundaries

Agency does not mean removing people from the system either. A human still needs to be in the loop at the points where judgement or accountability matters. Depending on the risk, that might mean deciding when to start the agent, reviewing its proposed change, approving an action it wants to take, or approving its deployment. The boundary will differ between teams and between changes; the important part is that it is deliberate rather than whatever the tooling happens to allow.

Deliberate boundaries also make the human responsibilities easier to see. People still need to define useful outcomes, make the relevant context available, decide what counts as low risk, ensure the tests describe acceptable behaviour, choose the signals that matter, and decide where an agent must stop and ask for help. Automation changes the boundary of the work; it does not remove judgement from the system. A change marked as low risk can still be wrong, so the classification and the automated path need their own checks.

Closing the feedback loop

The most important detail in the diagram is the feedback path from production back to the coding agent. An agent that can write code but cannot observe its consequences is just a faster way to create a queue of changes. An agent that can see failures, understand their context, and propose a fix starts to look more like a participant in the factory.

The agent does not need to remain active or control every stage. The factory could route the results of a failed build, deployment, or production alert to an agent with the relevant context. What matters is whether that path exists. Without it, the wider feedback loop is available to the human but closed to the agent.

Even when those feedback paths exist, there is another limit: an agent can only respond to signals the factory can produce. This is part of Dex Horthy’s wider argument. Tests and production metrics can quickly reveal certain failures, but maintainability has a much slower feedback loop. A design that makes the next six changes harder may not reveal itself until months later. This is not unique to agents, but faster implementation allows more of those design decisions to accumulate before their consequences become visible.

Where factories get stuck

A factory can have plenty of automation and still be slow.

If every change waits several days for a review, producing the initial change faster will not fix the queue. If deployments are frequent but nobody looks at production behaviour, the factory is producing changes without learning from them. If feature requests arrive faster than the team can understand and prioritise them, adding more implementation capacity will not fix that decision queue.

The slowest part of the system is often not the compiler or the test suite. It is a hand-off:

  • an engineer waits for somebody who understands the product decision;
  • a pull request waits for a reviewer who is also busy building something else;
  • a deployment waits for somebody to perform a manual check;
  • an incident waits for information that is spread across several systems;
  • a user report waits for somebody to turn it into a reproducible problem.

This is why the arrows in the diagram are as important as the boxes. A box describes an activity. An arrow describes how work and information move between activities.

A factory is not an assembly line

There is a risk in taking the factory analogy too literally. Software is not a pile of identical widgets. The work includes discovery, judgement, and learning. The thing being built often changes shape while we are building it.

Optimising only for throughput can make a team worse at its actual job. We might measure the number of pull requests merged, deployments made, or tickets closed because those numbers are easy to count. That does not tell us whether the product is becoming more useful or whether the system is becoming easier to change.

The useful part of the analogy is not “make engineers work like machines”. It is “look at the complete system”. Where does work enter? Where does it wait? Which checks happen automatically? Which decisions need a person? How quickly does information from production get back to the team?

The factory should make good changes easier to make and bad changes easier to notice. It should not turn every decision into a race for a higher throughput number.

What I want to try

I have been thinking about what a small software factory might look like for my own projects. I want to experiment with agents not only as a way to implement tasks, but as part of a system that helps me with the same four jobs I mentioned at the start: prototyping ideas, building them, keeping them maintained, and investigating failures.

Headcode is an obvious place to start. In Splitting Headcode into a polyrepo workspace, I described separating it into smaller repositories with clearer boundaries, repository-local checks, and a separate place for agent work plans. I made those changes partly to give agents bounded contexts. That workspace is not yet a software factory, but it gives me a practical system in which to explore how work moves between agents, repositories, checks, deployments, and production feedback.

I do not mean a lights-off factory that can be left to ship changes on its own. The interesting part is deciding which loops I can automate safely, where I still need to make decisions, and what context and signals an agent would need to do useful work.

To start with, I will keep most of the agent use manual: running an agent when I choose to, rather than wiring it to a trigger. Starting that way keeps costs predictable while I work out which loops are worth automating, and it keeps me close to what the agents are actually doing before I let them run on their own.

That raises more useful questions than simply choosing an agent:

  • Where does work enter the factory: a Linear ticket, a failed build, a production alert, or a note to myself?
  • How do I describe the outcome rather than only the implementation task?
  • What code, documentation, and operational context does the agent need?
  • Which checks provide meaningful feedback rather than merely producing a green build?
  • Which changes are safe to automate, and where should the agent stop?
  • How does information from maintenance, failures, and actual use make it back into the next change?

Adding another tool is not the same as improving the factory. A new tool only helps if it removes a real delay, improves a useful signal, or makes a risky decision safer.

I have not built that system yet. In follow-up posts, I want to explore what an agentic software factory looks like in practice, starting with personal projects where I can experiment freely and document what I learn. I am also interested in seeing how these ideas could apply to the systems I work with professionally, where I have permission to experiment. Thinking of it as a factory gives me a better place to start: not “which agent should I use?”, but “which loop am I trying to improve?”