AI Engineer Summit 2025

Building Multi-agent Systems with Finite State Machines

Read the talk

Building Multi-Agent Systems with Finite State Machines

Statecharts make agent behavior explicit, from guarded tool calls and human approval to collaborating specialists, central planners, and generated workflows.

From a talk by Adam Terlson

Before you start: Familiarity with LLM tool calling and basic TypeScript will help; statecharts and actors are introduced from first principles.

What controls an autonomous agent?

An AI system can plan and act, but how do you make its behavior predictable, observable, and controllable? Better model performance alone does not answer that operational question. Adam Terlson starts with this gap: as models gain autonomy, the surrounding application needs a way to govern their decisions and actions.

Terlson points to agentic AI and AI governance platforms as the first two trends listed in Gartner’s 2025 outlook. Governance includes ethical, legal, and operational performance. State machines do not resolve all of those concerns; their contribution here is narrower and concrete: define which behaviors are possible and enforce how execution moves between them.

0:040:23
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

0:04 · section reference included

A game makes the control model visible

Consider rock, paper, scissors. A finite state machine describes the game as a set of states, with events triggering transitions between them. The initial state is locking eyes. The players then select their throws in parallel, and the flow eventually reaches game over. These are declarative descriptions of the game’s modes, rather than scattered conditions whose combined meaning must be reconstructed from code.

Starting a round changes the state. Selecting rock, paper, or scissors can instead use a targetless transition: the event is handled without moving to another state. When the players shoot, a guard checks whether their throws match. A tie sends them back to select again; otherwise, the game continues toward its result.

Transitions can also run actions, such as sending a message or updating stored data. That data is the machine’s context: it supplies values for transition decisions and for the final output.

ComponentRole in the game
StatesLocking eyes, selecting throws, game over
TransitionsHandle starting a round or selecting a throw
GuardsCheck whether the throws match
Actions and effectsUpdate context or send messages
ContextRetain data used by decisions and output

The distinction between state and context keeps the control flow readable: the state says what the game is doing, while context holds the data it needs to do it.

Rock-paper-scissors statechart surrounded by annotations for state definitions, transition logic, actions and effects, guards and conditions, and context data.Open full source frame
The five components of a finite state machine, illustrated with rock, paper, scissors.

Strictly speaking, this example is a statechart. Statecharts extend finite state machines with a richer vocabulary, including hierarchical states and parallel states such as the two players’ simultaneous selections. Terlson uses the terms interchangeably for the remainder of the presentation, but the parallel behavior in the game depends on that richer model.

1:271:42
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

1:27 · section reference included

Actors execute the behavior; event history makes it recoverable

A statechart models behavior, but an application also needs an execution framework. The actor model supplies concurrent, distributed, encapsulated execution. An actor is an autonomous entity that communicates through messages; it is not synonymous with an AI agent. Its capabilities are deliberately small: send and receive messages, update its internal state, and create other actors. A state machine can define the actor’s internal logic, while messages connect it to the rest of the application.

Terlson recalls a Best Buy mentor—a senior principal security architect with more than forty years in IT—who had never met a finite state machine he disliked. The appeal is operational: explicit transitions make behavior predictable and provide a structure for tracing and auditing what happened. With an explicitly retained event history, replay can reconstruct lost state. Stopping replay at an earlier event also creates a point from which execution can branch. Recovery therefore depends on keeping the history and being able to interpret it, not merely on having drawn a statechart.

The same explicit model supports testing. Model-based testing can generate paths through the machine and check that tests exercise every valid transition. Terlson also highlights low-latency transition handling and declarative behavior: the control logic is available as a model that tools and operators can inspect. Transition coverage gives a precise testing target, though it does not by itself establish that every external effect is correct.

Modularity, adaptability, and scalability become especially useful when a workflow fails halfway through. In a saga, a transaction spans multiple requests. If a later step fails, compensating transactions undo the effects of earlier steps and return the customer to a valid state. The state machine can make both the forward path and the compensation path explicit, instead of treating recovery as an exception outside the workflow.

3:243:43
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

3:24 · section reference included

Explicit control brings explicit obligations

The cost of a declared transition model is limited flexibility. Trying to represent thousands of situations—or an effectively unbounded set—as separate states can produce state explosion. Transitions also have to be modeled before the machine can take them. In Terlson’s described handling, an unmodeled event leaves the machine unchanged and is logged for remediation. The machine does not invent a missing path.

