agent99 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +18 -1
- data/README.md +4 -2
- data/docs/README.md +57 -0
- data/docs/advanced_features.md +110 -0
- data/docs/agent_discovery.md +62 -0
- data/docs/agent_lifecycle.md +137 -0
- data/docs/agent_registry_processes.md +102 -0
- data/docs/api_reference.md +136 -0
- data/docs/architecture.md +77 -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/examples/README.md +43 -0
- data/examples/agent_watcher.rb +102 -0
- data/examples/agents/.keep +0 -0
- data/examples/example_agent.rb +26 -0
- data/examples/kaos_spy.rb +63 -0
- data/examples/registry.rb +8 -6
- data/lib/agent99/header_schema.rb +5 -0
- data/lib/agent99/version.rb +1 -1
- metadata +44 -3
- data/docs/todo.md +0 -66
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e269eac0e8a38fef70f8db9d0487fb3b723d5b928350f396cb8eae852f446897
|
4
|
+
data.tar.gz: e13090c1235e35de5c8665d7a7f6e6f0aee3a9aae999b82b1d925bdc07efcb4c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3546e420df4bb94fa6ec09cbbc4b6e735b6ceebb937f9a6438d69b7fecdeea39fa38108620d9327ca6053218e303ed77284de02886f18dce367f4b6ecb10e588
|
7
|
+
data.tar.gz: 5fb72619e4321a2db1cfcee0d959cdd7206efb21eead25dba81381008c6d893eb39fbb6205857851f34275a01a421c1c193694c874e21a12b1876de0da2e1ce9
|
data/CHANGELOG.md
CHANGED
@@ -1,8 +1,25 @@
|
|
1
|
-
|
1
|
+
# The Changelog
|
2
2
|
|
3
|
+
## [Unreleased]
|
3
4
|
|
4
5
|
## Released
|
5
6
|
|
7
|
+
### [0.0.3] - 2024-12-08
|
8
|
+
|
9
|
+
- Document advanced features and update examples
|
10
|
+
- Add AgentWatcher and ExampleAgent implementations
|
11
|
+
- Update control actions documentation for Agent99
|
12
|
+
- Add request flow diagram and update messaging docs
|
13
|
+
- Update schema documentation for improved clarity
|
14
|
+
- Reorganize documentation and update architecture details
|
15
|
+
- Update API reference with detailed implementation guidelines
|
16
|
+
- Extend agent lifecycle documentation
|
17
|
+
- Enhance agent discovery documentation and registry logic
|
18
|
+
- Add KaosSpy example agent
|
19
|
+
- Update README links to lowercase for consistency
|
20
|
+
- Add documentation for Agent99 framework
|
21
|
+
- Add Sinatra dependency and document registry processes
|
22
|
+
|
6
23
|
### [0.0.2] - 2024-12-07
|
7
24
|
|
8
25
|
- Added examples/control.rb
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Agent99 Framework (AFW)
|
2
2
|
|
3
|
-
**Under Development** Initial release has no AI components - its just a generic client-server / request-response micro-services system using a peer-to-peer messaging broker and a centralized agent registry.
|
3
|
+
**Under Development** Initial release has no AI components - its just a generic client-server / request-response micro-services system using a peer-to-peer messaging broker and a centralized agent registry. To keep up with the version changes review [The Changelog](./CHANGELOG.md) file.
|
4
4
|
|
5
5
|
Agent99 is a Ruby-based framework for building and managing AI agents in a distributed system. It provides a robust foundation for creating intelligent agents that can communicate, discover each other, and perform various tasks.
|
6
6
|
|
@@ -55,6 +55,8 @@ Whether you’re a seasoned Ruby developer or just getting started, Agent99 prov
|
|
55
55
|
- Registry Integration: Register and discover agents through a central registry
|
56
56
|
- Error Handling and Logging: Built-in error management and logging capabilities
|
57
57
|
- Control Actions: Pause, resume, update configuration, and request status of agents
|
58
|
+
- Dynamic Agent Loading: Support for runtime loading and deployment of new agents
|
59
|
+
- Multi-Agent Processing: Run multiple agents within the same process using thread isolation
|
58
60
|
|
59
61
|
## Installation
|
60
62
|
|
@@ -138,4 +140,4 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/MadBom
|
|
138
140
|
|
139
141
|
## License
|
140
142
|
|
141
|
-
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
143
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/docs/README.md
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
# Agent99 Framework Documentation
|
2
|
+
|
3
|
+
Welcome to the Agent99 Framework documentation! Below is a table of contents and brief summaries of each markdown file available in this directory. Explore each document for more detailed information on the Agent99 Framework and how to effectively utilize it in your projects!
|
4
|
+
|
5
|
+
## Table of Contents
|
6
|
+
|
7
|
+
1. **[Agent Discovery](agent_discovery.md)**
|
8
|
+
- This document explains how agents within the Agent99 framework discover each other based on their declared capabilities, including the registration and querying processes involved.
|
9
|
+
|
10
|
+
2. **[Agent Lifecycle](agent_lifecycle.md)**
|
11
|
+
- Learn about the various stages an agent undergoes during its lifetime, from creation and initialization to running and graceful shutdown.
|
12
|
+
|
13
|
+
3. **[Agent Registry Processes](agent_registry_processes.md)**
|
14
|
+
- This file details the processes handled by the Agent registry, including registration, discovery, and withdrawal of agents, along with example code to illustrate these concepts.
|
15
|
+
|
16
|
+
4. **[API Reference](api_reference.md)**
|
17
|
+
- The API Reference provides comprehensive details about public methods and classes within Agent99, ensuring developers can leverage its full capabilities.
|
18
|
+
|
19
|
+
5. **[Architecture Overview](architecture_overview.md)**
|
20
|
+
- An overview of the architecture of Agent99, describing its microservices-oriented structure, communication workflows, and how agents operate within the system.
|
21
|
+
|
22
|
+
6. **[Configuration](configuration.md)**
|
23
|
+
- Discover how to configure agents using environment variables, including important settings such as the registry base URL.
|
24
|
+
|
25
|
+
7. **[Control Actions](control_actions.md)**
|
26
|
+
- This document lists the control actions available to agents, such as shutdown, pause, and resume, along with instructions on how to create custom actions.
|
27
|
+
|
28
|
+
8. **[Custom Agent Implementation](custom_agent_implementation.md)**
|
29
|
+
- Guidelines on creating custom agents, including subclassing, defining schemas, and implementing request and response handling.
|
30
|
+
|
31
|
+
9. **[Error Handling and Logging](error_handling_and_logging.md)**
|
32
|
+
- Understanding the error handling mechanisms in Agent99, as well as how to configure logging for better monitoring and debugging.
|
33
|
+
|
34
|
+
10. **[Extending the Framework](extending_the_framework.md)**
|
35
|
+
- Instructions on how to extend Agent99 by implementing custom modules, defining new message types, and using hooks for additional functionality.
|
36
|
+
|
37
|
+
11. **[Message Processing](message_processing.md)**
|
38
|
+
- This document outlines the different message types supported by Agent99, how they are processed, and the importance of schema validation.
|
39
|
+
|
40
|
+
12. **[Messaging Systems](messaging_systems.md)**
|
41
|
+
- Overview of the messaging protocols supported by Agent99, including AMQP and NATS, and guidance on how to switch between them.
|
42
|
+
|
43
|
+
13. **[Advanced Features](advanced_features.md)**
|
44
|
+
- Learn about dynamic agent loading, multi-agent processing, and best practices for running multiple agents within the same process.
|
45
|
+
|
46
|
+
14. **[Performance Considerations](performance_considerations.md)**
|
47
|
+
- Best practices for ensuring optimal performance within the framework, including optimization techniques and profiling performance.
|
48
|
+
|
49
|
+
15. **[Schema Definition](schema_definition.md)**
|
50
|
+
- Detailed instructions on how to define schemas using `SimpleJsonSchemaBuilder`, with examples to guide you through the process.
|
51
|
+
|
52
|
+
16. **[Security](security.md)**
|
53
|
+
- Recommendations on implementing security measures within Agent99, focusing on message encryption and access control.
|
54
|
+
|
55
|
+
17. **[Troubleshooting](troubleshooting.md)**
|
56
|
+
- Common issues encountered while using Agent99 and suggested steps for debugging, including examining logs and configuration settings.
|
57
|
+
|
@@ -0,0 +1,110 @@
|
|
1
|
+
# Agent99 Framework
|
2
|
+
|
3
|
+
## Advanced Features
|
4
|
+
|
5
|
+
Ruby supports dynamic loading and deployment of libraries at runtime. Agent99 takes advantage of this ability through the `AgentWatcher` system. This powerful feature allows you to:
|
6
|
+
|
7
|
+
- Monitor a directory for new agent files
|
8
|
+
- Automatically load and instantiate new agents when detected
|
9
|
+
- Run multiple agents within the same process
|
10
|
+
- Manage agent lifecycle independently
|
11
|
+
|
12
|
+
### Using AgentWatcher
|
13
|
+
|
14
|
+
The `AgentWatcher` (found in `examples/agent_watcher.rb`) provides a framework for dynamically loading and running agents:
|
15
|
+
|
16
|
+
1. Start the AgentWatcher:
|
17
|
+
```ruby
|
18
|
+
watcher = AgentWatcher.new
|
19
|
+
watcher.run
|
20
|
+
```
|
21
|
+
|
22
|
+
2. Deploy new agents by copying their .rb files to the watched directory (default: './agents'):
|
23
|
+
```bash
|
24
|
+
cp my_new_agent.rb agents/
|
25
|
+
```
|
26
|
+
|
27
|
+
The AgentWatcher will:
|
28
|
+
- Detect the new file
|
29
|
+
- Load the agent class
|
30
|
+
- Instantiate the agent
|
31
|
+
- Run it in a separate thread
|
32
|
+
|
33
|
+
### Example Implementation
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
class MyDynamicAgent < Agent99::Base
|
37
|
+
TYPE = :server
|
38
|
+
|
39
|
+
def capabilities = ['my_capability']
|
40
|
+
|
41
|
+
def receive_request
|
42
|
+
# Handle requests
|
43
|
+
send_response(status: 'success')
|
44
|
+
end
|
45
|
+
end
|
46
|
+
```
|
47
|
+
|
48
|
+
## Multi-Agent Processing
|
49
|
+
|
50
|
+
Agent99 supports running multiple agents within the same process, with each agent running in its own thread. This approach:
|
51
|
+
|
52
|
+
- Reduces resource overhead compared to separate processes
|
53
|
+
- Maintains isolation between agents
|
54
|
+
- Allows efficient inter-agent communication
|
55
|
+
- Simplifies agent management
|
56
|
+
|
57
|
+
### Benefits
|
58
|
+
|
59
|
+
1. **Resource Efficiency**: Share common resources while maintaining agent isolation
|
60
|
+
2. **Simplified Deployment**: Manage multiple agents through a single process
|
61
|
+
3. **Enhanced Communication**: Direct inter-agent communication within the same process
|
62
|
+
4. **Centralized Management**: Monitor and control multiple agents from a single point
|
63
|
+
|
64
|
+
### Implementation Considerations
|
65
|
+
|
66
|
+
When running multiple agents in the same process:
|
67
|
+
|
68
|
+
1. Each agent runs in its own thread for isolation
|
69
|
+
2. Agents can still communicate through the standard messaging system
|
70
|
+
3. Errors in one agent won't affect others
|
71
|
+
4. Resource sharing is handled automatically by the framework
|
72
|
+
|
73
|
+
### Example Setup
|
74
|
+
|
75
|
+
Using AgentWatcher to manage multiple agents:
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
# Start the watcher
|
79
|
+
watcher = AgentWatcher.new
|
80
|
+
watcher.run
|
81
|
+
|
82
|
+
# Deploy multiple agents
|
83
|
+
cp agent1.rb agents/
|
84
|
+
cp agent2.rb agents/
|
85
|
+
cp agent3.rb agents/
|
86
|
+
```
|
87
|
+
|
88
|
+
Each agent will run independently in its own thread while sharing the same process space.
|
89
|
+
|
90
|
+
## Best Practices
|
91
|
+
|
92
|
+
1. **Error Handling**
|
93
|
+
- Implement proper error handling in each agent
|
94
|
+
- Use the built-in logging system
|
95
|
+
- Monitor agent health through status checks
|
96
|
+
|
97
|
+
2. **Resource Management**
|
98
|
+
- Monitor memory usage when running many agents
|
99
|
+
- Implement proper cleanup in the `fini` method
|
100
|
+
- Use appropriate thread pool sizes
|
101
|
+
|
102
|
+
3. **Deployment**
|
103
|
+
- Use meaningful file names for easy identification
|
104
|
+
- Maintain clear separation of concerns between agents
|
105
|
+
- Document agent dependencies and requirements
|
106
|
+
|
107
|
+
4. **Monitoring**
|
108
|
+
- Implement health checks in your agents
|
109
|
+
- Use logging for debugging and monitoring
|
110
|
+
- Set up appropriate alerting for critical agents
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# Agent99 Framework
|
2
|
+
|
3
|
+
## Agent Discovery
|
4
|
+
|
5
|
+
Agents within the Agent99 Framework can efficiently discover one another based on their declared capabilities. This feature fosters dynamic interactions that enhance the collaborative functionality of the agents.
|
6
|
+
|
7
|
+
### Overview
|
8
|
+
|
9
|
+
The agent discovery process involves the following steps:
|
10
|
+
|
11
|
+
1. **Registration**: Agents register their capabilities with a central registry upon startup.
|
12
|
+
2. **Discovery**: When an agent needs to discover other agents, it queries the registry for agents with specific capabilities.
|
13
|
+
3. **Response**: The registry responds with a list of available agents, allowing them to interact based on their capabilities.
|
14
|
+
|
15
|
+
### Declaring Capabilities
|
16
|
+
|
17
|
+
Each agent must implement the `capabilities` method to declare its capabilities as an array of strings:
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
def capabilities
|
21
|
+
['process_image', 'face_detection']
|
22
|
+
end
|
23
|
+
```
|
24
|
+
|
25
|
+
**Note**: The discovery mechanism is based on an exact match (case insensitive) between the requested capability and the entries in the agent's capabilities array. For example, if an agent declares its capabilities as mentioned above, a discovery request for `'FACE_DETECTION'` will successfully match.
|
26
|
+
|
27
|
+
### Discovery API
|
28
|
+
|
29
|
+
To find other agents, use the `discover_agent` method. Here are some usage examples:
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
# Find a single agent with a specific capability
|
33
|
+
agent = discover_agent(capability: 'face_detection')
|
34
|
+
|
35
|
+
# Find multiple agents
|
36
|
+
agents = discover_agent(capability: 'process_image', how_many: 3)
|
37
|
+
|
38
|
+
# Find all agents with a specific capability
|
39
|
+
all_agents = discover_agent(capability: 'process_image', all: true)
|
40
|
+
```
|
41
|
+
|
42
|
+
### Important Note on Capabilities
|
43
|
+
|
44
|
+
- **Single Capability**: A seeking agent can only request one kind of capability at a time.
|
45
|
+
- **Semantics-Based Capabilities**: The development roadmap includes enhancements towards semantic-based capabilities that could allow for more complex interactions between agents in the future. This would be a change from the current Array of Strings to a single String that is a description of the services the agent provides. This would be consistent with the way in which LLMs currently find Tools for augmented generation.
|
46
|
+
|
47
|
+
### Registry Configuration
|
48
|
+
|
49
|
+
The registry client comes with default settings, which you can override as needed:
|
50
|
+
|
51
|
+
- **URL**: Default is `http://localhost:4567` (you can override this using the `REGISTRY_BASE_URL` environment variable).
|
52
|
+
- **Interface**: Supports a standard HTTP REST interface.
|
53
|
+
- **Reconnection**: Automatic reconnection handling is provided to ensure reliable communication.
|
54
|
+
|
55
|
+
### Best Practices
|
56
|
+
|
57
|
+
1. **Check Discovery Success**: Always verify if agent discovery succeeded before attempting to establish communication with the discovered agent.
|
58
|
+
2. **Use Specific Capability Names**: This ensures that the correct agents are matched during the discovery process, avoiding ambiguity.
|
59
|
+
3. **Implement Multiple Capabilities**: Consider declaring multiple capabilities per agent to enhance its versatility and improve interaction possibilities.
|
60
|
+
|
61
|
+
With these guidelines, you can effectively implement and utilize the agent discovery feature within the Agent99 Framework, ensuring robust and dynamic interactions among agents based on their declared capabilities.
|
62
|
+
|
@@ -0,0 +1,137 @@
|
|
1
|
+
# Agent99 Framework
|
2
|
+
|
3
|
+
## Agent Lifecycle
|
4
|
+
|
5
|
+
The lifecycle of an agent within Agent99 consists of several key stages that are managed through dedicated lifecycle methods. Understanding these stages and their corresponding methods is crucial for proper agent implementation.
|
6
|
+
|
7
|
+
### Lifecycle Stages
|
8
|
+
|
9
|
+
1. **Creation**: An agent is instantiated through the `Agent99::Base` class.
|
10
|
+
2. **Initialization**: The agent sets up resources and establishes connections.
|
11
|
+
3. **Running**: The agent processes messages and performs its designated tasks.
|
12
|
+
4. **Shutdown**: The agent performs cleanup and gracefully terminates.
|
13
|
+
|
14
|
+
### Core Lifecycle Methods
|
15
|
+
|
16
|
+
#### The `init` Method
|
17
|
+
|
18
|
+
The `init` method is called automatically after the agent has been registered but before it starts processing messages. Its primary purpose is to perform any additional setup required for the agent following the default initialization provided by the `Agent99::Base` class. This may include:
|
19
|
+
|
20
|
+
- Setting up initial state
|
21
|
+
- Establishing connections to other agents or resources
|
22
|
+
- Discovering dependencies or agents to communicate with
|
23
|
+
- Sending initial messages to specific agents
|
24
|
+
|
25
|
+
Here’s an example implementation:
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
def init
|
29
|
+
@state = initialize_state
|
30
|
+
@resources = setup_resources
|
31
|
+
end
|
32
|
+
```
|
33
|
+
|
34
|
+
#### Custom Initialization
|
35
|
+
|
36
|
+
Agents can choose to either use the default behavior provided by the `Agent99::Base` class or implement their own `initialize` method to customize the `logger`, `message_client`, and `registry_client` attributes. For instance:
|
37
|
+
|
38
|
+
1. **Using Defaults**: If you do not define an `initialize` method in your agent class, it will inherit the defaults:
|
39
|
+
|
40
|
+
```ruby
|
41
|
+
class MyAgent < Agent99::Base
|
42
|
+
# Inherits default logger, message_client, and registry_client
|
43
|
+
end
|
44
|
+
```
|
45
|
+
|
46
|
+
2. **Customizing Initialization**: If you need custom initialization, you can ignore the `init` method and override the `initialize` method:
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
class MyCustomAgent < Agent99::Base
|
50
|
+
def initialize(
|
51
|
+
registry_client: CustomRegistryClient.new,
|
52
|
+
message_client: CustomMessageClient.new,
|
53
|
+
logger: Logger.new('custom_agent.log')
|
54
|
+
)
|
55
|
+
super # Registers the Agent and setups its message queue
|
56
|
+
|
57
|
+
# Additional state or resource initialization required
|
58
|
+
# by the new agent
|
59
|
+
end
|
60
|
+
end
|
61
|
+
```
|
62
|
+
|
63
|
+
In this case, the custom agent not need the `init` method to perform any additional setup.
|
64
|
+
|
65
|
+
#### The `fini` Method
|
66
|
+
|
67
|
+
The `fini` method is setup to be invoked when the `exit` method is called within `initialize` method by the `on_exit { fini }` hook.
|
68
|
+
|
69
|
+
The `fini` method ensures proper cleanup during agent shutdown:
|
70
|
+
|
71
|
+
The default `fini` method does:
|
72
|
+
- Withdrawing from the registry
|
73
|
+
- Closing message queue connections
|
74
|
+
|
75
|
+
If your agent requires additional cleanup or state presistence you should implement a custom `fini` method to do things like:
|
76
|
+
- Cleaning up resources
|
77
|
+
- Saving state (if required)
|
78
|
+
- Releasing system resources
|
79
|
+
|
80
|
+
Example implementation:
|
81
|
+
|
82
|
+
```ruby
|
83
|
+
def fini
|
84
|
+
save_state if @state
|
85
|
+
cleanup_resources
|
86
|
+
deregister_from_registry
|
87
|
+
|
88
|
+
super # Always call super last for proper framework cleanup
|
89
|
+
end
|
90
|
+
```
|
91
|
+
|
92
|
+
### Best Practices
|
93
|
+
|
94
|
+
1. **Proper Method Ordering**:
|
95
|
+
- Always call `super` first in `initialize`.
|
96
|
+
- Always call `super` last in `fini`.
|
97
|
+
- This order ensures proper framework initialization and cleanup.
|
98
|
+
|
99
|
+
2. **Resource Management**:
|
100
|
+
- Initialize all resources in `init` or `initialize`.
|
101
|
+
- Clean up all resources in `fini`.
|
102
|
+
- Handle cleanup idempotently.
|
103
|
+
|
104
|
+
3. **Error Handling**:
|
105
|
+
- Implement robust error handling in all methods.
|
106
|
+
- Ensure `fini` can handle partial initialization states.
|
107
|
+
- Log all significant lifecycle events.
|
108
|
+
|
109
|
+
4. **State Management**:
|
110
|
+
- Initialize state clearly.
|
111
|
+
- Save or cleanup state properly in `fini`.
|
112
|
+
- Consider persistence needs.
|
113
|
+
|
114
|
+
### Important Considerations
|
115
|
+
|
116
|
+
- Agents can be implemented as stand-alone processes.
|
117
|
+
- When an agent is implemented within the context of a larger application process, the agent should be "run" within its own thread.
|
118
|
+
```ruby
|
119
|
+
begin
|
120
|
+
my_agent = MyAgent.new
|
121
|
+
Thread.new { my_agent.run }
|
122
|
+
end
|
123
|
+
```
|
124
|
+
- Agents handle only one request message at a time.
|
125
|
+
- The `fini` method is called automatically during graceful shutdowns.
|
126
|
+
|
127
|
+
### Framework Integration
|
128
|
+
|
129
|
+
The Agent99 framework automatically manages the lifecycle of agents:
|
130
|
+
|
131
|
+
1. Calls `init` (if present) after agent creation.
|
132
|
+
2. Monitors agent health during operation.
|
133
|
+
3. Calls `fini` during shutdown (`on_exit {fini}`).
|
134
|
+
4. Handles cleanup if initialization fails.
|
135
|
+
|
136
|
+
This automated lifecycle management ensures reliable agent operation within the framework.
|
137
|
+
|
@@ -0,0 +1,102 @@
|
|
1
|
+
# Agent99 Framework
|
2
|
+
|
3
|
+
## Agent Registry Processes
|
4
|
+
|
5
|
+
In the Agent99 framework, an instance of the `Agent99::RegistryClient` class is responsible for registering agent capabilities with a centralized registry. `examples/registry.rb` is a Sinatra web-app example of what a centralized regristry service should be.
|
6
|
+
|
7
|
+
The registration process is transparent to a new instance of an `Agent99::Base` class.
|
8
|
+
|
9
|
+
First thing: start the registry.rb Sinatra app and the peer-to-peer messaging network. The default is the `AmqpMessageClient` class.
|
10
|
+
|
11
|
+
If you do not have the RabbitMQ server installed on your Macthen then grab it using `brew install rabbitmq-server` and while you are installing software do `brew install boxes` as well since the `chief_agent.rb` example uses that little CLI tool to highlight some text in the terminal.
|
12
|
+
|
13
|
+
```bash
|
14
|
+
git clone ssh://git@github.com/MadBomber/agent99
|
15
|
+
brew install rabbitmq-server boxes
|
16
|
+
gem install agent99
|
17
|
+
|
18
|
+
cd agent99/examples
|
19
|
+
./start_rabbitmq_and_registry.sh
|
20
|
+
```
|
21
|
+
|
22
|
+
Now go into `irb` in a different terminal window and try this code ...
|
23
|
+
|
24
|
+
```ruby
|
25
|
+
require 'agent99'
|
26
|
+
|
27
|
+
# Define the Schema for the Agent's request payload
|
28
|
+
|
29
|
+
class MyAgentRequest < SimpleJsonSchemaBuilder::Base
|
30
|
+
object do
|
31
|
+
object :header, schema: Agent99::HeaderSchema
|
32
|
+
|
33
|
+
string :greeting, required: false, examples: ["Hello"]
|
34
|
+
string :name, required: true, examples: ["World"]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Define the new Agent ....
|
39
|
+
|
40
|
+
class MyAgent < Agent99::Base
|
41
|
+
REQUEST_SCHEMA = MyAgentRequest.schema
|
42
|
+
def capabilities = %w[ greeter hello_world ]
|
43
|
+
end
|
44
|
+
|
45
|
+
# You may create multiple instances of the agent if needed
|
46
|
+
|
47
|
+
my_agent = MyAgent.new
|
48
|
+
|
49
|
+
I, [2024-12-07T14:42:08.140286 #36471] INFO -- : Registered Agent MyAgent with ID: 9e735449-582f-46e2-8f11-371e584d0f08
|
50
|
+
I, [2024-12-07T14:42:08.141978 #36471] INFO -- : Created queue for agent_id: 9e735449-582f-46e2-8f11-371e584d0f08
|
51
|
+
#=>
|
52
|
+
#<MyAgent:0x000000011d4d2e48
|
53
|
+
...
|
54
|
+
|
55
|
+
# The agent as an ID and an address in the peer-to-peer network
|
56
|
+
|
57
|
+
my_agent.id
|
58
|
+
#=> "9e735449-582f-46e2-8f11-371e584d0f08"
|
59
|
+
```
|
60
|
+
|
61
|
+
The image below shows how the `Agent99::Base` class uses dependency injection in its constructor method to bring in an instance of the `RegristryClient` class to provide an interface to the centralized regristery service.
|
62
|
+
|
63
|
+

