agent99 0.0.2 → 0.0.4
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/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.
|