把 Claude 用于长周期 Agent 任务,有一类问题几乎是必然出现的:任务跑到中途,Claude 开始”忘事”。它忘了第一步约定的格式规范,忘了某个已经确认过的业务规则,忘了三轮前你特别强调的约束条件。任务的方向越来越模糊,输出质量开始下滑,到最后你甚至不确定它还记不记得这个任务的核心目标。

上下文丢失不是 Claude 的能力问题,而是大语言模型在超长上下文中的固有特性——随着内容累积,早期信息的权重自然衰减。但这个问题可以通过架构和提示词设计大幅缓解。

本文由 Claude Ai中文官网 整理,提供 6 个在真实 Agent 项目中验证过的实用技巧,每个技巧都附上可直接复用的代码或提示词模板。

本文面向通过 Anthropic API 构建 Agent 的开发者,以及通过 Claude Code 执行长任务的用户。部分技巧同样适用于在 claude.ai 中进行长对话的场景。

一、先理解:上下文是怎么丢失的

有针对性地解决问题之前,先搞清楚上下文丢失的三种模式,因为不同模式需要不同的应对策略。

模式 A:早期信息权重衰减。这是最常见的模式。你在任务开始时定义的规则和约束,随着对话轮次增加被越来越多的中间内容”稀释”,Claude 对它们的关注度自然降低。表现为:任务运行到中后期,输出开始偏离最初定义的规范。

模式 B:工具调用结果噪音积累。Agent 每次调用工具(搜索、数据库、API),返回结果都会进入上下文。随着调用次数增加,大量已经处理过的结果堆积在上下文里,形成”噪音”,稀释了真正重要的信息密度。表现为:Claude 在后续步骤中引用了本该已经忽略的旧信息。

模式 C:多步推理中的误差传播。某个中间步骤的轻微偏差被后续步骤当作事实接受,误差逐步放大。表现为:任务方向逐渐漂移,每一步看起来都合理,但整体已经偏离了目标。

以下 6 个技巧分别针对这三种模式设计。

二、技巧 1:把核心约束放进永久性系统提示词

解决的问题:模式 A(早期信息权重衰减)

最简单也最有效的技巧:把任务中不会改变的核心约束,从对话历史里抽出来,放进系统提示词(system prompt),并通过 Prompt Caching 让它在每次调用中权重最高。

系统提示词在模型处理时享有天然的”前置优先级”,不会被对话历史的增长所稀释。只要任务继续,这些约束就永远在最高权重的位置。

import anthropic

client = anthropic.Anthropic()

# 把核心约束单独抽出来,放进系统提示词并缓存
CORE_CONSTRAINTS = """
【任务核心约束——始终遵守,不受对话内容影响】

1. 输出格式:所有代码块必须有语言标注,所有列表使用 Markdown 格式
2. 数据来源:只引用用户提供的文件,不使用外部推断
3. 不可做的事:不生成任何个人身份信息,不猜测缺失的数据
4. 错误处理:遇到不确定的情况,先说明"我不确定",再给出建议
5. 任务边界:只处理与当前任务直接相关的内容,不做范围外的延伸

在每次响应之前,先检查你的计划是否违反以上任何一条约束。
"""

def call_agent_with_stable_constraints(
    task_context: str,
    conversation_history: list[dict],
    current_user_message: str
) -> str:
    """
    每次调用都携带不变的核心约束作为系统提示词(缓存),
    同时携带动态的对话历史和当前消息。
    """
    response = client.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=4096,
        system=[
            {
                "type": "text",
                "text": CORE_CONSTRAINTS,
                "cache_control": {"type": "ephemeral"}  # 缓存核心约束
            },
            {
                "type": "text",
                "text": f"当前任务背景:\n{task_context}"
                # 任务背景如果不变,也可以加缓存
            }
        ],
        messages=conversation_history + [
            {"role": "user", "content": current_user_message}
        ]
    )
    return response.content[0].text

什么内容适合放进系统提示词:

  • 格式规范(输出格式、命名约定、结构要求)
  • 绝对禁止项(不能做的事)
  • 任务边界(超出范围的请求如何处理)
  • 错误处理规则(不确定时怎么办)

什么不适合放进系统提示词:会随任务进展变化的状态(已完成的步骤、中间结果、当前进度)——这些应该用下面的技巧处理。

三、技巧 2:定期压缩对话历史,而不是无限追加

