你把几十篇 Agent 博客收藏了一遍,看完每一篇都觉得"很有道理",合上页面却说不清自己到底学会了什么。

那是因为你一直在看"树",没看到"林"。

这篇文章是一张林的地图——把目录里那些博客(生产级 Agent、可观测性、上下文窗口、幂等、SSE、Redis、TTFT)和两个真实项目(Pi Agent Harness、Claude Code 会话式 CLI)串成一张总图,按设计问题、架构问题、安全问题、学习路线四个维度收拢,最后补一节从 Session 设计里提炼的硬需求与软实力。看完它,你再回头看任何一篇,都能说得出"它解决的是这条链路上哪一个问题"。


〇、一张总地图:一次 AI 请求,路过九站

先建全局直觉。一次 Agent 请求,从用户点下发送到最终答案流回屏幕,会路过下面这条链路的每一站。每一站都是一个问题域,每个问题域对应一篇博客或一个项目。

用户目标
   │
   ▼
① 上下文构建 ContextBuilder        ← 设计问题:Context 按编译产物来构建
   │  身份 → 检索 → 去重 → 排序 → 过滤 → Token 预算
   │  参考:LLM上下文窗口管理的四层工程防线
   ▼
② 模型调用 LLMGateway              ← 性能问题:首字延迟在这烧钱
   │  ← 参考:首字优化-思考博客(TTFT 六层)
   ▼
③ 工具执行 ToolGateway             ← 安全问题:权限要"结构上做不到"
   │  → PolicyEngine 风险分级/审批/Schema/限额
   │  参考:生产级Agent
   ▼
④ 流式返回 SSE                     ← 架构问题:流式链路的物理现实
   │  ← 参考:SSE双队列架构进化之路 / SSE深度解析
   ▼
⑤ 状态落盘 AgentRun / 幂等键        ← 架构问题:断电了还能续跑
   │  ← 参考:幂等性实战
   ▼
⑥ 全程可观测 Trace / Replay        ← 设计问题:先看见,再行动
   │  ← 参考:AI可观测性实战
   ▼
⑦ 跨进程共享 Redis                 ← 架构问题:多进程怎么安全共享状态
   │  ← 参考:Redis实战-AI工作流五个场景
   ▼
⑧ 经验晋升 Promotion               ← 治理问题:经验要过审才能成为规则
   │  ← 参考:生产级Agent 第七章
   ▼
⑨ Session(横切层,铺在每一站之下)  ← 设计+架构:Pi 的会话树 / CC 的对话上下文
   ├─ 执行记录(Pi:会话树 / 回退分支 / 版本化序列化)
   ├─ 上下文重建(compaction 检查点 / 记忆)
   └─ 隔离与干预(沙箱容器 / 权限模式 / 钩子 / 子代理)
   ← 参考:Pi Agent Harness / Claude Code 会话设计

把这张图压缩成一张"问题 → 博客/项目 → 一句话核心"的对照表,先记住整体:

问题域 博客 / 项目 一句话核心
设计 生产级Agent / 可控性 / AI可观测性 判断权归模型,执行权归系统
设计 LLM上下文窗口管理 Context 要按编译产物的标准构建
设计 幂等性实战 幂等是 Agent 的及格线
架构 SSE双队列进化之路 流式链路的关键在"队列 + 生命周期"管理
架构 Redis实战-AI工作流五场景 跨进程共享的每一步都要"原子"
架构 首字优化 性能要拉通整条链路看
安全 生产级Agent 第三章 / SSE深度解析 权限由结构保证,由协议选型配合
设计/架构 Pi Agent Harness / Claude Code 会话设计 Session 是横切一切状态的那一层
学习 上面全部 Agent 开发 = 后端工程基本功 + AI 特有的不确定性处理

下面几节,一节一个维度。每一节末尾都有一张可以直接拿去自检的清单。


一、设计问题:判断权归模型,执行权归系统

设计 Agent 最容易犯的第一个错,是把 Agent 当成"更聪明的提示词 + 更多工具"。

一旦一个 AI 系统拥有"调用工具、改数据"的能力,它就跨过了纯文本生成的边界,进入了**“运行一个程序”**的阶段(《生产级Agent》开场原话)。程序的经典毛病——断电、超时、重复执行、状态不一致——它一个都躲不掉。

从《生产级Agent》那篇里能提炼出六个设计原则,这就是设计问题域的全部骨架。

