外观
Skill
定义技能
typescript
import { type Context } from '@multi-agent/a2a'
async function skillHandler(params: ParamsType, ctx: Context) {
// 处理逻辑...
ctx.stream.send({ type: 'done', text: '完成', data: { result } })
}
const config: AgentConfig = {
// ...
skills: [
{
name: 'skillName',
description: '技能描述',
handler: skillHandler,
inputSchema: z.toJSONSchema(paramsSchema), // 可选
},
],
}基础示例
typescript
async function greetHandler(params: { name: string }, ctx: Context) {
ctx.stream.send({
type: 'done',
text: '完成',
data: { message: `Hello, ${params.name}!` },
})
}使用 Zod 定义参数
typescript
import { z } from 'zod'
const inputSchema = z.object({
code: z.string().describe('代码'),
language: z.enum(['js', 'ts', 'py']).default('js'),
timeout: z.number().optional(),
})
type Input = z.infer<typeof inputSchema>
async function executeHandler(params: Input, ctx: Context) {
const result = await run(params.code, params.language)
ctx.stream.send({ type: 'done', text: '完成', data: { output: result } })
}
const skill = {
name: 'execute',
description: '执行代码',
handler: executeHandler,
inputSchema: z.toJSONSchema(inputSchema),
}Context 用法
typescript
async function taskHandler(params: any, ctx: Context) {
// 发送进度
ctx.stream.send({ type: 'progress', text: '处理中...' })
// 读取元数据
const userId = ctx.getMetadata<string>('x-user-id')
// 检查取消
if (ctx.signal.aborted) return
// 传递信号给下游
await fetch(url, { signal: ctx.signal })
ctx.stream.send({ type: 'done', text: '完成' })
}向用户提问
typescript
async function deployHandler(params: { app: string }, ctx: Context) {
ctx.stream.send({
type: 'question',
text: '选择环境',
data: { questionId: 'env', options: ['dev', 'prod'] },
})
let env = ''
for await (const msg of ctx.stream) {
if (msg.type === 'answer' && msg.data.questionId === 'env') {
env = msg.data.answer
break
}
}
await deploy(params.app, env)
ctx.stream.send({ type: 'done', text: '部署完成', data: { env } })
}流式输出
typescript
async function chatHandler(params: { message: string }, ctx: Context) {
let response = ''
for await (const chunk of llm.stream(params.message, { signal: ctx.signal })) {
response += chunk
ctx.stream.send({ type: 'progress', text: chunk })
}
ctx.stream.send({ type: 'done', text: '完成', data: { response } })
}ctx.signal
将 ctx.signal 传递给 LLM,用户取消时立即中断调用,避免不必要的 token 消耗。
多步骤任务
typescript
async function pipelineHandler(params: any, ctx: Context) {
const steps = ['分析', '规划', '执行', '验证']
for (let i = 0; i < steps.length; i++) {
if (ctx.signal.aborted) return
ctx.stream.send({
type: 'progress',
text: `步骤 ${i + 1}/${steps.length}: ${steps[i]}`,
data: { step: i + 1, total: steps.length },
})
await performStep(steps[i])
}
ctx.stream.send({ type: 'done', text: '完成' })
}调用其他 Agent
typescript
async function orchestrateHandler(params: any, ctx: Context) {
const chatClient = createAgentClient({
agentId: 'chat-agent',
address: 'a2a://localhost:50054',
})
const stream = await chatClient.call('chat', params, {
signal: ctx.signal,
metadata: { 'x-trace-id': ctx.getMetadata('x-trace-id') },
})
for await (const msg of stream) {
ctx.stream.send(msg) // 转发消息
}
}注册技能
typescript
const config: AgentConfig = {
agentId: 'my-agent',
name: 'My Agent',
version: '1.0.0',
description: '...',
address: 'a2a://0.0.0.0:50061',
skills: [skill1, skill2, skill3],
defaultSkill: 'skill1',
}获取技能信息
typescript
const card = await client.getAgentCard()
for (const skill of card.skills) {
console.log(`${skill.name}: ${skill.description}`)
}