agentnet 0.0.1 → 0.0.3

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.
package/README.md CHANGED
@@ -1,215 +1,79 @@
1
- # SmartAgent Framework
2
-
3
- SmartAgent is a flexible, extensible framework for building and orchestrating LLM-powered agents that can communicate, collaborate, and leverage tools to solve complex tasks. It is specifically designed to develop autonomous networks of agents that can work together to accomplish sophisticated objectives with minimal human intervention.
1
+ # Agentnet
4
2
 
5
3
  ## Table of Contents
6
4
 
7
- - [Declarative Agent Definitions](#declarative-agent-definitions)
8
- - [Static Definitions (YAML)](#static-definitions-yaml)
9
- - [Dynamic Implementation (JavaScript)](#dynamic-implementation-javascript)
10
- - [Multi-Agent Systems with YAML](#multi-agent-systems-with-yaml)
11
- - [Key Features](#key-features)
12
- - [Quick Start](#quick-start)
13
- - [Core Concepts](#core-concepts)
14
- - [Agents](#agents)
15
- - [Agent Configuration](#agent-configuration)
16
- - [Tool Binding](#tool-binding)
17
- - [Transport Mechanisms](#transport-mechanisms)
18
- - [Agent Auto-Discovery](#agent-auto-discovery)
19
- - [Agent Handoffs](#agent-handoffs)
20
- - [Advanced Usage](#advanced-usage)
21
- - [Events and Hooks](#events-and-hooks)
22
- - [Multi-Agent Systems](#multi-agent-systems)
23
- - [Session State Management](#session-state-management)
5
+ - [Introduction](#introduction)
24
6
  - [Installation](#installation)
25
- - [License](#license)
26
-
27
- ## Declarative Agent Definitions
28
-
29
- A key feature of SmartAgent is the ability to define agents declaratively using YAML files, separating the static definition of agents from their dynamic runtime behavior:
7
+ - [API Keys Configuration](#api-keys-configuration)
8
+ - [Super Simple Example (Quick Start)](#super-simple-example-quick-start)
9
+ - [Declarative Agent Definitions (YAML & JavaScript)](#declarative-agent-definitions-yaml--javascript)
10
+ - [State Management](#state-management)
11
+ - [Network Topologies & Filtering](#network-topologies--filtering)
12
+ - [Available LLMs, Stores, and IO](#available-llms-stores-and-io)
13
+ - [Direct Access to Agent Fluent Interface](#direct-access-to-agent-fluent-interface)
14
+ - [Examples](#examples)
30
15
 
31
- ### Static Definitions (YAML)
32
-
33
- Agents can be defined in YAML files that specify:
34
- - Metadata (name, description)
35
- - LLM configuration (provider, model, system instructions)
36
- - Transport mechanisms (NATS, etc.)
37
- - Tool schemas (name, description, parameters)
38
- - Discovery schemas for inter-agent communication
39
16
 
40
- Example YAML definition:
17
+ ## Introduction
41
18
 
42
- ```yaml
43
- ---
44
- apiVersion: smartagent.io/v1alpha1
45
- kind: AgentDefinition
46
- metadata:
47
- name: bookingAgent
48
- namespace: smartchat
49
- spec:
50
- io:
51
- - type: NatsIO
52
- bindings:
53
- discoveryTopic: smartness.discovery
54
- doHandoffsTo:
55
- - "smartness.accomodation.*"
19
+ Agentnet empowers you to build sophisticated autonomous systems by creating and connecting intelligent agents. These agents can be defined statically for clear, version-controlled structures, or dynamically for flexible runtime behaviors. Agentnet facilitates the creation of powerful network meshes where agents can collaborate seamlessly.
56
20
 
57
- llm:
58
- provider: Gemini
59
- model: gemini-2.0-flash
60
- systemInstruction: |
61
- You are a highly advanced booking agent.
62
- Prioritize clarity and helpfulness.
63
- Use tools effectively to gather information.
64
- config:
65
- temperature: 0.5
66
- toolConfig:
67
- functionCallingConfig:
68
- mode: 'auto'
21
+ Key aspects include:
22
+ * **Static & Dynamic Definitions**: Define agents using YAML for a declarative approach, or implement them dynamically with JavaScript for ultimate flexibility. This separation allows for clear versioning of agent capabilities while enabling dynamic runtime bindings and behaviors.
23
+ * **Network Meshes & Auto-Discovery**: Agents can operate within complex network topologies, automatically discovering each other's capabilities. This enables them to form ad-hoc collaborations to solve tasks that a single agent could not.
24
+ * **Transport Agnostic**: Agentnet supports various transport mechanisms, like NATS for distributed systems or direct in-process communication, allowing you to choose the best fit for your deployment.
25
+ * **State Management & Stores**: Robust session state management ensures context is maintained across interactions. Agentnet supports multiple storage backends (e.g., Postgres, Redis, In-Memory) for persisting agent and session data.
69
26
 
70
- tools:
71
- - name: bookRoomTool
72
- description: Book a room to a specific hotel and room.
73
- parameters:
74
- type: object
75
- properties:
76
- hotelName:
77
- type: string
78
- description: The name of the hotel.
79
- roomName:
80
- type: string
81
- description: The name of the room.
82
- checkinDate:
83
- type: string
84
- description: The check-in date.
85
- checkoutDate:
86
- type: string
87
- description: The check-out date.
88
- required:
89
- - hotelName
90
- - roomName
91
-
92
- discoverySchemas:
93
- - name: booking_agent_query
94
- description: Perform a booking to a specific hotel and room.
95
- parameters:
96
- type: object
97
- properties:
98
- hotelName:
99
- type: string
100
- description: The name of the hotel.
101
- roomName:
102
- type: string
103
- description: The name of the room.
104
- ```
105
-
106
- You can define multiple agents in a single YAML file using YAML document separators (`---`). Each agent can have its own specialized role in a multi-agent system.
107
-
108
- ### Dynamic Implementation (JavaScript)
109
-
110
- The YAML definitions are loaded at runtime, and tool implementations are dynamically bound using JavaScript:
111
-
112
- ```javascript
113
- // Load all agents from a YAML file
114
- const agents = await AgentLoaderFile('./agents.yaml', {
115
- bindings: { [Bindings.NatsIO]: natsInstance }
116
- });
117
-
118
- // Access a specific agent
119
- const bookingAgent = agents.bookingAgent;
120
- const pricingAgent = agents.pricingAgent;
27
+ ## Key Features
121
28
 
122
- // Bind tool implementations
123
- bookingAgent.tools.bookRoomTool.bind(async (state, input) => {
124
- // Actual implementation to book a room
125
- return {
126
- confirmation: `Room ${input.roomName} booked at ${input.hotelName}
127
- from ${input.checkinDate} to ${input.checkoutDate}`
128
- };
129
- });
29
+ * **Autonomous Agent Networks**: Design self-organizing networks where agents discover, communicate, and collaborate with minimal human intervention.
30
+ * **Modular Agent Architecture**: Build specialized agents with distinct capabilities and compose them to tackle complex problems.
31
+ * **Declarative & Programmatic Definitions**: Define agents using YAML or configure them programmatically with a fluent JavaScript API.
32
+ * **Flexible Tool Binding**: Easily bind JavaScript functions to agent tools, enabling them to interact with external systems and data.
33
+ * **Agent Handoffs**: Seamlessly delegate tasks between agents based on their expertise.
34
+ * **LLM Provider Agnostic**: Supports multiple LLM providers (e.g., Gemini, OpenAI GPT) and is extensible.
35
+ * **Persistent Sessions**: Maintain conversation context and state across multiple interactions using configurable storage backends.
36
+ * **Network Filtering**: Control agent communication with powerful wildcard-based network filtering for enhanced security and efficiency.
130
37
 
131
- // Customize prompt/response handling
132
- bookingAgent.prompt((state, input) => {
133
- // Pre-process input before sending to LLM
134
- console.log(`Received booking request: ${input}`);
135
- return input;
136
- });
137
38
 
138
- bookingAgent.response((state, conversation, result) => {
139
- // Post-process response from LLM
140
- return `Booking confirmation: ${result}`;
141
- });
39
+ ## Installation
142
40
 
143
- // Compile all agents to make them ready for use
144
- await bookingAgent.compile();
145
- await pricingAgent.compile();
41
+ ```bash
42
+ npm install agentnet
146
43
  ```
147
44
 
148
- This separation of concerns allows for:
149
- - Version-controlled agent definitions
150
- - Reusable tool schemas
151
- - Dynamic runtime implementation
152
- - Easy testing and deployment
153
- - Clear separation between definition and implementation
154
-
155
- ### Multi-Agent Systems with YAML
156
-
157
- The framework excels at creating autonomous multi-agent systems where specialized agents collaborate with minimal supervision. Each agent in the network can operate independently while maintaining awareness of other agents' capabilities. This creates a resilient, self-organizing system that can tackle complex tasks through agent collaboration. An example setup might include:
158
-
159
- ```javascript
160
- // Load a set of specialized agents from YAML
161
- const agents = await AgentLoaderFile('./agents-smartness.yaml', {
162
- bindings: { [Bindings.NatsIO]: natsIO }
163
- });
164
-
165
- // Configure each agent with specific tool implementations
166
- agents.accomodationAgent.tools.getRoomsListTool.bind(async (state, input) => {
167
- // Implementation for listing available rooms
168
- return { rooms: ["Double room with sea view", "Single room with pool view"] };
169
- });
45
+ ## API Keys Configuration
170
46
 
171
- agents.pricingAgent.tools.getPricingTool.bind(async (state, input) => {
172
- // Implementation for getting room prices
173
- return { price: "200€ per night" };
174
- });
47
+ Agentnet requires API keys for accessing the LLM providers you plan to use. The keys should be set as environment variables:
175
48
 
176
- agents.bookingAgent.tools.bookRoomTool.bind(async (state, input) => {
177
- // Implementation for booking rooms
178
- return { confirmation: "Booking confirmed" };
179
- });
49
+ - **Gemini**: Set `GEMINI_API_KEY` for using Google's Gemini models
50
+ - **OpenAI**: Set `OPENAI_API_KEY` for using OpenAI's GPT models
180
51
 
181
- // Compile all agents
182
- await Promise.all(Object.values(agents).map(agent => agent.compile()));
52
+ You can set these environment variables in your deployment environment or use a `.env` file with a package like `dotenv`:
183
53
 
184
- // Wait for agent discovery to complete
185
- await new Promise(resolve => setTimeout(resolve, 2000));
54
+ ```javascript
55
+ // In your main file, before importing agentnet
56
+ import dotenv from 'dotenv';
57
+ dotenv.config();
186
58
 
187
- // Query the main orchestrator agent
188
- const client = AgentClient();
189
- const response = await client.queryIo(
190
- natsIO,
191
- 'smartnessAgent',
192
- "What rooms do you have available for next weekend and how much do they cost?"
193
- );
59
+ // Now the API keys are available to agentnet
60
+ import { Agent, Gemini } from "agentnet";
194
61
  ```
195
62
 
196
- With this setup, the smartness agent will automatically discover and delegate to specialized agents for accommodation, pricing, and booking, creating an autonomous network that collectively solves the user's query.
63
+ Example `.env` file:
64
+ ```
65
+ GEMINI_API_KEY=your_gemini_api_key_here
66
+ OPENAI_API_KEY=your_openai_api_key_here
67
+ ```
197
68
 
198
- ## Key Features
69
+ > Note: If you try to use an LLM provider without setting the corresponding API key, Agentnet will throw an error indicating which environment variable is missing.
199
70
 
200
- - **Autonomous Agent Networks**: Create self-organizing networks of agents that can discover, communicate, and collaborate with minimal human intervention
201
- - **Modular Agent Architecture**: Create specialized agents with distinct capabilities and compose them to solve complex problems
202
- - **Transport Agnostic**: Work with agents directly or through transport mechanisms like NATS
203
- - **Auto-Discovery**: Agents can discover each other's capabilities dynamically at runtime
204
- - **Tool Binding**: Easily bind JavaScript functions to agent tools
205
- - **Agent Handoffs**: Seamlessly delegate tasks between agents
206
- - **LLM Provider Agnostic**: Support for multiple LLM providers (Gemini and extensible to others)
207
- - **Persistent Sessions**: Maintain conversation context and state across interactions
71
+ ## Super Simple Example (Quick Start)
208
72
 
209
- ## Quick Start
73
+ Here's how you can quickly get an agent up and running:
210
74
 
211
75
  ```javascript
212
- import { Agent, Gemini, NatsIO } from "smartagent";
76
+ import { Agent, Gemini } from "agentnet"; // Assuming Gemini is configured
213
77
 
214
78
  // Create a simple agent
215
79
  const myAgent = Agent()
@@ -217,272 +81,361 @@ const myAgent = Agent()
217
81
  name: "myAgent",
218
82
  description: "A helpful assistant"
219
83
  })
220
- .withLLM(Gemini, {
221
- model: "gemini-pro",
84
+ .withLLM(Gemini, { // Or use LLMRuntime.GPT for OpenAI
85
+ model: "gemini-pro", // Replace with your desired model
222
86
  systemInstruction: "You are a helpful assistant"
223
87
  })
224
88
  .addToolSchema({
225
89
  name: "weatherTool",
226
90
  description: "Get weather information",
227
- parameters: {
91
+ parameters: { // Simplified for brevity; use JSON schema for complex types
228
92
  location: "string"
229
93
  }
230
94
  });
231
95
 
232
- // Bind tool implementation
96
+ // Compile the agent and bind tool implementation
233
97
  const compiledAgent = await myAgent.compile();
234
98
  compiledAgent.tools.weatherTool.bind(async (state, input) => {
235
- return { weather: "Sunny", temperature: 25 };
99
+ // Actual implementation to get weather
100
+ return { weather: "Sunny", temperature: 25, location: input.location };
236
101
  });
237
102
 
238
103
  // Query the agent
239
104
  const response = await compiledAgent.query("What's the weather like in Paris?");
240
- console.log(response);
105
+ console.log(response.getContent()); // Access the agent's response content
241
106
  ```
242
107
 
243
- ## Core Concepts
108
+ ## Declarative Agent Definitions (YAML & JavaScript)
244
109
 
245
- ### Agents
110
+ Agentnet shines with its ability to separate static agent definitions (YAML) from dynamic runtime behavior (JavaScript).
246
111
 
247
- Agents are the core building blocks of the framework. Each agent:
248
-
249
- - Has its own identity (name, description)
250
- - Can be configured with an LLM provider
251
- - Can define and implement tools
252
- - Can discover and communicate with other agents
112
+ ### Static Definitions (YAML)
253
113
 
254
- ### Agent Configuration
114
+ Define agent metadata, LLM configurations, transport, tools, and discovery schemas in YAML:
255
115
 
256
- Agents can be configured programmatically or via YAML definitions:
116
+ ```yaml
117
+ ---
118
+ apiVersion: agentnet/v1alpha1
119
+ kind: AgentDefinition
120
+ metadata:
121
+ name: bookingAgent
122
+ namespace: smartchat
123
+ spec:
124
+ io: # Transport and network configuration
125
+ - type: NatsIO
126
+ bindings:
127
+ discoveryTopic: "smartness.discovery"
128
+ acceptedNetworks:
129
+ - "smartchat.*" # Accepts messages from any agent in the 'smartchat' namespace
257
130
 
258
- ```javascript
259
- // Programmatic configuration
260
- const myAgent = Agent()
261
- .setMetadata({ name: "myAgent" })
262
- .withLLM(Gemini, { model: "gemini-pro" })
263
- .addToolSchema(myToolSchema);
131
+ llm:
132
+ provider: Gemini # Or GPT
133
+ model: gemini-1.5-flash # Example model
134
+ systemInstruction: |
135
+ You are a highly advanced booking agent.
136
+ Prioritize clarity and helpfulness.
137
+ config: # This is the native config of the npm driver (genai, openai)
138
+ temperature: 0.5
139
+ # Tool configuration specific to the LLM provider
140
+ toolConfig:
141
+ functionCallingConfig:
142
+ mode: 'auto' # For Gemini
264
143
 
265
- // YAML-based configuration
266
- const agents = await AgentLoaderFile('./agents.yaml', {
267
- bindings: { [Bindings.NatsIO]: natsInstance }
268
- });
144
+ tools: # This is the native config of the npm driver (genai, openai) for tools
145
+ - name: bookRoomTool
146
+ description: Book a room at a specific hotel.
147
+ parameters: # JSON Schema for tool parameters
148
+ type: object
149
+ properties:
150
+ hotelName: { type: string, description: "The name of the hotel." }
151
+ roomName: { type: string, description: "The name of the room." }
152
+ # ... other parameters
153
+ required: [hotelName, roomName]
154
+
155
+ discoverySchemas: # Capabilities this agent wants to discover from others
156
+ - name: pricing_query
157
+ description: Get pricing information for a room.
158
+ # parameters schema for the discovery...
269
159
  ```
270
160
 
271
- ### Tool Binding
161
+ ### API Versioning
272
162
 
273
- Tools allow agents to perform actions in the real world. Each tool:
163
+ Agentnet supports API versioning to maintain backwards compatibility while evolving the platform:
274
164
 
275
- - Has a schema that defines its interface (name, description, parameters)
276
- - Has an implementation bound to it at runtime
277
-
278
- ```javascript
279
- // Define tool schema
280
- agent.addToolSchema({
281
- name: "fetchData",
282
- description: "Fetch data from an API",
283
- parameters: {
284
- url: "string",
285
- method: "string"
286
- }
287
- });
288
-
289
- // Bind implementation
290
- agent.tools.fetchData.bind(async (state, input) => {
291
- // Actual implementation
292
- const response = await fetch(input.url, { method: input.method });
293
- return await response.json();
294
- });
165
+ ```yaml
166
+ apiVersion: agentnet/v1alpha1 # Specify which API version this definition uses
295
167
  ```
296
168
 
297
- ### Transport Mechanisms
169
+ Currently supported API versions:
298
170
 
299
- The framework supports different transport mechanisms for agent communication:
171
+ - `agentnet/v1alpha1`: Current API version
300
172
 
301
- #### Direct Communication
173
+ When creating agent definitions, you should specify which API version you're targeting. This allows Agentnet to:
302
174
 
303
- Agents can be queried directly in the same process:
175
+ 1. Apply the correct validation rules
176
+ 2. Handle differences in configuration format
177
+ 3. Maintain backward compatibility with older definitions
178
+ 4. Enable new features only available in newer versions
304
179
 
305
- ```javascript
306
- const compiledAgent = await myAgent.compile();
307
- const response = await compiledAgent.query("Hello, agent!");
308
- ```
180
+ If you don't specify an `apiVersion`, Agentnet will default to `agentnet/v1alpha1` but will log a warning.
309
181
 
310
- #### NATS-based Communication
182
+ #### Version Migration Tool
311
183
 
312
- Agents can communicate through NATS for distributed deployments:
184
+ Agentnet includes a command-line tool to help migrate your agent definitions to newer API versions:
313
185
 
314
- ```javascript
315
- // Initialize NATS transport
316
- const natsIO = NatsIO({ servers: ['nats://localhost:4222'] });
186
+ ```bash
187
+ # Migrate a YAML file to the latest version
188
+ node src/tools/migrate-version.js ./agents.yaml
317
189
 
318
- // Configure agent with NATS transport
319
- const myAgent = Agent()
320
- .setMetadata({ name: "distributedAgent" })
321
- .addIO(natsIO, { bindings: { discoveryTopic: "agent.discovery" } })
322
- .withLLM(Gemini, { model: "gemini-pro" });
190
+ # Specify a target version
191
+ node src/tools/migrate-version.js ./agents.yaml --version agentnet.io/v1alpha1
192
+
193
+ # Write to a specific output file
194
+ node src/tools/migrate-version.js ./agents.yaml --output ./agents-new.yaml
323
195
 
324
- // Query an agent through NATS
325
- const client = AgentClient();
326
- const response = await client.queryIo(natsIO, 'distributedAgent', "Hello!");
196
+ # Just check if migration is needed without modifying
197
+ node src/tools/migrate-version.js ./agents.yaml --check
327
198
  ```
328
199
 
329
- ### Agent Auto-Discovery
200
+ This tool helps you keep your agent definitions up-to-date with the latest features while maintaining compatibility with the Agentnet platform.
330
201
 
331
- Agents can discover each other's capabilities at runtime through a discovery protocol:
202
+ ### Dynamic Implementation (JavaScript)
332
203
 
333
- 1. Agents publish their capabilities (available tools and schemas) to a discovery topic
334
- 2. Other agents subscribe to the discovery topic and build a catalog of available agents
335
- 3. Agents can then delegate tasks to the most appropriate agent
204
+ Load YAML definitions and bind tool implementations dynamically:
336
205
 
337
206
  ```javascript
338
- // Auto-discovery happens automatically when agents share the same transport
339
- // Just wait for discovery to complete
340
- await new Promise(resolve => setTimeout(resolve, 2000));
207
+ import { AgentLoaderFile, NatsIO, Bindings } from "agentnet";
341
208
 
342
- // Now agents can communicate with each other
343
- ```
209
+ // NatsIO instance (example)
210
+ const natsInstance = NatsIO({ servers: ['nats://localhost:4222'] });
344
211
 
345
- ### Agent Handoffs
212
+ // Load agents from YAML
213
+ const agents = await AgentLoaderFile('./agents.yaml', {
214
+ bindings: { [Bindings.NatsIO]: natsInstance } // Provide necessary bindings
215
+ });
346
216
 
347
- Agents can delegate tasks to other agents with the right capabilities:
217
+ const bookingAgent = agents.bookingAgent;
348
218
 
349
- 1. An agent receives a task it can't handle directly
350
- 2. It identifies another agent with the required capability
351
- 3. It hands off the task to that agent
352
- 4. The specialized agent processes the task and returns the result
219
+ // Bind tool implementations
220
+ bookingAgent.tools.bookRoomTool.bind(async (state, input) => {
221
+ console.log(`Booking room: ${input.roomName} at ${input.hotelName}`);
222
+ // ... actual booking logic ...
223
+ return { confirmation: `Room ${input.roomName} booked at ${input.hotelName}.` };
224
+ });
353
225
 
354
- This happens transparently from the user's perspective, creating a seamless experience.
226
+ // Compile the agent to make it ready
227
+ await bookingAgent.compile();
228
+ ```
355
229
 
356
- ## Advanced Usage
230
+ ## State Management
357
231
 
358
- ### Events and Hooks
232
+ Agentnet provides robust session management for maintaining state across conversations and agent interactions.
359
233
 
360
- Customize agent behavior with event hooks:
234
+ When an agent receives a query, it can load existing session state. This state is merged with any new session data from the query. After processing, the updated state is saved back.
361
235
 
362
236
  ```javascript
363
- agent.prompt((state, input) => {
364
- // Customize input before it reaches the LLM
365
- return `[Processed] ${input}`;
366
- });
237
+ // Example: Querying an agent with session data
238
+ import { Message, AgentClient, NatsIO } from "agentnet"; // Added AgentClient and NatsIO for context
239
+
240
+ const client = AgentClient(); // Assuming you have an AgentClient instance
241
+ const natsIO = NatsIO({ servers: ['nats://localhost:4222'] }); // Example NatsIO
367
242
 
368
- agent.response((state, conversation, result) => {
369
- // Process the result before returning to the user
370
- return `Agent says: ${result}`;
243
+ // Example: Loading and compiling agents
244
+ const agents = await AgentLoaderFile('./hotel-agents.yaml', {
245
+ bindings: {
246
+ [Bindings.NatsIO]: natsIO,
247
+ [Bindings.Postgres]: PostgresStore({ url: "postgres://user:pass@host:port/db" })
248
+ }
371
249
  });
372
- ```
373
250
 
374
- ### Multi-Agent Systems
251
+ // Access individual agents
252
+ const bookingAgent = agents.bookingAgent;
253
+ const pricingAgent = agents.pricingAgent;
375
254
 
376
- Create autonomous networks of specialized agents that collaborate without human intervention:
255
+ // Bind tool implementations
256
+ bookingAgent.tools.bookRoomTool.bind(async (state, input) => {
257
+ // Implementation for booking tool
258
+ return { success: true, bookingId: "BK12345" };
259
+ });
377
260
 
378
- ```javascript
379
- // Create specialized agents
380
- const weatherAgent = Agent()
381
- .setMetadata({ name: "weatherAgent" })
382
- .addToolSchema(weatherToolSchema);
261
+ pricingAgent.tools.getPricingTool.bind(async (state, input) => {
262
+ // Implementation for pricing tool
263
+ state._privatePricingVariable = { done: true }
264
+ return { price: 200, currency: "EUR", perNight: true };
265
+ });
383
266
 
384
- const travelAgent = Agent()
385
- .setMetadata({ name: "travelAgent" })
386
- .addToolSchema(travelToolSchema);
387
-
388
- // The main agent that orchestrates others
389
- const smartAgent = Agent()
390
- .setMetadata({ name: "smartAgent" })
391
- .addDiscoverySchema(weatherDiscoverySchema)
392
- .addDiscoverySchema(travelDiscoverySchema);
393
-
394
- // Compile and connect all agents
395
- await weatherAgent.compile();
396
- await travelAgent.compile();
397
- await smartAgent.compile();
398
-
399
- // Query through the main agent
400
- const response = await smartAgent.query(
401
- "Plan a trip to Paris and tell me about the weather"
402
- );
403
- ```
267
+ // Compile all agents to make them ready
268
+ console.log("Compiling agents...");
269
+ await Promise.all(Object.values(agents).map(agent => agent.compile()));
404
270
 
405
- In this autonomous network:
406
- - Each agent is responsible for a specific domain of expertise
407
- - The orchestrator agent (smartAgent) discovers and routes requests to appropriate specialists
408
- - The network can scale by adding more specialized agents without changing existing ones
409
- - Agents can be deployed across different environments while maintaining communication
271
+ // Wait for agent discovery to complete
272
+ console.log("Waiting for agent discovery...");
273
+ await new Promise(resolve => setTimeout(resolve, 2000));
410
274
 
411
- ### Session State Management
275
+ console.log("Agent network ready!");
412
276
 
413
- The SmartAgent framework provides robust session management for maintaining state across conversations and agent interactions:
414
277
 
415
- ```javascript
416
- // Creating a message with session information
417
278
  const message = new Message({
418
- content: "What rooms do you have available?",
279
+ content: "What rooms do you have available for next weekend?",
419
280
  session: {
420
- id: "67a71e42-a7d8-1db2-ad17-64e1c8546b21", // Reserved system ID
421
- propertySetId: "123", // Custom session data
422
- userPreferences: { roomType: "suite" } // Custom session data
281
+ id: "session_123_user_abc", // Unique session identifier
282
+ userPreferences: { roomType: "suite", view: "sea" },
283
+ _internalCounter: 0 // Private agent variable, not propagated
423
284
  }
424
285
  });
425
286
 
426
- // Query the agent with session context
427
- const result = await agentInstance.query(message);
287
+ // Query the agent using the client
288
+ console.log("Sending query to the entrypoint agent...");
289
+ const response = await client.queryIo(natsIO, 'entrypointAgent', message);
290
+
291
+ // Process the response
292
+ console.log("Agent Response:", response.getContent());
293
+
294
+ // Access the updated session data (private variables like _internalCounter are excluded)
295
+ const updatedSession = response.getSession();
296
+ console.log("Updated Session:", updatedSession);
297
+
428
298
  ```
429
299
 
430
- #### Session ID
300
+ * **Session ID**: A unique `id` in the session object is used for loading/saving state and tracking conversation history.
301
+ * **State Propagation**:
302
+ * Regular session variables (e.g., `userPreferences`) are propagated between agents during handoffs.
303
+ * Private variables (prefixed with `_`, e.g., `_internalCounter`) are agent-specific and not shared. They are saved with the agent's state but removed from the response to the calling agent/client.
304
+ * **Stores Configuration**: Configure persistent storage for session state.
305
+ ```javascript
306
+ import { AgentLoaderFile, PostgresStore, RedisStore, MemoryStore, Bindings } from "agentnet";
307
+
308
+ const agents = await AgentLoaderFile('./agents.yaml', {
309
+ bindings: {
310
+ // [Bindings.NatsIO]: natsInstance, // If using NATS
311
+ [Bindings.Postgres]: PostgresStore({ url: "postgres://user:pass@host:port/db" }),
312
+ // [Bindings.Redis]: RedisStore({ url: "redis://host:port" }),
313
+ // [Bindings.Memory]: MemoryStore() // For testing or simple cases
314
+ }
315
+ });
316
+ ```
317
+ Agent definitions in YAML can specify which store to use if multiple are bound.
318
+
319
+ ## Network Topologies & Filtering
320
+
321
+ Agentnet enables complex multi-agent systems where specialized agents collaborate.
322
+
323
+ Agentnet supports complex network topologies where agents can discover and communicate with each other based on their capabilities and network configurations.
324
+
325
+ ![Agent Network Topology](assets/network01.png)
326
+
327
+ The diagram above illustrates how agents can be organized in a network, with different communication patterns and discovery mechanisms.
431
328
 
432
- The `id` keyword in the session object is reserved for the system. It's used to uniquely identify the session for:
433
- - Loading session state from persistent storage
434
- - Saving session state back to storage
435
- - Tracking conversation history
436
329
 
437
- #### State Propagation
330
+ ### Agent Auto-Discovery & Handoffs
331
+ Agents can publish their capabilities (tools and discovery schemas) and subscribe to discover others. This allows an orchestrator agent, for example, to delegate tasks to the most appropriate specialist agent. This handoff happens transparently.
438
332
 
439
- Session variables have different scopes:
333
+ ### Network Filtering
334
+ Control inter-agent communication using `acceptedNetworks` in the agent's I/O configuration. This uses wildcard patterns for fine-grained control:
440
335
 
441
- 1. **Regular variables** (without underscore prefix) are propagated between agents during handoffs, ensuring continuity of context across the agent system.
336
+ ```yaml
337
+ # In agent_definition.yaml
338
+ # ...
339
+ spec:
340
+ io:
341
+ - type: NatsIO
342
+ bindings:
343
+ discoveryTopic: "smartness.discovery"
344
+ acceptedNetworks:
345
+ - "smartchat.*" # Accept all services in 'smartchat' namespace
346
+ - "finance.pricing" # Accept only 'pricing' service in 'finance' namespace
347
+ - "*.analytics" # Accept 'analytics' services from any namespace
348
+ - "*.*" # Accept all networks (use with caution)
349
+ # ...
350
+ ```
351
+ Agents will only process discovery messages and requests from networks matching their acceptance patterns. The `network` field (e.g., `smartchat.orchestrator`) defines the agent's own address on the network.
442
352
 
443
- 2. **Private variables** (with underscore prefix `_`) are agent-specific and not shared during handoffs. For example:
444
- ```javascript
445
- message.session._agentPrivateData = "This stays with the current agent";
446
- message.session.sharedData = "This is passed between agents";
447
- ```
353
+ In Agentnet, each agent is uniquely identified by a combination of its namespace and name, formatted as `namespace.name`. This identifier serves as the agent's address on the network.
448
354
 
449
- When a session is saved to storage, private variables (starting with `_`) are saved on the agent store, but removed from response to the calling agent to keep the session data clean and focused on shareable information.
450
355
 
451
- #### Stores Configuration
356
+ ## Available LLMs, Stores, and IO
452
357
 
453
- SmartAgent supports different storage backends for persisting session state:
358
+ * **LLM Providers**:
359
+ * **Gemini**: Google's Gemini models.
360
+ * **OpenAI GPT**: OpenAI's GPT models.
361
+ * Easily extensible to other providers.
362
+ * **Stores**:
363
+ * **PostgresStore**: Persist session state in PostgreSQL.
364
+ * **RedisStore**: Use Redis for session state.
365
+ * **MemoryStore**: In-memory store, useful for testing or simple applications.
366
+ * **IO (Transport)**:
367
+ * **NatsIO**: For asynchronous, distributed agent communication using NATS.
368
+ * **Direct Call**: Agents can be invoked directly within the same process.
369
+
370
+ ## Direct Access to Agent Fluent Interface
371
+
372
+ Besides YAML, you can define and configure agents programmatically using a fluent JavaScript API. This offers fine-grained control and is great for dynamic setups or testing.
454
373
 
455
374
  ```javascript
456
- // Configure the agent with a Postgres store
457
- const agents = await AgentLoaderJSON(agentDefinition, {
458
- bindings: {
459
- [Bindings.Postgres]: PostgresStore({
460
- url: "postgres://postgres:postgres@localhost:5432/postgres"
461
- })
462
- }
375
+ import { Agent, Gemini, NatsIO } from "agentnet";
376
+
377
+ const natsIO = NatsIO({ servers: ['nats://localhost:4222'] }); // Example
378
+
379
+ const travelAgent = Agent()
380
+ .setMetadata({
381
+ name: "travelAgent",
382
+ namespace: "trips",
383
+ description: "Helps plan travels"
384
+ })
385
+ .withLLM(Gemini, {
386
+ model: "gemini-pro",
387
+ systemInstruction: "You are a travel planning assistant."
388
+ })
389
+ .addIO(natsIO, { // Configure NATS IO
390
+ network: "trips.travelAgent",
391
+ bindings: {
392
+ discoveryTopic: "global.discovery",
393
+ acceptedNetworks: ["trips.*", "common.weather"]
394
+ }
395
+ })
396
+ .addToolSchema({
397
+ name: "findFlightsTool",
398
+ description: "Find flights for given criteria.",
399
+ parameters: { /* ... schema ... */ }
400
+ })
401
+ .addDiscoverySchema({ // What this agent wants to discover
402
+ name: "weather_service_lookup",
403
+ description: "Finds an agent that can provide weather information.",
404
+ parameters: { /* ... schema ... */ }
405
+ });
406
+
407
+ // Bind implementation for its own tool
408
+ travelAgent.tools.findFlightsTool.bind(async (state, input) => {
409
+ // ... logic to find flights ...
410
+ return { flights: [/* ... flight data ... */] };
463
411
  });
464
412
 
465
- // Or with an in-memory store for testing
466
- const agents = await AgentLoaderJSON(agentDefinition, {
467
- bindings: {
468
- [Bindings.Memory]: MemoryStore()
469
- }
413
+ // Optional: Add prompt/response hooks
414
+ travelAgent.prompt((state, input) => {
415
+ console.log(`Travel agent received prompt: ${input}`);
416
+ return `Plan this trip: ${input}`; // Modify input to LLM
417
+ });
418
+
419
+ travelAgent.response((state, conversation, result) => {
420
+ console.log(`Travel agent sending response: ${result}`);
421
+ return `Your travel plan: ${result}`; // Modify output from LLM
470
422
  });
471
- ```
472
423
 
473
- #### Session Life Cycle
424
+ // Compile the agent
425
+ const compiledTravelAgent = await travelAgent.compile();
474
426
 
475
- 1. When an agent receives a query with a session ID, it attempts to load the existing session state
476
- 2. The state is merged with any new session data provided in the query
477
- 3. The agent processes the query with access to this state
478
- 4. Before responding, the updated state is saved back to storage
479
- 5. Private variables (with `_` prefix) are removed from the response
427
+ // The agent will now connect to NATS, announce itself, and start discovering others.
428
+ // It can also be queried directly if not solely NATS-based or for testing:
429
+ // const response = await compiledTravelAgent.query("Find me a flight to Bali.");
430
+ // console.log(response.getContent());
431
+ ```
480
432
 
481
- This mechanism allows agents to maintain context across multiple interactions while keeping appropriate boundaries between agent-specific and shared data.
433
+ ## Examples
482
434
 
483
- ## Installation
435
+ * **Simple Agent Example**: For beginners, the [`examples/simple/README.md`](https://github.com/smartpricing/agentnet/blob/master/examples/simple/README.md) provides a minimal implementation of an accommodation agent, perfect for understanding the basic concepts of agent definition and tool binding.
484
436
 
485
- ```bash
486
- npm install smartagent
487
- ```
437
+ * **Booking Example**: See a multi-agent system in action for a smart booking scenario in [`examples/smartness/README.md`](https://github.com/smartpricing/agentnet/blob/master/examples/smartness/README.md). This demonstrates concepts like agent discovery, handoffs, and tool usage in a practical setup.
438
+
439
+ * **Customer Support Example**: Explore a customer support system with specialized agents for different support domains in [`examples/customer-support/README.md`](https://github.com/smartpricing/agentnet/blob/master/examples/customer-support/README.md). This shows how agents can collaborate to resolve complex customer inquiries.
488
440
 
441
+ * **Event Planner Example**: Check out the event planning system in [`examples/event-planner/README.md`](https://github.com/smartpricing/agentnet/blob/master/examples/event-planner/README.md) that demonstrates how agents can coordinate to manage calendars, find suitable time slots, and handle event scheduling.