Skip to content

数据流追踪与端到端可观测性面试题 ​

这份题库关注的不是“给请求加一个 trace_id”这么简单,而是如何让一次 AI 请求从入口到最终业务事实都可关联、可重放、可审计、可脱敏。回答时要区分观测字段、业务主键、执行状态和外部事实,不能把日志、Trace、任务表和业务数据库混成一个系统。

一、先建立追踪模型 ​

用户点击“提交报销”后关掉页面,后台仍可能在调用模型、查政策和写财务系统。追踪链要回答这次请求用了哪个版本、工具是否真实执行、金额是否已落账,而不能只留一个浏览器 request id。

Q1:一次企业 Agent 请求为什么需要多个 ID? ​

考察点

是否能区分调用关联、任务生命周期、工具调用尝试和业务幂等语义。

回答脉络

先定义 trace_id、task_id、span_id、tool_call_id、idempotency_key,再说明它们的生命周期和关联关系。

详细参考答案

我会至少使用以下几类标识:

  • trace_id 表示一次请求或一次可观测调用树,贯穿 Gateway、模型、检索、工具和数据库访问,用于定位延迟、错误和成本。
  • task_id 表示一个可跨 HTTP 请求持续运行的业务任务。长任务断线、重试或人工接管后,新的网络请求仍然关联到同一个 task_id。
  • span_id 表示 Trace 中的一个时间区间,例如一次模型调用、一次向量查询或一次工具执行;父子关系由 parent_span_id 表示。
  • tool_call_id 表示模型在某一轮输出中的工具调用意图。工具重试通常可以产生多个 execution span,但仍应保留同一个调用意图和 attempt 序号。
  • idempotency_key 表示一次外部业务动作的去重契约,例如创建付款、发送邮件或写入订单。它不应等同于 trace_id,因为同一业务动作可能跨多个重试和任务恢复继续执行。

典型关系是 trace_id -> task_id -> step_id -> tool_call_id -> idempotency_key。每个实体都要记录租户、主体、配置版本和时间,但不能把用户输入、完整提示词或敏感结果直接拼进 ID。ID 应不可预测、不可包含隐私,并在跨服务传递时验证格式和归属。

常见追问及答案

  • 为什么不能只用一个 request_id? 短请求的 request_id 无法表示断线后的长任务,也无法区分同一工具意图的多次执行和业务幂等键。
  • tool_call_id 能直接当幂等键吗? 不能。一个模型调用可能因供应商重试或执行器重放产生多个业务动作,幂等键应绑定具体动作参数、资源和业务语义。

扣分点

  • 只会在 HTTP Header 里生成一个 ID。
  • 把 trace_id 当作支付、退款等业务动作的唯一键。
  • 不记录 attempt、父子关系和租户边界。

Q2:如何设计一份跨服务通用的 Trace Context? ​

考察点

是否能把标准传播、业务字段和安全边界分开设计。

回答脉络

先说 W3C Trace Context 或等价标准,再说明业务扩展字段、可信来源和跨异步边界的传递。

详细参考答案

同步 HTTP 调用使用标准的 traceparent 和可选 tracestate 传播采样和父子关系;业务字段单独放在受控 Header 或 RPC metadata 中,例如 tenant_id、task_id、actor_id_hash、config_snapshot_id。不要把所有业务字段塞进 tracestate,也不能依赖客户端传来的 tenant_id 作为授权依据。

进入队列时,把经过服务端确认的上下文写入消息信封,消息体中记录 trace_id、父 span、任务和租约版本。消费者创建新的处理 span,但保留关联上下文。跨服务边界要限制允许传播的字段,外部供应商只发送最少必要信息,通常不传播内部用户标识、完整租户名或原始 Prompt。

入口先生成或验证 Trace Context,禁止客户端伪造采样率、租户和权限范围。上下文大小应有上限,避免恶意请求利用 Header 或消息元数据造成资源耗尽。日志系统按 trace_id 查询,但权限系统仍要根据真实认证主体做访问控制。

常见追问及答案

  • 队列消息没有父请求怎么办? 由发布者创建消息生产 span,并把消息 ID 和任务上下文写入消息;消费者以消息生产 span 作为链接或父 span。
  • 是否应该传播完整用户 JWT? 通常不应该。服务之间使用短期服务凭证或受控的 actor context,避免在日志、队列和第三方请求中扩散长期令牌。

扣分点

  • 只复制所有 Header,不做字段白名单。
  • 把观测上下文当成授权上下文。
  • 异步队列和回调没有关联关系。

Q3:Trace、日志、指标和业务事件分别解决什么问题? ​

考察点

能否说明四类信号的职责、关联方式和存储边界。

回答脉络

从单请求诊断、聚合趋势、业务事实和长期审计四个角度比较。

详细参考答案

Trace 描述一次请求在服务、模型、检索和工具之间的时序和耗时,适合定位链路瓶颈;日志记录具体异常、决策原因和结构化上下文,适合搜索诊断;指标是低维聚合,例如 P95 TTFT、工具错误率、缓存命中率、每租户成本,适合告警和容量规划;业务事件记录“任务已批准”“订单已创建”这类需要长期保留、可重放和对账的事实。

四类信号通过 trace_id、task_id、span_id、event_id 和资源 ID 关联,但不能互相替代。Trace 不适合保存大段文档和完整 Prompt,指标不能带高基数原始 ID,日志不应成为业务事实的唯一来源,业务事件也不应承担高频调试日志的成本。

例如一次退款请求可以有一棵 Trace、若干结构化日志、一次工具耗时指标、一个 refund_requested 事件和一个由支付系统确认的 refund_succeeded 事实。只有后者才能用于财务对账。

常见追问及答案

  • 所有日志都带完整 Trace 吗? 关键日志应带;高频 debug 日志可采样,但不能采样掉安全和副作用事件。
  • 业务事件能否只放 Kafka? 需要有可查询、可恢复和可审计的持久化语义,通常由事件表、Outbox 或可靠事件平台共同实现。

扣分点

  • 只会说“把日志打全”。
  • 用指标记录每个用户和每个文档 ID,造成高基数爆炸。
  • 把模型输出日志当成业务成功事实。

