@agentforge/patterns 0.8.0 → 0.8.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/dist/index.cjs +57 -4
- package/dist/index.d.cts +117 -1
- package/dist/index.d.ts +117 -1
- package/dist/index.js +57 -4
- package/package.json +5 -5
package/dist/index.cjs
CHANGED
|
@@ -604,7 +604,8 @@ function createReActAgent(config, options) {
|
|
|
604
604
|
return ACTION_NODE;
|
|
605
605
|
};
|
|
606
606
|
const workflow = new import_langgraph.StateGraph(ReActState).addNode(REASONING_NODE, reasoningNode).addNode(ACTION_NODE, actionNode).addNode(OBSERVATION_NODE, observationNode).addEdge("__start__", REASONING_NODE).addConditionalEdges(REASONING_NODE, shouldContinue).addEdge(ACTION_NODE, OBSERVATION_NODE).addEdge(OBSERVATION_NODE, REASONING_NODE);
|
|
607
|
-
|
|
607
|
+
const checkpointerConfig = checkpointer === true ? { checkpointer: true } : checkpointer ? { checkpointer } : void 0;
|
|
608
|
+
return workflow.compile(checkpointerConfig);
|
|
608
609
|
}
|
|
609
610
|
|
|
610
611
|
// src/react/builder.ts
|
|
@@ -689,6 +690,43 @@ var ReActAgentBuilder = class {
|
|
|
689
690
|
this.options.nodeNames = nodeNames;
|
|
690
691
|
return this;
|
|
691
692
|
}
|
|
693
|
+
/**
|
|
694
|
+
* Set the checkpointer for state persistence (optional)
|
|
695
|
+
*
|
|
696
|
+
* Can be:
|
|
697
|
+
* - A BaseCheckpointSaver instance (e.g., MemorySaver) for standalone agents
|
|
698
|
+
* - `true` to use the parent graph's checkpointer with a separate namespace (for nested graphs)
|
|
699
|
+
*
|
|
700
|
+
* Required for human-in-the-loop workflows (askHuman tool) and conversation continuity.
|
|
701
|
+
*
|
|
702
|
+
* @param checkpointer - Checkpointer instance or `true` for nested graphs
|
|
703
|
+
*
|
|
704
|
+
* @example
|
|
705
|
+
* Standalone agent with its own checkpointer:
|
|
706
|
+
* ```typescript
|
|
707
|
+
* import { MemorySaver } from '@langchain/langgraph';
|
|
708
|
+
*
|
|
709
|
+
* const agent = new ReActAgentBuilder()
|
|
710
|
+
* .withModel(model)
|
|
711
|
+
* .withTools(tools)
|
|
712
|
+
* .withCheckpointer(new MemorySaver())
|
|
713
|
+
* .build();
|
|
714
|
+
* ```
|
|
715
|
+
*
|
|
716
|
+
* @example
|
|
717
|
+
* Nested agent using parent's checkpointer (for multi-agent systems):
|
|
718
|
+
* ```typescript
|
|
719
|
+
* const agent = new ReActAgentBuilder()
|
|
720
|
+
* .withModel(model)
|
|
721
|
+
* .withTools(tools)
|
|
722
|
+
* .withCheckpointer(true) // Use parent's checkpointer with separate namespace
|
|
723
|
+
* .build();
|
|
724
|
+
* ```
|
|
725
|
+
*/
|
|
726
|
+
withCheckpointer(checkpointer) {
|
|
727
|
+
this.config.checkpointer = checkpointer;
|
|
728
|
+
return this;
|
|
729
|
+
}
|
|
692
730
|
/**
|
|
693
731
|
* Build the ReAct agent
|
|
694
732
|
*
|
|
@@ -708,7 +746,8 @@ var ReActAgentBuilder = class {
|
|
|
708
746
|
systemPrompt: this.config.systemPrompt || DEFAULT_REACT_SYSTEM_PROMPT,
|
|
709
747
|
maxIterations: this.config.maxIterations ?? 10,
|
|
710
748
|
returnIntermediateSteps: this.config.returnIntermediateSteps ?? false,
|
|
711
|
-
stopCondition: this.config.stopCondition
|
|
749
|
+
stopCondition: this.config.stopCondition,
|
|
750
|
+
checkpointer: this.config.checkpointer
|
|
712
751
|
};
|
|
713
752
|
return createReActAgent(finalConfig, this.options);
|
|
714
753
|
}
|
|
@@ -2362,12 +2401,26 @@ function wrapReActAgent(workerId, agent, verbose = false) {
|
|
|
2362
2401
|
logger.debug("No active assignment found", { workerId });
|
|
2363
2402
|
return {};
|
|
2364
2403
|
}
|
|
2404
|
+
const workerThreadId = config?.configurable?.thread_id ? `${config.configurable.thread_id}:worker:${workerId}` : void 0;
|
|
2405
|
+
const workerConfig = workerThreadId ? {
|
|
2406
|
+
...config,
|
|
2407
|
+
configurable: {
|
|
2408
|
+
...config.configurable,
|
|
2409
|
+
thread_id: workerThreadId
|
|
2410
|
+
}
|
|
2411
|
+
} : config;
|
|
2412
|
+
logger.debug("Invoking ReAct agent with worker-specific config", {
|
|
2413
|
+
workerId,
|
|
2414
|
+
parentThreadId: config?.configurable?.thread_id,
|
|
2415
|
+
workerThreadId,
|
|
2416
|
+
hasConfig: !!workerConfig
|
|
2417
|
+
});
|
|
2365
2418
|
const result = await agent.invoke(
|
|
2366
2419
|
{
|
|
2367
2420
|
messages: [{ role: "user", content: task }]
|
|
2368
2421
|
},
|
|
2369
|
-
|
|
2370
|
-
//
|
|
2422
|
+
workerConfig
|
|
2423
|
+
// Worker-specific config with unique thread_id
|
|
2371
2424
|
);
|
|
2372
2425
|
const response = result.messages?.[result.messages.length - 1]?.content || "No response";
|
|
2373
2426
|
logger.debug("Received response from ReAct agent", {
|
package/dist/index.d.cts
CHANGED
|
@@ -172,7 +172,12 @@ interface ReActAgentConfig {
|
|
|
172
172
|
* Optional checkpointer for state persistence
|
|
173
173
|
* Required for human-in-the-loop workflows (askHuman tool), interrupts, and conversation continuity
|
|
174
174
|
*
|
|
175
|
+
* Can be:
|
|
176
|
+
* - A BaseCheckpointSaver instance (e.g., MemorySaver) for standalone agents
|
|
177
|
+
* - `true` to use the parent graph's checkpointer with a separate namespace (for nested graphs)
|
|
178
|
+
*
|
|
175
179
|
* @example
|
|
180
|
+
* Standalone agent with its own checkpointer:
|
|
176
181
|
* ```typescript
|
|
177
182
|
* import { MemorySaver } from '@langchain/langgraph';
|
|
178
183
|
*
|
|
@@ -183,8 +188,18 @@ interface ReActAgentConfig {
|
|
|
183
188
|
* checkpointer
|
|
184
189
|
* });
|
|
185
190
|
* ```
|
|
191
|
+
*
|
|
192
|
+
* @example
|
|
193
|
+
* Nested agent using parent's checkpointer (for multi-agent systems):
|
|
194
|
+
* ```typescript
|
|
195
|
+
* const agent = createReActAgent({
|
|
196
|
+
* model,
|
|
197
|
+
* tools,
|
|
198
|
+
* checkpointer: true // Use parent's checkpointer with separate namespace
|
|
199
|
+
* });
|
|
200
|
+
* ```
|
|
186
201
|
*/
|
|
187
|
-
checkpointer?: BaseCheckpointSaver;
|
|
202
|
+
checkpointer?: BaseCheckpointSaver | true;
|
|
188
203
|
/**
|
|
189
204
|
* Enable tool call deduplication to prevent calling the same tool with identical parameters multiple times
|
|
190
205
|
* @default true
|
|
@@ -287,6 +302,31 @@ declare const DEFAULT_REACT_SYSTEM_PROMPT = "You are a helpful assistant that us
|
|
|
287
302
|
* { configurable: { thread_id: 'conversation-123' } }
|
|
288
303
|
* );
|
|
289
304
|
* ```
|
|
305
|
+
*
|
|
306
|
+
* @example
|
|
307
|
+
* As a nested agent in a multi-agent system:
|
|
308
|
+
* ```typescript
|
|
309
|
+
* import { createReActAgent, createMultiAgentSystem } from '@agentforge/patterns';
|
|
310
|
+
* import { createAskHumanTool } from '@agentforge/tools';
|
|
311
|
+
* import { MemorySaver } from '@langchain/langgraph';
|
|
312
|
+
* import { ChatOpenAI } from '@langchain/openai';
|
|
313
|
+
*
|
|
314
|
+
* // Create worker agent with checkpointer: true to use parent's checkpointer
|
|
315
|
+
* const hrAgent = createReActAgent({
|
|
316
|
+
* model: new ChatOpenAI({ model: 'gpt-4' }),
|
|
317
|
+
* tools: [createAskHumanTool(), ...hrTools],
|
|
318
|
+
* checkpointer: true // Use parent's checkpointer with separate namespace
|
|
319
|
+
* });
|
|
320
|
+
*
|
|
321
|
+
* // Create multi-agent system with its own checkpointer
|
|
322
|
+
* const system = createMultiAgentSystem({
|
|
323
|
+
* workers: { hr: hrAgent },
|
|
324
|
+
* checkpointer: new MemorySaver() // Parent checkpointer
|
|
325
|
+
* });
|
|
326
|
+
*
|
|
327
|
+
* // When hrAgent calls askHuman, it will use a separate checkpoint namespace
|
|
328
|
+
* // Format: {parent_thread_id}:worker:hr
|
|
329
|
+
* ```
|
|
290
330
|
*/
|
|
291
331
|
declare function createReActAgent(config: ReActAgentConfig, options?: ReActBuilderOptions): CompiledStateGraph<any, any>;
|
|
292
332
|
|
|
@@ -372,6 +412,40 @@ declare class ReActAgentBuilder {
|
|
|
372
412
|
action?: string;
|
|
373
413
|
observation?: string;
|
|
374
414
|
}): this;
|
|
415
|
+
/**
|
|
416
|
+
* Set the checkpointer for state persistence (optional)
|
|
417
|
+
*
|
|
418
|
+
* Can be:
|
|
419
|
+
* - A BaseCheckpointSaver instance (e.g., MemorySaver) for standalone agents
|
|
420
|
+
* - `true` to use the parent graph's checkpointer with a separate namespace (for nested graphs)
|
|
421
|
+
*
|
|
422
|
+
* Required for human-in-the-loop workflows (askHuman tool) and conversation continuity.
|
|
423
|
+
*
|
|
424
|
+
* @param checkpointer - Checkpointer instance or `true` for nested graphs
|
|
425
|
+
*
|
|
426
|
+
* @example
|
|
427
|
+
* Standalone agent with its own checkpointer:
|
|
428
|
+
* ```typescript
|
|
429
|
+
* import { MemorySaver } from '@langchain/langgraph';
|
|
430
|
+
*
|
|
431
|
+
* const agent = new ReActAgentBuilder()
|
|
432
|
+
* .withModel(model)
|
|
433
|
+
* .withTools(tools)
|
|
434
|
+
* .withCheckpointer(new MemorySaver())
|
|
435
|
+
* .build();
|
|
436
|
+
* ```
|
|
437
|
+
*
|
|
438
|
+
* @example
|
|
439
|
+
* Nested agent using parent's checkpointer (for multi-agent systems):
|
|
440
|
+
* ```typescript
|
|
441
|
+
* const agent = new ReActAgentBuilder()
|
|
442
|
+
* .withModel(model)
|
|
443
|
+
* .withTools(tools)
|
|
444
|
+
* .withCheckpointer(true) // Use parent's checkpointer with separate namespace
|
|
445
|
+
* .build();
|
|
446
|
+
* ```
|
|
447
|
+
*/
|
|
448
|
+
withCheckpointer(checkpointer: any): this;
|
|
375
449
|
/**
|
|
376
450
|
* Build the ReAct agent
|
|
377
451
|
*
|
|
@@ -2593,7 +2667,20 @@ interface MultiAgentSystemConfig {
|
|
|
2593
2667
|
* Optional checkpointer for state persistence
|
|
2594
2668
|
* Required for human-in-the-loop workflows (askHuman tool), interrupts, and conversation continuity
|
|
2595
2669
|
*
|
|
2670
|
+
* **Worker Checkpoint Namespaces:**
|
|
2671
|
+
* When worker agents are configured with `checkpointer: true`, they automatically use
|
|
2672
|
+
* separate checkpoint namespaces to enable proper handling of nested graph interrupts.
|
|
2673
|
+
*
|
|
2674
|
+
* The namespace format is: `{parent_thread_id}:worker:{workerId}`
|
|
2675
|
+
*
|
|
2676
|
+
* For example, if the parent thread ID is `thread_abc123` and the worker ID is `hr`,
|
|
2677
|
+
* the worker's checkpoint namespace will be `thread_abc123:worker:hr`.
|
|
2678
|
+
*
|
|
2679
|
+
* This allows worker agents to use the `askHuman` tool without causing infinite loops,
|
|
2680
|
+
* as each worker's state is saved and resumed independently.
|
|
2681
|
+
*
|
|
2596
2682
|
* @example
|
|
2683
|
+
* Basic usage with checkpointer:
|
|
2597
2684
|
* ```typescript
|
|
2598
2685
|
* import { MemorySaver } from '@langchain/langgraph';
|
|
2599
2686
|
*
|
|
@@ -2604,6 +2691,35 @@ interface MultiAgentSystemConfig {
|
|
|
2604
2691
|
* checkpointer
|
|
2605
2692
|
* });
|
|
2606
2693
|
* ```
|
|
2694
|
+
*
|
|
2695
|
+
* @example
|
|
2696
|
+
* Worker agents with nested graph interrupts:
|
|
2697
|
+
* ```typescript
|
|
2698
|
+
* import { MemorySaver } from '@langchain/langgraph';
|
|
2699
|
+
* import { createReActAgent } from '@agentforge/patterns';
|
|
2700
|
+
* import { createAskHumanTool } from '@agentforge/tools';
|
|
2701
|
+
*
|
|
2702
|
+
* // Create worker agent with checkpointer: true
|
|
2703
|
+
* const hrAgent = createReActAgent({
|
|
2704
|
+
* model,
|
|
2705
|
+
* tools: [createAskHumanTool(), ...hrTools],
|
|
2706
|
+
* checkpointer: true // Use parent's checkpointer with separate namespace
|
|
2707
|
+
* });
|
|
2708
|
+
*
|
|
2709
|
+
* // Create multi-agent system with checkpointer
|
|
2710
|
+
* const system = createMultiAgentSystem({
|
|
2711
|
+
* supervisor: { strategy: 'skill-based', model },
|
|
2712
|
+
* workers: [{
|
|
2713
|
+
* id: 'hr',
|
|
2714
|
+
* capabilities: { skills: ['hr'], ... },
|
|
2715
|
+
* agent: hrAgent
|
|
2716
|
+
* }],
|
|
2717
|
+
* checkpointer: new MemorySaver()
|
|
2718
|
+
* });
|
|
2719
|
+
*
|
|
2720
|
+
* // When hrAgent calls askHuman, it will use checkpoint namespace:
|
|
2721
|
+
* // thread_abc123:worker:hr
|
|
2722
|
+
* ```
|
|
2607
2723
|
*/
|
|
2608
2724
|
checkpointer?: BaseCheckpointSaver;
|
|
2609
2725
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -172,7 +172,12 @@ interface ReActAgentConfig {
|
|
|
172
172
|
* Optional checkpointer for state persistence
|
|
173
173
|
* Required for human-in-the-loop workflows (askHuman tool), interrupts, and conversation continuity
|
|
174
174
|
*
|
|
175
|
+
* Can be:
|
|
176
|
+
* - A BaseCheckpointSaver instance (e.g., MemorySaver) for standalone agents
|
|
177
|
+
* - `true` to use the parent graph's checkpointer with a separate namespace (for nested graphs)
|
|
178
|
+
*
|
|
175
179
|
* @example
|
|
180
|
+
* Standalone agent with its own checkpointer:
|
|
176
181
|
* ```typescript
|
|
177
182
|
* import { MemorySaver } from '@langchain/langgraph';
|
|
178
183
|
*
|
|
@@ -183,8 +188,18 @@ interface ReActAgentConfig {
|
|
|
183
188
|
* checkpointer
|
|
184
189
|
* });
|
|
185
190
|
* ```
|
|
191
|
+
*
|
|
192
|
+
* @example
|
|
193
|
+
* Nested agent using parent's checkpointer (for multi-agent systems):
|
|
194
|
+
* ```typescript
|
|
195
|
+
* const agent = createReActAgent({
|
|
196
|
+
* model,
|
|
197
|
+
* tools,
|
|
198
|
+
* checkpointer: true // Use parent's checkpointer with separate namespace
|
|
199
|
+
* });
|
|
200
|
+
* ```
|
|
186
201
|
*/
|
|
187
|
-
checkpointer?: BaseCheckpointSaver;
|
|
202
|
+
checkpointer?: BaseCheckpointSaver | true;
|
|
188
203
|
/**
|
|
189
204
|
* Enable tool call deduplication to prevent calling the same tool with identical parameters multiple times
|
|
190
205
|
* @default true
|
|
@@ -287,6 +302,31 @@ declare const DEFAULT_REACT_SYSTEM_PROMPT = "You are a helpful assistant that us
|
|
|
287
302
|
* { configurable: { thread_id: 'conversation-123' } }
|
|
288
303
|
* );
|
|
289
304
|
* ```
|
|
305
|
+
*
|
|
306
|
+
* @example
|
|
307
|
+
* As a nested agent in a multi-agent system:
|
|
308
|
+
* ```typescript
|
|
309
|
+
* import { createReActAgent, createMultiAgentSystem } from '@agentforge/patterns';
|
|
310
|
+
* import { createAskHumanTool } from '@agentforge/tools';
|
|
311
|
+
* import { MemorySaver } from '@langchain/langgraph';
|
|
312
|
+
* import { ChatOpenAI } from '@langchain/openai';
|
|
313
|
+
*
|
|
314
|
+
* // Create worker agent with checkpointer: true to use parent's checkpointer
|
|
315
|
+
* const hrAgent = createReActAgent({
|
|
316
|
+
* model: new ChatOpenAI({ model: 'gpt-4' }),
|
|
317
|
+
* tools: [createAskHumanTool(), ...hrTools],
|
|
318
|
+
* checkpointer: true // Use parent's checkpointer with separate namespace
|
|
319
|
+
* });
|
|
320
|
+
*
|
|
321
|
+
* // Create multi-agent system with its own checkpointer
|
|
322
|
+
* const system = createMultiAgentSystem({
|
|
323
|
+
* workers: { hr: hrAgent },
|
|
324
|
+
* checkpointer: new MemorySaver() // Parent checkpointer
|
|
325
|
+
* });
|
|
326
|
+
*
|
|
327
|
+
* // When hrAgent calls askHuman, it will use a separate checkpoint namespace
|
|
328
|
+
* // Format: {parent_thread_id}:worker:hr
|
|
329
|
+
* ```
|
|
290
330
|
*/
|
|
291
331
|
declare function createReActAgent(config: ReActAgentConfig, options?: ReActBuilderOptions): CompiledStateGraph<any, any>;
|
|
292
332
|
|
|
@@ -372,6 +412,40 @@ declare class ReActAgentBuilder {
|
|
|
372
412
|
action?: string;
|
|
373
413
|
observation?: string;
|
|
374
414
|
}): this;
|
|
415
|
+
/**
|
|
416
|
+
* Set the checkpointer for state persistence (optional)
|
|
417
|
+
*
|
|
418
|
+
* Can be:
|
|
419
|
+
* - A BaseCheckpointSaver instance (e.g., MemorySaver) for standalone agents
|
|
420
|
+
* - `true` to use the parent graph's checkpointer with a separate namespace (for nested graphs)
|
|
421
|
+
*
|
|
422
|
+
* Required for human-in-the-loop workflows (askHuman tool) and conversation continuity.
|
|
423
|
+
*
|
|
424
|
+
* @param checkpointer - Checkpointer instance or `true` for nested graphs
|
|
425
|
+
*
|
|
426
|
+
* @example
|
|
427
|
+
* Standalone agent with its own checkpointer:
|
|
428
|
+
* ```typescript
|
|
429
|
+
* import { MemorySaver } from '@langchain/langgraph';
|
|
430
|
+
*
|
|
431
|
+
* const agent = new ReActAgentBuilder()
|
|
432
|
+
* .withModel(model)
|
|
433
|
+
* .withTools(tools)
|
|
434
|
+
* .withCheckpointer(new MemorySaver())
|
|
435
|
+
* .build();
|
|
436
|
+
* ```
|
|
437
|
+
*
|
|
438
|
+
* @example
|
|
439
|
+
* Nested agent using parent's checkpointer (for multi-agent systems):
|
|
440
|
+
* ```typescript
|
|
441
|
+
* const agent = new ReActAgentBuilder()
|
|
442
|
+
* .withModel(model)
|
|
443
|
+
* .withTools(tools)
|
|
444
|
+
* .withCheckpointer(true) // Use parent's checkpointer with separate namespace
|
|
445
|
+
* .build();
|
|
446
|
+
* ```
|
|
447
|
+
*/
|
|
448
|
+
withCheckpointer(checkpointer: any): this;
|
|
375
449
|
/**
|
|
376
450
|
* Build the ReAct agent
|
|
377
451
|
*
|
|
@@ -2593,7 +2667,20 @@ interface MultiAgentSystemConfig {
|
|
|
2593
2667
|
* Optional checkpointer for state persistence
|
|
2594
2668
|
* Required for human-in-the-loop workflows (askHuman tool), interrupts, and conversation continuity
|
|
2595
2669
|
*
|
|
2670
|
+
* **Worker Checkpoint Namespaces:**
|
|
2671
|
+
* When worker agents are configured with `checkpointer: true`, they automatically use
|
|
2672
|
+
* separate checkpoint namespaces to enable proper handling of nested graph interrupts.
|
|
2673
|
+
*
|
|
2674
|
+
* The namespace format is: `{parent_thread_id}:worker:{workerId}`
|
|
2675
|
+
*
|
|
2676
|
+
* For example, if the parent thread ID is `thread_abc123` and the worker ID is `hr`,
|
|
2677
|
+
* the worker's checkpoint namespace will be `thread_abc123:worker:hr`.
|
|
2678
|
+
*
|
|
2679
|
+
* This allows worker agents to use the `askHuman` tool without causing infinite loops,
|
|
2680
|
+
* as each worker's state is saved and resumed independently.
|
|
2681
|
+
*
|
|
2596
2682
|
* @example
|
|
2683
|
+
* Basic usage with checkpointer:
|
|
2597
2684
|
* ```typescript
|
|
2598
2685
|
* import { MemorySaver } from '@langchain/langgraph';
|
|
2599
2686
|
*
|
|
@@ -2604,6 +2691,35 @@ interface MultiAgentSystemConfig {
|
|
|
2604
2691
|
* checkpointer
|
|
2605
2692
|
* });
|
|
2606
2693
|
* ```
|
|
2694
|
+
*
|
|
2695
|
+
* @example
|
|
2696
|
+
* Worker agents with nested graph interrupts:
|
|
2697
|
+
* ```typescript
|
|
2698
|
+
* import { MemorySaver } from '@langchain/langgraph';
|
|
2699
|
+
* import { createReActAgent } from '@agentforge/patterns';
|
|
2700
|
+
* import { createAskHumanTool } from '@agentforge/tools';
|
|
2701
|
+
*
|
|
2702
|
+
* // Create worker agent with checkpointer: true
|
|
2703
|
+
* const hrAgent = createReActAgent({
|
|
2704
|
+
* model,
|
|
2705
|
+
* tools: [createAskHumanTool(), ...hrTools],
|
|
2706
|
+
* checkpointer: true // Use parent's checkpointer with separate namespace
|
|
2707
|
+
* });
|
|
2708
|
+
*
|
|
2709
|
+
* // Create multi-agent system with checkpointer
|
|
2710
|
+
* const system = createMultiAgentSystem({
|
|
2711
|
+
* supervisor: { strategy: 'skill-based', model },
|
|
2712
|
+
* workers: [{
|
|
2713
|
+
* id: 'hr',
|
|
2714
|
+
* capabilities: { skills: ['hr'], ... },
|
|
2715
|
+
* agent: hrAgent
|
|
2716
|
+
* }],
|
|
2717
|
+
* checkpointer: new MemorySaver()
|
|
2718
|
+
* });
|
|
2719
|
+
*
|
|
2720
|
+
* // When hrAgent calls askHuman, it will use checkpoint namespace:
|
|
2721
|
+
* // thread_abc123:worker:hr
|
|
2722
|
+
* ```
|
|
2607
2723
|
*/
|
|
2608
2724
|
checkpointer?: BaseCheckpointSaver;
|
|
2609
2725
|
}
|
package/dist/index.js
CHANGED
|
@@ -501,7 +501,8 @@ function createReActAgent(config, options) {
|
|
|
501
501
|
return ACTION_NODE;
|
|
502
502
|
};
|
|
503
503
|
const workflow = new StateGraph(ReActState).addNode(REASONING_NODE, reasoningNode).addNode(ACTION_NODE, actionNode).addNode(OBSERVATION_NODE, observationNode).addEdge("__start__", REASONING_NODE).addConditionalEdges(REASONING_NODE, shouldContinue).addEdge(ACTION_NODE, OBSERVATION_NODE).addEdge(OBSERVATION_NODE, REASONING_NODE);
|
|
504
|
-
|
|
504
|
+
const checkpointerConfig = checkpointer === true ? { checkpointer: true } : checkpointer ? { checkpointer } : void 0;
|
|
505
|
+
return workflow.compile(checkpointerConfig);
|
|
505
506
|
}
|
|
506
507
|
|
|
507
508
|
// src/react/builder.ts
|
|
@@ -586,6 +587,43 @@ var ReActAgentBuilder = class {
|
|
|
586
587
|
this.options.nodeNames = nodeNames;
|
|
587
588
|
return this;
|
|
588
589
|
}
|
|
590
|
+
/**
|
|
591
|
+
* Set the checkpointer for state persistence (optional)
|
|
592
|
+
*
|
|
593
|
+
* Can be:
|
|
594
|
+
* - A BaseCheckpointSaver instance (e.g., MemorySaver) for standalone agents
|
|
595
|
+
* - `true` to use the parent graph's checkpointer with a separate namespace (for nested graphs)
|
|
596
|
+
*
|
|
597
|
+
* Required for human-in-the-loop workflows (askHuman tool) and conversation continuity.
|
|
598
|
+
*
|
|
599
|
+
* @param checkpointer - Checkpointer instance or `true` for nested graphs
|
|
600
|
+
*
|
|
601
|
+
* @example
|
|
602
|
+
* Standalone agent with its own checkpointer:
|
|
603
|
+
* ```typescript
|
|
604
|
+
* import { MemorySaver } from '@langchain/langgraph';
|
|
605
|
+
*
|
|
606
|
+
* const agent = new ReActAgentBuilder()
|
|
607
|
+
* .withModel(model)
|
|
608
|
+
* .withTools(tools)
|
|
609
|
+
* .withCheckpointer(new MemorySaver())
|
|
610
|
+
* .build();
|
|
611
|
+
* ```
|
|
612
|
+
*
|
|
613
|
+
* @example
|
|
614
|
+
* Nested agent using parent's checkpointer (for multi-agent systems):
|
|
615
|
+
* ```typescript
|
|
616
|
+
* const agent = new ReActAgentBuilder()
|
|
617
|
+
* .withModel(model)
|
|
618
|
+
* .withTools(tools)
|
|
619
|
+
* .withCheckpointer(true) // Use parent's checkpointer with separate namespace
|
|
620
|
+
* .build();
|
|
621
|
+
* ```
|
|
622
|
+
*/
|
|
623
|
+
withCheckpointer(checkpointer) {
|
|
624
|
+
this.config.checkpointer = checkpointer;
|
|
625
|
+
return this;
|
|
626
|
+
}
|
|
589
627
|
/**
|
|
590
628
|
* Build the ReAct agent
|
|
591
629
|
*
|
|
@@ -605,7 +643,8 @@ var ReActAgentBuilder = class {
|
|
|
605
643
|
systemPrompt: this.config.systemPrompt || DEFAULT_REACT_SYSTEM_PROMPT,
|
|
606
644
|
maxIterations: this.config.maxIterations ?? 10,
|
|
607
645
|
returnIntermediateSteps: this.config.returnIntermediateSteps ?? false,
|
|
608
|
-
stopCondition: this.config.stopCondition
|
|
646
|
+
stopCondition: this.config.stopCondition,
|
|
647
|
+
checkpointer: this.config.checkpointer
|
|
609
648
|
};
|
|
610
649
|
return createReActAgent(finalConfig, this.options);
|
|
611
650
|
}
|
|
@@ -2259,12 +2298,26 @@ function wrapReActAgent(workerId, agent, verbose = false) {
|
|
|
2259
2298
|
logger.debug("No active assignment found", { workerId });
|
|
2260
2299
|
return {};
|
|
2261
2300
|
}
|
|
2301
|
+
const workerThreadId = config?.configurable?.thread_id ? `${config.configurable.thread_id}:worker:${workerId}` : void 0;
|
|
2302
|
+
const workerConfig = workerThreadId ? {
|
|
2303
|
+
...config,
|
|
2304
|
+
configurable: {
|
|
2305
|
+
...config.configurable,
|
|
2306
|
+
thread_id: workerThreadId
|
|
2307
|
+
}
|
|
2308
|
+
} : config;
|
|
2309
|
+
logger.debug("Invoking ReAct agent with worker-specific config", {
|
|
2310
|
+
workerId,
|
|
2311
|
+
parentThreadId: config?.configurable?.thread_id,
|
|
2312
|
+
workerThreadId,
|
|
2313
|
+
hasConfig: !!workerConfig
|
|
2314
|
+
});
|
|
2262
2315
|
const result = await agent.invoke(
|
|
2263
2316
|
{
|
|
2264
2317
|
messages: [{ role: "user", content: task }]
|
|
2265
2318
|
},
|
|
2266
|
-
|
|
2267
|
-
//
|
|
2319
|
+
workerConfig
|
|
2320
|
+
// Worker-specific config with unique thread_id
|
|
2268
2321
|
);
|
|
2269
2322
|
const response = result.messages?.[result.messages.length - 1]?.content || "No response";
|
|
2270
2323
|
logger.debug("Received response from ReAct agent", {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentforge/patterns",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.2",
|
|
4
4
|
"description": "Agent patterns (ReAct, Planner-Executor) for AgentForge framework",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -48,8 +48,8 @@
|
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
50
|
"@agentforge/core": "workspace:*",
|
|
51
|
-
"@langchain/core": "^1.1.
|
|
52
|
-
"@langchain/langgraph": "^1.
|
|
51
|
+
"@langchain/core": "^1.1.17",
|
|
52
|
+
"@langchain/langgraph": "^1.1.2",
|
|
53
53
|
"zod": "^3.23.8"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"vitest": "^1.6.1"
|
|
65
65
|
},
|
|
66
66
|
"peerDependencies": {
|
|
67
|
-
"@langchain/core": "^1.1.
|
|
68
|
-
"@langchain/langgraph": "^1.
|
|
67
|
+
"@langchain/core": "^1.1.17",
|
|
68
|
+
"@langchain/langgraph": "^1.1.2"
|
|
69
69
|
}
|
|
70
70
|
}
|