robot_lab 0.0.4 → 0.0.7

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.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +76 -0
  3. data/README.md +64 -6
  4. data/Rakefile +2 -1
  5. data/docs/api/core/index.md +41 -46
  6. data/docs/api/core/memory.md +200 -154
  7. data/docs/api/core/network.md +13 -3
  8. data/docs/api/core/robot.md +38 -26
  9. data/docs/api/core/state.md +55 -73
  10. data/docs/api/index.md +7 -28
  11. data/docs/api/messages/index.md +35 -20
  12. data/docs/api/messages/text-message.md +67 -21
  13. data/docs/api/messages/tool-call-message.md +80 -41
  14. data/docs/api/messages/tool-result-message.md +119 -50
  15. data/docs/api/messages/user-message.md +48 -24
  16. data/docs/architecture/core-concepts.md +10 -15
  17. data/docs/concepts.md +5 -7
  18. data/docs/examples/index.md +2 -2
  19. data/docs/getting-started/configuration.md +80 -0
  20. data/docs/guides/building-robots.md +10 -9
  21. data/docs/guides/creating-networks.md +49 -0
  22. data/docs/guides/index.md +0 -5
  23. data/docs/guides/rails-integration.md +244 -162
  24. data/docs/guides/streaming.md +118 -138
  25. data/docs/index.md +0 -8
  26. data/examples/03_network.rb +10 -7
  27. data/examples/08_llm_config.rb +40 -11
  28. data/examples/09_chaining.rb +45 -6
  29. data/examples/11_network_introspection.rb +30 -7
  30. data/examples/12_message_bus.rb +1 -1
  31. data/examples/14_rusty_circuit/heckler.rb +14 -8
  32. data/examples/14_rusty_circuit/open_mic.rb +5 -3
  33. data/examples/14_rusty_circuit/scout.rb +14 -31
  34. data/examples/15_memory_network_and_bus/editorial_pipeline.rb +1 -1
  35. data/examples/16_writers_room/display.rb +158 -0
  36. data/examples/16_writers_room/output/.gitignore +4 -0
  37. data/examples/16_writers_room/output/README.md +69 -0
  38. data/examples/16_writers_room/output/opus_001.md +263 -0
  39. data/examples/16_writers_room/output/opus_001_notes.log +470 -0
  40. data/examples/16_writers_room/output/opus_002.md +245 -0
  41. data/examples/16_writers_room/output/opus_002_notes.log +546 -0
  42. data/examples/16_writers_room/output/opus_002_screenplay.md +7989 -0
  43. data/examples/16_writers_room/output/opus_002_screenplay_notes.md +993 -0
  44. data/examples/16_writers_room/prompts/screenplay_writer.md +66 -0
  45. data/examples/16_writers_room/prompts/writer.md +37 -0
  46. data/examples/16_writers_room/room.rb +186 -0
  47. data/examples/16_writers_room/tools.rb +173 -0
  48. data/examples/16_writers_room/writer.rb +121 -0
  49. data/examples/16_writers_room/writers_room.rb +256 -0
  50. data/lib/generators/robot_lab/templates/initializer.rb.tt +0 -13
  51. data/lib/robot_lab/memory.rb +8 -32
  52. data/lib/robot_lab/network.rb +13 -20
  53. data/lib/robot_lab/robot/bus_messaging.rb +239 -0
  54. data/lib/robot_lab/robot/mcp_management.rb +88 -0
  55. data/lib/robot_lab/robot/template_rendering.rb +130 -0
  56. data/lib/robot_lab/robot.rb +56 -420
  57. data/lib/robot_lab/run_config.rb +184 -0
  58. data/lib/robot_lab/state_proxy.rb +2 -12
  59. data/lib/robot_lab/task.rb +8 -1
  60. data/lib/robot_lab/utils.rb +39 -0
  61. data/lib/robot_lab/version.rb +1 -1
  62. data/lib/robot_lab.rb +29 -8
  63. data/mkdocs.yml +0 -11
  64. metadata +21 -20
  65. data/docs/api/adapters/anthropic.md +0 -121
  66. data/docs/api/adapters/gemini.md +0 -133
  67. data/docs/api/adapters/index.md +0 -104
  68. data/docs/api/adapters/openai.md +0 -134
  69. data/docs/api/history/active-record-adapter.md +0 -275
  70. data/docs/api/history/config.md +0 -284
  71. data/docs/api/history/index.md +0 -128
  72. data/docs/api/history/thread-manager.md +0 -194
  73. data/docs/guides/history.md +0 -359
  74. data/lib/robot_lab/adapters/anthropic.rb +0 -163
  75. data/lib/robot_lab/adapters/base.rb +0 -85
  76. data/lib/robot_lab/adapters/gemini.rb +0 -193
  77. data/lib/robot_lab/adapters/openai.rb +0 -160
  78. data/lib/robot_lab/adapters/registry.rb +0 -81
  79. data/lib/robot_lab/errors.rb +0 -70
  80. data/lib/robot_lab/history/active_record_adapter.rb +0 -146
  81. data/lib/robot_lab/history/config.rb +0 -115
  82. data/lib/robot_lab/history/thread_manager.rb +0 -93
  83. data/lib/robot_lab/robotic_model.rb +0 -324