Q4:如何定义一条 Trace 的开始和结束? ​

考察点

是否能处理同步请求、异步任务、流式连接和后台补偿。

回答脉络

分别说明入口 span、任务 span、流式 span、后台 span 和外部确认 span 的边界。

详细参考答案

同步请求的入口 span 从 Gateway 收到请求开始,到响应头或响应体完成结束;流式请求可以把网络连接作为 transport span,同时为模型生成和每个下游调用单独建子 span,避免连接被用户长时间打开掩盖真正计算耗时。异步任务的入口 span 只覆盖“接受任务并落库”,后台执行创建新的 trace 或 span link,并通过 task_id 关联同一业务任务。

任务的“成功”不能简单等同于最后一个 HTTP span 结束。对于外部异步动作,还要有查询、回调或对账 span,直到状态机确认业务事实。人工等待期间不应保持一个永不结束的 span,而应记录等待事件和停留指标。补偿、回滚和人工接管各自创建独立 span,并保留原任务的链接。

结束时要区分 request_completed、task_succeeded、artifact_published 和 external_action_confirmed。一个回答已经返回,不代表文件已经生成成功,更不代表外部付款已经完成。

常见追问及答案

  • 流式连接断开就是 Trace 失败吗? 不一定。应记录客户端断开原因,判断模型和工具是否继续执行,并由任务状态确认最终结果。
  • 等待人工审批时 Trace 保持 open 好吗? 通常不建议,长时间 open 会浪费观测资源;用事件、任务停留时间和恢复后的新 span 表示等待。

扣分点

  • 用单个入口 span 覆盖数小时任务。
  • 把返回 HTTP 200 当作业务完成。
  • 不记录客户端断开和后台继续执行情况。

Q5:如何给 Span 设计字段,既能定位问题又不泄露数据? ​

考察点

是否能平衡可诊断性、高基数、隐私和成本。

回答脉络

先列稳定低维字段,再讲哈希、摘要、引用和受控采样,最后说明访问权限。

详细参考答案

通用字段包括服务名、环境、版本、区域、租户哈希、任务 ID、步骤类型、状态、错误码、模型名、配置快照、输入输出 token、缓存命中、工具名、检索索引版本和耗时。对于文档和 Prompt,不直接记录全文,而记录内容哈希、长度、schema 版本、引用 ID、页码、段落定位和必要的脱敏摘要。高基数字段如原始 URL、订单号和文档 ID 可以放日志或关联表,不应全部作为指标标签。

脱敏在采集前进行:识别邮箱、电话、身份证、密钥、Cookie、访问令牌、财务账号和自由文本中的个人信息;对需要关联的字段使用租户隔离的 HMAC,而不是可逆明文或无盐哈希。原文只在受控、加密、限时保留的证据存储中保存,并由少数角色按工单访问。

采样也要有规则:普通成功请求可采样,权限拒绝、越权、外部写入、未知结果、恢复失败和高额成本请求应强制保留最小必要证据。Trace 查询接口同样要做对象级授权,不能因为拥有观测权限就越过业务数据权限。

常见追问及答案

  • 哈希后就不算敏感数据了吗? 不一定。可关联哈希仍可能属于个人数据,且字典攻击可能还原低熵字段,需要密钥隔离和访问控制。
  • 调试时可以临时记录完整 Prompt 吗? 只能在审批、脱敏、时限和租户隔离条件下临时采集,结束后自动清理并记录谁访问过。

扣分点

  • 把 Prompt、文档、JWT 和工具结果原文全部写进 Trace。
  • 只用字符串替换几个固定字段,忽略自由文本和附件。
  • 观测系统不做权限控制。

二、端到端链路追踪 ​

Q6:请画出 Gateway 到最终 Artifact 的完整追踪链路。 ​

考察点

是否能把入口、运行时、模型、RAG、工具、数据库和产物服务连成可执行的时序。

回答脉络

按阶段说明输入、输出、ID、版本、权限和失败点。

详细参考答案

我会把链路画成:

text
Gateway
  -> Auth / Tenant / Rate Limit
  -> Runtime Task + Policy
  -> Prompt Assembly + Model Call
  -> Query Rewrite / RAG Retrieve / Rerank
  -> Tool Gateway + Approval + Idempotency
  -> DB / External Service
  -> Artifact Store / Citation
  -> Response Stream / Task Event

Gateway 生成 trace_id、校验用户身份和幂等创建请求;Runtime 创建 task_id、锁定 Agent 和策略版本;Prompt 阶段记录模板、变量 schema 和上下文来源的快照 ID;RAG 阶段记录查询改写、检索器、过滤条件、索引版本和证据引用;Tool Gateway 负责工具授权、参数校验、tool_call_id、idempotency_key 和执行租约;DB 或外部系统返回业务事实;Artifact 服务以不可变对象保存文件、引用清单或结构化结果;最后通过流式响应或任务事件返回状态。

每一段都创建父子 span,并在状态变更、权限决策、版本发布和外部副作用处写领域事件。大对象只记录 artifact_id、哈希和大小。任何一段失败都要说明是“未执行”“执行中断”“结果未知”还是“业务拒绝”,不能只返回一个通用 500。

常见追问及答案

  • 为什么 RAG 和工具不能共用一个 span? 两者的延迟、权限、重试和失败语义不同,合并会遮蔽瓶颈和泄露边界。
  • 最终回答和 Artifact 如何关联? 通过 task_id、artifact_id、内容哈希和引用事件,确保下载的文件与回答宣称的版本一致。

扣分点

  • 架构图只有 API、LLM 和数据库三个框。
  • 没有把权限、版本和幂等放进链路。
  • 只追踪成功路径,不描述中断和未知结果。

Q7:Gateway 层应该记录哪些字段,哪些字段不能信任客户端? ​

考察点

是否理解入口边界、请求幂等和用户输入的可信等级。

回答脉络

先说认证和请求元数据,再区分服务端生成字段与客户端声明字段。

详细参考答案

