Module: Phronomy::Agent::AsyncEventApi Private

Included in:
Base
Defined in:
lib/phronomy/agent/async_event_api.rb

Overview

This module is part of a private API. You should avoid using this module if possible, as it may be removed or be changed in the future.

Symmetric Agent async event contract layered onto Agent::Base.

invoke_async and stream_async share lifecycle/tool events. stream_async additionally emits :token events. The returned Task remains a normal Task and is settled after the terminal event listener returns.

Instance Method Summary collapse

Instance Method Details

#invoke(input, messages: [], thread_id: nil, config: {}, invocation_context: nil, on_event: nil) ⇒ Hash

Invokes the agent synchronously and returns the terminal result.

Provider errors are translated after the configured LLM adapter returns its final result. Phronomy does not replay the Agent invocation.

Parameters:

  • input (String, Hash)

    user input for this invocation

  • messages (Array<RubyLLM::Message>) (defaults to: [])

    conversation history

  • thread_id (String, nil) (defaults to: nil)

    conversation thread identifier

  • config (Hash) (defaults to: {})

    additional runtime options

  • invocation_context (Phronomy::InvocationContext, nil) (defaults to: nil)

    first-class invocation context

  • on_event (Proc, nil) (defaults to: nil)

    listener for lifecycle and Tool events

Returns:

  • (Hash)

    terminal invocation result

Raises:



29
30
31
32
33
34
35
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
# File 'lib/phronomy/agent/async_event_api.rb', line 29

def invoke(
  input,
  messages: [],
  thread_id: nil,
  config: {},
  invocation_context: nil,
  on_event: nil
)
  if invocation_context
    thread_id, config = _apply_invocation_context(
      thread_id,
      config,
      invocation_context
    )
  end
  _check_scheduler_reentrancy(:invoke, :invoke_async)

  trace(
    "agent.invoke",
    input: input,
    **_build_caller_meta(config)
  ) do |_span|
    result = invoke_async(
      input,
      messages: messages,
      thread_id: thread_id,
      config: config,
      on_event: on_event
    ).wait_result
    [result, result[:usage]]
  end
end

#invoke_async(input, messages: [], thread_id: nil, config: {}, invocation_context: nil, on_tool_approval_required: nil, on_event: nil) ⇒ Phronomy::Task

Invokes the agent asynchronously.

The returned Task settles after the terminal event listener returns. Lifecycle and Tool events are delivered from the Runtime-owned EventLoop thread.

Parameters:

  • input (String, Hash)

    user input for this invocation

  • messages (Array<RubyLLM::Message>) (defaults to: [])

    conversation history

  • thread_id (String, nil) (defaults to: nil)

    conversation thread identifier

  • config (Hash) (defaults to: {})

    additional runtime options

  • invocation_context (Phronomy::InvocationContext, nil) (defaults to: nil)

    first-class invocation context

  • on_tool_approval_required (Proc, nil) (defaults to: nil)

    per-invocation approval notification listener

  • on_event (Proc, nil) (defaults to: nil)

    listener for lifecycle and Tool events

Returns:



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/phronomy/agent/async_event_api.rb', line 79

def invoke_async(
  input,
  messages: [],
  thread_id: nil,
  config: {},
  invocation_context: nil,
  on_tool_approval_required: nil,
  on_event: nil
)
  if invocation_context
    thread_id, config = _apply_invocation_context(
      thread_id,
      config,
      invocation_context
    )
  end

  result_task = Phronomy::Task.deferred(
    name:
      "agent-#{(self.class.name || "anonymous").downcase}-async"
  )
  approval_snapshot = _approval_configuration_snapshot(
    on_tool_approval_required
  )
  _start_invocation(
    result_task,
    input,
    messages: messages,
    thread_id: thread_id,
    config: config,
    approval_snapshot: approval_snapshot,
    mode: :invoke,
    on_event: on_event
  )
  result_task
end

#stream(input, messages: [], thread_id: nil, config: {}, invocation_context: nil, on_tool_approval_required: nil, on_event: nil) {|event| ... } ⇒ Hash

