robot_lab 0.3.0 → 0.3.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 (256) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +12 -0
  3. data/README.md +1 -1
  4. data/lib/robot_lab/mcp/transports/streamable_http.rb +1 -1
  5. data/lib/robot_lab/version.rb +1 -1
  6. metadata +3 -253
  7. data/.architecture/AGENTS.md +0 -32
  8. data/.architecture/config.yml +0 -8
  9. data/.architecture/members.yml +0 -60
  10. data/.architecture/reviews/feature-free-will.md +0 -490
  11. data/.architecture/reviews/overall-codebase.md +0 -427
  12. data/.claude/settings.local.json +0 -57
  13. data/.codex/config.toml +0 -2
  14. data/.envrc +0 -6
  15. data/.github/workflows/deploy-github-pages.yml +0 -52
  16. data/.irbrc +0 -6
  17. data/.loki +0 -65
  18. data/.quality/reek_baseline.txt +0 -43
  19. data/.rubocop.yml +0 -10
  20. data/Archspec.rb +0 -44
  21. data/CLAUDE.md +0 -141
  22. data/COMMITS.md +0 -196
  23. data/Rakefile +0 -193
  24. data/_typos.toml +0 -21
  25. data/agent2agent_review.md +0 -192
  26. data/agentf_improvements.md +0 -253
  27. data/agents.md +0 -14
  28. data/docs/api/core/index.md +0 -147
  29. data/docs/api/core/memory.md +0 -578
  30. data/docs/api/core/network.md +0 -553
  31. data/docs/api/core/result.md +0 -211
  32. data/docs/api/core/robot.md +0 -1667
  33. data/docs/api/core/state.md +0 -145
  34. data/docs/api/core/tool.md +0 -520
  35. data/docs/api/errors.md +0 -323
  36. data/docs/api/hooks.md +0 -469
  37. data/docs/api/index.md +0 -137
  38. data/docs/api/mcp/client.md +0 -387
  39. data/docs/api/mcp/index.md +0 -267
  40. data/docs/api/mcp/server.md +0 -252
  41. data/docs/api/mcp/transports.md +0 -339
  42. data/docs/api/messages/index.md +0 -126
  43. data/docs/api/messages/text-message.md +0 -170
  44. data/docs/api/messages/tool-call-message.md +0 -206
  45. data/docs/api/messages/tool-result-message.md +0 -242
  46. data/docs/api/messages/user-message.md +0 -232
  47. data/docs/api/skills.md +0 -423
  48. data/docs/api/streaming/context.md +0 -280
  49. data/docs/api/streaming/events.md +0 -185
  50. data/docs/api/streaming/index.md +0 -156
  51. data/docs/api/support.md +0 -846
  52. data/docs/architecture/core-concepts.md +0 -575
  53. data/docs/architecture/index.md +0 -252
  54. data/docs/architecture/message-flow.md +0 -366
  55. data/docs/architecture/network-orchestration.md +0 -478
  56. data/docs/architecture/robot-execution.md +0 -396
  57. data/docs/architecture/state-management.md +0 -410
  58. data/docs/assets/css/custom.css +0 -56
  59. data/docs/assets/images/robot_lab.jpg +0 -0
  60. data/docs/concepts.md +0 -641
  61. data/docs/examples/basic-chat.md +0 -258
  62. data/docs/examples/index.md +0 -425
  63. data/docs/examples/mcp-server.md +0 -403
  64. data/docs/examples/multi-robot-network.md +0 -476
  65. data/docs/examples/tool-usage.md +0 -468
  66. data/docs/getting-started/configuration.md +0 -645
  67. data/docs/getting-started/index.md +0 -56
  68. data/docs/getting-started/installation.md +0 -197
  69. data/docs/getting-started/quick-start.md +0 -293
  70. data/docs/guides/building-robots.md +0 -1187
  71. data/docs/guides/creating-networks.md +0 -736
  72. data/docs/guides/hooks.md +0 -1206
  73. data/docs/guides/index.md +0 -78
  74. data/docs/guides/knowledge.md +0 -219
  75. data/docs/guides/mcp-integration.md +0 -740
  76. data/docs/guides/memory.md +0 -458
  77. data/docs/guides/observability.md +0 -733
  78. data/docs/guides/streaming.md +0 -323
  79. data/docs/guides/using-tools.md +0 -780
  80. data/docs/index.md +0 -280
  81. data/docs/superpowers/plans/2026-05-06-agentskills.md +0 -1303
  82. data/docs/superpowers/specs/2026-05-06-agentskills-design.md +0 -247
  83. data/examples/.envrc +0 -3
  84. data/examples/01_simple_robot.rb +0 -31
  85. data/examples/02_tools.rb +0 -109
  86. data/examples/03_network.rb +0 -118
  87. data/examples/04_mcp.rb +0 -217
  88. data/examples/05_streaming.rb +0 -137
  89. data/examples/06_prompt_templates.rb +0 -325
  90. data/examples/07_network_memory.rb +0 -313
  91. data/examples/08_llm_config.rb +0 -162
  92. data/examples/09_chaining.rb +0 -251
  93. data/examples/10_memory.rb +0 -315
  94. data/examples/11_network_introspection.rb +0 -239
  95. data/examples/12_message_bus.rb +0 -67
  96. data/examples/13_spawn.rb +0 -85
  97. data/examples/14_rusty_circuit/.envrc +0 -1
  98. data/examples/14_rusty_circuit/.gitignore +0 -1
  99. data/examples/14_rusty_circuit/README.md +0 -1
  100. data/examples/14_rusty_circuit/comic.rb +0 -149
  101. data/examples/14_rusty_circuit/display.rb +0 -217
  102. data/examples/14_rusty_circuit/heckler.rb +0 -65
  103. data/examples/14_rusty_circuit/open_mic.rb +0 -132
  104. data/examples/14_rusty_circuit/prompts/open_mic_comic.md +0 -20
  105. data/examples/14_rusty_circuit/prompts/open_mic_heckler.md +0 -23
  106. data/examples/14_rusty_circuit/prompts/open_mic_scout.md +0 -20
  107. data/examples/14_rusty_circuit/scout.rb +0 -165
  108. data/examples/14_rusty_circuit/show.log +0 -234
  109. data/examples/15_memory_network_and_bus/.envrc +0 -1
  110. data/examples/15_memory_network_and_bus/README.md +0 -66
  111. data/examples/15_memory_network_and_bus/editor_in_chief.rb +0 -24
  112. data/examples/15_memory_network_and_bus/editorial_pipeline.rb +0 -213
  113. data/examples/15_memory_network_and_bus/linux_writer.rb +0 -80
  114. data/examples/15_memory_network_and_bus/os_editor.rb +0 -48
  115. data/examples/15_memory_network_and_bus/os_writer.rb +0 -49
  116. data/examples/15_memory_network_and_bus/output/combined_article.md +0 -11
  117. data/examples/15_memory_network_and_bus/output/final_article.md +0 -8
  118. data/examples/15_memory_network_and_bus/output/linux_draft.md +0 -7
  119. data/examples/15_memory_network_and_bus/output/mac_draft.md +0 -7
  120. data/examples/15_memory_network_and_bus/output/memory.json +0 -13
  121. data/examples/15_memory_network_and_bus/output/revision_1.md +0 -29
  122. data/examples/15_memory_network_and_bus/output/revision_2.md +0 -50
  123. data/examples/15_memory_network_and_bus/output/revision_3.md +0 -8
  124. data/examples/15_memory_network_and_bus/output/windows_draft.md +0 -7
  125. data/examples/15_memory_network_and_bus/prompts/os_advocate.md +0 -13
  126. data/examples/15_memory_network_and_bus/prompts/os_chief.md +0 -13
  127. data/examples/15_memory_network_and_bus/prompts/os_editor.md +0 -13
  128. data/examples/16_writers_room/.envrc +0 -1
  129. data/examples/16_writers_room/display.rb +0 -158
  130. data/examples/16_writers_room/output/.gitignore +0 -4
  131. data/examples/16_writers_room/output/README.md +0 -69
  132. data/examples/16_writers_room/output/opus_001.md +0 -263
  133. data/examples/16_writers_room/output/opus_001_notes.log +0 -470
  134. data/examples/16_writers_room/output/opus_002.md +0 -245
  135. data/examples/16_writers_room/output/opus_002_notes.log +0 -546
  136. data/examples/16_writers_room/output/opus_002_screenplay.md +0 -7989
  137. data/examples/16_writers_room/output/opus_002_screenplay_notes.md +0 -993
  138. data/examples/16_writers_room/prompts/screenplay_writer.md +0 -66
  139. data/examples/16_writers_room/prompts/writer.md +0 -37
  140. data/examples/16_writers_room/room.rb +0 -186
  141. data/examples/16_writers_room/tools.rb +0 -173
  142. data/examples/16_writers_room/writer.rb +0 -121
  143. data/examples/16_writers_room/writers_room.rb +0 -256
  144. data/examples/17_skills.rb +0 -234
  145. data/examples/18_rails/.envrc +0 -3
  146. data/examples/18_rails/.gitignore +0 -5
  147. data/examples/18_rails/Gemfile +0 -11
  148. data/examples/18_rails/README.md +0 -67
  149. data/examples/18_rails/Rakefile +0 -4
  150. data/examples/18_rails/app/controllers/application_controller.rb +0 -4
  151. data/examples/18_rails/app/controllers/chat_controller.rb +0 -50
  152. data/examples/18_rails/app/jobs/application_job.rb +0 -4
  153. data/examples/18_rails/app/jobs/robot_run_job.rb +0 -25
  154. data/examples/18_rails/app/models/application_record.rb +0 -5
  155. data/examples/18_rails/app/models/robot_lab_result.rb +0 -36
  156. data/examples/18_rails/app/models/robot_lab_thread.rb +0 -23
  157. data/examples/18_rails/app/robots/chat_robot.rb +0 -25
  158. data/examples/18_rails/app/tools/time_tool.rb +0 -9
  159. data/examples/18_rails/app/views/chat/_user_message.html.erb +0 -1
  160. data/examples/18_rails/app/views/chat/index.html.erb +0 -67
  161. data/examples/18_rails/app/views/layouts/application.html.erb +0 -49
  162. data/examples/18_rails/bin/dev +0 -7
  163. data/examples/18_rails/bin/rails +0 -6
  164. data/examples/18_rails/bin/setup +0 -15
  165. data/examples/18_rails/config/application.rb +0 -33
  166. data/examples/18_rails/config/cable.yml +0 -2
  167. data/examples/18_rails/config/database.yml +0 -5
  168. data/examples/18_rails/config/environment.rb +0 -4
  169. data/examples/18_rails/config/initializers/robot_lab.rb +0 -11
  170. data/examples/18_rails/config/routes.rb +0 -6
  171. data/examples/18_rails/config.ru +0 -4
  172. data/examples/18_rails/db/migrate/001_create_robot_lab_tables.rb +0 -32
  173. data/examples/19_token_tracking.rb +0 -138
  174. data/examples/20_circuit_breaker.rb +0 -147
  175. data/examples/21_learning_loop.rb +0 -181
  176. data/examples/22_context_compression.rb +0 -172
  177. data/examples/23_convergence.rb +0 -133
  178. data/examples/24_structured_delegation.rb +0 -151
  179. data/examples/25_history_search/conversation.jsonl +0 -30
  180. data/examples/25_history_search.rb +0 -133
  181. data/examples/26_document_store/api_versioning_adr.md +0 -52
  182. data/examples/26_document_store/incident_postmortem.md +0 -46
  183. data/examples/26_document_store/postgres_runbook.md +0 -49
  184. data/examples/26_document_store/redis_caching_guide.md +0 -48
  185. data/examples/26_document_store/sidekiq_guide.md +0 -51
  186. data/examples/26_document_store.rb +0 -140
  187. data/examples/27_incident_response/README.md +0 -65
  188. data/examples/27_incident_response/incident_response.rb +0 -261
  189. data/examples/28_mcp_discovery.rb +0 -113
  190. data/examples/29_ractor_tools.rb +0 -240
  191. data/examples/30_ractor_network.rb +0 -252
  192. data/examples/31_launch_assessment.rb +0 -246
  193. data/examples/32_newsletter_reader.rb +0 -193
  194. data/examples/33_stock_generator.rb +0 -80
  195. data/examples/33_stock_predictor.rb +0 -327
  196. data/examples/34_agentskills.rb +0 -76
  197. data/examples/35_hooks.rb +0 -266
  198. data/examples/README.md +0 -550
  199. data/examples/common.rb +0 -180
  200. data/examples/prompts/assistant.md +0 -5
  201. data/examples/prompts/audit_trail.md +0 -8
  202. data/examples/prompts/billing.md +0 -10
  203. data/examples/prompts/classifier.md +0 -7
  204. data/examples/prompts/comedian.md +0 -6
  205. data/examples/prompts/comedy_critic.md +0 -10
  206. data/examples/prompts/configurable.md +0 -9
  207. data/examples/prompts/dispatcher.md +0 -12
  208. data/examples/prompts/entity_extractor.md +0 -14
  209. data/examples/prompts/escalation.md +0 -42
  210. data/examples/prompts/frontmatter_mcp_test.md +0 -9
  211. data/examples/prompts/frontmatter_named_test.md +0 -5
  212. data/examples/prompts/frontmatter_tools_test.md +0 -6
  213. data/examples/prompts/general.md +0 -7
  214. data/examples/prompts/github_assistant.md +0 -14
  215. data/examples/prompts/helper.md +0 -4
  216. data/examples/prompts/incident_responder.md +0 -18
  217. data/examples/prompts/keyword_extractor.md +0 -11
  218. data/examples/prompts/llm_config_demo.md +0 -20
  219. data/examples/prompts/order_support.md +0 -35
  220. data/examples/prompts/os_advocate.md +0 -13
  221. data/examples/prompts/os_chief.md +0 -13
  222. data/examples/prompts/os_editor.md +0 -13
  223. data/examples/prompts/parameterized_main_test.md +0 -6
  224. data/examples/prompts/pii_redactor.md +0 -7
  225. data/examples/prompts/product_support.md +0 -37
  226. data/examples/prompts/runbook_protocol.md +0 -12
  227. data/examples/prompts/sentiment_analyzer.md +0 -12
  228. data/examples/prompts/skill_a_test.md +0 -4
  229. data/examples/prompts/skill_b_test.md +0 -4
  230. data/examples/prompts/skill_config_test.md +0 -5
  231. data/examples/prompts/skill_cycle_a_test.md +0 -6
  232. data/examples/prompts/skill_cycle_b_test.md +0 -6
  233. data/examples/prompts/skill_description_test.md +0 -4
  234. data/examples/prompts/skill_leaf_test.md +0 -4
  235. data/examples/prompts/skill_nested_test.md +0 -6
  236. data/examples/prompts/skill_refs_main_test.md +0 -6
  237. data/examples/prompts/skill_self_ref_test.md +0 -6
  238. data/examples/prompts/skill_with_mcp_test.md +0 -9
  239. data/examples/prompts/skill_with_params_test.md +0 -6
  240. data/examples/prompts/skill_with_robot_name_test.md +0 -5
  241. data/examples/prompts/skill_with_tools_test.md +0 -6
  242. data/examples/prompts/sre_compliance.md +0 -10
  243. data/examples/prompts/structured_output.md +0 -7
  244. data/examples/prompts/synthesizer.md +0 -17
  245. data/examples/prompts/technical.md +0 -10
  246. data/examples/prompts/template_with_skills_test.md +0 -6
  247. data/examples/prompts/triage.md +0 -22
  248. data/examples/ruboruby.md +0 -423
  249. data/examples/run_all.rb +0 -60
  250. data/examples/xyzzy.rb +0 -97
  251. data/logfile +0 -8
  252. data/mkdocs.yml +0 -209
  253. data/robot_concurrency.md +0 -38
  254. data/simple_acp_review.md +0 -298
  255. data/temp.md +0 -6
  256. data/tool_manifest_plan.md +0 -155