@@ -36,7 +36,8 @@ Robot.new(
36
36
  max_tokens: nil,
37
37
  presence_penalty: nil,
38
38
  frequency_penalty: nil,
39
- stop: nil
39
+ stop: nil,
40
+ config: nil
40
41
  )
41
42
  ```
42
43
 
@@ -58,6 +59,7 @@ Robot.new(
58
59
  | `on_tool_result` | `Proc`, `nil` | `nil` | Callback invoked when a tool returns a result |
59
60
  | `enable_cache` | `Boolean` | `true` | Whether to enable semantic caching |
60
61
  | `bus` | `TypedBus::MessageBus`, `nil` | `nil` | Optional message bus for inter-robot communication |
62
+ | `config` | `RunConfig`, `nil` | `nil` | Shared config merged with explicit kwargs (see [RunConfig](#runconfig)) |
61
63
  | `temperature` | `Float`, `nil` | `nil` | Controls randomness (0.0-1.0) |
62
64
  | `top_p` | `Float`, `nil` | `nil` | Nucleus sampling threshold |
63
65
  | `top_k` | `Integer`, `nil` | `nil` | Top-k sampling |
@@ -66,6 +68,8 @@ Robot.new(
66
68
  | `frequency_penalty` | `Float`, `nil` | `nil` | Penalize based on frequency |
67
69
  | `stop` | `String`, `Array`, `nil` | `nil` | Stop sequences |
68
70
 
71
+ When both `config:` and explicit kwargs (e.g., `temperature:`) are provided, explicit kwargs always win.
72
+
69
73
  ## Factory Method
70
74
 
71
75
  ```ruby
@@ -97,6 +101,7 @@ If `name` is omitted, it defaults to `"robot"`.
97
101
  | `memory` | `Memory` | Inherent memory (used when standalone, not in network) |
98
102
  | `bus` | `TypedBus::MessageBus`, `nil` | Message bus instance (nil if not configured) |
99
103
  | `outbox` | `Hash` | Sent messages tracked by composite key with status and replies |
104
+ | `config` | `RunConfig` | Effective RunConfig (merged from constructor kwargs and passed-in config) |
100
105
  | `mcp_config` | `Symbol`, `Array` | Build-time MCP configuration (raw, unresolved) |
101
106
  | `tools_config` | `Symbol`, `Array` | Build-time tools configuration (raw, unresolved) |
102
107
 
@@ -279,24 +284,6 @@ Publish a correlated reply to a specific message. The `in_reply_to` composite ke
279
284
 
280
285
  **Raises:** `BusError` if no bus is configured.
281
286
 
282
- ### reply
283
-
284
- ```ruby
285
- robot.reply(message, "Here's my response")
286
- # => RobotMessage
287
- ```
288
-
289
- Convenience method that wraps `send_reply`. Extracts the `from` and `key` from the incoming `RobotMessage` automatically.
290
-
291
- **Parameters:**
292
-
293
- | Name | Type | Description |
294
- |------|------|-------------|
295
- | `message` | `RobotMessage` | The message being replied to |
296
- | `content` | `String`, `Hash` | Reply payload |
297
-
298
- **Returns:** `RobotMessage`
299
-
300
287
  ### on_message
