Skip to content

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}`)
}

MIT Licensed