Agent 面试深度指南:三个问题背后的工程认知

从生产级 Agent Loop 稳定性、状态快照与回滚策略、Self-Healing 三个核心问题切入,拆解 Agent 系统的工程本质。不是八股文,是真刀真枪的实践经验

#Agent#LLM#系统设计#工程实践#面试

Agent 面试深度指南:三个问题背后的工程认知

问题一:怎么保证 Agent Loop 的稳定?

为什么这个问题能筛掉大部分人

很多人对 Agent 的理解止步于一个 ReAct 循环:

TYPESCRIPT
// ReAct 循环 —— demo 级别,生产环境不可用
async function reactLoop(observation: string): Promise<Action> {
  while (true) {
    const action = await llm.predict(observation);
    if (action.isFinal) {
      return action;
    }
    observation = await tool.execute(action);
  }
}

这个 demo 级别的代码在真实环境里几乎无法存活。真正跑过生产 Agent 的人都知道,这个循环里每一个接口都可能出问题,而且问题不是 " 偶尔 ",是 " 一定会在某个时刻 " 发生。

真实生产环境的 "dirty work" 清单

故障场景表现触发条件
死循环Agent 在两个工具间反复横跳,或重复调用同一工具工具描述模糊、LLM 对结果理解偏差、缺乏终止条件
上下文溢出单轮 token 数超过模型上限,API 返回 400 错误长会话未做 compaction、工具返回超大结果、历史消息无限累积
模型 API 异常429 Rate Limit、500 内部错误、响应超时流量突增、模型厂商维护、网络抖动
工具调用失败工具返回 500/404、参数格式错误、权限不足下游服务变更、LLM 生成非法参数、认证过期
SSE/流式推送卡住客户端长时间收不到数据,连接假死移动网络切换、代理服务器缓存、心跳缺失
幻觉导致的错误行动Agent 调用不存在的工具、构造非法 JSON模型能力边界、prompt 描述歧义、上下文干扰

能回答多少,全看自己真正处理过多少 dirty work。

生产级 Agent Loop 的七层防护体系

1. 循环硬边界:永远不要信任 while True

TYPESCRIPT
const MAX_STEPS = 30; // 根据任务复杂度设置

async function agentLoopWithHardLimit(observation: string): Promise<Action | PartialResult> {
  for (let step = 0; step < MAX_STEPS; step++) {
    const action = await agent.step(observation);
    if (action.isTerminal) {
      return action;
    }
    observation = await environment.execute(action);
  }
  // 触发 step limit,返回部分结果或转入人工
  return {
    type: "partial",
    observation,
    reason: "max_steps_reached",
  };
}
  • max_steps 必须是硬限制,不是建议值——达到即强制终止
  • 不同任务类型设置不同的上限:简单问答 10 步,代码生成 50 步,数据分析 30 步
  • 达到上限时的策略:返回部分结果、降级为静态回复、或转人工

2. 死循环检测:识别重复模式

TYPESCRIPT
// 检测同一工具+参数组合的重复调用
const actionHistory = new Map<string, number>(); // key: `${tool_name}:${params_hash}` -> count

async function detectLoop(action: Action): Promise<void> {
  const key = `${action.toolName}:${hashParams(action.params)}`;
  const count = (actionHistory.get(key) ?? 0) + 1;
  actionHistory.set(key, count);

  if (count > MAX_REPEATS) {
    throw new LoopDetectedError("检测到循环调用,转入人工处理");
  }
}

更精细的检测手段:

  • 工具级去重:同一工具连续调用超过 2 次即告警
  • 状态哈希去重:对 observation 做哈希,检测是否回到之前的状态
  • 语义级去重:用 embedding 检测前后两轮 action 的语义相似度

3. 差异化重试:不同错误不同对待

这是生产 Agent 与 demo 的核心区别之一:

