我踩过的Agent harness几个坑:上下文越跑越慢

前阵子在写自己的agent harness,跑着跑着发现一个问题:上下文越跑越慢。

一开始以为是模型本身的问题,后来排查发现是harness工程上几个坑没填好。

今天把这几个坑写出来,给同样在写LLM应用的同学参考。

坑一:上下文膨胀------把所有历史都塞回去

一开始我写harness的时候,每次调模型都把全部历史对话塞进去。

短任务还好,跑个几十轮之后,上下文长度直接爆。模型处理变长的prompt,延迟指数上升,token成本也翻倍。

后来改了:

1、按消息类型分层------系统提示、用户输入、工具结果、助手回复,分开管理;

2、超过N轮就做摘要------把老的对话压缩成一段summary,而不是原样保留;

3、工具结果默认截断------长文本输出(比如文件内容、搜索结果)只保留前N个token,需要时再取。

代码示意:

python 复制代码
def trim_context(messages, max_tokens=8000):

while estimate_tokens(messages) > max_tokens:

if len(messages) > 4:

# 把中间几轮压成摘要

summary = summarize(messages[1:-2])

messages = [messages[0], {"role":"user","content":summary}] + messages[-2:]

else:

break

return messages

这个改完,上下文长度稳定了,延迟也降下来。

坑二:工具重试死循环------同一个错误反复调

有一次跑agent,发现它卡在一个工具调用上反复重试十几次。

原因很简单:工具返回错误,harness没有限制重试次数,模型就一直调一直错。

后来加了两层保护:

1、每个工具调用设重试次数上限(我设的3次),超过就把错误信息返回给模型,让它换思路;

2、错误分类------可重试错误(网络超时)和不可重试错误(参数错误)分开处理,后者直接告诉模型「这个调用失败了,换一个方法」。

python 复制代码
def call_tool_with_retry(name, args, max_retries=3):

for i in range(max_retries):

result = call_tool(name, args)

if not result.is_error:

return result

if is_non_retryable(result.error):

return result

return ToolError(f"工具{name}连续{max_retries}次失败,请换方案")

这个改完,死循环消失了,token成本也省了。

坑三:失败恢复------上下文断了不知道从哪续

跑长任务的时候,harness崩了或者超时了,下次启动不知道从哪续。

一开始我以为是加个checkpoint就行,后来发现没那么简单:

1、每轮对话结束后存一份快照------当前消息列表、工具调用记录、中间状态;

2、启动时检测快照,如果存在就让用户选择「从头跑」还是「从上次断点续」;

3、断点续的时候,把快照里的上下文重新喂给模型,让它知道「我们上次跑到哪了」。

lua 复制代码
def save_checkpoint(messages, state):

json.dump({"messages": messages, "state": state}, open("checkpoint.json","w"))

def load_checkpoint():

if os.path.exists("checkpoint.json"):

return json.load(open("checkpoint.json"))

return None

工程取舍:自研 vs 现成框架

现在主流的harness路线有几种:

1、纯自研------像我这样,从OpenAI SDK开始自己拼,灵活但坑多;

2、codex式------带工具调用、上下文管理、重试逻辑的现成框架;

3、harness式------更强调状态管理和多agent协作。

自研的好处是你完全知道每一步在干什么,坏处是所有坑都得自己踩。

现成框架好处是坑已经填了,坏处是你得适应它的抽象,有时候想做的事它不支持。

我的建议:如果是学习目的,自研一遍,把这几个坑都踩过;如果是生产环境,直接用成熟框架,别重复造轮子。

harness真正该抽象的是什么

不是把OpenAI SDK拼起来就完了。

harness的核心是:上下文管理、工具调用、错误恢复、状态持久化。

这四件事做好了,模型换成GPT、Claude、还是开源模型,都能跑。

这才是harness该抽象的层。

相关推荐
kaixin_啊啊39 分钟前
【零基础学AI】第 30 章——对话记录与结构化输出
人工智能
泯泷1 小时前
让知识"长骨架"——RAPTOR、GraphRAG 与 OpenViking(四)
人工智能·llm
kaixin_啊啊2 小时前
【零基础学AI】第 30 章课后练习与答案
人工智能
电科_银尘2 小时前
【深度学习项目实战·33】自定义数据集:把自己的图片接入PyTorch
人工智能·pytorch·深度学习
武子康2 小时前
单卡 A6000 跑 Qwen-Drive:怎样留下可比较的第一条基线?
linux·人工智能·深度学习
严肃小白兔2 小时前
第 06/24 期:神经网络的反向传播算法:从链式法则到梯度计算
人工智能·神经网络·算法
后端小肥肠3 小时前
公众号漫画又挖到长尾赛道:家常菜美食,流量稳定长期有收益
人工智能·aigc·agent
泯泷3 小时前
从"检索管道"到"主动助理"——Agentic RAG 与双层记忆(五)
人工智能·llm·agent