|
64
|
+
|
65
|
+
The above image also show the other services provided via the RegistryClient class.
|
66
|
+
|
67
|
+
The example centralized regristry service provides three processes:
|
68
|
+
|
69
|
+
1. Registration Process:
|
70
|
+
- MyAgent initializes the RegistryClient
|
71
|
+
- RegistryClient sends a POST request to the Central Registry
|
72
|
+
- Central Registry responds with a UUID
|
73
|
+
- RegistryClient returns the UUID to MyAgent
|
74
|
+
2. Discovery Process:
|
75
|
+
- MyAgent requests discovery of agents with a specific capability
|
76
|
+
- RegistryClient sends a GET request to the Central Registry
|
77
|
+
- Central Registry responds with matching agents
|
78
|
+
- RegistryClient returns the matching agents to MyAgent
|
79
|
+
3. Withdrawal Process:
|
80
|
+
- MyAgent requests withdrawal using its UUID
|
81
|
+
- RegistryClient sends a DELETE request to the Central Registry
|
82
|
+
- Central Registry responds with a 204 No Content
|
83
|
+
- RegistryClient confirms the withdrawal to MyAgent
|
84
|
+
|
85
|
+
Like the register process, the withdraw process is also transparent. Its executed on any exit via the public method `fini` in the base class' `on_exit {...}` handler. Calling `exit` for any reason within your agent class will withdraw it from the central registry and remove its message queue from peer-to-peer messaging network.
|
86
|
+
|
87
|
+
The discover process is primary business logic for your agent class. You must call the `@registry_client.discover(capability: "whatever")` method directly within the agents process.
|
88
|
+
|
89
|
+
For example suppose your agent needs to work with other agents that provide the "pne", "twp" and "three" services. That is 3 outside agents. You can do this in the `init` method for you agent.
|
90
|
+
|
91
|
+
```ruby
|
92
|
+
class MyAgent < Agent99::Base
|
93
|
+
def init
|
94
|
+
@agnet_1 = discover_agent(capability: 'one')
|
95
|
+
@agnet_2 = discover_agent(capability: 'two')
|
96
|
+
@agnet_3 = discover_agent(capability: 'three')
|
97
|
+
end
|
98
|
+
end
|
99
|
+
```
|
100
|
+
|
101
|
+
`discover_agent` is the `Agent99::Base` method that links to the registry client's instance to do the discovery via the central registry. Other parameters to `discover_agent` allow's you agent to specify `how_many` agents having the specify capability you want returned. The default is 1. If you want all the agents capable of providing the requested service use the `all: true` parameter with the `discover_agent` method.
|
102
|
+
|
@@ -0,0 +1,136 @@
|
|
1
|
+
# Agent99 Framework API Reference
|
2
|
+
|
3
|
+
## Agent Implementation Requirements
|
4
|
+
|
5
|
+
When creating a new agent by subclassing `Agent99::Base`, you must implement certain methods and may optionally override others.
|
6
|
+
|
7
|
+
### Required Methods
|
8
|
+
|
9
|
+
#### `capabilities`
|
10
|
+
Returns an array of strings describing the agent's capabilities.
|
11
|
+
```ruby
|
12
|
+
def capabilities
|
13
|
+
['process_image', 'face_detection']
|
14
|
+
end
|
15
|
+
```
|
16
|
+
|
17
|
+
#### `receive_request`
|
18
|
+
Handles incoming request messages. Must be implemented if the agent accepts requests.
|
19
|
+
```ruby
|
20
|
+
def receive_request
|
21
|
+
# Process the request message in @payload
|
22
|
+
# Access message data via @payload[:data]
|
23
|
+
# Send response using send_response(response_data)
|
24
|
+
end
|
25
|
+
```
|
26
|
+
|
27
|
+
### Optional Methods
|
28
|
+
|
29
|
+
#### `init`
|
30
|
+
Called after registration but before message processing begins. Use for additional setup.
|
31
|
+
```ruby
|
32
|
+
def init
|
33
|
+
@state = initialize_state
|
34
|
+
@resources = setup_resources
|
35
|
+
end
|
36
|
+
```
|
37
|
+
|
38
|
+
#### `fini`
|
39
|
+
Called during shutdown. Override to add custom cleanup.
|
40
|
+
```ruby
|
41
|
+
def fini
|
42
|
+
cleanup_resources
|
43
|
+
save_state if @state
|
44
|
+
super # Always call super last
|
45
|
+
end
|
46
|
+
```
|
47
|
+
|
48
|
+
#### `receive_response`
|
49
|
+
Handles incoming response messages. Override if the agent processes responses.
|
50
|
+
```ruby
|
51
|
+
def receive_response
|
52
|
+
# Process the response message in @payload
|
53
|
+
end
|
54
|
+
```
|
55
|
+
|
56
|
+
## Message Client Interface
|
57
|
+
|
58
|
+
To implement a custom message client, create a class that implements these methods:
|
59
|
+
|
60
|
+
### Required Methods
|
61
|
+
|
62
|
+
#### `initialize(logger: Logger.new($stdout))`
|
63
|
+
Sets up the messaging connection.
|
64
|
+
|
65
|
+
#### `setup(agent_id:, logger:)`
|
66
|
+
Initializes message queues/topics for the agent.
|
67
|
+
- Returns: queue/topic identifier
|
68
|
+
|
69
|
+
#### `listen_for_messages(queue, request_handler:, response_handler:, control_handler:)`
|
70
|
+
Starts listening for messages.
|
71
|
+
- `queue`: Queue/topic to listen on
|
72
|
+
- `request_handler`: Lambda for handling requests
|
73
|
+
- `response_handler`: Lambda for handling responses
|
74
|
+
- `control_handler`: Lambda for handling control messages
|
75
|
+
|
76
|
+
#### `publish(message)`
|
77
|
+
Publishes a message.
|
78
|
+
- `message`: Hash containing the message with :header and payload
|
79
|
+
- Returns: Hash with :success and optional :error
|
80
|
+
|
81
|
+
#### `delete_queue(queue_name)`
|
82
|
+
Cleans up agent's message queue/topic.
|
83
|
+
|
84
|
+
## Registry Client Interface
|
85
|
+
|
86
|
+
To implement a custom registry client, create a class that implements these methods:
|
87
|
+
|
88
|
+
### Required Methods
|
89
|
+
|
90
|
+
#### `initialize(base_url: ENV.fetch('REGISTRY_BASE_URL', 'http://localhost:4567'), logger: Logger.new($stdout))`
|
91
|
+
Sets up the registry connection.
|
92
|
+
|
93
|
+
#### `register(name:, capabilities:)`
|
94
|
+
Registers an agent with the registry.
|
95
|
+
- Returns: UUID string for the agent
|
96
|
+
|
97
|
+
#### `withdraw(id)`
|
98
|
+
Removes an agent from the registry.
|
99
|
+
|
100
|
+
## Base Class Public Methods
|
101
|
+
|
102
|
+
The `Agent99::Base` class provides these public methods:
|
103
|
+
|
104
|
+
#### `run`
|
105
|
+
Starts the agent's message processing loop.
|
106
|
+
|
107
|
+
#### `discover_agent(capability:, how_many: 1, all: false)`
|
108
|
+
Finds other agents by capability.
|
109
|
+
- Returns: Array of agent information hashes
|
110
|
+
|
111
|
+
#### `send_response(response)`
|
112
|
+
Sends a response message.
|
113
|
+
- `response`: Hash containing the response data
|
114
|
+
|
115
|
+
## Message Types
|
116
|
+
|
117
|
+
Messages in Agent99 must include a `:header` with:
|
118
|
+
- `:type`: One of "request", "response", or "control"
|
119
|
+
- `:to_uuid`: Destination agent's UUID
|
120
|
+
- `:from_uuid`: Sending agent's UUID
|
121
|
+
- `:event_uuid`: UUID to link request to response
|
122
|
+
- `:timestamp`: Integer (`Agent99::Timestamp.new.to_i`)
|
123
|
+
|
124
|
+
Example request message structure:
|
125
|
+
```ruby
|
126
|
+
{
|
127
|
+
header: {
|
128
|
+
type: 'request',
|
129
|
+
to_uuid: ,
|
130
|
+
from_uuid: ,
|
131
|
+
event_uuid: ,
|
132
|
+
timestamp: ,
|
133
|
+
},
|
134
|
+
# agent specific parameters
|
135
|
+
}
|
136
|
+
```
|