undo
Go Beyond the Code
arrow_forward_ios

FSM approach for complex assistants

Juan Altamirano
Software Engineer & Solver
November 26, 2025
To learn more about this topic, click here.

If you take a moment to look around, you’ll realize that events are constantly unfolding—like an apple falling from a tree. Newton famously explained this with gravity, but if we dig deeper, we see the apple fell because its initial state was to hang on the tree, and then certain forces acted on it to change that state.

From simple natural phenomena to configuration flows or building DIY furniture, some things must happen in a specific order. Skip a step, and everything can break—often badly.

The same principle applies when orchestrating tasks in complex systems, especially AI-powered workflows. You can’t move to the next step until the current one is done—and done right. Whether it’s running model predictions, sending notifications, or updating databases, each action depends on previous steps being completed successfully.

As the number of steps grows, so do the risks:


To avoid these pitfalls, we need a clear, enforceable structure that guarantees our processes move forward only when they should.

This is where Finite State Machines (FSMs) shine. FSMs allow you to define strict rules about what can happen, when, and under what conditions. They’re a natural fit when you have a well-defined set of states and transitions, each with dependencies and validations.

In this post, we’ll walk you through building a production-grade FSM that helps you:

But first, why can’t we just handle this with a few simple if statements?


The Problem

Imagine you’re building a chatbot that guides users through connecting a third-party platform. First, you map out all the necessary steps to complete the integration. Then, you figure out how each step should work.

The first step may ask for credentials. The next verifies the connection. Later steps rely on dynamic data retrieved earlier. At any point, the user should go back, skip ahead, or repeat a step.

Now add in network failures, invalid inputs, or partially completed actions—and suddenly your assistant isn’t just a simple script anymore. It becomes a stateful system that needs careful coordination.

Most developers start with basic conditionals:



            


But soon, the code turns into a mess of nested if statements, flags, and booleans—each added to patch an edge case. These ad-hoc solutions don’t scale. They introduce potential pitfalls in your application.

And the worst part? You won’t notice these issues in a happy-path demo. They show up when users push the boundaries—interrupting the flow, going off-script, or hitting errors.

If your assistant handles real business logic, partial execution or out-of-order transitions aren’t just annoying—they’re dangerous. They can lead to misconfigured automations, data loss, or production outages.

We needed a model that makes transitions explicit, enforces what should happen next, and gracefully handles when things go wrong.

That’s precisely what finite state machines offer.


Designing the State Machine

Once we decided to go with a finite state machine (FSM), the first step was simple: define the states.

Each state represents a point in the assistant’s flow where we’re waiting for something specific to happen—user input, a validation check, a response from an external API, etc.

For example, in a configuration assistant, our states might look like:

Each of these states has a clearly defined purpose. We only allow transitions when the right conditions are met—no jumping ahead, no skipping validations, no back-and-forth chaos.

This structure gives us three key benefits:

Transitions are just as important as states. They define when and how we move forward. For instance:

You can think of the whole system like a directed graph:
Nodes are your states. Edges are your transitions. Nothing moves unless it’s allowed.

This kind of explicit flow control solves the problems we discussed earlier. Instead, we get a predictable, testable, and extensible structure that keeps both our assistant and our users on track.


Implementing a Production-Ready FSM

Once we committed to using a robust, scalable FSM, we opted for Spring Statemachine—a production-ready framework with first-class support for states, transitions, guards, actions, listeners, and persistence.


1- Define States and Events

We begin by modeling our assistant’s flow with these enums used for managing the states and the events for our machine. These will help us to lay out each conversational milestone clearly:



            


As mentioned in the previous section, each State represents a distinct phase in your assistant’s flow. Each Event is a trigger that can cause a transition between states.

You can do this with Spring’s FSM by using:



            


Optionally, you can attach:



            


2- Configure the Machine

Using Spring’s EnumStateMachineConfigurerAdapter, we declaratively define:



            


3- Using the State Machine in a Service

Once the machine is configured, your service stays simple:



            


Conclusion

As you’ve seen, FSMs are incredibly useful when handling long, complex flows — like the chatbot example we explored earlier. That said, it’s essential first to evaluate whether your use case fits within the boundaries of a state machine model. FSMs work best when the logic can be broken down into discrete states and well-defined transitions.

FSMs provide structure and clarity. They make your logic more maintainable, your code more testable, and your features more predictable. Using Spring State Machine’s declarative approach, you can define all states, transitions, guards, and actions in one place — keeping your implementation flexible without sacrificing control. It’s a scalable, production-ready method that helps you tackle complex features with confidence.

Juan Altamirano
Software Engineer & Solver

Start Your Digital Journey Now!

Which capabilities are you interested in?
You may select more than one.
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.