Class: Protege::Orchestrator::Harness
- Inherits:
-
Object
- Object
- Protege::Orchestrator::Harness
- Defined in:
- lib/protege/orchestrator/harness.rb
Overview
Multi-turn inference runner — the heart of the LOGI Orchestrator. Generates against the
configured provider and dispatches tool calls until the model returns a tool-free response or
max_tool_turns is reached.
This is the abstract base that owns the shared algorithm (event-wrapped tool loop, provider
generation, tool dispatch, attachment review). What drives a run is left to subclasses, which
each define one clean path: ReplyHarness for a reactive run (an inbound email) and
ResponsibilityHarness for a proactive one (a scheduled Loop responsibility). The branch between
them lives at the job boundary — the caller picks the subclass — so there are no run-kind
conditionals in this loop. Subclasses fill the hooks: #resolvers, #user_content, #context,
and (reply only) #message / #streaming?.
Protege::Current.correlation_id must be set before calling so that emitted events carry the id
automatically. Collaborates with Inference (request building and generation), Tool (dispatch
and registry), the persona's ResolverChain (context assembly), and the Protege::*Event classes
(observability).
Lifecycle
- Emit
inference_startedevent. - Build the initial
Provider::Requestfrom the opening user turn, registered tools, and resolver-contributed context messages. - Enter the tool loop — generate, dispatch any tool calls, extend the request with results,
repeat until the model returns no tool calls or
max_tool_turnsis exhausted. - Emit
inference_completedevent and return the final response.
Direct Known Subclasses
Class Method Summary collapse
-
.run ⇒ Object
Instantiate the concrete harness and run it in one call.
Instance Method Summary collapse
- #initialize(persona:) ⇒ void constructor
-
#run ⇒ Object
Entry point.
Constructor Details
#initialize(persona:) ⇒ void
50 51 52 |
# File 'lib/protege/orchestrator/harness.rb', line 50 def initialize(persona:) @persona = persona end |
Class Method Details
.run ⇒ Object
Instantiate the concrete harness and run it in one call. Keyword arguments are forwarded to
the subclass initializer (e.g. message: for ReplyHarness, responsibility: for
ResponsibilityHarness).
43 44 45 |
# File 'lib/protege/orchestrator/harness.rb', line 43 def run(**) new(**).run end |
Instance Method Details
#run ⇒ Object
Entry point. Emit lifecycle events around the tool loop.
Always emits a terminal event — inference_completed on success or inference_failed when the
loop raises — so subscribers (and stateful hooks keyed by correlation id) are never left
waiting on a completion that never comes. The error is re-raised so the job's retry/discard
policy still applies.
63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/protege/orchestrator/harness.rb', line 63 def run InferenceStartedEvent.emit(persona:, message:) result = run_tool_loop InferenceCompletedEvent.emit(persona:, message:, result:) result rescue StandardError => e InferenceFailedEvent.emit(persona:, message:, error: e) raise end |