robot_lab 0.0.1

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 (153) hide show
  1. checksums.yaml +7 -0
  2. data/.envrc +1 -0
  3. data/.github/workflows/deploy-github-pages.yml +52 -0
  4. data/.github/workflows/deploy-yard-docs.yml +52 -0
  5. data/CHANGELOG.md +55 -0
  6. data/COMMITS.md +196 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +332 -0
  9. data/Rakefile +67 -0
  10. data/docs/api/adapters/anthropic.md +121 -0
  11. data/docs/api/adapters/gemini.md +133 -0
  12. data/docs/api/adapters/index.md +104 -0
  13. data/docs/api/adapters/openai.md +134 -0
  14. data/docs/api/core/index.md +113 -0
  15. data/docs/api/core/memory.md +314 -0
  16. data/docs/api/core/network.md +291 -0
  17. data/docs/api/core/robot.md +273 -0
  18. data/docs/api/core/state.md +273 -0
  19. data/docs/api/core/tool.md +353 -0
  20. data/docs/api/history/active-record-adapter.md +195 -0
  21. data/docs/api/history/config.md +191 -0
  22. data/docs/api/history/index.md +132 -0
  23. data/docs/api/history/thread-manager.md +144 -0
  24. data/docs/api/index.md +82 -0
  25. data/docs/api/mcp/client.md +221 -0
  26. data/docs/api/mcp/index.md +111 -0
  27. data/docs/api/mcp/server.md +225 -0
  28. data/docs/api/mcp/transports.md +264 -0
  29. data/docs/api/messages/index.md +67 -0
  30. data/docs/api/messages/text-message.md +102 -0
  31. data/docs/api/messages/tool-call-message.md +144 -0
  32. data/docs/api/messages/tool-result-message.md +154 -0
  33. data/docs/api/messages/user-message.md +171 -0
  34. data/docs/api/streaming/context.md +174 -0
  35. data/docs/api/streaming/events.md +237 -0
  36. data/docs/api/streaming/index.md +108 -0
  37. data/docs/architecture/core-concepts.md +243 -0
  38. data/docs/architecture/index.md +138 -0
  39. data/docs/architecture/message-flow.md +320 -0
  40. data/docs/architecture/network-orchestration.md +216 -0
  41. data/docs/architecture/robot-execution.md +243 -0
  42. data/docs/architecture/state-management.md +323 -0
  43. data/docs/assets/css/custom.css +56 -0
  44. data/docs/assets/images/robot_lab.jpg +0 -0
  45. data/docs/concepts.md +216 -0
  46. data/docs/examples/basic-chat.md +193 -0
  47. data/docs/examples/index.md +129 -0
  48. data/docs/examples/mcp-server.md +290 -0
  49. data/docs/examples/multi-robot-network.md +312 -0
  50. data/docs/examples/rails-application.md +420 -0
  51. data/docs/examples/tool-usage.md +310 -0
  52. data/docs/getting-started/configuration.md +230 -0
  53. data/docs/getting-started/index.md +56 -0
  54. data/docs/getting-started/installation.md +179 -0
  55. data/docs/getting-started/quick-start.md +203 -0
  56. data/docs/guides/building-robots.md +376 -0
  57. data/docs/guides/creating-networks.md +366 -0
  58. data/docs/guides/history.md +359 -0
  59. data/docs/guides/index.md +68 -0
  60. data/docs/guides/mcp-integration.md +356 -0
  61. data/docs/guides/memory.md +309 -0
  62. data/docs/guides/rails-integration.md +432 -0
  63. data/docs/guides/streaming.md +314 -0
  64. data/docs/guides/using-tools.md +394 -0
  65. data/docs/index.md +160 -0
  66. data/examples/01_simple_robot.rb +38 -0
  67. data/examples/02_tools.rb +106 -0
  68. data/examples/03_network.rb +103 -0
  69. data/examples/04_mcp.rb +219 -0
  70. data/examples/05_streaming.rb +124 -0
  71. data/examples/06_prompt_templates.rb +324 -0
  72. data/examples/07_network_memory.rb +329 -0
  73. data/examples/prompts/assistant/system.txt.erb +2 -0
  74. data/examples/prompts/assistant/user.txt.erb +1 -0
  75. data/examples/prompts/billing/system.txt.erb +7 -0
  76. data/examples/prompts/billing/user.txt.erb +1 -0
  77. data/examples/prompts/classifier/system.txt.erb +4 -0
  78. data/examples/prompts/classifier/user.txt.erb +1 -0
  79. data/examples/prompts/entity_extractor/system.txt.erb +11 -0
  80. data/examples/prompts/entity_extractor/user.txt.erb +3 -0
  81. data/examples/prompts/escalation/system.txt.erb +35 -0
  82. data/examples/prompts/escalation/user.txt.erb +34 -0
  83. data/examples/prompts/general/system.txt.erb +4 -0
  84. data/examples/prompts/general/user.txt.erb +1 -0
  85. data/examples/prompts/github_assistant/system.txt.erb +6 -0
  86. data/examples/prompts/github_assistant/user.txt.erb +1 -0
  87. data/examples/prompts/helper/system.txt.erb +1 -0
  88. data/examples/prompts/helper/user.txt.erb +1 -0
  89. data/examples/prompts/keyword_extractor/system.txt.erb +8 -0
  90. data/examples/prompts/keyword_extractor/user.txt.erb +3 -0
  91. data/examples/prompts/order_support/system.txt.erb +27 -0
  92. data/examples/prompts/order_support/user.txt.erb +22 -0
  93. data/examples/prompts/product_support/system.txt.erb +30 -0
  94. data/examples/prompts/product_support/user.txt.erb +32 -0
  95. data/examples/prompts/sentiment_analyzer/system.txt.erb +9 -0
  96. data/examples/prompts/sentiment_analyzer/user.txt.erb +3 -0
  97. data/examples/prompts/synthesizer/system.txt.erb +14 -0
  98. data/examples/prompts/synthesizer/user.txt.erb +15 -0
  99. data/examples/prompts/technical/system.txt.erb +7 -0
  100. data/examples/prompts/technical/user.txt.erb +1 -0
  101. data/examples/prompts/triage/system.txt.erb +16 -0
  102. data/examples/prompts/triage/user.txt.erb +17 -0
  103. data/lib/generators/robot_lab/install_generator.rb +78 -0
  104. data/lib/generators/robot_lab/robot_generator.rb +55 -0
  105. data/lib/generators/robot_lab/templates/initializer.rb.tt +41 -0
  106. data/lib/generators/robot_lab/templates/migration.rb.tt +32 -0
  107. data/lib/generators/robot_lab/templates/result_model.rb.tt +52 -0
  108. data/lib/generators/robot_lab/templates/robot.rb.tt +46 -0
  109. data/lib/generators/robot_lab/templates/robot_test.rb.tt +32 -0
  110. data/lib/generators/robot_lab/templates/routing_robot.rb.tt +53 -0
  111. data/lib/generators/robot_lab/templates/thread_model.rb.tt +40 -0
  112. data/lib/robot_lab/adapters/anthropic.rb +163 -0
  113. data/lib/robot_lab/adapters/base.rb +85 -0
  114. data/lib/robot_lab/adapters/gemini.rb +193 -0
  115. data/lib/robot_lab/adapters/openai.rb +159 -0
  116. data/lib/robot_lab/adapters/registry.rb +81 -0
  117. data/lib/robot_lab/configuration.rb +143 -0
  118. data/lib/robot_lab/error.rb +32 -0
  119. data/lib/robot_lab/errors.rb +70 -0
  120. data/lib/robot_lab/history/active_record_adapter.rb +146 -0
  121. data/lib/robot_lab/history/config.rb +115 -0
  122. data/lib/robot_lab/history/thread_manager.rb +93 -0
  123. data/lib/robot_lab/mcp/client.rb +210 -0
  124. data/lib/robot_lab/mcp/server.rb +84 -0
  125. data/lib/robot_lab/mcp/transports/base.rb +56 -0
  126. data/lib/robot_lab/mcp/transports/sse.rb +117 -0
  127. data/lib/robot_lab/mcp/transports/stdio.rb +133 -0
  128. data/lib/robot_lab/mcp/transports/streamable_http.rb +139 -0
  129. data/lib/robot_lab/mcp/transports/websocket.rb +108 -0
  130. data/lib/robot_lab/memory.rb +882 -0
  131. data/lib/robot_lab/memory_change.rb +123 -0
  132. data/lib/robot_lab/message.rb +357 -0
  133. data/lib/robot_lab/network.rb +350 -0
  134. data/lib/robot_lab/rails/engine.rb +29 -0
  135. data/lib/robot_lab/rails/railtie.rb +42 -0
  136. data/lib/robot_lab/robot.rb +560 -0
  137. data/lib/robot_lab/robot_result.rb +205 -0
  138. data/lib/robot_lab/robotic_model.rb +324 -0
  139. data/lib/robot_lab/state_proxy.rb +188 -0
  140. data/lib/robot_lab/streaming/context.rb +144 -0
  141. data/lib/robot_lab/streaming/events.rb +95 -0
  142. data/lib/robot_lab/streaming/sequence_counter.rb +48 -0
  143. data/lib/robot_lab/task.rb +117 -0
  144. data/lib/robot_lab/tool.rb +223 -0
  145. data/lib/robot_lab/tool_config.rb +112 -0
  146. data/lib/robot_lab/tool_manifest.rb +234 -0
  147. data/lib/robot_lab/user_message.rb +118 -0
  148. data/lib/robot_lab/version.rb +5 -0
  149. data/lib/robot_lab/waiter.rb +73 -0
  150. data/lib/robot_lab.rb +195 -0
  151. data/mkdocs.yml +214 -0
  152. data/sig/robot_lab.rbs +4 -0
  153. metadata +442 -0
