ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

情感智能嵌入Agent Harness:下一代Agent系统的核心工程

情感智能嵌入Agent Harness:下一代Agent系统的核心工程

做Agent系统这行做得久了,你会发现一个很有意思的现象:模型本身越来越会“说话”了,但Agent整体给人的感觉还是“聪明有余,温度不足”。尤其是涉及到客服、教育、医疗这些需要对用户情绪做出反馈的场景,用户明明已经着急上火了,Agent还在冷冰冰地报菜单。这个问题我琢磨了很久,结论是:问题往往不在模型,而在Agent外面的那层运行时框架——也就是Agent Harness。

我一直在想,下一代Agent Harness的核心竞争力到底是什么。现在比较明确的答案是情感智能。这不是指给模型加几句“你要温柔一点”的提示词,而是把情绪信号的感知、理解、表达和反馈,作为像上下文管理、记忆读写一样的底层能力,直接嵌进Harness里。这篇文章我就从工程落地的角度,拆一拆情感智能为什么必须进入Harness、进去了之后该怎么设计,以及我在实际项目里踩过的坑。

1. 为什么情感智能必须进 Harness,而不是贴在对话层

1.1 Agent 的“情商”瓶颈不在模型,在运行时

先澄清一个常见误区:很多人觉得让Agent有情商,就是在提示词里写“请用温和友善的语气回复用户”,或者在模型层换成更大的底座。这两招不是完全没用,但都解决不了核心问题。

我自己做过一个客服场景的Agent项目,一开始也是这么干的。业务方说用户反馈“Agent太生硬”,我们就让大模型把回复写得更委婉,结果上线之后效果确实好了一点,但很快暴露了新问题:用户说“我快崩溃了”,Agent确实用很温柔的话去安慰了,但安慰完还在走标准流程、问“请问您还有什么其他问题”,完全没判断出用户情绪已经到了需要特事特办的级别。这就是典型的“语气对了,判断错了”。

问题出在哪?出在运行时。模型是一个纯粹的文本生成器,它能在生成每一句话时考虑语气,但它没有一个稳定的机制去回答一个问题:用户当前处于什么情绪状态?这个情绪状态在整段对话里是怎么变化的?这次的负面情绪是因为什么事件触发的?没有这个机制,Agent表现出来的“高情商”就全靠临场发挥,时灵时不灵。

打个比方,模型是发动机,Harness是整车的底盘和控制系统。发动机性能再强,没有一套好的悬架和转向系统,过弯的时候照样翻车。情感智能就应该是悬架和转向的一部分,而不是贴在外面的一个装饰件。

1.2 Harness 是情绪信号的“高速公路”

那Agent Harness到底是什么?你可以把它理解成Agent的“驾驶舱”和“总控台”——模型之外的那一层代码逻辑,负责会话状态管理、上下文组织、工具调用调度、记忆读写、策略路由。大模型本身是不保留对话状态的,它每一次生成都是“一次性”的;让Agent表现出跨轮次记忆、会调用工具、能做出复杂决策的,就是Harness。

这一层框架,天然就是情绪信号流通的“高速公路”。用户的情绪必须经过这里,才能被记录下来、被跨轮次追踪、被用来调整后续策略。如果情感智能不放在这一层,而是放在对话层做一次性判断,那么:

  • 会话状态管理不知道用户情绪在持续恶化,仍然按正常流程走;
  • 记忆系统不会把“这次不愉快的经历”标注成影响未来互动的负面事件;
  • 策略路由不会因为用户处于愤怒状态就减少不必要的确认环节;
  • 工具调度不会在高压力场景下优先选择低摩擦的解决路径。

所以我的观点很明确:下一代Agent系统和上一代的区别,不是模型更强,而是Harness把情感智能内化成了基础设施。就好像智能手机和功能机的区别,不只是多了个触摸屏,而是整个操作系统都围绕触摸交互重构了。

2. 情感智能在 Harness 里的四层解剖

2.1 感知层:情绪信号的结构化捕捉

情感智能进Harness,第一步是感知。感知层要回答的问题是:用户当前的对话内容、交互行为中,包含哪些情绪信号,信号的强度有多大。