Concurrency needs a separate design. Each actor processes one event at a time, even though many actors can run concurrently. Terlson names Azure Service Bus sessions and Amazon SQS FIFO message groups as relevant mechanisms. Their ordering applies within a session or message group, not globally across the application.

Versioning complicates the promise of replay. If a new machine definition removes a state, where should an old event sequence land? Historical events and the logic interpreting them must remain compatible enough to produce a meaningful result. That requirement, along with explicit transition modeling and the learning curve, belongs in the design from the beginning.

These constraints explain why state machines and LLMs can complement one another. A model call does not itself supply predictable transitions, recovery, or a declarative execution contract. Terlson’s architecture assigns different jobs to different components:

Building blockResponsibility
ActorAutonomy, execution, and communication
State machineStructure and enforcement of allowed behavior
LLMDynamic interpretation and reasoning

The model can make a decision without owning the rules that permit its execution. The following patterns progressively increase what the model decides while retaining an explicit control structure.

5:586:13
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

5:58 · section reference included

Give the recipe writer access to inventory

Tool use sits at the bottom of the showcase’s autonomy chart because it supplies a capability the later patterns need: a way for the model to act through the application. The tool protocol has three parts:

  1. Give the model descriptions of available methods and their expected arguments.
  2. Receive the model’s description of a requested call, then execute it in the caller.
  3. Return the tool response as the next message so the model can continue.

The LLM does not call the method directly. That boundary is where the application can govern execution.

Tools can provide external information as well as perform actions, supporting retrieval-augmented generation. In the recipe example, the writer first retrieves the available ingredients through getInventory, then creates a recipe using only those ingredients. The statechart loops from calling the model to using the tool and back to the model before reaching done. Inventory becomes part of the model’s working information rather than something it must guess.

Tool Use slide with a Recipe Writer statechart connecting Calling Model, Using Tool with getInventory, and Done, alongside description, motivation, and example text.Open full source frame
A recipe writer loops between calling the model and retrieving inventory.
8:168:26
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

8:16 · section reference included

Pause a proposed call for human approval

Once a model can request tools, the next question is how to control those requests. Human-in-the-loop behavior is a general state-machine capability: insert an intermediate approval state and wait. Execution resumes only in response to an authenticated and authorized message. In the demonstration, the administrator first denies and then approves a request. A proposed call and permission to execute it are separate pieces of state.

A compact TypeScript transition function illustrates that separation for the recipe writer’s inventory request. The trusted application boundary supplies the principal after authentication; the transition checks authorization. Approval returns an execution command to the caller, rather than pretending the tool has already run.

typescript

type ToolCall = {
  name: "getInventory";
  arguments: Record<string, never>;
};

type State = {
  status: "awaitingApproval" | "denied" | "readyToExecute";
  request: ToolCall;
};

type Principal = {
  permissions: readonly string[];
};

type Decision = { type: "APPROVE" | "DENY" };

type Result = {
  state: State;
  commands: ToolCall[];
};

function decide(
  state: State,
  event: Decision,
  principal: Principal | null,
): Result {
  const canDecide = principal?.permissions.includes("approve-tools");
  if (!canDecide || state.status === "readyToExecute") {
    return { state, commands: [] };
  }

  if (event.type === "DENY") {
    return {
      state: { ...state, status: "denied" },
      commands: [],
    };
  }

  return {
    state: { ...state, status: "readyToExecute" },
    commands: [state.request],
  };
}

const pending: State = {
  status: "awaitingApproval",
  request: { name: "getInventory", arguments: {} },
};
const admin: Principal = { permissions: ["approve-tools"] };
const denied = decide(pending, { type: "DENY" }, admin);
const approved = decide(denied.state, { type: "APPROVE" }, admin);
// approved.commands contains the call for the executor to perform.

Here, denial preserves the request for a later decision. Approval changes its execution eligibility; a subsequent tool response would record the result of actually running it.

9:239:40
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

9:23 · section reference included

From a critic to a meal-delivery team