Invokes the agent synchronously and emits streaming events.

Accepts either on_event: or a block. Event callbacks run on the Runtime-owned EventLoop thread; the calling thread waits for the final Task result.

Parameters:

  • input (String, Hash)

    user input for this invocation

  • messages (Array<RubyLLM::Message>) (defaults to: [])

    conversation history

  • thread_id (String, nil) (defaults to: nil)

    conversation thread identifier

  • config (Hash) (defaults to: {})

    additional runtime options

  • invocation_context (Phronomy::InvocationContext, nil) (defaults to: nil)

    first-class invocation context

  • on_tool_approval_required (Proc, nil) (defaults to: nil)

    per-invocation approval notification listener

  • on_event (Proc, nil) (defaults to: nil)

    event listener

Yield Parameters:

Returns:

  • (Hash)

    terminal invocation result

Raises:

  • (ArgumentError)

    when no listener is supplied or both listener forms are supplied

  • (Phronomy::SchedulerReentrancyError)

    when called from the EventLoop thread or a guarded scheduler context



203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
# File 'lib/phronomy/agent/async_event_api.rb', line 203

def stream(
  input,
  messages: [],
  thread_id: nil,
  config: {},
  invocation_context: nil,
  on_tool_approval_required: nil,
  on_event: nil,
  &block
)
  listener = resolve_event_listener(on_event, block)
  unless listener
    raise ArgumentError,
      "stream requires on_event: or a block"
  end

  if invocation_context
    thread_id, config = _apply_invocation_context(
      thread_id,
      config,
      invocation_context
    )
  end
  _check_scheduler_reentrancy(:stream, :stream_async)

  trace(
    "agent.stream",
    input: input,
    **_build_caller_meta(config)
  ) do |_span|
    result = stream_async(
      input,
      messages: messages,
      thread_id: thread_id,
      config: config,
      on_tool_approval_required:
        on_tool_approval_required,
      on_event: listener
    ).wait_result
    [result, result[:usage]]
  end
end

#stream_async(input, messages: [], thread_id: nil, config: {}, invocation_context: nil, on_tool_approval_required: nil, on_event: nil) {|event| ... } ⇒ Phronomy::Task

Invokes the agent asynchronously and emits streaming events.

Accepts either on_event: or a block. Supplying both is rejected. Token events are emitted only by streaming invocations; lifecycle and Tool events use the same contract as #invoke_async.

Parameters:

  • input (String, Hash)

    user input for this invocation

  • messages (Array<RubyLLM::Message>) (defaults to: [])

    conversation history

  • thread_id (String, nil) (defaults to: nil)

    conversation thread identifier

  • config (Hash) (defaults to: {})

    additional runtime options

  • invocation_context (Phronomy::InvocationContext, nil) (defaults to: nil)

    first-class invocation context

  • on_tool_approval_required (Proc, nil) (defaults to: nil)

    per-invocation approval notification listener

  • on_event (Proc, nil) (defaults to: nil)

    event listener

Yield Parameters:

Returns:

Raises:

  • (ArgumentError)

    when no listener is supplied or both listener forms are supplied



136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/phronomy/agent/async_event_api.rb', line 136

def stream_async(
  input,
  messages: [],
  thread_id: nil,
  config: {},
  invocation_context: nil,
  on_tool_approval_required: nil,
  on_event: nil,
  &block
)
  listener = resolve_event_listener(on_event, block)
  unless listener
    raise ArgumentError,
      "stream_async requires on_event: or a block"
  end

  if invocation_context
    thread_id, config = _apply_invocation_context(
      thread_id,
      config,
      invocation_context
    )
  end

  result_task = Phronomy::Task.deferred(
    name:
      "agent-#{(self.class.name || "anonymous").downcase}" \
      "-stream-async"
  )
  approval_snapshot = _approval_configuration_snapshot(
    on_tool_approval_required
  )
  _start_invocation(
    result_task,
    input,
    messages: messages,
    thread_id: thread_id,
    config: config,
    approval_snapshot: approval_snapshot,
    mode: :stream,
    on_event: listener
  )
  result_task
end