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.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +25 -1
  3. data/README.md +34 -26
  4. data/docs/README.md +57 -0
  5. data/docs/advanced_features.md +115 -0
  6. data/docs/agent99_framework/central_registry.md +94 -0
  7. data/docs/agent99_framework/message_client.md +120 -0
  8. data/docs/agent99_framework/registry_client.md +119 -0
  9. data/docs/agent_discovery.md +66 -0
  10. data/docs/agent_lifecycle.md +137 -0
  11. data/docs/agent_registry_processes.md +108 -0
  12. data/docs/api_reference.md +146 -0
  13. data/docs/architecture.md +77 -0
  14. data/docs/breaking_change_v0.0.4.md +26 -0
  15. data/docs/configuration.md +17 -0
  16. data/docs/control_actions.md +179 -0
  17. data/docs/custom_agent_implementation.md +30 -0
  18. data/docs/diagrams/agent_registry_processes.dot +42 -0
  19. data/docs/diagrams/agent_registry_processes.png +0 -0
  20. data/docs/diagrams/high_level_architecture.dot +26 -0
  21. data/docs/diagrams/high_level_architecture.png +0 -0
  22. data/docs/diagrams/request_flow.dot +42 -0
  23. data/docs/diagrams/request_flow.png +0 -0
  24. data/docs/error_handling_and_logging.md +13 -0
  25. data/docs/extending_the_framework.md +11 -0
  26. data/docs/message_processing.md +165 -0
  27. data/docs/messaging_system.md +129 -0
  28. data/docs/preformance_considerations.md +9 -0
  29. data/docs/schema_definition.md +78 -0
  30. data/docs/security.md +9 -0
  31. data/docs/troubleshooting.md +11 -0
  32. data/docs/what_is_an_agent.md +293 -0
  33. data/examples/README.md +43 -0
  34. data/examples/agent_watcher.rb +106 -0
  35. data/examples/agents/.keep +0 -0
  36. data/examples/chief_agent.rb +17 -6
  37. data/examples/control.rb +16 -7
  38. data/examples/example_agent.rb +39 -0
  39. data/examples/kaos_spy.rb +63 -0
  40. data/examples/maxwell_agent86.rb +15 -26
  41. data/examples/registry.rb +24 -13
  42. data/lib/agent99/agent_discovery.rb +4 -0
  43. data/lib/agent99/agent_lifecycle.rb +34 -10
  44. data/lib/agent99/base.rb +5 -1
  45. data/lib/agent99/header_schema.rb +5 -0
  46. data/lib/agent99/message_processing.rb +3 -1
  47. data/lib/agent99/registry_client.rb +12 -11
  48. data/lib/agent99/tcp_message_client.rb +183 -0
  49. data/lib/agent99/version.rb +1 -1
  50. metadata +50 -3
  51. 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
+ }
@@ -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
+ }
@@ -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
+ ![Request Message Processing Flow](diagrams/request_flow.png)
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.