关于 Tool Use 的 Agent 工程师面试题目
那些面试题,筛的不是候选人,筛的是老实人
朋友半夜给我发消息。
说他正在给几个大厂做Agent方向的面试官培训,翻了一圈他们准备的题,直接笑出了声。
“什么是Function Calling?”
“ReAct和CoT有什么区别?”
“MCP协议解决了什么问题?”
——你说,这背书呢还是招人呢?
他说去年招了三个能把这些问题答得滚瓜烂熟的候选人,结果进项目第一个月,就把线上Agent全跑崩了。
一个工具调用失败后不知道回退,直接把生产数据库搞成了只读模式。
另一个更狠。让模型在循环里连续调了四十多次API。账单出来的时候,CTO脸都绿了。
你那些面试题,筛的压根不是聪明人。筛的,是老实人。
第一层:这人写没写过真实代码?
我面试的时候,从来不问概念。
我就直接甩一句:“你最近那个Agent项目里,工具调用的最长链路是几步?每步的回退策略是什么?”
很多人立马卡壳。
能说出“我用过OpenAI的天气查询Demo”的,基本没跑过真实项目。你信我,这种一进项目组就露馅。
真正干过活的,张嘴就来——
“我们需要先查数据库获取用户信息,然后根据用户等级决定调哪个价格API,拿到价格后要校验库存,最后还要走审批流程。每一步我都设了超时重试,重试三次失败就降级调缓存接口。”
听到这种回答,我先在心里给他鼓个掌。
去年我面了大概四十多号人。能说到这个细节的,一只手数得过来。
大部分人的回答停留在一个层面上:“我用了tools参数,传了一个JSON Schema进去。”
“那成功率多少?”
“大概80%吧。”
“给我讲一个失败案例。”
——开始支支吾吾。
你要没在生产环境里被工具调用折磨过,绝对说不出这种话:
“有时候模型会把参数格式搞错,比如日期填成2024/13/01,我不得不在工具层再加一层参数校验。”
你看,真实世界就是这么恶心。
我自己的项目里,工具调用的成功率从85%提到97%。靠的不是模型变强了,是整整加了三层防御——输入校验、输出校验、结果兜底。
所以面试官们,能不能别问“你用过Function Calling没”这种废话了?直接问踩过什么坑,比什么都管用。
第二层:你分得清“能用”和“好用”吗?
说到这儿,很多人爱把原生Function Calling和ReAct Prompting的区别背得滚瓜烂熟。什么“原生更省Token”、“ReAct更灵活”。
但你要是问我实操感受,我会告诉你另一件事。
原生Function Calling最大的优势,不是省Token。
是它把“说话”和“动手”分开了。
你想想看,如果模型一边在思考“我需要查一下天气”,一边又在回复用户“好的,我这就帮你查”——输出里夹着思维链和对话文本,下游解析起来有多痛苦?
我有个项目,最开始用纯Prompt做ReAct。
结果模型每轮都输出:“我需要调用X工具来获取Y信息,让我们开始吧!好的,现在调用:……”
就为了解析这一句废话,我写了四五十行正则。
换成原生Function Calling之后,代码直接从一百多行缩到了二十行。
不是模型变聪明了,是输出结构清晰了,状态机简单了。
但反过来也有坑。
原生Function Calling对复杂工具的描述能力有限。我试过让一个工具描述超过800个Token,模型直接不认了,给了一个空列表。
最后还是得靠Prompt工程打补丁。把最常用的工具写在System Prompt里,次要的才走tools参数。
你说这事儿讽刺不讽刺?你以为标准方案能解决一切,结果发现还得回到“能用”和“好用”之间找平衡。
有人跟我说:“现在模型能力越来越强,这些问题慢慢就没了。”
我只能说,天真。
模型越强,人越想让它干更复杂的事。 你今天觉得800个Token的工具描述是天花板,明天就有人给你塞2000个Token的描述进去。这个循环永远不会停。
第三层:你是真懂MCP,还是只会背概念?
MCP这玩意儿,现在面试都快被问烂了。
十个候选人,九个能说出“标准化协议、解决N乘M集成问题”。
但我追问一句:“那你用MCP部署过几个工具服务?”
——没人吭声。
我今年年初在自己的项目里试了一把MCP。
说实话,挺操蛋的。
首先它的Server端写得不够完善。我试了Anthropic官方的Python SDK,发现默认的超时时间是30秒。我那工具是个内部数据分析,跑个复杂查询动不动就要一两分钟。
结果Claude Desktop那边早断连了。
后来我翻代码才发现,得自己重写Transport层。一个简单的超时配置,折腾了我两天。
但这不代表MCP不好。
相反,我特别看好这个方向。
原因很简单:它让工具和模型解耦了。
以前你要用LangChain的一套Tool规范,后来换LlamaIndex又得重新写。现在只要实现一次MCP Server,啥Client都能接。
我现在的做法是:先把所有内部工具都用MCP封装一遍,然后统一注册到一个Gateway服务里。
前端Agent不管用的是Claude还是GPT还是开源模型,只要实现MCP Client,就能无缝调用所有工具。
这件事做到位了,你就再也不用操心“换模型要改工具集成代码”这种破事了。
但你说MCP是不是银弹?
当然不是。
它目前最大的问题,是没有解决好工具调用的权限控制和审计日志。
你通过MCP调了一个数据库查询工具——谁调的?查了什么数据?结果返回了什么?这些信息MCP默认是不记录的。你得自己在Server端手动加上。
所以面试官要真想考MCP,别问协议定义了。
直接问:“你部署MCP Server的时候,日志怎么记录的?权限怎么管理的?”
能把这个答清楚的,才是真干过活的人。
第四层:你的Agent跑十步之后还靠谱吗?
这是我觉得目前Agent面试最翻车的地方。
很多人能把ReAct的原理讲得天花乱坠,能把Plan-Then-Act、ReAct+规划、Tree Planning的区别说得头头是道。
但你一问:“你的Agent跑了十步之后,还能记着原始任务吗?”
——直接哑火。
我自己踩过的一个大坑:让Agent去调研三篇关于RAG+强化学习的论文。
最开始Agent执行得很正常:搜索论文→读取摘要→下载全文→提取核心观点。
跑到第五步的时候,它发现某篇论文的引用很有意思,开始顺着引用链去查其他论文。然后又觉得另一篇论文的实验数据不够全,去查了作者的GitHub。
等我回过头来看日志,它已经在第十四步了。
输出的结果里,原始任务“调研三篇论文”只完成了一篇。剩下全是对引用论文的分析。
这就是我常说的“上下文漂移”。
不是模型变傻了,是每一轮模型都在做“当前上下文下最合理的下一步”——但最合理,不等于最符合原始目标。
怎么解决?
我现在的做法分三层。
第一层,在System Prompt里显式写一句话:“每执行三步,回顾一下原始任务目标,确认没有偏移。”这个便宜,但有效。我的实验里,加了这一句,跑偏率从30%降到了8%。
第二层,在代码层面加一个状态机。直接上关键逻辑:
class AgentStateMachine:
def __init__(self, goal):
self.goal = goal
self.steps = []
self.last_checkpoint = 0
def step(self, action):
self.steps.append(action)
if len(self.steps) - self.last_checkpoint >= 3:
if not self._is_aligned():
self._replan()
self.last_checkpoint = len(self.steps)
def _is_aligned(self):
# 用LLM判断最近三步是否偏离原始目标
pass
def _replan(self):
# 重新生成剩余步骤计划
pass第三层,最暴力也最有效——每五步做一次全局重规划,把当前状态和历史回传给LLM,让LLM判断接下来该怎么走。
有人可能会说,这样Token消耗太大了。
是的。确实大。
但你是想要一个省Token但跑偏的Agent,还是想要一个贵一点但靠谱的Agent?
写这玩意儿不是为了显摆我多牛。
说实话,这些坑我全踩过,而且踩得可比上面说的惨多了。
最狠的一次,Agent在循环里调用支付接口查余额,因为没设频率限制,一个小时内调了三千多次。要不是运维发现得早,那个月的账单够买一辆Model 3。
说回面试这件事。
我觉得现在Agent方向的面试有一个很大的问题:大家都在考“科普知识”,没人考“工程判断力”。
你问Function Calling和ReAct的区别,这属于科普。但如果你问“什么时候该用Function Calling,什么时候该用纯Prompt ReAct,依据是什么”,这才叫面试。同样,光问MCP是啥太浅了,问问落地时成本和收益怎么算,哪些场景值得上,才算考到点子上。
所以给准备面试的朋友一个建议:别光背八股了。
去自己搭一个Agent,跑起来,再跑崩它,然后修好它。
这个过程里踩的每一个坑,都是面试时最值钱的谈资。
给面试官的建议:放过那些“背诵型”问题。问点真的。让候选人讲一个具体的失败案例,讲他怎么发现的、怎么修的、效果如何。
能从这件事里讲出思考和判断的人,才是你该招的人。
毕竟,Agent这玩意儿,真正难的不是让它动起来。
是你发现它已经跑偏了十万八千里,还能凭着一股子狠劲儿,把它拉回来。
这才是真本事。
对Agent是这样,对人也是如此。
读者评论 4