poml 0.0.6 → 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/lib/poml/components/base.rb +146 -4
- 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 +134 -5
- data/lib/poml/components/output_schema.rb +19 -1
- 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 +339 -10
- data/lib/poml/components/tools.rb +14 -0
- data/lib/poml/components/utilities.rb +34 -18
- data/lib/poml/components.rb +19 -0
- data/lib/poml/context.rb +19 -4
- data/lib/poml/parser.rb +88 -63
- 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 +31 -4
- data/TUTORIAL.md +0 -987
@@ -0,0 +1,540 @@
|
|
1
|
+
# Template Engine
|
2
|
+
|
3
|
+
POML includes a powerful template engine that supports variables, conditionals, loops, and meta variables for creating dynamic, reusable prompts.
|
4
|
+
|
5
|
+
## Variable Substitution
|
6
|
+
|
7
|
+
### Basic Variables
|
8
|
+
|
9
|
+
Use `{{variable_name}}` syntax for simple variable substitution:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
require 'poml'
|
13
|
+
|
14
|
+
markup = <<~POML
|
15
|
+
<poml>
|
16
|
+
<role>{{expert_type}} Expert</role>
|
17
|
+
<task>{{main_task}}</task>
|
18
|
+
<hint>Focus on {{focus_area}} and provide {{output_type}}</hint>
|
19
|
+
</poml>
|
20
|
+
POML
|
21
|
+
|
22
|
+
context = {
|
23
|
+
'expert_type' => 'Machine Learning',
|
24
|
+
'main_task' => 'Analyze model performance',
|
25
|
+
'focus_area' => 'accuracy metrics',
|
26
|
+
'output_type' => 'actionable recommendations'
|
27
|
+
}
|
28
|
+
|
29
|
+
result = Poml.process(markup: markup, context: context)
|
30
|
+
puts result['content']
|
31
|
+
```
|
32
|
+
|
33
|
+
### Variable Safety
|
34
|
+
|
35
|
+
Variables that don't exist in context are left unchanged:
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
markup = '<poml><role>{{existing}} and {{missing}}</role></poml>'
|
39
|
+
context = { 'existing' => 'Data Scientist' }
|
40
|
+
|
41
|
+
result = Poml.process(markup: markup, context: context)
|
42
|
+
# Output will contain: "Data Scientist and {{missing}}"
|
43
|
+
```
|
44
|
+
|
45
|
+
## Meta Variables
|
46
|
+
|
47
|
+
Use the `<meta variables="">` component to define template variables within the POML document:
|
48
|
+
|
49
|
+
```ruby
|
50
|
+
markup = <<~POML
|
51
|
+
<poml>
|
52
|
+
<meta variables='{"project": "E-commerce Platform", "deadline": "Q4 2024", "team_size": 8}' />
|
53
|
+
|
54
|
+
<role>Project Manager</role>
|
55
|
+
<task>Create project plan for {{project}}</task>
|
56
|
+
|
57
|
+
<p>Project Details:</p>
|
58
|
+
<list>
|
59
|
+
<item>Deadline: {{deadline}}</item>
|
60
|
+
<item>Team Size: {{team_size}} developers</item>
|
61
|
+
</list>
|
62
|
+
</poml>
|
63
|
+
POML
|
64
|
+
|
65
|
+
result = Poml.process(markup: markup)
|
66
|
+
puts result['content']
|
67
|
+
```
|
68
|
+
|
69
|
+
### Combining Context and Meta Variables
|
70
|
+
|
71
|
+
External context overrides meta variables:
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
markup = <<~POML
|
75
|
+
<poml>
|
76
|
+
<meta variables='{"environment": "development", "debug": true}' />
|
77
|
+
|
78
|
+
<role>DevOps Engineer</role>
|
79
|
+
<task>Deploy to {{environment}} environment</task>
|
80
|
+
<hint>Debug mode: {{debug}}</hint>
|
81
|
+
</poml>
|
82
|
+
POML
|
83
|
+
|
84
|
+
# Override meta variables
|
85
|
+
context = { 'environment' => 'production', 'debug' => false }
|
86
|
+
|
87
|
+
result = Poml.process(markup: markup, context: context)
|
88
|
+
# Will use production/false instead of development/true
|
89
|
+
```
|
90
|
+
|
91
|
+
## Conditional Logic
|
92
|
+
|
93
|
+
### Basic If Statements
|
94
|
+
|
95
|
+
Use `<if condition="">` for conditional content:
|
96
|
+
|
97
|
+
```ruby
|
98
|
+
markup = <<~POML
|
99
|
+
<poml>
|
100
|
+
<role>Security Analyst</role>
|
101
|
+
<task>Analyze security requirements</task>
|
102
|
+
|
103
|
+
<if condition="{{security_level}} == 'high'">
|
104
|
+
<p>Implement additional security measures:</p>
|
105
|
+
<list>
|
106
|
+
<item>Multi-factor authentication</item>
|
107
|
+
<item>End-to-end encryption</item>
|
108
|
+
<item>Regular security audits</item>
|
109
|
+
</list>
|
110
|
+
</if>
|
111
|
+
|
112
|
+
<if condition="{{compliance_required}}">
|
113
|
+
<p>Ensure compliance with {{compliance_standards}}.</p>
|
114
|
+
</if>
|
115
|
+
</poml>
|
116
|
+
POML
|
117
|
+
|
118
|
+
context = {
|
119
|
+
'security_level' => 'high',
|
120
|
+
'compliance_required' => true,
|
121
|
+
'compliance_standards' => 'SOC 2 and GDPR'
|
122
|
+
}
|
123
|
+
|
124
|
+
result = Poml.process(markup: markup, context: context)
|
125
|
+
```
|
126
|
+
|
127
|
+
### Comparison Operators
|
128
|
+
|
129
|
+
POML supports various comparison operators:
|
130
|
+
|
131
|
+
```ruby
|
132
|
+
markup = <<~POML
|
133
|
+
<poml>
|
134
|
+
<role>Performance Analyst</role>
|
135
|
+
<task>Analyze performance metrics</task>
|
136
|
+
|
137
|
+
<if condition="{{response_time}} > 500">
|
138
|
+
<p>⚠️ Response time is too slow: {{response_time}}ms</p>
|
139
|
+
</if>
|
140
|
+
|
141
|
+
<if condition="{{cpu_usage}} >= 80">
|
142
|
+
<p>🔥 High CPU usage detected: {{cpu_usage}}%</p>
|
143
|
+
</if>
|
144
|
+
|
145
|
+
<if condition="{{error_rate}} <= 0.1">
|
146
|
+
<p>✅ Error rate is acceptable: {{error_rate}}%</p>
|
147
|
+
</if>
|
148
|
+
|
149
|
+
<if condition="{{environment}} != 'production'">
|
150
|
+
<p>🚧 Non-production environment: {{environment}}</p>
|
151
|
+
</if>
|
152
|
+
</poml>
|
153
|
+
POML
|
154
|
+
|
155
|
+
context = {
|
156
|
+
'response_time' => 750,
|
157
|
+
'cpu_usage' => 85,
|
158
|
+
'error_rate' => 0.05,
|
159
|
+
'environment' => 'staging'
|
160
|
+
}
|
161
|
+
```
|
162
|
+
|
163
|
+
Supported operators:
|
164
|
+
|
165
|
+
- `==` - Equal to
|
166
|
+
- `!=` - Not equal to
|
167
|
+
- `>` - Greater than
|
168
|
+
- `>=` - Greater than or equal to
|
169
|
+
- `<` - Less than
|
170
|
+
- `<=` - Less than or equal to
|
171
|
+
|
172
|
+
### Boolean Conditions
|
173
|
+
|
174
|
+
```ruby
|
175
|
+
markup = <<~POML
|
176
|
+
<poml>
|
177
|
+
<role>DevOps Engineer</role>
|
178
|
+
<task>Configure deployment</task>
|
179
|
+
|
180
|
+
<if condition="{{enable_monitoring}}">
|
181
|
+
<p>Enable monitoring and alerting systems.</p>
|
182
|
+
</if>
|
183
|
+
|
184
|
+
<if condition="!{{debug_mode}}">
|
185
|
+
<p>Disable debug logging for production.</p>
|
186
|
+
</if>
|
187
|
+
</poml>
|
188
|
+
POML
|
189
|
+
|
190
|
+
context = {
|
191
|
+
'enable_monitoring' => true,
|
192
|
+
'debug_mode' => false
|
193
|
+
}
|
194
|
+
```
|
195
|
+
|
196
|
+
## Loops and Iteration
|
197
|
+
|
198
|
+
### Basic For Loops
|
199
|
+
|
200
|
+
Use `<for variable="" items="">` to iterate over arrays:
|
201
|
+
|
202
|
+
```ruby
|
203
|
+
markup = <<~POML
|
204
|
+
<poml>
|
205
|
+
<role>API Documentation Writer</role>
|
206
|
+
<task>Document API endpoints</task>
|
207
|
+
|
208
|
+
<p>Available endpoints:</p>
|
209
|
+
<list>
|
210
|
+
<for variable="endpoint" items="{{endpoints}}">
|
211
|
+
<item><b>{{endpoint.method}} {{endpoint.path}}</b> - {{endpoint.description}}</item>
|
212
|
+
</for>
|
213
|
+
</list>
|
214
|
+
</poml>
|
215
|
+
POML
|
216
|
+
|
217
|
+
context = {
|
218
|
+
'endpoints' => [
|
219
|
+
{ 'method' => 'GET', 'path' => '/users', 'description' => 'List all users' },
|
220
|
+
{ 'method' => 'POST', 'path' => '/users', 'description' => 'Create new user' },
|
221
|
+
{ 'method' => 'PUT', 'path' => '/users/:id', 'description' => 'Update user' },
|
222
|
+
{ 'method' => 'DELETE', 'path' => '/users/:id', 'description' => 'Delete user' }
|
223
|
+
]
|
224
|
+
}
|
225
|
+
|
226
|
+
result = Poml.process(markup: markup, context: context)
|
227
|
+
```
|
228
|
+
|
229
|
+
### Simple Array Iteration
|
230
|
+
|
231
|
+
For simple arrays, use `{{.}}` to reference the current item:
|
232
|
+
|
233
|
+
```ruby
|
234
|
+
markup = <<~POML
|
235
|
+
<poml>
|
236
|
+
<role>Tech Lead</role>
|
237
|
+
<task>Review technology stack</task>
|
238
|
+
|
239
|
+
<p>Current technologies:</p>
|
240
|
+
<list>
|
241
|
+
<for variable="tech" items="{{technologies}}">
|
242
|
+
<item>{{.}}</item>
|
243
|
+
</for>
|
244
|
+
</list>
|
245
|
+
</poml>
|
246
|
+
POML
|
247
|
+
|
248
|
+
context = {
|
249
|
+
'technologies' => ['Ruby on Rails', 'PostgreSQL', 'Redis', 'Docker', 'AWS']
|
250
|
+
}
|
251
|
+
```
|
252
|
+
|
253
|
+
### Nested Loops
|
254
|
+
|
255
|
+
```ruby
|
256
|
+
markup = <<~POML
|
257
|
+
<poml>
|
258
|
+
<role>Test Engineer</role>
|
259
|
+
<task>Create test plan</task>
|
260
|
+
|
261
|
+
<for variable="feature" items="{{features}}">
|
262
|
+
<p><b>Feature: {{feature.name}}</b></p>
|
263
|
+
<list>
|
264
|
+
<for variable="test" items="{{feature.tests}}">
|
265
|
+
<item>{{test.type}}: {{test.description}}</item>
|
266
|
+
</for>
|
267
|
+
</list>
|
268
|
+
</for>
|
269
|
+
</poml>
|
270
|
+
POML
|
271
|
+
|
272
|
+
context = {
|
273
|
+
'features' => [
|
274
|
+
{
|
275
|
+
'name' => 'User Authentication',
|
276
|
+
'tests' => [
|
277
|
+
{ 'type' => 'Unit', 'description' => 'Test password validation' },
|
278
|
+
{ 'type' => 'Integration', 'description' => 'Test login flow' }
|
279
|
+
]
|
280
|
+
},
|
281
|
+
{
|
282
|
+
'name' => 'Data Export',
|
283
|
+
'tests' => [
|
284
|
+
{ 'type' => 'Unit', 'description' => 'Test CSV generation' },
|
285
|
+
{ 'type' => 'E2E', 'description' => 'Test complete export workflow' }
|
286
|
+
]
|
287
|
+
}
|
288
|
+
]
|
289
|
+
}
|
290
|
+
```
|
291
|
+
|
292
|
+
## Combining Conditionals and Loops
|
293
|
+
|
294
|
+
### Conditional Lists
|
295
|
+
|
296
|
+
```ruby
|
297
|
+
markup = <<~POML
|
298
|
+
<poml>
|
299
|
+
<role>Release Manager</role>
|
300
|
+
<task>Prepare release notes</task>
|
301
|
+
|
302
|
+
<if condition="{{bug_fixes}}">
|
303
|
+
<p><b>Bug Fixes:</b></p>
|
304
|
+
<list>
|
305
|
+
<for variable="fix" items="{{bug_fixes}}">
|
306
|
+
<item>{{fix.description}} ({{fix.ticket}})</item>
|
307
|
+
</for>
|
308
|
+
</list>
|
309
|
+
</if>
|
310
|
+
|
311
|
+
<if condition="{{new_features}}">
|
312
|
+
<p><b>New Features:</b></p>
|
313
|
+
<list>
|
314
|
+
<for variable="feature" items="{{new_features}}">
|
315
|
+
<item>{{feature.name}} - {{feature.description}}</item>
|
316
|
+
</for>
|
317
|
+
</list>
|
318
|
+
</if>
|
319
|
+
</poml>
|
320
|
+
POML
|
321
|
+
|
322
|
+
context = {
|
323
|
+
'bug_fixes' => [
|
324
|
+
{ 'description' => 'Fixed login timeout issue', 'ticket' => 'BUG-123' },
|
325
|
+
{ 'description' => 'Resolved data export corruption', 'ticket' => 'BUG-124' }
|
326
|
+
],
|
327
|
+
'new_features' => [
|
328
|
+
{ 'name' => 'Dark Mode', 'description' => 'Added dark theme support' },
|
329
|
+
{ 'name' => 'API Rate Limiting', 'description' => 'Implemented request throttling' }
|
330
|
+
]
|
331
|
+
}
|
332
|
+
```
|
333
|
+
|
334
|
+
### Conditional Content Within Loops
|
335
|
+
|
336
|
+
```ruby
|
337
|
+
markup = <<~POML
|
338
|
+
<poml>
|
339
|
+
<role>Code Reviewer</role>
|
340
|
+
<task>Review code changes</task>
|
341
|
+
|
342
|
+
<p>Files Changed:</p>
|
343
|
+
<list>
|
344
|
+
<for variable="file" items="{{changed_files}}">
|
345
|
+
<item>
|
346
|
+
<b>{{file.path}}</b>
|
347
|
+
<if condition="{{file.lines_added}} > 100">
|
348
|
+
⚠️ Large change: +{{file.lines_added}} lines
|
349
|
+
</if>
|
350
|
+
<if condition="{{file.complexity}} == 'high'">
|
351
|
+
🔍 High complexity - needs careful review
|
352
|
+
</if>
|
353
|
+
</item>
|
354
|
+
</for>
|
355
|
+
</list>
|
356
|
+
</poml>
|
357
|
+
POML
|
358
|
+
|
359
|
+
context = {
|
360
|
+
'changed_files' => [
|
361
|
+
{ 'path' => 'app/models/user.rb', 'lines_added' => 45, 'complexity' => 'medium' },
|
362
|
+
{ 'path' => 'app/services/payment_processor.rb', 'lines_added' => 150, 'complexity' => 'high' },
|
363
|
+
{ 'path' => 'config/routes.rb', 'lines_added' => 5, 'complexity' => 'low' }
|
364
|
+
]
|
365
|
+
}
|
366
|
+
```
|
367
|
+
|
368
|
+
## Advanced Template Patterns
|
369
|
+
|
370
|
+
### Dynamic Role Assignment
|
371
|
+
|
372
|
+
```ruby
|
373
|
+
markup = <<~POML
|
374
|
+
<poml>
|
375
|
+
<role>
|
376
|
+
<if condition="{{user_level}} == 'beginner'">Friendly Tutor</if>
|
377
|
+
<if condition="{{user_level}} == 'intermediate'">Technical Mentor</if>
|
378
|
+
<if condition="{{user_level}} == 'expert'">Peer Reviewer</if>
|
379
|
+
</role>
|
380
|
+
|
381
|
+
<task>{{task_description}}</task>
|
382
|
+
|
383
|
+
<if condition="{{user_level}} == 'beginner'">
|
384
|
+
<hint>Provide detailed explanations and examples</hint>
|
385
|
+
</if>
|
386
|
+
<if condition="{{user_level}} == 'expert'">
|
387
|
+
<hint>Focus on edge cases and performance considerations</hint>
|
388
|
+
</if>
|
389
|
+
</poml>
|
390
|
+
POML
|
391
|
+
```
|
392
|
+
|
393
|
+
### Template Composition
|
394
|
+
|
395
|
+
```ruby
|
396
|
+
def create_review_prompt(review_type, language, complexity)
|
397
|
+
markup = <<~POML
|
398
|
+
<poml>
|
399
|
+
<meta variables='{"review_type": "#{review_type}", "language": "#{language}"}' />
|
400
|
+
|
401
|
+
<role>Senior {{language}} Developer</role>
|
402
|
+
<task>Perform {{review_type}} review</task>
|
403
|
+
|
404
|
+
<if condition="{{review_type}} == 'security'">
|
405
|
+
<p>Security Review Checklist:</p>
|
406
|
+
<list>
|
407
|
+
<item>Input validation and sanitization</item>
|
408
|
+
<item>Authentication and authorization</item>
|
409
|
+
<item>Data encryption and storage</item>
|
410
|
+
<item>Dependency vulnerabilities</item>
|
411
|
+
</list>
|
412
|
+
</if>
|
413
|
+
|
414
|
+
<if condition="{{review_type}} == 'performance'">
|
415
|
+
<p>Performance Review Checklist:</p>
|
416
|
+
<list>
|
417
|
+
<item>Algorithm complexity analysis</item>
|
418
|
+
<item>Database query optimization</item>
|
419
|
+
<item>Memory usage patterns</item>
|
420
|
+
<item>Caching strategies</item>
|
421
|
+
</list>
|
422
|
+
</if>
|
423
|
+
|
424
|
+
<if condition="{{review_type}} == 'code_quality'">
|
425
|
+
<p>Code Quality Review Checklist:</p>
|
426
|
+
<list>
|
427
|
+
<item>Code readability and maintainability</item>
|
428
|
+
<item>Design patterns and architecture</item>
|
429
|
+
<item>Test coverage and quality</item>
|
430
|
+
<item>Documentation completeness</item>
|
431
|
+
</list>
|
432
|
+
</if>
|
433
|
+
</poml>
|
434
|
+
POML
|
435
|
+
|
436
|
+
context = { 'complexity' => complexity }
|
437
|
+
Poml.process(markup: markup, context: context)
|
438
|
+
end
|
439
|
+
|
440
|
+
# Usage
|
441
|
+
security_prompt = create_review_prompt('security', 'Ruby', 'high')
|
442
|
+
performance_prompt = create_review_prompt('performance', 'Python', 'medium')
|
443
|
+
```
|
444
|
+
|
445
|
+
## Error Handling in Templates
|
446
|
+
|
447
|
+
### Safe Variable Access
|
448
|
+
|
449
|
+
```ruby
|
450
|
+
markup = <<~POML
|
451
|
+
<poml>
|
452
|
+
<role>Data Analyst</role>
|
453
|
+
<task>Generate report</task>
|
454
|
+
|
455
|
+
<if condition="{{report_data}}">
|
456
|
+
<p>Processing {{report_data.length}} records...</p>
|
457
|
+
|
458
|
+
<if condition="{{report_data.length}} > 1000">
|
459
|
+
<hint>Large dataset - consider sampling for initial analysis</hint>
|
460
|
+
</if>
|
461
|
+
</if>
|
462
|
+
|
463
|
+
<if condition="!{{report_data}}">
|
464
|
+
<p>⚠️ No data available for analysis</p>
|
465
|
+
</if>
|
466
|
+
</poml>
|
467
|
+
POML
|
468
|
+
```
|
469
|
+
|
470
|
+
### Default Values
|
471
|
+
|
472
|
+
```ruby
|
473
|
+
def safe_template_processing(markup, context = {})
|
474
|
+
# Provide default values
|
475
|
+
defaults = {
|
476
|
+
'environment' => 'development',
|
477
|
+
'debug_mode' => true,
|
478
|
+
'timeout' => 30
|
479
|
+
}
|
480
|
+
|
481
|
+
final_context = defaults.merge(context)
|
482
|
+
Poml.process(markup: markup, context: final_context)
|
483
|
+
end
|
484
|
+
```
|
485
|
+
|
486
|
+
## Performance Considerations
|
487
|
+
|
488
|
+
### Template Caching
|
489
|
+
|
490
|
+
```ruby
|
491
|
+
class TemplateProcessor
|
492
|
+
def initialize
|
493
|
+
@template_cache = {}
|
494
|
+
@result_cache = {}
|
495
|
+
end
|
496
|
+
|
497
|
+
def process_with_cache(template_key, markup, context)
|
498
|
+
# Cache compiled templates
|
499
|
+
@template_cache[template_key] ||= markup
|
500
|
+
|
501
|
+
# Cache results for identical context
|
502
|
+
cache_key = "#{template_key}:#{context.hash}"
|
503
|
+
@result_cache[cache_key] ||= Poml.process(
|
504
|
+
markup: @template_cache[template_key],
|
505
|
+
context: context
|
506
|
+
)
|
507
|
+
end
|
508
|
+
end
|
509
|
+
```
|
510
|
+
|
511
|
+
### Large Dataset Handling
|
512
|
+
|
513
|
+
```ruby
|
514
|
+
markup = <<~POML
|
515
|
+
<poml>
|
516
|
+
<role>Data Processor</role>
|
517
|
+
<task>Process dataset</task>
|
518
|
+
|
519
|
+
<if condition="{{items.length}} > 100">
|
520
|
+
<p>Large dataset detected ({{items.length}} items)</p>
|
521
|
+
<hint>Consider batch processing or pagination</hint>
|
522
|
+
</if>
|
523
|
+
|
524
|
+
<p>Sample items:</p>
|
525
|
+
<list>
|
526
|
+
<for variable="item" items="{{items}}">
|
527
|
+
<if condition="{{item.index}} < 5">
|
528
|
+
<item>{{item.name}} - {{item.value}}</item>
|
529
|
+
</if>
|
530
|
+
</for>
|
531
|
+
</list>
|
532
|
+
</poml>
|
533
|
+
POML
|
534
|
+
```
|
535
|
+
|
536
|
+
## Next Steps
|
537
|
+
|
538
|
+
- Learn about [Output Formats](output-formats.md) for different use cases
|
539
|
+
- Explore [Schema Components](components/schema-components.md) for structured data
|
540
|
+
- Check [Tool Registration](advanced/tool-registration.md) for AI tool integration
|