@librechat/agents 2.4.322 ā 3.0.0-rc10
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/cjs/agents/AgentContext.cjs +218 -0
- package/dist/cjs/agents/AgentContext.cjs.map +1 -0
- package/dist/cjs/common/enum.cjs +15 -5
- package/dist/cjs/common/enum.cjs.map +1 -1
- package/dist/cjs/events.cjs +10 -6
- package/dist/cjs/events.cjs.map +1 -1
- package/dist/cjs/graphs/Graph.cjs +309 -213
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/graphs/MultiAgentGraph.cjs +507 -0
- package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -0
- package/dist/cjs/llm/anthropic/index.cjs +54 -9
- package/dist/cjs/llm/anthropic/index.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/types.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/utils/message_inputs.cjs +52 -6
- package/dist/cjs/llm/anthropic/utils/message_inputs.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/utils/message_outputs.cjs +22 -2
- package/dist/cjs/llm/anthropic/utils/message_outputs.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/utils/tools.cjs +29 -0
- package/dist/cjs/llm/anthropic/utils/tools.cjs.map +1 -0
- package/dist/cjs/llm/google/index.cjs +144 -0
- package/dist/cjs/llm/google/index.cjs.map +1 -0
- package/dist/cjs/llm/google/utils/common.cjs +477 -0
- package/dist/cjs/llm/google/utils/common.cjs.map +1 -0
- package/dist/cjs/llm/ollama/index.cjs +67 -0
- package/dist/cjs/llm/ollama/index.cjs.map +1 -0
- package/dist/cjs/llm/ollama/utils.cjs +158 -0
- package/dist/cjs/llm/ollama/utils.cjs.map +1 -0
- package/dist/cjs/llm/openai/index.cjs +422 -3
- package/dist/cjs/llm/openai/index.cjs.map +1 -1
- package/dist/cjs/llm/openai/utils/index.cjs +672 -0
- package/dist/cjs/llm/openai/utils/index.cjs.map +1 -0
- package/dist/cjs/llm/providers.cjs +15 -15
- package/dist/cjs/llm/providers.cjs.map +1 -1
- package/dist/cjs/llm/text.cjs +14 -3
- package/dist/cjs/llm/text.cjs.map +1 -1
- package/dist/cjs/llm/vertexai/index.cjs +330 -0
- package/dist/cjs/llm/vertexai/index.cjs.map +1 -0
- package/dist/cjs/main.cjs +11 -0
- package/dist/cjs/main.cjs.map +1 -1
- package/dist/cjs/run.cjs +137 -85
- package/dist/cjs/run.cjs.map +1 -1
- package/dist/cjs/stream.cjs +86 -52
- package/dist/cjs/stream.cjs.map +1 -1
- package/dist/cjs/tools/ToolNode.cjs +10 -4
- package/dist/cjs/tools/ToolNode.cjs.map +1 -1
- package/dist/cjs/tools/handlers.cjs +119 -13
- package/dist/cjs/tools/handlers.cjs.map +1 -1
- package/dist/cjs/tools/search/anthropic.cjs +40 -0
- package/dist/cjs/tools/search/anthropic.cjs.map +1 -0
- package/dist/cjs/tools/search/firecrawl.cjs +55 -9
- package/dist/cjs/tools/search/firecrawl.cjs.map +1 -1
- package/dist/cjs/tools/search/format.cjs +6 -6
- package/dist/cjs/tools/search/format.cjs.map +1 -1
- package/dist/cjs/tools/search/rerankers.cjs +7 -29
- package/dist/cjs/tools/search/rerankers.cjs.map +1 -1
- package/dist/cjs/tools/search/search.cjs +86 -16
- package/dist/cjs/tools/search/search.cjs.map +1 -1
- package/dist/cjs/tools/search/tool.cjs +4 -2
- package/dist/cjs/tools/search/tool.cjs.map +1 -1
- package/dist/cjs/tools/search/utils.cjs +1 -1
- package/dist/cjs/tools/search/utils.cjs.map +1 -1
- package/dist/cjs/utils/events.cjs +31 -0
- package/dist/cjs/utils/events.cjs.map +1 -0
- package/dist/cjs/utils/title.cjs +57 -21
- package/dist/cjs/utils/title.cjs.map +1 -1
- package/dist/cjs/utils/tokens.cjs +54 -7
- package/dist/cjs/utils/tokens.cjs.map +1 -1
- package/dist/esm/agents/AgentContext.mjs +216 -0
- package/dist/esm/agents/AgentContext.mjs.map +1 -0
- package/dist/esm/common/enum.mjs +16 -6
- package/dist/esm/common/enum.mjs.map +1 -1
- package/dist/esm/events.mjs +10 -6
- package/dist/esm/events.mjs.map +1 -1
- package/dist/esm/graphs/Graph.mjs +311 -215
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/graphs/MultiAgentGraph.mjs +505 -0
- package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -0
- package/dist/esm/llm/anthropic/index.mjs +54 -9
- package/dist/esm/llm/anthropic/index.mjs.map +1 -1
- package/dist/esm/llm/anthropic/types.mjs.map +1 -1
- package/dist/esm/llm/anthropic/utils/message_inputs.mjs +52 -6
- package/dist/esm/llm/anthropic/utils/message_inputs.mjs.map +1 -1
- package/dist/esm/llm/anthropic/utils/message_outputs.mjs +22 -2
- package/dist/esm/llm/anthropic/utils/message_outputs.mjs.map +1 -1
- package/dist/esm/llm/anthropic/utils/tools.mjs +27 -0
- package/dist/esm/llm/anthropic/utils/tools.mjs.map +1 -0
- package/dist/esm/llm/google/index.mjs +142 -0
- package/dist/esm/llm/google/index.mjs.map +1 -0
- package/dist/esm/llm/google/utils/common.mjs +471 -0
- package/dist/esm/llm/google/utils/common.mjs.map +1 -0
- package/dist/esm/llm/ollama/index.mjs +65 -0
- package/dist/esm/llm/ollama/index.mjs.map +1 -0
- package/dist/esm/llm/ollama/utils.mjs +155 -0
- package/dist/esm/llm/ollama/utils.mjs.map +1 -0
- package/dist/esm/llm/openai/index.mjs +421 -4
- package/dist/esm/llm/openai/index.mjs.map +1 -1
- package/dist/esm/llm/openai/utils/index.mjs +666 -0
- package/dist/esm/llm/openai/utils/index.mjs.map +1 -0
- package/dist/esm/llm/providers.mjs +5 -5
- package/dist/esm/llm/providers.mjs.map +1 -1
- package/dist/esm/llm/text.mjs +14 -3
- package/dist/esm/llm/text.mjs.map +1 -1
- package/dist/esm/llm/vertexai/index.mjs +328 -0
- package/dist/esm/llm/vertexai/index.mjs.map +1 -0
- package/dist/esm/main.mjs +6 -5
- package/dist/esm/main.mjs.map +1 -1
- package/dist/esm/run.mjs +138 -87
- package/dist/esm/run.mjs.map +1 -1
- package/dist/esm/stream.mjs +88 -55
- package/dist/esm/stream.mjs.map +1 -1
- package/dist/esm/tools/ToolNode.mjs +10 -4
- package/dist/esm/tools/ToolNode.mjs.map +1 -1
- package/dist/esm/tools/handlers.mjs +119 -15
- package/dist/esm/tools/handlers.mjs.map +1 -1
- package/dist/esm/tools/search/anthropic.mjs +37 -0
- package/dist/esm/tools/search/anthropic.mjs.map +1 -0
- package/dist/esm/tools/search/firecrawl.mjs +55 -9
- package/dist/esm/tools/search/firecrawl.mjs.map +1 -1
- package/dist/esm/tools/search/format.mjs +7 -7
- package/dist/esm/tools/search/format.mjs.map +1 -1
- package/dist/esm/tools/search/rerankers.mjs +7 -29
- package/dist/esm/tools/search/rerankers.mjs.map +1 -1
- package/dist/esm/tools/search/search.mjs +86 -16
- package/dist/esm/tools/search/search.mjs.map +1 -1
- package/dist/esm/tools/search/tool.mjs +4 -2
- package/dist/esm/tools/search/tool.mjs.map +1 -1
- package/dist/esm/tools/search/utils.mjs +1 -1
- package/dist/esm/tools/search/utils.mjs.map +1 -1
- package/dist/esm/utils/events.mjs +29 -0
- package/dist/esm/utils/events.mjs.map +1 -0
- package/dist/esm/utils/title.mjs +57 -22
- package/dist/esm/utils/title.mjs.map +1 -1
- package/dist/esm/utils/tokens.mjs +54 -8
- package/dist/esm/utils/tokens.mjs.map +1 -1
- package/dist/types/agents/AgentContext.d.ts +91 -0
- package/dist/types/common/enum.d.ts +17 -7
- package/dist/types/events.d.ts +5 -4
- package/dist/types/graphs/Graph.d.ts +64 -67
- package/dist/types/graphs/MultiAgentGraph.d.ts +47 -0
- package/dist/types/graphs/index.d.ts +1 -0
- package/dist/types/llm/anthropic/index.d.ts +11 -0
- package/dist/types/llm/anthropic/types.d.ts +9 -3
- package/dist/types/llm/anthropic/utils/message_inputs.d.ts +1 -1
- package/dist/types/llm/anthropic/utils/output_parsers.d.ts +4 -4
- package/dist/types/llm/anthropic/utils/tools.d.ts +3 -0
- package/dist/types/llm/google/index.d.ts +13 -0
- package/dist/types/llm/google/types.d.ts +32 -0
- package/dist/types/llm/google/utils/common.d.ts +19 -0
- package/dist/types/llm/google/utils/tools.d.ts +10 -0
- package/dist/types/llm/google/utils/zod_to_genai_parameters.d.ts +14 -0
- package/dist/types/llm/ollama/index.d.ts +7 -0
- package/dist/types/llm/ollama/utils.d.ts +7 -0
- package/dist/types/llm/openai/index.d.ts +82 -3
- package/dist/types/llm/openai/types.d.ts +10 -0
- package/dist/types/llm/openai/utils/index.d.ts +20 -0
- package/dist/types/llm/text.d.ts +1 -1
- package/dist/types/llm/vertexai/index.d.ts +293 -0
- package/dist/types/messages/reducer.d.ts +9 -0
- package/dist/types/run.d.ts +19 -12
- package/dist/types/stream.d.ts +10 -3
- package/dist/types/tools/CodeExecutor.d.ts +2 -2
- package/dist/types/tools/ToolNode.d.ts +1 -1
- package/dist/types/tools/handlers.d.ts +17 -4
- package/dist/types/tools/search/anthropic.d.ts +16 -0
- package/dist/types/tools/search/firecrawl.d.ts +15 -0
- package/dist/types/tools/search/rerankers.d.ts +0 -1
- package/dist/types/tools/search/types.d.ts +30 -9
- package/dist/types/types/graph.d.ts +129 -15
- package/dist/types/types/llm.d.ts +25 -10
- package/dist/types/types/run.d.ts +50 -8
- package/dist/types/types/stream.d.ts +16 -2
- package/dist/types/types/tools.d.ts +1 -1
- package/dist/types/utils/events.d.ts +6 -0
- package/dist/types/utils/title.d.ts +2 -1
- package/dist/types/utils/tokens.d.ts +24 -0
- package/package.json +41 -17
- package/src/agents/AgentContext.ts +315 -0
- package/src/common/enum.ts +15 -5
- package/src/events.ts +24 -13
- package/src/graphs/Graph.ts +495 -313
- package/src/graphs/MultiAgentGraph.ts +598 -0
- package/src/graphs/index.ts +2 -1
- package/src/llm/anthropic/Jacob_Lee_Resume_2023.pdf +0 -0
- package/src/llm/anthropic/index.ts +78 -13
- package/src/llm/anthropic/llm.spec.ts +491 -115
- package/src/llm/anthropic/types.ts +39 -3
- package/src/llm/anthropic/utils/message_inputs.ts +67 -11
- package/src/llm/anthropic/utils/message_outputs.ts +21 -2
- package/src/llm/anthropic/utils/output_parsers.ts +25 -6
- package/src/llm/anthropic/utils/tools.ts +29 -0
- package/src/llm/google/index.ts +218 -0
- package/src/llm/google/types.ts +43 -0
- package/src/llm/google/utils/common.ts +646 -0
- package/src/llm/google/utils/tools.ts +160 -0
- package/src/llm/google/utils/zod_to_genai_parameters.ts +86 -0
- package/src/llm/ollama/index.ts +89 -0
- package/src/llm/ollama/utils.ts +193 -0
- package/src/llm/openai/index.ts +641 -14
- package/src/llm/openai/types.ts +24 -0
- package/src/llm/openai/utils/index.ts +912 -0
- package/src/llm/openai/utils/isReasoningModel.test.ts +90 -0
- package/src/llm/providers.ts +10 -9
- package/src/llm/text.ts +26 -7
- package/src/llm/vertexai/index.ts +360 -0
- package/src/messages/reducer.ts +80 -0
- package/src/run.ts +196 -116
- package/src/scripts/ant_web_search.ts +158 -0
- package/src/scripts/args.ts +12 -8
- package/src/scripts/cli4.ts +29 -21
- package/src/scripts/cli5.ts +29 -21
- package/src/scripts/code_exec.ts +54 -23
- package/src/scripts/code_exec_files.ts +48 -17
- package/src/scripts/code_exec_simple.ts +46 -27
- package/src/scripts/handoff-test.ts +135 -0
- package/src/scripts/image.ts +52 -20
- package/src/scripts/multi-agent-chain.ts +278 -0
- package/src/scripts/multi-agent-conditional.ts +220 -0
- package/src/scripts/multi-agent-document-review-chain.ts +197 -0
- package/src/scripts/multi-agent-hybrid-flow.ts +310 -0
- package/src/scripts/multi-agent-parallel.ts +341 -0
- package/src/scripts/multi-agent-sequence.ts +212 -0
- package/src/scripts/multi-agent-supervisor.ts +362 -0
- package/src/scripts/multi-agent-test.ts +186 -0
- package/src/scripts/search.ts +1 -9
- package/src/scripts/simple.ts +25 -10
- package/src/scripts/test-custom-prompt-key.ts +145 -0
- package/src/scripts/test-handoff-input.ts +170 -0
- package/src/scripts/test-multi-agent-list-handoff.ts +261 -0
- package/src/scripts/test-tools-before-handoff.ts +233 -0
- package/src/scripts/tools.ts +48 -18
- package/src/specs/anthropic.simple.test.ts +150 -34
- package/src/specs/azure.simple.test.ts +325 -0
- package/src/specs/openai.simple.test.ts +140 -33
- package/src/specs/openrouter.simple.test.ts +107 -0
- package/src/specs/prune.test.ts +4 -9
- package/src/specs/reasoning.test.ts +80 -44
- package/src/specs/token-memoization.test.ts +39 -0
- package/src/stream.test.ts +94 -0
- package/src/stream.ts +143 -61
- package/src/tools/ToolNode.ts +21 -7
- package/src/tools/handlers.ts +192 -18
- package/src/tools/search/anthropic.ts +51 -0
- package/src/tools/search/firecrawl.ts +69 -20
- package/src/tools/search/format.ts +6 -8
- package/src/tools/search/rerankers.ts +7 -40
- package/src/tools/search/search.ts +97 -16
- package/src/tools/search/tool.ts +5 -2
- package/src/tools/search/types.ts +30 -10
- package/src/tools/search/utils.ts +1 -1
- package/src/types/graph.ts +318 -103
- package/src/types/llm.ts +26 -12
- package/src/types/run.ts +56 -13
- package/src/types/stream.ts +22 -1
- package/src/types/tools.ts +16 -10
- package/src/utils/events.ts +32 -0
- package/src/utils/llmConfig.ts +19 -7
- package/src/utils/title.ts +104 -30
- package/src/utils/tokens.ts +69 -10
- package/dist/types/scripts/abort.d.ts +0 -1
- package/dist/types/scripts/args.d.ts +0 -6
- package/dist/types/scripts/caching.d.ts +0 -1
- package/dist/types/scripts/cli.d.ts +0 -1
- package/dist/types/scripts/cli2.d.ts +0 -1
- package/dist/types/scripts/cli3.d.ts +0 -1
- package/dist/types/scripts/cli4.d.ts +0 -1
- package/dist/types/scripts/cli5.d.ts +0 -1
- package/dist/types/scripts/code_exec.d.ts +0 -1
- package/dist/types/scripts/code_exec_files.d.ts +0 -1
- package/dist/types/scripts/code_exec_simple.d.ts +0 -1
- package/dist/types/scripts/content.d.ts +0 -1
- package/dist/types/scripts/empty_input.d.ts +0 -1
- package/dist/types/scripts/image.d.ts +0 -1
- package/dist/types/scripts/memory.d.ts +0 -1
- package/dist/types/scripts/search.d.ts +0 -1
- package/dist/types/scripts/simple.d.ts +0 -1
- package/dist/types/scripts/stream.d.ts +0 -1
- package/dist/types/scripts/thinking.d.ts +0 -1
- package/dist/types/scripts/tools.d.ts +0 -1
- package/dist/types/specs/spec.utils.d.ts +0 -1
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { config } from 'dotenv';
|
|
2
|
+
config();
|
|
3
|
+
|
|
4
|
+
import { HumanMessage, BaseMessage } from '@langchain/core/messages';
|
|
5
|
+
import { Run } from '@/run';
|
|
6
|
+
import { Providers, GraphEvents } from '@/common';
|
|
7
|
+
import { ChatModelStreamHandler, createContentAggregator } from '@/stream';
|
|
8
|
+
import { ToolEndHandler, ModelEndHandler } from '@/events';
|
|
9
|
+
import type * as t from '@/types';
|
|
10
|
+
|
|
11
|
+
const conversationHistory: BaseMessage[] = [];
|
|
12
|
+
|
|
13
|
+
async function testMultiAgentHandoff() {
|
|
14
|
+
console.log('Testing Multi-Agent Handoff System...\n');
|
|
15
|
+
|
|
16
|
+
// Set up content aggregator
|
|
17
|
+
const { contentParts, aggregateContent } = createContentAggregator();
|
|
18
|
+
|
|
19
|
+
// Define agent configurations
|
|
20
|
+
const agents: t.AgentInputs[] = [
|
|
21
|
+
{
|
|
22
|
+
agentId: 'flight_assistant',
|
|
23
|
+
provider: Providers.ANTHROPIC,
|
|
24
|
+
clientOptions: {
|
|
25
|
+
modelName: 'claude-3-5-sonnet-latest',
|
|
26
|
+
apiKey: process.env.ANTHROPIC_API_KEY,
|
|
27
|
+
},
|
|
28
|
+
instructions:
|
|
29
|
+
'You are a flight booking assistant. Help users book flights between airports.',
|
|
30
|
+
maxContextTokens: 28000,
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
agentId: 'hotel_assistant',
|
|
34
|
+
provider: Providers.ANTHROPIC,
|
|
35
|
+
clientOptions: {
|
|
36
|
+
modelName: 'claude-3-5-sonnet-latest',
|
|
37
|
+
apiKey: process.env.ANTHROPIC_API_KEY,
|
|
38
|
+
},
|
|
39
|
+
instructions:
|
|
40
|
+
'You are a hotel booking assistant. Help users book hotel stays.',
|
|
41
|
+
maxContextTokens: 28000,
|
|
42
|
+
},
|
|
43
|
+
];
|
|
44
|
+
|
|
45
|
+
// Define edges (handoff relationships)
|
|
46
|
+
// These edges create handoff tools that agents can use to transfer control dynamically
|
|
47
|
+
const edges: t.GraphEdge[] = [
|
|
48
|
+
{
|
|
49
|
+
from: 'flight_assistant',
|
|
50
|
+
to: 'hotel_assistant',
|
|
51
|
+
description:
|
|
52
|
+
'Transfer to hotel booking assistant when user needs hotel assistance',
|
|
53
|
+
// edgeType defaults to 'handoff' for single-to-single edges
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
from: 'hotel_assistant',
|
|
57
|
+
to: 'flight_assistant',
|
|
58
|
+
description:
|
|
59
|
+
'Transfer to flight booking assistant when user needs flight assistance',
|
|
60
|
+
// edgeType defaults to 'handoff' for single-to-single edges
|
|
61
|
+
},
|
|
62
|
+
];
|
|
63
|
+
|
|
64
|
+
// Create custom handlers similar to examples
|
|
65
|
+
const customHandlers = {
|
|
66
|
+
[GraphEvents.TOOL_END]: new ToolEndHandler(),
|
|
67
|
+
[GraphEvents.CHAT_MODEL_END]: new ModelEndHandler(),
|
|
68
|
+
[GraphEvents.CHAT_MODEL_STREAM]: new ChatModelStreamHandler(),
|
|
69
|
+
[GraphEvents.ON_RUN_STEP_COMPLETED]: {
|
|
70
|
+
handle: (
|
|
71
|
+
event: GraphEvents.ON_RUN_STEP_COMPLETED,
|
|
72
|
+
data: t.StreamEventData
|
|
73
|
+
): void => {
|
|
74
|
+
console.log('====== ON_RUN_STEP_COMPLETED ======');
|
|
75
|
+
console.dir(data, { depth: null });
|
|
76
|
+
aggregateContent({
|
|
77
|
+
event,
|
|
78
|
+
data: data as unknown as { result: t.ToolEndEvent },
|
|
79
|
+
});
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
[GraphEvents.ON_RUN_STEP]: {
|
|
83
|
+
handle: (
|
|
84
|
+
event: GraphEvents.ON_RUN_STEP,
|
|
85
|
+
data: t.StreamEventData
|
|
86
|
+
): void => {
|
|
87
|
+
console.log('====== ON_RUN_STEP ======');
|
|
88
|
+
console.dir(data, { depth: null });
|
|
89
|
+
aggregateContent({ event, data: data as t.RunStep });
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
[GraphEvents.ON_RUN_STEP_DELTA]: {
|
|
93
|
+
handle: (
|
|
94
|
+
event: GraphEvents.ON_RUN_STEP_DELTA,
|
|
95
|
+
data: t.StreamEventData
|
|
96
|
+
): void => {
|
|
97
|
+
console.log('====== ON_RUN_STEP_DELTA ======');
|
|
98
|
+
console.dir(data, { depth: null });
|
|
99
|
+
aggregateContent({ event, data: data as t.RunStepDeltaEvent });
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
[GraphEvents.ON_MESSAGE_DELTA]: {
|
|
103
|
+
handle: (
|
|
104
|
+
event: GraphEvents.ON_MESSAGE_DELTA,
|
|
105
|
+
data: t.StreamEventData
|
|
106
|
+
): void => {
|
|
107
|
+
console.log('====== ON_MESSAGE_DELTA ======');
|
|
108
|
+
console.dir(data, { depth: null });
|
|
109
|
+
aggregateContent({ event, data: data as t.MessageDeltaEvent });
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
[GraphEvents.ON_REASONING_DELTA]: {
|
|
113
|
+
handle: (
|
|
114
|
+
event: GraphEvents.ON_REASONING_DELTA,
|
|
115
|
+
data: t.StreamEventData
|
|
116
|
+
): void => {
|
|
117
|
+
console.log('====== ON_REASONING_DELTA ======');
|
|
118
|
+
console.dir(data, { depth: null });
|
|
119
|
+
aggregateContent({ event, data: data as t.ReasoningDeltaEvent });
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
[GraphEvents.TOOL_START]: {
|
|
123
|
+
handle: (
|
|
124
|
+
_event: string,
|
|
125
|
+
data: t.StreamEventData,
|
|
126
|
+
metadata?: Record<string, unknown>
|
|
127
|
+
): void => {
|
|
128
|
+
console.log('====== TOOL_START ======');
|
|
129
|
+
console.dir(data, { depth: null });
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
// Create multi-agent run configuration
|
|
135
|
+
const runConfig: t.RunConfig = {
|
|
136
|
+
runId: `multi-agent-test-${Date.now()}`,
|
|
137
|
+
graphConfig: {
|
|
138
|
+
type: 'multi-agent',
|
|
139
|
+
agents,
|
|
140
|
+
edges,
|
|
141
|
+
},
|
|
142
|
+
customHandlers,
|
|
143
|
+
returnContent: true,
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
try {
|
|
147
|
+
// Create and execute the run
|
|
148
|
+
const run = await Run.create(runConfig);
|
|
149
|
+
|
|
150
|
+
const userMessage =
|
|
151
|
+
'I need to book a flight from Boston to New York, and also need a hotel near Times Square.';
|
|
152
|
+
conversationHistory.push(new HumanMessage(userMessage));
|
|
153
|
+
|
|
154
|
+
console.log('Invoking multi-agent graph...\n');
|
|
155
|
+
|
|
156
|
+
const config = {
|
|
157
|
+
configurable: {
|
|
158
|
+
thread_id: 'multi-agent-conversation-1',
|
|
159
|
+
},
|
|
160
|
+
streamMode: 'values',
|
|
161
|
+
version: 'v2' as const,
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
// Process with streaming
|
|
165
|
+
const inputs = {
|
|
166
|
+
messages: conversationHistory,
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
const finalContentParts = await run.processStream(inputs, config);
|
|
170
|
+
const finalMessages = run.getRunMessages();
|
|
171
|
+
|
|
172
|
+
if (finalMessages) {
|
|
173
|
+
conversationHistory.push(...finalMessages);
|
|
174
|
+
console.log('\n\nConversation history:');
|
|
175
|
+
console.dir(conversationHistory, { depth: null });
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
console.log('\n\nFinal content parts:');
|
|
179
|
+
console.dir(contentParts, { depth: null });
|
|
180
|
+
} catch (error) {
|
|
181
|
+
console.error('Error in multi-agent test:', error);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Run the test
|
|
186
|
+
testMultiAgentHandoff();
|
package/src/scripts/search.ts
CHANGED
|
@@ -39,8 +39,6 @@ async function testStandardStreaming(): Promise<void> {
|
|
|
39
39
|
event: GraphEvents.ON_RUN_STEP,
|
|
40
40
|
data: t.StreamEventData
|
|
41
41
|
): void => {
|
|
42
|
-
console.log('====== ON_RUN_STEP ======');
|
|
43
|
-
console.dir(data, { depth: null });
|
|
44
42
|
aggregateContent({ event, data: data as t.RunStep });
|
|
45
43
|
},
|
|
46
44
|
},
|
|
@@ -49,8 +47,6 @@ async function testStandardStreaming(): Promise<void> {
|
|
|
49
47
|
event: GraphEvents.ON_RUN_STEP_DELTA,
|
|
50
48
|
data: t.StreamEventData
|
|
51
49
|
): void => {
|
|
52
|
-
console.log('====== ON_RUN_STEP_DELTA ======');
|
|
53
|
-
console.dir(data, { depth: null });
|
|
54
50
|
aggregateContent({ event, data: data as t.RunStepDeltaEvent });
|
|
55
51
|
},
|
|
56
52
|
},
|
|
@@ -59,8 +55,6 @@ async function testStandardStreaming(): Promise<void> {
|
|
|
59
55
|
event: GraphEvents.ON_MESSAGE_DELTA,
|
|
60
56
|
data: t.StreamEventData
|
|
61
57
|
): void => {
|
|
62
|
-
console.log('====== ON_MESSAGE_DELTA ======');
|
|
63
|
-
console.dir(data, { depth: null });
|
|
64
58
|
aggregateContent({ event, data: data as t.MessageDeltaEvent });
|
|
65
59
|
},
|
|
66
60
|
},
|
|
@@ -133,9 +127,7 @@ async function testStandardStreaming(): Promise<void> {
|
|
|
133
127
|
}
|
|
134
128
|
|
|
135
129
|
process.on('unhandledRejection', (reason, promise) => {
|
|
136
|
-
console.
|
|
137
|
-
console.log('Conversation history:');
|
|
138
|
-
process.exit(1);
|
|
130
|
+
console.warn('Unhandled Rejection (non-fatal):', reason);
|
|
139
131
|
});
|
|
140
132
|
|
|
141
133
|
testStandardStreaming().catch((err) => {
|
package/src/scripts/simple.ts
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
// src/scripts/cli.ts
|
|
2
2
|
import { config } from 'dotenv';
|
|
3
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
3
4
|
config();
|
|
4
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
HumanMessage,
|
|
7
|
+
BaseMessage,
|
|
8
|
+
UsageMetadata,
|
|
9
|
+
} from '@langchain/core/messages';
|
|
5
10
|
import { TavilySearchResults } from '@langchain/community/tools/tavily_search';
|
|
6
11
|
import type * as t from '@/types';
|
|
7
12
|
import { ChatModelStreamHandler, createContentAggregator } from '@/stream';
|
|
@@ -10,21 +15,27 @@ import {
|
|
|
10
15
|
ModelEndHandler,
|
|
11
16
|
createMetadataAggregator,
|
|
12
17
|
} from '@/events';
|
|
18
|
+
import { GraphEvents, Providers, TitleMethod } from '@/common';
|
|
13
19
|
import { getLLMConfig } from '@/utils/llmConfig';
|
|
14
20
|
import { getArgs } from '@/scripts/args';
|
|
15
|
-
import { GraphEvents, Providers } from '@/common';
|
|
16
21
|
import { Run } from '@/run';
|
|
17
22
|
|
|
18
23
|
const conversationHistory: BaseMessage[] = [];
|
|
19
24
|
let _contentParts: t.MessageContentComplex[] = [];
|
|
25
|
+
let collectedUsage: UsageMetadata[] = [];
|
|
20
26
|
|
|
21
27
|
async function testStandardStreaming(): Promise<void> {
|
|
22
|
-
const {
|
|
28
|
+
const {
|
|
29
|
+
userName,
|
|
30
|
+
location,
|
|
31
|
+
provider: _provider,
|
|
32
|
+
currentDate,
|
|
33
|
+
} = await getArgs();
|
|
23
34
|
const { contentParts, aggregateContent } = createContentAggregator();
|
|
24
35
|
_contentParts = contentParts as t.MessageContentComplex[];
|
|
25
36
|
const customHandlers = {
|
|
26
37
|
[GraphEvents.TOOL_END]: new ToolEndHandler(),
|
|
27
|
-
[GraphEvents.CHAT_MODEL_END]: new ModelEndHandler(),
|
|
38
|
+
[GraphEvents.CHAT_MODEL_END]: new ModelEndHandler(collectedUsage),
|
|
28
39
|
[GraphEvents.CHAT_MODEL_STREAM]: new ChatModelStreamHandler(),
|
|
29
40
|
[GraphEvents.ON_RUN_STEP_COMPLETED]: {
|
|
30
41
|
handle: (
|
|
@@ -32,7 +43,7 @@ async function testStandardStreaming(): Promise<void> {
|
|
|
32
43
|
data: t.StreamEventData
|
|
33
44
|
): void => {
|
|
34
45
|
console.log('====== ON_RUN_STEP_COMPLETED ======');
|
|
35
|
-
|
|
46
|
+
console.dir(data, { depth: null });
|
|
36
47
|
aggregateContent({
|
|
37
48
|
event,
|
|
38
49
|
data: data as unknown as { result: t.ToolEndEvent },
|
|
@@ -91,7 +102,7 @@ async function testStandardStreaming(): Promise<void> {
|
|
|
91
102
|
},
|
|
92
103
|
};
|
|
93
104
|
|
|
94
|
-
const llmConfig = getLLMConfig(
|
|
105
|
+
const llmConfig = getLLMConfig(_provider);
|
|
95
106
|
if (
|
|
96
107
|
'configuration' in llmConfig &&
|
|
97
108
|
(llmConfig as t.OpenAIClientOptions).configuration != null
|
|
@@ -99,7 +110,7 @@ async function testStandardStreaming(): Promise<void> {
|
|
|
99
110
|
const openAIConfig = llmConfig as t.OpenAIClientOptions;
|
|
100
111
|
if (openAIConfig.configuration) {
|
|
101
112
|
openAIConfig.configuration.fetch = (
|
|
102
|
-
url:
|
|
113
|
+
url: string | URL | Request,
|
|
103
114
|
init?: RequestInit
|
|
104
115
|
) => {
|
|
105
116
|
console.log('Fetching:', url);
|
|
@@ -107,6 +118,7 @@ async function testStandardStreaming(): Promise<void> {
|
|
|
107
118
|
};
|
|
108
119
|
}
|
|
109
120
|
}
|
|
121
|
+
const provider = llmConfig.provider;
|
|
110
122
|
|
|
111
123
|
if (provider === Providers.ANTHROPIC) {
|
|
112
124
|
(llmConfig as t.AnthropicClientOptions).clientOptions = {
|
|
@@ -118,12 +130,12 @@ async function testStandardStreaming(): Promise<void> {
|
|
|
118
130
|
}
|
|
119
131
|
|
|
120
132
|
const run = await Run.create<t.IState>({
|
|
121
|
-
runId:
|
|
133
|
+
runId: uuidv4(),
|
|
122
134
|
graphConfig: {
|
|
123
135
|
type: 'standard',
|
|
124
136
|
llmConfig,
|
|
125
137
|
// tools: [new TavilySearchResults()],
|
|
126
|
-
reasoningKey: 'reasoning',
|
|
138
|
+
// reasoningKey: 'reasoning',
|
|
127
139
|
instructions:
|
|
128
140
|
'You are a friendly AI assistant. Always address the user by their name.',
|
|
129
141
|
additional_instructions: `The user's name is ${userName} and they are located in ${location}.`,
|
|
@@ -160,8 +172,10 @@ async function testStandardStreaming(): Promise<void> {
|
|
|
160
172
|
console.dir(contentParts, { depth: null });
|
|
161
173
|
const { handleLLMEnd, collected } = createMetadataAggregator();
|
|
162
174
|
const titleOptions: t.RunTitleOptions = {
|
|
175
|
+
provider,
|
|
163
176
|
inputText: userMessage,
|
|
164
177
|
contentParts,
|
|
178
|
+
// titleMethod: TitleMethod.STRUCTURED,
|
|
165
179
|
chainOptions: {
|
|
166
180
|
callbacks: [
|
|
167
181
|
{
|
|
@@ -176,8 +190,9 @@ async function testStandardStreaming(): Promise<void> {
|
|
|
176
190
|
};
|
|
177
191
|
}
|
|
178
192
|
const titleResult = await run.generateTitle(titleOptions);
|
|
193
|
+
console.log('Collected usage metadata:', collectedUsage);
|
|
179
194
|
console.log('Generated Title:', titleResult);
|
|
180
|
-
console.log('Collected metadata:', collected);
|
|
195
|
+
console.log('Collected title usage metadata:', collected);
|
|
181
196
|
}
|
|
182
197
|
|
|
183
198
|
process.on('unhandledRejection', (reason, promise) => {
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
|
|
3
|
+
import { config } from 'dotenv';
|
|
4
|
+
config();
|
|
5
|
+
|
|
6
|
+
import { HumanMessage } from '@langchain/core/messages';
|
|
7
|
+
import { Run } from '@/run';
|
|
8
|
+
import { Providers } from '@/common';
|
|
9
|
+
import type * as t from '@/types';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Test the custom promptKey feature for handoff edges
|
|
13
|
+
* This demonstrates how to use custom parameter names instead of "instructions"
|
|
14
|
+
*/
|
|
15
|
+
async function testCustomPromptKey() {
|
|
16
|
+
console.log('Testing Custom Prompt Key Feature...\n');
|
|
17
|
+
|
|
18
|
+
const runConfig: t.RunConfig = {
|
|
19
|
+
runId: `test-custom-prompt-key-${Date.now()}`,
|
|
20
|
+
graphConfig: {
|
|
21
|
+
type: 'multi-agent',
|
|
22
|
+
agents: [
|
|
23
|
+
{
|
|
24
|
+
agentId: 'supervisor',
|
|
25
|
+
provider: Providers.ANTHROPIC,
|
|
26
|
+
clientOptions: {
|
|
27
|
+
modelName: 'claude-3-5-sonnet-latest',
|
|
28
|
+
apiKey: process.env.ANTHROPIC_API_KEY,
|
|
29
|
+
},
|
|
30
|
+
instructions: `You are a Task Supervisor managing different agents:
|
|
31
|
+
|
|
32
|
+
1. transfer_to_researcher - For research tasks (uses "query" parameter)
|
|
33
|
+
2. transfer_to_designer - For design tasks (uses "requirements" parameter)
|
|
34
|
+
3. transfer_to_coder - For coding tasks (uses "specification" parameter)
|
|
35
|
+
|
|
36
|
+
Each agent expects different parameter names in their handoff tools.
|
|
37
|
+
Pay attention to the parameter names when calling each tool.`,
|
|
38
|
+
maxContextTokens: 8000,
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
agentId: 'researcher',
|
|
42
|
+
provider: Providers.ANTHROPIC,
|
|
43
|
+
clientOptions: {
|
|
44
|
+
modelName: 'claude-3-5-sonnet-latest',
|
|
45
|
+
apiKey: process.env.ANTHROPIC_API_KEY,
|
|
46
|
+
},
|
|
47
|
+
instructions: `You are a Research Agent. You receive research queries to investigate.
|
|
48
|
+
Look for the "Query:" field in the transfer message.`,
|
|
49
|
+
maxContextTokens: 8000,
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
agentId: 'designer',
|
|
53
|
+
provider: Providers.ANTHROPIC,
|
|
54
|
+
clientOptions: {
|
|
55
|
+
modelName: 'claude-3-5-sonnet-latest',
|
|
56
|
+
apiKey: process.env.ANTHROPIC_API_KEY,
|
|
57
|
+
},
|
|
58
|
+
instructions: `You are a Design Agent. You receive design requirements to implement.
|
|
59
|
+
Look for the "Requirements:" field in the transfer message.`,
|
|
60
|
+
maxContextTokens: 8000,
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
agentId: 'coder',
|
|
64
|
+
provider: Providers.ANTHROPIC,
|
|
65
|
+
clientOptions: {
|
|
66
|
+
modelName: 'claude-3-5-sonnet-latest',
|
|
67
|
+
apiKey: process.env.ANTHROPIC_API_KEY,
|
|
68
|
+
},
|
|
69
|
+
instructions: `You are a Coding Agent. You receive technical specifications to implement.
|
|
70
|
+
Look for the "Specification:" field in the transfer message.`,
|
|
71
|
+
maxContextTokens: 8000,
|
|
72
|
+
},
|
|
73
|
+
],
|
|
74
|
+
edges: [
|
|
75
|
+
{
|
|
76
|
+
from: 'supervisor',
|
|
77
|
+
to: 'researcher',
|
|
78
|
+
edgeType: 'handoff',
|
|
79
|
+
// Custom parameter name: "query"
|
|
80
|
+
prompt: 'The research question or topic to investigate',
|
|
81
|
+
promptKey: 'query',
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
from: 'supervisor',
|
|
85
|
+
to: 'designer',
|
|
86
|
+
edgeType: 'handoff',
|
|
87
|
+
// Custom parameter name: "requirements"
|
|
88
|
+
prompt: 'The design requirements and constraints',
|
|
89
|
+
promptKey: 'requirements',
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
from: 'supervisor',
|
|
93
|
+
to: 'coder',
|
|
94
|
+
edgeType: 'handoff',
|
|
95
|
+
// Custom parameter name: "specification"
|
|
96
|
+
prompt: 'The technical specification for the code to implement',
|
|
97
|
+
promptKey: 'specification',
|
|
98
|
+
},
|
|
99
|
+
],
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
const run = await Run.create(runConfig);
|
|
104
|
+
|
|
105
|
+
// Test queries for different agents
|
|
106
|
+
const testQueries = [
|
|
107
|
+
// 'Research the latest trends in sustainable energy storage technologies',
|
|
108
|
+
'Design a mobile app interface for a fitness tracking application',
|
|
109
|
+
// 'Write a Python function that calculates the Fibonacci sequence recursively',
|
|
110
|
+
];
|
|
111
|
+
|
|
112
|
+
const config = {
|
|
113
|
+
configurable: {
|
|
114
|
+
thread_id: 'custom-prompt-key-test-1',
|
|
115
|
+
},
|
|
116
|
+
streamMode: 'values',
|
|
117
|
+
version: 'v2' as const,
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
for (const query of testQueries) {
|
|
121
|
+
console.log(`\n${'='.repeat(60)}`);
|
|
122
|
+
console.log(`USER QUERY: "${query}"`);
|
|
123
|
+
console.log('='.repeat(60));
|
|
124
|
+
|
|
125
|
+
const inputs = {
|
|
126
|
+
messages: [new HumanMessage(query)],
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
await run.processStream(inputs, config);
|
|
130
|
+
|
|
131
|
+
console.log(`\n${'ā'.repeat(60)}`);
|
|
132
|
+
console.log('Each agent receives instructions via their custom parameter:');
|
|
133
|
+
console.log('- Researcher expects "query"');
|
|
134
|
+
console.log('- Designer expects "requirements"');
|
|
135
|
+
console.log('- Coder expects "specification"');
|
|
136
|
+
console.log('ā'.repeat(60));
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
console.log('\n\nDemonstration complete!');
|
|
140
|
+
console.log('The promptKey feature allows for more semantic parameter names');
|
|
141
|
+
console.log('that better match the domain and purpose of each agent.');
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Run the test
|
|
145
|
+
testCustomPromptKey().catch(console.error);
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { config } from 'dotenv';
|
|
2
|
+
config();
|
|
3
|
+
|
|
4
|
+
import { HumanMessage } from '@langchain/core/messages';
|
|
5
|
+
import { Run } from '@/run';
|
|
6
|
+
import { Providers, GraphEvents } from '@/common';
|
|
7
|
+
import { ChatModelStreamHandler, createContentAggregator } from '@/stream';
|
|
8
|
+
import { ToolEndHandler, ModelEndHandler } from '@/events';
|
|
9
|
+
import type * as t from '@/types';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Test the new handoff input feature using the prompt field
|
|
13
|
+
* This demonstrates how supervisors can pass specific instructions to specialists
|
|
14
|
+
*/
|
|
15
|
+
async function testHandoffInput() {
|
|
16
|
+
console.log('Testing Handoff Input Feature...\n');
|
|
17
|
+
// Set up content aggregator
|
|
18
|
+
const { contentParts, aggregateContent } = createContentAggregator();
|
|
19
|
+
|
|
20
|
+
// Track which specialist role was selected
|
|
21
|
+
let selectedRole = '';
|
|
22
|
+
let roleInstructions = '';
|
|
23
|
+
|
|
24
|
+
// Create custom handlers
|
|
25
|
+
const customHandlers = {
|
|
26
|
+
[GraphEvents.TOOL_END]: new ToolEndHandler(),
|
|
27
|
+
[GraphEvents.CHAT_MODEL_END]: new ModelEndHandler(),
|
|
28
|
+
[GraphEvents.CHAT_MODEL_STREAM]: new ChatModelStreamHandler(),
|
|
29
|
+
[GraphEvents.ON_RUN_STEP]: {
|
|
30
|
+
handle: (
|
|
31
|
+
event: GraphEvents.ON_RUN_STEP,
|
|
32
|
+
data: t.StreamEventData
|
|
33
|
+
): void => {
|
|
34
|
+
const runStepData = data as any;
|
|
35
|
+
if (runStepData?.name) {
|
|
36
|
+
console.log(`\n[${runStepData.name}] Processing...`);
|
|
37
|
+
}
|
|
38
|
+
aggregateContent({ event, data: data as t.RunStep });
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
[GraphEvents.ON_RUN_STEP_COMPLETED]: {
|
|
42
|
+
handle: (
|
|
43
|
+
event: GraphEvents.ON_RUN_STEP_COMPLETED,
|
|
44
|
+
data: t.StreamEventData
|
|
45
|
+
): void => {
|
|
46
|
+
aggregateContent({
|
|
47
|
+
event,
|
|
48
|
+
data: data as unknown as { result: t.ToolEndEvent },
|
|
49
|
+
});
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
[GraphEvents.ON_MESSAGE_DELTA]: {
|
|
53
|
+
handle: (
|
|
54
|
+
event: GraphEvents.ON_MESSAGE_DELTA,
|
|
55
|
+
data: t.StreamEventData
|
|
56
|
+
): void => {
|
|
57
|
+
console.dir(data, { depth: null });
|
|
58
|
+
aggregateContent({ event, data: data as t.MessageDeltaEvent });
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
[GraphEvents.TOOL_START]: {
|
|
62
|
+
handle: (
|
|
63
|
+
_event: string,
|
|
64
|
+
data: t.StreamEventData,
|
|
65
|
+
metadata?: Record<string, unknown>
|
|
66
|
+
): void => {
|
|
67
|
+
const toolData = data as any;
|
|
68
|
+
if (toolData?.name?.includes('transfer_to_')) {
|
|
69
|
+
const specialist = toolData.name.replace('transfer_to_', '');
|
|
70
|
+
console.log(`\nš Transferring to ${specialist}...`);
|
|
71
|
+
selectedRole = specialist;
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const runConfig: t.RunConfig = {
|
|
78
|
+
customHandlers,
|
|
79
|
+
runId: `test-handoff-input-${Date.now()}`,
|
|
80
|
+
graphConfig: {
|
|
81
|
+
type: 'multi-agent',
|
|
82
|
+
agents: [
|
|
83
|
+
{
|
|
84
|
+
agentId: 'supervisor',
|
|
85
|
+
provider: Providers.ANTHROPIC,
|
|
86
|
+
clientOptions: {
|
|
87
|
+
modelName: 'claude-3-5-sonnet-latest',
|
|
88
|
+
apiKey: process.env.ANTHROPIC_API_KEY,
|
|
89
|
+
},
|
|
90
|
+
instructions: `You are a Task Supervisor. You have access to two specialist agents:
|
|
91
|
+
|
|
92
|
+
1. transfer_to_analyst - For data analysis tasks
|
|
93
|
+
2. transfer_to_writer - For content creation tasks
|
|
94
|
+
|
|
95
|
+
When transferring to a specialist, you MUST provide specific instructions
|
|
96
|
+
in the tool call to guide their work. Be detailed about what you need.`,
|
|
97
|
+
maxContextTokens: 8000,
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
agentId: 'analyst',
|
|
101
|
+
provider: Providers.ANTHROPIC,
|
|
102
|
+
clientOptions: {
|
|
103
|
+
modelName: 'claude-3-5-sonnet-latest',
|
|
104
|
+
apiKey: process.env.ANTHROPIC_API_KEY,
|
|
105
|
+
},
|
|
106
|
+
instructions: `You are a Data Analyst. Follow the supervisor's instructions carefully.
|
|
107
|
+
When you receive instructions, acknowledge them and perform the requested analysis.`,
|
|
108
|
+
maxContextTokens: 8000,
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
agentId: 'writer',
|
|
112
|
+
provider: Providers.ANTHROPIC,
|
|
113
|
+
clientOptions: {
|
|
114
|
+
modelName: 'claude-3-5-sonnet-latest',
|
|
115
|
+
apiKey: process.env.ANTHROPIC_API_KEY,
|
|
116
|
+
},
|
|
117
|
+
instructions: `You are a Content Writer. Follow the supervisor's instructions carefully.
|
|
118
|
+
When you receive instructions, acknowledge them and create the requested content.`,
|
|
119
|
+
maxContextTokens: 8000,
|
|
120
|
+
},
|
|
121
|
+
],
|
|
122
|
+
edges: [
|
|
123
|
+
{
|
|
124
|
+
from: 'supervisor',
|
|
125
|
+
to: ['analyst', 'writer'],
|
|
126
|
+
edgeType: 'handoff',
|
|
127
|
+
// This prompt field now serves as the description for the input parameter
|
|
128
|
+
prompt:
|
|
129
|
+
'Specific instructions for the specialist to follow. Be detailed about what analysis to perform, what data to focus on, or what content to create.',
|
|
130
|
+
},
|
|
131
|
+
],
|
|
132
|
+
},
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
const run = await Run.create(runConfig);
|
|
136
|
+
|
|
137
|
+
// Test queries that should result in different handoffs with specific instructions
|
|
138
|
+
const testQueries = [
|
|
139
|
+
// 'Analyze our Q4 sales data and identify the top 3 performing products',
|
|
140
|
+
'Write a blog post about the benefits of remote work for software developers',
|
|
141
|
+
];
|
|
142
|
+
|
|
143
|
+
const config = {
|
|
144
|
+
configurable: {
|
|
145
|
+
thread_id: 'handoff-input-test-1',
|
|
146
|
+
},
|
|
147
|
+
streamMode: 'values',
|
|
148
|
+
version: 'v2' as const,
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
for (const query of testQueries) {
|
|
152
|
+
console.log(`\n${'='.repeat(60)}`);
|
|
153
|
+
console.log(`USER QUERY: "${query}"`);
|
|
154
|
+
console.log('='.repeat(60));
|
|
155
|
+
|
|
156
|
+
const inputs = {
|
|
157
|
+
messages: [new HumanMessage(query)],
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
const finalContentParts = await run.processStream(inputs, config);
|
|
161
|
+
|
|
162
|
+
console.log(`\n${'ā'.repeat(60)}`);
|
|
163
|
+
console.log('Notice how the supervisor passes specific instructions');
|
|
164
|
+
console.log('to the specialist through the handoff tool input parameter.');
|
|
165
|
+
console.log('ā'.repeat(60));
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Run the test
|
|
170
|
+
testHandoffInput().catch(console.error);
|