Skip to content

Agent Server

创建 Server

typescript
import { createAgentServer, type AgentConfig, type Context } from '@multi-agent/a2a'

async function executeHandler(params: { task: string }, ctx: Context) {
  ctx.stream.send({ type: 'progress', text: '执行中...' })
  ctx.stream.send({ type: 'done', text: '完成', data: { result: 'ok' } })
}

const config: AgentConfig = {
  agentId: 'my-agent',
  name: 'My Agent',
  version: '1.0.0',
  description: '我的 Agent',
  address: 'a2a://0.0.0.0:50061',
  skills: [
    { name: 'execute', description: '执行任务', handler: executeHandler },
  ],
  defaultSkill: 'execute',
}

const server = createAgentServer(config)
await server.start()

配置项

typescript
const config: AgentConfig = {
  // 必填
  agentId: 'my-agent',           // 唯一标识
  name: 'My Agent',              // 显示名称
  version: '1.0.0',              // 版本号
  description: '描述',            // 能力描述
  address: 'a2a://0.0.0.0:50061', // 监听地址
  skills: [...],                 // 技能列表
  defaultSkill: 'skillName',     // 默认技能

  // TLS 配置(可选,使用 a2as:// 时必填)
  tls: {
    cert: '/path/to/cert.pem',   // 证书文件路径
    key: '/path/to/key.pem',     // 私钥文件路径
    ca: '/path/to/ca.pem',       // CA 证书(可选)
  },
}

定义技能

基础用法

typescript
import { type Context } from '@multi-agent/a2a'

async function greetHandler(params: { name: string }, ctx: Context) {
  ctx.stream.send({
    type: 'done',
    text: '完成',
    data: { message: `Hello, ${params.name}!` },
  })
}

const config: AgentConfig = {
  // ...
  skills: [
    { name: 'greet', description: '问候', handler: greetHandler },
  ],
}

使用 Zod Schema

typescript
import { z } from 'zod'

const inputSchema = z.object({
  code: z.string().describe('代码'),
  language: z.enum(['js', 'ts', 'py']).default('js'),
})

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 config: AgentConfig = {
  // ...
  skills: [
    {
      name: 'execute',
      description: '执行代码',
      handler: executeHandler,
      inputSchema: z.toJSONSchema(inputSchema),
    },
  ],
}

流式输出

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

读取 Metadata

typescript
async function taskHandler(params: any, ctx: Context) {
  const userId = ctx.getMetadata<string>('x-user-id')
  const traceId = ctx.getMetadata<string>('x-trace-id')
  // ...
}

处理取消

typescript
async function longTaskHandler(params: { items: string[] }, ctx: Context) {
  for (const item of params.items) {
    if (ctx.signal.aborted) return  // 提前退出
    await process(item)
    ctx.stream.send({ type: 'progress', text: `处理: ${item}` })
  }
  ctx.stream.send({ type: 'done', text: '完成' })
}

Server API

typescript
const server = createAgentServer(config)

await server.start()      // 启动
await server.shutdown()   // 关闭

server.use(plugin)        // 注册插件

使用插件

typescript
import { createAgentServer, createTracingPlugin } from '@multi-agent/a2a'

const server = createAgentServer(config)
  .use(createTracingPlugin({ provider: tracingProvider }))

await server.start()

TLS 配置

当 Agent 需要被 HTTPS 页面调用时,必须启用 TLS。详见 TLS 配置

MIT Licensed