1.1 第一条边界:模型只建议,系统才执行

这是整张地图里最重要的一句话:

LLM 负责提出判断和计划,真正的系统负责控制它"能看到什么、能做什么、失败后怎么办"。

落地成代码,就是划四条业务代码不得越过的边界:AIApplicationService(编排)、ContextBuilder(上下文)、LLMGateway(模型)、ToolGateway(工具)。任何业务方法里直接 new OpenAIClient()、直接 noteRepository.delete()、直接绕过权限系统,都算设计事故。

模型在链路里只占中间小小一格。它的"想法"都以请求的形式发出去,由外面这一圈确定性的系统来裁决和落地。

1.2 Context 是编译出来的产物

初期的系统这么拼 Prompt:

系统提示词 + 用户问题 + 最近聊天记录 + 搜索到的笔记 + 用户资料 = 最终 Prompt

能跑。跑一段时间问题全冒出来:上下文越来越长、私密内容可能错误进入、新旧文档互相冲突、Token 成本失控、出错后谁也不知道模型当时看到了什么。

解法是《生产级Agent》第二章的 Context Compiler:把"拼接"变成一个带明确 stage 顺序的编译管道。顺序即策略——身份检查永远在最前,Token 预算永远在靠后:

身份权限 → 任务类型 → 知识检索 → 去重 → 相关度排序 → 新鲜度 → 敏感过滤 → Token 预算 → 压缩

配合《LLM上下文窗口管理》那篇的细节:预算不够先砍证据,不砍权限;降级链从低价值信息开始丢,先动免费的(截断),再动便宜的(摘要),最后才动贵的(让人介入)。这背后是经济账,跟心情无关。

1.3 一切操作有回执,一切执行可重放

模型要删笔记,执行完不能只返回一个 successsuccess 无状态、无法核验,回答不了:谁删的、什么时候删的、能不能恢复、是不是重复执行。

所以要返回结构化 Receipt(operationId / tool / resourceId / status / actor / recoverable),并且每步执行都要落 AgentTrace,让"AI 为什么得出这个结论"从"两手一摊"变成"还原现场"。《AI可观测性实战》的 Trace/Span 设计和《生产级Agent》的 Replay 讲的就是同一件事的两种姿势。

Replay 还有三个用处:排查问题、模型升级回归测试、沉淀评估集。换模型从"凭感觉拍板"变成"看数据做决定"——这是 Agent 团队和聊天机器人团队的分水岭。

1.4 降级链要算经济账

《LLM上下文窗口管理》和《SSE双队列》反复验证同一个道理:正常路径谁都会写,降级路径的设计才是工程师水平的试金石。

上下文超限的降级链要按"先丢弃、再压缩、最后引导人"排序;SSE 的队列满了要先"等 100ms 再丢"而不要立刻丢;TTFT 的高峰期要"让快的、少的、好的,隔离于慢的、多的、坏的"。每条链的每一格,都标着成本:0 次 API、1 次 API、让人介入。

1.5 可观测性要作为设计起点

《首字优化》里最扎心的一句复盘:

V1 那个单点埋点告诉你总耗时,但从来没告诉你钱花在哪了。就像一个只知道总消费金额、却拿不到明细的人。

V1 靠直觉做了流式、连接池、异步解耦,P50 降了 400ms,但 P99 纹丝不动——因为 V1 只盯应用层那几十毫秒,对服务边界外的事一无所知。直到 V5 做了全链路分阶段 Trace,TTFT 的优化才从"猜谜"变成"看表"。看不到的东西没法优化,所以可观测性必须在写第一行业务代码时就埋好。

1.6 幂等是及格线

《幂等性实战》讲的是支付重复扣款,但结论对 Agent 一样致命:只要系统里有一个"超时重试"或"失败重投"机制,幂等就从选择题变成了必答题。

Agent 的每次工具调用都该带 requestId,同一个 requestId 重试时不产生第二次副作用。《生产级Agent》里的 IdempotentInvoker 用键值存储挡一道,就是幂等思想在 Agent 里的直接落地。

设计自检清单:

检查项 判断标准 对应博客
判断权与执行权分离 模型永远只发请求,不直接碰数据 生产级Agent
Context 统一编译 各模块不许自己查笔记/自己拼 Prompt 生产级Agent / 上下文窗口
操作都有回执 没有 success,只有结构化 Receipt 生产级Agent
执行可重放 给定 traceId,能还原模型当时看到的全部上下文 AI可观测性 / 生产级Agent
降级链有序 先免费再便宜再昂贵,每一步标成本 上下文窗口 / SSE
幂等兜底 每个写操作带 requestId,重试不重复 幂等性 / 生产级Agent