解决的问题:模式 A + 模式 B

对话历史无限增长是上下文丢失最直接的原因。每隔固定的轮次,对已经完成的对话部分做一次压缩摘要,用摘要替换原始内容。这样上下文长度保持在可控范围内,同时关键信息得以保留。

def compress_conversation_history(
    history: list[dict],
    keep_recent_n: int = 6,
    compress_threshold: int = 20
) -> list[dict]:
    """
    当对话历史超过阈值时,压缩早期部分为摘要。
    始终保留最近 N 轮对话的完整内容。
    """
    if len(history) <= compress_threshold:
        return history  # 未达到压缩阈值,原样返回

    # 分割:需要压缩的旧内容 + 保留的近期内容
    to_compress = history[:-keep_recent_n]
    recent = history[-keep_recent_n:]

    # 将旧内容格式化为可压缩的文本
    history_text = "\n\n".join([
        f"[{msg['role'].upper()}]: {msg['content'][:500]}..."
        if len(msg['content']) > 500
        else f"[{msg['role'].upper()}]: {msg['content']}"
        for msg in to_compress
    ])

    # 调用 Claude 生成摘要(用轻量模型节省成本)
    summary_response = client.messages.create(
        model="claude-haiku-4-5",  # 用轻量模型做摘要
        max_tokens=600,
        messages=[{
            "role": "user",
            "content": f"""请将以下对话历史压缩为简洁摘要。

保留:
- 已完成的关键操作和决策
- 重要的中间结论
- 后续步骤需要参考的信息
- 约定的规则或格式变更

去除:
- 过程细节和中间推理步骤
- 已经不再相关的工具调用结果
- 重复的确认和回应

摘要控制在 300 字以内。

对话历史:
{history_text}"""
        }]
    )

    summary = summary_response.content[0].text

    # 用摘要替换旧内容,作为对话历史的第一条消息
    compressed_history = [
        {
            "role": "user",
            "content": f"[对话历史摘要(已压缩)]\n{summary}"
        },
        {
            "role": "assistant",
            "content": "明白,我已了解之前的进展,继续执行当前任务。"
        }
    ] + recent

    return compressed_history

压缩时机的建议:

  • 每 15–20 轮对话压缩一次(根据每轮消息的平均长度调整)
  • 在开始一个新的任务阶段之前主动压缩,把旧阶段的内容归档
  • 当你感知到 Claude 开始”遗忘”早期约定时,立即手动触发压缩

四、技巧 3:把任务状态外化到结构化存储

解决的问题:模式 B + 模式 C

不要让 Claude 的上下文承担”任务状态数据库”的职责。把任务的完成进度、中间结果、待处理项,存到外部结构化存储(文件、数据库、Redis),每次调用 Claude 时只传入当前步骤真正需要的状态子集。

import json
from pathlib import Path
from datetime import datetime

class AgentStateStore:
    """
    Agent 任务的外部状态存储。
    Claude 的上下文只看到精选的状态快照,不是全部历史。
    """

    def __init__(self, task_id: str, store_path: str = "./agent_states"):
        self.task_id = task_id
        self.path = Path(store_path) / f"{task_id}.json"
        self.state = self._load()

    def _load(self) -> dict:
        if self.path.exists():
            with open(self.path) as f:
                return json.load(f)
        return {
            "task_id": self.task_id,
            "objective": "",
            "completed_steps": [],
            "pending_steps": [],
            "key_findings": [],      # 重要发现,后续步骤需要参考
            "decisions_made": [],    # 已做的关键决策
            "current_step": None,
            "artifacts": {},         # 中间产物(文件路径等)
            "created_at": datetime.now().isoformat()
        }

    def save(self):
        self.path.parent.mkdir(parents=True, exist_ok=True)
        with open(self.path, 'w') as f:
            json.dump(self.state, f, ensure_ascii=False, indent=2)

    def complete_step(self, step: str, result_summary: str):
        """标记步骤完成,只保存结果摘要而非全文"""
        self.state["completed_steps"].append({
            "step": step,
            "summary": result_summary,  # 摘要,不是全文
            "completed_at": datetime.now().isoformat()
        })
        if step in self.state["pending_steps"]:
            self.state["pending_steps"].remove(step)
        self.save()

    def add_key_finding(self, finding: str, relevant_to: list[str] = None):
        """记录重要发现,标注与哪些后续步骤相关"""
        self.state["key_findings"].append({
            "finding": finding,
            "relevant_to": relevant_to or [],
            "added_at": datetime.now().isoformat()
        })
        self.save()

    def get_context_for_step(self, current_step: str) -> str:
        """
        为当前步骤生成精选的上下文摘要。
        只包含与当前步骤真正相关的信息,不是全量历史。
        """
        # 找出与当前步骤相关的 key findings
        relevant_findings = [
            f["finding"] for f in self.state["key_findings"]
            if not f["relevant_to"] or current_step in f["relevant_to"]
        ]

        # 只展示最近 5 个已完成步骤的摘要
        recent_completed = self.state["completed_steps"][-5:]

        context = f"""【任务目标】
{self.state['objective']}

【已完成步骤(最近 5 个)】
{chr(10).join(f"✓ {s['step']}:{s['summary']}" for s in recent_completed) or "(无)"}

【关键发现(与当前步骤相关)】
{chr(10).join(f"• {f}" for f in relevant_findings) or "(无特别相关的发现)"}

【已做的关键决策】
{chr(10).join(f"• {d}" for d in self.state['decisions_made'][-3:]) or "(无)"}

【当前步骤】
{current_step}
"""
        return context