我建议不要把情绪简单地分成“正面的”“负面的”“中性的”,这个粒度太粗,对策略选择的指导意义很弱。更实用的做法是采用“效价-唤醒度”两个维度来描述情绪状态:效价表示情绪的积极程度,范围可能是-1到1;唤醒度表示情绪的强烈程度,范围是0到1。比如“有点不满”可能是效价-0.3、唤醒度0.4,“愤怒”则是效价-0.8、唤醒度0.9。加上具体的情绪标签,比如“困惑”“沮丧”“焦急”“失望”,就足够支撑后续的策略路由了。

感知层的输入不只有文本。用户连续输入“这到底怎么回事”“怎么又不行了”,输入速度、重复次数、停顿时长,这些都是高唤醒度的信号。在多模态场景下,语音的语调、语速、音量也能提供很丰富的信息。

具体落地的时候,不建议一开始就上多模态,成本太高。先做文本维度就够用:在Harness的请求入口加一个异步的情绪识别服务,把当前用户消息和最近几轮上下文一起送进去,输出情绪标签、效价、唤醒度、置信度。这里有一个关键点:情绪信号不要写死在数据库里就完事,而是要作为当前会话请求的元数据,在Harness内部流转,供后续所有模块使用。

2.2 认知层:情绪到策略的映射

感知层告诉我们用户“是什么情绪”,但没告诉我们“为什么会有这个情绪”,更没告诉我们“接下来该怎么办”。这个就交给认知层处理。

我见过不少团队在做情感智能的时候,直接把“情绪识别结果”映射到“回复模板”:检测到用户生气,就回复“非常抱歉给您带来了不好的体验”。这种做法的问题非常大,因为同样的情绪在不同场景下,对应的处理策略天差地别。

举个例子,用户说“你们这个功能怎么这么难用”,如果是从没使用过的新手,那他的“愤怒”其实是对自己的“沮丧”,需要的是引导和鼓励;如果是用了很久的老用户,那他的“愤怒”是对产品设计本身的不满,需要的是共情和转给产品团队;如果用户正赶着处理一个重要任务,他的“愤怒”是对时间损耗的抗拒,这个时候你跟他道歉、共情,他只会更加烦躁,他最需要的是“快速解决方案”。

所以认知层的核心工作叫“情绪归因”。它要结合当前的任务状态、用户历史画像、该轮对话的触发事件,判断情绪的来源,然后输出一个“策略意图”。认知层的产物不再是一个情绪标签,而是一个类似“用户因操作失败而产生沮丧,需要优先恢复其完成任务的信心,并提供低门槛的行动入口”这样的结构化判断结果。

从实现上讲,认知层可以做成一套规则引擎加一个轻量分类模型:规则引擎负责处理常见的、明确的场景(比如用户连续遇到报错),分类模型负责处理更复杂的、需要语义理解的场景(比如用户反讽、暗示)。两者结合,比单靠大模型硬猜要稳定得多。

2.3 表达层:策略的生成与抑制

有了策略意图,表达层负责把它变成真正的回复约束。这里说的“约束”不等于具体的回复话术,而是给生成模型限定的一组条件,比如:

  • 共情深度:是简单表达理解,还是需要深入承认用户的挫折感;
  • 解释密度:尽量少用术语,用大白话讲清楚;
  • 行动项数量:给用户提供的下一步操作选项不要超过多少个;
  • 道歉频次:整段回复中道歉最多出现几次;
  • 结构优先级:先给解决方案,还是先给予情绪支持。

为什么强调“约束”而不是“话术模板”?因为话术模板是死的,容易显得机械,而且不同场景的组合是无限的。生成约束则是在不牺牲自然度的前提下,把大模型的输出往正确的方向引导。

有一个点很容易被忽略:表达层不只是“生成”,还要负责“抑制”。在某些场景下,用户需要的不是安慰,而是方案;过度共情反而会拉长对话、消耗耐心。比如用户发了一句“帮我查下订单号,快点”,这个时候你说“我完全理解您现在焦急的心情,非常抱歉让您久等了”,然后再慢慢引导操作,用户大概率会更烦。合理的策略应当是:用半句话表达理解,立刻进入查单过程。这个“少说话”的动作,也必须由表达层通过约束来控制。

2.4 反馈层:闭环调节

情感智能落地到最后,一定要形成闭环。用户的情绪被识别、被处理、得到回复之后,其后续行为本身就是最好的反馈信号。

