agentnet 0.0.1 → 0.0.2

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,52 @@
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:
30
-
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
-
40
- Example YAML definition:
41
-
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.*"
56
-
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'
69
-
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.
7
+ - [Super Simple Example (Quick Start)](#super-simple-example-quick-start)
8
+ - [Declarative Agent Definitions (YAML & JavaScript)](#declarative-agent-definitions-yaml--javascript)
9
+ - [State Management](#state-management)
10
+ - [Network Topologies & Filtering](#network-topologies--filtering)
11
+ - [Available LLMs, Stores, and IO](#available-llms-stores-and-io)
12
+ - [Direct Access to Agent Fluent Interface](#direct-access-to-agent-fluent-interface)
13
+ - [Examples](#examples)
107
14
 
108
- ### Dynamic Implementation (JavaScript)
109
15
 
110
- The YAML definitions are loaded at runtime, and tool implementations are dynamically bound using JavaScript:
16
+ ## Introduction
111
17
 
112
- ```javascript
113
- // Load all agents from a YAML file
114
- const agents = await AgentLoaderFile('./agents.yaml', {
115
- bindings: { [Bindings.NatsIO]: natsInstance }
116
- });
18
+ 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.
117
19
 
118
- // Access a specific agent
119
- const bookingAgent = agents.bookingAgent;
120
- const pricingAgent = agents.pricingAgent;
20
+ Key aspects include:
21
+ * **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.
22
+ * **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.
23
+ * **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.
24
+ * **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.
121
25
 
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
- });
130
-
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
-
138
- bookingAgent.response((state, conversation, result) => {
139
- // Post-process response from LLM
140
- return `Booking confirmation: ${result}`;
141
- });
142
-
143
- // Compile all agents to make them ready for use
144
- await bookingAgent.compile();
145
- await pricingAgent.compile();
146
- ```
147
-
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
- });
26
+ ## Key Features
170
27
 
171
- agents.pricingAgent.tools.getPricingTool.bind(async (state, input) => {
172
- // Implementation for getting room prices
173
- return { price: "200€ per night" };
174
- });
28
+ * **Autonomous Agent Networks**: Design self-organizing networks where agents discover, communicate, and collaborate with minimal human intervention.
29
+ * **Modular Agent Architecture**: Build specialized agents with distinct capabilities and compose them to tackle complex problems.
30
+ * **Declarative & Programmatic Definitions**: Define agents using YAML or configure them programmatically with a fluent JavaScript API.
31
+ * **Flexible Tool Binding**: Easily bind JavaScript functions to agent tools, enabling them to interact with external systems and data.
32
+ * **Agent Handoffs**: Seamlessly delegate tasks between agents based on their expertise.
33
+ * **LLM Provider Agnostic**: Supports multiple LLM providers (e.g., Gemini, OpenAI GPT) and is extensible.
34
+ * **Persistent Sessions**: Maintain conversation context and state across multiple interactions using configurable storage backends.
35
+ * **Network Filtering**: Control agent communication with powerful wildcard-based network filtering for enhanced security and efficiency.
175
36
 
176
- agents.bookingAgent.tools.bookRoomTool.bind(async (state, input) => {
177
- // Implementation for booking rooms
178
- return { confirmation: "Booking confirmed" };
179
- });
180
37
 
181
- // Compile all agents
182
- await Promise.all(Object.values(agents).map(agent => agent.compile()));
183
-
184
- // Wait for agent discovery to complete
185
- await new Promise(resolve => setTimeout(resolve, 2000));
38
+ ## Installation
186
39
 
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
- );
40
+ ```bash
41
+ npm install agentnet
194
42
  ```
195
43
 
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.
44
+ ## Super Simple Example (Quick Start)
197
45
 
198
- ## Key Features
199
-
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
208
-
209
- ## Quick Start
46
+ Here's how you can quickly get an agent up and running:
210
47
 
211
48
  ```javascript
212
- import { Agent, Gemini, NatsIO } from "smartagent";
49
+ import { Agent, Gemini } from "agentnet"; // Assuming Gemini is configured
213
50
 
214
51
  // Create a simple agent
215
52
  const myAgent = Agent()
@@ -217,272 +54,320 @@ const myAgent = Agent()
217
54
  name: "myAgent",
218
55
  description: "A helpful assistant"
219
56
  })
220
- .withLLM(Gemini, {
221
- model: "gemini-pro",
57
+ .withLLM(Gemini, { // Or use LLMRuntime.GPT for OpenAI
58
+ model: "gemini-pro", // Replace with your desired model
222
59
  systemInstruction: "You are a helpful assistant"
223
60
  })
224
61
  .addToolSchema({
225
62
  name: "weatherTool",
226
63
  description: "Get weather information",
227
- parameters: {
64
+ parameters: { // Simplified for brevity; use JSON schema for complex types
228
65
  location: "string"
229
66
  }
230
67
  });
231
68
 
232
- // Bind tool implementation
69
+ // Compile the agent and bind tool implementation
233
70
  const compiledAgent = await myAgent.compile();
234
71
  compiledAgent.tools.weatherTool.bind(async (state, input) => {
235
- return { weather: "Sunny", temperature: 25 };
72
+ // Actual implementation to get weather
73
+ return { weather: "Sunny", temperature: 25, location: input.location };
236
74
  });
237
75
 
238
76
  // Query the agent
239
77
  const response = await compiledAgent.query("What's the weather like in Paris?");
240
- console.log(response);
78
+ console.log(response.getContent()); // Access the agent's response content
241
79
  ```
242
80
 
243
- ## Core Concepts
244
-
245
- ### Agents
81
+ ## Declarative Agent Definitions (YAML & JavaScript)
246
82
 
247
- Agents are the core building blocks of the framework. Each agent:
83
+ Agentnet shines with its ability to separate static agent definitions (YAML) from dynamic runtime behavior (JavaScript).
248
84
 
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
85
+ ### Static Definitions (YAML)
253
86
 
254
- ### Agent Configuration
87
+ Define agent metadata, LLM configurations, transport, tools, and discovery schemas in YAML:
255
88
 
256
- Agents can be configured programmatically or via YAML definitions:
89
+ ```yaml
90
+ ---
91
+ apiVersion: agentnet.io/v1alpha1
92
+ kind: AgentDefinition
93
+ metadata:
94
+ name: bookingAgent
95
+ namespace: smartchat
96
+ spec:
97
+ io: # Transport and network configuration
98
+ - type: NatsIO
99
+ bindings:
100
+ discoveryTopic: "smartness.discovery"
101
+ acceptedNetworks:
102
+ - "smartchat.*" # Accepts messages from any agent in the 'smartchat' namespace
257
103
 
258
- ```javascript
259
- // Programmatic configuration
260
- const myAgent = Agent()
261
- .setMetadata({ name: "myAgent" })
262
- .withLLM(Gemini, { model: "gemini-pro" })
263
- .addToolSchema(myToolSchema);
104
+ llm:
105
+ provider: Gemini # Or GPT
106
+ model: gemini-1.5-flash # Example model
107
+ systemInstruction: |
108
+ You are a highly advanced booking agent.
109
+ Prioritize clarity and helpfulness.
110
+ config: # This is the native config of the npm driver (genai, openai)
111
+ temperature: 0.5
112
+ # Tool configuration specific to the LLM provider
113
+ toolConfig:
114
+ functionCallingConfig:
115
+ mode: 'auto' # For Gemini
264
116
 
265
- // YAML-based configuration
266
- const agents = await AgentLoaderFile('./agents.yaml', {
267
- bindings: { [Bindings.NatsIO]: natsInstance }
268
- });
117
+ tools: # This is the native config of the npm driver (genai, openai) for tools
118
+ - name: bookRoomTool
119
+ description: Book a room at a specific hotel.
120
+ parameters: # JSON Schema for tool parameters
121
+ type: object
122
+ properties:
123
+ hotelName: { type: string, description: "The name of the hotel." }
124
+ roomName: { type: string, description: "The name of the room." }
125
+ # ... other parameters
126
+ required: [hotelName, roomName]
127
+
128
+ discoverySchemas: # Capabilities this agent wants to discover from others
129
+ - name: pricing_query
130
+ description: Get pricing information for a room.
131
+ # parameters schema for the discovery...
269
132
  ```
270
133
 
271
- ### Tool Binding
272
-
273
- Tools allow agents to perform actions in the real world. Each tool:
134
+ ### Dynamic Implementation (JavaScript)
274
135
 
275
- - Has a schema that defines its interface (name, description, parameters)
276
- - Has an implementation bound to it at runtime
136
+ Load YAML definitions and bind tool implementations dynamically:
277
137
 
278
138
  ```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
- });
295
- ```
139
+ import { AgentLoaderFile, NatsIO, Bindings } from "agentnet";
296
140
 
297
- ### Transport Mechanisms
141
+ // NatsIO instance (example)
142
+ const natsInstance = NatsIO({ servers: ['nats://localhost:4222'] });
298
143
 
299
- The framework supports different transport mechanisms for agent communication:
144
+ // Load agents from YAML
145
+ const agents = await AgentLoaderFile('./agents.yaml', {
146
+ bindings: { [Bindings.NatsIO]: natsInstance } // Provide necessary bindings
147
+ });
300
148
 
301
- #### Direct Communication
149
+ const bookingAgent = agents.bookingAgent;
302
150
 
303
- Agents can be queried directly in the same process:
151
+ // Bind tool implementations
152
+ bookingAgent.tools.bookRoomTool.bind(async (state, input) => {
153
+ console.log(`Booking room: ${input.roomName} at ${input.hotelName}`);
154
+ // ... actual booking logic ...
155
+ return { confirmation: `Room ${input.roomName} booked at ${input.hotelName}.` };
156
+ });
304
157
 
305
- ```javascript
306
- const compiledAgent = await myAgent.compile();
307
- const response = await compiledAgent.query("Hello, agent!");
158
+ // Compile the agent to make it ready
159
+ await bookingAgent.compile();
308
160
  ```
309
161
 
310
- #### NATS-based Communication
162
+ ## State Management
163
+
164
+ Agentnet provides robust session management for maintaining state across conversations and agent interactions.
311
165
 
312
- Agents can communicate through NATS for distributed deployments:
166
+ 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.
313
167
 
314
168
  ```javascript
315
- // Initialize NATS transport
316
- const natsIO = NatsIO({ servers: ['nats://localhost:4222'] });
169
+ // Example: Querying an agent with session data
170
+ import { Message, AgentClient, NatsIO } from "agentnet"; // Added AgentClient and NatsIO for context
317
171
 
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" });
172
+ const client = AgentClient(); // Assuming you have an AgentClient instance
173
+ const natsIO = NatsIO({ servers: ['nats://localhost:4222'] }); // Example NatsIO
323
174
 
324
- // Query an agent through NATS
325
- const client = AgentClient();
326
- const response = await client.queryIo(natsIO, 'distributedAgent', "Hello!");
327
- ```
175
+ // Example: Loading and compiling agents
176
+ const agents = await AgentLoaderFile('./hotel-agents.yaml', {
177
+ bindings: {
178
+ [Bindings.NatsIO]: natsIO,
179
+ [Bindings.Postgres]: PostgresStore({ url: "postgres://user:pass@host:port/db" })
180
+ }
181
+ });
328
182
 
329
- ### Agent Auto-Discovery
183
+ // Access individual agents
184
+ const bookingAgent = agents.bookingAgent;
185
+ const pricingAgent = agents.pricingAgent;
330
186
 
331
- Agents can discover each other's capabilities at runtime through a discovery protocol:
187
+ // Bind tool implementations
188
+ bookingAgent.tools.bookRoomTool.bind(async (state, input) => {
189
+ // Implementation for booking tool
190
+ return { success: true, bookingId: "BK12345" };
191
+ });
332
192
 
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
193
+ pricingAgent.tools.getPricingTool.bind(async (state, input) => {
194
+ // Implementation for pricing tool
195
+ state._privatePricingVariable = { done: true }
196
+ return { price: 200, currency: "EUR", perNight: true };
197
+ });
336
198
 
337
- ```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));
199
+ // Compile all agents to make them ready
200
+ console.log("Compiling agents...");
201
+ await Promise.all(Object.values(agents).map(agent => agent.compile()));
341
202
 
