构建 Agent
在不丢失语义的前提下流式输出
消费可见文本,同时保留推理、用量、警告与服务商事件。
流式执行为什么不同
流不是一串文本片段,而是正在发生的 Agent 执行循环。它包含模型增量、工具边界、 检索完成、用量更新、警告,以及一个最终结果。
需要降低首字延迟或展示实时进度时使用流;只关心完整结果时使用 prompt。
消费事件流
持续轮询直到流结束。每个项目都可能失败,因此必须处理 Result。
use futures_util::StreamExt;
use runifold::AgentStreamEvent;
let mut events = agent.stream("Explain the incident", &run);
while let Some(event) = events.next().await {
match event? {
AgentStreamEvent::Model { event, .. } => render_model_event(event),
AgentStreamEvent::UsageUpdated { usage } => update_usage(usage),
AgentStreamEvent::Completed { outcome } => save(outcome),
_ => {}
}
}业务层应处理服务商无关的 ModelStreamEvent,不要重复解析某家服务商的网络协议。
最终状态
不要通过拼接可见增量来重建最终答案。Completed 事件包含规范化的
AgentOutcome:最终响应、完整记录、计数器、警告与用量。
健壮的消费者会用通配分支兼容未来事件类型,并保证最终结果只持久化一次。
取消与断开连接
浏览器断开并不自动决定服务端任务是否继续。你需要明确选择:取消
RunContext、脱离连接并持久化进度,或把工作交给持久工作流。
HTTP 场景下,SSE 适合浏览器文本;NDJSON 往往更适合服务间的类型化事件。传输 帧格式应与 Runifold 事件语义分离。