301
288
 
302
289
  ```ruby
@@ -315,14 +302,14 @@ Register a custom handler for incoming bus messages. Block arity controls delive
315
302
  # Auto-ack mode (1 arg)
316
303
  robot.on_message do |message|
317
304
  joke = run(message.content.to_s).last_text_content
318
- reply(message, joke)
305
+ send_reply(to: message.from.to_sym, content: joke, in_reply_to: message.key)
319
306
  end
320
307
 
321
308
  # Manual mode (2 args)
322
309
  robot.on_message do |delivery, message|
323
310
  if message.content.to_s.length > 10
324
311
  delivery.ack!
325
- reply(message, "Got it!")
312
+ send_reply(to: message.from.to_sym, content: "Got it!", in_reply_to: message.key)
326
313
  else
327
314
  delivery.nack!
328
315
  end
@@ -459,6 +446,27 @@ Front matter supports two categories of keys:
459
446
  | `tools` | `Array<String>` | Tool class names resolved via `Object.const_get` |
460
447
  | `mcp` | `Array<Hash>` | MCP server configurations |
461
448
 
449
+ ## RunConfig
450
+
451
+ `RunConfig` provides shared operational defaults that flow through the configuration hierarchy. Pass it via the `config:` parameter on `Robot.new` or `RobotLab.build`.
452
+
453
+ ```ruby
454
+ shared = RobotLab::RunConfig.new(model: "claude-sonnet-4", temperature: 0.7)
455
+
456
+ robot = RobotLab.build(
457
+ name: "writer",
458
+ system_prompt: "You write creatively.",
459
+ config: shared,
460
+ temperature: 0.9 # explicit kwargs override config
461
+ )
462
+
463
+ robot.config #=> RunConfig with model: "claude-sonnet-4", temperature: 0.9, ...
464
+ ```
465
+
466
+ RunConfig fields: `model`, `temperature`, `top_p`, `top_k`, `max_tokens`, `presence_penalty`, `frequency_penalty`, `stop`, `mcp`, `tools`, `on_tool_call`, `on_tool_result`, `bus`, `enable_cache`.
467
+
468
+ See [Configuration: RunConfig](../../getting-started/configuration.md#runconfig-shared-operational-defaults) for full details.
469
+
462
470
  ## Configuration Hierarchy
463
471
 
464
472
  Tools and MCP servers use hierarchical resolution: **runtime > robot > network > global config**.
@@ -466,11 +474,15 @@ Tools and MCP servers use hierarchical resolution: **runtime > robot > network >
466
474
  ```
467
475
  RobotLab.config (global)
468
476
  |
469
- +-- Network
477
+ +-- Network (config:)
470
478
  | |
471
- | +-- Robot (build-time mcp:, tools:)
472
- | |
473
- | +-- run() call (runtime mcp:, tools:)
479
+ | +-- Task (config:)
480
+ | | |
481
+ | | +-- Robot (config: + build-time mcp:, tools:)
482
+ | | |
483
+ | | +-- Template front matter
484
+ | | |
485
+ | | +-- run() call (runtime mcp:, tools:)
474
486
  ```
475
487
 
476
488
  Values at each level:
@@ -572,7 +584,7 @@ end
572
584
 
573
585
  bob.on_message do |message|
574
586
  joke = bob.run(message.content.to_s).last_text_content
575
- bob.reply(message, joke)
587
+ bob.send_reply(to: message.from.to_sym, content: joke, in_reply_to: message.key)
576
588
  end
577
589
 
578
590
  alice.send_message(to: :bob, content: "Tell me a robot joke.")
@@ -1,54 +1,43 @@
1
- # State
1
+ # Memory (State Management)
2
2
 
3
- Manages conversation data, results, and memory.
3
+ Memory manages conversation data, results, and runtime state. There is no separate `State` class; `Memory` serves this role.
4
4
 
5
- ## Class: `RobotLab::State`
5
+ ## Class: `RobotLab::Memory`
6
6
 
7
7
  ```ruby