@@ -0,0 +1,104 @@
1
+ # Adapters
2
+
3
+ LLM provider adapters for unified API access.
4
+
5
+ ## Overview
6
+
7
+ Adapters provide a consistent interface to different LLM providers, handling the translation between RobotLab's message format and provider-specific APIs.
8
+
9
+ ```ruby
10
+ # Configure globally
11
+ RobotLab.configure do |config|
12
+ config.default_model = "claude-sonnet-4"
13
+ # Adapter is selected automatically based on model
14
+ end
15
+
16
+ # Or configure per-robot
17
+ robot = RobotLab.build do
18
+ model "gpt-4o" # Uses OpenAI adapter
19
+ end
20
+ ```
21
+
22
+ ## Adapter Selection
23
+
24
+ Adapters are automatically selected based on model name:
25
+
26
+ | Model Pattern | Adapter |
27
+ |---------------|---------|
28
+ | `claude-*`, `anthropic/*` | Anthropic |
29
+ | `gpt-*`, `o1-*`, `openai/*` | OpenAI |
30
+ | `gemini-*`, `google/*` | Gemini |
31
+
32
+ ## Common Interface
33
+
34
+ All adapters implement:
35
+
36
+ ```ruby
37
+ adapter.chat(
38
+ messages: messages,
39
+ model: model,
40
+ tools: tools,
41
+ system: system_prompt,
42
+ streaming: callback
43
+ )
44
+ # => Response with content and usage
45
+ ```
46
+
47
+ ## Available Adapters
48
+
49
+ | Adapter | Description |
50
+ |---------|-------------|
51
+ | [Anthropic](anthropic.md) | Claude models via Anthropic API |
52
+ | [OpenAI](openai.md) | GPT models via OpenAI API |
53
+ | [Gemini](gemini.md) | Gemini models via Google AI |
54
+
55
+ ## Configuration
56
+
57
+ ### API Keys
58
+
59
+ Set via environment variables:
60
+
61
+ ```bash
62
+ export ANTHROPIC_API_KEY="sk-ant-..."
63
+ export OPENAI_API_KEY="sk-..."
64
+ export GOOGLE_AI_API_KEY="..."
65
+ ```
66
+
67
+ ### Custom Endpoints
68
+
69
+ ```ruby
70
+ RobotLab.configure do |config|
71
+ config.adapter_options = {
72
+ anthropic: { base_url: "https://custom.anthropic.endpoint" },
73
+ openai: { base_url: "https://custom.openai.endpoint" }
74
+ }
75
+ end
76
+ ```
77
+
78
+ ## Creating Custom Adapters
79
+
80
+ Implement the adapter interface:
81
+
82
+ ```ruby
83
+ class MyAdapter
84
+ def chat(messages:, model:, tools: [], system: nil, streaming: nil)
85
+ # Translate messages to provider format
86
+ # Make API call
87
+ # Translate response back
88
+
89
+ Response.new(
90
+ content: content,
91
+ tool_calls: tool_calls,
92
+ usage: { input_tokens: x, output_tokens: y }
93
+ )
94
+ end
95
+ end
96
+
97
+ # Register the adapter
98
+ RobotLab.register_adapter(:my_provider, MyAdapter)
99
+ ```
100
+
101
+ ## See Also
102
+
103
+ - [Configuration Guide](../../getting-started/configuration.md)
104
+ - [Streaming Guide](../../guides/streaming.md)
@@ -0,0 +1,134 @@
1
+ # OpenAI Adapter
2
+
3
+ Adapter for GPT models via OpenAI API.
4
+
5
+ ## Class: `RobotLab::Adapters::OpenAI`
6
+
7
+ ```ruby
8
+ # Automatically used for GPT models
9
+ robot = RobotLab.build do
10
+ model "gpt-4o"
11
+ end
12
+ ```
13
+
14
+ ## Supported Models
15
+
16
+ | Model | Description |
17
+ |-------|-------------|
18
+ | `gpt-4o` | Latest GPT-4 Omni |
19
+ | `gpt-4o-mini` | Fast, efficient GPT-4 |
20
+ | `gpt-4-turbo` | GPT-4 Turbo |
21
+ | `o1-preview` | Reasoning model |
22
+ | `o1-mini` | Fast reasoning model |
23
+
24
+ ## Configuration
25
+
26
+ ### API Key
27
+
28
+ ```bash
29
+ export OPENAI_API_KEY="sk-..."
30
+ ```
31
+
32
+ ### Options
33
+
34
+ ```ruby
35
+ RobotLab.configure do |config|
36
+ config.adapter_options = {
37
+ openai: {
38
+ base_url: "https://api.openai.com/v1",
39
+ organization: "org-...",
40
+ timeout: 120,
41
+ max_tokens: 4096
42
+ }
43
+ }
44
+ end
45
+ ```
46
+
47
+ ### Azure OpenAI
48
+
49
+ ```ruby
50
+ RobotLab.configure do |config|
51
+ config.adapter_options = {
52
+ openai: {
53
+ base_url: "https://your-resource.openai.azure.com",
54
+ api_key: ENV["AZURE_OPENAI_KEY"],
55
+ api_version: "2024-02-15-preview"
56
+ }
57
+ }
58
+ end
59
+ ```
60
+
61
+ ## Features
62
+
63
+ ### Streaming
64
+
65
+ ```ruby
66
+ result = robot.run(state: state) do |event|
67
+ case event
68
+ when :text_delta
69
+ print event.text
70
+ when :tool_call
71
+ puts "Calling: #{event.name}"
72
+ end
73
+ end
74
+ ```
75
+
76
+ ### Tool Use
77
+
78
+ Tools are automatically converted to OpenAI's function calling format:
79
+
80
+ ```ruby
81
+ robot = RobotLab.build do
82
+ model "gpt-4o"
83
+
84
+ tool :get_weather do
85
+ description "Get current weather"
86
+ parameter :location, type: :string, required: true
87
+ handler { |location:, **_| WeatherAPI.fetch(location) }
88
+ end
89
+ end
90
+ ```
91
+
92
+ ### JSON Mode
93
+
94
+ ```ruby
95
+ robot = RobotLab.build do
96
+ model "gpt-4o"
97
+ template "Always respond with valid JSON."
98
+ # Response format is automatically configured
99
+ end
100
+ ```
101
+
102
+ ## Response Format
103
+
104
+ ```ruby
105
+ {
106
+ content: [TextMessage, ...],
107
+ tool_calls: [ToolCallMessage, ...],
108
+ usage: {
109
+ input_tokens: 150,
110
+ output_tokens: 250,
111
+ total_tokens: 400
112
+ },
113
+ stop_reason: "stop"
114
+ }
115
+ ```
116
+
117
+ ## Error Handling
118
+
119
+ ```ruby
120
+ begin
121
+ result = robot.run(state: state)
122
+ rescue RobotLab::Adapters::RateLimitError => e
123
+ sleep(e.retry_after || 60)
124
+ retry
125
+ rescue RobotLab::Adapters::APIError => e
126
+ logger.error("OpenAI API error: #{e.message}")
127
+ end
128
+ ```
129
+
130
+ ## See Also
131
+
132
+ - [Adapters Overview](index.md)
133
+ - [Streaming Guide](../../guides/streaming.md)
134
+ - [OpenAI API Documentation](https://platform.openai.com/docs/)
@@ -0,0 +1,113 @@
1
+ # Core Classes
2
+
3
+ The fundamental classes that power RobotLab.
4
+
5
+ ## Overview
6
+
7
+ ```mermaid
8
+ classDiagram
9
+ class Robot {
10
+ +name: String
11
+ +description: String
12
+ +model: String
13
+ +template: String
14
+ +tools: Array~Tool~
15
+ +run(state, network)
16
+ }
17
+
18
+ class Network {
19
+ +name: String
20
+ +robots: Hash
21
+ +router: Proc
22
+ +run(state)
23
+ }
24
+
25
+ class State {
26
+ +data: StateProxy
27
+ +results: Array
28
+ +messages: Array
29
+ +memory: Memory
30
+ }
31
+
32
+ class Tool {
33
+ +name: String
34
+ +description: String
35
+ +parameters: Hash
36
+ +handler: Proc
37
+ }
38
+
39
+ class Memory {
40
+ +remember(key, value)
41
+ +recall(key)
42
+ +forget(key)
43
+ +scoped(namespace)
44
+ }
45
+
46
+ Network --> Robot : contains
47
+ Robot --> Tool : has
48
+ State --> Memory : has
49
+ Network --> State : uses
50
+ ```
51
+
52
+ ## Classes
53
+
54
+ | Class | Purpose |
55
+ |-------|---------|
56
+ | [Robot](robot.md) | LLM agent with personality, tools, and model configuration |
57
+ | [Network](network.md) | Container for robots with routing and orchestration |
58
+ | [State](state.md) | Conversation state with data, results, and memory |
59
+ | [Tool](tool.md) | Callable function with parameters and handler |
60
+ | [Memory](memory.md) | Namespaced key-value store for sharing data |
61
+
62
+ ## Quick Examples
63
+
64
+ ### Robot
65
+
66
+ ```ruby
67
+ robot = RobotLab.build do
68
+ name "assistant"
69
+ model "claude-sonnet-4"
70
+ template "You are helpful."
71
+
72
+ tool :greet do
73
+ parameter :name, type: :string
74
+ handler { |name:, **_| "Hello, #{name}!" }
75
+ end
76
+ end
77
+ ```
78
+
79
+ ### Network
80
+
81
+ ```ruby
82
+ network = RobotLab.create_network do
83
+ name "my_network"
84
+ add_robot robot
85
+ router ->(args) { args.call_count.zero? ? :assistant : nil }
86
+ end
87
+ ```
88
+
89
+ ### State
90
+
91
+ ```ruby
92
+ state = RobotLab.create_state(
93
+ message: "Hello",
94
+ data: { user_id: "123" }
95
+ )
96
+ ```
97
+
98
+ ### Tool
99
+
100
+ ```ruby
101
+ tool = RobotLab::Tool.new(
102
+ name: "get_time",
103
+ description: "Get current time",
104
+ handler: ->(**, _) { Time.now.to_s }
105
+ )
106
+ ```
107
+
108
+ ### Memory
109
+
110
+ ```ruby
111
+ state.memory.remember("key", "value")
112
+ value = state.memory.recall("key")
113
+ ```
@@ -0,0 +1,314 @@
1
+ # Memory
2
+
3
+ Namespaced key-value store for sharing data between robots.
4
+
5
+ ## Class: `RobotLab::Memory`
6
+
7
+ ```ruby
8
+ memory = state.memory
9
+
10
+ memory.remember("key", "value")
11
+ value = memory.recall("key")
12
+ ```
13
+
14
+ ## Constants
15
+
16
+ ### SHARED_NAMESPACE
17
+
18
+ ```ruby
19
+ Memory::SHARED_NAMESPACE # => "SHARED"
20
+ ```
21
+
22
+ Conventional namespace for cross-robot data.
23
+
24
+ ## Constructor
25
+
26
+ ```ruby
27
+ memory = Memory.new(initial_data = {})
28
+ ```
29
+
30
+ ## Methods
31
+
32
+ ### remember
33
+
34
+ ```ruby
35
+ memory.remember(key, value)
36
+ ```
37
+
38
+ Store a value.
39
+
40
+ **Parameters:**
41
+
42
+ | Name | Type | Description |
43
+ |------|------|-------------|
44
+ | `key` | `String`, `Symbol` | Storage key |
45
+ | `value` | `Object` | Value to store |
46
+
47
+ ### recall
48
+
49
+ ```ruby
50
+ memory.recall(key) # => Object | nil
51
+ ```
52
+
53
+ Retrieve a value.
54
+
55
+ **Parameters:**
56
+
57
+ | Name | Type | Description |
58
+ |------|------|-------------|
59
+ | `key` | `String`, `Symbol` | Storage key |
60
+
61
+ **Returns:** Stored value or `nil`.
62
+
63
+ ### exists?
64
+
65
+ ```ruby
66
+ memory.exists?(key) # => Boolean
67
+ ```
68
+
69
+ Check if key exists.
70
+
71
+ ### forget
72
+
73
+ ```ruby
74
+ memory.forget(key) # => Object | nil
75
+ ```
76
+
77
+ Remove a key, returns the value.
78
+
79
+ ### all
80
+
81
+ ```ruby
82
+ memory.all # => Hash
83
+ ```
84
+
85
+ Get all stored data.
86
+
87
+ ### namespaces
88
+
89
+ ```ruby
90
+ memory.namespaces # => Array<String>
91
+ ```
92
+
93
+ List all namespaces.
94
+
95
+ ### clear
96
+
97
+ ```ruby
98
+ memory.clear
99
+ ```
100
+
101
+ Clear all data in current scope.
102
+
103
+ ### clear_all
104
+
105
+ ```ruby
106
+ memory.clear_all
107
+ ```
108
+
109
+ Clear all data globally.
110
+
111
+ ### search
112
+
113
+ ```ruby
114
+ memory.search(pattern) # => Hash
115
+ ```
116
+
117
+ Find keys matching pattern.
118
+
119
+ **Parameters:**
120
+
121
+ | Name | Type | Description |
122
+ |------|------|-------------|
123
+ | `pattern` | `String` | Glob pattern (e.g., "user:*") |
124
+
125
+ ### stats
126
+
127
+ ```ruby
128
+ memory.stats # => Hash
129
+ ```
130
+
131
+ Get memory statistics.
132
+
133
+ **Returns:**
134
+
135
+ ```ruby
136
+ {
137
+ total_keys: 15,
138
+ namespaces: ["user", "session"]
139
+ }
140
+ ```
141
+
142
+ ### scoped
143
+
144
+ ```ruby
145
+ scoped_memory = memory.scoped(namespace) # => ScopedMemory
146
+ ```
147
+
148
+ Create a scoped view.
149
+
150
+ ## ScopedMemory
151
+
152
+ Scoped view with automatic key prefixing.
153
+
154
+ ### Methods
155
+
156
+ All Memory methods are available:
157
+
158
+ ```ruby
159
+ scoped = memory.scoped("user:123")
160
+
161
+ scoped.remember("name", "Alice") # Key: "user:123:name"
162
+ scoped.recall("name") # => "Alice"
163
+ scoped.exists?("name") # => true
164
+ scoped.forget("name")
165
+ scoped.all # Only "user:123:*" keys
166
+ scoped.clear # Clear only this scope
167
+ ```
168
+
169
+ ### Nested Scopes
170
+
171
+ ```ruby
172
+ user = memory.scoped("user:123")
173
+ prefs = user.scoped("preferences")
174
+
175
+ prefs.remember("theme", "dark")
176
+ # Full key: "user:123:preferences:theme"
177
+ ```
178
+
179
+ ## Examples
180
+
181
+ ### Basic Usage
182
+
183
+ ```ruby
184
+ state.memory.remember("user_name", "Alice")
185
+ state.memory.remember("order_count", 5)
186
+
187
+ name = state.memory.recall("user_name") # => "Alice"
188
+ count = state.memory.recall("order_count") # => 5
189
+ ```
190
+
191
+ ### Storing Objects
192
+
193
+ ```ruby
194
+ state.memory.remember("user", {
195
+ id: 123,
196
+ name: "Alice",
197
+ plan: "pro"
198
+ })
199
+
200
+ user = state.memory.recall("user")
201
+ user[:plan] # => "pro"
202
+ ```
203
+
204
+ ### Scoped Organization
205
+
206
+ ```ruby
207
+ # User-specific data
208
+ user = state.memory.scoped("user:#{user_id}")
209
+ user.remember("last_login", Time.now)
210
+ user.remember("preferences", { theme: "dark" })
211
+
212
+ # Session-specific data
213
+ session = state.memory.scoped("session:#{session_id}")
214
+ session.remember("page_views", 0)
215
+
216
+ # Temporary working data
217
+ temp = state.memory.scoped("temp")
218
+ temp.remember("intermediate_result", calculation)
219
+ ```
220
+
221
+ ### Cross-Robot Communication
222
+
223
+ ```ruby
224
+ # In classifier robot
225
+ state.memory.remember("SHARED:intent", "billing")
226
+ state.memory.remember("SHARED:entities", ["order", "refund"])
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
249
+ end
250
+ ```
251
+
252
+ ### Search and Iteration
253
+
254
+ ```ruby
255
+ # Find all user keys
256
+ user_data = state.memory.search("user:*")
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}"
262
+ end
263
+ ```
264
+
265
+ ### Cleanup
266
+
267
+ ```ruby
268
+ # Clear temporary data
269
+ state.memory.scoped("temp").clear
270
+
271
+ # Clear specific namespace
272
+ state.memory.scoped("cache").clear
273
+
274
+ # Clear everything
275
+ state.memory.clear_all
276
+ ```
277
+
278
+ ### Caching Pattern
279
+
280
+ ```ruby
281
+ def cached_fetch(state, key, &block)
282
+ cache = state.memory.scoped("cache")
283
+ cached = cache.recall(key)
284
+ return cached if cached
285
+
286
+ result = block.call
287
+ cache.remember(key, result)
288
+ result
289
+ end
290
+
291
+ # Usage
292
+ data = cached_fetch(state, "expensive:#{id}") do
293
+ ExpensiveService.fetch(id)
294
+ end
295
+ ```
296
+
297
+ ### Accumulating Results
298
+
299
+ ```ruby
300
+ # In each robot, accumulate findings
301
+ findings = state.memory.recall("findings") || []
302
+ findings << { robot: robot.name, finding: new_finding }
303
+ state.memory.remember("findings", findings)
304
+
305
+ # In final robot, aggregate
306
+ all_findings = state.memory.recall("findings")
307
+ summary = all_findings.group_by { |f| f[:robot] }
308
+ ```
309
+
310
+ ## See Also
311
+
312
+ - [Memory Guide](../../guides/memory.md)
313
+ - [State](state.md)
314
+ - [State Management Architecture](../../architecture/state-management.md)