二、架构问题:Agent 是跨进程的分布式执行系统

设计问题管"每一处应该怎么长",架构问题管"整张网怎么织"。五个架构命题,全是从这几篇博客的线上事故里长出来的。

2.1 状态与恢复:断电了还能续跑

《生产级Agent》开头的场景:任务五步走到第三步模型超时了。没有执行状态,系统从头重跑——重复草稿、重复发布、重复扣费。

生产系统要把任务拆成明确步骤,每步状态落盘:幂等(同一操作执行两次结果一致)、Checkpoint(每完成一步保存状态)、Resume(从最后一个检查点继续)。重试要受控,不能无限循环烧钱——RetryPolicy 只重试可恢复的异常。

这里有一个 Agent 特有的架构直觉:普通的聊天是"一句话换一段话",Agent 是"一次任务换一段有副作用的多步执行"。前者无状态可以随时重试,后者一旦落下痕迹,就必须有断点续跑的能力。

2.2 多进程共享:Redis 那张网

《Redis实战》讲的是同一个道理:一条 Agent 请求,Redis 被摸五次——登录态、工具配置缓存、第三方限流、并行分支跨机器传参、汇总节点分布式锁。

把五次收拢成一个架构原则:“多个进程、多台机器之间,怎么安全地共享一份数据”。 每次共享都要回答四个问题:

  • 设不设 TTL?(防僵尸 key,也要匹配业务生命周期)
  • 要不要原子?(SET NX EX 一条命令、Lua 把"自增+设过期"捆成一块)
  • 序列化统一吗?(key 用 String,value 用 JSON,跨语言才通)
  • 内存满了怎么办?(明确 maxmemory-policy,别用默认 noeviction

2.3 分布式锁的诚实边界

《Redis实战》场景 2 把锁讲透了,也把锁的边界讲透了:主从异步复制下,主节点写锁成功但没同步给从节点,主节点挂了——新主上没有这把锁,两个客户端同时拿到锁。

这是 Redis 分布式锁的理论边界。业界回应有两派:RedLock(antirez)和被反复论证其不严谨(Kleppmann)。架构决策很实在:

  • 绝大多数业务,这个故障转移窗口的概率低到可以接受 → 直接用 Redisson;
  • 真正不能容忍任何并发(钱、库存的强一致)→ 上 etcd / ZooKeeper 这类基于 Raft / Paxos 的组件。

选型前先想清楚自己在哪一边。 这是架构里最难的部分:承认工具的边界,同时放弃假装没有边界。

2.4 流式链路的物理现实:SSE 的八个坑

《SSE双队列进化之路》的八次蜕变,本质是一次次打破"直觉"的过程:

直觉 现实
一个队列就够 生成快、推送慢,必须双队列解耦生产消费
队列能无限存 无界队列 = OOM,put() 会阻塞 LLM 源头,要用 offer()
队列满了丢最新的 流式场景用户盯着屏幕底部,丢旧保新——旧 token 已渲染,新 token 丢了才要命
断了就清空一切 连接和会话是两种生命周期的资源:瞬时资源随 TCP 死,会话上下文给 8s 宽限期复用
丢包就学 TCP 重传 LLM 生成是单向流、一次性的,不能"再生成一遍 seq=47"。 只能分层兜底

第 6 条最值得记住:TCP 重传模型假设发送方有缓存可以重发,这个假设在 LLM 场景不成立。强行套用通用方案是架构大忌,适配业务模型才是务实。

2.5 上下文窗口是物理约束

《LLM上下文窗口管理》的标题就点破了本质:模型有"短期记忆"的物理上限。 4K、16K、128K,对话无限增长,窗口固定大小,这是根本矛盾。

架构上的三连问:

  • 历史存哪?HashMap → Redis → Redis+Caffeine → 落库+向量化(RAG 语义召回替代全量塞入)
  • 窗口 vs RAG?都选。 滑动窗口和 RAG 回答的是两个不同维度的问题——滑动窗口回答"最近说了什么"(时间维度),RAG 回答"和现在最相关的是什么"(语义维度),叠加使用。
  • 截断了用户知道吗?别静默——前端推一条温和提示 + 操作建议。

2.6 性能要拉通整条链路来看

《首字优化》的五次推倒重来给出了 TTFT 的六层框架:客户端传输层 → 接入网关层 → 应用服务层 → 依赖中间件层(Embedding 本地化、向量索引)→ 模型推理层 → 可观测与稳定性层。

V1 只做了第三层,P50 好看 P99 不动。每一层的出现,都对应一次"发现漏了什么"的时刻:漏了链路前半段(DNS、TLS)、漏了 RAG 计算开销(占 30%+)、漏了并发排队效应(单用户快 ≈ 百万并发快)、漏了"先看见再行动"。

架构自检清单:

检查项 判断标准 对应博客
可恢复 有 AgentRun / Checkpoint / Resume,没有重跑一遍 生产级Agent
幂等键 每个写操作可去重 幂等性 / 生产级Agent
共享状态 跨进程状态进 Redis,明确 TTL / 原子 / 序列化 / 淘汰策略 Redis实战
锁的边界 想清楚自己能不能接受主从切换窗口,不能就换 etcd Redis实战
流式兜底 有界队列 + 丢旧保新 + 连接/会话资源分级 SSE双队列
性能分层 全链路埋点,瓶颈定位到 Span 而不是靠猜 首字优化
上下文预算 Token 预算绑定模型,降级链按成本排序 上下文窗口

三、安全问题:权限要"结构上做不到"

AI 工具的安全,大多数人第一反应是在提示词里写上禁止。这层误解最危险。

3.1 Prompt 只能算软约束,安全要靠硬机制

《生产级Agent》第三章直接点名了一个错误设计:Agent → DeleteNoteTool → 删除笔记,然后在 Prompt 里写"没有用户同意不要删除"。

模型可能误判用户意图,可能被注入的提示词误导,也可能就是状态不对产生幻觉。你把安全建立在"模型每次都记得这句叮嘱"上,等于把门锁建在"每个人都自觉关门"上。

生产级做法是加一道硬门卫——PolicyEngine:当前用户是谁、是否有权限、操作是否高风险、是否需要审批、参数是否符合 Schema、是否超限额。核心思想就一句:

Agent 可以申请执行,但决定权限的只能是策略引擎,不能让模型自己说了算。

3.2 风险分级 + 审批要落到代码上

把工具按危害面分三档:LOW(搜索/读取)直接放行,MEDIUM(创建/更新)校验权限和限额,HIGH(删除/发布/导出/改权限)必须走审批。

审批链路最关键的一步:先领审批凭证,凭证未确认之前系统什么都不做(生成凭证 → 用户确认 → 放行执行)。这样权限在结构上就被保证了,不依赖模型自觉。

3.3 注入与幻觉的统一解法:硬门卫

Prompt 注入的本质是"模型的判断被污染了"。既然你不可能 100% 防住模型的判断被污染,那就不要在模型判断正确的假设上设计安全。模型可能被骗着发出一条"危险请求"——没关系,请求到了 PolicyEngine 会被拦下来。这就是为什么注入攻击和幻觉,在架构上共享同一个解法:把信任从模型身上剥离开,放到确定性的门卫代码上。

3.4 敏感数据与日志边界

《AI可观测性实战》第十六章和《SSE深度解析》各指了一条数据泄漏渠道:

  • 日志:为了排查问题把所有 Prompt 和笔记全文打进日志——普通 Trace 里只留 runId / snapshotId / queryHash / documentCount / tokenCount / model / cost,完整上下文放加密存储 + 严格权限 + 有限保留期。
  • URL 参数EventSource 只能用 GET,Token 被迫放 URL——服务器日志、浏览器历史、Referrer 头三处泄漏。

这是 2025 年 MCP 从 SSE 迁到 Streamable HTTP 的直接原因之一。

3.5 认证的粒度:连接级还是消息级

SSE 的认证只在连接建立那一刻做,中途 Token 过期了连接照样活着;而且 SSE 长连接很难被标准安全中间件(WAF、API Gateway)逐消息检查。

如果你的场景需要"每一条消息都独立认证"或"严格的中间件审计",SSE 难当此任。选协议之前,先想清楚自己的信任边界在"连接级"还是"消息级"。

3.6 成本失控也是安全问题

《SSE双队列》第八层讲了四道成本防线:宽限期内复用上下文(根治)、会话级重试熔断、任务版本号抢占取消(过时任务自己停)、全局并发限流。核心区分是——“合理的用户行为成本"和"代码缺陷导致的不必要成本”,架构上要消除后者。 一次网络抖动触发的全量 LLM 重试,100 个用户切网就是账单翻倍。

安全自检清单:

检查项 判断标准 对应博客
硬门卫 权限判断在 PolicyEngine,不在模型脑子里 生产级Agent
风险分级 HIGH 操作必须审批,审批凭证先于执行 生产级Agent
数据脱敏 日志存 hash 不存原文,完整上下文加密隔离 AI可观测性
Token 传输 敏感凭证不落 URL / 日志 / Referrer SSE深度解析
认证粒度 想清楚连接级还是消息级认证,选对协议 SSE深度解析
成本熔断 重复调用有熔断,过时任务能自杀 SSE双队列 / Redis实战

四、Agent 开发:着重学什么

问题域都讲完了,回答最初的问题——如果你要往 Agent 方向深入,着重学什么?

4.1 一次思维迁移:从"提示词"到"执行系统"

Agent 开发和你之前学的所有后端开发之间,差了一次认知迁移。下表就是这次迁移的对照:

普通后端 Agent 开发
代码是确定性的,测试覆盖了就不出意外 模型是概率性的,同一输入今天明天可能不同
出错了能靠日志定位 出错了要先"还原现场"(Replay)
幂等是支付系统的要求 幂等是每次工具调用的默认要求
权限靠中间件挡 权限还要防住"被注入污染的模型判断"
性能优化到瓶颈点 瓶颈可能在应用层之外(DNS、排队、Embedding)

这个迁移一旦完成,你就会发现:那些你以为"是 AI 的坑"的东西,其实全是后端工程的坑。 队列满了是并发问题,跟 AI 无关;超时重试重复执行是幂等问题,跟 AI 无关;上下文拼错是抽象问题,跟 AI 无关。

4.2 七个能力模块,每块配一个精读对象

能力 精读对象 提取的核心技能
边界与分层 生产级Agent 划边界、Context Compiler 管道、Policy Engine、三阶段落地
可观测与评估 AI可观测性实战 Trace/Span 设计、Metric 体系、Dashboard、数据落库
上下文工程 LLM上下文窗口管理 Token 预估、降级链、消息分级、Token 计费
流式协议 SSE双队列 + SSE深度解析 有界队列、资源生命周期、丢包兜底、协议选型
分布式基础 Redis实战 + 幂等性实战 原子性、分布式锁边界、幂等 Token、缓存一致性
性能链路 首字优化 全链路 Trace、分位数、熔断限流、优先级调度
会话与状态 Pi Agent Harness + Claude Code 会话树/回退分支、compaction 检查点、记忆沉淀、权限模式与隔离

4.3 四个"你以为懂,其实要补"的点

《首字优化》结尾总结了 V1 直觉方案漏掉的四件事——这四件事就是 Agent 开发里最典型的盲区:

  1. 漏了链路的前半段:用户到服务器的路上,DNS 和 TLS 在消耗看不见的时间。你以为的"起点"其实在更前面。
  2. 漏了 RAG 的计算开销:Embedding 和向量检索占了 30%+ 却被当成"别人的事"。Agent 的性能问题,一半藏在"上下文准备"里。
  3. 漏了并发下的排队效应:单用户测试很快,不代表百万并发依然快。慢的根源常常在于"隔离不够"。
  4. 漏了"先看见再行动"的底气:没有分层 Trace,每次排查都是一场猜谜。

这四件事之外,还有一个更大的盲区——Session 怎么设计。下一节专门展开。

4.4 从博客到简历:怎么把经验沉淀成面试答案

目录里这些博客之所以是"面试宝典",关键在于一个共同的写法——每讲一个坑,都追到"为什么",再追到"所以架构上应该怎么设计"(博客里的"思维回溯")。

对应到面试,就是一套自洽的叙事结构:

场景(线上发生了什么)→ 根因(是设计问题还是架构问题)→ 方案(落到了哪条边界 / 哪个组件)→ 代价(牺牲了什么,为什么不选银弹)→ 迁移(这个教训还能用在哪)

你不需要背每篇博客的代码。你需要的是能对任意一个 AI 项目,一口气讲出《生产级Agent》那条总链路、讲出四个问题域各三条红线。能做到这一点,说明你已经有能力把"会调工具的聊天机器人"升级成"能把它变成执行系统的人"。


五、两个 Session 设计:Agent 开发的硬需求与软实力

前面四节讲的是"单体 Agent 服务"的骨架。但 Agent 开发还有一大块没有顾及到——Session 怎么设计。Session 是"一次对话 / 一次任务"的完整状态容器,它决定了你的 Agent 能不能:断线重连接着聊、跨请求记住上下文、并发出错后回到过去、上下文超长后继续干活。

拿两个真实项目对照。一个是 Pi Agent Harness(GitHub 上约 4 万 star 的开源编码 Agent,OpenClaw 的核心运行时也构建在它的 SDK 之上),一个是 Claude Code(会话式 CLI Agent)。两者都是"终端里的编码 Agent",Session 设计却走完全相反的两条路,正好把 Agent 开发的硬需求和软实力摊满。

5.1 Pi 的 Session:一棵可回退、可分支的树

Pi 把 Session 存成 JSONL 文件,每条记录带 idparentId,拼起来是一棵会话树,而不是一条直线:

├─ user: "试试方案 A"
│  └─ assistant: "方案 A 这样写..."
│     ├─ user: "A 跑通了"  ← 当前叶子
│     └─ user: "还是试方案 B"
│        └─ assistant: "方案 B..."

这套设计默认了 Agent 会犯错:/tree 可以回到任意一个历史点,改一句 prompt 重新提交,从那里长出新的分支;/fork/clone 可以把一条分支单独拎成新会话。撤销的单位从"一句回复"放大到了"整条执行路径"。 放弃一条分支时,模型会为那条被放弃的路径生成一段摘要(BranchSummary),挂在分支点附近——走掉的路丢了内容,但留下了上下文。

Pi 的 compaction 和《生产级Agent》的 Checkpoint 是同一思想的另一个落地:上下文超阈值时,把旧消息摘要成一条 CompactionEntry,里面带 summary + firstKeptEntryId + retainedTail(压缩后保留的尾部消息,作为自包含检查点)。重建上下文时从这个检查点往后走,无需翻旧条目。切分点永远落在回合边界,绝不在 tool-result 中间切。

Pi 的会话文件还带着一串很多项目会忽略的字段:

  • 版本号:session 格式有 version 1/2/3,加载时自动迁移。磁盘格式的演进是一等公民,升级不毁老会话。
  • 记账:每条 assistant 消息都带 usage(input/output/cacheRead/cacheWrite + cost)。Token 和费用长在会话里,能对账、能回溯。
  • 换模型:会话记录 model_change 事件,同一段对话中途切模型,重建上下文时还能还原当时用的是哪个 provider、哪个模型。

5.2 Claude Code 的 Session:一段可回放、可干预的对话

Claude Code 的 Session 走了另一条路:它把一次交互看作可记录、可续跑、可干预的对话上下文,连接状态只占其中一小部分。Session 里除了对话记录,还挂着:

Session = 对话记录(transcript)
        + 压缩与续跑(长对话自动摘要、断点恢复)
        + 记忆(跨 Session 的持久化文件,独立于上下文)
        + 工具与权限(用户选定的模式,被拒绝即调整)
        + 钩子(系统级干预,中途插入规则)
        + 子代理(隔离运行,并行推进)
        + 工作树隔离(git 级别的沙箱)

Pi 的答案可以概括为"Session 就是一棵树,其余交给沙箱和扩展";Claude Code 的答案是"Session 自带一套治理:记忆、权限、钩子、子代理全部内建"。两种取舍没有对错,差别在边界归谁管。

对应到软实力(做了才"好用",不做也能跑):

1. 上下文压缩的取舍。 对话长到放不下,自动把早期内容摘要成紧凑形式。但要清楚这是有损的——代码、SQL、合同这类内容被压缩等于改语义。正确姿势是分级:可压缩的普通对话才压,关键内容保留原文,并让用户知道"早期部分被精简了"。压缩的边界里同时装着业务判断和工程判断。

2. 记忆跨 Session 沉淀。 记忆文件存的是"用户的身份、偏好、被纠正过的工作方式",它独立于任何一次对话,用索引在每次会话加载。这和 RAG 召回知识是同一件事的两种形态:知识进上下文靠检索,经验进行为靠记忆。

3. 人在环上是安全底座。 权限模式由用户选定,工具调用被拦截时返回的是可调整的反馈,而不是一个硬错误。高风险操作永远留一个需要人确认的闸门。Agent 设计到后面,重心会从"让模型更聪明"挪向"让人更放心"。

4. 可干预、可隔离、可并行。 系统通过钩子在会话中途注入约束;子代理在独立工作区里并行干活、互不污染;文件级沙箱防止一个任务改坏另一个任务。隔离是 Agent 进化的分水岭——从"一个对话干一件事"到"一个对话派出一群隔离的执行者"。

5.3 硬需求 vs 软实力:一张对照表

两个项目的 Session 设计摊开对比,硬需求(结构上不做就崩)和软实力(做了才"好用")一目了然:

硬需求(结构上不做就崩) 软实力(做了才"好用")
Session 形态 有 ID、可序列化、格式带版本可迁移;断点可恢复 树 + 回退 + 分支,撤销粒度放大到整条执行路径
上下文 超长时能压缩,且能从检查点重建,不重翻旧条目 切分有业务判断:回合边界切、关键内容不压
记账 Token / 费用随消息落库,可对账可回溯 把成本当功能设计,而非事后统计
模型 跨 provider 可切换、可回放(record model_change) 不被单一模型锁死,切换有据可依
安全 必须选一种兜底:沙箱/容器(Pi)或 权限模式+工作树(CC) 诚实选择安全哲学,在"途中同意"和"容器隔离"之间取舍
演进 磁盘格式带版本、可自动迁移 极简主义:核心保持小,能力按需扩展

5.4 补进总地图

把两个项目放回总地图,Session 是横切在每一站下面的那一层:

  ……原链路每一站……
        ↓
  Session(横切层)
  ├─ 执行记录(Pi:会话树 / 回退分支 / 版本化序列化)
  ├─ 上下文重建(compaction 检查点 / 记忆沉淀)
  ├─ 记账与换模型(usage 随消息 / model_change 回放)
  └─ 隔离与干预(沙箱容器 / 权限模式 / 钩子 / 子代理)

Agent 开发的路由此补全:前面四节是"单体服务怎么设计",这一节是"一次执行实例怎么设计"。顺带一提,你自己的 PaiFlow 工作流引擎在 TTL 上下文传播、变量池并发安全上踩过的坑,跟这里两张 Session 设计是同一批硬需求的另一面——Session、任务、连接三层状态,永远是 Agent 架构里最容易被低估的地方。


六、落地路线图:别想着一步到位

《生产级Agent》第八章给了三阶段落地法。这里把前面所有维度(含 Session 设计)折叠进三阶段:

第一阶段 · 立边界(设计)
  AIApplicationService / ContextBuilder / LLMGateway / ToolGateway
  红线:Agent 不直接调 Repository、不碰 DB、不绕过权限系统

第二阶段 · 加恢复和可观测(架构 + Session)
  AgentRun / ToolCallLog / ContextSnapshot / RetryPolicy / IdempotencyKey
  Session 与上下文:会话序列化与版本 / compaction 检查点 / 跨线程上下文传播
  解决:执行断了能续、重复了能挡、出了事能查

第三阶段 · 上治理(安全 + 评估 + 记忆)
  ApprovalWorkflow / Replay / EvaluationDataset / PolicyEngine
  Session 与记忆:跨 Session 记忆 / 人在环上 / 子代理隔离
  解决:审批、回放、评估、策略引擎全部在位

每一阶段都建立在"你已经被上一层的问题折磨过"的前提上。没被 OOM 折磨过,你不会理解为什么要上有界队列;没被 Token 账单惊吓过,你不会觉得全链路计费是刚需。跳级不划算,因为每一层的设计都是问题驱动的。


把链路闭合

回到开头的总地图,把所有维度拼回去,就是一句话:

把不确定的智能,限制在确定的软件工程边界里。

LLM 可以不稳定,但外围系统必须稳定。各自的职责分得很干净:

模型    负责建议
策略    负责授权
工具    负责执行
Runtime 负责记录与恢复
Session 负责状态与记忆
可观测  负责让一切都看得见
人      负责高风险决策

这也是 AI 系统和普通后端最大的区别:你不能假设模型每次都会做对,所以架构要围绕"它可能判断错误"来设计。 模型出错并不可怕,可怕的是出错之后系统既不能发现、也不能恢复、还不能解释。

把这八个词记住——判断、授权、执行、记录、会话、隔离、决策、看见——然后回头去重读任何一篇博客,你都会发现:它写的其实都是这套边界的一个侧面。

更多推荐