8
- state = RobotLab.create_state(
9
- message: "Hello",
8
+ memory = RobotLab.create_memory(
10
9
  data: { user_id: "123" }
11
10
  )
12
11
  ```
13
12
 
14
13
  ## Attributes
15
14
 
16
- ### thread_id
15
+ ### session_id
17
16
 
18
17
  ```ruby
19
- state.thread_id # => String | nil
18
+ memory.session_id # => String | nil
20
19
  ```
21
20
 
22
- Conversation thread identifier for persistence.
23
-
24
- ### memory
25
-
26
- ```ruby
27
- state.memory # => Memory
28
- ```
29
-
30
- Shared key-value store.
31
-
32
- ## Methods
21
+ Conversation session identifier for persistence.
33
22
 
34
23
  ### data
35
24
 
36
25
  ```ruby
37
- state.data # => StateProxy
26
+ memory.data # => StateProxy
38
27
  ```
39
28
 
40
29
  Access workflow data as a proxy object.
41
30
 
42
31
  ```ruby
43
- state.data[:user_id] # Hash access
44
- state.data.user_id # Method access
45
- state.data[:status] = "active"
32
+ memory.data[:user_id] # Hash access
33
+ memory.data.user_id # Method access
34
+ memory.data[:status] = "active"
46
35
  ```
47
36
 
48
37
  ### results
49
38
 
50
39
  ```ruby
51
- state.results # => Array<RobotResult>
40
+ memory.results # => Array<RobotResult>
52
41
  ```
53
42
 
54
43
  All robot execution results.
@@ -56,15 +45,17 @@ All robot execution results.
56
45
  ### messages
57
46
 
58
47
  ```ruby
59
- state.messages # => Array<Message>
48
+ memory.messages # => Array<Message>
60
49
  ```
61
50
 
62
51
  Formatted conversation messages for LLM.
63
52
 
53
+ ## Methods
54
+
64
55
  ### append_result
65
56
 
66
57
  ```ruby
67
- state.append_result(robot_result)
58
+ memory.append_result(robot_result)
68
59
  ```
69
60
 
70
61
  Add a robot result to history.
@@ -72,7 +63,7 @@ Add a robot result to history.
72
63
  ### set_results
73
64
 
74
65
  ```ruby
75
- state.set_results(array_of_results)
66
+ memory.set_results(array_of_results)
76
67
  ```
77
68
 
78
69
  Replace all results.
@@ -80,23 +71,23 @@ Replace all results.
80
71
  ### results_from
81
72
 
82
73
  ```ruby
83
- state.results_from(5) # => Array<RobotResult>
74
+ memory.results_from(5) # => Array<RobotResult>
84
75
  ```
85
76
 
86
77
  Get results starting at index.
87
78
 
88
- ### thread_id=
79
+ ### session_id=
89
80
 
90
81
  ```ruby
91
- state.thread_id = "thread_123"
82
+ memory.session_id = "session_123"
92
83
  ```
93
84
 
94
- Set the thread identifier.
85
+ Set the session identifier.
95
86
 
96
87
  ### format_history
97
88
 
98
89
  ```ruby
99
- state.format_history # => Array<Message>
90
+ memory.format_history # => Array<Message>
100
91
  ```
101
92
 
102
93
  Format results as conversation history.
@@ -104,7 +95,7 @@ Format results as conversation history.
104
95
  ### clone
105
96
 
106
97
  ```ruby
107
- new_state = state.clone
98
+ new_memory = memory.clone
108
99
  ```
109
100
 
110
101
  Create a deep copy.
@@ -112,7 +103,7 @@ Create a deep copy.
112
103
  ### to_h
113
104
 
114
105
  ```ruby
115
- state.to_h # => Hash
106
+ memory.to_h # => Hash
116
107
  ```
117
108
 
118
109
  Hash representation.
@@ -120,7 +111,7 @@ Hash representation.
120
111
  ### to_json
121
112
 
122
113
  ```ruby
123
- state.to_json # => String
114
+ memory.to_json # => String
124
115
  ```
125
116
 
126
117
  JSON representation.
@@ -128,7 +119,7 @@ JSON representation.
128
119
  ### from_hash (class method)
129
120
 
130
121
  ```ruby
131
- state = State.from_hash(hash)
122
+ memory = Memory.from_hash(hash)
132
123
  ```
133
124
 
134
125
  Restore from hash.
@@ -138,7 +129,7 @@ Restore from hash.
138
129
  The `data` attribute is a `StateProxy`:
139
130
 
140
131
  ```ruby
141
- proxy = state.data
132
+ proxy = memory.data
142
133
 
143
134
  # Hash-style access
144
135
  proxy[:key]
@@ -160,19 +151,18 @@ proxy.empty?
160
151
  proxy.size
161
152
  ```
162
153
 
163
- ## Creating State
154
+ ## Creating Memory
164
155
 
165
156
  ### Basic
166
157
 
167
158
  ```ruby
168
- state = RobotLab.create_state(message: "Hello")
159
+ memory = RobotLab.create_memory
169
160
  ```
170
161
 
171
162
  ### With Data
172
163
 
173
164
  ```ruby
174
- state = RobotLab.create_state(
175
- message: "Process order",
165
+ memory = RobotLab.create_memory(
176
166
  data: {
177
167
  user_id: "user_123",
178
168
  order_id: "ord_456"
@@ -180,25 +170,18 @@ state = RobotLab.create_state(
180
170
  )
181
171
  ```
182
172
 
183
- ### With Thread ID
173
+ ### With Session ID
184
174
 
185
175
  ```ruby
186
- # Via UserMessage
187
- message = UserMessage.new("Continue", thread_id: "thread_123")
188
- state = RobotLab.create_state(message: message)
189
-
190
- # Direct assignment
191
- state = RobotLab.create_state(message: "Continue")
192
- state.thread_id = "thread_123"
176
+ memory = RobotLab.create_memory
177
+ memory.session_id = "session_123"
193
178
  ```
194
179
 
195
180
  ### With Existing Results
196
181
 
197
182
  ```ruby
198
- state = RobotLab.create_state(
199
- message: "Follow up",
200
- results: previous_results
201
- )
183
+ memory = RobotLab.create_memory
184
+ memory.set_results(previous_results)
202
185
  ```
203
186
 
204
187
  ## UserMessage
@@ -208,13 +191,13 @@ Enhanced message with metadata:
208
191
  ```ruby
209
192
  message = UserMessage.new(
210
193
  "What's my order status?",
211
- thread_id: "thread_123",
194
+ session_id: "session_123",
212
195
  system_prompt: "Respond in Spanish",
213
196
  metadata: { source: "web" }
214
197
  )
215
198
 
216
199
  message.content # => "What's my order status?"
217
- message.thread_id # => "thread_123"
200
+ message.session_id # => "session_123"
218
201
  message.system_prompt # => "Respond in Spanish"
219
202
  message.metadata # => { source: "web" }
220
203
  message.id # => UUID
@@ -226,48 +209,47 @@ message.created_at # => Time
226
209
  ### Accessing Data
227
210
 
228
211
  ```ruby
229
- state = RobotLab.create_state(
230
- message: "Help",
212
+ memory = RobotLab.create_memory(
231
213
  data: { user: { name: "Alice", plan: "pro" } }
232
214
  )
233
215
 
234
- state.data[:user][:name] # => "Alice"
235
- state.data.to_h # => { user: { name: "Alice", plan: "pro" } }
216
+ memory.data[:user][:name] # => "Alice"
217
+ memory.data.to_h # => { user: { name: "Alice", plan: "pro" } }
236
218
  ```
237
219
 
238
220
  ### Working with Results
239
221
 
240
222
  ```ruby
241
223
  # After running network
242
- state.results.size # Number of results
243
- state.results.last # Most recent
244
- state.results.map(&:robot_name) # ["classifier", "support"]
224
+ memory.results.size # Number of results
225
+ memory.results.last # Most recent
226
+ memory.results.map(&:robot_name) # ["classifier", "support"]
245
227
  ```
246
228
 
247
- ### Using Memory
229
+ ### Using Reactive Memory
248
230
 
249
231
  ```ruby
250
- state.memory.remember("intent", "billing")
251
- intent = state.memory.recall("intent")
232
+ memory.set(:intent, "billing")
233
+ intent = memory.get(:intent)
252
234
 
253
- scoped = state.memory.scoped("user:123")
254
- scoped.remember("preference", "dark_mode")
235
+ memory.subscribe(:status) do |change|
236
+ puts "Status changed to #{change.value} by #{change.writer}"
237
+ end
255
238
  ```
256
239
 
257
240
  ### Serialization
258
241
 
259
242
  ```ruby
260
- # Save state
261
- json = state.to_json
262
- File.write("state.json", json)
243
+ # Save memory
244
+ json = memory.to_json
245
+ File.write("memory.json", json)
263
246
 
264
- # Restore state
265
- data = JSON.parse(File.read("state.json"))
266
- state = State.from_hash(data)
247
+ # Restore memory
248
+ data = JSON.parse(File.read("memory.json"))
249
+ memory = Memory.from_hash(data)
267
250
  ```
268
251
 
269
252
  ## See Also
270
253
 
271
254
  - [State Management Architecture](../../architecture/state-management.md)
272
255
  - [Memory](memory.md)
273
- - [History Guide](../../guides/history.md)
data/docs/api/index.md CHANGED
@@ -10,9 +10,8 @@ The fundamental building blocks of RobotLab:
10
10
  |-------|-------------|
11
11
  | [Robot](core/robot.md) | LLM-powered agent with personality and tools |
12
12
  | [Network](core/network.md) | Orchestrates multiple robots |
13
- | [State](core/state.md) | Manages conversation and workflow data |
13
+ | [Memory](core/memory.md) | Reactive key-value store for sharing data |
14
14
  | [Tool](core/tool.md) | Custom function robots can call |
15
- | [Memory](core/memory.md) | Shared key-value store |
16
15
 
17
16
  ## Messages
18
17
 
@@ -21,20 +20,10 @@ Message types for LLM communication:
21
20
  | Class | Description |
22
21
  |-------|-------------|
23
22
  | [UserMessage](messages/user-message.md) | User input with metadata |
24
- | [TextMessage](messages/text-message.md) | Assistant text response |
23
+ | [TextMessage](messages/text-message.md) | Text message with role |
25
24
  | [ToolCallMessage](messages/tool-call-message.md) | Tool execution request |
26
25
  | [ToolResultMessage](messages/tool-result-message.md) | Tool execution result |
27
26
 
28
- ## Adapters
29
-
30
- Provider-specific message conversion:
31
-
32
- | Class | Description |
33
- |-------|-------------|
34
- | [Anthropic](adapters/anthropic.md) | Claude models adapter |
35
- | [OpenAI](adapters/openai.md) | GPT models adapter |
36
- | [Gemini](adapters/gemini.md) | Google Gemini adapter |
37
-
38
27
  ## MCP (Model Context Protocol)
39
28
 
40
29
  Connect to external tool servers:
@@ -54,29 +43,19 @@ Real-time response streaming:
54
43
  | [Context](streaming/context.md) | Streaming context |
55
44
  | [Events](streaming/events.md) | Event utilities |
56
45
 
57
- ## History
58
-
59
- Conversation persistence:
60
-
61
- | Class | Description |
62
- |-------|-------------|
63
- | [Config](history/config.md) | History configuration |
64
- | [ThreadManager](history/thread-manager.md) | Thread lifecycle |
65
- | [ActiveRecordAdapter](history/active-record-adapter.md) | Rails adapter |
66
-
67
46
  ## Module Methods
68
47
 
69
48
  ### RobotLab
70
49
 
71
50
  ```ruby
72
51
  # Configuration
73
- RobotLab.configuration
74
- RobotLab.configure { |config| ... }
52
+ RobotLab.config # => Config instance
53
+ RobotLab.reload_config! # => reload from all sources
75
54
 
76
55
  # Building
77
- RobotLab.build { ... }
78
- RobotLab.create_network { ... }
79
- RobotLab.create_state(...)
56
+ RobotLab.build(name:, template:, system_prompt:, context:, **options)
57
+ RobotLab.create_network(name:, concurrency:) { ... }
58
+ RobotLab.create_memory(data:, enable_cache:, **options)
80
59
  ```
81
60
 
82
61
  See individual class documentation for detailed method references.
@@ -8,60 +8,75 @@ RobotLab uses a structured message system to represent conversations between use
8
8
 
9
9
  ```ruby
10
10
  # User input
11
- user_msg = UserMessage.new("Hello", thread_id: "123")
11
+ user_msg = UserMessage.new("Hello", session_id: "123")
12
12
 
13
13
  # Assistant response
14
- text_msg = TextMessage.new("Hi there!")
14
+ text_msg = TextMessage.new(role: "assistant", content: "Hi there!")
15
15
 
16
16
  # Tool interaction
17
- tool_call = ToolCallMessage.new(id: "call_1", name: "get_weather", input: { city: "NYC" })
18
- tool_result = ToolResultMessage.new(id: "call_1", result: { temp: 72 })
17
+ tool = ToolMessage.new(id: "call_1", name: "get_weather", input: { city: "NYC" })
18
+ tool_call = ToolCallMessage.new(role: "assistant", tools: [tool])
19
+ tool_result = ToolResultMessage.new(tool: tool, content: { data: { temp: 72 } })
19
20
  ```
20
21
 
21
22
  ## Message Hierarchy
22
23
 
23
24
  ```
24
25
  Message (base)
25
- ├── UserMessage - User input with metadata
26
- ├── TextMessage - Assistant text response
27
- ├── ToolMessage - Tool-related messages
28
- │ ├── ToolCallMessage - Tool invocation
29
- │ └── ToolResultMessage - Tool result
30
- └── SystemMessage - System prompts
26
+ ├── TextMessage - role + text content
27
+ ├── ToolCallMessage - role + Array<ToolMessage>
28
+ └── ToolResultMessage - tool + result content
29
+
30
+ UserMessage - Standalone (not a Message subclass)
31
+ ToolMessage - Standalone (not a Message subclass)
31
32
  ```
32
33
 
33
34
  ## Common Interface
34
35
 
35
- All messages implement:
36
+ All Message subclasses implement:
36
37
 
37
38
  ```ruby
38
- message.role # => Symbol (:user, :assistant, :tool)
39
+ message.role # => String ("user", "assistant", "tool_result")
39
40
  message.content # => String or structured data
41
+ message.type # => String ("text", "tool_call", "tool_result")
40
42
  message.to_h # => Hash representation
41
43
  message.to_json # => JSON string
42
44
  ```
43
45
 
46
+ Type and role predicates:
47
+
48
+ ```ruby
49
+ message.text? # => true if type is "text"
50
+ message.tool_call? # => true if type is "tool_call"
51
+ message.tool_result? # => true if type is "tool_result"
52
+ message.system? # => true if role is "system"
53
+ message.user? # => true if role is "user"
54
+ message.assistant? # => true if role is "assistant"
55
+ message.stopped? # => true if stop_reason is "stop"
56
+ message.tool_stop? # => true if stop_reason is "tool"
57
+ ```
58
+
44
59
  ## Classes
45
60
 
46
61
  | Class | Description |
47
62
  |-------|-------------|
48
- | [UserMessage](user-message.md) | User input with thread and metadata |
49
- | [TextMessage](text-message.md) | Assistant text response |
50
- | [ToolCallMessage](tool-call-message.md) | Tool invocation request |
63
+ | [UserMessage](user-message.md) | User input with session and metadata |
64
+ | [TextMessage](text-message.md) | Text message with role (system, user, or assistant) |
65
+ | [ToolCallMessage](tool-call-message.md) | Tool invocation request containing ToolMessage objects |
51
66
  | [ToolResultMessage](tool-result-message.md) | Tool execution result |
52
67
 
53
- ## Usage in State
68
+ ## Usage in Memory
54
69
 
55
- Messages are typically accessed through state:
70
+ Messages are typically accessed through memory:
56
71
 
57
72
  ```ruby
58
- state.messages # => Array<Message>
73
+ memory.messages # => Array<Message>
59
74
 
60
75
  # Format for LLM
61
- state.format_history # => Array<Hash>
76
+ memory.format_history # => Array<Message>
62
77
  ```
63
78
 
64
79
  ## See Also
65
80
 
66
- - [State](../core/state.md)
81
+ - [Memory](../core/memory.md)
67
82
  - [Message Flow Architecture](../../architecture/message-flow.md)