@@ -1,242 +0,0 @@
1
- # ToolResultMessage
2
-
3
- Result from tool execution.
4
-
5
- ## Class: `RobotLab::ToolResultMessage`
6
-
7
- ```ruby
8
- tool = ToolMessage.new(id: "call_abc123", name: "get_weather", input: { city: "NYC" })
9
-
10
- message = ToolResultMessage.new(
11
- tool: tool,
12
- content: { data: { temperature: 72, conditions: "sunny" } }
13
- )
14
- ```
15
-
16
- ## Constructor
17
-
18
- ```ruby
19
- ToolResultMessage.new(tool:, content:, stop_reason: nil)
20
- ```
21
-
22
- **Parameters:**
23
-
24
- | Name | Type | Description |
25
- |------|------|-------------|
26
- | `tool` | `ToolMessage`, `Hash` | The tool call that was executed; a Hash is normalized via `ToolMessage.from_hash` |
27
- | `content` | `Hash` | Result with `:data` key (success) or `:error` key (failure) |
28
- | `stop_reason` | `String`, `nil` | Stop reason (defaults to "tool") |
29
-
30
- `tool:` accepts a plain Hash as well as a `ToolMessage`; anything else raises
31
- `ArgumentError: Invalid tool: must be ToolMessage or Hash`. As with
32
- `ToolCallMessage`, `from_hash` symbolizes keys and accepts `input:` or
33
- `arguments:` for the parameter hash.
34
-
35
- ```ruby
36
- ToolResultMessage.new(
37
- tool: { id: "call_1", name: "get_weather", arguments: { city: "NYC" } },
38
- content: { data: { temperature: 72 } }
39
- ).tool.input
40
- # => { city: "NYC" }
41
- ```
42
-
43
- `role` is hard-coded to `"tool_result"` — the value you pass for `tool:` has no
44
- bearing on it.
45
-
46
- ## Attributes
47
-
48
- ### tool
49
-
50
- ```ruby
51
- message.tool # => ToolMessage
52
- ```
53
-
54
- The `ToolMessage` representing the tool call that produced this result. Provides access to `tool.id`, `tool.name`, and `tool.input`.
55
-
56
- ### content
57
-
58
- ```ruby
59
- message.content # => Hash
60
- ```
61
-
62
- The result content. Contains either a `:data` key (success) or an `:error` key (failure).
63
-
64
- ### role
65
-
66
- ```ruby
67
- message.role # => "tool_result"
68
- ```
69
-
70
- Always returns `"tool_result"`.
71
-
72
- ### type
73
-
74
- ```ruby
75
- message.type # => "tool_result"
76
- ```
77
-
78
- Always returns `"tool_result"`.
79
-
80
- ### stop_reason
81
-
82
- ```ruby
83
- message.stop_reason # => "tool"
84
- ```
85
-
86
- Defaults to `"tool"`.
87
-
88
- ## Methods
89
-
90
- ### success?
91
-
92
- ```ruby
93
- message.success? # => Boolean
94
- ```
95
-
96
- Returns `true` if `content` is a Hash containing the **symbol** key `:data`.
97
- `content` is stored verbatim — it is not symbolized — so a result built with
98
- `content: { "data" => ... }` reports `success? == false` and `data == nil`.
99
-
100
- ### error?
101
-
102
- ```ruby
103
- message.error? # => Boolean
104
- ```
105
-
106
- Returns `true` if `content` is a Hash containing the **symbol** key `:error`.
107
-
108
- ### data
109
-
110
- ```ruby
111
- message.data # => Object | nil
112
- ```
113
-
114
- Returns the result data if successful, `nil` otherwise.
115
-
116
- ### error
117
-
118
- ```ruby
119
- message.error # => String | nil
120
- ```
121
-
122
- Returns the error message if there was an error, `nil` otherwise.
123
-
124
- ### to_h
125
-
126
- ```ruby
127
- message.to_h # => Hash
128
- ```
129
-
130
- Hash representation. `ToolResultMessage` overrides `Message#to_h` and does
131
- **not** compact, so all five keys are always present.
132
-
133
- **Returns:**
134
-
135
- ```ruby
136
- {
137
- type: "tool_result",
138
- role: "tool_result",
139
- tool: { type: "tool", id: "call_abc123", name: "get_weather", input: { city: "NYC" } },
140
- content: { data: { temperature: 72, conditions: "sunny" } },
141
- stop_reason: "tool"
142
- }
143
- ```
144
-
145
- ### to_json
146
-
147
- ```ruby
148
- message.to_json # => String
149
- ```
150
-
151
- JSON representation.
152
-
153
- ### Predicates
154
-
155
- ```ruby
156
- message.tool_result? # => true
157
- message.tool_call? # => false
158
- message.text? # => false
159
- message.tool_stop? # => true
160
- ```
161
-
162
- ## Examples
163
-
164
- ### Successful Result
165
-
166
- ```ruby
167
- tool = ToolMessage.new(id: "call_1", name: "search_orders", input: { user_id: "123" })
168
-
169
- result = ToolResultMessage.new(
170
- tool: tool,
171
- content: { data: { order_id: "ord_123", status: "shipped" } }
172
- )
173
-
174
- result.success? # => true
175
- result.data # => { order_id: "ord_123", status: "shipped" }
176
- ```
177
-
178
- ### Error Result
179
-
180
- ```ruby
181
- tool = ToolMessage.new(id: "call_order", name: "get_order", input: { id: "bad" })
182
-
183
- result = ToolResultMessage.new(
184
- tool: tool,
185
- content: { error: "Order not found" }
186
- )
187
-
188
- result.error? # => true
189
- result.error # => "Order not found"
190
- result.data # => nil
191
- ```
192
-
193
- ### Accessing Tool Information
194
-
195
- ```ruby
196
- result = ToolResultMessage.new(
197
- tool: ToolMessage.new(id: "call_1", name: "get_weather", input: { city: "Berlin" }),
198
- content: { data: { temperature: 15, unit: "celsius" } }
199
- )
200
-
201
- result.tool.name # => "get_weather"
202
- result.tool.id # => "call_1"
203
- result.tool.input # => { city: "Berlin" }
204
- result.data # => { temperature: 15, unit: "celsius" }
205
- ```
206
-
207
- ### Matching Tool Calls with Results
208
-
209
- ```ruby
210
- # Given a ToolCallMessage and its results
211
- tool_call_msg.tools.each do |tool|
212
- # Find the matching result
213
- matching_result = results.find { |r| r.tool.id == tool.id }
214
-
215
- if matching_result&.success?
216
- puts "#{tool.name}(#{tool.input}) => #{matching_result.data}"
217
- elsif matching_result&.error?
218
- puts "#{tool.name} failed: #{matching_result.error}"
219
- end
220
- end
221
- ```
222
-
223
- ### In Memory History
224
-
225
- ```ruby
226
- # Find all tool results from memory
227
- tool_results = memory.messages.select(&:tool_result?)
228
-
229
- tool_results.each do |tr|
230
- if tr.success?
231
- puts "#{tr.tool.name}: #{tr.data}"
232
- else
233
- puts "#{tr.tool.name} error: #{tr.error}"
234
- end
235
- end
236
- ```
237
-
238
- ## See Also
239
-
240
- - [ToolCallMessage](tool-call-message.md)
241
- - [Tool](../core/tool.md)
242
- - [Using Tools Guide](../../guides/using-tools.md)
@@ -1,232 +0,0 @@
1
- # UserMessage
2
-
3
- User input with conversation metadata.
4
-
5
- ## Class: `RobotLab::UserMessage`
6
-
7
- ```ruby
8
- message = UserMessage.new(
9
- "What's my order status?",
10
- session_id: "session_123",
11
- system_prompt: "Be concise",
12
- metadata: { source: "web" }
13
- )
14
- ```
15
-
16
- **Note:** `UserMessage` is a standalone class, not a subclass of `Message`.
17
-
18
- ## Constructor
19
-
20
- ```ruby
21
- UserMessage.new(content, session_id: nil, system_prompt: nil, metadata: nil, id: nil)
22
- ```
23
-
24
- **Parameters:**
25
-
26
- | Name | Type | Description |
27
- |------|------|-------------|
28
- | `content` | `String` | Message text |
29
- | `session_id` | `String`, `nil` | Conversation session ID |
30
- | `system_prompt` | `String`, `nil` | Override system prompt |
31
- | `metadata` | `Hash`, `nil` | Additional metadata |
32
- | `id` | `String`, `nil` | Unique message ID (defaults to UUID) |
33
-
34
- ## Attributes
35
-
36
- ### content
37
-
38
- ```ruby
39
- message.content # => String
40
- ```
41
-
42
- The message text.
43
-
44
- ### session_id
45
-
46
- ```ruby
47
- message.session_id # => String | nil
48
- ```
49
-
50
- Conversation session identifier for history persistence.
51
-
52
- ### system_prompt
53
-
54
- ```ruby
55
- message.system_prompt # => String | nil
56
- ```
57
-
58
- Optional system prompt override for this message.
59
-
60
- ### metadata
61
-
62
- ```ruby
63
- message.metadata # => Hash
64
- ```
65
-
66
- Arbitrary metadata (source, timestamp, user info, etc.).
67
-
68
- ### id
69
-
70
- ```ruby
71
- message.id # => String (UUID)
72
- ```
73
-
74
- Unique message identifier.
75
-
76
- ### created_at
77
-
78
- ```ruby
79
- message.created_at # => Time
80
- ```
81
-
82
- Message creation timestamp.
83
-
84
- ## Methods
85
-
86
- ### to_h
87
-
88
- ```ruby
89
- message.to_h # => Hash
90
- ```
91
-
92
- Hash representation. The hash ends in `.compact`, so keys whose value is `nil`
93
- are **omitted** — a message built without `session_id:` or `system_prompt:` has
94
- no such keys at all. `metadata` always survives because it defaults to `{}`.
95
-
96
- `created_at` is serialized with `Time#iso8601`, which carries the **local** UTC
97
- offset. It is not normalized to `Z`/UTC.
98
-
99
- **Returns:**
100
-
101
- ```ruby
102
- UserMessage.new(
103
- "What's my order status?",
104
- session_id: "session_123",
105
- system_prompt: "Be concise",
106
- metadata: { source: "web" }
107
- ).to_h
108
- # => {
109
- # content: "What's my order status?",
110
- # session_id: "session_123",
111
- # system_prompt: "Be concise",
112
- # metadata: { source: "web" },
113
- # id: "uuid-here",
114
- # created_at: "2026-07-31T13:04:42-05:00"
115
- # }
116
-
117
- UserMessage.new("hi").to_h
118
- # => {
119
- # content: "hi",
120
- # metadata: {},
121
- # id: "uuid-here",
122
- # created_at: "2026-07-31T13:04:42-05:00"
123
- # }
124
- ```
125
-
126
- ### to_json
127
-
128
- ```ruby
129
- message.to_json # => String
130
- ```
131
-
132
- JSON representation.
133
-
134
- ### to_message
135
-
136
- ```ruby
137
- message.to_message # => TextMessage
138
- ```
139
-
140
- Converts to a `TextMessage` with role `"user"` for use in conversation history.
141
-
142
- ### to_s
143
-
144
- ```ruby
145
- message.to_s # => String
146
- ```
147
-
148
- Returns the content string.
149
-
150
- ### self.from
151
-
152
- ```ruby
153
- UserMessage.from(input) # => UserMessage
154
- ```
155
-
156
- Normalizes any input into a `UserMessage`:
157
-
158
- | Input | Result |
159
- |-------|--------|
160
- | `UserMessage` | Returned unchanged (same object) |
161
- | `String` | `new(input)` |
162
- | `Hash` | Keys symbolized, then `new(content, session_id:, system_prompt:, metadata:, id:)` |
163
- | `TextMessage` | `new(input.content)` — role and stop reason are dropped |
164
- | anything else | `new(input.to_s)` |
165
-
166
- There is no "unsupported input" branch: `from` never raises for an unrecognized
167
- type, it falls through to `to_s`.
168
-
169
- ## Examples
170
-
171
- ### Basic Message
172
-
173
- ```ruby
174
- message = UserMessage.new("Hello!")
175
- ```
176
-
177
- ### With Session ID
178
-
179
- ```ruby
180
- message = UserMessage.new(
181
- "Continue our conversation",
182
- session_id: "session_abc123"
183
- )
184
- ```
185
-
186
- ### With System Prompt Override
187
-
188
- ```ruby
189
- message = UserMessage.new(
190
- "Translate this",
191
- system_prompt: "You are a translator. Respond in Spanish."
192
- )
193
- ```
194
-
195
- ### With Metadata
196
-
197
- ```ruby
198
- message = UserMessage.new(
199
- "Help with my account",
200
- metadata: {
201
- source: "mobile_app",
202
- user_id: "user_123",
203
- session_id: "sess_456",
204
- locale: "en-US"
205
- }
206
- )
207
- ```
208
-
209
- ### Creating from Various Inputs
210
-
211
- ```ruby
212
- # From a string
213
- msg = UserMessage.from("Hello!")
214
-
215
- # From a hash
216
- msg = UserMessage.from(content: "Hello!", session_id: "123")
217
-
218
- # From an existing UserMessage (returns as-is)
219
- msg = UserMessage.from(existing_message)
220
-
221
- # From a TextMessage (only the content is carried over)
222
- msg = UserMessage.from(TextMessage.new(role: "user", content: "Hello!"))
223
- msg.content # => "Hello!"
224
-
225
- # Anything else falls back to to_s
226
- UserMessage.from(42).content # => "42"
227
- ```
228
-
229
- ## See Also
230
-
231
- - [Memory](../core/memory.md)
232
- - [TextMessage](text-message.md)