错误类型根因正确策略错误策略
429 Rate Limit请求过快指数退避 + jitter,1s → 2s → 4s立即重试(加剧问题)
400 Bad Request请求参数非法不重试,修复参数格式或 prompt盲目重试(同样报错)
500 Server Error服务商内部故障有限重试(2-3 次)后熔断无限重试(资源耗尽)
Timeout网络/计算延迟先检查操作是否实际已执行(幂等性),再决定重试直接重试(可能导致重复写入)
Hallucination模型幻觉不要原 prompt 重试,改用约束更强的 prompt 或换模型同样 prompt 重试(大概率再幻觉)
TYPESCRIPT
type RetryStrategy =
  | { type: "exponential_backoff"; maxRetries: number; baseDelayMs: number }
  | { type: "no_retry" }
  | { type: "fixed_retry"; maxRetries: number }
  | { type: "conditional_retry"; checkIdempotency: boolean }
  | { type: "rephrase_and_retry"; model: string };

function resolveRetryStrategy(error: AgentError): RetryStrategy {
  if (error instanceof RateLimitError) {
    return { type: "exponential_backoff", maxRetries: 5, baseDelayMs: 1000 };
  }
  if (error instanceof BadRequestError) {
    return { type: "no_retry" }; // 直接返回错误
  }
  if (error instanceof ServerError) {
    return { type: "fixed_retry", maxRetries: 3 };
  }
  if (error instanceof TimeoutError) {
    return { type: "conditional_retry", checkIdempotency: true };
  }
  if (error instanceof HallucinationError) {
    return { type: "rephrase_and_retry", model: "stronger_model" };
  }
  return { type: "fixed_retry", maxRetries: 3 };
}

4. 熔断器模式(Circuit Breaker)

当某个依赖(模型 API、工具服务)持续失败时,继续重试只会浪费资源。熔断器提供三种状态:

  • Closed(闭合):正常通行,持续监控失败率
  • Open(断开):失败率超过阈值(如 5 次连续失败),直接拒绝请求,fail-fast
  • Half-Open(半开):经过冷却时间(如 30 秒),放少量探测请求通过,验证服务是否恢复
TYPESCRIPT
// 熔断器状态机
type CircuitState = "CLOSED" | "OPEN" | "HALF_OPEN";

interface CircuitBreakerConfig {
  failureThreshold: number;    // 连续失败阈值
  recoveryTimeoutMs: number;   // 恢复等待时间
  halfOpenMaxCalls: number;    // 半开状态探测请求数
}

class CircuitBreaker {
  private state: CircuitState = "CLOSED";
  private failureCount = 0;
  private lastFailureTime?: number;
  private halfOpenCalls = 0;

  constructor(private config: CircuitBreakerConfig) {}

  async execute<T>(fn: () => Promise<T>): Promise<T> {
    if (this.state === "OPEN") {
      if (Date.now() - (this.lastFailureTime ?? 0) > this.config.recoveryTimeoutMs) {
        this.state = "HALF_OPEN";
        this.halfOpenCalls = 0;
      } else {
        throw new CircuitOpenError("熔断器处于 OPEN 状态,快速失败");
      }
    }

    if (this.state === "HALF_OPEN" && this.halfOpenCalls >= this.config.halfOpenMaxCalls) {
      throw new CircuitOpenError("半开状态探测配额已用尽");
    }

    if (this.state === "HALF_OPEN") {
      this.halfOpenCalls++;
    }

    try {
      const result = await fn();
      this.onSuccess();
      return result;
    } catch (err) {
      this.onFailure();
      throw err;
    }
  }

  private onSuccess(): void {
    this.failureCount = 0;
    if (this.state === "HALF_OPEN") {
      this.state = "CLOSED";
      this.halfOpenCalls = 0;
    }
  }

  private onFailure(): void {
    this.failureCount++;
    this.lastFailureTime = Date.now();
    if (this.failureCount >= this.config.failureThreshold) {
      this.state = "OPEN";
    }
  }
}

// 使用
const circuit = new CircuitBreaker({
  failureThreshold: 5,      // 5 次连续失败触发熔断
  recoveryTimeoutMs: 30000, // 30 秒后尝试恢复
  halfOpenMaxCalls: 2,      // 半开状态最多 2 个探测请求
});

const result = await circuit.execute(() => openai.chat.completions.create(prompt));

熔断器的生产价值:

  • 防止一个挂掉的下游服务拖垮整个 Agent 系统
  • 与降级策略配合:主模型熔断时自动切换到备用模型
  • 为系统恢复争取时间窗口