如果收到安抚后用户语气变得缓和,说明策略有效;如果用户仍然重复同样的问题,或者直接要求转人工,说明策略没打准。这些反馈信号要回到Harness,用来做三件事:一是实时调整当前会话的情绪状态槽;二是离线记录策略效果,为后续优化提供数据;三是在策略置信度较低,或者负面情绪持续升级时,触发升级机制(比如转人工)。

反馈层让我感触最深的一点是:不要指望一次判断就能做对。情感其实是动态的,用户的情绪会在对话过程中波动,可能从平静变成不满,再从不满变成接受。Harness如果能跟踪这个变化曲线,比单独一次准确的判断有价值得多。

3. 把情感智能真正装进 Harness:实操设计

3.1 在既有 Harness 流程中插入情感节点

聊完理论,说点能直接动手做的。假设你已经有一个可运行的Agent Harness,里面包含请求解析、上下文管理、策略路由、模型调用这几个基本模块,现在要把情感智能插进去。

我比较推荐的做法是,在请求解析之后增加一个“情感感知节点”,这个节点不是阻塞式的,而是异步并行地调用情绪识别服务,拿到结果后回写到会话状态。主流程继续往下走,等到需要选择回复策略时,从会话状态里读取情绪信息,传递给策略路由。

async def handle_user_message(harness, user_input, session): # 1. 情感感知(异步,不阻塞主流程) emotion_feature = await harness.emotion_service.analyze( user_input, session.recent_context() ) # 2. 更新会话状态中的情绪状态槽 session.emotion_state.update(emotion_feature) # 3. 结合任务状态和场景进行策略选择 context = harness.context_builder.build(session) strategy = harness.strategy_router.select( emotion=emotion_feature, task_state=session.task_state, scenario=session.scenario, user_profile=session.user_profile ) # 4. 在生成约束下调用大模型 reply = harness.llm.generate( user_input, context=context, generation_constraints=strategy.generation_constraints ) # 5. 反馈追踪(放入异步队列,不影响响应) harness.task_queue.submit("feedback_trace", session.id, reply) return reply

提示:情绪识别服务要做好超时和降级。如果这个服务挂了或者超时,不能让整个Agent的回复卡住。合理的做法是设置一个极短的超时时间(比如200毫秒),超时就返回“中性情绪”默认值,主流程照常执行。

这个设计的好处是侵入性很小,不需要推翻原有架构,只需要在策略路由处接收一个新的信号。而且因为情绪信息被写入了会话状态,所有下游模块都能读得到。

3.2 情绪识别服务怎么搭

情绪识别服务是感知层的具体实现,这个服务的搭建质量直接决定上层效果。我建议的方案是“轻量模型为主,大模型兜底”,而不是一刀切全部用大模型。

全部用大模型做情绪识别,效果确实不错,但成本高、延迟不可控。尤其在对话高频场景下,每个请求都多一次大模型调用,整体开销翻倍都不止。轻量文本分类模型(比如基于预训练模型微调的小模型)可以处理大部分常见情绪标签的识别,延迟在几十毫秒级别,成本也低得多。只有当轻量模型的置信度低于阈值时,才上报给大模型做更细致的判断。

我建议的情绪标签体系可以包含八个基础类别:平静、愉悦、期待、困惑、沮丧、失望、愤怒、焦虑。每个类别输出一个概率,取最高概率作为情绪标签,同时保留效价和唤醒度两个数值。这套体系覆盖了绝大多数服务场景,又不至于细碎到难以标注。

训练数据的获取有一个捷径:先跑一版规则版情绪识别(基于关键词和表情符号),把规则版判出来的情绪和上下文存成候选样本,再让人工基于对话历史做标注。这样人工只需要改“规则判错了”的样本,标注效率会高不少。如果你有历史客服对话记录,这一步是很好的资源和起点。

识别结果怎么用,也要有明确的策略。当置信度低于阈值(比如小于0.6)时,宁可不触发任何情绪策略,也不要用一个大概率错误的情感判断去影响回复。我管这个原则叫“宁缺毋滥”。

3.3 策略库怎么设计

策略库是认知层和表达层的中间载体。每一条策略描述的是:当某个情绪状态和某个场景条件匹配时,生成回复应该遵循什么样的约束。

我的做法是把策略写成结构化的配置项,由Harness在运行时加载。举个例子:

