@hazeljs/agent 0.7.9 → 0.8.1
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/.eslintrc.js +4 -0
- package/IMPLEMENTATION_SUMMARY.md +36 -11
- package/PERSISTENCE.md +6 -0
- package/PRISMA_INTEGRATION.md +10 -5
- package/PRODUCTION_READINESS.md +37 -0
- package/QUICKSTART.md +12 -8
- package/README.md +72 -57
- package/STATE_VS_MEMORY.md +29 -12
- package/benchmarks/performance.benchmark.ts +1 -5
- package/coverage/clover.xml +616 -601
- package/coverage/lcov-report/index.html +33 -33
- package/coverage/lcov.info +957 -927
- package/dist/agent.module.js +2 -2
- package/dist/agent.module.js.map +1 -1
- package/dist/decorators/approval.decorator.d.ts +14 -0
- package/dist/decorators/approval.decorator.d.ts.map +1 -0
- package/dist/decorators/approval.decorator.js +20 -0
- package/dist/decorators/approval.decorator.js.map +1 -0
- package/dist/evaluation/agent-eval.d.ts +17 -0
- package/dist/evaluation/agent-eval.d.ts.map +1 -0
- package/dist/evaluation/agent-eval.js +18 -0
- package/dist/evaluation/agent-eval.js.map +1 -0
- package/dist/executor/agent.executor.d.ts +2 -0
- package/dist/executor/agent.executor.d.ts.map +1 -1
- package/dist/executor/agent.executor.js +4 -0
- package/dist/executor/agent.executor.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/runtime/agent.runtime.d.ts.map +1 -1
- package/dist/runtime/agent.runtime.js +1 -2
- package/dist/runtime/agent.runtime.js.map +1 -1
- package/dist/state/agent.state.d.ts.map +1 -1
- package/dist/state/agent.state.js +8 -7
- package/dist/state/agent.state.js.map +1 -1
- package/dist/state/database-state.manager.d.ts.map +1 -1
- package/dist/state/database-state.manager.js +8 -7
- package/dist/state/database-state.manager.js.map +1 -1
- package/dist/state/redis-state.manager.d.ts.map +1 -1
- package/dist/state/redis-state.manager.js +8 -7
- package/dist/state/redis-state.manager.js.map +1 -1
- package/dist/utils/circuit-breaker.d.ts +1 -1
- package/dist/utils/circuit-breaker.js +1 -1
- package/logs/combined.log +1 -1
- package/package.json +13 -7
- package/tsconfig.tsbuildinfo +1 -1
package/README.md
CHANGED
|
@@ -15,6 +15,7 @@ Part of the HazelJS AI-Native Backend Framework. Stateful, tool-using, memory-en
|
|
|
15
15
|
Built for **AI-native applications** - not just another agent framework. When you combine @hazeljs/agent with @hazeljs/core, @hazeljs/ai, and @hazeljs/rag, you get a complete stack for intelligent backends.
|
|
16
16
|
|
|
17
17
|
**Perfect for:**
|
|
18
|
+
|
|
18
19
|
- AI startups building production agent systems
|
|
19
20
|
- Teams creating customer support or automation agents
|
|
20
21
|
- Developers who want stateful, long-running workflows
|
|
@@ -67,10 +68,10 @@ export class SupportAgent {
|
|
|
67
68
|
|
|
68
69
|
@Tool({
|
|
69
70
|
description: 'Process a refund for an order',
|
|
70
|
-
requiresApproval: true,
|
|
71
|
+
requiresApproval: true, // requires human approval before execution
|
|
71
72
|
parameters: [
|
|
72
73
|
{ name: 'orderId', type: 'string', required: true },
|
|
73
|
-
{ name: 'amount',
|
|
74
|
+
{ name: 'amount', type: 'number', required: true },
|
|
74
75
|
],
|
|
75
76
|
})
|
|
76
77
|
async processRefund(input: { orderId: string; amount: number }) {
|
|
@@ -101,11 +102,11 @@ runtime.registerAgentInstance('support-agent', agent);
|
|
|
101
102
|
### 3. Execute
|
|
102
103
|
|
|
103
104
|
```typescript
|
|
104
|
-
const result = await runtime.execute(
|
|
105
|
-
'
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
);
|
|
105
|
+
const result = await runtime.execute('support-agent', 'I need to check my order #12345', {
|
|
106
|
+
sessionId: 'user-session-123',
|
|
107
|
+
userId: 'user-456',
|
|
108
|
+
enableMemory: true,
|
|
109
|
+
});
|
|
109
110
|
|
|
110
111
|
console.log(result.response);
|
|
111
112
|
console.log(`Completed in ${result.steps.length} steps`);
|
|
@@ -170,7 +171,10 @@ export class OrchestratorAgent {
|
|
|
170
171
|
|
|
171
172
|
@Agent({ name: 'ResearchAgent', systemPrompt: 'You are an expert researcher.' })
|
|
172
173
|
export class ResearchAgent {
|
|
173
|
-
@Tool({
|
|
174
|
+
@Tool({
|
|
175
|
+
description: 'Search the web',
|
|
176
|
+
parameters: [{ name: 'query', type: 'string', required: true }],
|
|
177
|
+
})
|
|
174
178
|
async searchWeb(input: { query: string }) {
|
|
175
179
|
return `Research findings for: ${input.query}`;
|
|
176
180
|
}
|
|
@@ -178,7 +182,10 @@ export class ResearchAgent {
|
|
|
178
182
|
|
|
179
183
|
@Agent({ name: 'WriterAgent', systemPrompt: 'You are a professional technical writer.' })
|
|
180
184
|
export class WriterAgent {
|
|
181
|
-
@Tool({
|
|
185
|
+
@Tool({
|
|
186
|
+
description: 'Format content as Markdown',
|
|
187
|
+
parameters: [{ name: 'raw', type: 'string', required: true }],
|
|
188
|
+
})
|
|
182
189
|
async formatMarkdown(input: { raw: string }) {
|
|
183
190
|
return `## Article\n\n${input.raw}`;
|
|
184
191
|
}
|
|
@@ -189,12 +196,15 @@ export class WriterAgent {
|
|
|
189
196
|
|
|
190
197
|
```typescript
|
|
191
198
|
const orchestrator = new OrchestratorAgent();
|
|
192
|
-
const researcher
|
|
193
|
-
const writer
|
|
199
|
+
const researcher = new ResearchAgent();
|
|
200
|
+
const writer = new WriterAgent();
|
|
194
201
|
|
|
195
|
-
[ResearchAgent, WriterAgent, OrchestratorAgent].forEach(A => runtime.registerAgent(A));
|
|
196
|
-
[
|
|
197
|
-
|
|
202
|
+
[ResearchAgent, WriterAgent, OrchestratorAgent].forEach((A) => runtime.registerAgent(A));
|
|
203
|
+
[
|
|
204
|
+
['OrchestratorAgent', orchestrator],
|
|
205
|
+
['ResearchAgent', researcher],
|
|
206
|
+
['WriterAgent', writer],
|
|
207
|
+
].forEach(([name, inst]) => runtime.registerAgentInstance(name as string, inst));
|
|
198
208
|
|
|
199
209
|
const result = await runtime.execute('OrchestratorAgent', 'Write a blog post about LLMs');
|
|
200
210
|
console.log(result.response);
|
|
@@ -227,7 +237,7 @@ const graph = runtime.createGraph('research-pipeline');
|
|
|
227
237
|
const pipeline = runtime
|
|
228
238
|
.createGraph('blog-pipeline')
|
|
229
239
|
.addNode('researcher', { type: 'agent', agentName: 'ResearchAgent' })
|
|
230
|
-
.addNode('writer',
|
|
240
|
+
.addNode('writer', { type: 'agent', agentName: 'WriterAgent' })
|
|
231
241
|
.addEdge('researcher', 'writer')
|
|
232
242
|
.addEdge('writer', END)
|
|
233
243
|
.setEntryPoint('researcher')
|
|
@@ -243,13 +253,11 @@ console.log(result.output);
|
|
|
243
253
|
const router = runtime
|
|
244
254
|
.createGraph('router')
|
|
245
255
|
.addNode('classifier', { type: 'agent', agentName: 'ClassifierAgent' })
|
|
246
|
-
.addNode('coder',
|
|
247
|
-
.addNode('writer',
|
|
256
|
+
.addNode('coder', { type: 'agent', agentName: 'CoderAgent' })
|
|
257
|
+
.addNode('writer', { type: 'agent', agentName: 'WriterAgent' })
|
|
248
258
|
.setEntryPoint('classifier')
|
|
249
|
-
.addConditionalEdge('classifier', (state) =>
|
|
250
|
-
|
|
251
|
-
)
|
|
252
|
-
.addEdge('coder', END)
|
|
259
|
+
.addConditionalEdge('classifier', (state) => (state.data?.type === 'code' ? 'coder' : 'writer'))
|
|
260
|
+
.addEdge('coder', END)
|
|
253
261
|
.addEdge('writer', END)
|
|
254
262
|
.compile();
|
|
255
263
|
|
|
@@ -265,19 +273,19 @@ async function splitTask(state: GraphState) {
|
|
|
265
273
|
|
|
266
274
|
async function mergeResults(state: GraphState) {
|
|
267
275
|
const results = state.data?.branchResults as ParallelBranchResult[];
|
|
268
|
-
return { ...state, output: results.map(r => r.output).join('\n---\n') };
|
|
276
|
+
return { ...state, output: results.map((r) => r.output).join('\n---\n') };
|
|
269
277
|
}
|
|
270
278
|
|
|
271
279
|
const parallel = runtime
|
|
272
280
|
.createGraph('parallel-research')
|
|
273
|
-
.addNode('splitter',
|
|
281
|
+
.addNode('splitter', { type: 'function', fn: splitTask })
|
|
274
282
|
.addNode('parallel-1', { type: 'parallel', branches: ['tech-researcher', 'market-researcher'] })
|
|
275
|
-
.addNode('tech-researcher',
|
|
283
|
+
.addNode('tech-researcher', { type: 'agent', agentName: 'TechResearchAgent' })
|
|
276
284
|
.addNode('market-researcher', { type: 'agent', agentName: 'MarketResearchAgent' })
|
|
277
|
-
.addNode('combiner',
|
|
278
|
-
.addEdge('splitter',
|
|
285
|
+
.addNode('combiner', { type: 'function', fn: mergeResults })
|
|
286
|
+
.addEdge('splitter', 'parallel-1')
|
|
279
287
|
.addEdge('parallel-1', 'combiner')
|
|
280
|
-
.addEdge('combiner',
|
|
288
|
+
.addEdge('combiner', END)
|
|
281
289
|
.setEntryPoint('splitter')
|
|
282
290
|
.compile();
|
|
283
291
|
|
|
@@ -308,7 +316,7 @@ interface AgentGraph {
|
|
|
308
316
|
interface CompiledGraph {
|
|
309
317
|
execute(input: string, options?: GraphExecutionOptions): Promise<GraphExecutionResult>;
|
|
310
318
|
stream(input: string, options?: GraphExecutionOptions): AsyncIterable<GraphStreamChunk>;
|
|
311
|
-
visualize(): string;
|
|
319
|
+
visualize(): string; // returns a Mermaid diagram string
|
|
312
320
|
}
|
|
313
321
|
```
|
|
314
322
|
|
|
@@ -346,26 +354,27 @@ const supervisor = runtime.createSupervisor({
|
|
|
346
354
|
},
|
|
347
355
|
});
|
|
348
356
|
|
|
349
|
-
const result = await supervisor.run(
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
);
|
|
357
|
+
const result = await supervisor.run('Build and document a REST API for a todo app', {
|
|
358
|
+
sessionId: 'proj-001',
|
|
359
|
+
});
|
|
353
360
|
|
|
354
361
|
console.log(result.response);
|
|
355
362
|
result.rounds.forEach((round, i) => {
|
|
356
|
-
console.log(
|
|
363
|
+
console.log(
|
|
364
|
+
`Round ${i + 1}: routed to ${round.worker} — ${round.workerResult.response.slice(0, 80)}`
|
|
365
|
+
);
|
|
357
366
|
});
|
|
358
367
|
```
|
|
359
368
|
|
|
360
369
|
**`SupervisorConfig`:**
|
|
361
370
|
|
|
362
|
-
| Field
|
|
363
|
-
|
|
364
|
-
| `name`
|
|
365
|
-
| `workers`
|
|
366
|
-
| `maxRounds` | number
|
|
367
|
-
| `llm`
|
|
368
|
-
| `sessionId` | string
|
|
371
|
+
| Field | Type | Default | Description |
|
|
372
|
+
| ----------- | ------------------------------------- | ------- | -------------------------------------------------- |
|
|
373
|
+
| `name` | string | — | Supervisor instance name |
|
|
374
|
+
| `workers` | string[] | — | Registered agent names available to the supervisor |
|
|
375
|
+
| `maxRounds` | number | 5 | Maximum routing iterations |
|
|
376
|
+
| `llm` | `(prompt: string) => Promise<string>` | — | LLM function for routing decisions |
|
|
377
|
+
| `sessionId` | string | auto | Session for memory continuity across rounds |
|
|
369
378
|
|
|
370
379
|
---
|
|
371
380
|
|
|
@@ -412,17 +421,17 @@ idle → thinking → using_tool → thinking → ... → completed
|
|
|
412
421
|
```typescript
|
|
413
422
|
import { AgentEventType } from '@hazeljs/agent';
|
|
414
423
|
|
|
415
|
-
runtime.on(AgentEventType.EXECUTION_STARTED,
|
|
416
|
-
runtime.on(AgentEventType.EXECUTION_COMPLETED, e => console.log('completed:',
|
|
417
|
-
runtime.on(AgentEventType.STEP_STARTED,
|
|
418
|
-
runtime.on(AgentEventType.TOOL_EXECUTION_STARTED,
|
|
419
|
-
runtime.on(AgentEventType.TOOL_APPROVAL_REQUESTED,
|
|
424
|
+
runtime.on(AgentEventType.EXECUTION_STARTED, (e) => console.log('started:', e.data));
|
|
425
|
+
runtime.on(AgentEventType.EXECUTION_COMPLETED, (e) => console.log('completed:', e.data));
|
|
426
|
+
runtime.on(AgentEventType.STEP_STARTED, (e) => console.log('step:', e.data));
|
|
427
|
+
runtime.on(AgentEventType.TOOL_EXECUTION_STARTED, (e) => console.log('tool:', e.data));
|
|
428
|
+
runtime.on(AgentEventType.TOOL_APPROVAL_REQUESTED, (e) => {
|
|
420
429
|
console.log('approval needed:', e.data);
|
|
421
430
|
runtime.approveToolExecution(e.data.requestId, 'admin');
|
|
422
431
|
});
|
|
423
432
|
|
|
424
433
|
// Catch-all
|
|
425
|
-
runtime.onAny(e => console.log(e.type, e.data));
|
|
434
|
+
runtime.onAny((e) => console.log(e.type, e.data));
|
|
426
435
|
```
|
|
427
436
|
|
|
428
437
|
---
|
|
@@ -436,7 +445,9 @@ import { RagModule } from '@hazeljs/rag';
|
|
|
436
445
|
|
|
437
446
|
@HazelModule({
|
|
438
447
|
imports: [
|
|
439
|
-
RagModule.forRoot({
|
|
448
|
+
RagModule.forRoot({
|
|
449
|
+
/* ... */
|
|
450
|
+
}),
|
|
440
451
|
AgentModule.forRoot({
|
|
441
452
|
runtime: { defaultMaxSteps: 10, enableObservability: true },
|
|
442
453
|
agents: [SupportAgent, ResearchAgent, WriterAgent, OrchestratorAgent],
|
|
@@ -467,11 +478,11 @@ Keep each agent focused on one domain. `@Delegate` lets the orchestrator combine
|
|
|
467
478
|
|
|
468
479
|
### Choose the right multi-agent pattern
|
|
469
480
|
|
|
470
|
-
| Pattern
|
|
471
|
-
|
|
472
|
-
| `@Delegate`
|
|
473
|
-
| `AgentGraph`
|
|
474
|
-
| `SupervisorAgent` | Task decomposition is dynamic; you want LLM-driven routing
|
|
481
|
+
| Pattern | Use when |
|
|
482
|
+
| ----------------- | ------------------------------------------------------------- |
|
|
483
|
+
| `@Delegate` | Two or three agents with a clear orchestrator / worker split |
|
|
484
|
+
| `AgentGraph` | Workflow is known at design time; conditional routing matters |
|
|
485
|
+
| `SupervisorAgent` | Task decomposition is dynamic; you want LLM-driven routing |
|
|
475
486
|
|
|
476
487
|
### Require approval for destructive actions
|
|
477
488
|
|
|
@@ -501,7 +512,11 @@ async callExternalAPI(input: { endpoint: string }) {
|
|
|
501
512
|
|
|
502
513
|
```typescript
|
|
503
514
|
class AgentRuntime {
|
|
504
|
-
execute(
|
|
515
|
+
execute(
|
|
516
|
+
agentName: string,
|
|
517
|
+
input: string,
|
|
518
|
+
options?: ExecuteOptions
|
|
519
|
+
): Promise<AgentExecutionResult>;
|
|
505
520
|
resume(executionId: string, input?: string): Promise<AgentExecutionResult>;
|
|
506
521
|
registerAgent(agentClass: new (...args: unknown[]) => unknown): void;
|
|
507
522
|
registerAgentInstance(name: string, instance: unknown): void;
|
|
@@ -516,10 +531,10 @@ class AgentRuntime {
|
|
|
516
531
|
|
|
517
532
|
### Decorators
|
|
518
533
|
|
|
519
|
-
| Decorator
|
|
520
|
-
|
|
521
|
-
| `@Agent(config)`
|
|
522
|
-
| `@Tool(config)`
|
|
534
|
+
| Decorator | Target | Description |
|
|
535
|
+
| ------------------- | ------ | ------------------------------------------------------------------------ |
|
|
536
|
+
| `@Agent(config)` | Class | Declares a class as an agent |
|
|
537
|
+
| `@Tool(config)` | Method | Exposes a method as an LLM-callable tool |
|
|
523
538
|
| `@Delegate(config)` | Method | Delegates a method to another agent (registers as `@Tool` automatically) |
|
|
524
539
|
|
|
525
540
|
### `GraphNodeConfig` types
|
package/STATE_VS_MEMORY.md
CHANGED
|
@@ -27,6 +27,7 @@ There are **two separate persistence layers** in the agent system that serve dif
|
|
|
27
27
|
**Purpose**: Track the **execution flow** and **state machine** of agent runs
|
|
28
28
|
|
|
29
29
|
**What it stores**:
|
|
30
|
+
|
|
30
31
|
- ✅ Execution ID and context
|
|
31
32
|
- ✅ Current state (IDLE, THINKING, WAITING_FOR_APPROVAL, etc.)
|
|
32
33
|
- ✅ Execution steps (what the agent did)
|
|
@@ -34,11 +35,13 @@ There are **two separate persistence layers** in the agent system that serve dif
|
|
|
34
35
|
- ✅ Execution metadata
|
|
35
36
|
- ✅ **Temporary** conversation history (during execution)
|
|
36
37
|
|
|
37
|
-
**Lifetime**:
|
|
38
|
+
**Lifetime**:
|
|
39
|
+
|
|
38
40
|
- **Short-lived** - typically minutes to hours
|
|
39
41
|
- Ephemeral - deleted after execution completes (or TTL expires)
|
|
40
42
|
|
|
41
43
|
**Use cases**:
|
|
44
|
+
|
|
42
45
|
- Resume paused executions
|
|
43
46
|
- Track execution progress
|
|
44
47
|
- Debug failed executions
|
|
@@ -46,11 +49,13 @@ There are **two separate persistence layers** in the agent system that serve dif
|
|
|
46
49
|
- State machine transitions
|
|
47
50
|
|
|
48
51
|
**Backends**:
|
|
52
|
+
|
|
49
53
|
- In-Memory (default)
|
|
50
54
|
- Redis (production)
|
|
51
55
|
- Database/Prisma (audit)
|
|
52
56
|
|
|
53
57
|
**Example**:
|
|
58
|
+
|
|
54
59
|
```typescript
|
|
55
60
|
// Agent State tracks: "Agent executed step 1, 2, 3, now waiting for approval"
|
|
56
61
|
{
|
|
@@ -69,6 +74,7 @@ There are **two separate persistence layers** in the agent system that serve dif
|
|
|
69
74
|
**Purpose**: Store **long-term knowledge** and **context** across sessions
|
|
70
75
|
|
|
71
76
|
**What it stores**:
|
|
77
|
+
|
|
72
78
|
- ✅ Conversation history (across all sessions)
|
|
73
79
|
- ✅ Entities (people, places, things mentioned)
|
|
74
80
|
- ✅ Facts (learned information)
|
|
@@ -76,11 +82,13 @@ There are **two separate persistence layers** in the agent system that serve dif
|
|
|
76
82
|
- ✅ Events (important occurrences)
|
|
77
83
|
|
|
78
84
|
**Lifetime**:
|
|
85
|
+
|
|
79
86
|
- **Long-lived** - days, weeks, months
|
|
80
87
|
- Persistent - survives agent restarts
|
|
81
88
|
- Cross-session - shared across multiple agent runs
|
|
82
89
|
|
|
83
90
|
**Use cases**:
|
|
91
|
+
|
|
84
92
|
- Build context for new conversations
|
|
85
93
|
- Remember entities across sessions
|
|
86
94
|
- Store learned facts
|
|
@@ -88,11 +96,13 @@ There are **two separate persistence layers** in the agent system that serve dif
|
|
|
88
96
|
- Semantic search of past conversations
|
|
89
97
|
|
|
90
98
|
**Backends**:
|
|
99
|
+
|
|
91
100
|
- BufferMemory (in-memory)
|
|
92
101
|
- VectorMemory (Pinecone, Weaviate, Qdrant, ChromaDB)
|
|
93
102
|
- HybridMemory (combination)
|
|
94
103
|
|
|
95
104
|
**Example**:
|
|
105
|
+
|
|
96
106
|
```typescript
|
|
97
107
|
// Memory stores: "User's name is John, likes coffee, mentioned Paris last week"
|
|
98
108
|
{
|
|
@@ -107,15 +117,15 @@ There are **two separate persistence layers** in the agent system that serve dif
|
|
|
107
117
|
|
|
108
118
|
## Key Differences
|
|
109
119
|
|
|
110
|
-
| Aspect
|
|
111
|
-
|
|
112
|
-
| **Purpose**
|
|
113
|
-
| **Lifetime**
|
|
114
|
-
| **Scope**
|
|
115
|
-
| **Data**
|
|
116
|
-
| **Query**
|
|
117
|
-
| **Backend**
|
|
118
|
-
| **When used** | During execution
|
|
120
|
+
| Aspect | Agent State | Memory (RAG) |
|
|
121
|
+
| ------------- | ----------------------- | ------------------------------ |
|
|
122
|
+
| **Purpose** | Execution flow tracking | Long-term knowledge |
|
|
123
|
+
| **Lifetime** | Minutes to hours | Days to months |
|
|
124
|
+
| **Scope** | Single execution | Cross-session |
|
|
125
|
+
| **Data** | Steps, state, metadata | Conversations, entities, facts |
|
|
126
|
+
| **Query** | By executionId | Semantic search, by sessionId |
|
|
127
|
+
| **Backend** | Redis/DB | Vector stores (Pinecone, etc.) |
|
|
128
|
+
| **When used** | During execution | Before/after execution |
|
|
119
129
|
|
|
120
130
|
## How They Work Together
|
|
121
131
|
|
|
@@ -179,12 +189,14 @@ await contextBuilder.persistToMemory(context);
|
|
|
179
189
|
**Both** store conversation history, but for different reasons:
|
|
180
190
|
|
|
181
191
|
### Agent State Conversation History
|
|
192
|
+
|
|
182
193
|
- **Purpose**: Track messages **during** execution
|
|
183
194
|
- **Scope**: Single execution only
|
|
184
195
|
- **Lifetime**: Until execution completes
|
|
185
196
|
- **Use**: Resume paused executions, debug current run
|
|
186
197
|
|
|
187
198
|
### Memory Conversation History
|
|
199
|
+
|
|
188
200
|
- **Purpose**: Build context for **future** conversations
|
|
189
201
|
- **Scope**: All sessions for a user/session
|
|
190
202
|
- **Lifetime**: Long-term (weeks/months)
|
|
@@ -193,6 +205,7 @@ await contextBuilder.persistToMemory(context);
|
|
|
193
205
|
## When to Use Which
|
|
194
206
|
|
|
195
207
|
### Use Agent State Persistence when:
|
|
208
|
+
|
|
196
209
|
- ✅ You need to resume paused executions
|
|
197
210
|
- ✅ You want to track execution progress
|
|
198
211
|
- ✅ You need to debug failed runs
|
|
@@ -200,6 +213,7 @@ await contextBuilder.persistToMemory(context);
|
|
|
200
213
|
- ✅ You need execution audit trails
|
|
201
214
|
|
|
202
215
|
### Use Memory Persistence when:
|
|
216
|
+
|
|
203
217
|
- ✅ You want agents to remember past conversations
|
|
204
218
|
- ✅ You need entity tracking across sessions
|
|
205
219
|
- ✅ You want to store learned facts
|
|
@@ -209,6 +223,7 @@ await contextBuilder.persistToMemory(context);
|
|
|
209
223
|
## Recommended Setup
|
|
210
224
|
|
|
211
225
|
### Development
|
|
226
|
+
|
|
212
227
|
```typescript
|
|
213
228
|
// In-memory for both (default)
|
|
214
229
|
const runtime = new AgentRuntime({
|
|
@@ -218,6 +233,7 @@ const runtime = new AgentRuntime({
|
|
|
218
233
|
```
|
|
219
234
|
|
|
220
235
|
### Production
|
|
236
|
+
|
|
221
237
|
```typescript
|
|
222
238
|
// Redis for agent state (fast, distributed)
|
|
223
239
|
// Vector store (Pinecone) for memory (semantic search)
|
|
@@ -226,8 +242,8 @@ const memoryStore = new VectorMemory(pineconeStore, embeddings);
|
|
|
226
242
|
const memoryManager = new MemoryManager(memoryStore);
|
|
227
243
|
|
|
228
244
|
const runtime = new AgentRuntime({
|
|
229
|
-
stateManager,
|
|
230
|
-
memoryManager,
|
|
245
|
+
stateManager, // ← Agent execution state
|
|
246
|
+
memoryManager, // ← Long-term memory
|
|
231
247
|
});
|
|
232
248
|
```
|
|
233
249
|
|
|
@@ -237,6 +253,7 @@ const runtime = new AgentRuntime({
|
|
|
237
253
|
- **Memory** = "What does the agent know from past conversations?"
|
|
238
254
|
|
|
239
255
|
They complement each other:
|
|
256
|
+
|
|
240
257
|
- **State** enables resumable, trackable executions
|
|
241
258
|
- **Memory** enables context-aware, continuous conversations
|
|
242
259
|
|
|
@@ -57,11 +57,7 @@ class PerformanceBenchmark {
|
|
|
57
57
|
* Format benchmark results
|
|
58
58
|
*/
|
|
59
59
|
formatResults(results: BenchmarkResult[]): string {
|
|
60
|
-
const lines: string[] = [
|
|
61
|
-
'Performance Benchmark Results',
|
|
62
|
-
'============================',
|
|
63
|
-
'',
|
|
64
|
-
];
|
|
60
|
+
const lines: string[] = ['Performance Benchmark Results', '============================', ''];
|
|
65
61
|
|
|
66
62
|
for (const result of results) {
|
|
67
63
|
lines.push(`${result.name}:`);
|