agent99 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +25 -1
- data/README.md +34 -26
- data/docs/README.md +57 -0
- data/docs/advanced_features.md +115 -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/agent_discovery.md +66 -0
- data/docs/agent_lifecycle.md +137 -0
- data/docs/agent_registry_processes.md +108 -0
- data/docs/api_reference.md +146 -0
- data/docs/architecture.md +77 -0
- data/docs/breaking_change_v0.0.4.md +26 -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/docs/what_is_an_agent.md +293 -0
- data/examples/README.md +43 -0
- data/examples/agent_watcher.rb +106 -0
- data/examples/agents/.keep +0 -0
- data/examples/chief_agent.rb +17 -6
- data/examples/control.rb +16 -7
- data/examples/example_agent.rb +39 -0
- data/examples/kaos_spy.rb +63 -0
- data/examples/maxwell_agent86.rb +15 -26
- data/examples/registry.rb +24 -13
- data/lib/agent99/agent_discovery.rb +4 -0
- data/lib/agent99/agent_lifecycle.rb +34 -10
- data/lib/agent99/base.rb +5 -1
- data/lib/agent99/header_schema.rb +5 -0
- data/lib/agent99/message_processing.rb +3 -1
- data/lib/agent99/registry_client.rb +12 -11
- data/lib/agent99/tcp_message_client.rb +183 -0
- data/lib/agent99/version.rb +1 -1
- metadata +50 -3
- data/docs/todo.md +0 -66
@@ -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/maxwell_agent86.rb
CHANGED
@@ -10,12 +10,21 @@ require_relative '../lib/agent99'
|
|
10
10
|
require_relative 'maxwell_request'
|
11
11
|
|
12
12
|
class MaxwellAgent86 < Agent99::Base
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
#
|
17
|
-
|
18
|
-
|
13
|
+
# this information is made available when the agent
|
14
|
+
# registers with the central registry service. It is
|
15
|
+
# made available during the discovery process.
|
16
|
+
#
|
17
|
+
def info
|
18
|
+
{
|
19
|
+
name: self.class.to_s,
|
20
|
+
type: :server,
|
21
|
+
capabilities: %w[ greeter hello_world hello-world hello],
|
22
|
+
request_schema: MaxwellRequest.schema,
|
23
|
+
# response_schema: {}, # Agent99::RESPONSE.schema
|
24
|
+
# control_schema: {}, # Agent99::CONTROL.schema
|
25
|
+
# error_schema: {}, # Agent99::ERROR.schema
|
26
|
+
}
|
27
|
+
end
|
19
28
|
|
20
29
|
#######################################
|
21
30
|
private
|
@@ -90,26 +99,6 @@ class MaxwellAgent86 < Agent99::Base
|
|
90
99
|
def receive_response(response)
|
91
100
|
loger.warn("Unexpected response type message: response.inspect")
|
92
101
|
end
|
93
|
-
|
94
|
-
|
95
|
-
# Phase One Implementation is to do a search
|
96
|
-
# using the String#include? and the Array#include?
|
97
|
-
# methods. If you want discrete word-based selection
|
98
|
-
# then use an Array of Strings to define the different
|
99
|
-
# things this agent can do.
|
100
|
-
#
|
101
|
-
# If you want to match on sub-strings then define the
|
102
|
-
# the capabilities as a String.
|
103
|
-
#
|
104
|
-
# Subsequent implementations may use a semantic search
|
105
|
-
# to find the agents to use in which case capabilities may
|
106
|
-
# be constrained to be a String.
|
107
|
-
#
|
108
|
-
# For now, lets just go with the Array of Strings.
|
109
|
-
#
|
110
|
-
def capabilities
|
111
|
-
%w[ greeter hello_world hello-world hello]
|
112
|
-
end
|
113
102
|
end
|
114
103
|
|
115
104
|
# Example usage
|
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
|
#
|
@@ -24,14 +27,22 @@ end
|
|
24
27
|
# Endpoint to register an agent
|
25
28
|
post '/register' do
|
26
29
|
request.body.rewind
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
agent_uuid
|
33
|
-
|
34
|
-
|
30
|
+
request_data = JSON.parse(request.body.read, symbolize_names: true)
|
31
|
+
debug_me{[
|
32
|
+
:request_data
|
33
|
+
]}
|
34
|
+
agent_name = request_data[:name]
|
35
|
+
agent_uuid = SecureRandom.uuid
|
36
|
+
|
37
|
+
debug_me{[
|
38
|
+
:agent_name,
|
39
|
+
:agent_uuid
|
40
|
+
]}
|
41
|
+
|
42
|
+
# Ensure capabilities are lowercase
|
43
|
+
request_data[:capabilities].map!{|c| c.downcase}
|
44
|
+
|
45
|
+
AGENT_REGISTRY << request_data.merge({uuid: agent_uuid})
|
35
46
|
|
36
47
|
status 201
|
37
48
|
content_type :json
|
@@ -42,10 +53,10 @@ end
|
|
42
53
|
# TODO: This is a simple keyword matcher. Looking
|
43
54
|
# => for a semantic match process.
|
44
55
|
get '/discover' do
|
45
|
-
capability = params['capability']
|
56
|
+
capability = params['capability'].downcase
|
46
57
|
|
47
58
|
matching_agents = AGENT_REGISTRY.select do |agent|
|
48
|
-
agent[:capabilities]
|
59
|
+
agent[:capabilities]&.include?(capability)
|
49
60
|
end
|
50
61
|
|
51
62
|
content_type :json
|
@@ -77,4 +88,4 @@ end
|
|
77
88
|
# Start the Sinatra server
|
78
89
|
if __FILE__ == $PROGRAM_NAME
|
79
90
|
Sinatra::Application.run!
|
80
|
-
end
|
91
|
+
end
|
@@ -11,16 +11,19 @@ module Agent99::AgentLifecycle
|
|
11
11
|
def initialize(registry_client: Agent99::RegistryClient.new,
|
12
12
|
message_client: Agent99::AmqpMessageClient.new,
|
13
13
|
logger: Logger.new($stdout))
|
14
|
-
@
|
15
|
-
@
|
16
|
-
@
|
17
|
-
@
|
18
|
-
@
|
19
|
-
@
|
20
|
-
@
|
14
|
+
@agents = {}
|
15
|
+
@payload = nil
|
16
|
+
@name = self.class.name
|
17
|
+
@capabilities = capabilities
|
18
|
+
@id = nil
|
19
|
+
@registry_client = registry_client
|
20
|
+
@message_client = message_client
|
21
|
+
@logger = logger
|
22
|
+
|
23
|
+
validate_info_keys
|
21
24
|
|
22
25
|
@registry_client.logger = logger
|
23
|
-
register
|
26
|
+
register(info)
|
24
27
|
|
25
28
|
@queue = message_client.setup(agent_id: id, logger:)
|
26
29
|
|
@@ -29,12 +32,33 @@ module Agent99::AgentLifecycle
|
|
29
32
|
setup_signal_handlers
|
30
33
|
end
|
31
34
|
|
35
|
+
|
36
|
+
def validate_info_keys
|
37
|
+
required_keys = [:name, :capabilities]
|
38
|
+
if respond_to? :info
|
39
|
+
missing_keys = required_keys - info.keys
|
40
|
+
unless missing_keys.empty?
|
41
|
+
logger.error <<~MESSAGE
|
42
|
+
This agent's info method is missing
|
43
|
+
#{1 == missing_keys.size ? 'a required key' : 'some required keys'}:
|
44
|
+
#{missing_keys}
|
45
|
+
MESSAGE
|
46
|
+
.split("\n").join
|
47
|
+
exit(1)
|
48
|
+
end
|
49
|
+
else
|
50
|
+
logger.error "An agent must implement the info method"
|
51
|
+
exit(1)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
|
32
56
|
# Registers the agent with the registry service.
|
33
57
|
#
|
34
58
|
# @raise [StandardError] If registration fails
|
35
59
|
#
|
36
|
-
def register
|
37
|
-
@id = registry_client.register(
|
60
|
+
def register(agent_info)
|
61
|
+
@id = registry_client.register(info: agent_info)
|
38
62
|
logger.info "Registered Agent #{name} with ID: #{id}"
|
39
63
|
rescue StandardError => e
|
40
64
|
handle_error("Error during registration", e)
|
data/lib/agent99/base.rb
CHANGED
@@ -37,7 +37,11 @@ class Agent99::Base
|
|
37
37
|
|
38
38
|
MESSAGE_TYPES = %w[request response control]
|
39
39
|
|
40
|
-
attr_reader :id, :capabilities, :name
|
40
|
+
attr_reader :id, :capabilities, :name
|
41
|
+
attr_reader :payload, :header, :queue
|
42
|
+
attr_reader :logger
|
43
|
+
attr_reader :agents
|
44
|
+
|
41
45
|
attr_accessor :registry_client, :message_client
|
42
46
|
|
43
47
|
|
@@ -128,7 +128,9 @@ module Agent99::MessageProcessing
|
|
128
128
|
# @return [Array] An array of validation errors, empty if validation succeeds
|
129
129
|
#
|
130
130
|
def validate_schema
|
131
|
-
|
131
|
+
return unless info[:request_schema]
|
132
|
+
|
133
|
+
schema = JsonSchema.parse!(info[:request_schema])
|
132
134
|
schema.expand_references!
|
133
135
|
validator = JsonSchema::Validator.new(schema)
|
134
136
|
|
@@ -8,17 +8,18 @@ class Agent99::RegistryClient
|
|
8
8
|
attr_accessor :logger
|
9
9
|
|
10
10
|
def initialize(
|
11
|
-
base_url: ENV.fetch('
|
11
|
+
base_url: ENV.fetch('AGENT99_REGISTRY_URL', 'http://localhost:4567'),
|
12
12
|
logger: Logger.new($stdout)
|
13
13
|
)
|
14
|
-
@base_url
|
15
|
-
@logger
|
16
|
-
@http_client
|
14
|
+
@base_url = base_url
|
15
|
+
@logger = logger
|
16
|
+
@http_client = Net::HTTP.new(URI.parse(base_url).host, URI.parse(base_url).port)
|
17
17
|
end
|
18
18
|
|
19
|
-
def register(
|
20
|
-
|
21
|
-
|
19
|
+
def register(info:)
|
20
|
+
payload = info
|
21
|
+
request = create_request(:post, "/register", payload)
|
22
|
+
@id = send_request(request)
|
22
23
|
end
|
23
24
|
|
24
25
|
def withdraw(id)
|
@@ -37,16 +38,16 @@ class Agent99::RegistryClient
|
|
37
38
|
|
38
39
|
|
39
40
|
def fetch_all_agents
|
40
|
-
request
|
41
|
-
response
|
41
|
+
request = create_request(:get, "/")
|
42
|
+
response = send_request(request)
|
42
43
|
end
|
43
44
|
|
44
45
|
################################################
|
45
46
|
private
|
46
47
|
|
47
48
|
def create_request(method, path, body = nil)
|
48
|
-
request
|
49
|
-
request.body
|
49
|
+
request = Object.const_get("Net::HTTP::#{method.capitalize}").new(path, { "Content-Type" => "application/json" })
|
50
|
+
request.body = body.to_json if body
|
50
51
|
request
|
51
52
|
end
|
52
53
|
|
@@ -0,0 +1,183 @@
|
|
1
|
+
# lib/agent99/tcp_message_client.rb
|
2
|
+
#
|
3
|
+
# NOTE: This is an early attempt at a true
|
4
|
+
# peer-to-peer messaging platform. Its not
|
5
|
+
# not ready for prime time.
|
6
|
+
|
7
|
+
require 'socket'
|
8
|
+
require 'json'
|
9
|
+
require 'logger'
|
10
|
+
|
11
|
+
class Agent99::TcpMessageClient
|
12
|
+
attr_accessor :agents
|
13
|
+
|
14
|
+
def initialize(
|
15
|
+
agents: {},
|
16
|
+
logger: Logger.new($stdout)
|
17
|
+
)
|
18
|
+
@agents = agents
|
19
|
+
@logger = logger
|
20
|
+
@server_socket = nil
|
21
|
+
@client_connections = {}
|
22
|
+
@handlers = {}
|
23
|
+
@running = false
|
24
|
+
end
|
25
|
+
|
26
|
+
def listen_for_messages(queue, request_handler:, response_handler:, control_handler:)
|
27
|
+
@handlers = {
|
28
|
+
request: request_handler,
|
29
|
+
response: response_handler,
|
30
|
+
control: control_handler
|
31
|
+
}
|
32
|
+
|
33
|
+
start_server(queue[:port])
|
34
|
+
end
|
35
|
+
|
36
|
+
def publish(message)
|
37
|
+
target = message.dig(:header, :to_uuid)
|
38
|
+
return unless target
|
39
|
+
|
40
|
+
agent_info = agents(target)
|
41
|
+
return unless agent_info
|
42
|
+
|
43
|
+
socket = connect_to_agent(agent_info[:ip], agent_info[:port])
|
44
|
+
return unless socket
|
45
|
+
|
46
|
+
begin
|
47
|
+
socket.puts(message.to_json)
|
48
|
+
true
|
49
|
+
|
50
|
+
rescue StandardError => e
|
51
|
+
@logger.error("Failed to send message: #{e.message}")
|
52
|
+
false
|
53
|
+
|
54
|
+
ensure
|
55
|
+
socket.close unless socket.closed?
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def stop
|
60
|
+
@running = false
|
61
|
+
@server_socket&.close
|
62
|
+
@client_connections.each_value(&:close)
|
63
|
+
@client_connections.clear
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def start_server(port)
|
69
|
+
@server_socket = TCPServer.new(port)
|
70
|
+
@running = true
|
71
|
+
|
72
|
+
Thread.new do
|
73
|
+
while @running
|
74
|
+
begin
|
75
|
+
client = @server_socket.accept
|
76
|
+
handle_client(client)
|
77
|
+
rescue StandardError => e
|
78
|
+
@logger.error("Server error: #{e.message}")
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def handle_client(client)
|
85
|
+
Thread.new do
|
86
|
+
while @running
|
87
|
+
begin
|
88
|
+
message = client.gets
|
89
|
+
break if message.nil?
|
90
|
+
|
91
|
+
parsed_message = JSON.parse(message, symbolize_names: true)
|
92
|
+
route_message(parsed_message)
|
93
|
+
|
94
|
+
rescue JSON::ParserError => e
|
95
|
+
@logger.error("Invalid JSON received: #{e.message}")
|
96
|
+
|
97
|
+
rescue StandardError => e
|
98
|
+
@logger.error("Error handling client: #{e.message}")
|
99
|
+
break
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
client.close unless client.closed?
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def route_message(message)
|
108
|
+
type = message.dig(:header, :type)&.to_sym
|
109
|
+
handler = @handlers[type]
|
110
|
+
|
111
|
+
if handler
|
112
|
+
handler.call(message)
|
113
|
+
else
|
114
|
+
@logger.warn("No handler for message type: #{type}")
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def connect_to_agent(ip, port)
|
119
|
+
TCPSocket.new(ip, port)
|
120
|
+
|
121
|
+
rescue StandardError => e
|
122
|
+
@logger.error("Failed to connect to #{ip}:#{port}: #{e.message}")
|
123
|
+
nil
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
|
128
|
+
__END__
|
129
|
+
|
130
|
+
Based on the provided code for the `Agent99::TcpMessageClient` class, here's an analysis of your questions:
|
131
|
+
|
132
|
+
1. Does this class queue up JSON messages while a previous message is being processed?
|
133
|
+
|
134
|
+
No, this class does not explicitly queue up JSON messages while a previous message is being processed. The class processes messages as they are received, without maintaining an internal queue. Each incoming message is handled in its own thread (see the `handle_client` method), which allows for concurrent processing of messages from multiple clients.
|
135
|
+
|
136
|
+
2. Does it present a complete JSON message at once or does it only provide part of one?
|
137
|
+
|
138
|
+
The class attempts to present complete JSON messages at once. Here's why:
|
139
|
+
|
140
|
+
- In the `handle_client` method, messages are read using `client.gets`, which typically reads a full line of input (up to a newline character).
|
141
|
+
- The received message is then parsed as JSON using `JSON.parse(message, symbolize_names: true)`.
|
142
|
+
- If the parsing is successful, the entire parsed message is passed to the `route_message` method.
|
143
|
+
|
144
|
+
However, there are a few potential issues to consider:
|
145
|
+
|
146
|
+
- If a JSON message spans multiple lines, `client.gets` might not capture the entire message in one read.
|
147
|
+
- There's no explicit handling for partial messages or message boundaries.
|
148
|
+
- Large messages might be split across multiple TCP packets, and the current implementation doesn't account for reassembling these.
|
149
|
+
|
150
|
+
To ensure complete message handling, you might want to consider implementing a more robust message framing protocol, such as using message length prefixes or delimiter-based framing.
|
151
|
+
|
152
|
+
For example, you could modify the `handle_client` method to use a delimiter-based approach:
|
153
|
+
|
154
|
+
```ruby
|
155
|
+
def handle_client(client)
|
156
|
+
Thread.new do
|
157
|
+
buffer = ""
|
158
|
+
while @running
|
159
|
+
begin
|
160
|
+
chunk = client.readpartial(1024)
|
161
|
+
buffer += chunk
|
162
|
+
while (message_end = buffer.index("\n"))
|
163
|
+
message = buffer[0...message_end]
|
164
|
+
buffer = buffer[(message_end + 1)..]
|
165
|
+
parsed_message = JSON.parse(message, symbolize_names: true)
|
166
|
+
route_message(parsed_message)
|
167
|
+
end
|
168
|
+
rescue EOFError
|
169
|
+
break
|
170
|
+
rescue JSON::ParserError => e
|
171
|
+
@logger.error("Invalid JSON received: #{e.message}")
|
172
|
+
rescue StandardError => e
|
173
|
+
@logger.error("Error handling client: #{e.message}")
|
174
|
+
break
|
175
|
+
end
|
176
|
+
end
|
177
|
+
client.close unless client.closed?
|
178
|
+
end
|
179
|
+
end
|
180
|
+
```
|
181
|
+
|
182
|
+
This modification would allow for handling of messages that might be split across multiple reads, ensuring that complete JSON messages are processed.
|
183
|
+
|
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.4
|
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-14 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,44 @@ files:
|
|
138
152
|
- LICENSE
|
139
153
|
- README.md
|
140
154
|
- Rakefile
|
141
|
-
- docs/
|
155
|
+
- docs/README.md
|
156
|
+
- docs/advanced_features.md
|
157
|
+
- docs/agent99_framework/central_registry.md
|
158
|
+
- docs/agent99_framework/message_client.md
|
159
|
+
- docs/agent99_framework/registry_client.md
|
160
|
+
- docs/agent_discovery.md
|
161
|
+
- docs/agent_lifecycle.md
|
162
|
+
- docs/agent_registry_processes.md
|
163
|
+
- docs/api_reference.md
|
164
|
+
- docs/architecture.md
|
165
|
+
- docs/breaking_change_v0.0.4.md
|
166
|
+
- docs/configuration.md
|
167
|
+
- docs/control_actions.md
|
168
|
+
- docs/custom_agent_implementation.md
|
169
|
+
- docs/diagrams/agent_registry_processes.dot
|
170
|
+
- docs/diagrams/agent_registry_processes.png
|
171
|
+
- docs/diagrams/high_level_architecture.dot
|
172
|
+
- docs/diagrams/high_level_architecture.png
|
173
|
+
- docs/diagrams/request_flow.dot
|
174
|
+
- docs/diagrams/request_flow.png
|
175
|
+
- docs/error_handling_and_logging.md
|
176
|
+
- docs/extending_the_framework.md
|
177
|
+
- docs/message_processing.md
|
178
|
+
- docs/messaging_system.md
|
179
|
+
- docs/preformance_considerations.md
|
180
|
+
- docs/schema_definition.md
|
181
|
+
- docs/security.md
|
182
|
+
- docs/troubleshooting.md
|
183
|
+
- docs/what_is_an_agent.md
|
142
184
|
- examples/README.md
|
185
|
+
- examples/agent_watcher.rb
|
186
|
+
- examples/agents/.keep
|
143
187
|
- examples/chief_agent.rb
|
144
188
|
- examples/control.rb
|
145
189
|
- examples/diagram.dot
|
146
190
|
- examples/diagram.png
|
191
|
+
- examples/example_agent.rb
|
192
|
+
- examples/kaos_spy.rb
|
147
193
|
- examples/maxwell_agent86.rb
|
148
194
|
- examples/maxwell_request.rb
|
149
195
|
- examples/registry.rb
|
@@ -160,6 +206,7 @@ files:
|
|
160
206
|
- lib/agent99/message_processing.rb
|
161
207
|
- lib/agent99/nats_message_client.rb
|
162
208
|
- lib/agent99/registry_client.rb
|
209
|
+
- lib/agent99/tcp_message_client.rb
|
163
210
|
- lib/agent99/timestamp.rb
|
164
211
|
- lib/agent99/version.rb
|
165
212
|
- sig/ai_agent.rbs
|
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
|