Class: Phronomy::Agent::FSM Private
- Inherits:
-
Object
- Object
- Phronomy::Agent::FSM
- Defined in:
- lib/phronomy/agent/fsm.rb
Overview
This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.
EventLoop-registered execution unit for a single agent invocation.
+AgentFSM+ implements the minimal interface expected by EventLoop (+#id+, +#start+, +#handle+) so it can be managed alongside FSMSession instances. It is not a traditional finite-state machine; the name reflects its role in the EventLoop rather than internal state transitions.
== Execution model
#start is called by the EventLoop on the +:start+ event. It immediately returns after spawning a background IO thread that runs the agent's full invocation pipeline (via +_invoke_impl+). The EventLoop thread is never blocked by agent execution.
Inside the IO thread, the +:phronomy_agent_parallel_tools+ thread-local flag is set to +true+ so that Base#build_chat returns a ParallelToolChat instance, enabling concurrent tool dispatch when the LLM returns multiple tool calls in one response.
== Completion events
On success:
- Posts +:finished+ to this FSM's own +#id+ so the EventLoop cleans up its registry entry and unblocks any +completion_queue.pop+ caller.
- When +parent_id+ is set (child-FSM pattern), additionally posts +:child_completed+ to +parent_id+, carrying the result hash as the event payload. The parent FSMSession must declare an +on:+ transition for +:child_completed+ to advance correctly.
On error:
- Posts +:error+ to this FSM's own +#id+. The EventLoop propagates the exception through the +completion_queue+ so that the original caller of +Agent::Base#invoke+ (in EventLoop mode) receives and re-raises it.
== Standalone usage (blocking caller)
Phronomy.configure { |c| c.event_loop = true } result = MyAgent.new.invoke("Hello!") # => { output:, messages:, usage: }
Base#invoke detects EventLoop mode, creates an +AgentFSM+, registers it via EventLoop#register, and blocks the calling thread on the returned +completion_queue+ until the agent finishes.
== Child-FSM usage (non-blocking, inside a Workflow)
state :run_agent entry :run_agent, ->(ctx) { MyAgent.new.run_as_child(ctx.query, ctx: ctx) } transition from: :run_agent, on: :child_completed, to: :process_result
Base#run_as_child creates an +AgentFSM+ with +parent_id+ set to +ctx.thread_id+, registers it with the EventLoop, and returns immediately. The parent FSMSession waits for the +:child_completed+ event.
Instance Attribute Summary collapse
-
#current_phase ⇒ Symbol
readonly
private
Current internal phase (:idle, :running).
-
#id ⇒ String
readonly
private
Unique identifier used as the EventLoop target_id.
Instance Method Summary collapse
-
#handle(_event) ⇒ Object
private
Called by EventLoop for external events dispatched to this id.
-
#initialize(agent:, input:, messages: [], thread_id: nil, config: {}, parent_id: nil, result_writer: nil) ⇒ FSM
constructor
private
A new instance of FSM.
-
#start ⇒ Object
private
Called by EventLoop on the +:start+ event.
Constructor Details
#initialize(agent:, input:, messages: [], thread_id: nil, config: {}, parent_id: nil, result_writer: nil) ⇒ FSM
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns a new instance of FSM.
92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/phronomy/agent/fsm.rb', line 92 def initialize(agent:, input:, messages: [], thread_id: nil, config: {}, parent_id: nil, result_writer: nil) @agent = agent @input = input @messages = Array().dup @thread_id = thread_id || SecureRandom.uuid @config = config @parent_id = parent_id @result_writer = result_writer @id = @thread_id @current_phase = :idle end |
Instance Attribute Details
#current_phase ⇒ Symbol (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns current internal phase (:idle, :running).
66 67 68 |
# File 'lib/phronomy/agent/fsm.rb', line 66 def current_phase @current_phase end |
#id ⇒ String (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns unique identifier used as the EventLoop target_id.
63 64 65 |
# File 'lib/phronomy/agent/fsm.rb', line 63 def id @id end |
Instance Method Details
#handle(_event) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Called by EventLoop for external events dispatched to this id. +AgentFSM+ is fully driven by its own IO thread and does not respond to external events after #start.
114 115 116 |
# File 'lib/phronomy/agent/fsm.rb', line 114 def handle(_event) # No-op: AgentFSM is driven entirely by its IO thread. end |
#start ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Called by EventLoop on the +:start+ event. Transitions to +:running+ and spawns the agent IO thread.
106 107 108 109 |
# File 'lib/phronomy/agent/fsm.rb', line 106 def start @current_phase = :running spawn_agent_thread end |