342
- // Now agents can communicate with each other
343
- ```
203
+ // Wait for agent discovery to complete
204
+ console.log("Waiting for agent discovery...");
205
+ await new Promise(resolve => setTimeout(resolve, 2000));
344
206
 
345
- ### Agent Handoffs
207
+ console.log("Agent network ready!");
346
208
 
347
- Agents can delegate tasks to other agents with the right capabilities:
348
209
 
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
210
+ const message = new Message({
211
+ content: "What rooms do you have available for next weekend?",
212
+ session: {
213
+ id: "session_123_user_abc", // Unique session identifier
214
+ userPreferences: { roomType: "suite", view: "sea" },
215
+ _internalCounter: 0 // Private agent variable, not propagated
216
+ }
217
+ });
353
218
 
354
- This happens transparently from the user's perspective, creating a seamless experience.
219
+ // Query the agent using the client
220
+ console.log("Sending query to the entrypoint agent...");
221
+ const response = await client.queryIo(natsIO, 'entrypointAgent', message);
355
222
 
356
- ## Advanced Usage
223
+ // Process the response
224
+ console.log("Agent Response:", response.getContent());
357
225
 
358
- ### Events and Hooks
226
+ // Access the updated session data (private variables like _internalCounter are excluded)
227
+ const updatedSession = response.getSession();
228
+ console.log("Updated Session:", updatedSession);
359
229
 
360
- Customize agent behavior with event hooks:
230
+ ```
361
231
 