Gateway 应记录请求到达时间、路由、协议、客户端版本、认证主体、租户、权限版本、请求大小、限流结果、入口区域、trace_id、创建任务的幂等键摘要和响应状态。租户、主体、角色、权限范围、配置版本和采样策略应由认证、策略或服务端配置解析得到;客户端传来的 tenant_id、user_id、role、is_admin 和 trace_id 只能作为非可信输入或被覆盖。

请求幂等键要绑定租户和 API 操作,服务端保存请求摘要,发现同键不同体时返回冲突而不是复用旧结果。Gateway 先做 schema、大小、附件类型和速率校验,再把最小可信上下文交给 Runtime。认证失败、权限拒绝、限流和 body 解析错误也要生成足够的诊断信息,但不能把原始凭据写入日志。

常见追问及答案

  • 客户端重试时如何避免重复创建任务? 使用租户范围内的 API 幂等键和请求摘要,已创建则返回原 task_id。
  • 入口生成的新 trace 可以接受客户端 trace 吗? 可以作为链接字段保留,但内部主 Trace 应由服务端生成,避免伪造和串线。

扣分点

  • 信任请求 body 中的租户和管理员标记。
  • 没有请求摘要,导致幂等键被错误复用。
  • 日志包含 Authorization、Cookie 或完整请求体。

Q8:Runtime 如何追踪一次多轮模型循环? ​

考察点

是否能区分轮次、步骤、模型调用和状态快照。

回答脉络

说明 loop、step、attempt、checkpoint 和事件之间的关系,避免把模型文本当状态。

详细参考答案

Runtime 为任务建立不可变的 run_id 或执行分支,循环中的每一轮有 step_id 和 iteration,模型请求、RAG 查询、工具执行分别创建子 span。每轮开始前读取当前 checkpoint,记录输入消息摘要、预算、策略版本和可用工具集合;模型返回后先进行 schema 校验和策略判定,再决定是生成回复、检索、调用工具、等待审批还是结束。

每次状态转移都写事件并更新带版本号的任务快照。模型输出的自然语言只是一种候选结果,不能直接覆盖任务状态。若同一轮发生网络重试,保留 attempt 序号和供应商 request ID;若执行器恢复,则从最近已确认的 checkpoint 继续,而不是重新猜测已经完成的步骤。

常见追问及答案

  • 每一轮都保存完整上下文吗? 大上下文放加密对象存储,快照保存哈希、消息引用、token 统计和必要的结构化状态。
  • 模型返回工具调用但参数不合法怎么办? 记录模型响应和校验错误,进入修正或失败状态,不能直接调用工具。

扣分点

  • 只记录最终答案,不记录模型轮次和工具意图。
  • 模型输出可任意改变任务状态。
  • 重试覆盖原 attempt,导致无法判断是否重复执行。

Q9:Prompt 组装阶段如何追踪上下文来源和版本? ​

考察点

是否能做到 Prompt 可解释、可复现且不泄露原文。

回答脉络

从模板版本、变量来源、RAG 证据、工具结果和消息裁剪说明展开。

详细参考答案

Prompt span 应记录 prompt_template_id、模板版本、system policy 版本、变量 schema、模型路由、上下文预算和组装策略。每段上下文标注来源类型:用户消息、系统规则、RAG 证据、工具结果、历史摘要或人工输入,并记录来源 ID、内容哈希、权限判定、知识版本和截断原因。不要在普通 Trace 中存完整 Prompt,可以在受控证据存储中保存脱敏快照。

上下文组装必须是确定性的:同一版本、输入摘要和证据集合应能得到相同的消息结构。发生窗口裁剪、摘要替换、Prompt Cache 命中或安全指令覆盖时,写出决策字段和 token 变化。这样排查“模型突然答错”时,能判断是检索变化、上下文丢失、模板改动还是模型本身波动。

常见追问及答案

  • 模板版本和模型版本哪个更重要? 两者都要。模板决定约束和字段,模型决定推理行为;还需记录工具 schema、索引和策略版本。
  • 上下文快照是否可以永久保存? 受数据保留、用户删除和合规要求约束;保存摘要和哈希通常优于永久保存原文。

扣分点

  • 只记 prompt 名称,不记版本和变量来源。
  • 把所有用户文档拼进日志。
  • 忽略上下文裁剪和缓存命中导致的输入差异。

Q10:如何追踪 RAG 检索到引用生成的证据链? ​

考察点

是否能把查询改写、候选、权限过滤、排序、上下文和引用逐层关联。

回答脉络

从 query、retrieval、rerank、evidence、claim-citation 五层展开。

详细参考答案

RAG 追踪至少包含:原始问题哈希和改写查询版本;检索器类型、过滤条件、索引 release、召回数量和延迟;候选文档/片段 ID、分数和被过滤原因;reranker 版本及最终上下文顺序;模型输出中的 claim 与引用 ID 映射。候选内容在进入模型前必须完成租户和 ACL 过滤,Trace 里只保存引用 ID、版本、页码、字符范围和摘要哈希。

如果答案包含多个声明,生成后应做 claim-citation 校验并记录支持、冲突、过期和无证据状态。引用链接指向 Artifact 或受控文档服务,由服务端再次检查权限和版本,不让前端根据一个裸 URL 绕过授权。检索缓存命中时仍记录命中的索引版本、权限版本和过滤摘要。

常见追问及答案

  • 为什么要记录被过滤的候选? 可以记录数量和原因码,通常不记录未授权内容本身;这样能发现权限错误而不泄露文档。
  • 模型引用了不存在的片段怎么办? 将其标记为无效引用,阻断高风险回答或触发重试/人工,而不是自动拼接一个近似链接。

扣分点

  • 只记录最终引用 URL,不记录索引和版本。
  • 先把未授权文档送给 reranker 或模型,再在输出阶段过滤。
  • 用检索分数代替证据支持关系。

三、权限、版本与成本传播 ​

Q11:权限上下文如何从 Gateway 传播到 RAG、Tool 和 Artifact? ​

考察点

是否能保证每个下游都基于可信身份和资源范围授权,而不是依赖模型或前端。

回答脉络

认证主体 -> policy snapshot -> 下游过滤/授权 -> 结果再次复核 -> 审计。

详细参考答案

