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 +265 -380
- package/_OLD_README.md +554 -0
- package/assets/network01.png +0 -0
- package/examples/customer-support/README.md +66 -0
- package/examples/customer-support/agents.yaml +457 -0
- package/examples/customer-support/index.js +408 -0
- package/examples/event-planner/README.md +69 -0
- package/examples/event-planner/agents.yaml +318 -0
- package/examples/event-planner/index.js +547 -0
- package/{src/examples → examples/smartness}/agents-smartness.yaml +8 -17
- package/{src/examples/def3.js → examples/smartness/index.js} +9 -9
- package/package.json +2 -2
- package/src/agent/agent.js +9 -1
- package/src/agent/runtime.js +2 -2
- package/src/agent/runtimes/nats.js +154 -27
- package/src/llm/gemini.js +7 -2
- package/src/llm/gpt.js +6 -1
- package/src/store/store.js +82 -48
- package/src/examples/agents.yaml +0 -394
- package/src/examples/def.js +0 -74
- package/src/examples/def2.js +0 -65
- /package/{src/examples → examples/simple}/simple.js +0 -0
package/README.md
CHANGED
|
@@ -1,215 +1,52 @@
|
|
|
1
|
-
#
|
|
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
|
-
- [
|
|
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
|
-
- [
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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
|
-
|
|
16
|
+
## Introduction
|
|
111
17
|
|
|
112
|
-
|
|
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
|
-
|
|
119
|
-
|
|
120
|
-
|
|
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
|
-
|
|
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
|
|
172
|
-
|
|
173
|
-
|
|
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
|
-
|
|
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
|
-
|
|
188
|
-
|
|
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
|
-
|
|
44
|
+
## Super Simple Example (Quick Start)
|
|
197
45
|
|
|
198
|
-
|
|
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
|
|
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
|
-
//
|
|
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
|
-
|
|
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
|
-
##
|
|
244
|
-
|
|
245
|
-
### Agents
|
|
81
|
+
## Declarative Agent Definitions (YAML & JavaScript)
|
|
246
82
|
|
|
247
|
-
|
|
83
|
+
Agentnet shines with its ability to separate static agent definitions (YAML) from dynamic runtime behavior (JavaScript).
|
|
248
84
|
|
|
249
|
-
|
|
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
|
-
|
|
87
|
+
Define agent metadata, LLM configurations, transport, tools, and discovery schemas in YAML:
|
|
255
88
|
|
|
256
|
-
|
|
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
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
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
|
-
|
|
266
|
-
|
|
267
|
-
|
|
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
|
-
###
|
|
272
|
-
|
|
273
|
-
Tools allow agents to perform actions in the real world. Each tool:
|
|
134
|
+
### Dynamic Implementation (JavaScript)
|
|
274
135
|
|
|
275
|
-
|
|
276
|
-
- Has an implementation bound to it at runtime
|
|
136
|
+
Load YAML definitions and bind tool implementations dynamically:
|
|
277
137
|
|
|
278
138
|
```javascript
|
|
279
|
-
|
|
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
|
-
|
|
141
|
+
// NatsIO instance (example)
|
|
142
|
+
const natsInstance = NatsIO({ servers: ['nats://localhost:4222'] });
|
|
298
143
|
|
|
299
|
-
|
|
144
|
+
// Load agents from YAML
|
|
145
|
+
const agents = await AgentLoaderFile('./agents.yaml', {
|
|
146
|
+
bindings: { [Bindings.NatsIO]: natsInstance } // Provide necessary bindings
|
|
147
|
+
});
|
|
300
148
|
|
|
301
|
-
|
|
149
|
+
const bookingAgent = agents.bookingAgent;
|
|
302
150
|
|
|
303
|
-
|
|
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
|
-
|
|
306
|
-
|
|
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
|
-
|
|
162
|
+
## State Management
|
|
163
|
+
|
|
164
|
+
Agentnet provides robust session management for maintaining state across conversations and agent interactions.
|
|
311
165
|
|
|
312
|
-
|
|
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
|
-
//
|
|
316
|
-
|
|
169
|
+
// Example: Querying an agent with session data
|
|
170
|
+
import { Message, AgentClient, NatsIO } from "agentnet"; // Added AgentClient and NatsIO for context
|
|
317
171
|
|
|
318
|
-
//
|
|
319
|
-
const
|
|
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
|
-
//
|
|
325
|
-
const
|
|
326
|
-
|
|
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
|
-
|
|
183
|
+
// Access individual agents
|
|
184
|
+
const bookingAgent = agents.bookingAgent;
|
|
185
|
+
const pricingAgent = agents.pricingAgent;
|
|
330
186
|
|
|
331
|
-
|
|
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
|
-
|
|
334
|
-
|
|
335
|
-
|
|
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
|
-
|
|
338
|
-
|
|
339
|
-
|
|
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
|
-
//
|
|
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
|
-
|
|
207
|
+
console.log("Agent network ready!");
|
|
346
208
|
|
|
347
|
-
Agents can delegate tasks to other agents with the right capabilities:
|
|
348
209
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
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
|
-
|
|
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
|
-
|
|
223
|
+
// Process the response
|
|
224
|
+
console.log("Agent Response:", response.getContent());
|
|
357
225
|
|
|
358
|
-
|
|
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
|
-
|
|
230
|
+
```
|
|
361
231
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
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
|
-
|
|
369
|
-
|
|
370
|
-
|
|
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
|
-
|
|
251
|
+
## Network Topologies & Filtering
|
|
375
252
|
|
|
376
|
-
|
|
253
|
+
Agentnet enables complex multi-agent systems where specialized agents collaborate.
|
|
377
254
|
|
|
378
|
-
|
|
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
|
-
|
|
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
|
+

|
|
404
258
|
|
|
405
|
-
|
|
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
|
-
|
|
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
|
-
|
|
416
|
-
|
|
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
|
-
|
|
427
|
-
|
|
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
|
-
|
|
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
|
-
|
|
288
|
+
## Available LLMs, Stores, and IO
|
|
438
289
|
|
|
439
|
-
|
|
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
|
-
|
|
302
|
+
## Direct Access to Agent Fluent Interface
|
|
442
303
|
|
|
443
|
-
|
|
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
|
-
|
|
306
|
+
```javascript
|
|
307
|
+
import { Agent, Gemini, NatsIO } from "agentnet";
|
|
450
308
|
|
|
451
|
-
|
|
309
|
+
const natsIO = NatsIO({ servers: ['nats://localhost:4222'] }); // Example
|
|
452
310
|
|
|
453
|
-
|
|
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
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
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
|
-
//
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
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
|
-
|
|
356
|
+
// Compile the agent
|
|
357
|
+
const compiledTravelAgent = await travelAgent.compile();
|
|
474
358
|
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
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
|
-
|
|
365
|
+
## Examples
|
|
482
366
|
|
|
483
|
-
|
|
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
|
-
|
|
486
|
-
|
|
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.
|