I was challenged to design a workforce management system with a few constraints: make it highly customisable with fewer primitives, break it into smaller services, and design it to be built 99.5% by AI agents rather than people. What would you do differently if an agent was the primary developer?
I'm building Mosaic to find out. It's a platform spanning HR, scheduling, engagement, and payroll. But really it's a proof of concept for myself. I want to explore what it means to architect a system and have it built by an agent whilst I stay in the leading and architectural role.
Three Primitives Instead of Many Contexts
The system needed to work across different industries and countries without rewriting core logic. That drove me toward a small set of flexible primitives: entities (things that exist like people and locations), events (things that happen like shifts and absences), and participations (how entities relate to events, like being a worker or trainee).
A shift is an event. An absence is an event. A training session is an event. The differences are in their configuration, their attributes, their status workflows. This makes the system adaptable without constant code changes.
But here's what changes with an agent as the primary developer. If I were implementing this myself, I'd still create a Shifts context. I'd build Shifts.create_shift() and Shifts.assign_worker() as conveniences. These domain-specific functions would help me keep track of business logic and make the codebase easier to navigate as a human.
The agent doesn't need that layer. It can work directly with Operations.execute(:create, "event", nil, params, user) and understand from the configuration that this particular event is a shift. It doesn't need separate modules for each event type to keep the domain concepts straight.
What Changes in the Architecture
The codebase looks different when an agent is the primary developer. Everything becomes introspectable. The agent reads JSON blueprints at runtime to discover what entity types, event types, and participation types exist. It doesn't need these encoded in separate modules.
Operations are consistent and generic rather than domain-specific. There's no Shift.create() or Absence.approve(). There's Operations.execute() with different parameters. Queries build from parameters instead of calling named functions. This isn't because agents struggle with multiple functions. It's because they don't need the convenience layer.
Error responses include enough structure for the agent to understand what went wrong and fix it. A validation error returns which fields failed and why. A permission error suggests what the user can do instead. A concurrency conflict returns the current state so the agent can retry with fresh data.
Documentation becomes more important, not less. Module docs, function docs, inline comments. When a human writes code they understand the context implicitly. When an agent writes code, that context needs to be explicit. Good documentation helps the agent make better decisions about edge cases and understand how pieces fit together.
The specifications explain why the system is shaped this way, not just what it does. When I write "entities can form hierarchies" or "events have status workflows", the agent understands the implications without me detailing every case. It can figure out that hierarchies need parent references and recursive queries, that status transitions need validation and cascade rules.
The Human's Job
My responsibility is the system's conceptual integrity. Getting the primitives right. Thinking through how entities, events, and participations compose to handle workforce management's full complexity across industries and jurisdictions.
I write specifications that explain these decisions. The agent uses them to implement. When it gets stuck or heads in the wrong direction, I provide corrections. I review whether the implementation matches the intended architecture, not whether it follows style guides.
The valuable skill becomes architectural thinking. Understanding how to decompose problems. Recognising what's primitive and what's derived. Seeing where flexibility matters and where constraints help. These were always important, but now they're the primary value rather than implementation ability.
What This Means
If an agent can implement most systems given clear specifications, then architecture becomes the core work. Not framework knowledge or implementation patterns, but designing systems that make sense, explaining them clearly, and verifying the implementation matches intent.
That's a different way of thinking about software development. The code quality is fine. The question is whether the architecture is sound and whether you can communicate it well enough for an agent to build correctly.
Worth exploring what that changes about how we design systems.
Worth exploring what that changes about how we design systems.