Solon v4.0.4

team - TeamTrace 协作记忆与轨迹治理

</> markdown
2026年7月30日 下午5:28:18

在多智能体(Multi-Agent)协作中,如何让 Agent 知道"别人刚才说了什么"?如何统计整个团队的消耗?如何防止 Agent 之间陷入死循环?

TeamTrace 是 Solon AI 提供的协作轨迹模型。它像一个随身的"黑匣子",全程记录团队内部每个智能体的发言、耗时及决策路径。

1、自动收集原理:数据是怎么进来的?

开发者不需要手动为每个 Agent 写抓取代码。其核心秘密在于 Agent 接口的默认执行逻辑:

  • 环境感知:TeamAgent 启动时,会在工作流上下文(FlowContext)中埋入一个 _current_trace_key
  • 生命周期注入:每个 Agent 执行时,其 run 方法会自动完成以下操作:
    • 读记忆:从 TeamTrace 提取历史记录,拼接到当前 Prompt 中,让 Agent 拥有"全局视野"。
    • 记轨迹:执行完成后,自动调用 trace.addRecord(ChatRole.ASSISTANT, name(), content, duration),记录谁(Name)、说了什么(Content)、耗时多久(Duration)。

2、获取方式

从会话中提取"当前" TeamTrace

TeamTrace.getCurrent(session.getSnapshot());

从同步调用结果中获取

TeamResponse resp = agent.prompt("...").call();
TeamTrace trace = resp.getTrace();

从流式响应事件中获取

agent.prompt("...").stream()
    .doOnNext(event -> {
        if (event instanceof SupervisorDeltaEvent) {
            SupervisorDeltaEvent supervisorEvent = (SupervisorDeltaEvent) event;
            supervisorEvent.getTrace();
        }
    })
    .subscribe();

从拦截器中获取。具体参考拦截器资料。

3、示例参考:在自定义 Agent 中利用 TeamTrace

当你实现自定义 Agent 时,可以通过 TeamTrace 实现更复杂的逻辑判断,例如"根据前一个人的反馈来调整自己的策略"。

场景:一个负责"复核"的 Agent

public class ReviewAgent implements Agent {
    @Override
    public String name() { return "reviewer"; }

    @Override
    public AssistantMessage call(FlowContext context, Prompt prompt) throws Throwable {
        // 1. 获取当前 TeamTrace 实例
        TeamTrace trace = TeamTrace.getCurrent(context);

        if (trace != null) {
            // 2. 检查最近一次协作
            long duration = trace.getLastAgentDuration();

            // 如果前一个 Agent 耗时过短,可能产生了幻觉,要求重审
            if (duration < 1000) {
                // 通过协议上下文传递重审标记,让调度器知晓
                trace.getProtocolContext().put("needs_review", true);
            }

            // 3. 获取前一个 Agent 的输出作为上下文参考
            String lastContent = trace.getLastAgentContent();
            prompt = prompt.appendContext("上一个专家的输出: " + lastContent);
        }

        // 执行 LLM 调用
        return call(prompt);
    }
}

4、流式事件中的团队轨迹

在 TeamAgent 流式模式下,不仅会产生 Supervisor 调度决策事件,还会产生节点级生命周期事件:

事件类触发时机关键字段
TeamStartEvent团队协作任务开始时getTrace()
TeamEndEvent团队协作任务结束时,携带最终 TeamResponsegetResponse(), getTrace()
NodeStartEvent图节点(子 Agent)即将开始执行时getNode(), getTrace()
NodeEndEvent图节点(子 Agent)执行完毕,携带该 Agent 的输出消息getNode(), getTrace(), getMessage()
SupervisorDeltaEvent调度器(Supervisor)推理过程中产生流式内容getNode(), getTrace(), getResponse()

注意NodeChunk 已在 4.0.4 版本标记为 @Deprecated,请使用 NodeStartEvent / NodeEndEvent 替代。

从流式中获取团队轨迹的完整示例:

agent.prompt("策划一次团建活动").stream()
    .doOnNext(event -> {
        if (event instanceof TeamStartEvent) {
            TeamStartEvent e = (TeamStartEvent) event;
            System.out.println("🏁 团队任务开始: " + e.getTrace().getAgentName());
        } else if (event instanceof NodeStartEvent) {
            NodeStartEvent e = (NodeStartEvent) event;
            System.out.println("👤 专家开始工作: " + e.getNode().getId());
        } else if (event instanceof SupervisorDeltaEvent) {
            SupervisorDeltaEvent e = (SupervisorDeltaEvent) event;
            System.out.print(e.getResponse().getMessage().getContent()); // 调度器实时输出
        } else if (event instanceof NodeEndEvent) {
            NodeEndEvent e = (NodeEndEvent) event;
            System.out.println("✅ 专家完成: " + e.getNode().getId());
        } else if (event instanceof TeamEndEvent) {
            TeamEndEvent e = (TeamEndEvent) event;
            System.out.println("🎯 团队任务完成,最终答案: " + e.getMessage().getContent());
        }
    })
    .subscribe();

5、常用 API 快速查阅

分类方法返回类型功能描述
基础信息getOriginalPrompt()Prompt获取用户最初输入的任务指令。
getConfig()TeamAgentConfig获取当前团队的静态配置信息。
getSession()AgentSession获取当前协作关联的会话(持有 LLM 记忆)。
getProtocol()TeamProtocol获取当前团队的协作协议(如 NONE、SWARM 等)。
轨迹记录getRecords()List<TeamRecord>获取所有协作足迹(按时间排序的流水账)。
getRecordCount()int获取已执行的步骤(记录)总数。
addRecord(ChatRole, source, content, duration)void手动添加一条协作记录(非注入场景使用)。
getLastAgentContent()String快速提取最近一位专家 Agent 的输出内容。
getLastAgentDuration()long获取最近一位专家 Agent 的执行耗时(毫秒)。
逻辑治理getFormattedHistory()String获取 Markdown 格式的全量对话历史(含系统指令)。
getFormattedHistory(windowSize)String获取最近指定步数的对话历史,适合长任务摘要。
getFormattedHistory(windowSize, includeSystem)String可选择是否包含调度器系统指令。
getProtocolContext()Map获取协议私有上下文,用于传递结构化中间变量。
getProtocolDashboardSnapshot()String获取协议状态快照(JSON 格式),供 Agent 感知全局进度。
状态控制getTurnCount()int获取当前的协作轮数(迭代次数)。
nextTurn()int轮次递增(通常在调度器每一轮决策前自动调用)。
resetTurnCount()void重置轮次计数器。
getRoute() / setRoute()String获取或设置当前的路由指令(决策指向)。
isInitial()boolean判断是否初始状态(records 为空)。
结果与度量getFinalAnswer()String获取团队的最终输出答案。
setFinalAnswer(content)void设置最终答案,标志协作任务圆满完成。
getMetrics()Metrics获取整个团队的性能度量(耗时、Token 消耗)。

6、最佳实践提示

  • 内存与长度管理:对于超长对话,getFormattedHistory() 会产生巨大的字符串。如果 LLM 窗口受限,建议使用 getFormattedHistory(windowSize) 仅获取最近 N 步。
  • 结构化通信:如果你的团队在执行过程中需要传递中间变量(如:提取出的订单号),不要试图让下一个 Agent 去解析上一人的文本,直接使用 getProtocolContext().put(key, value) 更加可靠。
  • 如何获取实例?:
// 在任何能拿到 FlowContext 的地方执行
TeamTrace trace = TeamTrace.getCurrent(context);