State Machine¶
Module: agentspype.agent.state_machine
AgentStateMachine¶
Base class for all agent state machines. Extends agentspype.fsm.StateMachine with agent integration: a weakref back to the owning agent, automatic subscription on start, automatic teardown on entering a final state, and default state/transition injection via StateMachineMeta.
Class Variables¶
The following class variables are injected by StateMachineMeta into every concrete subclass that does not define them:
| Name | Type | Description |
|---|---|---|
starting |
State(initial=True) |
Initial state |
idle |
State |
Default idle/ready state |
end |
State(final=True) |
Terminal state |
start |
TransitionList |
starting → idle |
stop |
TransitionList |
starting → end | idle → end |
Constructor¶
AgentStateMachine(agent: Agent) -> None
Stores a weakref to agent and sets _should_stop = False. Calls super().__init__() from StateMachine.
Properties¶
agent -> Agent¶
Resolves the weakref. Raises RuntimeError("Agent has been deactivated") if the agent has been garbage-collected.
Built-in Hooks¶
on_enter_end() -> None¶
Called automatically when the machine enters the end state. Calls self.agent.teardown().
before_transition(event, state, source, target) -> None¶
Called before every transition. If source != target, logs a DEBUG message:
[ClassName:StateMachine] (event) source -> target
Override to add pre-transition guards or validation.
after_transition(event, state) -> None (abstract)¶
Called after every successful transition. Must be implemented in every concrete subclass. Typical implementation:
def after_transition(self, event, state):
if isinstance(self.agent.publishing, StateAgentPublishing):
self.agent.publishing.publish_transition(event, state)
on_start() -> None¶
Called when the start transition fires. Calls self.agent.listening.subscribe().
on_stop() -> None¶
Called when the stop transition fires. Sets _should_stop = True.
Condition¶
should_stop() -> bool¶
Returns True after on_stop() has been called. Useful for polling loops.
Convenience Methods¶
safe_start() -> None¶
Fires start(f=True) only if the machine is in an initial state. No-op otherwise.
agent.machine.safe_start() # safe to call multiple times
safe_stop() -> None¶
Fires stop(f=True) only if the machine is not in a final state. No-op otherwise.
agent.machine.safe_stop() # safe to call multiple times
StateMachineMeta¶
Module: agentspype.fsm.machine
Metaclass for StateMachine. Handles state collection, transition mapping, hook resolution, and state isolation across inheritance hierarchies.
Behavior¶
When a new class is created using this metaclass (other than AgentStateMachine itself), the metaclass inspects the class namespace and injects missing defaults:
- If
startingis not in the namespace, injectsState("Starting", initial=True). - If
idleis not in the namespace, injectsState("Idle"). - If
endis not in the namespace, injectsState("End", final=True). - If
startis not in the namespace, injectsstarting.to(idle). - If
stopis not in the namespace, injectsstarting.to(end) | idle.to(end).
This happens at class creation time (before any instance is created), so the injected states and transitions behave identically to explicitly declared ones.
Overriding Defaults¶
If you declare any of these names in your subclass, the metaclass will not overwrite them:
class MyMachine(AgentStateMachine):
# Override end — metaclass will not inject a default end state
starting = State("Starting", initial=True)
processing = State("Processing")
done = State("Done", final=True) # use 'done' instead of 'end'
start = starting.to(processing)
stop = processing.to(done)
def after_transition(self, event, state): pass
BasicAgentStateMachine¶
Module: agentspype.agent.state_machine
A ready-to-use concrete subclass of AgentStateMachine. Uses all metaclass-injected defaults and implements after_transition to publish transitions via StateAgentPublishing.
class BasicAgentStateMachine(AgentStateMachine):
def after_transition(self, event: str, state: State) -> None:
if isinstance(self.agent.publishing, StateAgentPublishing):
self.agent.publishing.publish_transition(event, state)
States¶
starting(initial)idleend(final)
Transitions¶
start:starting → idlestop:starting → end | idle → end
Usage¶
from agentspype.agent.state_machine import BasicAgentStateMachine
class SimpleAgent(Agent):
definition = AgentDefinition(
state_machine_class=BasicAgentStateMachine,
events_publishing_class=StateAgentPublishing,
...
)