-
Notifications
You must be signed in to change notification settings - Fork 20
Expand file tree
/
Copy path05-handoffs.ts
More file actions
125 lines (111 loc) · 3.42 KB
/
Copy path05-handoffs.ts
File metadata and controls
125 lines (111 loc) · 3.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/**
* Handoffs — agent delegating to sub-agents.
*
* Demonstrates the handoff strategy where the parent agent's LLM decides
* which sub-agent to delegate to. Sub-agents appear as callable tools.
*
* Requirements:
* - Conductor server with LLM support
* - CONDUCTOR_SERVER_URL=http://localhost:8080/api
* - CONDUCTOR_AGENT_LLM_MODEL=openai/gpt-4o-mini
*/
import { Agent, AgentRuntime, tool } from '@io-orkes/conductor-javascript/agents';
import { llmModel } from './settings';
// -- Sub-agent tools --------------------------------------------------------
const checkBalance = tool(
async (args: { accountId: string }) => {
return { account_id: args.accountId, balance: 5432.10, currency: 'USD' };
},
{
name: 'check_balance',
description: 'Check the balance of a bank account.',
inputSchema: {
type: 'object',
properties: {
accountId: { type: 'string', description: 'The account ID to check' },
},
required: ['accountId'],
},
},
);
const lookupOrder = tool(
async (args: { orderId: string }) => {
return { order_id: args.orderId, status: 'shipped', eta: '2 days' };
},
{
name: 'lookup_order',
description: 'Look up the status of an order.',
inputSchema: {
type: 'object',
properties: {
orderId: { type: 'string', description: 'The order ID to look up' },
},
required: ['orderId'],
},
},
);
const getPricing = tool(
async (args: { product: string }) => {
return { product: args.product, price: 99.99, discount: '10% off' };
},
{
name: 'get_pricing',
description: 'Get pricing information for a product.',
inputSchema: {
type: 'object',
properties: {
product: { type: 'string', description: 'The product to get pricing for' },
},
required: ['product'],
},
},
);
// -- Specialist agents -------------------------------------------------------
export const billingAgent = new Agent({
name: 'billing',
model: llmModel,
instructions: 'You handle billing questions: balances, payments, invoices.',
tools: [checkBalance],
});
export const technicalAgent = new Agent({
name: 'technical',
model: llmModel,
instructions: 'You handle technical questions: order status, shipping, returns.',
tools: [lookupOrder],
});
export const salesAgent = new Agent({
name: 'sales',
model: llmModel,
instructions: 'You handle sales questions: pricing, products, promotions.',
tools: [getPricing],
});
// -- Orchestrator with handoffs -----------------------------------------------
export const support = new Agent({
name: 'support',
model: llmModel,
instructions:
'Route customer requests to the right specialist: billing, technical, or sales.',
agents: [billingAgent, technicalAgent, salesAgent],
strategy: 'handoff',
});
async function main() {
const runtime = new AgentRuntime();
try {
const result = await runtime.run(
support,
"What's the balance on account ACC-123?",
);
result.printResult();
// Production pattern:
// 1. Deploy once during CI/CD (optional -- serve() below also deploys):
// await runtime.deploy(support);
// CLI alternative:
// conductor deploy --package examples/agents --agents support
//
// 2. In a separate long-lived worker process (deploys + registers workers + starts polling):
// await runtime.serve(support);
} finally {
await runtime.shutdown();
}
}
main().catch(console.error);