Gateway 从身份系统解析主体、租户、组织、角色和权限版本,Runtime 将其固化为本次任务的 access_context_snapshot_id。RAG 查询使用该快照做文档、片段和附件过滤;Tool Gateway 根据主体和资源计算动作权限,必要时发放短期、最小范围的执行令牌;DB 访问使用数据库行级权限或服务端资源校验;Artifact 下载和引用解析再次检查当前权限,避免任务创建时有权限、交付时已撤权仍可读取。

权限上下文不能由模型输出、用户消息或 RAG 文档内容覆盖。权限变化要有版本号和失效时间,缓存键包含租户、主体/权限版本、资源范围、策略版本和知识版本。审计记录授权决策、策略版本、拒绝原因和资源摘要,但不记录完整敏感内容。

常见追问及答案

  • 任务运行很久,权限变化怎么办? 高风险动作和 Artifact 交付时重新授权;对于长任务可配置快照权限或强制使用当前权限,必须明确产品语义。
  • 为什么工具还要自己授权? Runtime 的策略不能替代资源服务的最终授权,纵深防御要求工具和业务服务拒绝越权。

扣分点

  • 只在 Gateway 鉴权一次。
  • 把权限信息放进 Prompt 让模型自行判断。
  • 忽略撤权、缓存和产物下载阶段。

Q12:如何做版本快照,才能复现一次线上失败? ​

考察点

是否知道一次结果受哪些可变依赖影响,以及如何冻结和回滚。

回答脉络

列出模型、Prompt、工具、RAG、权限、代码、特性开关和数据快照,说明 manifest 与哈希。

详细参考答案

任务创建时生成不可变 manifest,至少包含应用和 Runtime 版本、模型供应商/模型版本、Prompt 模板与策略版本、工具 schema 和实现版本、RAG pipeline/embedding/reranker/index release、权限快照、特性开关、区域、采样参数、依赖服务版本和输入摘要哈希。manifest 自身有版本和内容哈希,事件、Trace、checkpoint、Artifact 和成本记录都引用它。

复现不等于把生产数据原样复制。应在脱敏隔离环境恢复输入、可用的知识版本和模拟工具响应;对于外部副作用只做 dry-run 或查询,不重放真实写入。若供应商模型不可冻结,记录响应、随机种子(若支持)、请求参数和供应商 request ID,并明确这是轨迹复现而非位级确定性复现。

常见追问及答案

  • 只保存 Git commit 行不行? 不够,模型、索引、Prompt、工具 schema 和权限策略可能在代码之外变化。
  • 用户删除数据后还能复现吗? 需要遵守删除和保留政策;可保留脱敏摘要、哈希和结构化证据,不应绕过用户删除永久保存原文。

扣分点

  • 只记录当前应用版本。
  • 线上排障直接调用真实写工具重放。
  • 版本信息散落在文本日志中,没有可校验 manifest。

Q13:如何把缓存命中和成本计入端到端 Trace? ​

考察点

是否能区分模型、Prompt、RAG、工具和 Artifact 缓存,并避免用缓存掩盖权限或版本问题。

回答脉络

先列缓存层,再讲 key、命中事件、token/费用归属和失效。

详细参考答案

每个缓存层创建独立 span 或事件:Prompt Cache/KV Cache 记录前缀哈希、命中范围和节省 token;RAG 结果缓存记录 query 策略、权限版本、索引 release、TTL 和候选摘要;工具只读缓存记录资源版本和新鲜度;Artifact 缓存记录对象哈希和租户隔离。统一费用明细中区分输入 token、缓存命中 token、输出 token、工具调用费、检索资源费和存储/带宽费。

缓存 key 必须包含影响正确性和授权的字段,不能只用自然语言问题。命中后仍要校验当前权限、租户、数据版本和过期时间;权限撤销、文档删除、工具资源变化和策略发布应触发失效或版本隔离。Trace 记录命中/未命中、回源耗时、节省估算和失效原因,用于计算“每个成功任务成本”,而不是只看平均 API 账单。

常见追问及答案

  • 缓存命中就不需要记录下游 span 吗? 可以不创建未发生的下游调用,但要记录 cache span、命中依据和版本,避免链路看起来像数据凭空出现。
  • 为什么缓存命中率高但成本没有下降? 可能只缓存了低成本检索、命中的是短前缀,或重试、输出 token、工具费用占主导;需要联合分析。

扣分点

  • 用用户问题作为全局缓存键。
  • 缓存绕过 ACL 和版本检查。
  • 只统计模型账单,不算检索、工具、存储和重试成本。

Q14:如何做跨租户和跨用户的 Trace 查询隔离? ​

考察点

是否把观测平台本身当作敏感数据系统治理。

回答脉络

主体授权 -> Trace 归属 -> 字段脱敏 -> 索引隔离 -> 导出审计。

详细参考答案

每条 Trace 和日志必须写入服务端解析出的 tenant_id、数据分类和访问域,查询 API 根据调用者的观测权限做对象级过滤。平台管理员也不应默认看到所有 Prompt 或附件正文;可以按职责提供指标、脱敏 Trace、受审批的证据查看和临时 break-glass。索引、对象存储、导出文件和缓存都要沿用租户隔离,不能只在前端隐藏字段。

脱敏策略在写入前执行并保留规则版本;涉及高风险数据的 Trace 默认只保存哈希、引用和错误码。查询、下载、恢复原文、批量导出和权限提升都写观测平台审计。跨租户聚合只展示统计结果,并限制小样本和高基数查询,防止通过差分推断泄露数据。

常见追问及答案

  • 运维排障需要跨租户看一条链怎么办? 使用受审批的临时权限和最小字段视图,查询结果自动过期并记录工单、操作者和原因。
  • Trace ID 猜不到就安全吗? 不安全。ID 不可预测只能降低枚举,真正保护来自授权、索引过滤和存储隔离。

扣分点

  • 认为“日志平台只有内部人使用,所以可以全量明文”。
  • 只在 UI 做租户过滤。
  • 导出和 break-glass 没有审计。

四、Tool、DB 与外部副作用 ​

Q15:如何把 tool_call_id、执行 attempt 和 idempotency_key 关联起来? ​

考察点

