agent99 0.0.4 → 0.0.5

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 (92) hide show
  1. checksums.yaml +4 -4
  2. data/A2A_SPEC-dev.md +1829 -0
  3. data/CHANGELOG.md +31 -0
  4. data/COMMITS.md +196 -0
  5. data/DOCS.md +96 -0
  6. data/README.md +200 -78
  7. data/Rakefile +62 -0
  8. data/docs/AI/htm.md +215 -0
  9. data/docs/AI/htm.rb +141 -0
  10. data/docs/AI/htm_demo.db +0 -0
  11. data/docs/AI/notes_on_htm_implementation.md +1319 -0
  12. data/docs/AI/some_code.rb +692 -0
  13. data/docs/advanced-topics/a2a-protocol.md +13 -0
  14. data/docs/{control_actions.md → advanced-topics/control-actions.md} +2 -0
  15. data/docs/advanced-topics/model-context-protocol.md +4 -0
  16. data/docs/advanced-topics/multi-agent-processing.md +674 -0
  17. data/docs/agent-development/request-response-handling.md +512 -0
  18. data/docs/api-reference/agent99-base.md +463 -0
  19. data/docs/api-reference/message-clients.md +495 -0
  20. data/docs/api-reference/registry-client.md +470 -0
  21. data/docs/api-reference/schemas.md +518 -0
  22. data/docs/assets/css/custom.css +27 -0
  23. data/docs/assets/images/agent-lifecycle.svg +73 -0
  24. data/docs/assets/images/agent-registry-process.svg +86 -0
  25. data/docs/assets/images/agent-registry-processes.svg +114 -0
  26. data/docs/assets/images/agent-types-overview.svg +51 -0
  27. data/docs/assets/images/agent99-architecture.svg +85 -0
  28. data/docs/assets/images/agent99_logo.png +0 -0
  29. data/docs/assets/images/control-actions-state.svg +83 -0
  30. data/docs/assets/images/knowledge-graph.svg +77 -0
  31. data/docs/assets/images/message-processing-flow.svg +148 -0
  32. data/docs/assets/images/multi-agent-system.svg +66 -0
  33. data/docs/assets/images/proxy-pattern-sequence.svg +48 -0
  34. data/docs/assets/images/request-flow.svg +97 -0
  35. data/docs/assets/images/request-processing-lifecycle.svg +50 -0
  36. data/docs/assets/images/request-response-sequence.svg +39 -0
  37. data/docs/{agent_lifecycle.md → core-concepts/agent-lifecycle.md} +2 -0
  38. data/docs/core-concepts/agent-types.md +255 -0
  39. data/docs/{architecture.md → core-concepts/architecture.md} +5 -5
  40. data/docs/{what_is_an_agent.md → core-concepts/what-is-an-agent.md} +1 -1
  41. data/docs/diagrams/message-flow-sequence.svg +198 -0
  42. data/docs/diagrams/p2p-network-topology.svg +181 -0
  43. data/docs/diagrams/smart-transport-routing.svg +165 -0
  44. data/docs/diagrams/three-layer-architecture.svg +77 -0
  45. data/docs/diagrams/transport-extension-api.svg +309 -0
  46. data/docs/diagrams/transport-extension-architecture.svg +234 -0
  47. data/docs/diagrams/transport-selection-flowchart.svg +264 -0
  48. data/docs/examples/advanced-examples.md +951 -0
  49. data/docs/examples/basic-examples.md +268 -0
  50. data/docs/{agent_registry_processes.md → framework-components/agent-registry.md} +1 -1
  51. data/docs/{message_processing.md → framework-components/message-processing.md} +3 -1
  52. data/docs/getting-started/basic-example.md +306 -0
  53. data/docs/getting-started/installation.md +160 -0
  54. data/docs/getting-started/overview.md +64 -0
  55. data/docs/getting-started/quick-start.md +179 -0
  56. data/docs/index.md +97 -0
  57. data/examples/DEMO.md +148 -0
  58. data/examples/README.md +50 -0
  59. data/examples/bad_agent.rb +32 -0
  60. data/examples/registry.rb +0 -8
  61. data/examples/run_demo.rb +433 -0
  62. data/lib/agent99/amqp_message_client.rb +2 -2
  63. data/lib/agent99/base.rb +1 -1
  64. data/lib/agent99/message_processing.rb +6 -12
  65. data/lib/agent99/registry_client.rb +4 -1
  66. data/lib/agent99/version.rb +1 -1
  67. data/lib/agent99.rb +1 -1
  68. data/mkdocs.yml +195 -0
  69. data/p2p_plan.md +533 -0
  70. data/p2p_roadmap.md +299 -0
  71. data/registry_plan.md +1818 -0
  72. metadata +89 -32
  73. data/docs/README.md +0 -57
  74. data/docs/diagrams/agent_registry_processes.dot +0 -42
  75. data/docs/diagrams/agent_registry_processes.png +0 -0
  76. data/docs/diagrams/high_level_architecture.dot +0 -26
  77. data/docs/diagrams/high_level_architecture.png +0 -0
  78. data/docs/diagrams/request_flow.dot +0 -42
  79. data/docs/diagrams/request_flow.png +0 -0
  80. /data/docs/{advanced_features.md → advanced-topics/advanced-features.md} +0 -0
  81. /data/docs/{extending_the_framework.md → advanced-topics/extending-the-framework.md} +0 -0
  82. /data/docs/{custom_agent_implementation.md → agent-development/custom-agent-implementation.md} +0 -0
  83. /data/docs/{error_handling_and_logging.md → agent-development/error-handling-and-logging.md} +0 -0
  84. /data/docs/{schema_definition.md → agent-development/schema-definition.md} +0 -0
  85. /data/docs/{api_reference.md → api-reference/overview.md} +0 -0
  86. /data/docs/{agent_discovery.md → framework-components/agent-discovery.md} +0 -0
  87. /data/docs/{messaging_system.md → framework-components/messaging-system.md} +0 -0
  88. /data/docs/{breaking_change_v0.0.4.md → operations/breaking-changes.md} +0 -0
  89. /data/docs/{configuration.md → operations/configuration.md} +0 -0
  90. /data/docs/{preformance_considerations.md → operations/performance-considerations.md} +0 -0
  91. /data/docs/{security.md → operations/security.md} +0 -0
  92. /data/docs/{troubleshooting.md → operations/troubleshooting.md} +0 -0
