AIAI EngineerFeb 22, 2025· 17:11

Building Multi agent Systems with Finite State Machines

Adam Terlson argues that finite state machines (state charts) combined with the Actor model provide a structured, reliable foundation for building AI agents, addressing the predictability, observability, and control that LLMs lack. He introduces five agentic patterns—tool use, human-in-the-loop, feedback, collaboration, orchestration, and chartering—each demonstrated with concrete examples like a recipe-writing agent that checks inventory, a two-agent feedback loop for nutritional critique, and a multi-agent team delivering a meal. For orchestration, an LLM directs state transitions via event emitters, while chartering lets the LLM generate the entire state chart from a privacy-removal process. Terlson uses XState library for implementations and points to his demo 'Red versus Blue' for further exploration.

Transcript

Intro0:00

Adam Terlson0:05

Hi, I'm Adam Turleson, and in this video I'll walk you through how Finite State Machines provide a structured, reliable foundation for building applications including AI agents. As AI becomes more autonomous, the challenge isn't just intelligence or model performance; it's also how to build systems with predictability, observability, and control—especially important qualities when orchestrating large language models.

So the year is 2025, and the top AI trends, as listed by Gartner and probably everyone else too, is Agentic AI, where autonomous AI plans and acts to achieve all our hopes and dreams. But the number 2 trend, called out by Gartner, is just as, if not more, important, and that is the development of AI governance platforms.

We humans need to find a way to manage the ethical, legal, and operational performance of agentic systems. Now, State Machines probably don't have much to offer to the ethical or perhaps legal challenges of AI governance, but I believe they may have a foundational role to play in building platforms that effectively govern agent decision-making and behavior.

State Machines1:27

Adam Terlson1:27

So let's diveright in: what is a Finite State Machine? Well, it's a computational model of a system with states and transitions that are triggered by events. The example shown here is for the game of rock-paper-scissors. Our game is defined by five key components.

The first are the state definitions: this is a declarative set of system modes and configurations. In our game, it's the initial state of locking eyes, the parallel states where players are selecting their throws, all the way to the final state when the game is over.

There is transition logic for how we move between these states when events occur, like when we start the round, but these can also be targetless transitions, as is the case with rock, paper, and scissors. On shoot, we apply a guard, which enforces valid transitions.

So on the case of shoot, we check if the throws match, and if they do, then we go back to select another throw; otherwise, we can continue on in the flow. In each transition, we can apply actions and effects—side effects that are triggered by transitions, like sending a message or updating context.

And context is stored data that is used for transition logic and also final output. Now, the lovely nerds out there are likely yelling at their screens at this point, saying, "That's not a state machine, it's a state chart!"

You'reright. A state chart is an extension of the state machine that adds a richer vocabulary to the model, including things like hierarchical and parallel states, which I use in my game. In this presentation, however, I may use these terms interchangeably.

It'll be okay. A state chart models an application's behavior, but on its own it lacks essential capabilities needed to build a whole application. The Actor model complements State Charts by providing a framework for concurrent, distributed, and encapsulated execution.

Actor Model3:22

Adam Terlson3:43

That'sright, not an agent, an Actor. So what is an Actor? An Actor is an autonomous entity that interacts with other actors via message passing. Actors in software only have three capabilities: they can send and receive messages, they can update their internal state, and they can create new actors.

And of course, Finite State Machines can be used to define that actor's internal behavior or logic. So together, State Machines and Actors create a scalable and maintainable application architecture.

Pros & Cons4:24

Adam Terlson4:24

A mentor of mine at Best Buy said that in his more than 40 years in IT, he's never met a Finite State Machine he did not like. Why would he, today working as a Senior Principal Security Architect, say that?

And the answer is because of the significant advantages that State Machines bring to the operator. They are predictable, they're traceable and auditable, they're reliable and recoverable. If you lose your current state, you can actually recalculate it by playing your log of events.

If you only play back some of those events, stopping at a certain point in time, you can then create a new branch in history, effectively traveling through time. They're low latency. They're declarative, as we saw with the state chart itself.

They're easily tested. You can do what's called model-based testing, where you can be programmatically certain that your tests are exercising every valid transition in your machine. They're modular and adaptable, they're scalable, and they allow you to handle the most complex error scenarios, even implementing what's called the Saga's pattern for distributed transactions.

In the Saga's pattern, you have a transaction that takes place over multiple requests. If a step in the process fails, you can apply compensating transactions to undo the previous steps and get the customer back into a valid state.

Of course, they also come with challenges. There's a limited flexibility to the system, and if you're trying to model

a system with thousands, perhaps infinite number of states, your state can really explode. You have to model your transitions explicitly, and you can sometimes have an issue where an event lands on your machine that you haven't modeled yet.

And so, thankfully, your machine doesn't do anything in that case, except for log it for remediation. You do have to handle concurrency and parallelism because, as I mentioned before, the Actor can only process one event at a time.

This is where something like Azure Service Bus sessions and AWS SQS FIFO message groups would come into play. Versioning is a definite challenge, as maybe you have a state in one version that goes away in the next. Now, if you were to replay your log of events through your machine, what state do you land in?

You have to take this into account. And there's a learning curve associated with State Machines. I think that curve is a joy, but you may be feeling something elseright now.

LLM Fusion7:14

Adam Terlson7:14

What I want to draw your attention to is that these advantages brought by State Machines are everything that LLMs are not. LLMs are not predictable. They're not traceable or auditable. They're not reliable or recoverable. They're not declarative or low latency, etc.

The opportunity is that by combining LLMs and State Machines together, we can build a system that leverages the strengths of one to mitigate the weaknesses of the other. So we have our building blocks of agentic systems: our Actors enable autonomy and communication, the State Machine provides structure and enforces predictable behaviors, and the LLM enables dynamic intelligence.