是否能处理模型重复意图、网络重试、Worker 恢复和业务去重。

回答脉络

意图记录 -> 参数规范化 -> 动作键生成 -> 执行尝试 -> 外部确认。

详细参考答案

模型输出一条工具调用时,Runtime 先持久化 tool_call_id、工具 schema 版本、规范化参数摘要、主体、资源、风险决策和当前 step_id。执行器根据业务动作生成稳定的 idempotency_key,例如由租户、动作类型、资源 ID、任务步骤和语义版本组成;不能把易变化的 Trace 或随机 attempt 放进键。每次网络请求有 attempt 和供应商 request ID,但所有 attempt 都引用同一动作记录。

动作表保存 PENDING、SENT、SUCCEEDED、FAILED、UNKNOWN 状态和请求哈希。超时后先用幂等键查询外部系统;若外部系统不支持幂等或查询,必须进入人工/对账流程,不能盲重试。参数摘要变化时返回冲突,防止同一键被用于不同资源。

常见追问及答案

  • 同一个工具调用重放时是否生成新 tool_call_id? 如果是同一模型意图恢复执行,保留原 tool_call_id 并增加 attempt;如果是人工确认后产生的新业务意图,才创建新的调用。
  • 只读查询需要幂等键吗? 业务副作用较低,但仍应有请求关联和去重/缓存语义,避免昂贵查询风暴。

扣分点

  • 每次重试都随机生成幂等键。
  • 用工具名称和用户问题简单拼接键。
  • 超时后直接再次扣款或发邮件。

Q16:Tool Gateway 如何保证权限、参数和资源边界可追踪? ​

考察点

是否能把模型的意图变成经过多层校验的受控动作。

回答脉络

工具注册信息 -> schema 校验 -> 业务授权 -> 风险/审批 -> 执行隔离 -> 结果校验。

详细参考答案

Tool Gateway 为每个工具维护 owner、版本、风险等级、允许主体、资源范围、网络/文件能力、预算、超时和审批策略。收到调用后依次做 JSON Schema 类型校验、业务规则校验、资源归属校验、租户/主体授权、敏感字段检查和高风险确认。所有决策写入 tool_policy_decision span,记录策略版本、拒绝原因和参数摘要。

执行环境使用短期最小权限凭证、网络白名单、文件目录隔离、CPU/内存/时间/输出大小限制。工具返回后校验 response schema、业务状态和副作用证据,不能仅凭 HTTP 200 宣称成功。工具结果进入 Prompt 前再次标记来源和不可信内容,防止外部文本改变控制流。

常见追问及答案

  • 工具返回“已成功”就能更新任务吗? 还要根据业务系统事实或可验证回执确认,尤其是异步 202、超时和部分成功。
  • 参数已通过 Schema 是否足够? 不够。Schema 只能保证形状,不能保证用户有权访问资源、金额在额度内或动作经过确认。

扣分点

  • 让模型决定是否有权限。
  • 把 schema 校验当成安全校验。
  • 没有记录拒绝、审批和响应校验。

Q17:数据库读写如何在 Trace 中体现事务、版本和提交结果? ​

考察点

是否能区分 SQL 执行完成、事务提交和业务事实。

回答脉络

说明 DB span 字段、事务边界、乐观锁、Outbox 和提交后事件。

详细参考答案

数据库 span 记录服务名、数据库类型、操作类别、事务 ID 的不可逆摘要、表/逻辑资源、查询模板哈希、行数、锁等待、重试和耗时,不记录完整 SQL 参数中的敏感值。写操作必须携带 task_id、动作 ID、幂等键和当前版本条件;通过乐观锁或唯一约束防止旧 Worker 覆盖新状态。

业务状态、动作记录和 Outbox 事件在同一个事务中提交。只有提交成功后才发布“动作已记录”的事件;提交失败要明确是未生效还是结果未知。跨数据库或外部系统不能假设分布式事务,使用 Outbox、Saga、对账和补偿。Trace 中把“SQL 执行成功”“事务提交成功”“下游事实确认”分开记录。

常见追问及答案

  • 数据库返回影响行数为 0 怎么处理? 可能是版本冲突、资源不存在或已幂等完成,应重新读取并按状态机判断,不能直接当成功。
  • 事务回滚后需要保留日志吗? 要保留脱敏的失败事件和 Trace,说明未提交;不能让调试日志看起来像业务事实已发生。

扣分点

  • 日志打印完整 SQL 和参数。
  • 数据库更新成功就认为外部动作成功。
  • 没有版本条件、唯一约束或 Outbox。

Q18:外部 API 超时但可能已经成功,如何追踪和收口? ​

考察点

是否能处理“未知结果”而不是把网络错误等同于业务失败。

回答脉络

记录发送事实 -> 标记 UNKNOWN -> 查询/回调/对账 -> 成功、失败或人工终态。

详细参考答案

发送前把动作和幂等键写入动作表,生成 outbound span;收到响应则记录状态码、供应商 request ID 和业务回执。若连接在响应前中断,动作转为 UNKNOWN,Trace 标记 outcome=unknown,不直接重试副作用。随后按退避查询接口、接收 Webhook 或对账文件,所有确认都关联同一动作和原 Trace/任务。

如果查询确认成功,写入事实事件并推进任务;确认失败才允许按政策重试;长期无法确认则进入人工队列,保留影响范围和停止自动执行的标记。客户端看到的是“处理中/待确认”,不能看到伪造的成功或失败。告警关注未知动作数量和停留时间。

常见追问及答案

  • 外部 API 没有查询接口怎么办? 要求供应商提供幂等键、回执或对账能力;否则将动作列为不可自动重试的高风险能力,并设置人工收口。
  • 任务超时就能取消外部请求吗? 只能取消本地等待;外部请求是否停止取决于供应商协议,不能把本地取消当成业务回滚。

扣分点

  • 所有 timeout 都重试。
  • 把 HTTP 连接断开当作未发送。
  • 没有 UNKNOWN、查询或人工收口状态。

Q19:最终 Artifact 如何与输入、Trace、版本和权限关联? ​

考察点

是否能保证文件、报告、引用清单或结构化结果可验证、可撤销和可审计。