362
- ```javascript
363
- agent.prompt((state, input) => {
364
- // Customize input before it reaches the LLM
365
- return `[Processed] ${input}`;
366
- });
232
+ * **Session ID**: A unique `id` in the session object is used for loading/saving state and tracking conversation history.
233
+ * **State Propagation**:
234
+ * Regular session variables (e.g., `userPreferences`) are propagated between agents during handoffs.
235
+ * 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.
236
+ * **Stores Configuration**: Configure persistent storage for session state.
237
+ ```javascript
238
+ import { AgentLoaderFile, PostgresStore, RedisStore, MemoryStore, Bindings } from "agentnet";
367
239
 
368
- agent.response((state, conversation, result) => {
369
- // Process the result before returning to the user
370
- return `Agent says: ${result}`;
371
- });
372
- ```
240
+ const agents = await AgentLoaderFile('./agents.yaml', {
241
+ bindings: {
242
+ // [Bindings.NatsIO]: natsInstance, // If using NATS
243
+ [Bindings.Postgres]: PostgresStore({ url: "postgres://user:pass@host:port/db" }),
244
+ // [Bindings.Redis]: RedisStore({ url: "redis://host:port" }),
245
+ // [Bindings.Memory]: MemoryStore() // For testing or simple cases
246
+ }
247
+ });
248
+ ```
249
+ Agent definitions in YAML can specify which store to use if multiple are bound.
373
250
 