{ "scenario": "task_failure", "emotion": "frustrated", "intensity": "high", "strategy": { "type": "comfort_then_action", "priority": "task_completion", "constraints": { "empathy_level": 2, "apology_max_count": 1, "solution_first": true, "jargon_density": "low", "max_steps": 2 }, "fallback": "escalate_to_human" } }

这条策略的含义是:当用户处于“任务失败”场景且情绪是“高强度的沮丧”时,优先采用“先安抚再行动”的方式,回复中最多道歉一次、必须尽快给出解决方案、减少术语、把后续操作压缩到两步以内,如果用户仍然情绪强烈就转人工。

策略库不需要一开始就很庞大,先把最常见的几个场景覆盖掉,比如“操作失败”“等待过久”“诉求被拒绝”“信息难以理解”。每个场景配合两到三种情绪状态,总共也就二三十条策略。上线之后根据真实数据持续扩充。

策略库的设计过程中有一条原则值得反复强调:策略是给Harness和生成模型的约束,不是给用户的文案。你不需要把策略写得像人话,你需要把它写得像一份明确的行动指令。

4. Harness 架构如何被情感智能“重塑”

4.1 会话状态管理要新增“情绪状态槽”

传统Harness的会话状态里存的是对话历史、槽位信息、任务进度。情感智能落地之后,我强烈建议增加一个“情绪状态槽”,专门用来存放当前会话的情绪状态。

情绪状态槽不能只是一个字符串“frustrated”那么简单,它应该是一个结构化的对象,至少包含四项内容:

  • 当前情绪标签及其强度;
  • 效价和唤醒度数值;
  • 情绪趋势(是恶化、缓解还是平稳);
  • 最近一次情绪变迁的触发事件。
{ "user_id": "u_10023", "session_id": "s_89012", "emotion": "frustrated", "valence": -0.6, "arousal": 0.7, "trend": "rising", "trigger_event": "user_failed_step_3", "confidence": 0.82, "update_time": "2025-06-18T10:23:41Z" }

有了这个状态槽,跨轮次追踪才可以实现。比如用户在第一轮表现出“困惑”,第二轮变成“沮丧”,第三轮已经接近“愤怒”,这个趋势信号会让策略路由知道:普通的安抚话术已经不够了,需要直接转换处理方式,或者尽快转人工。

如果没有情绪状态槽,每一轮的情绪识别就都是孤立的,相当于每次都重新认识一个用户,情绪积累和爆发这个过程就完全察觉不到。很多同学说“Agent感觉不灵敏”,其实不是不灵敏,是根本没把情绪连起来看。

4.2 记忆层要增加情绪标注与衰减

长期记忆系统是另一个必须被情感智能改造的模块。让Agent记住“用户A曾经在某个功能上遇到过问题”,这很重要;但如果记成“用户A很讨厌这个功能”,这就危险了。

我建议在长期记忆里给每条关键事件加上情绪标注,但情绪标注必须和事实分开存,并且加上时间衰减。比如用户在某次会话里表达过强烈不满,这条记忆可以标记为“包含负面情绪事件”,但它在未来决策中的权重应该随时间自然衰减。一周后衰减到一半,一个月后衰减到接近零。不然就会出现一种很尴尬的情况:用户半年前发过一次火,此后每次正常使用Agent都会被特殊对待,对方体验反而很差。

衰减机制也不需要搞太复杂,一个简单的公式就能用:记忆权重 = 初始权重 × 衰减系数 ^(距今天数 / 半衰期天数)。把半衰期设成7天,负面情绪的记忆在两周后影响力就很弱了,这样既能保护“用户曾经受挫所以要更小心”的信息,又不会让用户被一张旧标签永远贴住。

还有一个细节:情绪标注不要写“用户是攻击型人格”这种对人的评价,而要写“当前主题在用户侧曾触发强烈负面反馈”。前者是归因于人,后者是归因于事件。这不仅是工程问题,也是产品价值观问题。

4.3 工具调用与延迟策略

情感智能还会影响Harness里的工具调度逻辑。传统Harness判断要不要调用某个工具,主要看任务是否需要。但加入情感维度之后,还需要考虑用户当前的情绪状态是否适合进行某一类操作。

高唤醒度的负面情绪(比如愤怒、焦虑)下,用户的耐心非常有限。这时候Harness应该自动切换到“快速通道”模式:减少不必要的二次确认、合并操作步骤、优先展示直接结果。比如用户在售卖系统里发起退款申请但一直失败,系统提示“您确定要申请退款吗?退款会需要1-3个工作日”,这个确认动作在平静状态下是合理设计,在愤怒状态下就是火上浇油。

