Agent SDK
消息流与实时输出
消费文本、工具和终态消息,避免漏读、重复展示与误判完成。
从消息流构建界面
运行时返回的是带类型的事件序列,包含初始化、Assistant 内容、工具结果、进度和最终结果。ReceivedMessage.Type 负责分类,对应的指针字段可能为空,读取前需要判断。
下面是完整的单轮消费程序。它显示完整 Assistant 文本,并把最终结果作为任务是否结束的依据。
package main
import (
"context"
"fmt"
"log"
"time"
"github.com/nexus-research-lab/nexus-agent-sdk-bridge/client"
"github.com/nexus-research-lab/nexus-agent-sdk-bridge/protocol"
)
func run() error {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
defer cancel()
stream, err := client.Query(ctx, client.QueryRequest{
Prompt: "阅读 README.md,列出三个主要能力。",
Options: client.NewOptions().WithRuntime(client.RuntimeNXS).
WithCWD(".").WithTools("Read", "Glob", "Grep").
WithAllowedTools("Read", "Glob", "Grep"),
})
if err != nil { return err }
defer stream.Close(context.Background())
for {
message, err := stream.Recv(ctx)
if err != nil { return fmt.Errorf("收到最终结果前读取失败:%w", err) }
if message.Assistant != nil {
for _, block := range message.Assistant.Message.Content {
if text, ok := protocol.AsTextBlock(block); ok {
fmt.Println(text.Text)
}
}
}
if message.Type == protocol.MessageTypeResult {
if message.Result == nil { return client.ErrNoResult }
if message.Result.IsError {
return fmt.Errorf("任务失败:%s %v", message.Result.Subtype, message.Result.Errors)
}
fmt.Printf("完成,会话 %s,回合数 %d\n", message.SessionID, message.Result.NumTurns)
return nil
}
}
}
func main() {
if err := run(); err != nil { log.Fatal(err) }
}
选择展示粒度
完整 Assistant 消息适合聊天记录。需要逐字显示时启用 WithIncludePartialMessages(true),再处理 ReceivedMessage.Stream 中的增量事件。增量事件用于更新正在生成的气泡,完整消息用于确认最终内容;把两者都直接追加到记录,会出现重复文本。
工具内容可以通过 protocol.AsToolUseBlock、protocol.AsToolResultBlock 等辅助函数辨认。保留工具调用 ID,让结果归到对应调用,而不要按“上一条消息”猜测。工具执行过程中的进度消息可以更新状态,但不应把每次进度都永久保存为新的聊天气泡。
关联消息与任务
| 字段 | 宿主用途 |
|---|---|
SessionID | 找到运行时会话 |
UUID | 标识消息,支持记录与精确分叉 |
ParentToolUseID | 将子 Agent 输出归到父工具调用 |
ToolProgress | 更新正在运行的工具状态 |
TaskStarted、TaskProgress、TaskNotification | 跟踪后台任务的生命周期 |
RuntimeLifecycle | bridge 派生的生命周期事件,不是额外 wire 消息 |
Raw | 排错时核对原始字段,避免作为日常展示入口 |
未知消息类型不应使整个界面崩溃。可以保留诊断摘要并继续读取,直到明确终态或读取错误。不要把 Raw 整体发给浏览器;其中可能含有工具输入、路径或服务返回的数据。
终态与业务完成
result 标志本轮结束。先处理空 Result,再检查 IsError、Subtype、Errors 与 PermissionDenials。只有完成业务验收后,才把文件标为可交付,或让下游流程继续执行。
流提前出现 EOF 不等同于成功。使用 Stream.Result 时,bridge 会在没有终态的情况下返回 StreamClosedBeforeTerminalError 或底层退出错误;自行消费 Recv 时要保留相同判断。
流量与断开
输出读取不能长期被慢客户端阻塞。宿主可把界面进度合并后发送,但应保留最终结果和错误。每个会话只设一个读取者;连接断开后的恢复需要 Session ID 和会话策略,不是重新创建一个 Query 就能接续原任务。