@@ -0,0 +1,518 @@
1
+ # Schemas API
2
+
3
+ Agent99 uses JSON Schema validation to ensure data integrity in agent communication. This document covers the schema system, built-in schemas, and how to create custom validation schemas.
4
+
5
+ ## Overview
6
+
7
+ Agent99 leverages `simple_json_schema_builder` to define and validate request/response schemas, providing:
8
+
9
+ - **Type safety** - Ensure data types match expectations
10
+ - **Required field validation** - Enforce mandatory fields
11
+ - **Format validation** - Validate emails, URLs, dates, etc.
12
+ - **Custom validation** - Define business-specific rules
13
+ - **Auto-documentation** - Schemas serve as API documentation
14
+
15
+ ## Built-in Schemas
16
+
17
+ ### Header Schema
18
+
19
+ All Agent99 messages include a standard header:
20
+
21
+ ```ruby
22
+ class Agent99::HeaderSchema < SimpleJsonSchemaBuilder::Base
23
+ object do
24
+ string :request_id, required: true, format: :uuid
25
+ string :agent_name, required: true
26
+ string :correlation_id, format: :uuid
27
+ string :timestamp, required: true, format: :datetime
28
+ string :reply_to
29
+ object :metadata do
30
+ # Additional metadata fields
31
+ end
32
+ end
33
+ end
34
+ ```
35
+
36
+ **Example usage:**
37
+ ```ruby
38
+ header = {
39
+ request_id: SecureRandom.uuid,
40
+ agent_name: "CalculatorAgent",
41
+ correlation_id: SecureRandom.uuid,
42
+ timestamp: Time.now.iso8601,
43
+ metadata: { version: "1.0.0" }
44
+ }
45
+
46
+ # Validate header
47
+ Agent99::HeaderSchema.new.validate!(header)
48
+ ```
49
+
50
+ ### Basic Message Schema
51
+
52
+ Base schema for all agent messages:
53
+
54
+ ```ruby
55
+ class Agent99::MessageSchema < SimpleJsonSchemaBuilder::Base
56
+ object do
57
+ object :header, schema: Agent99::HeaderSchema, required: true
58
+ # Payload varies by message type
59
+ end
60
+ end
61
+ ```
62
+
63
+ ## Creating Custom Schemas
64
+
65
+ ### Simple Request Schema
66
+
67
+ ```ruby
68
+ require 'simple_json_schema_builder'
69
+
70
+ class GreetingRequest < SimpleJsonSchemaBuilder::Base
71
+ object do
72
+ object :header, schema: Agent99::HeaderSchema
73
+ string :name, required: true, minLength: 1, maxLength: 100
74
+ string :language, enum: %w[en es fr de], default: 'en'
75
+ boolean :formal, default: false
76
+ end
77
+ end
78
+
79
+ # Usage in agent
80
+ class GreeterAgent < Agent99::Base
81
+ def info
82
+ {
83
+ name: self.class.to_s,
84
+ type: :server,
85
+ capabilities: ['greeting'],
86
+ request_schema: GreetingRequest.schema
87
+ }
88
+ end
89
+
90
+ def process_request(payload)
91
+ # Payload is automatically validated against schema
92
+ name = payload[:name]
93
+ language = payload[:language] || 'en'
94
+ formal = payload[:formal] || false
95
+
96
+ greeting = generate_greeting(name, language, formal)
97
+ send_response(message: greeting)
98
+ end
99
+ end
100
+ ```
101
+
102
+ ### Complex Schema with Nested Objects
103
+
104
+ ```ruby
105
+ class OrderRequest < SimpleJsonSchemaBuilder::Base
106
+ object do
107
+ object :header, schema: Agent99::HeaderSchema
108
+
109
+ string :customer_id, required: true, format: :uuid
110
+
111
+ array :items, required: true, minItems: 1 do
112
+ object do
113
+ string :product_id, required: true, format: :uuid
114
+ integer :quantity, required: true, minimum: 1
115
+ number :unit_price, required: true, minimum: 0
116
+ object :metadata do
117
+ string :color
118
+ string :size, enum: %w[XS S M L XL XXL]
119
+ boolean :gift_wrap, default: false
120
+ end
121
+ end
122
+ end
123
+
124
+ object :shipping_address, required: true do
125
+ string :street, required: true
126
+ string :city, required: true
127
+ string :state, required: true
128
+ string :zip_code, required: true, pattern: '^\d{5}(-\d{4})?$'
129
+ string :country, required: true, enum: %w[US CA MX]
130
+ end
131
+
132
+ object :payment do
133
+ string :method, required: true, enum: %w[credit_card paypal bank_transfer]
134
+ string :token, required: true
135
+ number :amount, required: true, minimum: 0
136
+ end
137
+ end
138
+ end
139
+ ```
140
+
141
+ ### Response Schema
142
+
143
+ ```ruby
144
+ class OrderResponse < SimpleJsonSchemaBuilder::Base
145
+ object do
146
+ object :header, schema: Agent99::HeaderSchema
147
+
148
+ string :order_id, required: true, format: :uuid
149
+ string :status, required: true, enum: %w[pending confirmed processing shipped delivered cancelled]
150
+ number :total_amount, required: true, minimum: 0
151
+ string :estimated_delivery, format: :datetime
152
+
153
+ array :items do
154
+ object do
155
+ string :product_id, required: true
156
+ integer :quantity, required: true
157
+ number :line_total, required: true
158
+ string :status, enum: %w[available backordered discontinued]
159
+ end
160
+ end
161
+
162
+ object :tracking do
163
+ string :carrier
164
+ string :tracking_number
165
+ string :tracking_url, format: :uri
166
+ end
167
+ end
168
+ end
169
+ ```
170
+
171
+ ## Schema Validation
172
+
173
+ ### Automatic Validation
174
+
175
+ Agent99 automatically validates incoming requests against defined schemas:
176
+
177
+ ```ruby
178
+ class ValidatingAgent < Agent99::Base
179
+ def info
180
+ {
181
+ name: self.class.to_s,
182
+ type: :server,
183
+ capabilities: ['validation_example'],
184
+ request_schema: OrderRequest.schema,
185
+ response_schema: OrderResponse.schema
186
+ }
187
+ end
188
+
189
+ def process_request(payload)
190
+ # payload is already validated by framework
191
+
192
+ order_id = SecureRandom.uuid
193
+ total = calculate_total(payload[:items])
194
+
195
+ response = {
196
+ order_id: order_id,
197
+ status: 'confirmed',
198
+ total_amount: total,
199
+ estimated_delivery: (Time.now + 7.days).iso8601,
200
+ items: process_items(payload[:items])
201
+ }
202
+
203
+ # Response will be validated before sending
204
+ send_response(response)
205
+ end
206
+ end
207
+ ```
208
+
209
+ ### Manual Validation
210
+
211
+ For custom validation scenarios:
212
+
213
+ ```ruby
214
+ def process_request(payload)
215
+ # Additional business logic validation
216
+ begin
217
+ validate_business_rules(payload)
218
+ rescue ValidationError => e
219
+ return send_error("Business validation failed: #{e.message}", "BUSINESS_VALIDATION_ERROR")
220
+ end
221
+
222
+ # Continue processing...
223
+ end
224
+
225
+ private
226
+
227
+ def validate_business_rules(payload)
228
+ customer_id = payload[:customer_id]
229
+
230
+ # Check customer exists and is active
231
+ customer = Customer.find(customer_id)
232
+ raise ValidationError, "Customer not found" unless customer
233
+ raise ValidationError, "Customer account suspended" unless customer.active?
234
+
235
+ # Validate inventory
236
+ payload[:items].each do |item|
237
+ product = Product.find(item[:product_id])
238
+ raise ValidationError, "Product #{item[:product_id]} not available" unless product&.available?
239
+ raise ValidationError, "Insufficient inventory for #{product.name}" if product.stock < item[:quantity]
240
+ end
241
+ end
242
+ ```
243
+
244
+ ## Advanced Schema Features
245
+
246
+ ### Conditional Schemas
247
+
248
+ ```ruby
249
+ class ConditionalRequest < SimpleJsonSchemaBuilder::Base
250
+ object do
251
+ object :header, schema: Agent99::HeaderSchema
252
+ string :operation, required: true, enum: %w[create update delete]
253
+
254
+ # Conditional fields based on operation
255
+ if_property :operation, equals: 'create' do
256
+ string :name, required: true
257
+ string :email, required: true, format: :email
258
+ end
259
+
260
+ if_property :operation, equals: 'update' do
261
+ string :id, required: true, format: :uuid
262
+ string :name
263
+ string :email, format: :email
264
+ end
265
+
266
+ if_property :operation, equals: 'delete' do
267
+ string :id, required: true, format: :uuid
268
+ end
269
+ end
270
+ end
271
+ ```
272
+
273
+ ### Custom Format Validators
274
+
275
+ ```ruby
276
+ # Define custom formats
277
+ SimpleJsonSchemaBuilder.configure do |config|
278
+ config.add_format :phone_number, /^\+?[\d\s\-\(\)]+$/
279
+ config.add_format :product_sku, /^[A-Z]{2}\d{6}$/
280
+ end
281
+
282
+ class ProductRequest < SimpleJsonSchemaBuilder::Base
283
+ object do
284
+ object :header, schema: Agent99::HeaderSchema
285
+ string :sku, required: true, format: :product_sku
286
+ string :support_phone, format: :phone_number
287
+ end
288
+ end
289
+ ```
290
+
291
+ ### Schema Composition
292
+
293
+ ```ruby
294
+ # Base schemas for reuse
295
+ class AddressSchema < SimpleJsonSchemaBuilder::Base
296
+ object do
297
+ string :street, required: true
298
+ string :city, required: true
299
+ string :state, required: true
300
+ string :zip_code, required: true
301
+ string :country, required: true
302
+ end
303
+ end
304
+
305
+ class PersonSchema < SimpleJsonSchemaBuilder::Base
306
+ object do
307
+ string :first_name, required: true
308
+ string :last_name, required: true
309
+ string :email, format: :email
310
+ string :phone, format: :phone_number
311
+ end
312
+ end
313
+
314
+ # Compose into larger schema
315
+ class CustomerRequest < SimpleJsonSchemaBuilder::Base
316
+ object do
317
+ object :header, schema: Agent99::HeaderSchema
318
+ object :personal_info, schema: PersonSchema, required: true
319
+ object :billing_address, schema: AddressSchema, required: true
320
+ object :shipping_address, schema: AddressSchema
321
+ end
322
+ end
323
+ ```
324
+
325
+ ## Schema Testing
326
+
327
+ ### Unit Tests
328
+
329
+ ```ruby
330
+ require 'minitest/autorun'
331
+
332
+ class TestOrderSchema < Minitest::Test
333
+ def test_valid_order_request
334
+ valid_payload = {
335
+ header: {
336
+ request_id: SecureRandom.uuid,
337
+ agent_name: "TestAgent",
338
+ timestamp: Time.now.iso8601
339
+ },
340
+ customer_id: SecureRandom.uuid,
341
+ items: [
342
+ {
343
+ product_id: SecureRandom.uuid,
344
+ quantity: 2,
345
+ unit_price: 29.99
346
+ }
347
+ ],
348
+ shipping_address: {
349
+ street: "123 Main St",
350
+ city: "Anytown",
351
+ state: "CA",
352
+ zip_code: "12345",
353
+ country: "US"
354
+ }
355
+ }
356
+
357
+ schema = OrderRequest.new
358
+ assert schema.valid?(valid_payload)
359
+ end
360
+
361
+ def test_invalid_order_request
362
+ invalid_payload = {
363
+ header: {
364
+ request_id: "not-a-uuid", # Invalid format
365
+ agent_name: "TestAgent",
366
+ timestamp: Time.now.iso8601
367
+ },
368
+ items: [], # Empty array not allowed
369
+ shipping_address: {
370
+ # Missing required fields
371
+ street: "123 Main St"
372
+ }
373
+ }
374
+
375
+ schema = OrderRequest.new
376
+ refute schema.valid?(invalid_payload)
377
+
378
+ errors = schema.validate(invalid_payload)
379
+ assert errors.any? { |e| e.include?("request_id") }
380
+ assert errors.any? { |e| e.include?("items") }
381
+ end
382
+ end
383
+ ```
384
+
385
+ ### Schema Documentation Generation
386
+
387
+ ```ruby
388
+ class SchemaDocGenerator
389
+ def self.generate_docs(schema_class, output_file)
390
+ schema = schema_class.schema
391
+
392
+ docs = {
393
+ title: schema_class.name,
394
+ description: extract_description(schema),
395
+ properties: extract_properties(schema),
396
+ required: schema.dig('required') || [],
397
+ examples: generate_examples(schema)
398
+ }
399
+
400
+ File.write(output_file, docs.to_json)
401
+ end
402
+
403
+ private
404
+
405
+ def self.extract_properties(schema)
406
+ schema.dig('properties') || {}
407
+ end
408
+
409
+ def self.generate_examples(schema)
410
+ # Generate example data based on schema
411
+ example_generator = JsonSchemaExampleGenerator.new(schema)
412
+ example_generator.generate
413
+ end
414
+ end
415
+
416
+ # Generate documentation
417
+ SchemaDocGenerator.generate_docs(OrderRequest, 'docs/schemas/order_request.json')
418
+ ```
419
+
420
+ ## Error Handling
421
+
422
+ ### Schema Validation Errors
423
+
424
+ ```ruby
425
+ class OrderAgent < Agent99::Base
426
+ def process_request(payload)
427
+ # Framework automatically validates, but you can catch validation errors
428
+ begin
429
+ validate_additional_rules(payload)
430
+ rescue Agent99::SchemaValidationError => e
431
+ return send_error(
432
+ "Validation failed: #{e.message}",
433
+ "SCHEMA_VALIDATION_ERROR",
434
+ {
435
+ errors: e.validation_errors,
436
+ schema_version: "1.0.0"
437
+ }
438
+ )
439
+ end
440
+
441
+ # Process valid request...
442
+ end
443
+
444
+ private
445
+
446
+ def validate_additional_rules(payload)
447
+ # Custom validation beyond schema
448
+ if payload[:items].sum { |item| item[:quantity] } > 100
449
+ raise Agent99::SchemaValidationError, "Order too large (max 100 items)"
450
+ end
451
+ end
452
+ end
453
+ ```
454
+
455
+ ### Schema Version Management
456
+
457
+ ```ruby
458
+ class VersionedSchema
459
+ SCHEMA_VERSIONS = {
460
+ "1.0" => OrderRequestV1,
461
+ "1.1" => OrderRequestV11,
462
+ "2.0" => OrderRequestV2
463
+ }.freeze
464
+
465
+ def self.validate(payload, version = "2.0")
466
+ schema_class = SCHEMA_VERSIONS[version]
467
+ raise ArgumentError, "Unsupported schema version: #{version}" unless schema_class
468
+
469
+ schema = schema_class.new
470
+ unless schema.valid?(payload)
471
+ errors = schema.validate(payload)
472
+ raise Agent99::SchemaValidationError, "Validation failed: #{errors.join(', ')}"
473
+ end
474
+
475
+ payload
476
+ end
477
+ end
478
+
479
+ # Usage in agent
480
+ def process_request(payload)
481
+ schema_version = header_value('schema_version') || "2.0"
482
+ validated_payload = VersionedSchema.validate(payload, schema_version)
483
+
484
+ # Process with validated payload...
485
+ end
486
+ ```
487
+
488
+ ## Best Practices
489
+
490
+ ### 1. Schema Design
491
+ - **Be explicit**: Define all expected fields and types
492
+ - **Use descriptive names**: Clear field names and descriptions
493
+ - **Version your schemas**: Plan for schema evolution
494
+ - **Provide examples**: Include example payloads in documentation
495
+
496
+ ### 2. Validation Strategy
497
+ - **Validate early**: Catch errors as soon as possible
498
+ - **Provide clear errors**: Include helpful validation messages
499
+ - **Use business validation**: Complement schema validation with business rules
500
+ - **Test thoroughly**: Cover valid and invalid cases
501
+
502
+ ### 3. Performance
503
+ - **Cache compiled schemas**: Don't recompile schemas on every request
504
+ - **Validate incrementally**: Only validate changed portions when possible
505
+ - **Monitor validation time**: Track validation performance
506
+ - **Use appropriate depth**: Don't over-validate in performance-critical paths
507
+
508
+ ### 4. Evolution
509
+ - **Backward compatibility**: Plan for schema changes
510
+ - **Optional fields**: Use optional fields for new features
511
+ - **Deprecation strategy**: Plan how to retire old schema versions
512
+ - **Migration support**: Provide tools to migrate between schema versions
513
+
514
+ ## Next Steps
515
+
516
+ - **[Agent99::Base](agent99-base.md)** - Core agent class reference
517
+ - **[Message Clients](message-clients.md)** - Message broker APIs
518
+ - **[Schema Definition](../agent-development/schema-definition.md)** - Detailed schema guide
@@ -0,0 +1,27 @@
1
+ /* Custom CSS for Agent99 Documentation */
2
+
3
+ /* Header background - dark red */
4
+ .md-header {
5
+ background-color: #8B0000 !important; /* Dark red color */
6
+ }
7
+
8
+ /* Ensure navigation tabs have proper contrast with dark red background */
9
+ .md-header__nav {
10
+ background-color: #8B0000 !important;
11
+ }
12
+
13
+ /* Tab bar under header - slightly darker red */
14
+ .md-tabs {
15
+ background-color: #660000 !important;
16
+ }
17
+
18
+ /* Active tab styling */
19
+ .md-tabs__link--active {
20
+ color: #ffffff !important;
21
+ border-bottom: 2px solid #ffffff;
22
+ }
23
+
24
+ /* Hover state for tabs */
25
+ .md-tabs__link:hover {
26
+ color: #ffcccc !important;
27
+ }
@@ -0,0 +1,73 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 400" style="background: transparent;">
2
+ <defs>
3
+ <marker id="arrow-life" markerWidth="10" markerHeight="10" refX="9" refY="5" orient="auto">
4
+ <path d="M0,0 L10,5 L0,10 L5,5 z" fill="#66b3ff"/>
5
+ </marker>
6
+ <filter id="shadow">
7
+ <feGaussianBlur in="SourceAlpha" stdDeviation="3"/>
8
+ <feOffset dx="2" dy="2" result="offsetblur"/>
9
+ <feComponentTransfer>
10
+ <feFuncA type="linear" slope="0.3"/>
11
+ </feComponentTransfer>
12
+ <feMerge>
13
+ <feMergeNode/>
14
+ <feMergeNode in="SourceGraphic"/>
15
+ </feMerge>
16
+ </filter>
17
+ </defs>
18
+
19
+ <!-- Title -->
20
+ <text x="400" y="30" text-anchor="middle" font-family="monospace" font-size="18" fill="#e0e0e0" font-weight="bold">Agent Lifecycle State Machine</text>
21
+
22
+ <!-- States -->
23
+ <!-- Created -->
24
+ <circle cx="120" cy="200" r="50" fill="#2a2a3e" stroke="#66b3ff" stroke-width="3" filter="url(#shadow)"/>
25
+ <text x="120" y="200" text-anchor="middle" font-family="monospace" font-size="14" fill="#99ccff" font-weight="bold">Created</text>
26
+ <text x="120" y="220" text-anchor="middle" font-family="monospace" font-size="10" fill="#66b3ff">new()</text>
27
+
28
+ <!-- Initialized -->
29
+ <circle cx="320" cy="200" r="50" fill="#2a2a3e" stroke="#66ff99" stroke-width="3" filter="url(#shadow)"/>
30
+ <text x="320" y="200" text-anchor="middle" font-family="monospace" font-size="14" fill="#99ffcc" font-weight="bold">Initialized</text>
31
+ <text x="320" y="220" text-anchor="middle" font-family="monospace" font-size="10" fill="#66ff99">init() called</text>
32
+
33
+ <!-- Running -->
34
+ <circle cx="520" cy="200" r="50" fill="#2a2a3e" stroke="#ffcc66" stroke-width="3" filter="url(#shadow)"/>
35
+ <text x="520" y="200" text-anchor="middle" font-family="monospace" font-size="14" fill="#ffdd99" font-weight="bold">Running</text>
36
+ <text x="520" y="220" text-anchor="middle" font-family="monospace" font-size="10" fill="#ffcc66">Processing</text>
37
+
38
+ <!-- Shutdown -->
39
+ <circle cx="700" cy="200" r="50" fill="#2a2a3e" stroke="#ff6666" stroke-width="3" filter="url(#shadow)"/>
40
+ <text x="700" y="200" text-anchor="middle" font-family="monospace" font-size="14" fill="#ff9999" font-weight="bold">Shutdown</text>
41
+ <text x="700" y="220" text-anchor="middle" font-family="monospace" font-size="10" fill="#ff6666">fini() called</text>
42
+
43
+ <!-- Transitions -->
44
+ <!-- Created to Initialized -->
45
+ <path d="M 170 200 L 270 200" stroke="#66b3ff" stroke-width="2" marker-end="url(#arrow-life)"/>
46
+ <text x="220" y="190" text-anchor="middle" font-family="monospace" font-size="11" fill="#99ccff">initialize()</text>
47
+
48
+ <!-- Initialized to Running -->
49
+ <path d="M 370 200 L 470 200" stroke="#66ff99" stroke-width="2" marker-end="url(#arrow-life)"/>
50
+ <text x="420" y="190" text-anchor="middle" font-family="monospace" font-size="11" fill="#99ffcc">start()</text>
51
+
52
+ <!-- Running to Shutdown -->
53
+ <path d="M 570 200 L 650 200" stroke="#ffcc66" stroke-width="2" marker-end="url(#arrow-life)"/>
54
+ <text x="610" y="190" text-anchor="middle" font-family="monospace" font-size="11" fill="#ffdd99">stop()</text>
55
+
56
+ <!-- Error paths -->
57
+ <!-- Created to Shutdown (error) -->
58
+ <path d="M 120 250 Q 400 350 700 250" stroke="#ff6666" stroke-width="1.5" stroke-dasharray="5,3" marker-end="url(#arrow-life)" opacity="0.6"/>
59
+ <text x="400" y="340" text-anchor="middle" font-family="monospace" font-size="10" fill="#ff9999">Error/Abort</text>
60
+
61
+ <!-- Initialized to Shutdown (error) -->
62
+ <path d="M 320 250 Q 500 320 700 250" stroke="#ff6666" stroke-width="1.5" stroke-dasharray="5,3" marker-end="url(#arrow-life)" opacity="0.6"/>
63
+
64
+ <!-- Self-loop on Running -->
65
+ <path d="M 520 150 Q 580 100 520 150" stroke="#ffcc66" stroke-width="1.5" marker-end="url(#arrow-life)" fill="none"/>
66
+ <text x="550" y="95" text-anchor="middle" font-family="monospace" font-size="10" fill="#ffdd99">process_request()</text>
67
+
68
+ <!-- Phase labels -->
69
+ <text x="120" y="100" text-anchor="middle" font-family="monospace" font-size="12" fill="#666" font-style="italic">Setup</text>
70
+ <text x="320" y="100" text-anchor="middle" font-family="monospace" font-size="12" fill="#666" font-style="italic">Configuration</text>
71
+ <text x="520" y="100" text-anchor="middle" font-family="monospace" font-size="12" fill="#666" font-style="italic">Operation</text>
72
+ <text x="700" y="100" text-anchor="middle" font-family="monospace" font-size="12" fill="#666" font-style="italic">Cleanup</text>
73
+ </svg>