Posted on :: Updated 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.

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. The factory is useful when those signals make it back to the people deciding what to do next.

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. This is reporting about one company’s internal setup, not a reference architecture to copy.

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 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 yet know which parts would help a small project and which would only add another layer of machinery. So I sketched a generic version of the 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.

What stands out to me in this version is not that every step is automated. It is that the agent has access to feedback from several parts of the factory. It can learn that a build failed, that a deployment caused a regression, or that an incident needs more context.

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 is probably how I have been using agents so far. The agent works on one part of the system, while I provide the connections to everything else. I notice that a check failed, find the relevant logs, decide what matters, and bring that context back to the agent.

That is manageable for a small project, but it hides part of the cost. The agent may be producing code quickly while I am doing the work of connecting it to the rest of the factory. The work has not disappeared. It has moved into my head and my terminal.

That does not mean the agent needs unrestricted access or permission to act autonomously. It may only need read access to the systems relevant to the task, with human approval still required for consequential actions.

For my own projects, the first question is not whether I can connect an agent to every system. It is which connections would remove work I am currently doing manually. A failed build might be easy to route to an agent. Deciding whether a feature is worth building is different. That still needs product judgement, even if an agent can gather the relevant evidence.

Human boundaries

Agency does not mean removing people from the system either. The boundary will not be the same for every change. I might be comfortable letting an agent inspect a failed build, suggest a fix, or open a pull request. I would be less comfortable letting it decide that a product change is safe to release simply because the tests pass.

That means the boundary is not just about whether a person approves the final deployment. It is also about who decides the outcome, what evidence counts as sufficient, and which actions the agent is allowed to take without asking.

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.

There is still a kind of feedback the factory may not produce quickly. Tests and production metrics can reveal certain failures within minutes or hours. A design that makes the next six changes harder may take months to expose itself.

That is the limit I keep coming back to. An agent can respond quickly to the signals available to it, but it cannot compensate for a factory that measures the wrong things. Faster loops are useful only when they are connected to useful feedback.

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?”