回答脉络

说明 Artifact manifest、内容哈希、来源引用、权限和交付事件。

详细参考答案

Artifact 使用不可变 artifact_id,manifest 记录 task_id、生成步骤、输入摘要、内容哈希、大小、媒体类型、创建时间、代码/模型/Prompt/RAG 版本、引用清单和数据分类。大对象存储只允许短期签名 URL 或受控下载服务访问;下载时再次检查租户、主体、权限版本和撤销状态。

Artifact 生成、上传、病毒扫描、索引和发布分别创建 span/事件,上传成功不代表已发布。回答中的引用必须指向对应 Artifact 版本或可验证的文档位置,不能因文件被覆盖而改变历史答案。删除请求通过 tombstone 和对象清理传播到缓存、搜索索引和下载链接,同时保留法规允许的审计摘要。

常见追问及答案

  • Artifact 可以覆盖同名文件吗? 物理对象应不可变,使用新版本和别名指向当前版本,避免旧 Trace 解析到新内容。
  • 如何防止用户篡改下载后的报告? 提供内容哈希、签名或 manifest,接收方可校验;高风险报告还应记录发布者和审批凭证。

扣分点

  • 只保存一个可变文件路径。
  • 签名 URL 长期有效或不检查权限。
  • Artifact 没有来源、版本和哈希。

Q20:Checkpoint 应该保存什么,哪些内容不应该保存? ​

考察点

是否能设计可恢复而不过度持久化的执行快照。

回答脉络

任务/步骤状态 -> 已确认事实 -> 下一步意图 -> 版本预算 -> 引用和安全上下文。

详细参考答案

Checkpoint 至少保存任务和步骤状态、状态机版本、最近确认的事件序号、当前轮次、已完成的工具动作 ID、外部动作状态、剩余预算、截止时间、权限/配置/知识版本快照、消息和 Artifact 引用、重试次数以及下一步可执行条件。对大 Prompt、文档和工具结果保存加密对象引用、长度和哈希,避免每次复制大上下文。

不能把未验证的模型计划当作业务事实,也不应保存长期凭据、原始 JWT、完整敏感附件或随意可执行的 Shell 命令。写入 checkpoint 要原子化并带版本;只有数据库提交、Artifact 完成或外部回执确认后,才能把相应事实标为已完成。

常见追问及答案

  • 每个 token 都 checkpoint 吗? 不需要。按步骤边界、外部副作用前后和可恢复粒度保存,流式 token 用短期缓冲或事件记录。
  • checkpoint 和日志有什么区别? checkpoint 是恢复所需的权威状态;日志/Trace 是诊断证据,可能采样,不能单独驱动恢复。

扣分点

  • 只保存最后一段模型文本。
  • 把日志当 checkpoint 使用。
  • 把未确认的外部写入标为成功。

Q21:Worker 恢复后如何判断从哪里继续? ​

考察点

是否能处理租约、fencing、重复事件和未知副作用。

回答脉络

租约校验 -> 读取快照 -> 检查动作事实 -> 选择重试/查询/人工 -> 新 checkpoint。

详细参考答案

恢复 Worker 必须先获取新的 lease/fencing token,旧 Worker 的迟到写入全部被拒绝。读取最新快照和事件后,按步骤分类:纯计算、幂等读和未开始步骤可以从 checkpoint 重试;已经提交数据库事务的步骤从提交后的状态继续;外部写入处于 UNKNOWN 时先查询或对账;审批、人工和外部回调步骤恢复到等待状态。

恢复决策写入 recovery_decision 事件,记录依据的 checkpoint、动作事实、重试次数、版本和操作者。若快照与事件不一致,以事务内的状态和业务事实为准,通过重放修复物化视图;不要让 Worker 自己根据模型文本猜测。

常见追问及答案

  • checkpoint 丢了怎么办? 使用事件、动作表和 Artifact manifest 重建最近可确认状态;无法确认的副作用进入人工而不是盲目补做。
  • 旧 Worker 恢复后还能继续吗? 不能直接写入,必须重新获取租约并从新快照重新判断。

扣分点

  • 总是从头重跑。
  • 没有 fencing token。
  • 不核对外部动作就重放写操作。

Q22:流式输出已经发送一半,客户端断开时如何追踪? ​

考察点

是否能区分传输中断、任务取消、模型停止和业务副作用。

回答脉络

记录发送游标 -> 检测断开 -> 取消策略 -> 任务状态 -> 重连补发。

详细参考答案

流式响应中的每个 chunk 或事件带 task_id、event_id、单调 sequence 和 schema 版本,服务端记录已生成、已发送和客户端确认的游标。检测到连接断开时写入 client_disconnected 事件,随后按产品策略决定继续后台执行、协作式取消或进入可恢复任务;不能因为 socket 关闭就假定模型和工具已停止。

如果流中已经触发工具或外部写,按动作状态处理,必要时继续查询确认。客户端重连携带 cursor,服务端从事件存储补发,过期游标则返回当前快照和可用 Artifact。对不可重放的增量内容,记录最终完整结果或摘要,避免重连造成重复副作用。

常见追问及答案

  • 客户端没收到最后一个 chunk,能否重发工具调用? 不能根据传输情况重发;先查 tool_call_id 和动作状态,再决定是否只补发事件。
  • 流式响应要不要保存全文? 依据隐私和产品需求,可以保存最终脱敏结果或引用,而不是永久保存每个 token。

扣分点

  • 断线直接 kill Worker。
  • 没有发送游标和重连协议。
  • 以“用户没看到”为由重新执行副作用。

Q23:如何设计可重放的 Trace 和事件,而不重放真实副作用? ​

考察点

是否理解重放是诊断/评估工具,不是把生产任务再执行一遍。

回答脉络

固定 manifest 和输入 -> 替换外部依赖 -> dry-run -> 比较轨迹。

详细参考答案

重放前冻结原任务的 manifest、Prompt/RAG/工具版本、输入摘要、权限策略和事件序列,并在隔离租户生成新的 replay ID。模型可以使用录制响应或受控调用;RAG 使用脱敏的索引快照;数据库使用只读快照;外部工具全部替换为模拟器,按原始响应、延迟、错误、重复和超时注入。高风险动作只输出“将执行的参数和策略结果”,不发送真实写请求。