更合理的做法是:识别到高唤醒负面情绪后,Harness将工具调用策略调整为“直达目标”:直接给出退款入口,自动预填已通过校验的信息,把需要用户确认的内容压缩到一项,并同时提示人工客服通道。用“减少摩擦”来应对“情绪升级”,这个思路在很多场景下都验证有效。

5. 常见问题与踩坑记录

5.1 操作误区:过度共情导致“假温情”

这是我见过最多的问题。情绪识别上线后,Agent开始对用户每一句话都表现得很关心,用户随便说一句“头晕”,它就说“很抱歉听到您不舒服,要不要休息一下”;用户说“功能太复杂”,它就“非常理解您的感受,这个设计确实不够友好”。时间一长,用户会觉得:“这个助手太假了。”

问题出在两个地方:一是没有区分情绪强度,轻微不满也被当作强烈负面情绪处理;二是共情动作没有分级,所有情绪触发同一档位的安慰。我建议对情绪强度和共情动作都做分级:低强度的负面情绪只做最低限度的共情,重心放在任务推进上;只有高强度的负面情绪才启用完整的情绪策略。真实的人和人交流也是这个逻辑,没有人会对朋友一句轻飘飘的抱怨每次都郑重道歉。

5.2 记忆层踩坑:情绪标签污染了事实记忆

有一次测试,我们的Agent在用户提了一个敏感操作后变得异常保守,连正常操作都不敢推荐,排查后发现记忆系统里有一条负面情绪事件和当前操作主题关联在一起。本来只是一次独立的失败经历,但在记忆检索时被当成了“这类操作都会让用户不满”的泛化结论。

后来我把“情绪事件记忆”和“事实偏好记忆”分成两个独立的存储空间和检索通道,主题重叠时,情绪事件只作为策略参考,不影响事实判断。这个拆分很关键。你可以把它理解成:知道用户上次在这个环节受挫过,但不要预设他这次还会受挫。

5.3 性能陷阱:情绪识别拖慢了主流程

早期版本里,我把情绪识别做成了主流程的同步调用,结果平均响应时间增加了差不多一位数,用户等得心焦,负面情绪更严重,形成一种恶性循环。后来把所有情绪识别服务改成异步并行,并设置超时降级,主链路完全不被拖累。这个改动上线后整个系统就稳了。

如果要再进一步优化,还可以做两层缓存:同一用户如果连续几条消息情绪稳定,就复用最近一次的情绪判断结果,不必每条消息都调用模型。多轮对话里用户往往是会连续说几句话的,中间的情绪没有突变,复用是合理的。

5.4 评测维度的缺失:只追识别准确率,不追策略效果

很多团队做情感智能,第一反应是先堆“情绪识别准确率”,在测试集上刷到很高,但上线之后业务指标没变化。原因很简单:情绪识别准确率高,不等于后续应对有效。

我建议建立两层评测体系。第一层是离线层,评估“策略路由准确率”——构造一批带标注的情绪对话场景,标注里写清楚“这种情况下应该采用什么样的应对策略”,然后看Harness选出来的策略和标注的一致性。第二层是在线层,看业务指标——用户满意度、问题解决率、因情绪问题升级人工的比例。在线层的效果才是最终标准。情感智能做得好的直接体现应该是:用户能更顺利地完成自己想做的事,而不是Agent说话说得多么动听。

最后再分享一个小技巧

我自己的习惯是,在正式做情感策略之前,先给Harness加一个“旁路情绪日志”通道。这个通道只做记录,不干预任何决策——每条用户消息进来,异步记录一下情绪识别结果、当时的策略选择、用户的后续行为。跑上一到两周,你手里就有了第一批真实数据,再基于这些数据去做策略,思路就会清晰很多,也不会凭空设计出一堆用不上的方案。

另一个经验是,情感智能的迭代不能只看对话记录,还要看产品本身能不能消化这个能力。用户情绪是在具体产品流程里产生的,如果流程本身太虐人,Agent再怎么安抚也只是缓兵之计。一个负责任的技术方案,应当既让Agent察觉情绪,又让产品能根据情绪信号把流程改顺。这两条腿并行,情感智能才真正能成为下一代Agent Harness的核心竞争力。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进