agent99 0.0.3 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/A2A_SPEC-dev.md +1829 -0
- data/CHANGELOG.md +38 -0
- data/COMMITS.md +196 -0
- data/DOCS.md +96 -0
- data/README.md +212 -84
- data/Rakefile +62 -0
- data/docs/AI/htm.md +215 -0
- data/docs/AI/htm.rb +141 -0
- data/docs/AI/htm_demo.db +0 -0
- data/docs/AI/notes_on_htm_implementation.md +1319 -0
- data/docs/AI/some_code.rb +692 -0
- data/docs/advanced-topics/a2a-protocol.md +13 -0
- data/docs/{advanced_features.md → advanced-topics/advanced-features.md} +9 -4
- data/docs/{control_actions.md → advanced-topics/control-actions.md} +2 -0
- data/docs/advanced-topics/model-context-protocol.md +4 -0
- data/docs/advanced-topics/multi-agent-processing.md +674 -0
- data/docs/agent-development/request-response-handling.md +512 -0
- data/docs/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/api-reference/agent99-base.md +463 -0
- data/docs/api-reference/message-clients.md +495 -0
- data/docs/{api_reference.md → api-reference/overview.md} +14 -4
- data/docs/api-reference/registry-client.md +470 -0
- data/docs/api-reference/schemas.md +518 -0
- data/docs/assets/css/custom.css +27 -0
- data/docs/assets/images/agent-lifecycle.svg +73 -0
- data/docs/assets/images/agent-registry-process.svg +86 -0
- data/docs/assets/images/agent-registry-processes.svg +114 -0
- data/docs/assets/images/agent-types-overview.svg +51 -0
- data/docs/assets/images/agent99-architecture.svg +85 -0
- data/docs/assets/images/agent99_logo.png +0 -0
- data/docs/assets/images/control-actions-state.svg +83 -0
- data/docs/assets/images/knowledge-graph.svg +77 -0
- data/docs/assets/images/message-processing-flow.svg +148 -0
- data/docs/assets/images/multi-agent-system.svg +66 -0
- data/docs/assets/images/proxy-pattern-sequence.svg +48 -0
- data/docs/assets/images/request-flow.svg +97 -0
- data/docs/assets/images/request-processing-lifecycle.svg +50 -0
- data/docs/assets/images/request-response-sequence.svg +39 -0
- data/docs/{agent_lifecycle.md → core-concepts/agent-lifecycle.md} +2 -0
- data/docs/core-concepts/agent-types.md +255 -0
- data/docs/{architecture.md → core-concepts/architecture.md} +5 -5
- data/docs/core-concepts/what-is-an-agent.md +293 -0
- data/docs/diagrams/message-flow-sequence.svg +198 -0
- data/docs/diagrams/p2p-network-topology.svg +181 -0
- data/docs/diagrams/smart-transport-routing.svg +165 -0
- data/docs/diagrams/three-layer-architecture.svg +77 -0
- data/docs/diagrams/transport-extension-api.svg +309 -0
- data/docs/diagrams/transport-extension-architecture.svg +234 -0
- data/docs/diagrams/transport-selection-flowchart.svg +264 -0
- data/docs/examples/advanced-examples.md +951 -0
- data/docs/examples/basic-examples.md +268 -0
- data/docs/{agent_discovery.md → framework-components/agent-discovery.md} +9 -5
- data/docs/{agent_registry_processes.md → framework-components/agent-registry.md} +9 -3
- data/docs/{message_processing.md → framework-components/message-processing.md} +3 -1
- data/docs/getting-started/basic-example.md +306 -0
- data/docs/getting-started/installation.md +160 -0
- data/docs/getting-started/overview.md +64 -0
- data/docs/getting-started/quick-start.md +179 -0
- data/docs/index.md +97 -0
- data/docs/operations/breaking-changes.md +26 -0
- data/examples/DEMO.md +148 -0
- data/examples/README.md +50 -0
- data/examples/agent_watcher.rb +5 -1
- data/examples/bad_agent.rb +32 -0
- data/examples/chief_agent.rb +17 -6
- data/examples/control.rb +16 -7
- data/examples/example_agent.rb +16 -3
- data/examples/maxwell_agent86.rb +15 -26
- data/examples/registry.rb +10 -9
- data/examples/run_demo.rb +433 -0
- data/lib/agent99/agent_discovery.rb +4 -0
- data/lib/agent99/agent_lifecycle.rb +34 -10
- data/lib/agent99/amqp_message_client.rb +2 -2
- data/lib/agent99/base.rb +6 -2
- data/lib/agent99/message_processing.rb +6 -10
- data/lib/agent99/registry_client.rb +15 -11
- data/lib/agent99/tcp_message_client.rb +183 -0
- data/lib/agent99/version.rb +1 -1
- data/lib/agent99.rb +1 -1
- data/mkdocs.yml +195 -0
- data/p2p_plan.md +533 -0
- data/p2p_roadmap.md +299 -0
- data/registry_plan.md +1818 -0
- metadata +93 -30
- data/docs/README.md +0 -57
- data/docs/diagrams/agent_registry_processes.dot +0 -42
- data/docs/diagrams/agent_registry_processes.png +0 -0
- data/docs/diagrams/high_level_architecture.dot +0 -26
- data/docs/diagrams/high_level_architecture.png +0 -0
- data/docs/diagrams/request_flow.dot +0 -42
- data/docs/diagrams/request_flow.png +0 -0
- /data/docs/{extending_the_framework.md → advanced-topics/extending-the-framework.md} +0 -0
- /data/docs/{custom_agent_implementation.md → agent-development/custom-agent-implementation.md} +0 -0
- /data/docs/{error_handling_and_logging.md → agent-development/error-handling-and-logging.md} +0 -0
- /data/docs/{schema_definition.md → agent-development/schema-definition.md} +0 -0
- /data/docs/{messaging_system.md → framework-components/messaging-system.md} +0 -0
- /data/docs/{configuration.md → operations/configuration.md} +0 -0
- /data/docs/{preformance_considerations.md → operations/performance-considerations.md} +0 -0
- /data/docs/{security.md → operations/security.md} +0 -0
- /data/docs/{troubleshooting.md → operations/troubleshooting.md} +0 -0
@@ -0,0 +1,120 @@
|
|
1
|
+
# Message Client Documentation for Agent99 Framework
|
2
|
+
|
3
|
+
## Overview
|
4
|
+
|
5
|
+
The Message Client is a crucial component of the Agent99 Framework, providing an interface for agents to communicate with each other through a message broker. This document outlines the required methods and functionalities that should be implemented in any message client to ensure compatibility with the Agent99 Framework.
|
6
|
+
|
7
|
+
## Message Format Requirements
|
8
|
+
|
9
|
+
All messages sent and received through the Agent99 Framework must adhere to the following format requirements:
|
10
|
+
|
11
|
+
1. **JSON Format**: All messages must be in JSON format. This ensures consistency and ease of parsing across different implementations and languages.
|
12
|
+
|
13
|
+
2. **Header Element**: Each message must include a `header` element that conforms to the `HeaderSchema` defined for the Agent99 Framework. The `HeaderSchema` is as follows:
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
class Agent99::HeaderSchema < SimpleJsonSchemaBuilder::Base
|
17
|
+
object do
|
18
|
+
string :from_uuid, required: true, examples: [SecureRandom.uuid]
|
19
|
+
string :to_uuid, required: true, examples: [SecureRandom.uuid]
|
20
|
+
string :event_uuid, required: true, examples: [SecureRandom.uuid]
|
21
|
+
string :type, required: true, examples: %w[request response control]
|
22
|
+
integer :timestamp, required: true, examples: [Agent99::Timestamp.new.to_i]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
```
|
26
|
+
|
27
|
+
3. **Message Types**: The `type` field in the header must be one of: `request`, `response`, or `control`.
|
28
|
+
|
29
|
+
4. **Validation**: All incoming messages are validated against the appropriate schema based on their type. If validation errors are found, an error response message is returned to the sender.
|
30
|
+
|
31
|
+
## Class: MessageClient
|
32
|
+
|
33
|
+
### Initialization
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
def initialize(config: {}, logger: Logger.new($stdout))
|
37
|
+
# Implementation details...
|
38
|
+
end
|
39
|
+
```
|
40
|
+
|
41
|
+
Creates a new instance of the MessageClient.
|
42
|
+
|
43
|
+
- `config:` A hash containing configuration options for the message broker connection.
|
44
|
+
- `logger:` A logger instance for output (default: stdout logger).
|
45
|
+
|
46
|
+
### Public Methods
|
47
|
+
|
48
|
+
#### setup
|
49
|
+
|
50
|
+
```ruby
|
51
|
+
def setup(agent_id:, logger:)
|
52
|
+
# Implementation details...
|
53
|
+
end
|
54
|
+
```
|
55
|
+
|
56
|
+
Sets up the necessary resources for an agent to start communicating.
|
57
|
+
|
58
|
+
- `agent_id:` The unique identifier for the agent.
|
59
|
+
- `logger:` A logger instance for output.
|
60
|
+
- Returns: An object representing the agent's message queue or channel.
|
61
|
+
|
62
|
+
#### listen_for_messages
|
63
|
+
|
64
|
+
```ruby
|
65
|
+
def listen_for_messages(
|
66
|
+
queue,
|
67
|
+
request_handler:,
|
68
|
+
response_handler:,
|
69
|
+
control_handler:
|
70
|
+
)
|
71
|
+
# Implementation details...
|
72
|
+
end
|
73
|
+
```
|
74
|
+
|
75
|
+
Starts listening for incoming messages on the specified queue.
|
76
|
+
|
77
|
+
- `queue:` The queue or channel object returned by the `setup` method.
|
78
|
+
- `request_handler:` A callable object to handle incoming request messages.
|
79
|
+
- `response_handler:` A callable object to handle incoming response messages.
|
80
|
+
- `control_handler:` A callable object to handle incoming control messages.
|
81
|
+
|
82
|
+
#### publish
|
83
|
+
|
84
|
+
```ruby
|
85
|
+
def publish(message:)
|
86
|
+
# Implementation details...
|
87
|
+
end
|
88
|
+
```
|
89
|
+
|
90
|
+
Publishes a message to the specified queue.
|
91
|
+
|
92
|
+
- `message:` A hash containing the message to be published. This must be in JSON format and include a header that conforms to the `HeaderSchema`.
|
93
|
+
- Returns: A hash indicating the success or failure of the publish operation, including details if the message structure is invalid.
|
94
|
+
|
95
|
+
#### delete_queue
|
96
|
+
|
97
|
+
```ruby
|
98
|
+
def delete_queue(queue_name:)
|
99
|
+
# Implementation details...
|
100
|
+
end
|
101
|
+
```
|
102
|
+
|
103
|
+
Deletes the specified queue or cleans up resources associated with it.
|
104
|
+
|
105
|
+
- `queue_name:` The name of the queue to be deleted.
|
106
|
+
|
107
|
+
### Implementation Notes
|
108
|
+
|
109
|
+
1. **Message Validation**: Implement thorough validation for all incoming and outgoing messages. Ensure that they are in JSON format and contain a header that conforms to the `HeaderSchema`. If validation fails for incoming messages, send an error response to the sender with details about the validation issues.
|
110
|
+
|
111
|
+
2. **Error Handling**: Implement robust error handling for all methods, especially for connection, publishing, and validation errors.
|
112
|
+
|
113
|
+
3. **Logging**: Provide detailed logging for all operations, including successful actions, validation results, and errors.
|
114
|
+
|
115
|
+
4. **Performance and Scalability**: Optimize the client to handle a large number of JSON-formatted messages efficiently, considering potential performance impacts of validation.
|
116
|
+
|
117
|
+
5. **Thread Safety**: Ensure that the client is thread-safe, particularly when handling message validation and publishing.
|
118
|
+
|
119
|
+
By adhering to these requirements and implementing the MessageClient with these considerations, developers can ensure that their implementations will be fully compatible with the Agent99 Framework. The strict adherence to JSON formatting and the inclusion of a standardized header in all messages promotes consistency and reliability in inter-agent communication within the framework.
|
120
|
+
|
@@ -0,0 +1,119 @@
|
|
1
|
+
# RegistryClient Documentation
|
2
|
+
|
3
|
+
## Overview
|
4
|
+
|
5
|
+
The RegistryClient class is a crucial component of the Agent99 framework, providing a Ruby interface to interact with the Central Registry service. It encapsulates the HTTP communication logic required to register agents, discover capabilities, and manage agent lifecycle within the Agent99 ecosystem.
|
6
|
+
|
7
|
+
## Class: Agent99::RegistryClient
|
8
|
+
|
9
|
+
### Initialization
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
def initialize(base_url: ENV.fetch('REGISTRY_BASE_URL', 'http://localhost:4567'),
|
13
|
+
logger: Logger.new($stdout))
|
14
|
+
```
|
15
|
+
|
16
|
+
Creates a new instance of the RegistryClient.
|
17
|
+
|
18
|
+
- `base_url`: The URL of the Central Registry service (default: http://localhost:4567)
|
19
|
+
- `logger`: A logger instance for output (default: stdout logger)
|
20
|
+
|
21
|
+
### Public Methods
|
22
|
+
|
23
|
+
#### register
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
def register(name:, capabilities:)
|
27
|
+
```
|
28
|
+
|
29
|
+
Registers an agent with the Central Registry.
|
30
|
+
|
31
|
+
- `name`: The name of the agent
|
32
|
+
- `capabilities`: An array of capabilities the agent possesses
|
33
|
+
- Returns: The UUID of the registered agent
|
34
|
+
|
35
|
+
One of the first improvement that should be considered when registering a new agent is adding its JSON schema for its request and response messages. This way there should be no question about how to interface with the agent.
|
36
|
+
|
37
|
+
#### withdraw
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
def withdraw(id)
|
41
|
+
```
|
42
|
+
|
43
|
+
Withdraws an agent from the Central Registry.
|
44
|
+
|
45
|
+
- `id`: The UUID of the agent to withdraw
|
46
|
+
- Returns: nil
|
47
|
+
|
48
|
+
#### discover
|
49
|
+
|
50
|
+
```ruby
|
51
|
+
def discover(capability:)
|
52
|
+
```
|
53
|
+
|
54
|
+
Discovers agents with a specific capability.
|
55
|
+
|
56
|
+
- `capability`: The capability to search for
|
57
|
+
- Returns: An array of agents matching the capability
|
58
|
+
|
59
|
+
#### fetch_all_agents
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
def fetch_all_agents
|
63
|
+
```
|
64
|
+
|
65
|
+
Retrieves all registered agents from the Central Registry.
|
66
|
+
|
67
|
+
- Returns: An array of all registered agents
|
68
|
+
|
69
|
+
### Private Methods
|
70
|
+
|
71
|
+
The class includes several private methods for handling HTTP requests and responses:
|
72
|
+
|
73
|
+
- `create_request`: Creates an HTTP request object
|
74
|
+
- `send_request`: Sends an HTTP request and handles exceptions
|
75
|
+
- `handle_response`: Processes the HTTP response based on its status code
|
76
|
+
|
77
|
+
## Usage Example
|
78
|
+
|
79
|
+
```ruby
|
80
|
+
client = Agent99::RegistryClient.new
|
81
|
+
agent_id = client.register(name: "TextAnalyzer", capabilities: ["sentiment analysis", "named entity recognition"])
|
82
|
+
matching_agents = client.discover(capability: "sentiment analysis")
|
83
|
+
client.withdraw(agent_id)
|
84
|
+
```
|
85
|
+
|
86
|
+
## Potential Improvements
|
87
|
+
|
88
|
+
1. **Error Handling**: Implement more granular error handling and custom exceptions for different types of failures (e.g., network errors, authentication errors).
|
89
|
+
|
90
|
+
2. **Retry Mechanism**: Add a retry mechanism for transient failures, potentially using a library like `retriable`.
|
91
|
+
|
92
|
+
3. **Connection Pooling**: Implement connection pooling to improve performance when making multiple requests.
|
93
|
+
|
94
|
+
4. **Caching**: Add caching for frequently accessed data, such as the list of all agents or common capability searches.
|
95
|
+
|
96
|
+
5. **Asynchronous Operations**: Provide asynchronous versions of methods for non-blocking operations, possibly using Ruby's `async`/`await` syntax or a library like `concurrent-ruby`.
|
97
|
+
|
98
|
+
6. **Pagination Support**: Implement pagination for methods that return potentially large datasets, such as `fetch_all_agents`.
|
99
|
+
|
100
|
+
7. **Capability Normalization**: Normalize capabilities (e.g., lowercase, remove whitespace) before sending to ensure consistent matching.
|
101
|
+
|
102
|
+
8. **Batch Operations**: Add support for batch registration or withdrawal of multiple agents in a single request.
|
103
|
+
|
104
|
+
9. **Logging Enhancements**: Improve logging to include more detailed information about requests and responses for better debugging.
|
105
|
+
|
106
|
+
10. **Configuration Options**: Allow more configuration options, such as timeout settings, custom headers, or SSL/TLS options.
|
107
|
+
|
108
|
+
11. **Capability Validation**: Implement client-side validation of capabilities before sending requests to the server.
|
109
|
+
|
110
|
+
12. **Agent Status Updates**: Add methods to update an agent's status or capabilities without full re-registration.
|
111
|
+
|
112
|
+
13. **Metrics Collection**: Integrate with a metrics library to collect and report on API usage and performance.
|
113
|
+
|
114
|
+
14. **Authentication Support**: Add support for authentication mechanisms if the Central Registry implements them in the future.
|
115
|
+
|
116
|
+
15. **API Versioning**: Implement support for API versioning to handle potential future changes in the Central Registry API.
|
117
|
+
|
118
|
+
By implementing these improvements, the RegistryClient can become more robust, efficient, and feature-rich, enhancing its utility within the Agent99 framework.
|
119
|
+
|
@@ -0,0 +1,463 @@
|
|
1
|
+
# Agent99::Base
|
2
|
+
|
3
|
+
The `Agent99::Base` class is the foundation of all agents in the Agent99 framework. It provides core functionality for agent lifecycle, messaging, discovery, and error handling.
|
4
|
+
|
5
|
+
## Class Overview
|
6
|
+
|
7
|
+
```ruby
|
8
|
+
class Agent99::Base
|
9
|
+
include Agent99::HeaderManagement
|
10
|
+
include Agent99::AgentDiscovery
|
11
|
+
include Agent99::ControlActions
|
12
|
+
include Agent99::AgentLifecycle
|
13
|
+
include Agent99::MessageProcessing
|
14
|
+
end
|
15
|
+
```
|
16
|
+
|
17
|
+
## Instance Methods
|
18
|
+
|
19
|
+
### Core Lifecycle
|
20
|
+
|
21
|
+
#### `#run`
|
22
|
+
|
23
|
+
Starts the agent and begins listening for messages.
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
def run
|
27
|
+
```
|
28
|
+
|
29
|
+
**Example:**
|
30
|
+
```ruby
|
31
|
+
agent = MyAgent.new
|
32
|
+
agent.run # Blocks until shutdown
|
33
|
+
```
|
34
|
+
|
35
|
+
#### `#shutdown`
|
36
|
+
|
37
|
+
Gracefully shuts down the agent.
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
def shutdown
|
41
|
+
```
|
42
|
+
|
43
|
+
**Example:**
|
44
|
+
```ruby
|
45
|
+
agent.shutdown
|
46
|
+
```
|
47
|
+
|
48
|
+
#### `#info`
|
49
|
+
|
50
|
+
Abstract method that must be implemented by subclasses. Returns agent metadata.
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
def info
|
54
|
+
# Must return hash with:
|
55
|
+
# - :name (String)
|
56
|
+
# - :type (Symbol: :server, :client, or :hybrid)
|
57
|
+
# - :capabilities (Array of Strings)
|
58
|
+
end
|
59
|
+
```
|
60
|
+
|
61
|
+
**Example:**
|
62
|
+
```ruby
|
63
|
+
def info
|
64
|
+
{
|
65
|
+
name: self.class.to_s,
|
66
|
+
type: :server,
|
67
|
+
capabilities: ['calculator', 'math']
|
68
|
+
}
|
69
|
+
end
|
70
|
+
```
|
71
|
+
|
72
|
+
### Message Processing
|
73
|
+
|
74
|
+
#### `#process_request(payload)`
|
75
|
+
|
76
|
+
Abstract method for handling incoming requests. Only called for server and hybrid agents.
|
77
|
+
|
78
|
+
```ruby
|
79
|
+
def process_request(payload)
|
80
|
+
# Process the payload and call send_response or send_error
|
81
|
+
end
|
82
|
+
```
|
83
|
+
|
84
|
+
**Parameters:**
|
85
|
+
- `payload` (Hash) - The request data
|
86
|
+
|
87
|
+
**Example:**
|
88
|
+
```ruby
|
89
|
+
def process_request(payload)
|
90
|
+
name = payload.dig(:name) || "World"
|
91
|
+
send_response(message: "Hello, #{name}!")
|
92
|
+
end
|
93
|
+
```
|
94
|
+
|
95
|
+
#### `#send_response(data)`
|
96
|
+
|
97
|
+
Sends a successful response back to the requester.
|
98
|
+
|
99
|
+
```ruby
|
100
|
+
def send_response(data)
|
101
|
+
```
|
102
|
+
|
103
|
+
**Parameters:**
|
104
|
+
- `data` (Hash) - Response data
|
105
|
+
|
106
|
+
**Example:**
|
107
|
+
```ruby
|
108
|
+
send_response(
|
109
|
+
result: 42,
|
110
|
+
status: "success",
|
111
|
+
timestamp: Time.now.iso8601
|
112
|
+
)
|
113
|
+
```
|
114
|
+
|
115
|
+
#### `#send_error(message, code = nil, details = nil)`
|
116
|
+
|
117
|
+
Sends an error response back to the requester.
|
118
|
+
|
119
|
+
```ruby
|
120
|
+
def send_error(message, code = nil, details = nil)
|
121
|
+
```
|
122
|
+
|
123
|
+
**Parameters:**
|
124
|
+
- `message` (String) - Error message
|
125
|
+
- `code` (String, optional) - Error code
|
126
|
+
- `details` (Hash, optional) - Additional error details
|
127
|
+
|
128
|
+
**Example:**
|
129
|
+
```ruby
|
130
|
+
send_error(
|
131
|
+
"Invalid input data",
|
132
|
+
"VALIDATION_ERROR",
|
133
|
+
{ field: "email", expected: "valid email address" }
|
134
|
+
)
|
135
|
+
```
|
136
|
+
|
137
|
+
#### `#send_request(agent_name, payload, options = {})`
|
138
|
+
|
139
|
+
Sends a request to another agent. Only available for client and hybrid agents.
|
140
|
+
|
141
|
+
```ruby
|
142
|
+
def send_request(agent_name, payload, options = {})
|
143
|
+
```
|
144
|
+
|
145
|
+
**Parameters:**
|
146
|
+
- `agent_name` (String) - Target agent name
|
147
|
+
- `payload` (Hash) - Request data
|
148
|
+
- `options` (Hash, optional) - Request options (timeout, etc.)
|
149
|
+
|
150
|
+
**Returns:** Response hash or nil if failed
|
151
|
+
|
152
|
+
**Example:**
|
153
|
+
```ruby
|
154
|
+
response = send_request(
|
155
|
+
"CalculatorAgent",
|
156
|
+
{ operation: "add", a: 5, b: 3 },
|
157
|
+
{ timeout: 30 }
|
158
|
+
)
|
159
|
+
```
|
160
|
+
|
161
|
+
### Agent Discovery
|
162
|
+
|
163
|
+
#### `#discover_agents(capabilities = [])`
|
164
|
+
|
165
|
+
Finds agents that match the specified capabilities.
|
166
|
+
|
167
|
+
```ruby
|
168
|
+
def discover_agents(capabilities = [])
|
169
|
+
```
|
170
|
+
|
171
|
+
**Parameters:**
|
172
|
+
- `capabilities` (Array) - List of required capabilities
|
173
|
+
|
174
|
+
**Returns:** Array of agent info hashes
|
175
|
+
|
176
|
+
**Example:**
|
177
|
+
```ruby
|
178
|
+
calculators = discover_agents(['calculator'])
|
179
|
+
weather_agents = discover_agents(['weather', 'forecast'])
|
180
|
+
```
|
181
|
+
|
182
|
+
#### `#register_agent`
|
183
|
+
|
184
|
+
Registers this agent with the registry.
|
185
|
+
|
186
|
+
```ruby
|
187
|
+
def register_agent
|
188
|
+
```
|
189
|
+
|
190
|
+
**Example:**
|
191
|
+
```ruby
|
192
|
+
register_agent
|
193
|
+
```
|
194
|
+
|
195
|
+
#### `#unregister_agent`
|
196
|
+
|
197
|
+
Removes this agent from the registry.
|
198
|
+
|
199
|
+
```ruby
|
200
|
+
def unregister_agent
|
201
|
+
```
|
202
|
+
|
203
|
+
### Header Management
|
204
|
+
|
205
|
+
#### `#header_value(key)`
|
206
|
+
|
207
|
+
Gets a header value from the current request.
|
208
|
+
|
209
|
+
```ruby
|
210
|
+
def header_value(key)
|
211
|
+
```
|
212
|
+
|
213
|
+
**Parameters:**
|
214
|
+
- `key` (String) - Header key
|
215
|
+
|
216
|
+
**Returns:** Header value or nil
|
217
|
+
|
218
|
+
**Example:**
|
219
|
+
```ruby
|
220
|
+
user_id = header_value('user_id')
|
221
|
+
correlation_id = header_value('correlation_id')
|
222
|
+
```
|
223
|
+
|
224
|
+
#### `#set_header(key, value)`
|
225
|
+
|
226
|
+
Sets a header value for the current response.
|
227
|
+
|
228
|
+
```ruby
|
229
|
+
def set_header(key, value)
|
230
|
+
```
|
231
|
+
|
232
|
+
**Parameters:**
|
233
|
+
- `key` (String) - Header key
|
234
|
+
- `value` (String) - Header value
|
235
|
+
|
236
|
+
**Example:**
|
237
|
+
```ruby
|
238
|
+
set_header('processing_time', '150ms')
|
239
|
+
set_header('cache_status', 'hit')
|
240
|
+
```
|
241
|
+
|
242
|
+
### Control Actions
|
243
|
+
|
244
|
+
#### `#pause`
|
245
|
+
|
246
|
+
Pauses the agent (stops processing new requests).
|
247
|
+
|
248
|
+
```ruby
|
249
|
+
def pause
|
250
|
+
```
|
251
|
+
|
252
|
+
#### `#resume`
|
253
|
+
|
254
|
+
Resumes the agent after being paused.
|
255
|
+
|
256
|
+
```ruby
|
257
|
+
def resume
|
258
|
+
```
|
259
|
+
|
260
|
+
#### `#status`
|
261
|
+
|
262
|
+
Returns the current agent status.
|
263
|
+
|
264
|
+
```ruby
|
265
|
+
def status
|
266
|
+
```
|
267
|
+
|
268
|
+
**Returns:** Symbol (`:running`, `:paused`, `:stopped`)
|
269
|
+
|
270
|
+
### Configuration
|
271
|
+
|
272
|
+
#### `#logger`
|
273
|
+
|
274
|
+
Returns the logger instance for this agent.
|
275
|
+
|
276
|
+
```ruby
|
277
|
+
def logger
|
278
|
+
```
|
279
|
+
|
280
|
+
**Example:**
|
281
|
+
```ruby
|
282
|
+
logger.info "Processing request"
|
283
|
+
logger.error "Something went wrong: #{error.message}"
|
284
|
+
```
|
285
|
+
|
286
|
+
#### `#config`
|
287
|
+
|
288
|
+
Returns the configuration hash for this agent.
|
289
|
+
|
290
|
+
```ruby
|
291
|
+
def config
|
292
|
+
```
|
293
|
+
|
294
|
+
**Example:**
|
295
|
+
```ruby
|
296
|
+
timeout = config[:timeout] || 30
|
297
|
+
registry_url = config[:registry_url]
|
298
|
+
```
|
299
|
+
|
300
|
+
## Class Methods
|
301
|
+
|
302
|
+
### `Agent99::Base.create(type:, **options)`
|
303
|
+
|
304
|
+
Factory method for creating agents.
|
305
|
+
|
306
|
+
```ruby
|
307
|
+
Agent99::Base.create(type: :server, name: 'TestAgent')
|
308
|
+
```
|
309
|
+
|
310
|
+
**Parameters:**
|
311
|
+
- `type` (Symbol) - Agent type (`:server`, `:client`, `:hybrid`)
|
312
|
+
- `options` (Hash) - Configuration options
|
313
|
+
|
314
|
+
## Configuration Options
|
315
|
+
|
316
|
+
When creating agents, you can pass configuration options:
|
317
|
+
|
318
|
+
```ruby
|
319
|
+
class MyAgent < Agent99::Base
|
320
|
+
def initialize(options = {})
|
321
|
+
super(options)
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
agent = MyAgent.new(
|
326
|
+
registry_url: 'http://localhost:4567',
|
327
|
+
message_client: 'nats',
|
328
|
+
timeout: 30,
|
329
|
+
log_level: :info
|
330
|
+
)
|
331
|
+
```
|
332
|
+
|
333
|
+
### Available Options
|
334
|
+
|
335
|
+
| Option | Type | Default | Description |
|
336
|
+
|--------|------|---------|-------------|
|
337
|
+
| `registry_url` | String | `http://localhost:4567` | Registry service URL |
|
338
|
+
| `message_client` | String | `nats` | Message broker type (`nats`, `amqp`, `tcp`) |
|
339
|
+
| `timeout` | Integer | 30 | Default request timeout (seconds) |
|
340
|
+
| `log_level` | Symbol | `:info` | Logging level |
|
341
|
+
| `retry_attempts` | Integer | 3 | Request retry attempts |
|
342
|
+
| `retry_delay` | Integer | 1 | Delay between retries (seconds) |
|
343
|
+
|
344
|
+
## Examples
|
345
|
+
|
346
|
+
### Simple Server Agent
|
347
|
+
|
348
|
+
```ruby
|
349
|
+
class GreeterAgent < Agent99::Base
|
350
|
+
def info
|
351
|
+
{
|
352
|
+
name: self.class.to_s,
|
353
|
+
type: :server,
|
354
|
+
capabilities: ['greeting', 'hello']
|
355
|
+
}
|
356
|
+
end
|
357
|
+
|
358
|
+
def process_request(payload)
|
359
|
+
name = payload.dig(:name) || "World"
|
360
|
+
logger.info "Greeting #{name}"
|
361
|
+
|
362
|
+
send_response(
|
363
|
+
message: "Hello, #{name}!",
|
364
|
+
timestamp: Time.now.iso8601
|
365
|
+
)
|
366
|
+
end
|
367
|
+
end
|
368
|
+
```
|
369
|
+
|
370
|
+
### Client Agent with Error Handling
|
371
|
+
|
372
|
+
```ruby
|
373
|
+
class ClientAgent < Agent99::Base
|
374
|
+
def info
|
375
|
+
{
|
376
|
+
name: self.class.to_s,
|
377
|
+
type: :client,
|
378
|
+
capabilities: ['client_operations']
|
379
|
+
}
|
380
|
+
end
|
381
|
+
|
382
|
+
def make_greeting_request(name)
|
383
|
+
greeters = discover_agents(['greeting'])
|
384
|
+
|
385
|
+
if greeters.empty?
|
386
|
+
logger.warn "No greeting agents available"
|
387
|
+
return nil
|
388
|
+
end
|
389
|
+
|
390
|
+
begin
|
391
|
+
response = send_request(
|
392
|
+
greeters.first[:name],
|
393
|
+
{ name: name },
|
394
|
+
{ timeout: 10 }
|
395
|
+
)
|
396
|
+
|
397
|
+
logger.info "Received: #{response[:message]}"
|
398
|
+
response
|
399
|
+
rescue => e
|
400
|
+
logger.error "Request failed: #{e.message}"
|
401
|
+
nil
|
402
|
+
end
|
403
|
+
end
|
404
|
+
end
|
405
|
+
```
|
406
|
+
|
407
|
+
### Hybrid Agent with State
|
408
|
+
|
409
|
+
```ruby
|
410
|
+
class StatefulAgent < Agent99::Base
|
411
|
+
def initialize(options = {})
|
412
|
+
super(options)
|
413
|
+
@request_count = 0
|
414
|
+
@mutex = Mutex.new
|
415
|
+
end
|
416
|
+
|
417
|
+
def info
|
418
|
+
{
|
419
|
+
name: self.class.to_s,
|
420
|
+
type: :hybrid,
|
421
|
+
capabilities: ['stateful', 'counter']
|
422
|
+
}
|
423
|
+
end
|
424
|
+
|
425
|
+
def process_request(payload)
|
426
|
+
@mutex.synchronize do
|
427
|
+
@request_count += 1
|
428
|
+
|
429
|
+
if payload[:operation] == 'get_count'
|
430
|
+
send_response(count: @request_count)
|
431
|
+
elsif payload[:operation] == 'reset_count'
|
432
|
+
@request_count = 0
|
433
|
+
send_response(count: 0, status: 'reset')
|
434
|
+
else
|
435
|
+
send_error('Unknown operation', 'INVALID_OPERATION')
|
436
|
+
end
|
437
|
+
end
|
438
|
+
end
|
439
|
+
end
|
440
|
+
```
|
441
|
+
|
442
|
+
## Thread Safety
|
443
|
+
|
444
|
+
The `Agent99::Base` class is designed to be thread-safe for concurrent request processing. However:
|
445
|
+
|
446
|
+
- **Subclass implementations** should ensure thread safety in their `process_request` methods
|
447
|
+
- **Shared state** should be protected with mutexes or other synchronization primitives
|
448
|
+
- **Instance variables** may be accessed concurrently during request processing
|
449
|
+
|
450
|
+
## Error Handling
|
451
|
+
|
452
|
+
The base class provides automatic error handling for:
|
453
|
+
|
454
|
+
- **Network failures** during agent registration and discovery
|
455
|
+
- **Message broker disconnections** with automatic retry
|
456
|
+
- **Invalid message formats** with appropriate error responses
|
457
|
+
- **Unhandled exceptions** in `process_request` (converted to error responses)
|
458
|
+
|
459
|
+
## Next Steps
|
460
|
+
|
461
|
+
- **[Registry Client](registry-client.md)** - Registry service API
|
462
|
+
- **[Message Clients](message-clients.md)** - Message broker clients
|
463
|
+
- **[Schemas](schemas.md)** - Schema validation system
|