374
- ### Multi-Agent Systems
251
+ ## Network Topologies & Filtering
375
252
 
376
- Create autonomous networks of specialized agents that collaborate without human intervention:
253
+ Agentnet enables complex multi-agent systems where specialized agents collaborate.
377
254
 
378
- ```javascript
379
- // Create specialized agents
380
- const weatherAgent = Agent()
381
- .setMetadata({ name: "weatherAgent" })
382
- .addToolSchema(weatherToolSchema);
255
+ Agentnet supports complex network topologies where agents can discover and communicate with each other based on their capabilities and network configurations.
383
256
 
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
- ```
257
+ ![Agent Network Topology](assets/network01.png)
404
258
 
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
259
+ The diagram above illustrates how agents can be organized in a network, with different communication patterns and discovery mechanisms.
410
260
 
411
- ### Session State Management
412
261
 
413
- The SmartAgent framework provides robust session management for maintaining state across conversations and agent interactions:
262
+ ### Agent Auto-Discovery & Handoffs
263
+ 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.
414
264
 
415
- ```javascript
416
- // Creating a message with session information
417
- const message = new Message({
418
- content: "What rooms do you have available?",
419
- session: {
420
- id: "67a71e42-a7d8-1db2-ad17-64e1c8546b21", // Reserved system ID
421
- propertySetId: "123", // Custom session data
422
- userPreferences: { roomType: "suite" } // Custom session data
423
- }
424
- });
265
+ ### Network Filtering
266
+ Control inter-agent communication using `acceptedNetworks` in the agent's I/O configuration. This uses wildcard patterns for fine-grained control:
425
267
 
426
- // Query the agent with session context
427
- const result = await agentInstance.query(message);
268
+ ```yaml
269
+ # In agent_definition.yaml
270
+ # ...
271
+ spec:
272
+ io:
273
+ - type: NatsIO
274
+ bindings:
275
+ discoveryTopic: "smartness.discovery"
276
+ acceptedNetworks:
277
+ - "smartchat.*" # Accept all services in 'smartchat' namespace
278
+ - "finance.pricing" # Accept only 'pricing' service in 'finance' namespace
279
+ - "*.analytics" # Accept 'analytics' services from any namespace
280
+ - "*.*" # Accept all networks (use with caution)
281
+ # ...
428
282
  ```
283
+ 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.
429
284
 
430
- #### Session ID
285
+ 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.
431
286
 
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
287
 
437
- #### State Propagation
288
+ ## Available LLMs, Stores, and IO
438
289
 
439
- Session variables have different scopes:
290
+ * **LLM Providers**:
291
+ * **Gemini**: Google's Gemini models.
292
+ * **OpenAI GPT**: OpenAI's GPT models.
293
+ * Easily extensible to other providers.
294
+ * **Stores**:
295
+ * **PostgresStore**: Persist session state in PostgreSQL.
296
+ * **RedisStore**: Use Redis for session state.
297
+ * **MemoryStore**: In-memory store, useful for testing or simple applications.
298
+ * **IO (Transport)**:
299
+ * **NatsIO**: For asynchronous, distributed agent communication using NATS.
300
+ * **Direct Call**: Agents can be invoked directly within the same process.
440
301
 
441
- 1. **Regular variables** (without underscore prefix) are propagated between agents during handoffs, ensuring continuity of context across the agent system.
302
+ ## Direct Access to Agent Fluent Interface
442
303
 
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
- ```
304
+ 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.
448
305
 
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.
306
+ ```javascript
307
+ import { Agent, Gemini, NatsIO } from "agentnet";
450
308
 
451
- #### Stores Configuration
309
+ const natsIO = NatsIO({ servers: ['nats://localhost:4222'] }); // Example
452
310
 
453
- SmartAgent supports different storage backends for persisting session state:
311
+ const travelAgent = Agent()
312
+ .setMetadata({
313
+ name: "travelAgent",
314
+ namespace: "trips",
315
+ description: "Helps plan travels"
316
+ })
317
+ .withLLM(Gemini, {
318
+ model: "gemini-pro",
319
+ systemInstruction: "You are a travel planning assistant."
320
+ })
321
+ .addIO(natsIO, { // Configure NATS IO
322
+ network: "trips.travelAgent",
323
+ bindings: {
324
+ discoveryTopic: "global.discovery",
325
+ acceptedNetworks: ["trips.*", "common.weather"]
326
+ }
327
+ })
328
+ .addToolSchema({
329
+ name: "findFlightsTool",
330
+ description: "Find flights for given criteria.",
331
+ parameters: { /* ... schema ... */ }
332
+ })
333
+ .addDiscoverySchema({ // What this agent wants to discover
334
+ name: "weather_service_lookup",
335
+ description: "Finds an agent that can provide weather information.",
336
+ parameters: { /* ... schema ... */ }
337
+ });
454
338
 
455
- ```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
- }
339
+ // Bind implementation for its own tool
340
+ travelAgent.tools.findFlightsTool.bind(async (state, input) => {
341
+ // ... logic to find flights ...
342
+ return { flights: [/* ... flight data ... */] };
463
343
  });