So let's put these building blocks into action in the Agentic State Machines pattern showcase.

Tool Use8:16

Adam Terlson8:16

Our showcase begins, as did the human race, with tool use. Tool use is at the bottom of the autonomy chart because it really is foundational for the other patterns that follow. That is, it gives the LLM the ability to act.

In tool use, a description of available tools is passed to the LLM, including method names and expected arguments, and the LLM returns a response describing to the caller how the tool should be called. The LLM doesn't call that method directly.

The LLM then expects the next message in the flow to be the tool response. This is motivated by especially needing to give additional capability and functionality to the LLM, allowing it to take action. Tools can also be used to improve response relevance via retrieval-augmented generation.

In this example, a model with a prompt to create a recipe is given a tool to fetch the inventory first, so that the recipe return uses only the ingredients that are actually available.

Now,right away, we can talk about human-in-the-loop. Human-in-the-loop is something that State Machines are naturally very good at. This doesn't have anything to do with agents. But we all know that LLMs are famously unreliable, so how do we put controls around its use of tools?

Well, we can simply add an intermediate approval step and wait for an authenticated and authorized message to direct what happens next. In this example, the admin first denies and then approves the request.

Feedback9:59

Adam Terlson9:59

Next, feedback. In feedback, instead of having one agent, we have two. And agents, just like humans, improve over time with feedback. We need to give LLMs time to think, and iterating with feedback, either from another agent, another human, or both, can dramatically improve response quality.

In this example, our recipe writer from before sends its output to the critic agent, perhaps a specialist in nutrition. The critic sends its feedback back, like "use less sugar," and the recipe writer has the opportunity to improve its response.

Collaboration10:43

Adam Terlson10:43

Here, we have two agents working directly together. But what if we want a whole team of agents? Well, that is collaboration.

With collaboration, multiple agents, each specializing in their own small slice of a task, work together to achieve a broader outcome. This is motivated by the training limitations of LLMs and the scaling limitations of prompting them. We can't achieve broad, multi-faceted goals with a single prompt to a model.

Instead, we create specialized units and compose them together into a broader workflow. In this example of collaboration, multiple agents work together to deliver a meal to a customer. We have the recipe writer from before, but also an agent specialized in procuring ingredients, one that is responsible for preparing the meal, getting feedback, and finally publishing a report.

State Machines don't need to have a final state. In this example, the report, and any other context, is used by the recipe writer as feedback for how to continuously improve. With State Machines, that flow is predictable and tightly governed.

But what if we want to change that? What if we want to make the sequence of states itself determined by the LLM? And that is agentic orchestration. With orchestration, a centralized planning node can direct the next state. This is helpful when reasoning around context is required to determine the next state, for example, by understanding if the goal has been achieved and whether it can exit the flow.

Orchestration12:08

Adam Terlson12:39

Now, the example that I'm showing here got a bit big, so I apologize that it's hard to see. But notice the bouncing back and forth between various states and the central planning agent. The tool in this case that I gave to the planning agent was, in fact, a set of event emitters.

And then I implemented transition guards to enforce that these transitions are valid and direct to the appropriate state. So we're definitely having fun now. Beyond selecting the next state, how can we take this even further? Well, what if we gave the whole state chart over to the LLM and asked it to generate it?

I call this agentic chartering. I wasn't able to find much about this pattern online. There may be a better name for it, and if you know of one, please let me know in the comments. Chartering is helpful when you want to separate your planning phase from your execution phase.

Chartering13:25

Adam Terlson13:45

With chartering, the agent has the capability of inventing a wholly new and novel process to achieve its goal. With prompting and fine-tuning, one can imagine LLMs being able to build these processes using off-the-shelf patterns and tools, like predetermined events, known context, available actors, etc.

So, for example, I hate postal junk mail. When I get something sent to my house, I do my best to get myself off whatever list they were using to send it to me. Wouldn't it be nice if I had a personal agent that could do this work for me?

To experiment with this, I gave an article I found on privacyrights.org for how to remove myself from the White Pages Data Broker, and I gave this process to O1 to build a new process, and it did a remarkable good job, especially considering this was done essentially zero-shot with no examples given.

LLMs are also good at interpreting State Charts visually. Just think, we have 70 years of State Charts to train on. We could add a visualization agent as feedback to the chartering agent to get on how to improve its plan.

That's the fun thing about agents. Whatever the problem is, the solution is always to just add another agent.

So where is this graph leading? I think the answer is towards emergence. And now, that's one pattern I haven't been able to express with a state chart yet. But if we are going to achieve something that performs and feels like emergence, I do not believe it will be because we've created a system modeled more closely to the human brain.

Emergence15:19

Adam Terlson15:47

It'll be because we found a way to make building agentic systems feel like building with Legos. All the best technology, in my opinion, has this quality in common. Whether you're building an app with React Native, deploying it with GitHub Actions, or provisioning services on AWS with Infrastructure as Code, each of these technologies have a model of composing specialized units together into a broader system that is greater than the sum of its parts.

So perhaps in achieving that, the humble State Machine may have a foundational role to play for the next 70 years as well. A special thank you to XState, the library I used for all the state charts and visualizations in this presentation.

If you haven't tried XState already, it's a really powerful tool for tackling system complexity, and it's a joy to use, especially with the changes they made in v5. If you want to see these patterns in action, check out my demo "Red versus Blue," where I explore more about the operational side of State Machines, with a surprise emergence at the end.

Please reach out to me on LinkedIn if you have any questions, feedback, or just want to connect. Thank you so much.