使用这个状态存储的关键原则:进入 Claude 上下文的不是原始数据,而是经过筛选的相关摘要。 一个完整的工具调用返回结果可能有 5000 字,但进入后续步骤上下文的只需要 2–3 行关键发现。

五、技巧 4:工具调用结果的即时精炼

解决的问题:模式 B(工具调用结果噪音积累)

每次工具调用返回结果后,不要直接把原始结果放进下一次调用的上下文——先做一次精炼,只保留对后续步骤有价值的部分。

def refine_tool_result(
    tool_name: str,
    raw_result: str,
    current_objective: str,
    max_output_tokens: int = 200
) -> str:
    """
    对工具调用的原始结果做即时精炼。
    只保留对当前目标有价值的信息。
    """
    if len(raw_result) < 500:
        return raw_result  # 结果足够短,直接使用

    response = client.messages.create(
        model="claude-haiku-4-5",  # 轻量模型快速精炼
        max_tokens=max_output_tokens,
        messages=[{
            "role": "user",
            "content": f"""从以下 {tool_name} 的返回结果中,
提取与以下目标最相关的关键信息:

目标:{current_objective}

工具返回结果:
{raw_result[:3000]}  # 截取前 3000 字避免精炼本身也超长

要求:
- 只保留与目标直接相关的信息
- 去除冗余的格式信息和不相关内容
- 用简洁的要点格式呈现
- 控制在 {max_output_tokens // 4} 字以内"""
        }]
    )
    return response.content[0].text


# 在 Agent 循环中使用
def agent_step_with_refined_tools(
    current_objective: str,
    tool_call_result: dict
) -> str:
    tool_name = tool_call_result["tool"]
    raw_result = tool_call_result["result"]

    # 精炼工具结果
    refined = refine_tool_result(
        tool_name=tool_name,
        raw_result=raw_result,
        current_objective=current_objective
    )

    # 进入上下文的是精炼后的结果,不是原始结果
    return f"[{tool_name} 结果摘要]\n{refined}"

哪些工具调用结果最需要精炼:

  • 搜索引擎返回:通常包含大量不相关的页面摘要
  • 数据库查询返回:原始数据往往远多于实际需要的字段
  • 网页内容抓取:HTML 解析后的文本通常包含大量导航栏、广告等噪音
  • 大文件读取:只需要文件的相关部分,不需要全文

六、技巧 5:显式的阶段切换和状态重置

解决的问题:模式 A + 模式 C

长周期任务通常有自然的阶段划分(调研阶段 → 分析阶段 → 实现阶段 → 验证阶段)。在阶段切换时,不要无缝继续,而是做一次显式的”状态重置”:用一条消息总结上一阶段的关键产出,明确声明进入新阶段,并在新阶段的第一条系统消息中重申核心约束。

