robot_lab 0.0.4 → 0.0.6
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/CHANGELOG.md +50 -0
- data/README.md +64 -6
- data/Rakefile +2 -1
- data/docs/api/core/index.md +41 -46
- data/docs/api/core/memory.md +200 -154
- data/docs/api/core/network.md +13 -3
- data/docs/api/core/robot.md +38 -26
- data/docs/api/core/state.md +55 -73
- data/docs/api/index.md +7 -28
- data/docs/api/messages/index.md +35 -20
- data/docs/api/messages/text-message.md +67 -21
- data/docs/api/messages/tool-call-message.md +80 -41
- data/docs/api/messages/tool-result-message.md +119 -50
- data/docs/api/messages/user-message.md +48 -24
- data/docs/architecture/core-concepts.md +10 -15
- data/docs/concepts.md +5 -7
- data/docs/examples/index.md +2 -2
- data/docs/getting-started/configuration.md +80 -0
- data/docs/guides/building-robots.md +10 -9
- data/docs/guides/creating-networks.md +49 -0
- data/docs/guides/index.md +0 -5
- data/docs/guides/rails-integration.md +244 -162
- data/docs/guides/streaming.md +118 -138
- data/docs/index.md +0 -8
- data/examples/03_network.rb +10 -7
- data/examples/08_llm_config.rb +40 -11
- data/examples/09_chaining.rb +45 -6
- data/examples/11_network_introspection.rb +30 -7
- data/examples/12_message_bus.rb +1 -1
- data/examples/14_rusty_circuit/heckler.rb +14 -8
- data/examples/14_rusty_circuit/open_mic.rb +5 -3
- data/examples/14_rusty_circuit/scout.rb +14 -31
- data/examples/15_memory_network_and_bus/editorial_pipeline.rb +1 -1
- data/examples/16_writers_room/display.rb +158 -0
- data/examples/16_writers_room/output/.gitignore +2 -0
- data/examples/16_writers_room/output/opus_001.md +263 -0
- data/examples/16_writers_room/output/opus_001_notes.log +470 -0
- data/examples/16_writers_room/prompts/writer.md +37 -0
- data/examples/16_writers_room/room.rb +150 -0
- data/examples/16_writers_room/tools.rb +162 -0
- data/examples/16_writers_room/writer.rb +121 -0
- data/examples/16_writers_room/writers_room.rb +162 -0
- data/lib/generators/robot_lab/templates/initializer.rb.tt +0 -13
- data/lib/robot_lab/memory.rb +8 -32
- data/lib/robot_lab/network.rb +13 -20
- data/lib/robot_lab/robot/bus_messaging.rb +239 -0
- data/lib/robot_lab/robot/mcp_management.rb +88 -0
- data/lib/robot_lab/robot/template_rendering.rb +130 -0
- data/lib/robot_lab/robot.rb +56 -420
- data/lib/robot_lab/run_config.rb +184 -0
- data/lib/robot_lab/state_proxy.rb +2 -12
- data/lib/robot_lab/task.rb +8 -1
- data/lib/robot_lab/utils.rb +39 -0
- data/lib/robot_lab/version.rb +1 -1
- data/lib/robot_lab.rb +29 -8
- data/mkdocs.yml +0 -11
- metadata +15 -20
- data/docs/api/adapters/anthropic.md +0 -121
- data/docs/api/adapters/gemini.md +0 -133
- data/docs/api/adapters/index.md +0 -104
- data/docs/api/adapters/openai.md +0 -134
- data/docs/api/history/active-record-adapter.md +0 -275
- data/docs/api/history/config.md +0 -284
- data/docs/api/history/index.md +0 -128
- data/docs/api/history/thread-manager.md +0 -194
- data/docs/guides/history.md +0 -359
- data/lib/robot_lab/adapters/anthropic.rb +0 -163
- data/lib/robot_lab/adapters/base.rb +0 -85
- data/lib/robot_lab/adapters/gemini.rb +0 -193
- data/lib/robot_lab/adapters/openai.rb +0 -160
- data/lib/robot_lab/adapters/registry.rb +0 -81
- data/lib/robot_lab/errors.rb +0 -70
- data/lib/robot_lab/history/active_record_adapter.rb +0 -146
- data/lib/robot_lab/history/config.rb +0 -115
- data/lib/robot_lab/history/thread_manager.rb +0 -93
- data/lib/robot_lab/robotic_model.rb +0 -324
data/docs/api/core/memory.md
CHANGED
|
@@ -1,314 +1,360 @@
|
|
|
1
1
|
# Memory
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Reactive key-value store for sharing data between robots.
|
|
4
4
|
|
|
5
5
|
## Class: `RobotLab::Memory`
|
|
6
6
|
|
|
7
7
|
```ruby
|
|
8
|
-
memory =
|
|
8
|
+
memory = robot.memory
|
|
9
9
|
|
|
10
|
-
memory.
|
|
11
|
-
value = memory.
|
|
10
|
+
memory.set(:key, "value")
|
|
11
|
+
value = memory.get(:key)
|
|
12
12
|
```
|
|
13
13
|
|
|
14
14
|
## Constants
|
|
15
15
|
|
|
16
|
-
###
|
|
16
|
+
### RESERVED_KEYS
|
|
17
17
|
|
|
18
18
|
```ruby
|
|
19
|
-
Memory::
|
|
19
|
+
Memory::RESERVED_KEYS # => [:data, :results, :messages, :session_id, :cache]
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
Reserved keys with special accessors and behavior.
|
|
23
23
|
|
|
24
24
|
## Constructor
|
|
25
25
|
|
|
26
26
|
```ruby
|
|
27
|
-
memory = Memory.new(
|
|
27
|
+
memory = Memory.new(
|
|
28
|
+
data: {},
|
|
29
|
+
results: [],
|
|
30
|
+
messages: [],
|
|
31
|
+
session_id: nil,
|
|
32
|
+
backend: :auto,
|
|
33
|
+
enable_cache: true,
|
|
34
|
+
network_name: nil
|
|
35
|
+
)
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
**Parameters:**
|
|
39
|
+
|
|
40
|
+
| Name | Type | Default | Description |
|
|
41
|
+
|------|------|---------|-------------|
|
|
42
|
+
| `data` | `Hash` | `{}` | Initial runtime data |
|
|
43
|
+
| `results` | `Array` | `[]` | Pre-loaded robot results |
|
|
44
|
+
| `messages` | `Array` | `[]` | Pre-loaded conversation messages |
|
|
45
|
+
| `session_id` | `String, nil` | `nil` | Session identifier |
|
|
46
|
+
| `backend` | `Symbol` | `:auto` | Storage backend (`:auto`, `:redis`, `:hash`) |
|
|
47
|
+
| `enable_cache` | `Boolean` | `true` | Whether to enable semantic caching |
|
|
48
|
+
| `network_name` | `String, nil` | `nil` | Network this memory belongs to |
|
|
49
|
+
|
|
50
|
+
## Factory Method
|
|
51
|
+
|
|
52
|
+
```ruby
|
|
53
|
+
memory = RobotLab.create_memory(data: { user_id: 123 })
|
|
28
54
|
```
|
|
29
55
|
|
|
30
56
|
## Methods
|
|
31
57
|
|
|
32
|
-
###
|
|
58
|
+
### set
|
|
33
59
|
|
|
34
60
|
```ruby
|
|
35
|
-
memory.
|
|
61
|
+
memory.set(:key, value)
|
|
36
62
|
```
|
|
37
63
|
|
|
38
|
-
Store a value.
|
|
64
|
+
Store a value and notify subscribers asynchronously.
|
|
39
65
|
|
|
40
66
|
**Parameters:**
|
|
41
67
|
|
|
42
68
|
| Name | Type | Description |
|
|
43
69
|
|------|------|-------------|
|
|
44
|
-
| `key` | `
|
|
70
|
+
| `key` | `Symbol`, `String` | Storage key |
|
|
45
71
|
| `value` | `Object` | Value to store |
|
|
46
72
|
|
|
47
|
-
###
|
|
73
|
+
### get
|
|
48
74
|
|
|
49
75
|
```ruby
|
|
50
|
-
memory.
|
|
76
|
+
memory.get(:key) # => value or nil
|
|
77
|
+
memory.get(:key, wait: true) # Block until available
|
|
78
|
+
memory.get(:key, wait: 30) # Block up to 30 seconds
|
|
79
|
+
memory.get(:a, :b, :c, wait: 60) # Multiple keys, returns Hash
|
|
51
80
|
```
|
|
52
81
|
|
|
53
|
-
Retrieve
|
|
82
|
+
Retrieve one or more values, optionally waiting until they exist.
|
|
54
83
|
|
|
55
84
|
**Parameters:**
|
|
56
85
|
|
|
57
86
|
| Name | Type | Description |
|
|
58
87
|
|------|------|-------------|
|
|
59
|
-
| `
|
|
88
|
+
| `keys` | `Symbol`, `String` | One or more keys to retrieve |
|
|
89
|
+
| `wait` | `Boolean`, `Numeric` | `false`: immediate, `true`: block, `Numeric`: timeout |
|
|
60
90
|
|
|
61
|
-
**Returns:**
|
|
91
|
+
**Returns:** Single value for one key, `Hash` for multiple keys.
|
|
62
92
|
|
|
63
|
-
|
|
93
|
+
**Raises:** `AwaitTimeout` if timeout expires.
|
|
94
|
+
|
|
95
|
+
### key?
|
|
64
96
|
|
|
65
97
|
```ruby
|
|
66
|
-
memory.
|
|
98
|
+
memory.key?(:key) # => Boolean
|
|
67
99
|
```
|
|
68
100
|
|
|
69
|
-
Check if key exists.
|
|
101
|
+
Check if key exists. Aliases: `has_key?`, `include?`.
|
|
70
102
|
|
|
71
|
-
###
|
|
103
|
+
### delete
|
|
72
104
|
|
|
73
105
|
```ruby
|
|
74
|
-
memory.
|
|
106
|
+
memory.delete(:key) # => deleted value
|
|
75
107
|
```
|
|
76
108
|
|
|
77
|
-
Remove a key
|
|
109
|
+
Remove a key. Cannot delete reserved keys.
|
|
78
110
|
|
|
79
|
-
###
|
|
111
|
+
### keys
|
|
80
112
|
|
|
81
113
|
```ruby
|
|
82
|
-
memory.
|
|
114
|
+
memory.keys # => Array<Symbol>
|
|
83
115
|
```
|
|
84
116
|
|
|
85
|
-
Get all
|
|
117
|
+
Get all non-reserved keys.
|
|
86
118
|
|
|
87
|
-
###
|
|
119
|
+
### clear
|
|
88
120
|
|
|
89
121
|
```ruby
|
|
90
|
-
memory.
|
|
122
|
+
memory.clear
|
|
91
123
|
```
|
|
92
124
|
|
|
93
|
-
|
|
125
|
+
Clear all non-reserved keys.
|
|
94
126
|
|
|
95
|
-
###
|
|
127
|
+
### reset
|
|
96
128
|
|
|
97
129
|
```ruby
|
|
98
|
-
memory.
|
|
130
|
+
memory.reset
|
|
99
131
|
```
|
|
100
132
|
|
|
101
|
-
|
|
133
|
+
Reset memory to initial state (clears everything including reserved keys, preserves cache).
|
|
102
134
|
|
|
103
|
-
###
|
|
135
|
+
### subscribe
|
|
104
136
|
|
|
105
137
|
```ruby
|
|
106
|
-
memory.
|
|
138
|
+
sub_id = memory.subscribe(:key1, :key2) do |change|
|
|
139
|
+
puts "#{change.key} changed: #{change.value}"
|
|
140
|
+
end
|
|
107
141
|
```
|
|
108
142
|
|
|
109
|
-
|
|
143
|
+
Subscribe to changes on one or more keys. Callback receives a `MemoryChange` object.
|
|
110
144
|
|
|
111
|
-
|
|
145
|
+
**MemoryChange attributes:**
|
|
146
|
+
|
|
147
|
+
| Attribute | Type | Description |
|
|
148
|
+
|-----------|------|-------------|
|
|
149
|
+
| `key` | `Symbol` | The changed key |
|
|
150
|
+
| `value` | `Object` | New value |
|
|
151
|
+
| `previous` | `Object` | Previous value |
|
|
152
|
+
| `writer` | `String, nil` | Name of robot that wrote |
|
|
153
|
+
| `network_name` | `String, nil` | Network name |
|
|
154
|
+
| `timestamp` | `Time` | When the change occurred |
|
|
155
|
+
| `created?` | `Boolean` | Previous was nil |
|
|
156
|
+
| `updated?` | `Boolean` | Previous was not nil |
|
|
157
|
+
| `deleted?` | `Boolean` | New value is nil |
|
|
158
|
+
|
|
159
|
+
### subscribe_pattern
|
|
112
160
|
|
|
113
161
|
```ruby
|
|
114
|
-
memory.
|
|
162
|
+
sub_id = memory.subscribe_pattern("analysis:*") do |change|
|
|
163
|
+
puts "Analysis key #{change.key} updated"
|
|
164
|
+
end
|
|
115
165
|
```
|
|
116
166
|
|
|
117
|
-
|
|
167
|
+
Subscribe to keys matching a glob pattern (`*` and `?` supported).
|
|
118
168
|
|
|
119
|
-
|
|
169
|
+
### unsubscribe
|
|
120
170
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
171
|
+
```ruby
|
|
172
|
+
memory.unsubscribe(sub_id) # => Boolean
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Remove a subscription by its ID.
|
|
176
|
+
|
|
177
|
+
### merge!
|
|
178
|
+
|
|
179
|
+
```ruby
|
|
180
|
+
memory.merge!(key1: "value1", key2: "value2")
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Merge multiple key-value pairs into memory.
|
|
184
|
+
|
|
185
|
+
## Reserved Key Accessors
|
|
186
|
+
|
|
187
|
+
### data
|
|
188
|
+
|
|
189
|
+
```ruby
|
|
190
|
+
memory.data # => StateProxy
|
|
191
|
+
memory.data[:user_id] # Hash access
|
|
192
|
+
memory.data.user_id # Method access
|
|
193
|
+
memory.data[:status] = "active"
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Runtime data accessed through `StateProxy` for method-style access.
|
|
124
197
|
|
|
125
|
-
###
|
|
198
|
+
### results
|
|
126
199
|
|
|
127
200
|
```ruby
|
|
128
|
-
memory.
|
|
201
|
+
memory.results # => Array<RobotResult>
|
|
129
202
|
```
|
|
130
203
|
|
|
131
|
-
|
|
204
|
+
Accumulated robot results (returns a copy).
|
|
132
205
|
|
|
133
|
-
|
|
206
|
+
### messages
|
|
134
207
|
|
|
135
208
|
```ruby
|
|
136
|
-
|
|
137
|
-
total_keys: 15,
|
|
138
|
-
namespaces: ["user", "session"]
|
|
139
|
-
}
|
|
209
|
+
memory.messages # => Array<Message>
|
|
140
210
|
```
|
|
141
211
|
|
|
142
|
-
|
|
212
|
+
Conversation messages (returns a copy).
|
|
213
|
+
|
|
214
|
+
### session_id
|
|
143
215
|
|
|
144
216
|
```ruby
|
|
145
|
-
|
|
217
|
+
memory.session_id # => String | nil
|
|
218
|
+
memory.session_id = "abc" # Set session identifier
|
|
146
219
|
```
|
|
147
220
|
|
|
148
|
-
|
|
221
|
+
### cache
|
|
149
222
|
|
|
150
|
-
|
|
223
|
+
```ruby
|
|
224
|
+
memory.cache # => RubyLLM::SemanticCache
|
|
225
|
+
```
|
|
151
226
|
|
|
152
|
-
|
|
227
|
+
Semantic cache module (read-only after initialization).
|
|
153
228
|
|
|
154
|
-
|
|
229
|
+
## Serialization
|
|
155
230
|
|
|
156
|
-
|
|
231
|
+
### to_h
|
|
157
232
|
|
|
158
233
|
```ruby
|
|
159
|
-
|
|
234
|
+
memory.to_h
|
|
235
|
+
# => { data: {...}, results: [...], messages: [...], session_id: "...", custom: {...} }
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### to_json
|
|
160
239
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
scoped.exists?("name") # => true
|
|
164
|
-
scoped.forget("name")
|
|
165
|
-
scoped.all # Only "user:123:*" keys
|
|
166
|
-
scoped.clear # Clear only this scope
|
|
240
|
+
```ruby
|
|
241
|
+
memory.to_json # => String
|
|
167
242
|
```
|
|
168
243
|
|
|
169
|
-
###
|
|
244
|
+
### from_hash
|
|
170
245
|
|
|
171
246
|
```ruby
|
|
172
|
-
|
|
173
|
-
|
|
247
|
+
memory = Memory.from_hash(hash)
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
Reconstruct memory from a hash.
|
|
251
|
+
|
|
252
|
+
### clone
|
|
174
253
|
|
|
175
|
-
|
|
176
|
-
|
|
254
|
+
```ruby
|
|
255
|
+
new_memory = memory.clone
|
|
177
256
|
```
|
|
178
257
|
|
|
258
|
+
Deep copy with fresh subscriptions (cache and network_name preserved).
|
|
259
|
+
|
|
179
260
|
## Examples
|
|
180
261
|
|
|
181
262
|
### Basic Usage
|
|
182
263
|
|
|
183
264
|
```ruby
|
|
184
|
-
|
|
185
|
-
|
|
265
|
+
robot.memory.set(:user_name, "Alice")
|
|
266
|
+
robot.memory.set(:order_count, 5)
|
|
267
|
+
|
|
268
|
+
name = robot.memory.get(:user_name) # => "Alice"
|
|
269
|
+
count = robot.memory.get(:order_count) # => 5
|
|
270
|
+
```
|
|
186
271
|
|
|
187
|
-
|
|
188
|
-
|
|
272
|
+
### Bracket Access
|
|
273
|
+
|
|
274
|
+
```ruby
|
|
275
|
+
robot.memory[:user_id] = 123
|
|
276
|
+
robot.memory[:user_id] # => 123
|
|
189
277
|
```
|
|
190
278
|
|
|
191
279
|
### Storing Objects
|
|
192
280
|
|
|
193
281
|
```ruby
|
|
194
|
-
|
|
282
|
+
robot.memory.set(:user, {
|
|
195
283
|
id: 123,
|
|
196
284
|
name: "Alice",
|
|
197
285
|
plan: "pro"
|
|
198
286
|
})
|
|
199
287
|
|
|
200
|
-
user =
|
|
288
|
+
user = robot.memory.get(:user)
|
|
201
289
|
user[:plan] # => "pro"
|
|
202
290
|
```
|
|
203
291
|
|
|
204
|
-
###
|
|
292
|
+
### Blocking Reads (Network Parallel Execution)
|
|
205
293
|
|
|
206
294
|
```ruby
|
|
207
|
-
#
|
|
208
|
-
|
|
209
|
-
user.remember("last_login", Time.now)
|
|
210
|
-
user.remember("preferences", { theme: "dark" })
|
|
295
|
+
# In robot A (writer)
|
|
296
|
+
network.memory.set(:sentiment, { score: 0.8, confidence: 0.95 })
|
|
211
297
|
|
|
212
|
-
#
|
|
213
|
-
|
|
214
|
-
|
|
298
|
+
# In robot B (reader, may run concurrently)
|
|
299
|
+
result = network.memory.get(:sentiment, wait: true) # Block indefinitely
|
|
300
|
+
result = network.memory.get(:sentiment, wait: 30) # Block up to 30s
|
|
215
301
|
|
|
216
|
-
#
|
|
217
|
-
|
|
218
|
-
|
|
302
|
+
# Multiple keys with timeout
|
|
303
|
+
results = network.memory.get(:sentiment, :entities, :keywords, wait: 60)
|
|
304
|
+
# => { sentiment: {...}, entities: [...], keywords: [...] }
|
|
219
305
|
```
|
|
220
306
|
|
|
221
|
-
###
|
|
307
|
+
### Reactive Subscriptions
|
|
222
308
|
|
|
223
309
|
```ruby
|
|
224
|
-
#
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
# In handler robot
|
|
229
|
-
intent = state.memory.recall("SHARED:intent")
|
|
230
|
-
entities = state.memory.recall("SHARED:entities")
|
|
231
|
-
```
|
|
232
|
-
|
|
233
|
-
### In Tool Handlers
|
|
234
|
-
|
|
235
|
-
```ruby
|
|
236
|
-
tool :update_preference do
|
|
237
|
-
handler do |key:, value:, state:, **_|
|
|
238
|
-
prefs = state.memory.scoped("preferences")
|
|
239
|
-
old_value = prefs.recall(key)
|
|
240
|
-
prefs.remember(key, value)
|
|
241
|
-
|
|
242
|
-
{
|
|
243
|
-
success: true,
|
|
244
|
-
key: key,
|
|
245
|
-
old_value: old_value,
|
|
246
|
-
new_value: value
|
|
247
|
-
}
|
|
248
|
-
end
|
|
310
|
+
# Subscribe to a key
|
|
311
|
+
memory.subscribe(:raw_data) do |change|
|
|
312
|
+
enriched = enrich(change.value)
|
|
313
|
+
memory.set(:enriched, enriched)
|
|
249
314
|
end
|
|
250
|
-
```
|
|
251
|
-
|
|
252
|
-
### Search and Iteration
|
|
253
315
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
# => { "user:123:name" => "Alice", "user:123:email" => "..." }
|
|
258
|
-
|
|
259
|
-
# Process all keys
|
|
260
|
-
state.memory.all.each do |key, value|
|
|
261
|
-
puts "#{key}: #{value}"
|
|
316
|
+
# Subscribe with pattern
|
|
317
|
+
memory.subscribe_pattern("user:*") do |change|
|
|
318
|
+
puts "User key #{change.key} updated by #{change.writer}"
|
|
262
319
|
end
|
|
263
320
|
```
|
|
264
321
|
|
|
265
|
-
###
|
|
322
|
+
### Cross-Robot Communication via Network Memory
|
|
266
323
|
|
|
267
324
|
```ruby
|
|
268
|
-
#
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
# Clear specific namespace
|
|
272
|
-
state.memory.scoped("cache").clear
|
|
325
|
+
# In classifier robot
|
|
326
|
+
network.memory.set(:intent, "billing")
|
|
327
|
+
network.memory.set(:entities, ["order", "refund"])
|
|
273
328
|
|
|
274
|
-
#
|
|
275
|
-
|
|
329
|
+
# In handler robot
|
|
330
|
+
intent = network.memory.get(:intent)
|
|
331
|
+
entities = network.memory.get(:entities)
|
|
276
332
|
```
|
|
277
333
|
|
|
278
|
-
###
|
|
334
|
+
### Data Proxy
|
|
279
335
|
|
|
280
336
|
```ruby
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
return cached if cached
|
|
285
|
-
|
|
286
|
-
result = block.call
|
|
287
|
-
cache.remember(key, result)
|
|
288
|
-
result
|
|
289
|
-
end
|
|
337
|
+
memory = RobotLab.create_memory(
|
|
338
|
+
data: { user: { name: "Alice", plan: "pro" } }
|
|
339
|
+
)
|
|
290
340
|
|
|
291
|
-
#
|
|
292
|
-
data
|
|
293
|
-
ExpensiveService.fetch(id)
|
|
294
|
-
end
|
|
341
|
+
memory.data[:user][:name] # => "Alice"
|
|
342
|
+
memory.data.to_h # => { user: { name: "Alice", plan: "pro" } }
|
|
295
343
|
```
|
|
296
344
|
|
|
297
|
-
###
|
|
345
|
+
### Serialization
|
|
298
346
|
|
|
299
347
|
```ruby
|
|
300
|
-
#
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
state.memory.remember("findings", findings)
|
|
348
|
+
# Save memory
|
|
349
|
+
json = memory.to_json
|
|
350
|
+
File.write("memory.json", json)
|
|
304
351
|
|
|
305
|
-
#
|
|
306
|
-
|
|
307
|
-
|
|
352
|
+
# Restore memory
|
|
353
|
+
data = JSON.parse(File.read("memory.json"))
|
|
354
|
+
memory = Memory.from_hash(data)
|
|
308
355
|
```
|
|
309
356
|
|
|
310
357
|
## See Also
|
|
311
358
|
|
|
312
359
|
- [Memory Guide](../../guides/memory.md)
|
|
313
|
-
- [State](state.md)
|
|
314
360
|
- [State Management Architecture](../../architecture/state-management.md)
|
data/docs/api/core/network.md
CHANGED
|
@@ -5,7 +5,7 @@ Orchestrates multiple robots using SimpleFlow pipelines with DAG-based execution
|
|
|
5
5
|
## Class: `RobotLab::Network`
|
|
6
6
|
|
|
7
7
|
```ruby
|
|
8
|
-
network = RobotLab.create_network(name: "support") do
|
|
8
|
+
network = RobotLab.create_network(name: "support", config: config) do
|
|
9
9
|
task :classifier, classifier_robot, depends_on: :none
|
|
10
10
|
task :billing, billing_robot, depends_on: :optional
|
|
11
11
|
end
|
|
@@ -29,6 +29,14 @@ network.robots # => Hash<String, Robot>
|
|
|
29
29
|
|
|
30
30
|
Hash of robots keyed by name.
|
|
31
31
|
|
|
32
|
+
### config
|
|
33
|
+
|
|
34
|
+
```ruby
|
|
35
|
+
network.config # => RunConfig
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Shared operational defaults for all robots in the network. Passed to robots during `run()` so they can inherit network-wide LLM settings. See [RunConfig](../../getting-started/configuration.md#runconfig-shared-operational-defaults).
|
|
39
|
+
|
|
32
40
|
### pipeline
|
|
33
41
|
|
|
34
42
|
```ruby
|
|
@@ -64,7 +72,7 @@ Execute the network pipeline.
|
|
|
64
72
|
### task
|
|
65
73
|
|
|
66
74
|
```ruby
|
|
67
|
-
network.task(name, robot, context: {}, mcp: :none, tools: :none, memory: nil, depends_on: :none)
|
|
75
|
+
network.task(name, robot, context: {}, mcp: :none, tools: :none, memory: nil, config: nil, depends_on: :none)
|
|
68
76
|
# => self
|
|
69
77
|
```
|
|
70
78
|
|
|
@@ -80,6 +88,7 @@ Add a task to the pipeline with optional per-task configuration.
|
|
|
80
88
|
| `mcp` | `:none`, Array | MCP server config (`:none` or array of servers) |
|
|
81
89
|
| `tools` | `:none`, Array | Tools config (`:none` or array of tools) |
|
|
82
90
|
| `memory` | `Memory`, `nil` | Task-specific memory |
|
|
91
|
+
| `config` | `RunConfig`, `nil` | Per-task config (merged on top of network's RunConfig) |
|
|
83
92
|
| `depends_on` | `:none`, `Array<Symbol>`, `:optional` | Task dependencies |
|
|
84
93
|
|
|
85
94
|
**Dependency Types:**
|
|
@@ -153,7 +162,8 @@ Hash representation of network configuration.
|
|
|
153
162
|
name: "support",
|
|
154
163
|
robots: ["classifier", "billing", "technical"],
|
|
155
164
|
tasks: ["classifier", "billing", "technical"],
|
|
156
|
-
optional_tasks: [:billing, :technical]
|
|
165
|
+
optional_tasks: [:billing, :technical],
|
|
166
|
+
config: { model: "claude-sonnet-4", temperature: 0.7 } # if set
|
|
157
167
|
}
|
|
158
168
|
```
|
|
159
169
|
|