Sometimes you want an agent action to block until the robot enters a
particular state — for example, "wait until the robot is :idle before
issuing the next move". This guide covers the two available patterns.
Option 1: BB.Jido.Action.WaitForState
The simplest case is a single, foreground wait. The action is on the agent already (the robot plugin attaches it). Send it via the default route:
:ok =
Jido.AgentServer.cast(
pid,
Jido.Signal.new!(
"bb.state.wait",
%{robot: MyRobot, target: :idle, timeout: 5_000}
)
)Return shapes:
| Outcome | Return |
|---|---|
Robot already in target | {:ok, %{robot: ..., state: target}} |
Transitions into target within timeout | {:ok, %{robot: ..., state: target}} |
timeout elapses first | {:error, :timeout} |
The action subscribes to [:state_machine] for the duration of the wait
and unsubscribes when it returns.
Caveat: this blocks the agent process while it waits. If your agent also needs to react to other signals during the wait, that processing is paused. For non-blocking waits, see Option 2.
Option 2: an event-driven decision
For long waits or concurrent waits, react to the transition signal
instead. The robot plugin already forwards bb.state.transition signals
into the agent; scaffold an action that pattern-matches on the payload:
mix bb_jido.add_action MyRobot.OnTransition
defmodule MyRobot.OnTransition do
use Jido.Action,
name: "on_transition",
schema: [
robot: [type: :atom, required: true],
path: [type: {:list, :atom}, required: true],
message: [type: :any, required: true]
]
@impl Jido.Action
def run(%{robot: robot, message: %BB.Message{payload: payload}}, _context) do
case payload do
%BB.StateMachine.Transition{to: :idle} -> handle_idle(robot)
%BB.StateMachine.Transition{to: :error} -> handle_error(robot)
_ -> {:ok, %{ignored: true}}
end
end
endAttach via a plugin with signal_routes: [{"bb.state.transition", MyRobot.OnTransition}].
The agent stays responsive throughout — the action runs only when the
transition actually happens, and only for the transitions you care about.
Rule of thumb: if the timeout is short (sub-second), Option 1 is fine. If it's seconds or more, prefer Option 2.
Pre-cached state on the plugin
BB.Jido.Plugin.Robot keeps a safety_state field in its plugin state
that's updated whenever a transition signal arrives. Read it from another
action via context.agent.state.robot.safety_state to skip a Runtime
lookup. This is a convenience cache — BB.Robot.Runtime.state/1 is also
cheap (ETS), so use whichever reads better in your code.