464
344
 
465
- // Or with an in-memory store for testing
466
- const agents = await AgentLoaderJSON(agentDefinition, {
467
- bindings: {
468
- [Bindings.Memory]: MemoryStore()
469
- }
345
+ // Optional: Add prompt/response hooks
346
+ travelAgent.prompt((state, input) => {
347
+ console.log(`Travel agent received prompt: ${input}`);
348
+ return `Plan this trip: ${input}`; // Modify input to LLM
349
+ });
350
+
351
+ travelAgent.response((state, conversation, result) => {
352
+ console.log(`Travel agent sending response: ${result}`);
353
+ return `Your travel plan: ${result}`; // Modify output from LLM
470
354
  });
471
- ```
472
355
 
473
- #### Session Life Cycle
356
+ // Compile the agent
357
+ const compiledTravelAgent = await travelAgent.compile();
474
358
 
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
359
+ // The agent will now connect to NATS, announce itself, and start discovering others.
360
+ // It can also be queried directly if not solely NATS-based or for testing:
361
+ // const response = await compiledTravelAgent.query("Find me a flight to Bali.");
362
+ // console.log(response.getContent());
363
+ ```
480
364
 
481
- This mechanism allows agents to maintain context across multiple interactions while keeping appropriate boundaries between agent-specific and shared data.
365
+ ## Examples
482
366
 
483
- ## Installation
367
+ * **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
368
 
485
- ```bash
486
- npm install smartagent
487
- ```
369
+ * **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.
370
+
371
+ * **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
372
 
373
+ * **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.