5. 超时控制:永远不要无限等待

TYPESCRIPT
// 分层超时设计(单位:毫秒)
const TIMEOUTS = {
  TASK: 120_000,           // 整个任务 2 分钟
  STEP: 30_000,            // 单步 30 秒
  LLM_CALL: 15_000,        // LLM 调用 15 秒
  TOOL: 10_000,            // 工具执行 10 秒
  SSE_HEARTBEAT: 60_000,   // SSE 心跳超时 60 秒
} as const;

// 带超时的 Promise 包装器
async function withTimeout<T>(promise: Promise<T>, ms: number, context: string): Promise<T> {
  const timeout = new Promise<never>((_, reject) =>
    setTimeout(() => reject(new TimeoutError(`${context} 超时 (${ms}ms)`)), ms)
  );
  return Promise.race([promise, timeout]);
}

SSE/流式连接的特殊处理:

  • 心跳机制:服务端定期发送 :heartbeat\n\n,客户端检测心跳中断即重连
  • Last-Event-ID:断线重连时携带上次接收的 event ID,服务端补发遗漏数据
  • 指数退避重连:1s → 2s → 4s → 最大 30s,避免重连风暴

6. 优雅降级:坏了也要给出最优解

当 Agent 的核心能力受损时,不是直接报错,而是尽可能提供有用的响应:

故障组件降级策略
主模型不可用切换到备用模型(Claude → GPT → Gemini),或降级到更小模型
工具服务不可用告知用户 " 暂时无法查询实时数据,但我可以基于已有知识回答 "
RAG 检索失败直接用模型内置知识回答,不阻塞用户
记忆系统不可用仅使用当前会话上下文继续对话
所有自动化都失败返回结构化错误信息 + 转人工的入口

7. 上下文溢出防护:Compaction 是必选项

Agent 每轮循环都在累积历史消息,最终必然触及模型上下文上限。生产系统必须在达到上限前主动 compaction:

  • 滑动窗口:保留最近 N 轮对话,丢弃更早的
  • 工具结果折叠:保留工具调用记录但清空原始返回数据(尤其是大文件内容)
  • 摘要替换:用廉价模型(如 Haiku/4o-mini)对历史对话做摘要,用摘要替代原文
  • Head+Tail 策略:保留系统提示和初始任务(head)以及最近几轮(tail),丢弃中间部分

面试中这样答

初级回答:" 加 try-catch 和重试。"

深度回答

  1. 首先定义 Agent Loop 的故障分层——基础设施层(API 超时、网络抖动)、模型层(幻觉、输出格式错误)、工具层(工具调用失败、返回异常)、编排层(死循环、上下文溢出)
  2. 每一层有对应的防护策略:基础设施层用熔断器 + 指数退避,模型层用输出校验 + prompt 约束,工具层用参数校验 + 备选工具,编排层用 max_steps + 循环检测
  3. 补充一个你在生产里实际遇到的案例:比如某次工具返回了 10MB 的 JSON 导致上下文溢出,你们是怎么通过 tool result truncation + compaction 解决的
  4. 强调观测的重要性——没有监控的防护都是盲打,需要跟踪 error rate、retry frequency、fallback rate、latency percentile 等指标

问题二:你在 Agent 的 Context 里面放了哪些东西?

这个问题在考察什么

Context Engineering 是 Agent 工程中最被低估的核心能力。同样一个 GPT-4o,context 放得好与不好,效果可能相差一个数量级。

这个问题能自然触及 Skills、MCP、RAG、Memory 等核心概念——如果一个人只能答 " 放系统提示和用户消息 ",基本确定只做过 demo。

Context 的分层架构

生产级 Agent 的 context 不是一个长字符串,而是一个分层组装、按需加载的结构:

Plain Text
┌─────────────────────────────────────────────────┐
│  Context Window (有限的宝贵资源)                  │
├─────────────────────────────────────────────────┤
│  Layer 1: System Prompt (系统指令)                │
│  - Agent 的身份、行为准则                          │
│  - 输出格式约束、安全策略                          │
│  - 稳定存在,适合缓存                              │
├─────────────────────────────────────────────────┤
│  Layer 2: Active Tools / MCP (工具层)            │
│  - 当前可用的工具描述 (JSON Schema)                │
│  - MCP Server 动态发现的工具                       │
│  - 按需加载:复杂任务加载更多工具                   │
├─────────────────────────────────────────────────┤
│  Layer 3: Retrieved Context (RAG)                │
│  - 从向量数据库检索的 top-k 相关文档               │
│  - 动态变化,每轮可能不同                          │
├─────────────────────────────────────────────────┤
│  Layer 4: Memory (记忆层)                         │
│  - Short-term: 当前会话的近期消息                   │
│  - Long-term: 跨会话的用户偏好、历史决策             │
│  - Episodic: 关键事件、成功经验/失败教训             │
├─────────────────────────────────────────────────┤
│  Layer 5: Session History (会话历史)              │
│  - 当前任务的对话轮次                              │
│  - 经 compaction 处理的压缩历史                    │
└─────────────────────────────────────────────────┘

每一层的设计要点

1. System Prompt:稳定、精确、可缓存

Plain Text
你是 {product} 的 AI 助手,专门帮助用户解决 {domain} 问题。

## 行为准则
1. 优先使用 search_knowledge_base 工具查询知识库
2. 如果知识库无结果,明确告知用户"知识库中未找到相关信息"
3. 禁止编造不存在的产品功能
4. 每次回复使用结构化格式:问题分析 → 解决方案 → 相关链接

## 安全策略
- 遇到账号/密码相关请求,引导用户联系客服
- 涉及退款/投诉,自动触发工单创建工具

## 输出格式
{"analysis": "...", "solution": "...", "references": [...]}

设计原则:

  • 放在 context 最前面,最大化 prefix caching 的命中率
  • 保持长期稳定,减少 cache invalidation
  • 用结构化格式(Markdown/XML/JSON),LLM 对结构化指令的理解远好于纯文本

2. Tools / MCP:按需加载,而非全部塞入

不是所有工具都要每轮都塞给模型。工具描述很占 token(一个复杂工具可能 500-2000 tokens),工具多了 context 很快就满。

按需加载策略

  • 静态加载:核心工具(搜索、计算)始终保留
  • 动态加载:根据用户意图识别,只加载相关工具。例如用户问代码问题,加载代码相关工具;问财务问题,加载财务工具
  • MCP 动态发现:通过 MCP Server 在运行时动态获取可用工具列表,而非硬编码
TYPESCRIPT
interface Tool {
  name: string;
  category: string;
  description: string;
}

interface Intent {
  categories: string[];
  confidence: number;
}

// 工具选择:用廉价模型做意图分类,按需加载工具
async function selectTools(userQuery: string, availableTools: Tool[]): Promise<Tool[]> {
  const intent: Intent = await classifyIntent(userQuery, availableTools); // 用 Haiku,~$0.001
  return availableTools.filter((tool) => intent.categories.includes(tool.category));
}

MCP 的定位

MCP(Model Context Protocol)是 Anthropic 推动的开放标准,用于标准化 Agent 与外部工具的集成。核心价值:

  • 标准化:Agent 不需要为每个工具写自定义集成,MCP Server 提供统一接口
  • 动态发现:Agent 运行时动态发现 MCP Server 提供的工具
  • 安全隔离:工具执行在独立进程中,通过 stdio/SSE 通信,降低安全风险
  • 生态复用:社区已有大量 MCP Server(GitHub、Slack、数据库、文件系统等)

面试时提到 MCP 说明你对 Agent 工具集成的前瞻架构有了解——但要注意,MCP 目前还在快速发展阶段,生产环境使用需要考虑稳定性。

3. RAG:检索什么、怎么检索

RAG 不是 " 把向量数据库接进来 " 这么简单:

  • 分块策略(Chunking):按段落、语义、或固定 token 数分块?不同策略影响检索精度
  • Embedding 模型选择:OpenAI text-embedding-3-large、BGE、M3E 等,需要根据领域数据测试
  • 重排序(Rerank):先用向量检索 top-20,再用 cross-encoder 重排取 top-5
  • 元数据过滤:按用户权限、文档类型、时间范围做前置过滤
  • 上下文压缩:检索到的文档 chunk 可能很长,需要摘要或提取关键段落后再放入 context

