agent99 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.envrc +3 -0
- data/CHANGELOG.md +5 -0
- data/LICENSE +21 -0
- data/README.md +99 -0
- data/Rakefile +8 -0
- data/docs/todo.md +66 -0
- data/examples/README.md +79 -0
- data/examples/hello_world.rb +97 -0
- data/examples/hello_world_client.rb +70 -0
- data/examples/hello_world_request.rb +12 -0
- data/examples/registry.rb +81 -0
- data/examples/start_agents.sh +20 -0
- data/lib/agent99/.irbrc +5 -0
- data/lib/agent99/agent_discovery.rb +35 -0
- data/lib/agent99/agent_lifecycle.rb +87 -0
- data/lib/agent99/amqp_message_client.rb +117 -0
- data/lib/agent99/base.rb +61 -0
- data/lib/agent99/control_actions.rb +56 -0
- data/lib/agent99/header_management.rb +24 -0
- data/lib/agent99/header_schema.rb +15 -0
- data/lib/agent99/message_processing.rb +155 -0
- data/lib/agent99/nats_message_client.rb +101 -0
- data/lib/agent99/registry_client.rb +73 -0
- data/lib/agent99/timestamp.rb +36 -0
- data/lib/agent99/version.rb +7 -0
- data/lib/agent99.rb +19 -0
- data/sig/ai_agent.rbs +4 -0
- metadata +205 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 827e521c4a6580cfe954cf07cf04f1a822c00b9ed6eebf75598d925aeb555626
|
4
|
+
data.tar.gz: 1b3e9b499610b9b3853757432fd4e3e39acab8fb70e29feb94eae1d22f6097aa
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ce549f64fb88cd2f152e7af27b9724dbfedfda0f6255033ea1773dda7eaf89dd71a6b622667d023b3093ae1eca72ae3a55e7bd6b1f538e3035fe889ab52ac7c4
|
7
|
+
data.tar.gz: 959b0c9c342738bb9ee75f2dd82a4caaa825a13656f6d12dba2a11434857c08f11d746c1754f03ce1902f9e4ced1f3b7e1067ab1cdbe39c054250b23592ae94f
|
data/.envrc
ADDED
data/CHANGELOG.md
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2024 Dewayne VanHoozer
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
# Agent99 Framework (AFW)
|
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.
|
4
|
+
|
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
|
+
|
7
|
+
## Features
|
8
|
+
|
9
|
+
- Agent Lifecycle Management: Easy setup and teardown of agents
|
10
|
+
- Message Processing: Handle requests, responses, and control messages
|
11
|
+
- Agent Discovery: Find other agents based on capabilities
|
12
|
+
- Flexible Communication: Support for both AMQP and NATS messaging systems
|
13
|
+
- Registry Integration: Register and discover agents through a central registry
|
14
|
+
- Error Handling and Logging: Built-in error management and logging capabilities
|
15
|
+
- Control Actions: Pause, resume, update configuration, and request status of agents
|
16
|
+
|
17
|
+
## Installation
|
18
|
+
|
19
|
+
Add this line to your application's Gemfile:
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
gem 'agent99'
|
23
|
+
```
|
24
|
+
|
25
|
+
And then execute:
|
26
|
+
|
27
|
+
```
|
28
|
+
$ bundle install
|
29
|
+
```
|
30
|
+
|
31
|
+
Or install it yourself as:
|
32
|
+
|
33
|
+
```
|
34
|
+
$ gem install agent99
|
35
|
+
```
|
36
|
+
|
37
|
+
## Usage
|
38
|
+
|
39
|
+
Here's a basic example of how to create an AI agent:
|
40
|
+
|
41
|
+
```ruby
|
42
|
+
require 'agent99'
|
43
|
+
|
44
|
+
class MyAgentRequest < SimpleJsonSchemaBuilder::Base
|
45
|
+
object do
|
46
|
+
object :header, schema: Agent99::HeaderSchema
|
47
|
+
|
48
|
+
# Define your agents parameters ....
|
49
|
+
string :greeting, required: false, examples: ["Hello"]
|
50
|
+
string :name, required: true, examples: ["World"]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
class MyAgent < Agent99::Base
|
55
|
+
REQUEST_SCHEMA = MyAgentRequest.schema
|
56
|
+
|
57
|
+
def capabilities
|
58
|
+
['text_processing', 'sentiment_analysis']
|
59
|
+
# TODO: make up mind on keyword or unstructured text
|
60
|
+
end
|
61
|
+
|
62
|
+
def receive_request
|
63
|
+
# Handle the validated incoming requests
|
64
|
+
response = { result: "Processed request" }
|
65
|
+
|
66
|
+
# Not every request needs a response
|
67
|
+
send_response(response)
|
68
|
+
end
|
69
|
+
|
70
|
+
def receive_response
|
71
|
+
# You sent a request to another agent
|
72
|
+
# now handle the response.
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
agent = MyAgent.new
|
77
|
+
agent.run
|
78
|
+
```
|
79
|
+
|
80
|
+
## Configuration
|
81
|
+
|
82
|
+
The framework can be configured through environment variables:
|
83
|
+
|
84
|
+
- `REGISTRY_BASE_URL`: URL of the agent registry service (default: 'http://localhost:4567') See the default registry service in the examples folder.
|
85
|
+
|
86
|
+
## Contributing
|
87
|
+
|
88
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/MadBomber/agent99.
|
89
|
+
|
90
|
+
## Short-term Roadmap
|
91
|
+
|
92
|
+
- In the example registry, replace the Array(Hash) datastore with sqlite3 with a vector table to support discovery using semantic search.
|
93
|
+
- Treat the agent like a Tool w/r/t RAG for prompts.
|
94
|
+
- Add AgentRequest schema to agent's info in the registry.
|
95
|
+
- Add AgentResponse schema to define the `result` element in the response JSON payload
|
96
|
+
|
97
|
+
## License
|
98
|
+
|
99
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/docs/todo.md
ADDED
@@ -0,0 +1,66 @@
|
|
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
|
data/examples/README.md
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
# Agent99 Framework Examples
|
2
|
+
|
3
|
+
- TODO
|
4
|
+
- Review and edit
|
5
|
+
- Add instructions for brew install rabbitmq nats-server boxes
|
6
|
+
- review example agents to see code can be tightened
|
7
|
+
|
8
|
+
This folder contains example implementations using the Agent99 framework. The framework provides a foundation for building AI agents that can communicate with each other through a message-based system.
|
9
|
+
|
10
|
+
## Files
|
11
|
+
|
12
|
+
### 1. hello_world.rb
|
13
|
+
|
14
|
+
This file demonstrates a basic AI agent implementation using the Agent99 framework.
|
15
|
+
|
16
|
+
- Class: `HelloWorld < Agent99::Base`
|
17
|
+
- Functionality: Responds to "hello world" requests
|
18
|
+
- Key methods:
|
19
|
+
- `receive_request`: Handles incoming requests
|
20
|
+
- `validate_request`: Validates the request against a schema
|
21
|
+
- `process`: Generates the response
|
22
|
+
|
23
|
+
### 2. hello_world_client.rb
|
24
|
+
|
25
|
+
This file shows how to create a client that interacts with the HelloWorld agent.
|
26
|
+
|
27
|
+
- Class: `HelloWorldClient < Agent99::Base`
|
28
|
+
- Functionality: Sends a request to a HelloWorld agent and processes the response
|
29
|
+
- Key methods:
|
30
|
+
- `init`: Initiates the request sending process
|
31
|
+
- `send_request`: Builds and sends the request
|
32
|
+
- `receive_response`: Handles the response from the HelloWorld agent
|
33
|
+
|
34
|
+
### 3. hello_world_request.rb
|
35
|
+
|
36
|
+
This file defines the schema for HelloWorld requests using SimpleJsonSchemaBuilder.
|
37
|
+
|
38
|
+
- Class: `HelloWorldRequest < SimpleJsonSchemaBuilder::Base`
|
39
|
+
- Defines the structure of a valid HelloWorld request
|
40
|
+
|
41
|
+
### 4. registry.rb
|
42
|
+
|
43
|
+
This file implements a simple registry service for AI agents using Sinatra.
|
44
|
+
|
45
|
+
- Functionality: Allows agents to register, discover other agents, and withdraw from the registry
|
46
|
+
- Endpoints:
|
47
|
+
- GET `/healthcheck`: Returns the number of registered agents
|
48
|
+
- POST `/register`: Registers a new agent
|
49
|
+
- GET `/discover`: Discovers agents by capability
|
50
|
+
- DELETE `/withdraw/:uuid`: Withdraws an agent from the registry
|
51
|
+
- GET `/`: Lists all registered agents
|
52
|
+
|
53
|
+
## Usage
|
54
|
+
|
55
|
+
1. Start the registry service:
|
56
|
+
```
|
57
|
+
ruby registry.rb
|
58
|
+
```
|
59
|
+
|
60
|
+
2. Run the HelloWorld agent:
|
61
|
+
```
|
62
|
+
ruby hello_world.rb
|
63
|
+
```
|
64
|
+
|
65
|
+
3. Run the HelloWorld client:
|
66
|
+
```
|
67
|
+
ruby hello_world_client.rb
|
68
|
+
```
|
69
|
+
|
70
|
+
## Dependencies
|
71
|
+
|
72
|
+
- Ruby 3.3+
|
73
|
+
- Gems: json, json_schema, sinatra, bunny, securerandom
|
74
|
+
|
75
|
+
## Notes
|
76
|
+
|
77
|
+
- The framework uses modern Ruby 3.3 syntax, especially for hashes and method signatures with named parameters.
|
78
|
+
- The examples demonstrate basic usage of the Agent99 framework, including request/response handling, validation, and agent discovery.
|
79
|
+
- The registry service uses an in-memory store (AGENT_REGISTRY) for simplicity, but it's recommended to use a more robust solution like SQLite for production use.
|
@@ -0,0 +1,97 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# examples/hello_world.rb
|
3
|
+
|
4
|
+
require 'json'
|
5
|
+
require 'json_schema'
|
6
|
+
|
7
|
+
require_relative '../lib/agent99'
|
8
|
+
require_relative 'hello_world_request'
|
9
|
+
|
10
|
+
class HelloWorld < Agent99::Base
|
11
|
+
REQUEST_SCHEMA = HelloWorldRequest.schema
|
12
|
+
# RESPONSE_SCHEMA = Agent99::RESPONSE.schema
|
13
|
+
# ERROR_SCHEMA = Agent99::ERROR.schema
|
14
|
+
|
15
|
+
# The request is in @payload
|
16
|
+
def receive_request
|
17
|
+
send_response( validate_request || process )
|
18
|
+
end
|
19
|
+
|
20
|
+
# This method validates the incoming request and returns any errors found
|
21
|
+
# or nil if there are no errors.
|
22
|
+
# It allows for returning an array of errors.
|
23
|
+
#
|
24
|
+
# TODO: consider a 4th message type of error
|
25
|
+
#
|
26
|
+
def validate_request
|
27
|
+
responses = []
|
28
|
+
|
29
|
+
# Check if the ID matches
|
30
|
+
unless id == to_uuid
|
31
|
+
logger.error <<~ERROR
|
32
|
+
#{name} received someone else's request
|
33
|
+
id: #{id} timestamp: #{timestamp}
|
34
|
+
to_uuid: #{to_uuid}
|
35
|
+
from_uuid: #{from_uuid}
|
36
|
+
event_uuid:#{event_uuid}
|
37
|
+
ERROR
|
38
|
+
responses << {
|
39
|
+
error: "Incorrect message queue for header",
|
40
|
+
details: {
|
41
|
+
id: id,
|
42
|
+
header: header
|
43
|
+
}
|
44
|
+
}
|
45
|
+
end
|
46
|
+
|
47
|
+
# Validate the incoming request body against the schema
|
48
|
+
validation_errors = validate_schema
|
49
|
+
unless validation_errors.empty?
|
50
|
+
logger.error "Validation errors: #{validation_errors}"
|
51
|
+
responses << {
|
52
|
+
error: "Invalid request",
|
53
|
+
details: validation_errors
|
54
|
+
}
|
55
|
+
end
|
56
|
+
|
57
|
+
responses.empty? ? nil : responses
|
58
|
+
end
|
59
|
+
|
60
|
+
# Returns the response value
|
61
|
+
# All response message have the same schema in that
|
62
|
+
# they have a header (all messages have headers) and
|
63
|
+
# a result element that is a String. Could it be
|
64
|
+
# a JSON string, sure but then we would need a
|
65
|
+
# RESPONSE_SCHEMA constant for the class.
|
66
|
+
def process
|
67
|
+
{
|
68
|
+
result: get(:greeting) + ' ' + get(:name)
|
69
|
+
}
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
# As a server type, HelloWorld should never receive
|
74
|
+
# a response message.
|
75
|
+
def receive_response(response)
|
76
|
+
loger.warn("Unexpected response type message: response.inspect")
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
# NOTE: what I'm thinking about here is similar to the
|
82
|
+
# prompt tool (aka function) callback facility
|
83
|
+
# where descriptive text is used to describe
|
84
|
+
# what the tool does.
|
85
|
+
#
|
86
|
+
# TODO: scale this idea back to just keywords
|
87
|
+
# until the registry program gets more
|
88
|
+
# stuff added to its discovery process.
|
89
|
+
#
|
90
|
+
def capabilities
|
91
|
+
%w[ greeter hello_world hello-world hello]
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# Example usage
|
96
|
+
agent = HelloWorld.new
|
97
|
+
agent.run # Starts listening for messages
|
@@ -0,0 +1,70 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# examples/hello_world_client.rb
|
3
|
+
|
4
|
+
require 'json'
|
5
|
+
require 'json_schema'
|
6
|
+
require 'securerandom'
|
7
|
+
require_relative '../lib/agent99'
|
8
|
+
|
9
|
+
class HelloWorldClient < Agent99::Base
|
10
|
+
def init
|
11
|
+
send_request
|
12
|
+
end
|
13
|
+
|
14
|
+
def send_request
|
15
|
+
to_uuid = discover_agent(capability: 'greeter', how_many: 1).first[:uuid]
|
16
|
+
|
17
|
+
request = build_request(
|
18
|
+
to_uuid:,
|
19
|
+
greeting: 'Hey',
|
20
|
+
name: 'MadBomber'
|
21
|
+
)
|
22
|
+
|
23
|
+
result = @message_client.publish(request)
|
24
|
+
logger.info "Sent request: #{request.inspect}; status? #{result.inspect}"
|
25
|
+
end
|
26
|
+
|
27
|
+
def build_request(
|
28
|
+
to_uuid:,
|
29
|
+
greeting: 'Hello',
|
30
|
+
name: 'World'
|
31
|
+
)
|
32
|
+
|
33
|
+
{
|
34
|
+
header: {
|
35
|
+
type: 'request',
|
36
|
+
from_uuid: @id,
|
37
|
+
to_uuid:,
|
38
|
+
event_uuid: SecureRandom.uuid,
|
39
|
+
timestamp: Agent99::Timestamp.new.to_i
|
40
|
+
},
|
41
|
+
greeting:,
|
42
|
+
name:
|
43
|
+
}
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
def receive_response
|
48
|
+
logger.info "Received response: #{payload.inspect}"
|
49
|
+
result = payload[:result]
|
50
|
+
|
51
|
+
puts
|
52
|
+
puts `echo "#{result}" | boxes -d info`
|
53
|
+
puts
|
54
|
+
|
55
|
+
exit(0)
|
56
|
+
end
|
57
|
+
|
58
|
+
#####################################################
|
59
|
+
private
|
60
|
+
|
61
|
+
def capabilities
|
62
|
+
['hello_world_client']
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
# Example usage
|
68
|
+
client = HelloWorldClient.new
|
69
|
+
client.run
|
70
|
+
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# examples/hello_world_request.rb
|
2
|
+
|
3
|
+
require_relative '../lib/agent99/header_schema'
|
4
|
+
|
5
|
+
class HelloWorldRequest < SimpleJsonSchemaBuilder::Base
|
6
|
+
object do
|
7
|
+
object :header, schema: Agent99::HeaderSchema
|
8
|
+
|
9
|
+
string :greeting, required: false, examples: ["Hello"]
|
10
|
+
string :name, required: true, examples: ["World"]
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# examples/registry.rb
|
3
|
+
|
4
|
+
require 'debug_me'
|
5
|
+
include DebugMe
|
6
|
+
|
7
|
+
require 'sinatra'
|
8
|
+
require 'json'
|
9
|
+
require 'bunny'
|
10
|
+
require 'securerandom'
|
11
|
+
|
12
|
+
# In-memory registry to store agent capabilities
|
13
|
+
# Array(Hash)
|
14
|
+
# TODO: change this data store to a sqlite database
|
15
|
+
# maybe with a vector search capability.
|
16
|
+
#
|
17
|
+
AGENT_REGISTRY = []
|
18
|
+
|
19
|
+
# Health check endpoint
|
20
|
+
get '/healthcheck' do
|
21
|
+
content_type :json
|
22
|
+
{ agent_count: AGENT_REGISTRY.size }.to_json
|
23
|
+
end
|
24
|
+
|
25
|
+
# Endpoint to register an agent
|
26
|
+
post '/register' do
|
27
|
+
request.body.rewind
|
28
|
+
agent_info = JSON.parse(request.body.read, symbolize_names: true)
|
29
|
+
|
30
|
+
agent_name = agent_info[:name]
|
31
|
+
capabilities = agent_info[:capabilities]
|
32
|
+
|
33
|
+
agent_uuid = SecureRandom.uuid
|
34
|
+
|
35
|
+
AGENT_REGISTRY << agent_info.merge({uuid: agent_uuid})
|
36
|
+
|
37
|
+
status 201
|
38
|
+
content_type :json
|
39
|
+
{ uuid: agent_uuid }.to_json
|
40
|
+
end
|
41
|
+
|
42
|
+
# Endpoint to discover agents by capability
|
43
|
+
# TODO: This is a simple keyword matcher. Looking
|
44
|
+
# => for a semantic match process.
|
45
|
+
get '/discover' do
|
46
|
+
capability = params['capability']
|
47
|
+
|
48
|
+
matching_agents = AGENT_REGISTRY.select do |agent|
|
49
|
+
agent[:capabilities].include?(capability)
|
50
|
+
end
|
51
|
+
|
52
|
+
content_type :json
|
53
|
+
matching_agents.to_json
|
54
|
+
end
|
55
|
+
|
56
|
+
# Withdraw an agent from the registry
|
57
|
+
delete '/withdraw/:uuid' do
|
58
|
+
uuid = params['uuid']
|
59
|
+
how_many = AGENT_REGISTRY.size
|
60
|
+
|
61
|
+
AGENT_REGISTRY.delete_if { |agent_info| agent_info[:uuid] == uuid }
|
62
|
+
|
63
|
+
if AGENT_REGISTRY.size == how_many
|
64
|
+
status 404 # Not Found
|
65
|
+
content_type :json
|
66
|
+
{ error: "Agent with UUID #{uuid} not found." }.to_json
|
67
|
+
else
|
68
|
+
status 204 # No Content
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# Display all registered agents
|
73
|
+
get '/' do
|
74
|
+
content_type :json
|
75
|
+
AGENT_REGISTRY.to_json
|
76
|
+
end
|
77
|
+
|
78
|
+
# Start the Sinatra server
|
79
|
+
if __FILE__ == $PROGRAM_NAME
|
80
|
+
Sinatra::Application.run!
|
81
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
# Start the registry server
|
4
|
+
echo "Starting registry server..."
|
5
|
+
# Assuming the registry server is a separate process, replace with actual command
|
6
|
+
# e.g., ruby registry_server.rb &
|
7
|
+
# Replace 'registry_server_command' with the actual command to start your registry server
|
8
|
+
# Example: ruby registry_server.rb &
|
9
|
+
./registry.rb &
|
10
|
+
|
11
|
+
# Start the HelloWorld agent
|
12
|
+
echo "Starting HelloWorld agent..."
|
13
|
+
./hello_world.rb &
|
14
|
+
|
15
|
+
# Start the HelloWorldClient agent
|
16
|
+
echo "Starting HelloWorldClient agent..."
|
17
|
+
./hello_world_client.rb &
|
18
|
+
|
19
|
+
# Wait for all background processes to finish
|
20
|
+
wait
|
data/lib/agent99/.irbrc
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# lib/agent99/agent_discovery.rb
|
2
|
+
|
3
|
+
module Agent99::AgentDiscovery
|
4
|
+
|
5
|
+
# Returns the agent's capabilities (to be overridden by subclasses).
|
6
|
+
#
|
7
|
+
# @return [Array<String>] The agent's capabilities
|
8
|
+
#
|
9
|
+
def capabilities
|
10
|
+
[]
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
################################################
|
15
|
+
private
|
16
|
+
|
17
|
+
# Discovers other agents with a specific capability.
|
18
|
+
#
|
19
|
+
# @param capability [String] The capability to search for
|
20
|
+
# @param how_many [Integer] The number of agents to return
|
21
|
+
# @param all [Boolean] Whether to return all matching agents
|
22
|
+
# @return [Array<Hash>] The discovered agents
|
23
|
+
# @raise [RuntimeError] If no agents are found
|
24
|
+
#
|
25
|
+
def discover_agent(capability:, how_many: 1, all: false)
|
26
|
+
result = @registry_client.discover(capability:)
|
27
|
+
|
28
|
+
if result.empty?
|
29
|
+
logger.error "No agents found for capability: #{capability}"
|
30
|
+
raise "No agents available"
|
31
|
+
end
|
32
|
+
|
33
|
+
all ? result : result.sample(how_many)
|
34
|
+
end
|
35
|
+
end
|