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
@@ -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.
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# Agent99 Framework
|
2
|
+
|
3
|
+
## Schema Definition
|
4
|
+
|
5
|
+
Agent99 uses `SimpleJsonSchemaBuilder` for defining message schemas. This gem was chosen for its Ruby-like DSL that makes schema definitions readable and maintainable, while still producing JSON Schema compatible output.
|
6
|
+
|
7
|
+
### Header Schema
|
8
|
+
|
9
|
+
All messages in Agent99 must include a header that conforms to this schema:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
class Agent99::HeaderSchema < SimpleJsonSchemaBuilder::Base
|
13
|
+
object do
|
14
|
+
string :type, required: true,
|
15
|
+
enum: %w[request response control]
|
16
|
+
string :to_uuid, required: true
|
17
|
+
string :from_uuid, required: true
|
18
|
+
string :event_uuid,required: true
|
19
|
+
integer :timestamp, required: true
|
20
|
+
end
|
21
|
+
end
|
22
|
+
```
|
23
|
+
|
24
|
+
### Request Schema Example
|
25
|
+
|
26
|
+
Define your agent's request schema by inheriting from SimpleJsonSchemaBuilder::Base:
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
class MyAgentRequest < SimpleJsonSchemaBuilder::Base
|
30
|
+
object do
|
31
|
+
object :header, schema: Agent99::HeaderSchema
|
32
|
+
string :greeting, required: false, examples: ["Hello"]
|
33
|
+
string :name, required: true, examples: ["World"]
|
34
|
+
end
|
35
|
+
end
|
36
|
+
```
|
37
|
+
|
38
|
+
In this example, the agent has two parameters that it uses from the request message: greeting and name; however, greeting is not required. **The Agent99 framework will use the first item in the examples array as a default for optional parameters.**
|
39
|
+
|
40
|
+
### Automatic Schema Validation
|
41
|
+
|
42
|
+
Agent99 automatically validates incoming request messages against your agent's REQUEST_SCHEMA:
|
43
|
+
|
44
|
+
1. When a request arrives, the framework checks if your agent class defines REQUEST_SCHEMA
|
45
|
+
2. If defined, the message is validated before reaching your receive_request method
|
46
|
+
3. If validation fails:
|
47
|
+
- An error response is automatically sent back to the requester
|
48
|
+
- Your receive_request method is not called
|
49
|
+
- The validation errors are logged
|
50
|
+
|
51
|
+
Example validation error response:
|
52
|
+
|
53
|
+
```ruby
|
54
|
+
{
|
55
|
+
header: {
|
56
|
+
type: 'error',
|
57
|
+
to_uuid: original_from_uuid,
|
58
|
+
from_uuid: agent_id,
|
59
|
+
event_uuid: original_event_uuid,
|
60
|
+
timestamp: current_timestamp
|
61
|
+
},
|
62
|
+
errors: ['Required property "name" not found in request']
|
63
|
+
}
|
64
|
+
```
|
65
|
+
|
66
|
+
### Why SimpleJsonSchemaBuilder?
|
67
|
+
|
68
|
+
SimpleJsonSchemaBuilder was chosen for Agent99 because it:
|
69
|
+
|
70
|
+
1. Provides a Ruby-native DSL for schema definition
|
71
|
+
2. Generates standard JSON Schema output
|
72
|
+
3. Supports schema composition and reuse
|
73
|
+
4. Includes built-in validation
|
74
|
+
5. Has excellent performance characteristics
|
75
|
+
6. Maintains type safety through static analysis
|
76
|
+
|
77
|
+
The gem allows us to define schemas that are both human-readable and machine-validatable, while staying within the Ruby ecosystem.
|
78
|
+
|
data/docs/security.md
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
# Agent99 Framework
|
2
|
+
|
3
|
+
## Security
|
4
|
+
|
5
|
+
While Agent99 focuses on communication efficiency, it is recommended to implement security measures like:
|
6
|
+
|
7
|
+
- Encrypting messages in transit.
|
8
|
+
- Using secure protocols for messaging (e.g., AMQPS or NATS with TLS).
|
9
|
+
- Implementing access control mechanisms for sensitive operations.
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# Agent99 Framework
|
2
|
+
|
3
|
+
## Troubleshooting
|
4
|
+
|
5
|
+
Common issues may include:
|
6
|
+
|
7
|
+
- Failed registrations: Ensure that your registry URL is correctly configured.
|
8
|
+
- Message routing issues: Verify routing keys and message schemata.
|
9
|
+
- Unhandled exceptions: Check logs for details.
|
10
|
+
|
11
|
+
For effective debugging, use the logging facilities provided and monitor agent activities.
|
data/examples/README.md
CHANGED
@@ -45,6 +45,49 @@ This file implements a simple registry service for AI agents using Sinatra.
|
|
45
45
|
- DELETE `/withdraw/:uuid`: Withdraws an agent from the registry
|
46
46
|
- GET `/`: Lists all registered agents
|
47
47
|
|
48
|
+
### 5. control_agent.rb
|
49
|
+
|
50
|
+
Example use of control messages.
|
51
|
+
|
52
|
+
### 6. kaos_spy.rb
|
53
|
+
- Agent 99 was kinnapped by KAOS and forced to reveal the secrets of Control's centralized registry and communications network.
|
54
|
+
- The KAOS spy raided hacked the registry, stole the records for all of Control's agents in the field and DOX'ed them on social media.
|
55
|
+
- That was not enough for KAOS. Knowing the secret UUID for each agent, KAOS proceeded to turn off the communication network one queue at a time.
|
56
|
+
- Get Smart -- Get Security
|
57
|
+
|
58
|
+
### 7. agent_watcher.rb
|
59
|
+
|
60
|
+
This file implements an agent watcher that dynamically loads and runs new agents.
|
61
|
+
|
62
|
+
- Class: `AgentWatcher < Agent99::Base`
|
63
|
+
- Functionality: Monitors a specified directory for new Ruby files and loads them as agents
|
64
|
+
- Key features:
|
65
|
+
- Watches a configurable directory (default: './agents')
|
66
|
+
- Detects new .rb files added to the watched directory
|
67
|
+
- Dynamically loads new files as Ruby agents
|
68
|
+
- Instantiates and runs each new agent in a separate thread
|
69
|
+
- Handles errors during the loading and running process
|
70
|
+
- Terminates all loaded agents when the watcher is stopped
|
71
|
+
- Key methods:
|
72
|
+
- `init`: Sets up the file watcher
|
73
|
+
- `setup_watcher`: Configures the directory listener
|
74
|
+
- `handle_new_agent`: Processes newly detected agent files
|
75
|
+
|
76
|
+
### 8. example_agent.rb
|
77
|
+
|
78
|
+
This file provides a simple example agent that can be dynamically loaded by the AgentWatcher.
|
79
|
+
|
80
|
+
- Class: `ExampleAgent < Agent99::Base`
|
81
|
+
- Functionality: Demonstrates a basic agent that can be dynamically loaded
|
82
|
+
- Key features:
|
83
|
+
- Defines capabilities as a rubber stamp and yes-man
|
84
|
+
- Responds to all requests with a success status
|
85
|
+
- Key methods:
|
86
|
+
- `capabilities`: Defines the agent's capabilities
|
87
|
+
- `receive_request`: Handles incoming requests and sends a response
|
88
|
+
|
89
|
+
Note: To use the example_agent.rb, first run the AgentWatcher, then copy example_agent.rb into the 'agents' directory. The AgentWatcher will automatically detect, load, and run the new agent.
|
90
|
+
|
48
91
|
## Usage
|
49
92
|
|
50
93
|
From the examples directory you will need to start three different processes. You will want to keep them all in the forgound so it would be best to start them in different terminal windows.
|
@@ -0,0 +1,102 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# examples/agent_watcher.rb
|
3
|
+
#
|
4
|
+
# This file defines an AgentWatcher class that monitors a specified directory
|
5
|
+
# for new Ruby files and dynamically loads and runs them as agents.
|
6
|
+
|
7
|
+
# When running, the AgentWatcher does the following:
|
8
|
+
# 1. Watches the directory specified by AGENT_WATCH_PATH (default: './agents')
|
9
|
+
# 2. Detects when new .rb files are added to the watched directory
|
10
|
+
# 3. Attempts to load each new file as a Ruby agent
|
11
|
+
# 4. If successful, instantiates the agent and runs it in a separate thread
|
12
|
+
#
|
13
|
+
# When example_agent.rb is copied into the agents directory:
|
14
|
+
# 1. The AgentWatcher detects the new file
|
15
|
+
# 2. It attempts to load the file and extract the agent class
|
16
|
+
# 3. If the class is a subclass of Agent99::Base, it instantiates the agent
|
17
|
+
# 4. The new agent is then run in a separate thread
|
18
|
+
# 5. Any errors during this process are logged for debugging
|
19
|
+
#
|
20
|
+
# When AgentWatcher is terminated, it first terminates all of the
|
21
|
+
# agents that it has previously loaded and then terminates itself.
|
22
|
+
|
23
|
+
|
24
|
+
require 'listen'
|
25
|
+
|
26
|
+
require_relative '../lib/agent99'
|
27
|
+
|
28
|
+
class AgentWatcher < Agent99::Base
|
29
|
+
TYPE = :client
|
30
|
+
|
31
|
+
def capabilities = %w[ launch_agents watcher launcher ]
|
32
|
+
|
33
|
+
def init
|
34
|
+
@watch_path = ENV.fetch('AGENT_WATCH_PATH', './agents')
|
35
|
+
setup_watcher
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def setup_watcher
|
41
|
+
@listener = Listen.to(@watch_path) do |modified, added, removed|
|
42
|
+
added.each do |file|
|
43
|
+
handle_new_agent(file)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Start listening in a separate thread
|
48
|
+
@listener.start
|
49
|
+
end
|
50
|
+
|
51
|
+
def handle_new_agent(file)
|
52
|
+
return unless File.extname(file) == '.rb'
|
53
|
+
|
54
|
+
begin
|
55
|
+
# Load the new agent file
|
56
|
+
require file
|
57
|
+
|
58
|
+
# Extract the class name from the file name
|
59
|
+
class_name = File.basename(file, '.rb')
|
60
|
+
.split('_')
|
61
|
+
.map(&:capitalize)
|
62
|
+
.join
|
63
|
+
|
64
|
+
# Get the class object
|
65
|
+
agent_class = Object.const_get(class_name)
|
66
|
+
|
67
|
+
# Verify it's an Agent99::Base subclass
|
68
|
+
return unless agent_class < Agent99::Base
|
69
|
+
|
70
|
+
# Create and run the new agent in a thread
|
71
|
+
Thread.new do
|
72
|
+
begin
|
73
|
+
agent = agent_class.new
|
74
|
+
agent.run
|
75
|
+
rescue StandardError => e
|
76
|
+
logger.error "Error running agent #{class_name}: #{e.message}"
|
77
|
+
logger.debug e.backtrace.join("\n")
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
logger.info "Successfully launched agent: #{class_name}"
|
82
|
+
|
83
|
+
rescue LoadError => e
|
84
|
+
logger.error "Failed to load agent file #{file}: #{e.message}"
|
85
|
+
|
86
|
+
rescue NameError => e
|
87
|
+
logger.error "Failed to instantiate agent class from #{file}: #{e.message}"
|
88
|
+
|
89
|
+
rescue StandardError => e
|
90
|
+
logger.error "Unexpected error handling #{file}: #{e.message}"
|
91
|
+
logger.debug e.backtrace.join("\n")
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def fini
|
96
|
+
@listener&.stop
|
97
|
+
super
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
watcher = AgentWatcher.new
|
102
|
+
watcher.run
|
File without changes
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# examples/example_agent.rb
|
2
|
+
#
|
3
|
+
# NOTE: This agent is meant to be loaded
|
4
|
+
# by the agent_watcher.rb be file.
|
5
|
+
# To do that first have AgentWatcher running
|
6
|
+
# then `cp example_agent.rb agents`
|
7
|
+
# AgentWatcher will see the new file arrive
|
8
|
+
# in the `agents` folder, will determine that the
|
9
|
+
# new file contains an Agent99 subclass, will
|
10
|
+
# load it, create a new instance of the class and
|
11
|
+
# finally run the new instance within its own
|
12
|
+
# thread as part of the AgentWatcher process.
|
13
|
+
#
|
14
|
+
|
15
|
+
require_relative '../../lib/agent99'
|
16
|
+
|
17
|
+
class ExampleAgent < Agent99::Base
|
18
|
+
TYPE = :server
|
19
|
+
|
20
|
+
def capabilities = %w[ rubber_stamp yes_man example ]
|
21
|
+
|
22
|
+
def receive_request
|
23
|
+
logger.info "Example agent received request: #{payload}"
|
24
|
+
send_response(status: 'success')
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# examples/kaos_spy.rb
|
3
|
+
#
|
4
|
+
# KAOS stood for "Kreatively Akting Out Simultaneously."
|
5
|
+
|
6
|
+
require 'agent99'
|
7
|
+
|
8
|
+
# Kaos captured Agent99 and forced her to reveal the
|
9
|
+
# secrets of the centralized registry and the communication
|
10
|
+
# network used by Control. Max was not there to save her.
|
11
|
+
|
12
|
+
require 'tty-table'
|
13
|
+
|
14
|
+
class KaosSpy
|
15
|
+
# TODO: spread some choas!
|
16
|
+
|
17
|
+
attr_reader :registry, :comms, :agents
|
18
|
+
|
19
|
+
def initialize
|
20
|
+
@registry = Agent99::RegistryClient.new
|
21
|
+
@agents = registry.fetch_all_agents
|
22
|
+
dox_control_agents
|
23
|
+
|
24
|
+
@comms = Agent99::AmqpMessageClient.new
|
25
|
+
take_out_communications
|
26
|
+
end
|
27
|
+
|
28
|
+
def dox_control_agents
|
29
|
+
if agents.empty?
|
30
|
+
puts "\nKAOS won! There are no Control agents in the field."
|
31
|
+
else
|
32
|
+
report = [ %w[Name Address Capabilities] ]
|
33
|
+
|
34
|
+
agents.each{|agent|
|
35
|
+
report << [
|
36
|
+
agent[:name],
|
37
|
+
agent[:uuid],
|
38
|
+
agent[:capabilities].join(', ')
|
39
|
+
]
|
40
|
+
}
|
41
|
+
|
42
|
+
table = TTY::Table.new(report[0], report[1..])
|
43
|
+
puts table.render(:unicode)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def take_out_communications
|
48
|
+
puts
|
49
|
+
puts "Destroy Control's Comms Network ..."
|
50
|
+
puts
|
51
|
+
|
52
|
+
agents.each do |agent|
|
53
|
+
comms.delete_queue(agent[:uuid])
|
54
|
+
puts " Agent #{agent[:name]} cannot make or receive calls@"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
KaosSpy.new
|
60
|
+
puts
|
61
|
+
puts "That's all it takes - Get Smart; get security!"
|
62
|
+
puts
|
63
|
+
|
data/examples/registry.rb
CHANGED
@@ -8,8 +8,11 @@ require 'sinatra'
|
|
8
8
|
require 'json'
|
9
9
|
require 'securerandom'
|
10
10
|
|
11
|
-
# In-memory registry to store agent
|
12
|
-
#
|
11
|
+
# In-memory registry to store agent Array(Hash)
|
12
|
+
#
|
13
|
+
# Agent capabilities are save as lower case. The
|
14
|
+
# discovery process also compares content as lower case.
|
15
|
+
#
|
13
16
|
# TODO: change this data store to a sqlite database
|
14
17
|
# maybe with a vector search capability.
|
15
18
|
#
|
@@ -25,12 +28,11 @@ end
|
|
25
28
|
post '/register' do
|
26
29
|
request.body.rewind
|
27
30
|
agent_info = JSON.parse(request.body.read, symbolize_names: true)
|
28
|
-
|
29
31
|
agent_name = agent_info[:name]
|
30
|
-
capabilities = agent_info[:capabilities]
|
31
|
-
|
32
32
|
agent_uuid = SecureRandom.uuid
|
33
33
|
|
34
|
+
agent_info[:capabilities].map!{|c| c.downcase}
|
35
|
+
|
34
36
|
AGENT_REGISTRY << agent_info.merge({uuid: agent_uuid})
|
35
37
|
|
36
38
|
status 201
|
@@ -42,7 +44,7 @@ end
|
|
42
44
|
# TODO: This is a simple keyword matcher. Looking
|
43
45
|
# => for a semantic match process.
|
44
46
|
get '/discover' do
|
45
|
-
capability = params['capability']
|
47
|
+
capability = params['capability'].downcase
|
46
48
|
|
47
49
|
matching_agents = AGENT_REGISTRY.select do |agent|
|
48
50
|
agent[:capabilities].include?(capability)
|
data/lib/agent99/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: agent99
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dewayne VanHoozer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-12-
|
11
|
+
date: 2024-12-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bunny
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: sinatra
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: amazing_print
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -138,12 +152,39 @@ files:
|
|
138
152
|
- LICENSE
|
139
153
|
- README.md
|
140
154
|
- Rakefile
|
141
|
-
- docs/
|
155
|
+
- docs/README.md
|
156
|
+
- docs/advanced_features.md
|
157
|
+
- docs/agent_discovery.md
|
158
|
+
- docs/agent_lifecycle.md
|
159
|
+
- docs/agent_registry_processes.md
|
160
|
+
- docs/api_reference.md
|
161
|
+
- docs/architecture.md
|
162
|
+
- docs/configuration.md
|
163
|
+
- docs/control_actions.md
|
164
|
+
- docs/custom_agent_implementation.md
|
165
|
+
- docs/diagrams/agent_registry_processes.dot
|
166
|
+
- docs/diagrams/agent_registry_processes.png
|
167
|
+
- docs/diagrams/high_level_architecture.dot
|
168
|
+
- docs/diagrams/high_level_architecture.png
|
169
|
+
- docs/diagrams/request_flow.dot
|
170
|
+
- docs/diagrams/request_flow.png
|
171
|
+
- docs/error_handling_and_logging.md
|
172
|
+
- docs/extending_the_framework.md
|
173
|
+
- docs/message_processing.md
|
174
|
+
- docs/messaging_system.md
|
175
|
+
- docs/preformance_considerations.md
|
176
|
+
- docs/schema_definition.md
|
177
|
+
- docs/security.md
|
178
|
+
- docs/troubleshooting.md
|
142
179
|
- examples/README.md
|
180
|
+
- examples/agent_watcher.rb
|
181
|
+
- examples/agents/.keep
|
143
182
|
- examples/chief_agent.rb
|
144
183
|
- examples/control.rb
|
145
184
|
- examples/diagram.dot
|
146
185
|
- examples/diagram.png
|
186
|
+
- examples/example_agent.rb
|
187
|
+
- examples/kaos_spy.rb
|
147
188
|
- examples/maxwell_agent86.rb
|
148
189
|
- examples/maxwell_request.rb
|
149
190
|
- examples/registry.rb
|
data/docs/todo.md
DELETED
@@ -1,66 +0,0 @@
|
|
1
|
-
# Documentation
|
2
|
-
|
3
|
-
TODO: Lets get some more detailed documentation underway that can be linked to from the main README.md file.
|
4
|
-
|
5
|
-
Here are some key areas that should be covered in comprehensive documentation files:
|
6
|
-
|
7
|
-
1. Architecture Overview:
|
8
|
-
- Explain the overall structure of the AiAgent framework
|
9
|
-
- Describe the roles of different components (Base, MessageClient, RegistryClient, etc.)
|
10
|
-
- Illustrate how agents communicate and interact within the system
|
11
|
-
|
12
|
-
2. Agent Lifecycle:
|
13
|
-
- Detail the process of creating, initializing, running, and shutting down an agent
|
14
|
-
- Explain the registration and withdrawal process with the registry service
|
15
|
-
|
16
|
-
3. Message Processing:
|
17
|
-
- Describe the different types of messages (request, response, control)
|
18
|
-
- Explain how messages are routed and processed
|
19
|
-
- Detail the schema validation process for incoming messages
|
20
|
-
|
21
|
-
4. Agent Discovery:
|
22
|
-
- Explain how agents can discover other agents based on capabilities
|
23
|
-
- Describe the process of querying the registry for available agents
|
24
|
-
|
25
|
-
5. Control Actions:
|
26
|
-
- List and explain all available control actions (shutdown, pause, resume, etc.)
|
27
|
-
- Describe how to implement custom control actions
|
28
|
-
|
29
|
-
6. Configuration:
|
30
|
-
- Detail all configuration options available for agents
|
31
|
-
- Explain how to use environment variables for configuration
|
32
|
-
|
33
|
-
7. Error Handling and Logging:
|
34
|
-
- Describe the error handling mechanisms in place
|
35
|
-
- Explain how to configure and use the logging system effectively
|
36
|
-
|
37
|
-
8. Messaging Systems:
|
38
|
-
- Provide details on both AMQP and NATS messaging systems
|
39
|
-
- Explain how to switch between different messaging backends
|
40
|
-
|
41
|
-
9. Custom Agent Implementation:
|
42
|
-
- Provide a step-by-step guide on creating a custom agent
|
43
|
-
- Explain how to define capabilities, handle requests, and send responses
|
44
|
-
|
45
|
-
10. Schema Definition:
|
46
|
-
- Explain how to define and use request and response schemas
|
47
|
-
- Provide examples of complex schema definitions
|
48
|
-
|
49
|
-
11. Performance Considerations:
|
50
|
-
- Discuss any performance optimizations in the framework
|
51
|
-
- Provide guidelines for writing efficient agents
|
52
|
-
|
53
|
-
12. Security:
|
54
|
-
- Explain any security measures in place (if any)
|
55
|
-
- Provide best practices for securing agent communications
|
56
|
-
|
57
|
-
13. Extending the Framework:
|
58
|
-
- Describe how to add new features or modify existing functionality
|
59
|
-
- Explain the plugin system (if one exists)
|
60
|
-
|
61
|
-
14. Troubleshooting:
|
62
|
-
- Provide a list of common issues and their solutions
|
63
|
-
- Explain how to debug agents effectively
|
64
|
-
|
65
|
-
15. API Reference:
|
66
|
-
- Provide a comprehensive API reference for all public methods and classes
|