class LittleGhost::Run
Observe one top-level agent or workflow execution from start to finish. A run records its response, outcome, usage, error, and owned resources.
run = CustomerSupportAgent.ask("Why is transfer 481 pending?") run.completed? # => true run.outcome # => "completed" run.response # => "Transfer 481 is waiting for the receiving bank."
Agent.ask[LittleGhost::Agent.ask] or standalone ask consumes the event stream and returns the Run. For a live interface, stream_ask yields StreamEvent objects and returns the same run after enumeration. A run can execute only once.
Completion, failure, deadline, and cancellation become the completed, failed, partial, and cancelled outcomes. Ordinary execution failures are available through error and the terminal stream event; cleanup, event delivery, or instrumentation failures may still raise because the framework cannot safely report a clean stop.
The run opens its workspace, sandbox, session, and entrypoint, then closes registered resources in reverse order. register extends that lifecycle for application resources. Interruption is available only while an agent entrypoint is active and unambiguous.
Attributes
Runtime and declarations used to execute the run; its request, cancellation token, resources, terminal outcome, response, result, usage, and error.
Runtime and declarations used to execute the run; its request, cancellation token, resources, terminal outcome, response, result, usage, and error.
Runtime and declarations used to execute the run; its request, cancellation token, resources, terminal outcome, response, result, usage, and error.
Runtime and declarations used to execute the run; its request, cancellation token, resources, terminal outcome, response, result, usage, and error.
Runtime and declarations used to execute the run; its request, cancellation token, resources, terminal outcome, response, result, usage, and error.
Runtime and declarations used to execute the run; its request, cancellation token, resources, terminal outcome, response, result, usage, and error.
Runtime and declarations used to execute the run; its request, cancellation token, resources, terminal outcome, response, result, usage, and error.
Runtime and declarations used to execute the run; its request, cancellation token, resources, terminal outcome, response, result, usage, and error.
Runtime and declarations used to execute the run; its request, cancellation token, resources, terminal outcome, response, result, usage, and error.
Runtime and declarations used to execute the run; its request, cancellation token, resources, terminal outcome, response, result, usage, and error.
Runtime and declarations used to execute the run; its request, cancellation token, resources, terminal outcome, response, result, usage, and error.
Runtime and declarations used to execute the run; its request, cancellation token, resources, terminal outcome, response, result, usage, and error.
Runtime and declarations used to execute the run; its request, cancellation token, resources, terminal outcome, response, result, usage, and error.
Runtime and declarations used to execute the run; its request, cancellation token, resources, terminal outcome, response, result, usage, and error.
Public Class Methods
# File lib/little_ghost/run.rb, line 40 def initialize(invocation:, agent_class:, runtime:, entrypoint_class: agent_class, cancellation_token: Support::CancellationToken.new, workspace: nil, sandbox: nil) @runtime = runtime @agent_class = agent_class @entrypoint_class = entrypoint_class @invocation = invocation @cancellation_token = cancellation_token @workspace = workspace @sandbox = sandbox @operation_id = SecureRandom.uuid @resources = [] @closed = false @started = false @mutex = Mutex.new @event_mutex = Mutex.new @subagent_instrumentation_mutex = Mutex.new @subagent_instrumentation = {} @exclusive_tools_mutex = Mutex.new @once_mutex = Mutex.new @once_keys = {} @interruption_mutex = Mutex.new @interruption_state = :not_started @entrypoint = nil @usage = Usage.new end
Creates a dormant run for invocation.
Public Instance Methods
Source
# File lib/little_ghost/run.rb, line 67 def call each { |_event| } self end
Consumes the event stream and returns self.
Source
# File lib/little_ghost/run.rb, line 98 def cancelled? = outcome == "cancelled"
True when cancellation stopped the run without a response.
Source
# File lib/little_ghost/run.rb, line 193 def close callbacks = @mutex.synchronize do return if @closed @closed = true @resources.reverse end errors = [] callbacks.each do |callback| callback.call rescue => error errors << error end cleanup_error = errors.find { |caught| caught.is_a?(CleanupError) } || errors.first begin finish_remaining_subagent_instrumentation( outcome: cleanup_error ? :error : :cancelled, error_type: cleanup_error&.class&.name ) rescue => error errors << error end error = errors.find { |caught| caught.is_a?(CleanupError) } || errors.first raise error if error end
Closes registered resources in reverse order.
The operation is idempotent. It attempts every closer and then raises the first LittleGhost::CleanupError, or otherwise the first cleanup exception.
Source
# File lib/little_ghost/run.rb, line 89 def completed? = outcome == "completed"
True after successful completion.
# File lib/little_ghost/run.rb, line 137 def context(state: {}, metadata: {}) RunContext.new( state:, cancellation_token:, deadline: invocation.deadline_at, metadata: ) end
Creates a RunContext with this run’s cancellation token and deadline.
Source
# File lib/little_ghost/run.rb, line 75 def each return enum_for(__method__) unless block_given? begin_execution! @emitter = ->(event) { yield_event(event) { |value| yield value } } Instrumentation.with_context(correlation_attributes.except(:operation_id)) do execute { |event| yield event } end self ensure @emitter = nil end
Yields events and returns self after the terminal event.
Without a block, returns an Enumerator. A second execution raises Error.
Source
# File lib/little_ghost/run.rb, line 92 def failed? = outcome == "failed"
True after execution or cleanup failed.
# File lib/little_ghost/run.rb, line 104 def interrupt_response( message, interruption_id: nil, batch_key: nil, metadata: {}, cancellation_token: Support::CancellationToken.new, deadline: nil ) entrypoint = @interruption_mutex.synchronize do case @interruption_state when :not_started, :starting raise AgentInterruptError, "Run entrypoint is not ready for interruptions" when :terminal raise AgentInterruptError, "Run has already finished" end @entrypoint end unless entrypoint.respond_to?(:interrupt_response) raise AgentInterruptError, "Run entrypoint does not support interruptions" end entrypoint.interrupt_response( message, interruption_id:, batch_key:, metadata:, cancellation_token:, deadline: ) end
Adds an interruption to the active entrypoint and waits for its response.
Raises LittleGhost::AgentInterruptError before the entrypoint is ready, after it finishes, or when the entrypoint does not support interruptions.
Source
# File lib/little_ghost/run.rb, line 175 def once(key) @once_mutex.synchronize do return if @once_keys.key?(key) value = yield @once_keys[key] = true value end end
Performs the block at most once successfully for key during this run.
Concurrent callers are serialized. The caller that performs the block receives its value; later callers receive nil. If the block raises, the key is not recorded and a later call may retry it.
Source
# File lib/little_ghost/run.rb, line 95 def partial? = outcome == "partial"
True when the deadline preserved a partial response.
# File lib/little_ghost/run.rb, line 157 def register(resource = nil, &closer) callback = closer || close_callback(resource) @mutex.synchronize do raise Error, "run is already closed" if @closed @resources << callback end resource end
Adds a resource or closer to reverse-order cleanup and returns the resource.
A resource must respond to close unless a block supplies the cleanup operation. Registering after the run has closed raises Error.