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 +317 -364
- 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/simple}/simple.js +2 -2
- package/{src/examples → examples/smartness}/agents-smartness.yaml +8 -17
- package/{src/examples/def3.js → examples/smartness/index.js} +9 -9
- package/jest.config.js +1 -0
- package/package.json +6 -3
- package/src/agent/agent-loader.js +75 -12
- package/src/agent/agent.js +13 -3
- package/src/agent/runtime.js +9 -6
- package/src/llm/base.js +131 -0
- package/src/llm/gemini.js +137 -117
- package/src/llm/gpt.js +131 -104
- package/src/store/store.js +82 -48
- package/src/tests/agent.test.js +350 -0
- package/src/tools/migrate-version.js +250 -0
- package/src/transport/README.md +123 -0
- package/src/transport/base.js +237 -0
- package/src/transport/index.js +89 -0
- package/src/transport/kafka.js +474 -0
- package/src/transport/nats.js +521 -0
- package/src/transport/rabbitmq.js +722 -0
- package/src/transport/redis.js +532 -0
- package/src/utils/version.js +212 -0
- package/src/agent/runtimes/nats.js +0 -379
- package/src/examples/agents.yaml +0 -394
- package/src/examples/def.js +0 -74
- package/src/examples/def2.js +0 -65
package/README.md
CHANGED
|
@@ -1,215 +1,79 @@
|
|
|
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
|
-
|
|
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
|
-
|
|
17
|
+
## Introduction
|
|
41
18
|
|
|
42
|
-
|
|
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
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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
|
-
|
|
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
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
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
|
-
|
|
139
|
-
// Post-process response from LLM
|
|
140
|
-
return `Booking confirmation: ${result}`;
|
|
141
|
-
});
|
|
39
|
+
## Installation
|
|
142
40
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
await pricingAgent.compile();
|
|
41
|
+
```bash
|
|
42
|
+
npm install agentnet
|
|
146
43
|
```
|
|
147
44
|
|
|
148
|
-
|
|
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
|
-
|
|
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
|
-
|
|
177
|
-
|
|
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
|
-
|
|
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
|
-
|
|
185
|
-
|
|
54
|
+
```javascript
|
|
55
|
+
// In your main file, before importing agentnet
|
|
56
|
+
import dotenv from 'dotenv';
|
|
57
|
+
dotenv.config();
|
|
186
58
|
|
|
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
|
-
);
|
|
59
|
+
// Now the API keys are available to agentnet
|
|
60
|
+
import { Agent, Gemini } from "agentnet";
|
|
194
61
|
```
|
|
195
62
|
|
|
196
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
73
|
+
Here's how you can quickly get an agent up and running:
|
|
210
74
|
|
|
211
75
|
```javascript
|
|
212
|
-
import { Agent, Gemini
|
|
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
|
-
//
|
|
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
|
-
|
|
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
|
-
##
|
|
108
|
+
## Declarative Agent Definitions (YAML & JavaScript)
|
|
244
109
|
|
|
245
|
-
|
|
110
|
+
Agentnet shines with its ability to separate static agent definitions (YAML) from dynamic runtime behavior (JavaScript).
|
|
246
111
|
|
|
247
|
-
|
|
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
|
-
|
|
114
|
+
Define agent metadata, LLM configurations, transport, tools, and discovery schemas in YAML:
|
|
255
115
|
|
|
256
|
-
|
|
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
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
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
|
-
|
|
266
|
-
|
|
267
|
-
|
|
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
|
-
###
|
|
161
|
+
### API Versioning
|
|
272
162
|
|
|
273
|
-
|
|
163
|
+
Agentnet supports API versioning to maintain backwards compatibility while evolving the platform:
|
|
274
164
|
|
|
275
|
-
|
|
276
|
-
|
|
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
|
-
|
|
169
|
+
Currently supported API versions:
|
|
298
170
|
|
|
299
|
-
|
|
171
|
+
- `agentnet/v1alpha1`: Current API version
|
|
300
172
|
|
|
301
|
-
|
|
173
|
+
When creating agent definitions, you should specify which API version you're targeting. This allows Agentnet to:
|
|
302
174
|
|
|
303
|
-
|
|
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
|
-
|
|
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
|
-
####
|
|
182
|
+
#### Version Migration Tool
|
|
311
183
|
|
|
312
|
-
|
|
184
|
+
Agentnet includes a command-line tool to help migrate your agent definitions to newer API versions:
|
|
313
185
|
|
|
314
|
-
```
|
|
315
|
-
|
|
316
|
-
|
|
186
|
+
```bash
|
|
187
|
+
# Migrate a YAML file to the latest version
|
|
188
|
+
node src/tools/migrate-version.js ./agents.yaml
|
|
317
189
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
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
|
-
|
|
325
|
-
|
|
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
|
-
|
|
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
|
-
|
|
202
|
+
### Dynamic Implementation (JavaScript)
|
|
332
203
|
|
|
333
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
343
|
-
|
|
209
|
+
// NatsIO instance (example)
|
|
210
|
+
const natsInstance = NatsIO({ servers: ['nats://localhost:4222'] });
|
|
344
211
|
|
|
345
|
-
|
|
212
|
+
// Load agents from YAML
|
|
213
|
+
const agents = await AgentLoaderFile('./agents.yaml', {
|
|
214
|
+
bindings: { [Bindings.NatsIO]: natsInstance } // Provide necessary bindings
|
|
215
|
+
});
|
|
346
216
|
|
|
347
|
-
|
|
217
|
+
const bookingAgent = agents.bookingAgent;
|
|
348
218
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
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
|
-
|
|
226
|
+
// Compile the agent to make it ready
|
|
227
|
+
await bookingAgent.compile();
|
|
228
|
+
```
|
|
355
229
|
|
|
356
|
-
##
|
|
230
|
+
## State Management
|
|
357
231
|
|
|
358
|
-
|
|
232
|
+
Agentnet provides robust session management for maintaining state across conversations and agent interactions.
|
|
359
233
|
|
|
360
|
-
|
|
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
|
|
364
|
-
|
|
365
|
-
|
|
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
|
-
|
|
369
|
-
|
|
370
|
-
|
|
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
|
-
|
|
251
|
+
// Access individual agents
|
|
252
|
+
const bookingAgent = agents.bookingAgent;
|
|
253
|
+
const pricingAgent = agents.pricingAgent;
|
|
375
254
|
|
|
376
|
-
|
|
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
|
-
|
|
379
|
-
//
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
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
|
-
|
|
385
|
-
|
|
386
|
-
|
|
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
|
-
|
|
406
|
-
|
|
407
|
-
|
|
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
|
-
|
|
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: "
|
|
421
|
-
|
|
422
|
-
|
|
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
|
|
427
|
-
|
|
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
|
-
|
|
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
|
+

|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
356
|
+
## Available LLMs, Stores, and IO
|
|
452
357
|
|
|
453
|
-
|
|
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
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
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
|
-
//
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
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
|
-
|
|
424
|
+
// Compile the agent
|
|
425
|
+
const compiledTravelAgent = await travelAgent.compile();
|
|
474
426
|
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
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
|
-
|
|
433
|
+
## Examples
|
|
482
434
|
|
|
483
|
-
|
|
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
|
-
|
|
486
|
-
|
|
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.
|