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.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +25 -1
  3. data/README.md +34 -26
  4. data/docs/README.md +57 -0
  5. data/docs/advanced_features.md +115 -0
  6. data/docs/agent99_framework/central_registry.md +94 -0
  7. data/docs/agent99_framework/message_client.md +120 -0
  8. data/docs/agent99_framework/registry_client.md +119 -0
  9. data/docs/agent_discovery.md +66 -0
  10. data/docs/agent_lifecycle.md +137 -0
  11. data/docs/agent_registry_processes.md +108 -0
  12. data/docs/api_reference.md +146 -0
  13. data/docs/architecture.md +77 -0
  14. data/docs/breaking_change_v0.0.4.md +26 -0
  15. data/docs/configuration.md +17 -0
  16. data/docs/control_actions.md +179 -0
  17. data/docs/custom_agent_implementation.md +30 -0
  18. data/docs/diagrams/agent_registry_processes.dot +42 -0
  19. data/docs/diagrams/agent_registry_processes.png +0 -0
  20. data/docs/diagrams/high_level_architecture.dot +26 -0
  21. data/docs/diagrams/high_level_architecture.png +0 -0
  22. data/docs/diagrams/request_flow.dot +42 -0
  23. data/docs/diagrams/request_flow.png +0 -0
  24. data/docs/error_handling_and_logging.md +13 -0
  25. data/docs/extending_the_framework.md +11 -0
  26. data/docs/message_processing.md +165 -0
  27. data/docs/messaging_system.md +129 -0
  28. data/docs/preformance_considerations.md +9 -0
  29. data/docs/schema_definition.md +78 -0
  30. data/docs/security.md +9 -0
  31. data/docs/troubleshooting.md +11 -0
  32. data/docs/what_is_an_agent.md +293 -0
  33. data/examples/README.md +43 -0
  34. data/examples/agent_watcher.rb +106 -0
  35. data/examples/agents/.keep +0 -0
  36. data/examples/chief_agent.rb +17 -6
  37. data/examples/control.rb +16 -7
  38. data/examples/example_agent.rb +39 -0
  39. data/examples/kaos_spy.rb +63 -0
  40. data/examples/maxwell_agent86.rb +15 -26
  41. data/examples/registry.rb +24 -13
  42. data/lib/agent99/agent_discovery.rb +4 -0
  43. data/lib/agent99/agent_lifecycle.rb +34 -10
  44. data/lib/agent99/base.rb +5 -1
  45. data/lib/agent99/header_schema.rb +5 -0
  46. data/lib/agent99/message_processing.rb +3 -1
  47. data/lib/agent99/registry_client.rb +12 -11
  48. data/lib/agent99/tcp_message_client.rb +183 -0
  49. data/lib/agent99/version.rb +1 -1
  50. metadata +50 -3
  51. 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
+
@@ -10,12 +10,21 @@ require_relative '../lib/agent99'
10
10
  require_relative 'maxwell_request'
11
11
 
12
12
  class MaxwellAgent86 < Agent99::Base
13
- REQUEST_SCHEMA = MaxwellRequest.schema
14
- TYPE = :server
15
-
16
- # RESPONSE_SCHEMA = Agent99::RESPONSE.schema
17
- # ERROR_SCHEMA = Agent99::ERROR.schema
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 capabilities
12
- # Array(Hash)
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
- agent_info = JSON.parse(request.body.read, symbolize_names: true)
28
-
29
- agent_name = agent_info[:name]
30
- capabilities = agent_info[:capabilities]
31
-
32
- agent_uuid = SecureRandom.uuid
33
-
34
- AGENT_REGISTRY << agent_info.merge({uuid: agent_uuid})
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].include?(capability)
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
@@ -32,4 +32,8 @@ module Agent99::AgentDiscovery
32
32
 
33
33
  all ? result : result.sample(how_many)
34
34
  end
35
+
36
+ def add_agent(agent_info)
37
+ @agents[agent_info[:uuid]] = agent_info
38
+ end
35
39
  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
- @payload = nil
15
- @name = self.class.name
16
- @capabilities = capabilities
17
- @id = nil
18
- @registry_client = registry_client
19
- @message_client = message_client
20
- @logger = logger
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(name:, capabilities:)
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, :payload, :header, :logger, :queue
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
 
@@ -13,3 +13,8 @@ class Agent99::HeaderSchema < SimpleJsonSchemaBuilder::Base
13
13
  integer :timestamp, required: true, examples: [Agent99::Timestamp.new.to_i]
14
14
  end
15
15
  end
16
+
17
+ __END__
18
+
19
+ string :type, required: true, enum: %w[request response control]
20
+
@@ -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
- schema = JsonSchema.parse!(self.class::REQUEST_SCHEMA)
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('REGISTRY_BASE_URL', 'http://localhost:4567'),
11
+ base_url: ENV.fetch('AGENT99_REGISTRY_URL', 'http://localhost:4567'),
12
12
  logger: Logger.new($stdout)
13
13
  )
14
- @base_url = base_url
15
- @logger = logger
16
- @http_client = Net::HTTP.new(URI.parse(base_url).host, URI.parse(base_url).port)
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(name:, capabilities:)
20
- request = create_request(:post, "/register", { name: name, capabilities: capabilities })
21
- @id = send_request(request)
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 = create_request(:get, "/")
41
- response = send_request(request)
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 = Object.const_get("Net::HTTP::#{method.capitalize}").new(path, { "Content-Type" => "application/json" })
49
- request.body = body.to_json if 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
+
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Agent99
4
- VERSION = "0.0.2"
4
+ VERSION = "0.0.4"
5
5
 
6
6
  def self.version = VERSION
7
7
  end
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.2
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-07 00:00:00.000000000 Z
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/todo.md
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