def transition_to_new_phase(
    state_store: AgentStateStore,
    completed_phase: str,
    next_phase: str,
    phase_deliverables: dict
) -> list[dict]:
    """
    显式地切换任务阶段,重置上下文焦点。
    返回新阶段的初始对话历史(干净的起点)。
    """

    # 保存阶段产出到外部存储
    state_store.state["artifacts"][completed_phase] = phase_deliverables
    state_store.state["completed_steps"].append({
        "step": f"完成阶段:{completed_phase}",
        "summary": f"产出:{', '.join(phase_deliverables.keys())}",
        "completed_at": datetime.now().isoformat()
    })
    state_store.save()

    # 生成阶段交接摘要
    handoff_summary = f"""
【阶段交接摘要】

已完成阶段:{completed_phase}
主要产出:
{chr(10).join(f"- {k}:{str(v)[:100]}..." for k, v in phase_deliverables.items())}

关键决策和发现:
{chr(10).join(f"- {d}" for d in state_store.state['decisions_made'][-5:])}

即将进入阶段:{next_phase}
"""

    # 新阶段以干净的对话历史开始,只包含交接摘要
    # 不携带上一阶段的完整对话历史
    new_phase_history = [
        {
            "role": "user",
            "content": handoff_summary + f"\n\n请确认你已了解上一阶段的产出,并准备开始 {next_phase} 阶段。"
        },
        {
            "role": "assistant",
            "content": f"已了解。{completed_phase} 阶段的关键产出已记录。现在开始 {next_phase} 阶段,将基于以上产出继续推进。"
        }
    ]

    return new_phase_history

为什么这很重要:不做显式切换,对话历史会把两个阶段的内容混合在一起,Claude 在新阶段的工作中可能受到旧阶段噪音的干扰。显式切换相当于给 Claude 一个”清空黑板,重新开始”的信号,但关键成果通过交接摘要传递,不会丢失。

七、技巧 6:在关键节点插入”上下文确认”

解决的问题:所有三种模式的主动预防

在执行关键操作之前,主动让 Claude 复述它对任务的理解——不是为了让它”再想一想”,而是作为一个早期预警机制:如果它复述出来的和你预期的不一样,说明上下文已经出现了漂移,现在修正比发现输出错误后再修正成本低得多。

CONTEXT_CHECK_PROMPT = """在执行下一步之前,请先确认你对以下内容的理解:

1. 当前任务的核心目标是什么?(一句话)
2. 你即将执行的操作是什么?
3. 这个操作完成后,下一步是什么?
4. 有没有任何约束条件你需要在这个操作中特别注意?

确认完成后再执行。"""


def run_with_context_check(
    agent_fn,
    check_every_n_steps: int = 8,
    current_step_number: int = 0,
    **kwargs
) -> str:
    """
    每隔 N 步插入一次上下文确认检查。
    """
    if current_step_number > 0 and current_step_number % check_every_n_steps == 0:
        # 插入确认检查
        check_response = agent_fn(
            user_message=CONTEXT_CHECK_PROMPT,
            **kwargs
        )

        print(f"\n[步骤 {current_step_number} - 上下文确认]\n{check_response}\n")

        # 在实际系统中,这里可以加一个人工确认的机会
        # 或者用另一个 Claude 调用来验证复述是否正确

    return agent_fn(**kwargs)

在 claude.ai 交互场景中的用法:如果你是通过界面手动进行长对话,可以每 10 条左右发一次这样的消息:

在继续之前,请用 3 句话告诉我:
1. 你对这个任务的当前理解
2. 你认为下一步应该做什么
3. 有没有任何你不确定的地方

不需要长篇大论,简洁准确地告诉我就好。

如果 Claude 的复述出现了任何偏差,立即在这一步修正,比等到 10 步后发现方向跑偏再回头要省很多时间。

八、组合使用:一个完整的长周期 Agent 架构

以上 6 个技巧不是独立的选项,它们设计来协同工作。把它们组合起来,是一套完整的长周期 Agent 稳定性架构:

