phronomy 0.21.0 → 0.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +11 -0
- data/docs/getting-started.md +26 -17
- data/examples/workflows/agent_event_mapping.rb +27 -30
- data/lib/phronomy/agent/async_event_api.rb +14 -4
- data/lib/phronomy/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ce5a4ac39be13ef17ca1c7cd5d812b0ccdd8ea8523fdf2e59ee8f7e78e2830fa
|
|
4
|
+
data.tar.gz: 3c943cd7b11ddd1bbe2e22fdd16f3855564361c3dba093d39f5f32d193850b5a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e41fcf5aee7eaed49f3ef13c7399c787c281232909b07d1fa2a2e14b4a4d443222280ead723e885faeea0534e9173c036e16e90e6af04de4a440f0a76020e2c1
|
|
7
|
+
data.tar.gz: f0dbf8fa8947760cafbc530226a021b009acf3f0be37ddee08a5404087422b5508cd5df83ab50456b43fa8f1eb57a889f8a1974372d95b98edcad1752ddda562
|
data/README.md
CHANGED
|
@@ -91,6 +91,17 @@ task = ResearchAgent.new.invoke_async("Research Ruby AI frameworks")
|
|
|
91
91
|
result = task.wait_result # top-level/external caller only
|
|
92
92
|
```
|
|
93
93
|
|
|
94
|
+
A block listener receives Agent lifecycle events and is equivalent to `on_event:`:
|
|
95
|
+
|
|
96
|
+
```ruby
|
|
97
|
+
task = ResearchAgent.new.invoke_async("Research Ruby AI frameworks") do |event|
|
|
98
|
+
puts event.type # :done, :error, :tool_call, :tool_result, etc.
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# on_event: keyword form is also accepted and behaves identically
|
|
102
|
+
task = ResearchAgent.new.invoke_async("Research Ruby AI frameworks", on_event: listener)
|
|
103
|
+
```
|
|
104
|
+
|
|
94
105
|
## Runtime model
|
|
95
106
|
|
|
96
107
|
Phronomy uses one completion model with two execution mechanisms:
|
data/docs/getting-started.md
CHANGED
|
@@ -142,6 +142,19 @@ task = agent.invoke_async("Hello")
|
|
|
142
142
|
result = task.wait_result
|
|
143
143
|
```
|
|
144
144
|
|
|
145
|
+
Both `invoke` and `invoke_async` can receive public Agent events through either
|
|
146
|
+
an `on_event:` listener or a block. A block is convenient when the listener is
|
|
147
|
+
local to the call:
|
|
148
|
+
|
|
149
|
+
```ruby
|
|
150
|
+
task = agent.invoke_async("Hello") do |event|
|
|
151
|
+
puts event.payload[:output] if event.type == :done
|
|
152
|
+
end
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Use `on_event:` when the listener already exists as a callable. Do not provide
|
|
156
|
+
both `on_event:` and a block to the same invocation.
|
|
157
|
+
|
|
145
158
|
`Phronomy::Task` is the common caller-facing completion handle for asynchronous
|
|
146
159
|
Phronomy work. Logical lifecycle progress is driven by EventLoop/FSMSession;
|
|
147
160
|
synchronous work that must execute away from EventLoop is submitted to
|
|
@@ -159,13 +172,12 @@ end
|
|
|
159
172
|
```
|
|
160
173
|
|
|
161
174
|
```ruby
|
|
162
|
-
task = agent.stream_async(
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
)
|
|
175
|
+
task = agent.stream_async("Explain the design") do |event|
|
|
176
|
+
puts event.payload if event.type == :token
|
|
177
|
+
end
|
|
166
178
|
```
|
|
167
179
|
|
|
168
|
-
|
|
180
|
+
Agent event callbacks execute on EventLoop and therefore should return quickly.
|
|
169
181
|
|
|
170
182
|
## Human-in-the-loop approval
|
|
171
183
|
|
|
@@ -283,18 +295,15 @@ workflow = Phronomy::Workflow.define(AnswerContext) do
|
|
|
283
295
|
entry :asking, ->(ctx) {
|
|
284
296
|
thread_id = ctx.thread_id
|
|
285
297
|
|
|
286
|
-
my_agent.invoke_async(
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
)
|
|
296
|
-
}
|
|
297
|
-
)
|
|
298
|
+
my_agent.invoke_async(ctx.question) do |event|
|
|
299
|
+
next unless event.type == :done
|
|
300
|
+
|
|
301
|
+
workflow.signal(
|
|
302
|
+
thread_id: thread_id,
|
|
303
|
+
event: :answer_ready,
|
|
304
|
+
payload: {answer: event.payload[:output]}
|
|
305
|
+
)
|
|
306
|
+
end
|
|
298
307
|
|
|
299
308
|
ctx
|
|
300
309
|
}
|
|
@@ -42,36 +42,33 @@ workflow = Phronomy::Workflow.define(GenerationContext) do
|
|
|
42
42
|
request_id = context.generation_request_id
|
|
43
43
|
|
|
44
44
|
# The Agent Task is intentionally not returned from the entry action.
|
|
45
|
-
#
|
|
46
|
-
agent.invoke_async(
|
|
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
|
-
)
|
|
45
|
+
# The block is the application-level integration channel.
|
|
46
|
+
agent.invoke_async(context.prompt) do |agent_event|
|
|
47
|
+
workflow_event =
|
|
48
|
+
case agent_event.type
|
|
49
|
+
when :done
|
|
50
|
+
:generation_completed
|
|
51
|
+
when :error, :timeout, :cancelled, :approval_required
|
|
52
|
+
:generation_failed
|
|
53
|
+
end
|
|
54
|
+
next unless workflow_event
|
|
55
|
+
|
|
56
|
+
workflow.signal(
|
|
57
|
+
thread_id: context.thread_id,
|
|
58
|
+
event: workflow_event,
|
|
59
|
+
payload: {
|
|
60
|
+
generation_request_id: request_id,
|
|
61
|
+
agent_result: (
|
|
62
|
+
agent_event.payload if agent_event.type == :done
|
|
63
|
+
),
|
|
64
|
+
error:
|
|
65
|
+
agent_event.payload[:error] ||
|
|
66
|
+
Phronomy::Error.new(
|
|
67
|
+
"Agent requested Tool approval"
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
)
|
|
71
|
+
end
|
|
75
72
|
|
|
76
73
|
context
|
|
77
74
|
}
|
|
@@ -5,7 +5,15 @@ module Phronomy
|
|
|
5
5
|
# Public Agent execution API. Agent instances are always stateful and all
|
|
6
6
|
# operations are coordinated through Phronomy::Persistence.
|
|
7
7
|
module AsyncEventApi
|
|
8
|
-
def invoke(
|
|
8
|
+
def invoke(
|
|
9
|
+
input,
|
|
10
|
+
thread_id: nil,
|
|
11
|
+
config: {},
|
|
12
|
+
invocation_context: nil,
|
|
13
|
+
on_event: nil,
|
|
14
|
+
&block
|
|
15
|
+
)
|
|
16
|
+
listener = resolve_event_listener(on_event, block)
|
|
9
17
|
if invocation_context
|
|
10
18
|
thread_id, config = _apply_invocation_context(thread_id, config, invocation_context)
|
|
11
19
|
end
|
|
@@ -15,7 +23,7 @@ module Phronomy
|
|
|
15
23
|
input,
|
|
16
24
|
thread_id: thread_id,
|
|
17
25
|
config: config,
|
|
18
|
-
on_event:
|
|
26
|
+
on_event: listener
|
|
19
27
|
).wait_result
|
|
20
28
|
[result, result[:usage]]
|
|
21
29
|
end
|
|
@@ -27,8 +35,10 @@ module Phronomy
|
|
|
27
35
|
config: {},
|
|
28
36
|
invocation_context: nil,
|
|
29
37
|
on_tool_approval_required: nil,
|
|
30
|
-
on_event: nil
|
|
38
|
+
on_event: nil,
|
|
39
|
+
&block
|
|
31
40
|
)
|
|
41
|
+
listener = resolve_event_listener(on_event, block)
|
|
32
42
|
if invocation_context
|
|
33
43
|
thread_id, config = _apply_invocation_context(thread_id, config, invocation_context)
|
|
34
44
|
end
|
|
@@ -40,7 +50,7 @@ module Phronomy
|
|
|
40
50
|
mode: :invoke,
|
|
41
51
|
approval_policy: approval[:policy],
|
|
42
52
|
approval_listener: approval[:listener],
|
|
43
|
-
on_event:
|
|
53
|
+
on_event: listener
|
|
44
54
|
)
|
|
45
55
|
end
|
|
46
56
|
|
data/lib/phronomy/version.rb
CHANGED