agent99 0.0.2 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +25 -1
- data/README.md +34 -26
- data/docs/README.md +57 -0
- data/docs/advanced_features.md +115 -0
- data/docs/agent99_framework/central_registry.md +94 -0
- data/docs/agent99_framework/message_client.md +120 -0
- data/docs/agent99_framework/registry_client.md +119 -0
- data/docs/agent_discovery.md +66 -0
- data/docs/agent_lifecycle.md +137 -0
- data/docs/agent_registry_processes.md +108 -0
- data/docs/api_reference.md +146 -0
- data/docs/architecture.md +77 -0
- data/docs/breaking_change_v0.0.4.md +26 -0
- data/docs/configuration.md +17 -0
- data/docs/control_actions.md +179 -0
- data/docs/custom_agent_implementation.md +30 -0
- data/docs/diagrams/agent_registry_processes.dot +42 -0
- data/docs/diagrams/agent_registry_processes.png +0 -0
- data/docs/diagrams/high_level_architecture.dot +26 -0
- data/docs/diagrams/high_level_architecture.png +0 -0
- data/docs/diagrams/request_flow.dot +42 -0
- data/docs/diagrams/request_flow.png +0 -0
- data/docs/error_handling_and_logging.md +13 -0
- data/docs/extending_the_framework.md +11 -0
- data/docs/message_processing.md +165 -0
- data/docs/messaging_system.md +129 -0
- data/docs/preformance_considerations.md +9 -0
- data/docs/schema_definition.md +78 -0
- data/docs/security.md +9 -0
- data/docs/troubleshooting.md +11 -0
- data/docs/what_is_an_agent.md +293 -0
- data/examples/README.md +43 -0
- data/examples/agent_watcher.rb +106 -0
- data/examples/agents/.keep +0 -0
- data/examples/chief_agent.rb +17 -6
- data/examples/control.rb +16 -7
- data/examples/example_agent.rb +39 -0
- data/examples/kaos_spy.rb +63 -0
- data/examples/maxwell_agent86.rb +15 -26
- data/examples/registry.rb +24 -13
- data/lib/agent99/agent_discovery.rb +4 -0
- data/lib/agent99/agent_lifecycle.rb +34 -10
- data/lib/agent99/base.rb +5 -1
- data/lib/agent99/header_schema.rb +5 -0
- data/lib/agent99/message_processing.rb +3 -1
- data/lib/agent99/registry_client.rb +12 -11
- data/lib/agent99/tcp_message_client.rb +183 -0
- data/lib/agent99/version.rb +1 -1
- metadata +50 -3
- data/docs/todo.md +0 -66
@@ -0,0 +1,179 @@
|
|
1
|
+
# Agent99 Framework
|
2
|
+
|
3
|
+
## Control Actions
|
4
|
+
|
5
|
+
Agent99 provides a robust control system that allows for dynamic management of agents during runtime. Control actions enable administrative operations and state management without requiring agent restarts or redeployment.
|
6
|
+
|
7
|
+
### Built-in Control Actions
|
8
|
+
|
9
|
+
The framework includes several built-in control actions:
|
10
|
+
|
11
|
+
#### shutdown
|
12
|
+
- Gracefully stops the agent
|
13
|
+
- Withdraws registration from the registry
|
14
|
+
- Cleans up resources and connections
|
15
|
+
- Triggers the `fini` method
|
16
|
+
- Example usage:
|
17
|
+
```ruby
|
18
|
+
{
|
19
|
+
header: {
|
20
|
+
type: "control",
|
21
|
+
to_uuid: "target_agent_id",
|
22
|
+
from_uuid: "control_agent_id",
|
23
|
+
event_uuid: "evt_123",
|
24
|
+
timestamp: 1638360000000000
|
25
|
+
},
|
26
|
+
action: "shutdown"
|
27
|
+
}
|
28
|
+
```
|
29
|
+
|
30
|
+
#### pause
|
31
|
+
TODO: haven't decided whether messages are left in the messaging network or whether they should be queued within the agent. TBD
|
32
|
+
|
33
|
+
- Temporarily halts message processing
|
34
|
+
- Maintains agent registration
|
35
|
+
- Continues to accept control messages
|
36
|
+
- Queues other messages for later processing
|
37
|
+
- Example usage:
|
38
|
+
```ruby
|
39
|
+
{
|
40
|
+
header: {
|
41
|
+
type: "control",
|
42
|
+
to_uuid: "target_agent_id",
|
43
|
+
from_uuid: "control_agent_id",
|
44
|
+
event_uuid: "evt_456",
|
45
|
+
timestamp: 1638360000000000
|
46
|
+
},
|
47
|
+
action: "pause"
|
48
|
+
}
|
49
|
+
```
|
50
|
+
|
51
|
+
#### resume
|
52
|
+
- Reactivates a paused agent
|
53
|
+
- Processes any queued messages
|
54
|
+
- Restores normal operation
|
55
|
+
- Example usage:
|
56
|
+
```ruby
|
57
|
+
{
|
58
|
+
header: {
|
59
|
+
type: "control",
|
60
|
+
to_uuid: "target_agent_id",
|
61
|
+
from_uuid: "control_agent_id",
|
62
|
+
event_uuid: "evt_789",
|
63
|
+
timestamp: 1638360000000000
|
64
|
+
},
|
65
|
+
action: "resume"
|
66
|
+
}
|
67
|
+
```
|
68
|
+
|
69
|
+
#### update_config
|
70
|
+
|
71
|
+
TODO: This is still TBD waiting for the design of the overall configuration class.
|
72
|
+
|
73
|
+
- Updates agent configuration at runtime
|
74
|
+
- Allows dynamic behavior modification
|
75
|
+
- Example usage:
|
76
|
+
```ruby
|
77
|
+
{
|
78
|
+
header: {
|
79
|
+
type: "control",
|
80
|
+
to_uuid: "target_agent_id",
|
81
|
+
from_uuid: "control_agent_id",
|
82
|
+
event_uuid: "evt_101",
|
83
|
+
timestamp: 1638360000000000
|
84
|
+
},
|
85
|
+
action: "update_config",
|
86
|
+
config: {
|
87
|
+
"log_level": "DEBUG",
|
88
|
+
"timeout": 30
|
89
|
+
}
|
90
|
+
}
|
91
|
+
```
|
92
|
+
|
93
|
+
#### status
|
94
|
+
- Requests current agent status
|
95
|
+
- Returns operational statistics
|
96
|
+
- Example usage:
|
97
|
+
```ruby
|
98
|
+
{
|
99
|
+
header: {
|
100
|
+
type: "control",
|
101
|
+
to_uuid: "target_agent_id",
|
102
|
+
from_uuid: "control_agent_id",
|
103
|
+
event_uuid: "evt_102",
|
104
|
+
timestamp: 1638360000000000
|
105
|
+
},
|
106
|
+
action: "status"
|
107
|
+
}
|
108
|
+
```
|
109
|
+
|
110
|
+
### Implementing Custom Control Actions
|
111
|
+
|
112
|
+
You can implement custom control actions by:
|
113
|
+
|
114
|
+
1. Adding a handler method to your agent class:
|
115
|
+
```ruby
|
116
|
+
def handle_custom_action
|
117
|
+
# Implementation
|
118
|
+
send_control_response(status: "custom action completed")
|
119
|
+
end
|
120
|
+
```
|
121
|
+
|
122
|
+
2. Registering the handler in CONTROL_HANDLERS:
|
123
|
+
```ruby
|
124
|
+
CONTROL_HANDLERS.merge!({
|
125
|
+
'custom_action' => :handle_custom_action
|
126
|
+
})
|
127
|
+
```
|
128
|
+
|
129
|
+
### Best Practices
|
130
|
+
|
131
|
+
1. **Response Handling**
|
132
|
+
- Always send a control response
|
133
|
+
- Include relevant status information
|
134
|
+
- Handle errors gracefully
|
135
|
+
|
136
|
+
2. **State Management**
|
137
|
+
- Maintain consistent state transitions
|
138
|
+
- Document state dependencies
|
139
|
+
- Handle edge cases (e.g., pause while paused)
|
140
|
+
|
141
|
+
3. **Security Considerations**
|
142
|
+
- Validate control message sources
|
143
|
+
- Implement appropriate authorization
|
144
|
+
- Log all control actions
|
145
|
+
|
146
|
+
4. **Error Recovery**
|
147
|
+
- Implement timeout mechanisms
|
148
|
+
- Handle partial failures
|
149
|
+
- Provide status feedback
|
150
|
+
|
151
|
+
### Control Flow Example
|
152
|
+
|
153
|
+
```ruby
|
154
|
+
class MyAgent < Agent99::Base
|
155
|
+
def handle_custom_restart
|
156
|
+
begin
|
157
|
+
cleanup_resources
|
158
|
+
reinitialize_state
|
159
|
+
send_control_response(status: "restart completed")
|
160
|
+
rescue StandardError => e
|
161
|
+
send_control_response(
|
162
|
+
status: "restart failed",
|
163
|
+
error: e.message
|
164
|
+
)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
```
|
169
|
+
|
170
|
+
### Monitoring Control Actions
|
171
|
+
|
172
|
+
All control actions are automatically logged with:
|
173
|
+
* Timestamp
|
174
|
+
* Action type
|
175
|
+
* Source agent
|
176
|
+
* Result status
|
177
|
+
* Error information (if any)
|
178
|
+
|
179
|
+
This enables effective monitoring and troubleshooting of agent behavior and system state.
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# Agent99 Framework
|
2
|
+
|
3
|
+
## Custom Agent Implementation
|
4
|
+
|
5
|
+
### Creating a Custom Agent
|
6
|
+
|
7
|
+
To create a custom agent:
|
8
|
+
|
9
|
+
1. Subclass `Agent99::Base`.
|
10
|
+
2. Define the request and response schemas.
|
11
|
+
3. Implement the `receive_request` and `receive_response` methods.
|
12
|
+
|
13
|
+
Example:
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
class MyCustomAgent < Agent99::Base
|
17
|
+
REQUEST_SCHEMA = MyAgentRequest.schema
|
18
|
+
|
19
|
+
def receive_request
|
20
|
+
# Handle incoming request
|
21
|
+
response = { result: "Handled request" }
|
22
|
+
send_response(response)
|
23
|
+
end
|
24
|
+
|
25
|
+
def receive_response
|
26
|
+
# Handle incoming response from another agent
|
27
|
+
end
|
28
|
+
end
|
29
|
+
```
|
30
|
+
|
@@ -0,0 +1,42 @@
|
|
1
|
+
digraph AgentRegistration {
|
2
|
+
rankdir=LR;
|
3
|
+
node [shape=box, style=rounded];
|
4
|
+
edge [fontsize=10];
|
5
|
+
|
6
|
+
MyAgent [label="MyAgent"];
|
7
|
+
RegistryClient [label="RegistryClient"];
|
8
|
+
CentralRegistry [label="Central Registry\n(Sinatra Server)"];
|
9
|
+
|
10
|
+
subgraph cluster_registration {
|
11
|
+
label="Registration Process";
|
12
|
+
color=lightgrey;
|
13
|
+
style=filled;
|
14
|
+
|
15
|
+
MyAgent -> RegistryClient [label="1. initialize"];
|
16
|
+
RegistryClient -> CentralRegistry [label="2. POST /register\n{name, capabilities}"];
|
17
|
+
CentralRegistry -> RegistryClient [label="3. 201 Created\n{uuid}"];
|
18
|
+
RegistryClient -> MyAgent [label="4. Return uuid"];
|
19
|
+
}
|
20
|
+
|
21
|
+
subgraph cluster_discovery {
|
22
|
+
label="Discovery Process";
|
23
|
+
color=lightblue;
|
24
|
+
style=filled;
|
25
|
+
|
26
|
+
MyAgent -> RegistryClient [label="5. discover(capability)"];
|
27
|
+
RegistryClient -> CentralRegistry [label="6. GET /discover?capability=..."];
|
28
|
+
CentralRegistry -> RegistryClient [label="7. 200 OK\n[matching agents]"];
|
29
|
+
RegistryClient -> MyAgent [label="8. Return matching agents"];
|
30
|
+
}
|
31
|
+
|
32
|
+
subgraph cluster_withdrawal {
|
33
|
+
label="Withdrawal Process";
|
34
|
+
color=lightpink;
|
35
|
+
style=filled;
|
36
|
+
|
37
|
+
MyAgent -> RegistryClient [label="9. withdraw(uuid)"];
|
38
|
+
RegistryClient -> CentralRegistry [label="10. DELETE /withdraw/:uuid"];
|
39
|
+
CentralRegistry -> RegistryClient [label="11. 204 No Content"];
|
40
|
+
RegistryClient -> MyAgent [label="12. Confirm withdrawal"];
|
41
|
+
}
|
42
|
+
}
|
Binary file
|
@@ -0,0 +1,26 @@
|
|
1
|
+
digraph Agent99Architecture {
|
2
|
+
rankdir=LR;
|
3
|
+
node [shape=box, style=rounded];
|
4
|
+
|
5
|
+
subgraph cluster_0 {
|
6
|
+
label="Agent99 Framework";
|
7
|
+
style=dashed;
|
8
|
+
|
9
|
+
Agent1 [label="Agent 1\n(Client)"];
|
10
|
+
Agent2 [label="Agent 2\n(Server)"];
|
11
|
+
Agent3 [label="Agent 3\n(Hybrid)"];
|
12
|
+
}
|
13
|
+
|
14
|
+
Registry [shape=cylinder, label="Registry\nService"];
|
15
|
+
MessageBroker [shape=diamond, label="Message Broker\n(AMQP/NATS)"];
|
16
|
+
|
17
|
+
// Registration flows
|
18
|
+
Agent1 -> Registry [label="register/discover", style=dashed];
|
19
|
+
Agent2 -> Registry [label="register/discover", style=dashed];
|
20
|
+
Agent3 -> Registry [label="register/discover", style=dashed];
|
21
|
+
|
22
|
+
// Message flows
|
23
|
+
Agent1 -> MessageBroker [dir=both, label="publish/subscribe"];
|
24
|
+
Agent2 -> MessageBroker [dir=both, label="publish/subscribe"];
|
25
|
+
Agent3 -> MessageBroker [dir=both, label="publish/subscribe"];
|
26
|
+
}
|
Binary file
|
@@ -0,0 +1,42 @@
|
|
1
|
+
digraph RequestFlow {
|
2
|
+
rankdir=TB;
|
3
|
+
node [shape=box, style=rounded];
|
4
|
+
|
5
|
+
// Message arrival and initial processing
|
6
|
+
start [shape=oval, label="Message Arrives"];
|
7
|
+
dispatch [label="dispatcher()\nMessage Processing Loop"];
|
8
|
+
process [label="process_request(message)"];
|
9
|
+
validate [label="validate_schema()"];
|
10
|
+
|
11
|
+
// Main processing branch
|
12
|
+
receive [label="receive_request()\nAgent Implementation"];
|
13
|
+
send [label="send_response()\nOptional Response"];
|
14
|
+
|
15
|
+
// Error handling branch
|
16
|
+
error [label="Error Handler"];
|
17
|
+
error_response [label="Send Error Response"];
|
18
|
+
|
19
|
+
// Flow connections
|
20
|
+
start -> dispatch;
|
21
|
+
dispatch -> process;
|
22
|
+
process -> validate;
|
23
|
+
|
24
|
+
// Success path
|
25
|
+
validate -> receive [label="Valid"];
|
26
|
+
receive -> send [style=dashed];
|
27
|
+
|
28
|
+
// Error path
|
29
|
+
validate -> error [label="Invalid"];
|
30
|
+
error -> error_response;
|
31
|
+
|
32
|
+
// Styling
|
33
|
+
{
|
34
|
+
node [shape=note, style=filled, fillcolor=lightyellow];
|
35
|
+
note1 [label="Schema validation\nensures message\nintegrity"];
|
36
|
+
note2 [label="Custom processing\nin agent subclass"];
|
37
|
+
}
|
38
|
+
|
39
|
+
// Connect notes
|
40
|
+
validate -> note1 [style=dotted, arrowhead=none];
|
41
|
+
receive -> note2 [style=dotted, arrowhead=none];
|
42
|
+
}
|
Binary file
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# Agent99 Framework
|
2
|
+
|
3
|
+
## Error Handling and Logging
|
4
|
+
|
5
|
+
Agent99 incorporates robust error handling mechanisms, with error messages being captured and logged. The logging system is configured through environment variables to define the logging level and output destination.
|
6
|
+
|
7
|
+
Example:
|
8
|
+
|
9
|
+
```bash
|
10
|
+
export LOG_LEVEL=DEBUG
|
11
|
+
```
|
12
|
+
|
13
|
+
Logs provide insights into agent activities, including errors encountered during message processing and system events.
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# Agent99 Framework
|
2
|
+
|
3
|
+
## Extending the Framework
|
4
|
+
|
5
|
+
To extend Agent99:
|
6
|
+
|
7
|
+
1. Implement custom modules and include them in your agents.
|
8
|
+
2. Define new message types or schemas as needed.
|
9
|
+
3. Use hooks to add functionality or override existing behavior.
|
10
|
+
|
11
|
+
If a plugin system is developed in the future, it would allow for additional features without modifying the core framework.
|
@@ -0,0 +1,165 @@
|
|
1
|
+
# Agent99 Framework
|
2
|
+
|
3
|
+
## Message Processing
|
4
|
+
|
5
|
+
The Agent99 framework implements a robust message processing system that handles three main types of
|
6
|
+
messages: Request, Response, and Control messages. Each message type follows specific processing flows
|
7
|
+
and validation rules.
|
8
|
+
|
9
|
+
### Message Types
|
10
|
+
|
11
|
+
1. **Request Messages**
|
12
|
+
- Sent by clients to request services or actions
|
13
|
+
- Must include a valid schema definition
|
14
|
+
- Processed through the `receive_request` handler
|
15
|
+
- Automatically validated against REQUEST_SCHEMA
|
16
|
+
- Can trigger responses back to the sender
|
17
|
+
|
18
|
+
2. **Response Messages**
|
19
|
+
- Sent in reply to requests
|
20
|
+
- Contain results or error information
|
21
|
+
- Processed through the `receive_response` handler
|
22
|
+
- Include original request reference
|
23
|
+
- May trigger additional processing flows
|
24
|
+
|
25
|
+
3. **Control Messages**
|
26
|
+
- Manage agent lifecycle and behavior
|
27
|
+
- Include actions like shutdown, pause, resume
|
28
|
+
- Processed through dedicated control handlers
|
29
|
+
- Support configuration updates
|
30
|
+
- Enable status monitoring
|
31
|
+
|
32
|
+
### Message Processing Flow
|
33
|
+
|
34
|
+
#### Request Processing
|
35
|
+
1. Message arrives and is validated against schema
|
36
|
+
2. If validation passes:
|
37
|
+
- `receive_request` is called
|
38
|
+
- Custom processing occurs
|
39
|
+
- Optional response is sent
|
40
|
+
3. If validation fails:
|
41
|
+
- Error response is automatically sent
|
42
|
+
- Error is logged
|
43
|
+
- Request is not processed further
|
44
|
+
|
45
|
+

|
46
|
+
|
47
|
+
#### Response Processing
|
48
|
+
1. Response message is received
|
49
|
+
2. `receive_response` handler is called
|
50
|
+
3. Response data is processed
|
51
|
+
4. Any follow-up actions are triggered
|
52
|
+
|
53
|
+
#### Control Processing
|
54
|
+
1. Control message is received
|
55
|
+
2. Action is identified
|
56
|
+
3. Appropriate handler is called:
|
57
|
+
- `handle_shutdown`
|
58
|
+
- `handle_pause`
|
59
|
+
- `handle_resume`
|
60
|
+
- `handle_update_config`
|
61
|
+
- `handle_status_request`
|
62
|
+
4. Control response is sent if needed
|
63
|
+
|
64
|
+
### Error Handling
|
65
|
+
|
66
|
+
The framework provides comprehensive error handling:
|
67
|
+
|
68
|
+
1. **Validation Errors**
|
69
|
+
- Schema validation failures
|
70
|
+
- Missing required fields
|
71
|
+
- Invalid data types
|
72
|
+
|
73
|
+
2. **Processing Errors**
|
74
|
+
- Handler exceptions
|
75
|
+
- Resource unavailability
|
76
|
+
- Timeout conditions
|
77
|
+
|
78
|
+
3. **System Errors**
|
79
|
+
- Connection issues
|
80
|
+
- Resource constraints
|
81
|
+
- Framework-level problems
|
82
|
+
|
83
|
+
### Best Practices
|
84
|
+
|
85
|
+
1. **Message Validation**
|
86
|
+
- Always define REQUEST_SCHEMA for request-handling agents
|
87
|
+
- Include comprehensive examples in schema
|
88
|
+
- Validate message structure
|
89
|
+
|
90
|
+
2. **Error Handling**
|
91
|
+
- Implement robust error handling in handlers
|
92
|
+
- Return meaningful error messages
|
93
|
+
- Log all significant events
|
94
|
+
|
95
|
+
3. **Response Management**
|
96
|
+
- Send responses promptly
|
97
|
+
- Include relevant context
|
98
|
+
- Handle partial success cases
|
99
|
+
|
100
|
+
4. **Control Messages**
|
101
|
+
- Respond to all control messages
|
102
|
+
- Implement graceful shutdown
|
103
|
+
- Maintain agent state properly
|
104
|
+
|
105
|
+
### Implementation Example
|
106
|
+
|
107
|
+
```ruby
|
108
|
+
class MyAgent < Agent99::Base
|
109
|
+
REQUEST_SCHEMA = {
|
110
|
+
type: "object",
|
111
|
+
properties: {
|
112
|
+
header: HEADER_SCHEMA,
|
113
|
+
data: {
|
114
|
+
type: "object",
|
115
|
+
required: ["action"],
|
116
|
+
properties: {
|
117
|
+
action: { type: "string" }
|
118
|
+
}
|
119
|
+
}
|
120
|
+
}
|
121
|
+
}
|
122
|
+
|
123
|
+
def receive_request
|
124
|
+
action = payload.dig(:data, :action)
|
125
|
+
result = process_action(action)
|
126
|
+
send_response(result)
|
127
|
+
rescue StandardError => e
|
128
|
+
send_response(error: e.message)
|
129
|
+
end
|
130
|
+
|
131
|
+
private
|
132
|
+
|
133
|
+
def process_action(action)
|
134
|
+
# Custom processing logic
|
135
|
+
{ status: "success", result: action }
|
136
|
+
end
|
137
|
+
end
|
138
|
+
```
|
139
|
+
|
140
|
+
### Message Structure
|
141
|
+
|
142
|
+
All messages must include a header with:
|
143
|
+
* `type`: Message type (request/response/control)
|
144
|
+
* `to_uuid`: Destination agent ID
|
145
|
+
* `from_uuid`: Sender agent ID
|
146
|
+
* `event_uuid`: Unique event identifier
|
147
|
+
* `timestamp`: Message creation time
|
148
|
+
|
149
|
+
Example message structure:
|
150
|
+
```ruby
|
151
|
+
{
|
152
|
+
header: {
|
153
|
+
type: "request",
|
154
|
+
to_uuid: "agent_123",
|
155
|
+
from_uuid: "agent_456",
|
156
|
+
event_uuid: "evt_789",
|
157
|
+
timestamp: 1638360000000000
|
158
|
+
},
|
159
|
+
data: {
|
160
|
+
# Message-specific payload
|
161
|
+
}
|
162
|
+
}
|
163
|
+
```
|
164
|
+
|
165
|
+
|
@@ -0,0 +1,129 @@
|
|
1
|
+
# Agent99 Framework
|
2
|
+
|
3
|
+
## Messaging Systems
|
4
|
+
|
5
|
+
Agent99 supports both AMQP and NATS messaging systems, allowing you to choose the most appropriate messaging backend for your needs. The framework provides a consistent interface regardless of which messaging system you use.
|
6
|
+
|
7
|
+
### Supported Message Brokers
|
8
|
+
|
9
|
+
#### AMQP (RabbitMQ)
|
10
|
+
The AMQP implementation uses RabbitMQ as the message broker and provides:
|
11
|
+
|
12
|
+
- **Durability**: Messages can persist across broker restarts
|
13
|
+
- **Queue TTL**: Queues automatically expire after 60 seconds of inactivity
|
14
|
+
- **Automatic Reconnection**: Handles connection drops gracefully
|
15
|
+
- **Default Configuration**:
|
16
|
+
```ruby
|
17
|
+
{
|
18
|
+
host: "127.0.0.1",
|
19
|
+
port: 5672,
|
20
|
+
ssl: false,
|
21
|
+
vhost: "/",
|
22
|
+
user: "guest",
|
23
|
+
pass: "guest",
|
24
|
+
heartbeat: :server,
|
25
|
+
frame_max: 131072,
|
26
|
+
auth_mechanism: "PLAIN"
|
27
|
+
}
|
28
|
+
```
|
29
|
+
|
30
|
+
#### NATS
|
31
|
+
The NATS implementation provides:
|
32
|
+
|
33
|
+
- **Lightweight**: Simple pub/sub with minimal overhead
|
34
|
+
- **Auto-Pruning**: Automatically cleans up unused subjects
|
35
|
+
- **High Performance**: Optimized for speed and throughput
|
36
|
+
- **Default Configuration**: Uses NATS default connection settings
|
37
|
+
|
38
|
+
### Choosing a Message Client
|
39
|
+
|
40
|
+
You can select your messaging backend when initializing an agent:
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
# For AMQP
|
44
|
+
agent = MyAgent.new(message_client: Agent99::AmqpMessageClient.new)
|
45
|
+
|
46
|
+
# For NATS
|
47
|
+
agent = MyAgent.new(message_client: Agent99::NatsMessageClient.new)
|
48
|
+
```
|
49
|
+
|
50
|
+
Or configure it via environment variables:
|
51
|
+
|
52
|
+
TODO: Need to add this to the configuration class which is still TBD
|
53
|
+
|
54
|
+
```bash
|
55
|
+
# For AMQP
|
56
|
+
export MESSAGE_SYSTEM=amqp
|
57
|
+
export RABBITMQ_URL=amqp://guest:guest@localhost:5672
|
58
|
+
|
59
|
+
# For NATS
|
60
|
+
export MESSAGE_SYSTEM=nats
|
61
|
+
export NATS_URL=nats://localhost:4222
|
62
|
+
```
|
63
|
+
|
64
|
+
### Message Handling
|
65
|
+
|
66
|
+
Both implementations support these core operations:
|
67
|
+
|
68
|
+
1. **Queue Setup**:
|
69
|
+
```ruby
|
70
|
+
queue = message_client.setup(agent_id: id, logger: logger)
|
71
|
+
```
|
72
|
+
|
73
|
+
2. **Message Publishing**:
|
74
|
+
```ruby
|
75
|
+
message_client.publish({
|
76
|
+
header: {
|
77
|
+
type: "request",
|
78
|
+
to_uuid: recipient_id,
|
79
|
+
from_uuid: sender_id,
|
80
|
+
event_uuid: event_id,
|
81
|
+
timestamp: Agent99::Timestamp.new.to_i
|
82
|
+
},
|
83
|
+
data: payload # or whatever for the agent.
|
84
|
+
})
|
85
|
+
```
|
86
|
+
|
87
|
+
3. **Message Subscription**:
|
88
|
+
```ruby
|
89
|
+
message_client.listen_for_messages(
|
90
|
+
queue,
|
91
|
+
request_handler: ->(msg) { handle_request(msg) },
|
92
|
+
response_handler: ->(msg) { handle_response(msg) },
|
93
|
+
control_handler: ->(msg) { handle_control(msg) }
|
94
|
+
)
|
95
|
+
```
|
96
|
+
|
97
|
+
### Key Differences
|
98
|
+
|
99
|
+
1. **Queue Management**:
|
100
|
+
- AMQP: Explicit queue creation and deletion
|
101
|
+
- NATS: Implicit subject-based routing
|
102
|
+
|
103
|
+
2. **Message Persistence**:
|
104
|
+
- AMQP: Supports persistent messages and queues
|
105
|
+
- NATS: Ephemeral messaging by default
|
106
|
+
|
107
|
+
3. **Error Handling**:
|
108
|
+
- AMQP: Provides detailed connection and channel errors
|
109
|
+
- NATS: Simplified error handling with auto-reconnect
|
110
|
+
|
111
|
+
### Best Practices
|
112
|
+
|
113
|
+
1. **Error Handling**: Always wrap message operations in begin/rescue blocks
|
114
|
+
2. **Logging**: Use the provided logger for debugging and monitoring
|
115
|
+
3. **Configuration**: Use environment variables for deployment flexibility
|
116
|
+
4. **Testing**: Test your agents with both messaging systems to ensure compatibility
|
117
|
+
|
118
|
+
### Monitoring
|
119
|
+
|
120
|
+
Both implementations provide logging for:
|
121
|
+
- Message publication success/failure
|
122
|
+
- Queue creation and deletion
|
123
|
+
- Connection status
|
124
|
+
- Error conditions
|
125
|
+
|
126
|
+
Use the logger to monitor your messaging system:
|
127
|
+
```ruby
|
128
|
+
message_client.logger.level = Logger::DEBUG # For detailed logging
|
129
|
+
```
|
@@ -0,0 +1,9 @@
|
|
1
|
+
# Agent99 Framework
|
2
|
+
|
3
|
+
## Performance Considerations
|
4
|
+
|
5
|
+
To ensure optimal performance:
|
6
|
+
|
7
|
+
- Optimize message processing by minimizing complex logic in request handlers.
|
8
|
+
- Use asynchronous processing wherever possible to prevent blocking operations.
|
9
|
+
- Profile agent performance during development to identify bottlenecks.
|