In the book Soul of a New Machine profiling a team of computer engineers developing a novel product, the “soul” is the people: the engineers sacrificing their sleep, time, and sanity to create the Eagle. They finish the design, send it to manufacturing, and get some rest at the end of their Pulitzer-prize-winning development process.
While the people and practices in the book are still relatable decades later, the way software developers ship our work doesn’t grant us a tidy hand-off like the one the Eagle team enjoyed. Many services from companies such as Stripe, Salesforce, and Atlassian blur the lines between software, human, and business processes. In addition to being the soul of their machine, software engineering teams, with varying levels of awareness and competence, can find themselves performing unexpected functional roles within the systems they build: not the soul, but the spleen… or worse.
Understanding the scope of the machine beyond the compiled code, and the engineering team’s role in it, is critical to scaling a business, building a healthy team, and avoiding burnout. And in the era of AI, understanding the roles of both humans and machines in an organization is essential to finding the right places to incorporate agents.
A machine: something that uses energy to perform work toward a specific purpose. Doors, faucets, cars, dishwashers, phones, and laptops are all physical machines. The definition easily stretches to include software: apps running on the phone, programs running on a laptop, even web sites. But it goes broader still! A human has the ability to fill the role of a machine. Throwing a ball? You’re a pitching machine. Driving a car? Cars drive themselves now so I guess you’re like a driving machine. Writing a poem? The jury is still out on that one.
Businesses go to great lengths to present their interface to the public as a simple machine. Customers like simple machines. Press Button, Get Food: this is my interface to DoorDash, regardless of how many steps along the way involve a large and varying number of humans and automated systems.
It’s difficult to present a facade of a simple machine over a collection of complex and unreliable parts. Figuring out how to do it is one of the primary daily tasks of system engineers. But what is an engineer?
Engineers design the machines to achieve their purpose! At least that’s what we like to think. However, in modern software-as-a-service development practice, it’s only part of the job.
Engineers are placed (or place themselves) within the workings of their machines in various ways. Are you on-call, where you must take a corrective action when part of your machine fails? From the perspective of the service’s customers, you are part of the machine. Do you respond to support tickets by customizing the customer’s software? From their perspective, you are part of the service. Do you monitor health of the system over time, and take action when something looks degraded? You’re a link in that feedback loop; you’re a part of the machine.
Any role engineers perform where the machine would stop running if it wasn’t done, is really part of the machine itself. Has your team put as much care and thought into those aspects of the system as you put into the code?
The title of this section references the dystopian train from Snowpiercer. I’ll avoid spoilers, suffice to say you don’t want to be part of that machine. Tragic fates await engineering teams that don’t acknowledge and manage their role in their machines due to denial, greed, short-sightedness, or other reasons.
Some engineering teams determine that they are not part of the machine, because they shouldn’t be: software services should be self-healing and not require manual intervention. Once deployed, it runs on its own. This is a noble goal and can be achieved, but when reality doesn’t match the ideal the team’s role in the machine will be ad-hoc and, from the customer’s perspective, unreliable.
Some managers understand their engineering team’s role in the machine, but don’t want to pay for a sufficient team size to support it. This is a common problem. It leads to operational burden falling on a small number of engineers without regard for working hours, leading to turnover and unreliable service from the customer’s perspective.
Some engineers, under pressure from a deadline, might see a manual process as a way to finish their work more quickly. No time to build the workflow for enabling ShinyThing? Have the button send an email to the engineering team and they’ll do it manually! This approach works in the short term, but it’s too slow to match most customer’s expectations. It becomes a tax on attention and capacity over time, and it doesn’t scale.
Preventing the issues caused by inadequate design around human participation in a service starts by acknowledging the real roles the engineering team and others in an organization perform in a product’s operation. From there, the human functions can be carefully designed around the capabilities and limitations of the team. Google and others have written a lot about this, yet simply talking carefully through the various ways humans are involved in the operation of a product and consciously designing those roles might be enough.
There’s a current gold rush in incorporating LLM-powered agents into software products. It’s unclear what the common practices will become, but the agents are quite different in their capabilities than software advances that have come before. Rather than focusing solely on augmenting the software components, taking a broad view of all the human processes of a business surrounding the software will probably lead to better results.
Maybe many key activities currently performed by engineers or other disciplines within a business, the human elements of the business machine, can be performed instead by agents. Maybe my DoorDash will soon be delivered by self-driving car. In the case of the engineering team’s role, we can hope LLMs can start taking over much of the operational and monitoring burden. But it will remain important to admit to the roles humans will continue to fill, or the same problems listed above will arise all over again in slightly different forms and services will become worse in the eyes of customers.
If you’re in a role where you are designing a machine, take a wide view, of not just the code, but of the surrounding systems involved in achieving the purpose for the user. Admit it to yourself when you are making yourself or others part of the machine and treat those aspects with the same design discipline you might apply to the software, and with more respect.
If you are considering LLMs, look broadly at where they can fit, but acknowledge the continuing need for human checks and accountability. Through careful design and thoughtfulness we can make the software and LLMs replace us in the fixed-function or tedious roles in a system, leaving the “soul” to us humans.