4. Memory 层:短期记忆与长期记忆

短期记忆(Short-term Memory)

  • 当前会话的对话历史
  • 存在内存中,速度快,会话结束即清除
  • 容量有限,需要 sliding window 或 compaction

长期记忆(Long-term Memory)

  • 跨会话持久化的用户偏好、事实、经验
  • 存储在外部数据库(PostgreSQL、Redis、向量数据库)
  • 通过 embedding 检索按需加载

记忆的类型

类型内容存储方式检索方式
Semantic用户偏好、产品偏好、身份信息向量数据库 + 键值存储Embedding 相似度搜索
Episodic关键对话片段、成功经验、失败教训向量数据库 + 时间索引按主题 + 时间检索
ProceduralAgent 的操作流程、工具使用模式规则引擎 / 少样本示例按任务类型匹配

长期记忆的防损坏策略

这是追问点——" 怎么保证长期的 Memory 记忆不坏掉?"

  1. 写入验证:记忆写入前 LLM 做质量校验,过滤低质量、矛盾的信息
  2. 版本控制:重要记忆保留历史版本,可回滚到之前的状态
  3. 冲突检测:新记忆与已有记忆矛盾时,触发冲突解决流程(人工确认或 LLM 仲裁)
  4. 定期清理:基于时间衰减(90 天未访问降低权重)和重要性评分清理过期记忆
  5. 摘要合并:定期用 LLM 将多条相关记忆合并为高质量摘要
  6. 人类审核:对关键业务记忆设置人工审核节点

5. Session History: compaction 的艺术

Session History 是上下文消耗的大头,compaction 策略直接影响 Agent 的长期表现:

策略做法优点缺点
Sliding Window保留最近 N 轮,丢弃更早的简单高效可能丢弃关键历史信息
Head+Tail保留开头(任务定义)和结尾(最近几轮),丢弃中间兼顾任务定义和最新上下文中间过程丢失
Tool Result Clearing保留工具调用记录但清空详细返回数据大幅减少 token无法回溯工具执行细节
Summarization用廉价模型对历史做摘要保留信息密度摘要可能丢失关键细节(幻觉风险)
Semantic Selection用 embedding 检索与当前查询相关的历史消息保留真正相关的上下文增加检索开销

Claude Code 的五层 compaction pipeline 是目前业界比较先进的实践:

  1. Tool Result Compaction(折叠旧工具结果)
  2. Summarization(摘要旧对话)
  3. Sliding Window(保留最近 N 轮)
  4. Truncation(硬截断兜底)
  5. 每层按触发条件渐进式执行,gentle 策略优先

Context 组装的最佳实践

  1. 稳定内容在前,可变内容在后:系统提示、工具定义放前面,用户消息、检索结果放后面,最大化 prefix caching
  2. 给内容打标签:用 XML 标签包裹不同层的内容,帮助模型理解结构
  3. 控制总长度:预留 20% 的 context window 余量,避免触发 compaction 的紧急情况
  4. 敏感信息隔离:在 context 中标记隐私数据,确保不会出现在日志或缓存中

面试中这样答

初级回答:" 放系统提示、工具描述、用户消息。"

深度回答

  1. 把 context 理解为一个分层组装的管道,每一层有不同的生命周期和加载策略
  2. 从 System Prompt(稳定、可缓存)→ Tools/MCP(按需加载)→ RAG(动态检索)→ Memory(按需检索)→ Session History(需 compaction)逐层讲解
  3. 主动提及 MCP 的价值和局限——标准化工具接入、动态发现、但仍在快速发展
  4. 重点讲 Memory 的设计:短期 vs 长期、semantic/episodic/procedural 三种类型、长期记忆的防损坏策略(写入验证、版本控制、冲突检测、定期清理)
  5. 讲一个你做过的 context optimization 案例:比如发现工具描述占用了 60% 的 context,通过动态工具选择减少了 50% 的 token 消耗

问题三:如何控制 Agent 的成本?

为什么这是必修课

