外观
浏览器环境
导入
typescript
// 浏览器环境
import { createAgentClient } from '@multi-agent/a2a/browser'
// Node.js 环境
import { createAgentClient } from '@multi-agent/a2a'基本用法
typescript
import { createAgentClient } from '@multi-agent/a2a/browser'
const client = createAgentClient({
agentId: 'chat-agent',
address: 'a2a://localhost:50054',
})
const stream = await client.call('chat', { message: '你好' })
for await (const msg of stream) {
if (msg.type === 'progress') console.log(msg.text)
if (msg.type === 'done') console.log('完成:', msg.data)
}React 示例
tsx
import { useState, useRef } from 'react'
import { createAgentClient } from '@multi-agent/a2a/browser'
const client = createAgentClient({
agentId: 'chat-agent',
address: 'a2a://localhost:50054',
})
const Chat = () => {
const [messages, setMessages] = useState<string[]>([])
const [loading, setLoading] = useState(false)
const abortRef = useRef<AbortController | null>(null)
const send = async (text: string) => {
setLoading(true)
setMessages(prev => [...prev, `You: ${text}`])
abortRef.current = new AbortController()
const stream = await client.call('chat', { message: text }, {
signal: abortRef.current.signal,
})
let response = ''
setMessages(prev => [...prev, 'AI: '])
for await (const msg of stream) {
if (msg.type === 'progress') {
response += msg.text
setMessages(prev => [...prev.slice(0, -1), `AI: ${response}`])
}
}
setLoading(false)
}
const cancel = () => {
abortRef.current?.abort()
setLoading(false)
}
return (
<div>
{messages.map((msg, i) => <div key={i}>{msg}</div>)}
<input
onKeyPress={e => {
if (e.key === 'Enter') {
send(e.currentTarget.value)
e.currentTarget.value = ''
}
}}
disabled={loading}
/>
<button onClick={cancel} disabled={!loading}>取消</button>
</div>
)
}Vue 示例
vue
<script setup lang="ts">
import { ref } from 'vue'
import { createAgentClient } from '@multi-agent/a2a/browser'
const client = createAgentClient({
agentId: 'chat-agent',
address: 'a2a://localhost:50054',
})
const messages = ref<string[]>([])
const loading = ref(false)
const input = ref('')
let abortController: AbortController | null = null
const send = async () => {
if (!input.value.trim()) return
loading.value = true
messages.value.push(`You: ${input.value}`)
abortController = new AbortController()
const stream = await client.call('chat', { message: input.value }, {
signal: abortController.signal,
})
input.value = ''
let response = ''
messages.value.push('AI: ')
for await (const msg of stream) {
if (msg.type === 'progress') {
response += msg.text
messages.value[messages.value.length - 1] = `AI: ${response}`
}
}
loading.value = false
}
const cancel = () => {
abortController?.abort()
loading.value = false
}
</script>
<template>
<div>
<div v-for="(msg, i) in messages" :key="i">{{ msg }}</div>
<input v-model="input" @keypress.enter="send" :disabled="loading" />
<button @click="cancel" :disabled="!loading">取消</button>
</div>
</template>取消请求
typescript
const controller = new AbortController()
const stream = await client.call('chat', { message: 'Hi' }, {
signal: controller.signal,
})
// 取消按钮
cancelBtn.onclick = () => controller.abort()
for await (const msg of stream) {
if (msg.type === 'progress') console.log(msg.text)
if (msg.type === 'done') console.log(msg.data)
}
// 取消后循环正常退出传递 Metadata
typescript
const stream = await client.call('chat', { message: 'Hi' }, {
metadata: {
'x-user-id': 'user-123',
'x-session-id': 'session-abc',
},
})HTTPS 页面连接
HTTPS 页面必须使用 a2as:// 连接启用了 TLS 的 Agent。详见 TLS 配置。
与 Node.js 的区别
| 特性 | Node.js | 浏览器 |
|---|---|---|
| 协议 | gRPC | WebSocket |
| 导入 | @multi-agent/a2a | @multi-agent/a2a/browser |
| Server | 支持 | 不支持 |
| TLS | a2as:// → gRPC + TLS | a2as:// → wss:// |