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.
- checksums.yaml +4 -4
- data/A2A_SPEC-dev.md +1829 -0
- data/CHANGELOG.md +31 -0
- data/COMMITS.md +196 -0
- data/DOCS.md +96 -0
- data/README.md +200 -78
- data/Rakefile +62 -0
- data/docs/AI/htm.md +215 -0
- data/docs/AI/htm.rb +141 -0
- data/docs/AI/htm_demo.db +0 -0
- data/docs/AI/notes_on_htm_implementation.md +1319 -0
- data/docs/AI/some_code.rb +692 -0
- data/docs/advanced-topics/a2a-protocol.md +13 -0
- data/docs/{control_actions.md → advanced-topics/control-actions.md} +2 -0
- data/docs/advanced-topics/model-context-protocol.md +4 -0
- data/docs/advanced-topics/multi-agent-processing.md +674 -0
- data/docs/agent-development/request-response-handling.md +512 -0
- data/docs/api-reference/agent99-base.md +463 -0
- data/docs/api-reference/message-clients.md +495 -0
- data/docs/api-reference/registry-client.md +470 -0
- data/docs/api-reference/schemas.md +518 -0
- data/docs/assets/css/custom.css +27 -0
- data/docs/assets/images/agent-lifecycle.svg +73 -0
- data/docs/assets/images/agent-registry-process.svg +86 -0
- data/docs/assets/images/agent-registry-processes.svg +114 -0
- data/docs/assets/images/agent-types-overview.svg +51 -0
- data/docs/assets/images/agent99-architecture.svg +85 -0
- data/docs/assets/images/agent99_logo.png +0 -0
- data/docs/assets/images/control-actions-state.svg +83 -0
- data/docs/assets/images/knowledge-graph.svg +77 -0
- data/docs/assets/images/message-processing-flow.svg +148 -0
- data/docs/assets/images/multi-agent-system.svg +66 -0
- data/docs/assets/images/proxy-pattern-sequence.svg +48 -0
- data/docs/assets/images/request-flow.svg +97 -0
- data/docs/assets/images/request-processing-lifecycle.svg +50 -0
- data/docs/assets/images/request-response-sequence.svg +39 -0
- data/docs/{agent_lifecycle.md → core-concepts/agent-lifecycle.md} +2 -0
- data/docs/core-concepts/agent-types.md +255 -0
- data/docs/{architecture.md → core-concepts/architecture.md} +5 -5
- data/docs/{what_is_an_agent.md → core-concepts/what-is-an-agent.md} +1 -1
- data/docs/diagrams/message-flow-sequence.svg +198 -0
- data/docs/diagrams/p2p-network-topology.svg +181 -0
- data/docs/diagrams/smart-transport-routing.svg +165 -0
- data/docs/diagrams/three-layer-architecture.svg +77 -0
- data/docs/diagrams/transport-extension-api.svg +309 -0
- data/docs/diagrams/transport-extension-architecture.svg +234 -0
- data/docs/diagrams/transport-selection-flowchart.svg +264 -0
- data/docs/examples/advanced-examples.md +951 -0
- data/docs/examples/basic-examples.md +268 -0
- data/docs/{agent_registry_processes.md → framework-components/agent-registry.md} +1 -1
- data/docs/{message_processing.md → framework-components/message-processing.md} +3 -1
- data/docs/getting-started/basic-example.md +306 -0
- data/docs/getting-started/installation.md +160 -0
- data/docs/getting-started/overview.md +64 -0
- data/docs/getting-started/quick-start.md +179 -0
- data/docs/index.md +97 -0
- data/examples/DEMO.md +148 -0
- data/examples/README.md +50 -0
- data/examples/bad_agent.rb +32 -0
- data/examples/registry.rb +0 -8
- data/examples/run_demo.rb +433 -0
- data/lib/agent99/amqp_message_client.rb +2 -2
- data/lib/agent99/base.rb +1 -1
- data/lib/agent99/message_processing.rb +6 -12
- data/lib/agent99/registry_client.rb +4 -1
- data/lib/agent99/version.rb +1 -1
- data/lib/agent99.rb +1 -1
- data/mkdocs.yml +195 -0
- data/p2p_plan.md +533 -0
- data/p2p_roadmap.md +299 -0
- data/registry_plan.md +1818 -0
- metadata +89 -32
- data/docs/README.md +0 -57
- data/docs/diagrams/agent_registry_processes.dot +0 -42
- data/docs/diagrams/agent_registry_processes.png +0 -0
- data/docs/diagrams/high_level_architecture.dot +0 -26
- data/docs/diagrams/high_level_architecture.png +0 -0
- data/docs/diagrams/request_flow.dot +0 -42
- data/docs/diagrams/request_flow.png +0 -0
- /data/docs/{advanced_features.md → advanced-topics/advanced-features.md} +0 -0
- /data/docs/{extending_the_framework.md → advanced-topics/extending-the-framework.md} +0 -0
- /data/docs/{custom_agent_implementation.md → agent-development/custom-agent-implementation.md} +0 -0
- /data/docs/{error_handling_and_logging.md → agent-development/error-handling-and-logging.md} +0 -0
- /data/docs/{schema_definition.md → agent-development/schema-definition.md} +0 -0
- /data/docs/{api_reference.md → api-reference/overview.md} +0 -0
- /data/docs/{agent_discovery.md → framework-components/agent-discovery.md} +0 -0
- /data/docs/{messaging_system.md → framework-components/messaging-system.md} +0 -0
- /data/docs/{breaking_change_v0.0.4.md → operations/breaking-changes.md} +0 -0
- /data/docs/{configuration.md → operations/configuration.md} +0 -0
- /data/docs/{preformance_considerations.md → operations/performance-considerations.md} +0 -0
- /data/docs/{security.md → operations/security.md} +0 -0
- /data/docs/{troubleshooting.md → operations/troubleshooting.md} +0 -0
@@ -0,0 +1,495 @@
|
|
1
|
+
# Message Clients API
|
2
|
+
|
3
|
+
Agent99 supports multiple message broker clients for different messaging protocols. This document covers the APIs and configuration for each supported client type.
|
4
|
+
|
5
|
+
## Overview
|
6
|
+
|
7
|
+
Agent99 currently supports three message client types:
|
8
|
+
|
9
|
+
- **NATS** - High-performance, cloud-native messaging (recommended)
|
10
|
+
- **AMQP** - Advanced Message Queuing Protocol via RabbitMQ
|
11
|
+
- **TCP** - Simple TCP-based messaging for testing
|
12
|
+
|
13
|
+
## Client Selection
|
14
|
+
|
15
|
+
The message client is automatically selected based on configuration:
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
# Environment variable
|
19
|
+
ENV['AGENT99_MESSAGE_CLIENT'] = 'nats' # or 'amqp', 'tcp'
|
20
|
+
|
21
|
+
# Or via agent initialization
|
22
|
+
agent = MyAgent.new(message_client: 'nats')
|
23
|
+
```
|
24
|
+
|
25
|
+
## NATS Client
|
26
|
+
|
27
|
+
### Configuration
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
# Environment variables
|
31
|
+
ENV['NATS_URL'] = 'nats://localhost:4222'
|
32
|
+
ENV['NATS_USERNAME'] = 'agent99' # optional
|
33
|
+
ENV['NATS_PASSWORD'] = 'secret' # optional
|
34
|
+
|
35
|
+
# Or programmatically
|
36
|
+
nats_config = {
|
37
|
+
servers: ['nats://localhost:4222'],
|
38
|
+
username: 'agent99',
|
39
|
+
password: 'secret',
|
40
|
+
timeout: 30,
|
41
|
+
reconnect_attempts: 10
|
42
|
+
}
|
43
|
+
|
44
|
+
client = Agent99::MessageClients::NatsClient.new(nats_config)
|
45
|
+
```
|
46
|
+
|
47
|
+
### Connection Options
|
48
|
+
|
49
|
+
| Option | Type | Default | Description |
|
50
|
+
|--------|------|---------|-------------|
|
51
|
+
| `servers` | Array | `['nats://localhost:4222']` | NATS server URLs |
|
52
|
+
| `username` | String | `nil` | Authentication username |
|
53
|
+
| `password` | String | `nil` | Authentication password |
|
54
|
+
| `timeout` | Integer | 30 | Connection timeout (seconds) |
|
55
|
+
| `reconnect_attempts` | Integer | 10 | Reconnection attempts |
|
56
|
+
| `max_reconnect_attempts` | Integer | -1 | Max reconnection attempts (-1 = unlimited) |
|
57
|
+
|
58
|
+
### Usage Example
|
59
|
+
|
60
|
+
```ruby
|
61
|
+
class NatsAgent < Agent99::Base
|
62
|
+
def initialize
|
63
|
+
super(message_client: 'nats')
|
64
|
+
end
|
65
|
+
|
66
|
+
def info
|
67
|
+
{
|
68
|
+
name: self.class.to_s,
|
69
|
+
type: :server,
|
70
|
+
capabilities: ['nats_example']
|
71
|
+
}
|
72
|
+
end
|
73
|
+
|
74
|
+
def process_request(payload)
|
75
|
+
# NATS-specific features can be accessed via client
|
76
|
+
subject = current_message_subject
|
77
|
+
reply_to = current_reply_subject
|
78
|
+
|
79
|
+
logger.info "Received on subject: #{subject}"
|
80
|
+
|
81
|
+
send_response(
|
82
|
+
message: "Processed via NATS",
|
83
|
+
subject: subject,
|
84
|
+
timestamp: Time.now.iso8601
|
85
|
+
)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
```
|
89
|
+
|
90
|
+
## AMQP Client (RabbitMQ)
|
91
|
+
|
92
|
+
### Configuration
|
93
|
+
|
94
|
+
```ruby
|
95
|
+
# Environment variables
|
96
|
+
ENV['RABBITMQ_URL'] = 'amqp://localhost:5672'
|
97
|
+
ENV['RABBITMQ_USERNAME'] = 'guest' # optional
|
98
|
+
ENV['RABBITMQ_PASSWORD'] = 'guest' # optional
|
99
|
+
|
100
|
+
# Or programmatically
|
101
|
+
amqp_config = {
|
102
|
+
url: 'amqp://localhost:5672',
|
103
|
+
username: 'agent99',
|
104
|
+
password: 'secret',
|
105
|
+
vhost: '/',
|
106
|
+
timeout: 30,
|
107
|
+
heartbeat: 30
|
108
|
+
}
|
109
|
+
|
110
|
+
client = Agent99::MessageClients::AmqpClient.new(amqp_config)
|
111
|
+
```
|
112
|
+
|
113
|
+
### Connection Options
|
114
|
+
|
115
|
+
| Option | Type | Default | Description |
|
116
|
+
|--------|------|---------|-------------|
|
117
|
+
| `url` | String | `amqp://localhost:5672` | RabbitMQ connection URL |
|
118
|
+
| `username` | String | `guest` | Authentication username |
|
119
|
+
| `password` | String | `guest` | Authentication password |
|
120
|
+
| `vhost` | String | `/` | Virtual host |
|
121
|
+
| `timeout` | Integer | 30 | Connection timeout (seconds) |
|
122
|
+
| `heartbeat` | Integer | 30 | Heartbeat interval (seconds) |
|
123
|
+
| `exchange` | String | `agent99` | Default exchange name |
|
124
|
+
| `exchange_type` | String | `topic` | Exchange type |
|
125
|
+
|
126
|
+
### Exchange and Routing
|
127
|
+
|
128
|
+
```ruby
|
129
|
+
class AmqpAgent < Agent99::Base
|
130
|
+
def initialize
|
131
|
+
super(
|
132
|
+
message_client: 'amqp',
|
133
|
+
exchange: 'agent99.services',
|
134
|
+
routing_key: 'services.calculator'
|
135
|
+
)
|
136
|
+
end
|
137
|
+
|
138
|
+
def process_request(payload)
|
139
|
+
# AMQP-specific features
|
140
|
+
routing_key = current_routing_key
|
141
|
+
exchange = current_exchange
|
142
|
+
|
143
|
+
logger.info "Message from: #{routing_key} on #{exchange}"
|
144
|
+
|
145
|
+
# Can publish to specific routing keys
|
146
|
+
publish_to_routing_key('notifications.processed', {
|
147
|
+
agent: info[:name],
|
148
|
+
processed_at: Time.now.iso8601
|
149
|
+
})
|
150
|
+
|
151
|
+
send_response(
|
152
|
+
message: "Processed via AMQP",
|
153
|
+
routing_key: routing_key
|
154
|
+
)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
```
|
158
|
+
|
159
|
+
## TCP Client
|
160
|
+
|
161
|
+
### Configuration
|
162
|
+
|
163
|
+
The TCP client is primarily for testing and simple setups:
|
164
|
+
|
165
|
+
```ruby
|
166
|
+
# Environment variables
|
167
|
+
ENV['TCP_HOST'] = 'localhost'
|
168
|
+
ENV['TCP_PORT'] = '9999'
|
169
|
+
|
170
|
+
# Or programmatically
|
171
|
+
tcp_config = {
|
172
|
+
host: 'localhost',
|
173
|
+
port: 9999,
|
174
|
+
timeout: 30
|
175
|
+
}
|
176
|
+
|
177
|
+
client = Agent99::MessageClients::TcpClient.new(tcp_config)
|
178
|
+
```
|
179
|
+
|
180
|
+
### Usage Example
|
181
|
+
|
182
|
+
```ruby
|
183
|
+
class TcpAgent < Agent99::Base
|
184
|
+
def initialize
|
185
|
+
super(message_client: 'tcp')
|
186
|
+
end
|
187
|
+
|
188
|
+
def process_request(payload)
|
189
|
+
client_address = current_client_address
|
190
|
+
|
191
|
+
logger.info "Request from: #{client_address}"
|
192
|
+
|
193
|
+
send_response(
|
194
|
+
message: "Processed via TCP",
|
195
|
+
client: client_address
|
196
|
+
)
|
197
|
+
end
|
198
|
+
end
|
199
|
+
```
|
200
|
+
|
201
|
+
## Message Client API
|
202
|
+
|
203
|
+
### Common Interface
|
204
|
+
|
205
|
+
All message clients implement a common interface:
|
206
|
+
|
207
|
+
```ruby
|
208
|
+
class MessageClientBase
|
209
|
+
def initialize(config = {})
|
210
|
+
# Initialize connection with config
|
211
|
+
end
|
212
|
+
|
213
|
+
def connect
|
214
|
+
# Establish connection to message broker
|
215
|
+
end
|
216
|
+
|
217
|
+
def disconnect
|
218
|
+
# Close connection
|
219
|
+
end
|
220
|
+
|
221
|
+
def subscribe(subject, &block)
|
222
|
+
# Subscribe to messages on subject/queue
|
223
|
+
end
|
224
|
+
|
225
|
+
def publish(subject, message, options = {})
|
226
|
+
# Publish message to subject/exchange
|
227
|
+
end
|
228
|
+
|
229
|
+
def request(subject, message, options = {})
|
230
|
+
# Send request and wait for response
|
231
|
+
end
|
232
|
+
|
233
|
+
def connected?
|
234
|
+
# Check connection status
|
235
|
+
end
|
236
|
+
end
|
237
|
+
```
|
238
|
+
|
239
|
+
### Connection Management
|
240
|
+
|
241
|
+
```ruby
|
242
|
+
# Check connection status
|
243
|
+
if client.connected?
|
244
|
+
logger.info "Connected to message broker"
|
245
|
+
else
|
246
|
+
logger.warn "Not connected, attempting reconnect..."
|
247
|
+
client.connect
|
248
|
+
end
|
249
|
+
|
250
|
+
# Graceful shutdown
|
251
|
+
Signal.trap('TERM') do
|
252
|
+
logger.info "Shutting down..."
|
253
|
+
client.disconnect
|
254
|
+
exit
|
255
|
+
end
|
256
|
+
```
|
257
|
+
|
258
|
+
### Error Handling
|
259
|
+
|
260
|
+
```ruby
|
261
|
+
begin
|
262
|
+
response = client.request('service.calculate', payload, timeout: 10)
|
263
|
+
rescue Agent99::MessageClient::TimeoutError
|
264
|
+
logger.error "Request timed out"
|
265
|
+
rescue Agent99::MessageClient::ConnectionError => e
|
266
|
+
logger.error "Connection failed: #{e.message}"
|
267
|
+
# Attempt reconnection
|
268
|
+
client.connect
|
269
|
+
rescue Agent99::MessageClient::Error => e
|
270
|
+
logger.error "Message client error: #{e.message}"
|
271
|
+
end
|
272
|
+
```
|
273
|
+
|
274
|
+
## Advanced Features
|
275
|
+
|
276
|
+
### Message Filtering
|
277
|
+
|
278
|
+
```ruby
|
279
|
+
# NATS subject filtering
|
280
|
+
client.subscribe('services.calculator.*') do |message|
|
281
|
+
# Receives: services.calculator.add, services.calculator.multiply, etc.
|
282
|
+
end
|
283
|
+
|
284
|
+
# AMQP routing key patterns
|
285
|
+
client.subscribe('services.#') do |message|
|
286
|
+
# Receives all messages starting with 'services.'
|
287
|
+
end
|
288
|
+
```
|
289
|
+
|
290
|
+
### Message Persistence
|
291
|
+
|
292
|
+
```ruby
|
293
|
+
# AMQP persistent messages
|
294
|
+
client.publish('important.task', payload, persistent: true)
|
295
|
+
|
296
|
+
# NATS with JetStream persistence (if available)
|
297
|
+
client.publish('stream.data', payload, stream: 'EVENTS')
|
298
|
+
```
|
299
|
+
|
300
|
+
### Load Balancing
|
301
|
+
|
302
|
+
```ruby
|
303
|
+
# NATS queue groups for load balancing
|
304
|
+
client.subscribe('work.queue', queue: 'workers') do |message|
|
305
|
+
# Multiple subscribers share the work
|
306
|
+
end
|
307
|
+
|
308
|
+
# AMQP work queues
|
309
|
+
client.subscribe('task.queue', durable: true, ack: true) do |message|
|
310
|
+
process_task(message)
|
311
|
+
message.ack # Acknowledge completion
|
312
|
+
end
|
313
|
+
```
|
314
|
+
|
315
|
+
## Performance Considerations
|
316
|
+
|
317
|
+
### Connection Pooling
|
318
|
+
|
319
|
+
```ruby
|
320
|
+
class PooledMessageClient
|
321
|
+
def initialize(config = {})
|
322
|
+
@pool_size = config[:pool_size] || 10
|
323
|
+
@pool = ConnectionPool.new(size: @pool_size) do
|
324
|
+
Agent99::MessageClients::NatsClient.new(config)
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
328
|
+
def with_connection(&block)
|
329
|
+
@pool.with(&block)
|
330
|
+
end
|
331
|
+
end
|
332
|
+
```
|
333
|
+
|
334
|
+
### Batching
|
335
|
+
|
336
|
+
```ruby
|
337
|
+
# Batch messages for better performance
|
338
|
+
messages = []
|
339
|
+
(1..100).each do |i|
|
340
|
+
messages << { id: i, data: "message #{i}" }
|
341
|
+
end
|
342
|
+
|
343
|
+
# Send in batches
|
344
|
+
messages.each_slice(10) do |batch|
|
345
|
+
batch.each { |msg| client.publish('batch.data', msg) }
|
346
|
+
sleep(0.1) # Rate limiting
|
347
|
+
end
|
348
|
+
```
|
349
|
+
|
350
|
+
### Monitoring
|
351
|
+
|
352
|
+
```ruby
|
353
|
+
class MonitoredClient
|
354
|
+
def initialize(base_client)
|
355
|
+
@client = base_client
|
356
|
+
@metrics = {
|
357
|
+
messages_sent: 0,
|
358
|
+
messages_received: 0,
|
359
|
+
errors: 0
|
360
|
+
}
|
361
|
+
end
|
362
|
+
|
363
|
+
def publish(subject, message, options = {})
|
364
|
+
start_time = Time.now
|
365
|
+
|
366
|
+
begin
|
367
|
+
@client.publish(subject, message, options)
|
368
|
+
@metrics[:messages_sent] += 1
|
369
|
+
rescue => e
|
370
|
+
@metrics[:errors] += 1
|
371
|
+
raise
|
372
|
+
ensure
|
373
|
+
duration = Time.now - start_time
|
374
|
+
logger.debug "Published to #{subject} in #{duration}s"
|
375
|
+
end
|
376
|
+
end
|
377
|
+
|
378
|
+
def stats
|
379
|
+
@metrics.dup
|
380
|
+
end
|
381
|
+
end
|
382
|
+
```
|
383
|
+
|
384
|
+
## Testing Message Clients
|
385
|
+
|
386
|
+
### Mock Client for Testing
|
387
|
+
|
388
|
+
```ruby
|
389
|
+
class MockMessageClient
|
390
|
+
def initialize
|
391
|
+
@messages = []
|
392
|
+
@subscriptions = {}
|
393
|
+
end
|
394
|
+
|
395
|
+
def publish(subject, message, options = {})
|
396
|
+
@messages << {
|
397
|
+
subject: subject,
|
398
|
+
message: message,
|
399
|
+
options: options,
|
400
|
+
timestamp: Time.now
|
401
|
+
}
|
402
|
+
|
403
|
+
# Trigger subscriptions
|
404
|
+
@subscriptions[subject]&.each { |block| block.call(message) }
|
405
|
+
end
|
406
|
+
|
407
|
+
def subscribe(subject, &block)
|
408
|
+
@subscriptions[subject] ||= []
|
409
|
+
@subscriptions[subject] << block
|
410
|
+
end
|
411
|
+
|
412
|
+
def published_messages
|
413
|
+
@messages
|
414
|
+
end
|
415
|
+
|
416
|
+
def clear_messages
|
417
|
+
@messages.clear
|
418
|
+
end
|
419
|
+
end
|
420
|
+
```
|
421
|
+
|
422
|
+
### Integration Testing
|
423
|
+
|
424
|
+
```ruby
|
425
|
+
require 'minitest/autorun'
|
426
|
+
|
427
|
+
class TestMessageClientIntegration < Minitest::Test
|
428
|
+
def setup
|
429
|
+
@client = Agent99::MessageClients::NatsClient.new
|
430
|
+
@client.connect
|
431
|
+
end
|
432
|
+
|
433
|
+
def teardown
|
434
|
+
@client.disconnect
|
435
|
+
end
|
436
|
+
|
437
|
+
def test_request_response
|
438
|
+
# Start a responder
|
439
|
+
response_thread = Thread.new do
|
440
|
+
@client.subscribe('test.echo') do |message|
|
441
|
+
@client.publish(message.reply, { echo: message.data })
|
442
|
+
end
|
443
|
+
end
|
444
|
+
|
445
|
+
# Send request
|
446
|
+
response = @client.request('test.echo', { text: 'hello' })
|
447
|
+
|
448
|
+
assert_equal 'hello', response[:echo][:text]
|
449
|
+
|
450
|
+
response_thread.kill
|
451
|
+
end
|
452
|
+
end
|
453
|
+
```
|
454
|
+
|
455
|
+
## Configuration Examples
|
456
|
+
|
457
|
+
### Production NATS Cluster
|
458
|
+
|
459
|
+
```yaml
|
460
|
+
# config/nats.yml
|
461
|
+
production:
|
462
|
+
servers:
|
463
|
+
- nats://nats1.example.com:4222
|
464
|
+
- nats://nats2.example.com:4222
|
465
|
+
- nats://nats3.example.com:4222
|
466
|
+
username: <%= ENV['NATS_USERNAME'] %>
|
467
|
+
password: <%= ENV['NATS_PASSWORD'] %>
|
468
|
+
tls:
|
469
|
+
cert_file: /etc/ssl/certs/client.crt
|
470
|
+
key_file: /etc/ssl/private/client.key
|
471
|
+
ca_file: /etc/ssl/certs/ca.crt
|
472
|
+
```
|
473
|
+
|
474
|
+
### Production RabbitMQ
|
475
|
+
|
476
|
+
```yaml
|
477
|
+
# config/rabbitmq.yml
|
478
|
+
production:
|
479
|
+
url: <%= ENV['RABBITMQ_URL'] %>
|
480
|
+
heartbeat: 30
|
481
|
+
connection_timeout: 10
|
482
|
+
read_timeout: 30
|
483
|
+
write_timeout: 30
|
484
|
+
ssl:
|
485
|
+
enabled: true
|
486
|
+
verify: true
|
487
|
+
cert_path: /etc/ssl/certs/client.pem
|
488
|
+
key_path: /etc/ssl/private/client.key
|
489
|
+
```
|
490
|
+
|
491
|
+
## Next Steps
|
492
|
+
|
493
|
+
- **[Agent99::Base](agent99-base.md)** - Core agent class reference
|
494
|
+
- **[Registry Client](registry-client.md)** - Registry service API
|
495
|
+
- **[Configuration](../operations/configuration.md)** - Detailed configuration options
|