比较结果时同时比较状态转移、工具选择、参数、引用、成本、延迟和安全决策,而不只比较自然语言。重放产物标记为实验数据,不能污染线上任务、账单和业务事件。若为了事故取证需要访问原文,遵守临时授权、脱敏和保留期限。

常见追问及答案

  • 模型有随机性,怎样判断回归? 固定可用种子和录制依赖,并使用轨迹级断言、关键字段和统计阈值,不要求自然语言逐字一致。
  • 为什么不能直接复制生产数据库? 可能扩大敏感数据和副作用范围,且无法隔离回放写入;优先使用快照、脱敏和模拟器。

扣分点

  • 用生产凭据重放工具。
  • 只比较最终文本。
  • 重放事件再次写入业务事件流。

Q24:流式中断、取消和超时如何形成一致的状态机? ​

考察点

是否能区分用户意图、传输状态和执行状态。

回答脉络

请求事件 -> 运行时取消 token -> 步骤边界 -> 外部动作收口 -> 终态。

详细参考答案

我会分别记录 client_disconnected、cancel_requested、deadline_exceeded、step_interrupted 和 external_action_unknown,而不是把它们都映射成 FAILED。客户端断开只表示传输层状态;用户主动取消表示业务意图;deadline 表示预算耗尽;步骤中断要说明是否可安全重试;外部动作未知需要查询或人工。

Runtime 通过取消 token 协作式通知模型、检索和工具,在安全边界检查后停止新步骤。不能中断的外部调用继续等待或进入 UNKNOWN,完成后由状态机决定 CANCELLED、SUCCEEDED 或 MANUAL_REVIEW。每次转移带当前版本和原因,终态不可被普通取消覆盖。

常见追问及答案

  • 超时后一定失败吗? 不一定;要区分本地计算超时、等待外部回执超时和整体 deadline。
  • 取消请求返回什么? 返回已受理和当前状态;只有状态机完成安全收口后才宣称已取消。

扣分点

  • 把 socket 断开当作任务取消。
  • 强杀进程造成未知副作用。
  • 没有不可中断步骤和人工收口状态。

六、综合设计与故障排查 ​

Q25:如何排查“用户说答案错了,但系统指标正常”的问题? ​

考察点

是否能从用户反馈反查版本、证据、权限、缓存和模型轨迹。

回答脉络

先锁定 task/trace,再按 manifest、Prompt、RAG、工具和输出校验逐层排查。

详细参考答案

先获取用户有权限的 task_id 和 trace_id,确认请求是否命中正确租户、主体、配置和知识版本。检查 Prompt manifest 是否发生裁剪、摘要或模板变更;RAG 侧查看原始/改写 query、候选数量、ACL 过滤、索引 release、rerank 和引用支持;缓存侧核对 key、权限版本和失效时间;模型侧检查响应 schema、停止原因、token 截断和工具调用。

如果答案声称执行了动作,继续查询 tool_call_id、动作表、DB 提交、外部 request ID 和 Artifact manifest,判断是文本错误、引用错误还是业务事实错误。最后将脱敏轨迹按根因分类,加入回归样本,并比较失败是否集中在某租户、语言、文档版本或缓存路径,而不是只看全局成功率。

常见追问及答案

  • 用户没有 trace_id 怎么办? 通过认证主体、时间窗口、task_id、请求摘要和网关日志定位,但要防止把同一用户的请求混淆。
  • 指标正常是否说明个案不重要? 不说明。长尾、高风险和少数租户的错误可能被总体均值掩盖。

扣分点

  • 只重新跑一次问题。
  • 只看模型输出,不查证据和业务事实。
  • 为了修复个案直接改线上 Prompt,无回归样本。

Q26:如何定位 TTFT 高、但下游模型耗时正常的问题? ​

考察点

是否能沿 Gateway、排队、Prompt、RAG、网关缓冲和流式发送分解延迟。

回答脉络

先定义时间点,再比较各 span 和队列/网络指标,最后给出消融实验。

详细参考答案

我会记录请求到达、认证结束、任务入队、Worker 领取、Prompt 完成、RAG 完成、模型请求发送、供应商首 token、Gateway 首字节和客户端首个有效内容等时间点。若模型服务端耗时正常而 TTFT 高,重点检查队列等待、冷启动、Query Rewrite、Multi-Query、Rerank、串行检索、Prompt 过长、连接池、TLS、代理缓冲和流式 flush。

按路径做消融:关闭改写、改为并行检索、减少 top-k、跳过非必要 rerank、启用连接复用和 Prompt Cache,并比较 P50/P95、质量和成本。Trace 中标记快速路径/复杂路径、缓存命中、降级和取消,不能只优化平均值。若网关缓冲导致客户端看不到 token,要同时检查 TTFB 和首个有效内容时间。

常见追问及答案

  • 首 token 快了但质量下降怎么办? 将延迟优化作为带质量门禁的实验;高风险问题保留复杂路径或按置信度升级。
  • 只看模型供应商的 TTFT 可以吗? 不可以,它不包含本地排队、检索、Prompt 组装和网关传输。

扣分点

  • 看到 TTFT 高就换更快模型。
  • 不拆时间点和队列等待。
  • 用首字节时间冒充用户看到有效内容的时间。

Q27:设计一个支持数据流追踪的企业 Agent Schema。 ​

考察点

是否能把任务、步骤、动作、事件、证据和产物设计成可查询的数据模型。

回答脉络

先列聚合根,再列不可变记录、唯一约束、版本和保留策略。

详细参考答案

可以拆成以下核心表或等价集合:

text
tasks(task_id, tenant_id, actor_ref, status, version, manifest_id, deadline)
steps(step_id, task_id, sequence, kind, status, attempt, checkpoint_ref, lease_token)
tool_calls(tool_call_id, step_id, tool_name, schema_version, args_hash, status)
external_actions(action_id, tool_call_id, idempotency_key, request_hash, status, provider_ref)
trace_links(trace_id, task_id, span_id, parent_span_id, service, start_at, end_at)
evidence(evidence_id, task_id, source_id, source_version, acl_version, locator, hash)
artifacts(artifact_id, task_id, manifest_id, content_hash, classification, status)
events(event_id, task_id, sequence, type, payload_ref, schema_version, occurred_at)