Feedback adds a second agent to the recipe workflow. The writer sends its output to a critic, perhaps a nutrition specialist. The critic responds with guidance such as “Use less sugar,” and the writer gets another opportunity to revise the recipe. Feedback can come from another agent, a human, or both. The mechanism is iterative revision of an output, not an automatic update to the model’s trained parameters.

Collaboration expands that pair into a team of specialists. Terlson motivates the decomposition through limitations in model training and the difficulty of scaling a single prompt to cover a broad, multifaceted goal. For meal delivery, the workflow includes recipe writing, ingredient procurement, meal preparation, feedback collection, and report publication. Each unit owns a narrower responsibility, and the state machine composes their work into a broader process.

That process need not terminate. The report and other accumulated context can return to the recipe writer as feedback for the next cycle. A state machine does not require a final state: it can govern an ongoing loop in which the sequence remains predictable while the content improves through feedback.

9:5910:24
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

9:59 · section reference included

Let a planner choose the next transition

The collaboration workflow fixes the sequence of work. Agentic orchestration moves that sequencing decision into a central planning node. The planner reasons over context to decide what should happen next, whether the goal has been achieved, and whether the process can exit. Execution moves back and forth between task states and the planning agent.

In Terlson’s implementation, the planner’s tools are event emitters. The model requests an event, and transition guards determine whether it is valid and where execution may move. The planner therefore chooses among opportunities exposed by the machine; a model-generated event does not bypass the machine’s rules. This preserves an enforcement boundary even when the next step requires contextual reasoning.

12:0712:20
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

12:07 · section reference included

Generate the process before executing it

A further step gives the LLM responsibility for generating the statechart itself. Terlson provisionally calls this agentic chartering; he does not present the name as established terminology. Where orchestration chooses the next step during execution, chartering separates planning from execution by first producing a process that can be run.

The proposed building materials are constrained and reusable: predetermined events, known context, available actors, and existing patterns. Terlson suggests prompting and fine-tuning as ways to help a model compose those materials into a new workflow. That shifts the planning output from a single routing decision to an explicit description of the process.

His motivating example is postal junk mail. He wants a personal agent that can remove him from the lists behind unwanted mail, so he gives o1 an article from Privacy Rights Clearinghouse describing removal from Whitepages and asks it to build a process. Terlson reports that the generated process was remarkably good, especially for an essentially zero-shot attempt with no examples. This is a qualitative report of process generation; the presentation does not establish that the opt-out was executed or completed.

A possible next step is a visualization agent that inspects the generated statechart and sends feedback to the chartering agent. Terlson invokes a long history of diagrams as potential training material, although his reference to seventy years of statecharts conflates them with the older history of state machines: David Harel’s bibliography dates the preliminary statecharts report to 1984 and the journal paper to 1987. Visual critique remains a proposed feedback loop here, not a measured capability. The suggestion ends with his joke that the solution to any agent problem is to add another agent.

13:0813:25
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

13:08 · section reference included

Build larger behavior from specialized units

The showcase points toward emergence, but Terlson says he has not expressed that pattern with a statechart. His hypothesis is that useful emergent behavior will come from making agentic systems feel like building with Lego, rather than from modeling them more closely on the human brain. React Native applications, GitHub Actions deployments, and AWS infrastructure as code provide his analogies: specialized units compose into systems with capabilities beyond any one unit. He closes with the hope that state machines will remain foundational for decades to come.

All of the presentation’s statecharts and visualizations use XState, with particular praise for its v5 changes. That is the demonstrated version; the live documentation inspected for further reading now carries a v6-alpha label. For a continuation focused on operational behavior, Terlson points to Red vs. Blue, promising a surprise emergence at the end of that companion demo.

Agentic State Machine Ops slide titled Red vs Blue + EMERGENCE, with a YouTube address, LinkedIn and GitHub addresses, and two QR codes; the presenter inset overlaps the lower code.Open full source frame
The closing slide points to the Red vs Blue + Emergence demo and contact resources.
15:1815:43
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

15:18 · section reference included

Resources

From the talk

Updates since the talk

  • Current documentation explains actor communication, internal state, mailboxes and lifecycle management; the retrieved site is labeled v6 alpha.

  • Current documentation covers saving snapshots, replaying stored events and handling restoration caveats; the retrieved site is labeled v6 alpha.

Transcript download
Read the transcript and explore slides

Loading transcript and slides…