class StableLongCycleAgent:
    """
    集成了上下文稳定性技巧的长周期 Agent。
    适用于预计运行超过 2 小时、包含多个阶段的复杂任务。
    """

    def __init__(
        self,
        task_id: str,
        core_constraints: str,
        task_objective: str
    ):
        self.task_id = task_id
        self.core_constraints = core_constraints
        self.state_store = AgentStateStore(task_id)
        self.state_store.state["objective"] = task_objective
        self.state_store.save()
        self.conversation_history = []
        self.step_counter = 0

    def execute_step(
        self,
        step_description: str,
        tool_results: Optional[list[dict]] = None
    ) -> str:
        self.step_counter += 1

        # 技巧 1:每次调用都携带核心约束(缓存)
        # 技巧 3:从外部状态存储获取精选上下文
        step_context = self.state_store.get_context_for_step(step_description)

        # 技巧 4:精炼工具调用结果
        refined_tool_content = ""
        if tool_results:
            refined_parts = [
                refine_tool_result(
                    tr["tool"], tr["result"],
                    step_description
                )
                for tr in tool_results
            ]
            refined_tool_content = "\n\n".join(refined_parts)

        # 技巧 6:每 8 步插入上下文确认
        if self.step_counter % 8 == 0:
            check_message = step_context + "\n\n" + CONTEXT_CHECK_PROMPT
        else:
            check_message = step_context
            if refined_tool_content:
                check_message += f"\n\n【工具返回(已精炼)】\n{refined_tool_content}"
            check_message += f"\n\n请执行当前步骤:{step_description}"

        self.conversation_history.append({
            "role": "user",
            "content": check_message
        })

        # 技巧 2:超过阈值时压缩对话历史
        self.conversation_history = compress_conversation_history(
            self.conversation_history,
            keep_recent_n=6,
            compress_threshold=20
        )

        # 调用 Claude(技巧 1:核心约束在系统提示词里)
        response = client.messages.create(
            model="claude-sonnet-4-6",
            max_tokens=4096,
            system=[
                {
                    "type": "text",
                    "text": self.core_constraints,
                    "cache_control": {"type": "ephemeral"}
                }
            ],
            messages=self.conversation_history
        )

        result = response.content[0].text
        self.conversation_history.append({
            "role": "assistant",
            "content": result
        })

        return result

    def complete_step(self, step: str, result_summary: str):
        """记录步骤完成,更新外部状态"""
        self.state_store.complete_step(step, result_summary)

    def start_new_phase(
        self,
        completed_phase: str,
        next_phase: str,
        deliverables: dict
    ):
        """技巧 5:显式阶段切换,重置上下文"""
        self.conversation_history = transition_to_new_phase(
            self.state_store,
            completed_phase,
            next_phase,
            deliverables
        )
        self.step_counter = 0  # 重置步骤计数器

九、针对 claude.ai 网页端用户的简化版技巧

如果你不是通过 API 构建 Agent,而是在 claude.ai 的对话框里做长任务,以上技巧的简化版同样适用:

对应技巧 1(固定核心约束):在对话最开始发一条”任务说明”消息,把所有规则和约束列清楚。当对话变长后,如果发现 Claude 开始忘记规则,把这条消息的内容复制粘贴到新消息里,说”请重新确认以下规则仍然适用”。

对应技巧 2(压缩历史):当对话超过 20 轮,发一条消息:”请总结我们到目前为止完成的工作和关键结论,控制在 300 字以内。”然后把这个摘要复制保存,开启新对话时把它粘贴进去作为起点。

对应技巧 5(阶段切换):在切换任务阶段时,主动发一条消息:”好的,第一阶段完成。关键产出是:[列出产出]。现在进入第二阶段,目标是:[说明目标]。请确认理解后开始。”

对应技巧 6(上下文确认):每隔 10 条消息左右,发一次上面提到的确认提问,让 Claude 复述它的当前理解。

总结:6 个技巧的适用时机

技巧 主要解决的问题 实现成本 最适合的场景
核心约束进系统提示词 早期规则被遗忘 所有长任务,第一个该做的
定期压缩对话历史 上下文无限膨胀 超过 20 轮的多轮对话任务
状态外化到结构化存储 中间结果噪音积累 多步骤、有多种类型中间结果的任务
工具结果即时精炼 工具返回噪音积累 频繁调用外部工具的 Agent
显式阶段切换 跨阶段内容互相干扰 有明确阶段划分的长任务
上下文确认检查 所有模式的主动预防 关键操作前,或每隔 N 步

如果只能选一个:把核心约束放进系统提示词并缓存——这是成本最低、效果最直接的单一改进,能解决大多数长任务中”规则被遗忘”的问题。

如果要构建生产级的长周期 Agent:六个技巧组合使用,按照文中的架构示例实现。

更多关于 Claude Agent 开发的最佳实践和最新 API 功能说明,欢迎访问 Claude Ai中文官网 查阅持续更新的中文开发者文档。

上下文管理是 Agent 工程中被低估最多的问题。它不是”优化”,而是让长任务能够可靠完成的基础设施。把这 6 个技巧当作 Agent 设计的标配,而不是出了问题才想起来的补救措施。