tasks 是当前快照,events 是可审计时间线,external_actions 用唯一 tenant_id + idempotency_key 约束副作用,evidence 保存引用和版本而非默认全文。Trace 明细通常放专业观测系统,通过 trace_id/task_id 关联;大对象放加密对象存储。状态更新、动作记录和 Outbox 事件在事务中提交,敏感字段采用引用、哈希和访问策略。

常见追问及答案

  • 为什么不把所有字段放一张 JSON 表? 长期查询、唯一约束、并发更新、审计和局部保留都会变困难;结构化核心字段配合不可变引用更稳妥。
  • Trace 表需要和业务数据库同库吗? 不必。重点是关联键、可靠投递和权限边界;业务事实不能依赖观测系统可用性。

扣分点

  • 没有租户、版本、唯一键和状态字段。
  • 把大 Prompt、附件和日志全文塞进任务表。
  • 没有把动作和证据单独建模。

Q28:如何为数据流追踪系统设计容量和成本预算? ​

考察点

是否能识别 Trace、事件、日志、对象和索引的增长来源。

回答脉络

请求量 -> span/event 数 -> 字节量 -> 保留和采样 -> 查询/导出成本。

详细参考答案

先估算峰值 RPS、平均模型轮次、每轮下游 span、工具重试、流式事件频率、每个任务的 Artifact 和证据大小。粗略存储量为“请求数 × 每请求记录字节 × 保留天数”,再加索引、复制、压缩和高峰缓冲。流式 token 不应每个 token 写一条长期事件,可按时间或语义批量聚合;Trace 采用头部采样加尾部按错误/高风险保留。

成本拆成采集、传输、索引、存储、查询、导出、模型、检索和工具费用。对大租户设置配额和预算,超限时降低普通成功 Trace 采样,但强制保留安全、未知副作用、恢复失败和高成本样本。定期验证采样不会破坏故障定位,保留策略与合规删除策略要有明确 SLA。

常见追问及答案

  • 为什么不把所有 Trace 永久保存? 成本、隐私和查询性能都会恶化;应按数据分类、风险和事故保留周期分层。
  • 采样会不会漏掉偶发事故? 对错误、尾延迟、权限拒绝和高风险动作采用尾部采样/强制采集,不能只做固定比例随机采样。

扣分点

  • 只按 QPS 估算,不算轮次、重试和事件频率。
  • 为降成本删除安全证据。
  • 没有保留、压缩、索引和查询预算。

Q29:一次 Trace 出现“权限允许但结果为空”,如何排查? ​

考察点

是否能区分权限误拦、数据新鲜度、索引版本、缓存和业务不存在。

回答脉络

比较权限快照、源系统、索引 release、缓存和删除事件,最后给出安全处理。

详细参考答案

先确认 Gateway 的主体、租户和权限版本,再检查 RAG/DB 查询使用的 ACL 版本和过滤条件。若源系统可见但索引无结果,查看同步延迟、解析失败、tombstone、索引 alias 和文档生效时间;若索引有候选但缓存为空,检查 cache key、TTL 和失效事件。若工具返回空,还要区分资源不存在、权限拒绝被统一隐藏和下游临时错误。

Trace 记录过滤数量、原因码、索引和缓存版本,而不记录未授权正文。高风险场景宁可返回“当前资料未找到或无权访问”,也不要通过错误消息泄露资源存在性。确认是系统误拦后补发索引或修复权限传播,并将样本加入回归。

常见追问及答案

  • 能否告诉用户“你没有权限”? 取决于资源存在性和产品策略;避免通过错误差异泄露敏感资源。
  • 为什么不能只扩大 top-k? 空结果可能来自版本、ACL、同步或缓存问题,扩大召回会增加成本和泄露风险。

扣分点

  • 看到空结果就放宽权限过滤。
  • 不区分源数据、索引和缓存。
  • 错误消息泄露文档存在性。

Q30:如何把数据流追踪建设成发布门禁,而不是事后查日志? ​

考察点

是否能把追踪字段、质量指标、安全和回滚串成持续治理闭环。

回答脉络

字段契约 -> 采集验证 -> 评估与门禁 -> 灰度观测 -> 事故回流。

详细参考答案

首先为 Gateway、Runtime、Prompt、RAG、Tool、DB、Artifact 定义版本化 schema 和必填字段:Trace/Task 关联、租户、配置快照、权限版本、错误码、成本和副作用状态。CI 中跑 schema/契约测试,确保新服务不会丢失关键上下文;发布前用回放和故障注入验证 checkpoint、幂等、流式重连和脱敏。

灰度期间设置硬门禁:跨租户暴露为零、无审批高风险调用为零、未知副作用在阈值内、关键字段完整率达标、P95 延迟/成本不超过预算。异常自动停止扩容、禁用高风险工具或回滚配置;保留 manifest 和 Trace 证据。事故和用户反馈脱敏后进入回归集,持续更新字段、策略和检测规则。

常见追问及答案

  • 字段完整率为何是质量指标? 缺少 task、版本或动作关联会让系统不可审计、不可恢复,即使最终答案看起来正确也不达标。
  • 如何避免门禁过于严格影响迭代? 按风险分层:低风险字段可告警,高风险权限、幂等和脱敏字段必须阻断;用采样和灰度控制成本。

扣分点

  • 只在事故后补日志。
  • 发布门禁只有接口成功率。
  • 没有 schema 版本、灰度、回滚和反馈回流。

结语 ​

数据流追踪的目标不是收集越多日志越好,而是让系统能够回答四个问题:这次请求使用了什么版本和权限;模型和检索依据是什么;哪些工具和数据库动作真实发生了;如果中断或出错,怎样安全恢复并证明结果。把 trace_id、task_id、tool_call_id 和 idempotency_key 放进正确的状态、事件和业务边界,才能让 AI 应用从“能跑”变成可解释、可审计、可运营的企业系统。

持续学习,持续实践。