poml 0.0.5 → 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.
- checksums.yaml +4 -4
- data/docs/tutorial/advanced/performance.md +695 -0
- data/docs/tutorial/advanced/tool-registration.md +776 -0
- data/docs/tutorial/basic-usage.md +351 -0
- data/docs/tutorial/components/chat-components.md +552 -0
- data/docs/tutorial/components/formatting.md +623 -0
- data/docs/tutorial/components/index.md +366 -0
- data/docs/tutorial/components/media-components.md +259 -0
- data/docs/tutorial/components/schema-components.md +668 -0
- data/docs/tutorial/index.md +184 -0
- data/docs/tutorial/output-formats.md +688 -0
- data/docs/tutorial/quickstart.md +30 -0
- data/docs/tutorial/template-engine.md +540 -0
- data/examples/303_new_component_syntax.poml +45 -0
- data/lib/poml/components/base.rb +150 -3
- data/lib/poml/components/content.rb +10 -3
- data/lib/poml/components/data.rb +539 -19
- data/lib/poml/components/examples.rb +235 -1
- data/lib/poml/components/formatting.rb +184 -18
- data/lib/poml/components/layout.rb +7 -2
- data/lib/poml/components/lists.rb +69 -35
- data/lib/poml/components/meta.rb +191 -6
- data/lib/poml/components/output_schema.rb +103 -0
- data/lib/poml/components/template.rb +72 -61
- data/lib/poml/components/text.rb +30 -1
- data/lib/poml/components/tool.rb +81 -0
- data/lib/poml/components/tool_definition.rb +427 -0
- data/lib/poml/components/tools.rb +14 -0
- data/lib/poml/components/utilities.rb +34 -18
- data/lib/poml/components.rb +29 -0
- data/lib/poml/context.rb +19 -4
- data/lib/poml/parser.rb +90 -64
- data/lib/poml/renderer.rb +191 -9
- data/lib/poml/template_engine.rb +138 -13
- data/lib/poml/version.rb +1 -1
- data/lib/poml.rb +16 -1
- data/readme.md +154 -27
- metadata +34 -4
- data/TUTORIAL.md +0 -987
@@ -0,0 +1,776 @@
|
|
1
|
+
# Tool Registration
|
2
|
+
|
3
|
+
POML provides an enhanced tool registration system with automatic parameter conversion, multiple registration formats, and comprehensive metadata integration.
|
4
|
+
|
5
|
+
## Overview
|
6
|
+
|
7
|
+
The enhanced tool registration system includes:
|
8
|
+
|
9
|
+
- **Multiple Registration Formats** - Various ways to define tools
|
10
|
+
- **Runtime Parameter Conversion** - Automatic type conversion for parameters
|
11
|
+
- **kebab-case to camelCase Conversion** - Automatic parameter key conversion
|
12
|
+
- **Comprehensive Metadata** - Full tool integration in response metadata
|
13
|
+
|
14
|
+
## Basic Tool Registration
|
15
|
+
|
16
|
+
### Using tool-definition Component
|
17
|
+
|
18
|
+
```ruby
|
19
|
+
require 'poml'
|
20
|
+
|
21
|
+
markup = <<~POML
|
22
|
+
<poml>
|
23
|
+
<role>Database Assistant</role>
|
24
|
+
<task>Help with database operations</task>
|
25
|
+
|
26
|
+
<tool-definition name="execute_query">
|
27
|
+
{
|
28
|
+
"description": "Execute a SQL query on the database",
|
29
|
+
"parameters": {
|
30
|
+
"type": "object",
|
31
|
+
"properties": {
|
32
|
+
"query": {
|
33
|
+
"type": "string",
|
34
|
+
"description": "The SQL query to execute"
|
35
|
+
},
|
36
|
+
"database": {
|
37
|
+
"type": "string",
|
38
|
+
"description": "Target database name"
|
39
|
+
}
|
40
|
+
},
|
41
|
+
"required": ["query", "database"]
|
42
|
+
}
|
43
|
+
}
|
44
|
+
</tool-definition>
|
45
|
+
</poml>
|
46
|
+
POML
|
47
|
+
|
48
|
+
result = Poml.process(markup: markup)
|
49
|
+
puts result['tools'] # Tools are now at top level
|
50
|
+
```
|
51
|
+
|
52
|
+
### Using meta Component
|
53
|
+
|
54
|
+
```ruby
|
55
|
+
markup = <<~POML
|
56
|
+
<poml>
|
57
|
+
<role>File Manager</role>
|
58
|
+
<task>Manage files and directories</task>
|
59
|
+
|
60
|
+
<meta type="tool" name="file_operations">
|
61
|
+
{
|
62
|
+
"description": "Perform file system operations",
|
63
|
+
"parameters": {
|
64
|
+
"type": "object",
|
65
|
+
"properties": {
|
66
|
+
"operation": {"type": "string", "enum": ["read", "write", "delete"]},
|
67
|
+
"path": {"type": "string"},
|
68
|
+
"content": {"type": "string"}
|
69
|
+
},
|
70
|
+
"required": ["operation", "path"]
|
71
|
+
}
|
72
|
+
}
|
73
|
+
</meta>
|
74
|
+
</poml>
|
75
|
+
POML
|
76
|
+
|
77
|
+
result = Poml.process(markup: markup)
|
78
|
+
```
|
79
|
+
|
80
|
+
### Attribute-Based Registration
|
81
|
+
|
82
|
+
```ruby
|
83
|
+
markup = <<~POML
|
84
|
+
<poml>
|
85
|
+
<role>API Helper</role>
|
86
|
+
<task>Make HTTP requests</task>
|
87
|
+
|
88
|
+
<meta tool="http_request" description="Make HTTP API requests">
|
89
|
+
{
|
90
|
+
"parameters": {
|
91
|
+
"type": "object",
|
92
|
+
"properties": {
|
93
|
+
"url": {"type": "string", "format": "uri"},
|
94
|
+
"method": {"type": "string", "enum": ["GET", "POST", "PUT", "DELETE"]},
|
95
|
+
"headers": {"type": "object"},
|
96
|
+
"body": {"type": "object"}
|
97
|
+
},
|
98
|
+
"required": ["url", "method"]
|
99
|
+
}
|
100
|
+
}
|
101
|
+
</meta>
|
102
|
+
</poml>
|
103
|
+
POML
|
104
|
+
|
105
|
+
result = Poml.process(markup: markup)
|
106
|
+
```
|
107
|
+
|
108
|
+
## Enhanced Parameter Conversion
|
109
|
+
|
110
|
+
### Automatic Type Conversion
|
111
|
+
|
112
|
+
The enhanced tool registration automatically converts parameter types at runtime:
|
113
|
+
|
114
|
+
```ruby
|
115
|
+
markup = <<~POML
|
116
|
+
<poml>
|
117
|
+
<role>Configuration Manager</role>
|
118
|
+
<task>Manage application configuration</task>
|
119
|
+
|
120
|
+
<tool-definition name="update_config">
|
121
|
+
{
|
122
|
+
"description": "Update application configuration",
|
123
|
+
"parameters": {
|
124
|
+
"type": "object",
|
125
|
+
"properties": {
|
126
|
+
"enabled": "boolean",
|
127
|
+
"max_connections": "number",
|
128
|
+
"timeout": "number",
|
129
|
+
"features": "array",
|
130
|
+
"metadata": "object",
|
131
|
+
"config_name": "string"
|
132
|
+
}
|
133
|
+
}
|
134
|
+
}
|
135
|
+
</tool-definition>
|
136
|
+
</poml>
|
137
|
+
POML
|
138
|
+
|
139
|
+
result = Poml.process(markup: markup)
|
140
|
+
|
141
|
+
# Parameter types are automatically converted:
|
142
|
+
# "boolean" -> {"type": "boolean"}
|
143
|
+
# "number" -> {"type": "number"}
|
144
|
+
# "array" -> {"type": "array"}
|
145
|
+
# "object" -> {"type": "object"}
|
146
|
+
# "string" -> {"type": "string"}
|
147
|
+
```
|
148
|
+
|
149
|
+
### Complex Type Conversion
|
150
|
+
|
151
|
+
```ruby
|
152
|
+
markup = <<~POML
|
153
|
+
<poml>
|
154
|
+
<role>Data Processor</role>
|
155
|
+
<task>Process and validate data</task>
|
156
|
+
|
157
|
+
<tool-definition name="process_data">
|
158
|
+
{
|
159
|
+
"description": "Process and validate input data",
|
160
|
+
"parameters": {
|
161
|
+
"type": "object",
|
162
|
+
"properties": {
|
163
|
+
"input_data": {
|
164
|
+
"type": "array",
|
165
|
+
"items": "object",
|
166
|
+
"description": "Array of data objects to process"
|
167
|
+
},
|
168
|
+
"validation_rules": {
|
169
|
+
"type": "object",
|
170
|
+
"properties": {
|
171
|
+
"required_fields": "array",
|
172
|
+
"field_types": "object",
|
173
|
+
"custom_validators": "array"
|
174
|
+
}
|
175
|
+
},
|
176
|
+
"processing_options": {
|
177
|
+
"type": "object",
|
178
|
+
"properties": {
|
179
|
+
"batch_size": "number",
|
180
|
+
"parallel_processing": "boolean",
|
181
|
+
"error_handling": "string"
|
182
|
+
}
|
183
|
+
}
|
184
|
+
}
|
185
|
+
}
|
186
|
+
}
|
187
|
+
</tool-definition>
|
188
|
+
</poml>
|
189
|
+
POML
|
190
|
+
|
191
|
+
result = Poml.process(markup: markup)
|
192
|
+
```
|
193
|
+
|
194
|
+
## kebab-case to camelCase Conversion
|
195
|
+
|
196
|
+
### Automatic Key Conversion
|
197
|
+
|
198
|
+
Parameter keys in kebab-case are automatically converted to camelCase:
|
199
|
+
|
200
|
+
```ruby
|
201
|
+
markup = <<~POML
|
202
|
+
<poml>
|
203
|
+
<role>API Integration Specialist</role>
|
204
|
+
<task>Configure API integrations</task>
|
205
|
+
|
206
|
+
<tool-definition name="configure_api">
|
207
|
+
{
|
208
|
+
"description": "Configure API integration settings",
|
209
|
+
"parameters": {
|
210
|
+
"type": "object",
|
211
|
+
"properties": {
|
212
|
+
"api-endpoint": {"type": "string"},
|
213
|
+
"request-timeout": {"type": "number"},
|
214
|
+
"retry-attempts": {"type": "number"},
|
215
|
+
"authentication-type": {"type": "string"},
|
216
|
+
"rate-limit-requests": {"type": "number"},
|
217
|
+
"enable-logging": {"type": "boolean"},
|
218
|
+
"custom-headers": {"type": "object"},
|
219
|
+
"response-format": {"type": "string"}
|
220
|
+
}
|
221
|
+
}
|
222
|
+
}
|
223
|
+
</tool-definition>
|
224
|
+
</poml>
|
225
|
+
POML
|
226
|
+
|
227
|
+
result = Poml.process(markup: markup)
|
228
|
+
|
229
|
+
# Keys are automatically converted:
|
230
|
+
# "api-endpoint" -> "apiEndpoint"
|
231
|
+
# "request-timeout" -> "requestTimeout"
|
232
|
+
# "retry-attempts" -> "retryAttempts"
|
233
|
+
# "authentication-type" -> "authenticationType"
|
234
|
+
# "rate-limit-requests" -> "rateLimitRequests"
|
235
|
+
# "enable-logging" -> "enableLogging"
|
236
|
+
# "custom-headers" -> "customHeaders"
|
237
|
+
# "response-format" -> "responseFormat"
|
238
|
+
```
|
239
|
+
|
240
|
+
### Deep Nested Conversion
|
241
|
+
|
242
|
+
The conversion works recursively on nested objects:
|
243
|
+
|
244
|
+
```ruby
|
245
|
+
markup = <<~POML
|
246
|
+
<poml>
|
247
|
+
<role>Database Configuration Manager</role>
|
248
|
+
<task>Configure database connections</task>
|
249
|
+
|
250
|
+
<tool-definition name="setup_database">
|
251
|
+
{
|
252
|
+
"description": "Setup database connection configuration",
|
253
|
+
"parameters": {
|
254
|
+
"type": "object",
|
255
|
+
"properties": {
|
256
|
+
"connection-settings": {
|
257
|
+
"type": "object",
|
258
|
+
"properties": {
|
259
|
+
"host-address": {"type": "string"},
|
260
|
+
"port-number": {"type": "number"},
|
261
|
+
"database-name": {"type": "string"},
|
262
|
+
"connection-timeout": {"type": "number"},
|
263
|
+
"pool-settings": {
|
264
|
+
"type": "object",
|
265
|
+
"properties": {
|
266
|
+
"min-connections": {"type": "number"},
|
267
|
+
"max-connections": {"type": "number"},
|
268
|
+
"connection-lifetime": {"type": "number"},
|
269
|
+
"idle-timeout": {"type": "number"}
|
270
|
+
}
|
271
|
+
}
|
272
|
+
}
|
273
|
+
},
|
274
|
+
"security-options": {
|
275
|
+
"type": "object",
|
276
|
+
"properties": {
|
277
|
+
"ssl-enabled": {"type": "boolean"},
|
278
|
+
"certificate-path": {"type": "string"},
|
279
|
+
"encryption-level": {"type": "string"}
|
280
|
+
}
|
281
|
+
}
|
282
|
+
}
|
283
|
+
}
|
284
|
+
}
|
285
|
+
</tool-definition>
|
286
|
+
</poml>
|
287
|
+
POML
|
288
|
+
|
289
|
+
result = Poml.process(markup: markup)
|
290
|
+
|
291
|
+
# All nested keys are converted:
|
292
|
+
# connection-settings -> connectionSettings
|
293
|
+
# host-address -> hostAddress
|
294
|
+
# port-number -> portNumber
|
295
|
+
# pool-settings -> poolSettings
|
296
|
+
# min-connections -> minConnections
|
297
|
+
# max-connections -> maxConnections
|
298
|
+
# etc.
|
299
|
+
```
|
300
|
+
|
301
|
+
## Multiple Tool Registration
|
302
|
+
|
303
|
+
### Registering Multiple Tools
|
304
|
+
|
305
|
+
```ruby
|
306
|
+
markup = <<~POML
|
307
|
+
<poml>
|
308
|
+
<role>DevOps Engineer</role>
|
309
|
+
<task>Manage infrastructure and deployments</task>
|
310
|
+
|
311
|
+
<tool-definition name="deploy_application">
|
312
|
+
{
|
313
|
+
"description": "Deploy application to specified environment",
|
314
|
+
"parameters": {
|
315
|
+
"type": "object",
|
316
|
+
"properties": {
|
317
|
+
"environment": {"type": "string", "enum": ["dev", "staging", "prod"]},
|
318
|
+
"version": {"type": "string"},
|
319
|
+
"rollback-on-failure": {"type": "boolean", "default": true}
|
320
|
+
}
|
321
|
+
}
|
322
|
+
}
|
323
|
+
</tool-definition>
|
324
|
+
|
325
|
+
<tool-definition name="scale_service">
|
326
|
+
{
|
327
|
+
"description": "Scale service instances up or down",
|
328
|
+
"parameters": {
|
329
|
+
"type": "object",
|
330
|
+
"properties": {
|
331
|
+
"service-name": {"type": "string"},
|
332
|
+
"instance-count": {"type": "number", "minimum": 1},
|
333
|
+
"auto-scaling": {"type": "boolean", "default": false}
|
334
|
+
}
|
335
|
+
}
|
336
|
+
}
|
337
|
+
</tool-definition>
|
338
|
+
|
339
|
+
<tool-definition name="check_health">
|
340
|
+
{
|
341
|
+
"description": "Perform health check on services",
|
342
|
+
"parameters": {
|
343
|
+
"type": "object",
|
344
|
+
"properties": {
|
345
|
+
"services": {"type": "array", "items": {"type": "string"}},
|
346
|
+
"include-dependencies": {"type": "boolean", "default": true}
|
347
|
+
}
|
348
|
+
}
|
349
|
+
}
|
350
|
+
</tool-definition>
|
351
|
+
</poml>
|
352
|
+
POML
|
353
|
+
|
354
|
+
result = Poml.process(markup: markup)
|
355
|
+
puts "Registered #{result['tools'].length} tools"
|
356
|
+
```
|
357
|
+
|
358
|
+
### Mixed Registration Formats
|
359
|
+
|
360
|
+
```ruby
|
361
|
+
markup = <<~POML
|
362
|
+
<poml>
|
363
|
+
<role>System Administrator</role>
|
364
|
+
<task>Manage system operations</task>
|
365
|
+
|
366
|
+
<!-- New format -->
|
367
|
+
<tool-definition name="system_monitor">
|
368
|
+
{
|
369
|
+
"description": "Monitor system performance metrics",
|
370
|
+
"parameters": {
|
371
|
+
"type": "object",
|
372
|
+
"properties": {
|
373
|
+
"metric-types": {"type": "array"},
|
374
|
+
"time-range": {"type": "string"}
|
375
|
+
}
|
376
|
+
}
|
377
|
+
}
|
378
|
+
</tool-definition>
|
379
|
+
|
380
|
+
<!-- Legacy format -->
|
381
|
+
<meta type="tool" name="backup_data">
|
382
|
+
{
|
383
|
+
"description": "Backup system data",
|
384
|
+
"parameters": {
|
385
|
+
"type": "object",
|
386
|
+
"properties": {
|
387
|
+
"backup-location": {"type": "string"},
|
388
|
+
"compression-enabled": {"type": "boolean"}
|
389
|
+
}
|
390
|
+
}
|
391
|
+
}
|
392
|
+
</meta>
|
393
|
+
|
394
|
+
<!-- Attribute format -->
|
395
|
+
<meta tool="restart_service" description="Restart system service">
|
396
|
+
{
|
397
|
+
"parameters": {
|
398
|
+
"type": "object",
|
399
|
+
"properties": {
|
400
|
+
"service-name": {"type": "string"},
|
401
|
+
"force-restart": {"type": "boolean"}
|
402
|
+
}
|
403
|
+
}
|
404
|
+
}
|
405
|
+
</meta>
|
406
|
+
</poml>
|
407
|
+
POML
|
408
|
+
|
409
|
+
result = Poml.process(markup: markup)
|
410
|
+
```
|
411
|
+
|
412
|
+
## Template Variables in Tools
|
413
|
+
|
414
|
+
### Dynamic Tool Definitions
|
415
|
+
|
416
|
+
```ruby
|
417
|
+
markup = <<~POML
|
418
|
+
<poml>
|
419
|
+
<role>{{service_type}} Manager</role>
|
420
|
+
<task>Manage {{service_type}} operations</task>
|
421
|
+
|
422
|
+
<tool-definition name="{{tool_name}}">
|
423
|
+
{
|
424
|
+
"description": "{{tool_description}}",
|
425
|
+
"parameters": {
|
426
|
+
"type": "object",
|
427
|
+
"properties": {
|
428
|
+
{{#parameters}}
|
429
|
+
"{{name}}": {
|
430
|
+
"type": "{{type}}",
|
431
|
+
"description": "{{description}}"
|
432
|
+
{{#default}}, "default": {{default}}{{/default}}
|
433
|
+
}{{#unless @last}},{{/unless}}
|
434
|
+
{{/parameters}}
|
435
|
+
}
|
436
|
+
}
|
437
|
+
}
|
438
|
+
</tool-definition>
|
439
|
+
</poml>
|
440
|
+
POML
|
441
|
+
|
442
|
+
context = {
|
443
|
+
'service_type' => 'Database',
|
444
|
+
'tool_name' => 'execute_query',
|
445
|
+
'tool_description' => 'Execute SQL query on database',
|
446
|
+
'parameters' => [
|
447
|
+
{ 'name' => 'query', 'type' => 'string', 'description' => 'SQL query to execute' },
|
448
|
+
{ 'name' => 'timeout', 'type' => 'number', 'description' => 'Query timeout in seconds', 'default' => '30' }
|
449
|
+
]
|
450
|
+
}
|
451
|
+
|
452
|
+
result = Poml.process(markup: markup, context: context)
|
453
|
+
```
|
454
|
+
|
455
|
+
### Conditional Tool Registration
|
456
|
+
|
457
|
+
```ruby
|
458
|
+
markup = <<~POML
|
459
|
+
<poml>
|
460
|
+
<role>{{environment}} Administrator</role>
|
461
|
+
<task>Manage {{environment}} environment</task>
|
462
|
+
|
463
|
+
<if condition="{{environment}} == 'production'">
|
464
|
+
<tool-definition name="production_deploy">
|
465
|
+
{
|
466
|
+
"description": "Deploy to production with safety checks",
|
467
|
+
"parameters": {
|
468
|
+
"type": "object",
|
469
|
+
"properties": {
|
470
|
+
"version": {"type": "string"},
|
471
|
+
"approval-required": {"type": "boolean", "default": true},
|
472
|
+
"rollback-plan": {"type": "string"}
|
473
|
+
},
|
474
|
+
"required": ["version", "rollback-plan"]
|
475
|
+
}
|
476
|
+
}
|
477
|
+
</tool-definition>
|
478
|
+
</if>
|
479
|
+
|
480
|
+
<if condition="{{environment}} == 'development'">
|
481
|
+
<tool-definition name="dev_deploy">
|
482
|
+
{
|
483
|
+
"description": "Quick deployment for development",
|
484
|
+
"parameters": {
|
485
|
+
"type": "object",
|
486
|
+
"properties": {
|
487
|
+
"branch": {"type": "string", "default": "main"},
|
488
|
+
"skip-tests": {"type": "boolean", "default": false}
|
489
|
+
}
|
490
|
+
}
|
491
|
+
}
|
492
|
+
</tool-definition>
|
493
|
+
</if>
|
494
|
+
</poml>
|
495
|
+
POML
|
496
|
+
|
497
|
+
context = { 'environment' => 'production' }
|
498
|
+
result = Poml.process(markup: markup, context: context)
|
499
|
+
```
|
500
|
+
|
501
|
+
## Schema Consistency
|
502
|
+
|
503
|
+
### Enhanced Storage Format
|
504
|
+
|
505
|
+
The enhanced tool registration ensures consistent schema storage:
|
506
|
+
|
507
|
+
```ruby
|
508
|
+
markup = <<~POML
|
509
|
+
<poml>
|
510
|
+
<role>API Documentation Generator</role>
|
511
|
+
<task>Generate API documentation</task>
|
512
|
+
|
513
|
+
<tool-definition name="generate_docs">
|
514
|
+
{
|
515
|
+
"description": "Generate API documentation from schema",
|
516
|
+
"parameters": {
|
517
|
+
"type": "object",
|
518
|
+
"properties": {
|
519
|
+
"api-specification": "object",
|
520
|
+
"output-format": "string",
|
521
|
+
"include-examples": "boolean"
|
522
|
+
}
|
523
|
+
}
|
524
|
+
}
|
525
|
+
</tool-definition>
|
526
|
+
</poml>
|
527
|
+
POML
|
528
|
+
|
529
|
+
result = Poml.process(markup: markup)
|
530
|
+
|
531
|
+
# Enhanced storage format ensures consistency:
|
532
|
+
tool = result['tools'][0] # Tools are now at top level
|
533
|
+
puts tool['name'] # "generate_docs"
|
534
|
+
puts tool['description'] # "Generate API documentation from schema"
|
535
|
+
puts tool['parameters'] # Properly structured parameters object
|
536
|
+
|
537
|
+
# Parameters are stored in consistent format:
|
538
|
+
# - Type conversion applied
|
539
|
+
# - camelCase conversion applied
|
540
|
+
# - Proper JSON schema structure maintained
|
541
|
+
```
|
542
|
+
|
543
|
+
## Integration with Output Formats
|
544
|
+
|
545
|
+
### OpenAI Chat Format
|
546
|
+
|
547
|
+
```ruby
|
548
|
+
markup = <<~POML
|
549
|
+
<poml>
|
550
|
+
<role>Code Assistant</role>
|
551
|
+
<task>Help with programming tasks</task>
|
552
|
+
|
553
|
+
<tool-definition name="analyze_code">
|
554
|
+
{
|
555
|
+
"description": "Analyze code for issues and improvements",
|
556
|
+
"parameters": {
|
557
|
+
"type": "object",
|
558
|
+
"properties": {
|
559
|
+
"source-code": {"type": "string"},
|
560
|
+
"language": {"type": "string"},
|
561
|
+
"analysis-type": {"type": "array", "items": {"type": "string"}}
|
562
|
+
}
|
563
|
+
}
|
564
|
+
}
|
565
|
+
</tool-definition>
|
566
|
+
</poml>
|
567
|
+
POML
|
568
|
+
|
569
|
+
result = Poml.process(markup: markup, format: 'openai_chat')
|
570
|
+
|
571
|
+
# Tools are included in OpenAI format for function calling
|
572
|
+
puts result # Contains both messages and tool definitions
|
573
|
+
```
|
574
|
+
|
575
|
+
### OpenAI Response Format
|
576
|
+
|
577
|
+
```ruby
|
578
|
+
result = Poml.process(markup: markup, format: 'openaiResponse')
|
579
|
+
|
580
|
+
puts result['tools'] # Tools available at top level
|
581
|
+
puts result['content'] # Formatted prompt content
|
582
|
+
```
|
583
|
+
|
584
|
+
## Error Handling and Validation
|
585
|
+
|
586
|
+
### Tool Definition Validation
|
587
|
+
|
588
|
+
```ruby
|
589
|
+
def validate_tool_definition(markup)
|
590
|
+
begin
|
591
|
+
result = Poml.process(markup: markup)
|
592
|
+
tools = result['tools'] # Tools are now at top level
|
593
|
+
|
594
|
+
tools.each do |tool|
|
595
|
+
errors = []
|
596
|
+
|
597
|
+
# Check required fields
|
598
|
+
errors << "Missing description" unless tool['description']
|
599
|
+
errors << "Missing parameters" unless tool['parameters']
|
600
|
+
|
601
|
+
# Validate parameters structure
|
602
|
+
if tool['parameters']
|
603
|
+
params = tool['parameters']
|
604
|
+
errors << "Parameters must have type 'object'" unless params['type'] == 'object'
|
605
|
+
errors << "Parameters missing properties" unless params['properties']
|
606
|
+
end
|
607
|
+
|
608
|
+
if errors.empty?
|
609
|
+
puts "✅ Tool '#{tool['name']}' is valid"
|
610
|
+
else
|
611
|
+
puts "❌ Tool '#{tool['name']}' errors: #{errors.join(', ')}"
|
612
|
+
end
|
613
|
+
end
|
614
|
+
|
615
|
+
rescue StandardError => e
|
616
|
+
puts "❌ Error processing tools: #{e.message}"
|
617
|
+
end
|
618
|
+
end
|
619
|
+
|
620
|
+
# Usage
|
621
|
+
markup = <<~POML
|
622
|
+
<poml>
|
623
|
+
<tool-definition name="test_tool">
|
624
|
+
{
|
625
|
+
"description": "Test tool",
|
626
|
+
"parameters": {
|
627
|
+
"type": "object",
|
628
|
+
"properties": {
|
629
|
+
"input": {"type": "string"}
|
630
|
+
}
|
631
|
+
}
|
632
|
+
}
|
633
|
+
</tool-definition>
|
634
|
+
</poml>
|
635
|
+
POML
|
636
|
+
|
637
|
+
validate_tool_definition(markup)
|
638
|
+
```
|
639
|
+
|
640
|
+
### Safe Tool Processing
|
641
|
+
|
642
|
+
```ruby
|
643
|
+
class SafeToolProcessor
|
644
|
+
def self.process_tools(markup, context = {})
|
645
|
+
begin
|
646
|
+
result = Poml.process(markup: markup, context: context)
|
647
|
+
|
648
|
+
# Validate tool structure
|
649
|
+
tools = result['tools'] || [] # Tools are now at top level
|
650
|
+
valid_tools = tools.select { |tool| valid_tool?(tool) }
|
651
|
+
|
652
|
+
{
|
653
|
+
success: true,
|
654
|
+
tools: valid_tools,
|
655
|
+
invalid_count: tools.length - valid_tools.length
|
656
|
+
}
|
657
|
+
|
658
|
+
rescue StandardError => e
|
659
|
+
{
|
660
|
+
success: false,
|
661
|
+
error: e.message,
|
662
|
+
tools: []
|
663
|
+
}
|
664
|
+
end
|
665
|
+
end
|
666
|
+
|
667
|
+
private
|
668
|
+
|
669
|
+
def self.valid_tool?(tool)
|
670
|
+
tool.is_a?(Hash) &&
|
671
|
+
tool['name'] &&
|
672
|
+
tool['description'] &&
|
673
|
+
tool['parameters']&.is_a?(Hash)
|
674
|
+
end
|
675
|
+
end
|
676
|
+
|
677
|
+
# Usage
|
678
|
+
result = SafeToolProcessor.process_tools(markup, context)
|
679
|
+
if result[:success]
|
680
|
+
puts "Processed #{result[:tools].length} valid tools"
|
681
|
+
else
|
682
|
+
puts "Error: #{result[:error]}"
|
683
|
+
end
|
684
|
+
```
|
685
|
+
|
686
|
+
## Best Practices
|
687
|
+
|
688
|
+
### 1. Use Descriptive Tool Names
|
689
|
+
|
690
|
+
```ruby
|
691
|
+
# Good
|
692
|
+
<tool-definition name="execute_query">
|
693
|
+
|
694
|
+
# Better
|
695
|
+
<tool-definition name="execute_database_query">
|
696
|
+
|
697
|
+
# Best
|
698
|
+
<tool-definition name="execute_sql_query_with_validation">
|
699
|
+
```
|
700
|
+
|
701
|
+
### 2. Provide Comprehensive Descriptions
|
702
|
+
|
703
|
+
```ruby
|
704
|
+
{
|
705
|
+
"description": "Execute a SQL query on the specified database with optional result limiting and error handling",
|
706
|
+
"parameters": {
|
707
|
+
"type": "object",
|
708
|
+
"properties": {
|
709
|
+
"query": {
|
710
|
+
"type": "string",
|
711
|
+
"description": "Valid SQL SELECT, INSERT, UPDATE, or DELETE statement"
|
712
|
+
}
|
713
|
+
}
|
714
|
+
}
|
715
|
+
}
|
716
|
+
```
|
717
|
+
|
718
|
+
### 3. Use Validation Constraints
|
719
|
+
|
720
|
+
```ruby
|
721
|
+
{
|
722
|
+
"parameters": {
|
723
|
+
"type": "object",
|
724
|
+
"properties": {
|
725
|
+
"timeout": {
|
726
|
+
"type": "number",
|
727
|
+
"minimum": 1,
|
728
|
+
"maximum": 300,
|
729
|
+
"default": 30,
|
730
|
+
"description": "Query timeout in seconds (1-300)"
|
731
|
+
},
|
732
|
+
"operation": {
|
733
|
+
"type": "string",
|
734
|
+
"enum": ["select", "insert", "update", "delete"],
|
735
|
+
"description": "Type of database operation"
|
736
|
+
}
|
737
|
+
}
|
738
|
+
}
|
739
|
+
}
|
740
|
+
```
|
741
|
+
|
742
|
+
### 4. Organize Complex Tools
|
743
|
+
|
744
|
+
```ruby
|
745
|
+
# Break complex tools into logical sections
|
746
|
+
{
|
747
|
+
"description": "Comprehensive API request tool",
|
748
|
+
"parameters": {
|
749
|
+
"type": "object",
|
750
|
+
"properties": {
|
751
|
+
"request_config": {
|
752
|
+
"type": "object",
|
753
|
+
"description": "HTTP request configuration",
|
754
|
+
"properties": {
|
755
|
+
"url": {"type": "string"},
|
756
|
+
"method": {"type": "string"}
|
757
|
+
}
|
758
|
+
},
|
759
|
+
"auth_config": {
|
760
|
+
"type": "object",
|
761
|
+
"description": "Authentication configuration",
|
762
|
+
"properties": {
|
763
|
+
"type": {"type": "string"},
|
764
|
+
"credentials": {"type": "object"}
|
765
|
+
}
|
766
|
+
}
|
767
|
+
}
|
768
|
+
}
|
769
|
+
}
|
770
|
+
```
|
771
|
+
|
772
|
+
## Next Steps
|
773
|
+
|
774
|
+
- Learn about [Schema Components](../components/schema-components.md) for output schemas
|
775
|
+
- Explore [Performance](performance.md) optimization for tool processing
|
776
|
+
- Check [Integration Examples](../integration/rails.md) for real-world tool usage
|