真正做过 Agent 的人,肯定深知 token 成本远超其他所有基础设施——CI/CD、服务器、数据库加起来一年的成本可能都不如你一个月的 token 账单。

以一个实际场景为例:一个 200 步的 Agent 会话,用 Claude Opus 4(22.50/会话**。如果每天有 1000 个活跃用户,月成本接近 3-5/会话,月成本降至 $9-15 万——节省了 70-85%。

Agent 成本优化的五大杠杆

杠杆一:Prompt Caching(最高性价比,优先实施)

Prompt Caching 的原理:模型对输入做 attention 计算时会生成 KV Cache,如果前后两次请求的前缀相同,可以复用 KV Cache,只需处理新变化的 tokens。各厂商实现:

厂商实现方式Cache Read 折扣Cache Write 成本TTL
Anthropic显式 cache_control 断点90% 折扣1.25x 输入价格5 分钟(可续期)/ 1 小时
OpenAI自动缓存(无需代码改动)~50-90% 折扣免费5-10 分钟 / 最长 24 小时
Gemini显式 Context Caching API90% 折扣有写成本可配置,最长数小时
DeepSeekContext Caching API98% 折扣有写成本视具体模型

关键策略

  • Anthropic 的显式缓存:在 system prompt 和工具定义上设置 cache_control: {type: "ephemeral"} 断点。适合多轮对话和 Agent 工具循环场景——每轮工具调用都复用相同的 system prompt + tools 前缀
  • Gemini 的显式 vs 隐式缓存
    • 显式缓存:适合大文档问答场景,先创建缓存(一次性写成本),后续查询复用
    • 隐式缓存:适合对话历史自动复用,无需额外配置
    • 判断标准:如果文档 > 32K tokens 且会被多次查询,显式缓存更划算;小文档或一次性查询不需要缓存
  • OpenAI 的自动缓存:最简单,prompt > 1024 tokens 自动触发,零代码改动

实战建议

  1. 把稳定内容(system prompt、tools)放在 prompt 最前面
  2. 可变内容(用户消息、检索结果)放在后面
  3. 确保 cache prefix 字节级一致——任何微小变化都会导致 cache miss
  4. Cache hit 率低于 50% 时排查 prompt 结构是否稳定

杠杆二:Model Routing(模型路由,最大节省潜力)

不是所有任务都需要最强模型。一个分类任务用 GPT-4o-mini 和 GPT-4o 的结果可能一样,但成本相差 94%

三级路由策略

Plain Text
┌─────────────────────────────────────────────────┐
│  用户请求                                        │
├─────────────────────────────────────────────────┤
│  Step 1: 意图分类(Haiku / 4o-mini, $0.001)    │
├────────────┬────────────────────┬───────────────┤
│  简单任务   │    中等复杂度       │   复杂任务     │
│  10-20%    │     50-60%         │   20-30%      │
├────────────┼────────────────────┼───────────────┤
│  Haiku     │   Sonnet / 4o      │  Opus / o1    │
│  $1/M      │   $3/M             │  $5-15/M      │
└────────────┴────────────────────┴───────────────┘

路由的实现方式

  1. 规则路由:基于关键词、正则、或请求类型硬编码规则(零成本,适合场景明确)
  2. 分类器路由:用一个小模型做复杂度分类,再路由到对应模型(每次分类 $0.001,可忽略)
  3. 置信度路由:先用廉价模型回答,如果置信度低于阈值,再用强模型重试
  4. 级联路由(Cascading):廉价模型 → 中等模型 → 强模型,逐级升级直到质量达标

面试要点:要能讲出路由的质量监控——不能只管省钱不管质量。需要:

  • 离线评估:定期抽样对比不同模型的输出质量
  • 在线监控:跟踪用户满意度、下游任务成功率
  • 逃逸舱:允许用户或特定功能强制使用最强模型

杠杆三:Context Compaction(上下文压缩)

Agent 会话越长,每轮的 input tokens 越多(因为要发送完整历史)。Compaction 的目标是在不丢失关键信息的前提下减少 token 数:

  • Summarization:用廉价模型(Haiku/4o-mini)对历史对话做摘要,替代原始消息
  • Tool Result Truncation:工具返回超大结果时截断或摘要(如代码搜索结果只保留前 10 条)
  • Selective History:只保留用户消息和关键工具调用,丢弃中间推理过程
  • Context Folding:子任务完成后折叠为摘要,不保留中间步骤

效果:compaction 通常能减少 50-70% 的上下文 tokens。

杠杆四:Batch Processing(异步场景)

OpenAI 和 Anthropic 都提供 Batch API,异步处理可接受延迟的任务,统一 50% 折扣

适用场景:

  • nightly 报告生成
  • 大批量文档分类/标注
  • 历史数据清洗
  • 评估测试集

Batch + Caching 可叠加:batch 折扣 + cache read 折扣 = 最高 95% 的节省。

杠杆五:Prompt Optimization(精细打磨)

  • 精简 system prompt:从 2000 tokens 压缩到 800 tokens,不影响效果
  • 要求结构化输出:用 JSON/XML schema 约束输出,减少无效内容
  • Tool description 优化:删除工具描述中的冗余信息,保留关键字段
  • 避免重复:不要把同样的指令在 system prompt 和 few-shot 中重复

成本优化的 ROI 计算

用一个 Agent 会话的成本变化来说明五大杠杆的叠加效果:

优化阶段Input CostOutput Cost总成本/会话累计节省
基线(全部 Opus,无优化)$20.00$2.50$22.500%
+ Model Routing$6.40$1.60$8.0064%
+ Context Compaction$2.56$1.60$4.1681%
+ Prompt Caching$0.50$1.60$2.1091%
+ Batch(异步场景)$0.25$0.80$1.0595%

数字来源:基于 Anthropic Opus 3/M、Haiku $1/M 的定价计算,假设 200 步/会话,平均 20K input tokens/步。

成本监控体系

优化前先测量——不能优化你测量不了的东西:

指标用途告警阈值
Cost per request定位高成本请求超过基线 2x
Cost per user识别异常用户单日超过阈值
Cache hit rate验证缓存效果低于 50%
Model distribution验证路由效果强模型占比异常升高
Token per request检测 context 膨胀持续增长趋势

面试中这样答

初级回答:" 用更便宜的模型。"

深度回答

  1. 先强调成本结构认知:token 成本是 Agent 最主要的成本项,远超基础设施
  2. 五大杠杆按优先级排序:Caching(最高 ROI)→ Model Routing(最大节省潜力)→ Compaction(解决上下文膨胀)→ Batch(异步场景)→ Prompt Optimization(持续打磨)
  3. 详细讲 Caching 的厂商差异:Anthropic 显式断点(90% off)、OpenAI 自动(零改动)、Gemini 显式/隐式的选择策略——比如大文档 QA 场景下 Gemini 显式缓存什么时候创建更合适(文档 > 32K tokens 且多次查询时)
  4. 讲 Model Routing 的质量保障:不能只看省钱,要有离线评估、在线监控、逃逸舱机制
  5. 给出一个你实际做过的 ROI 数字:比如 " 通过 routing 60% 流量到 Haiku + caching system prompt,我们把月度 API 账单从 1.2 万 "

总结:三个问题背后的共同认知

这三个问题分别对应 Agent 工程的三个核心维度

问题维度核心能力
Loop 稳定可靠性工程故障分层、防护体系、可观测性
Context 设计系统工程架构分层、按需加载、状态管理
成本控制经济学思维ROI 计算、杠杆优先级、量化决策

真正做过 Agent 的人,会在回答中自然流露出这些特质:

  1. 分层思维——不是给一个银弹方案,而是分层次、分场景地讨论 trade-off
  2. 量化意识——不只是说 " 能省钱 ",而是能算出省多少、怎么衡量
  3. 务实的悲观——默认一切都会出问题,系统设计围绕故障场景展开
  4. 持续迭代——不存在一劳永逸的方案,优化是持续过程

最后,原文说得好:认知和执行力从来就是不分家的。这三个问题的答案不需要背诵,它们来自你在生产环境里一次次踩坑、调试、优化的真实经历。如果你还没做过,至少先在面试前动手搭一个 Agent,跑长一点会话,看看哪些问题会出现——这比看一百篇博客都有效。


参考资源

最后更新于: 2026-05-09