Class: Phronomy::Agent::InvocationPipeline Private
- Inherits:
-
Object
- Object
- Phronomy::Agent::InvocationPipeline
- Defined in:
- lib/phronomy/agent/invocation_pipeline.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.
Encapsulates the core per-invocation LLM round-trip for Base.
Base#invoke_once delegates the body of each LLM turn to this class, keeping the caller to a thin setup + trace frame (span≈2). The pipeline executes inside the agent's binding via +instance_exec+ so that private concern methods (guardrails, hooks, cancellation) remain encapsulated in their original modules while the orchestration logic lives here.
Instance Method Summary collapse
-
#initialize(agent) ⇒ InvocationPipeline
constructor
private
A new instance of InvocationPipeline.
-
#run(input, messages:, thread_id:, config:) ⇒ Array(Hash, Phronomy::TokenUsage, nil)
private
Runs one LLM round-trip inside the agent's execution context.
Constructor Details
#initialize(agent) ⇒ InvocationPipeline
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 InvocationPipeline.
18 19 20 |
# File 'lib/phronomy/agent/invocation_pipeline.rb', line 18 def initialize(agent) @agent = agent end |
Instance Method Details
#run(input, messages:, thread_id:, config:) ⇒ Array(Hash, Phronomy::TokenUsage, nil)
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.
Runs one LLM round-trip inside the agent's execution context.
Calls private Base concern methods (guardrails, hooks, cancellation) via +instance_exec+ so that their encapsulation is preserved, then routes the LLM request through the configured adapter.
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/phronomy/agent/invocation_pipeline.rb', line 36 def run(input, messages:, thread_id:, config:) @agent.instance_exec(input, , thread_id, config) do |inp, msgs, tid, cfg| # Run input guardrails before touching the LLM. run_input_guardrails!(inp) = (inp) chat = build_chat # Assemble context (system prompt + history). Override #build_context to # inject custom context editing logic at the Agent subclass level. context = build_context(inp, messages: msgs, thread_id: tid, config: cfg) apply_instructions(chat, context[:system]) if context[:system] context[:messages].each { |msg| chat. << msg } # Run before_completion hooks (global → class → instance) before the LLM call. run_before_completion_hooks!(chat, cfg) # Register suspension hook for approval-required tools (no-op when a # synchronous on_approval_required handler is already registered). _register_suspension_hook!(chat) # Check for cancellation immediately before the LLM call. check_cancellation!(cfg, "invocation cancelled before LLM call") # Forward the cancellation token to ParallelToolChat explicitly # via the chat instance so that tool dispatch batches can observe # cancellation without needing Thread.current. chat.cancellation_token = cfg[:cancellation_token] if chat.respond_to?(:cancellation_token=) begin # Route the LLM call through the configured LLMAdapter so that the # blocking HTTP request runs inside BlockingAdapterPool and the # adapter can be swapped without changing agent code. adapter = Phronomy.configuration.llm_adapter response = adapter.complete_async(chat, , config: cfg).await rescue SuspendSignal => signal checkpoint = Checkpoint.new( thread_id: tid, original_input: inp, messages: chat..dup, pending_tool_name: signal.tool_name, pending_tool_args: signal.args, pending_tool_call_id: signal.tool_call_id ) suspended_result = {output: nil, suspended: true, checkpoint: checkpoint, messages: chat.} next [suspended_result, nil] ensure # Clear the chat's cancellation token reference after each LLM call. chat.cancellation_token = nil if chat.respond_to?(:cancellation_token=) end output = response.content usage = Phronomy::TokenUsage.from_tokens(response.tokens) # Run output guardrails before returning to the caller. run_output_guardrails!(output) result = {output: output, messages: chat., usage: usage} [result, usage] end end |