Interview Bank
328 questions total; 4 shown with current filters.
CourseAllFrom Frontend Engineer to Agent Engineer in 30 DaysPrompt Engineering From Scratch in 5 DaysMastering Claude: From Conversation to Claude Code in 5 DaysMastering Codex and the OpenAI Agents SDK in 5 DaysMCP in 7 Days: Wire Tools Into Any AgentAgent Skills in 7 Days: Turn Experience Into Reusable CapabilityContext Engineering in 5 DaysRAG in 14 Days: From Retrieval to Trustworthy AnswersBuild an AI Short-Drama Production Pipeline With Agents in 14 Days
Tag
All#client4#evaluation30#cost29#reliability24#architecture22#agent-skills21#security18#observability15#streaming12#error-handling11#idempotency10#system-design10
361 more tagsShow fewer tags
#api-design9#coding-agent9#distributed-systems8#multi-agent8#rag8#chunking7#debugging7#pipeline-design7#structured-output7#agent-loop6#mcp6#operations6#prompt-injection6#sse6#tool-calling6#tool-design6#context5#context-engineering5#deployment5#embeddings5#hybrid-search5#message-bus5#scheduling5#system-prompt5#agentic-rag4#behavioral4#concurrency4#consistency4#framework-design4#ingestion4#prompt-engineering4#rate-limiting4#retrieval4#routing4#trade-offs4#abstention3#agents-sdk3#caching3#communication3#context-window3#cost-control3#data-quality3#failure-modes3#image-generation3#interview-prep3#langgraph3#latency3#llm-as-judge3#long-context3#model-migration3#model-routing3#orchestration3#ordering3#progressive-disclosure3#prompt-basics3#prompt-caching3#protocol3#provider-abstraction3#ranking3#recall3#redis-streams3#responses-api3#resume3#retry3#runtime3#scalability3#skills3#state-management3#statelessness3#subagents3#timeline3#versioning3#workflow-engine3#access-control2#agent-design2#async-task2#auth2#checkpointing2#citation-verification2#citations2#claude-md2#code-review2#compaction2#context-rot2#contextual-retrieval2#cost-tradeoff2#data-modeling2#database2#distribution2#fallback2#ffmpeg2#golden-set2#grounding2#interview-process2#llm-basics2#long-term-memory2#media-pipeline2#memory2#multi-hop2#multi-tenancy2#oauth2#prioritization2#project-storytelling2#prompt-techniques2#query-rewriting2#react2#refusal2#reproducibility2#rerank2#retrieval-quality2#retrospective2#scripts2#sharding2#state-machine2#tool-permissions2#tooling2#tools2#tracing2#transport2#tts2#ux2#vector-database2#verification2#workflow2#agent-basics1#agent-quality1#agent-sdk1#agents-md1#altitude1#analytics1#approvals1#architecture-review1#async1#atomicity1#attention-budget1#av-sync1#backoff1#bi-encoder1#bm251#budget-control1#build-vs-buy1#cancellation1#candidate-selection1#capacity-planning1#career1#chain-of-thought1#ci1#circuit-breaker1#claude-code1#cli-design1#client-integration1#cloud1#compliance1#compression1#configuration1#confused-deputy1#consistent-hashing1#content-hash1#content-safety1#context-assembly1#context-compression1#context-management1#copyright1#coreference1#correctness1#cost-accounting1#cost-analysis1#cost-optimization1#cross-encoder1#cross-model1#customer-support1#dag1#decision-making1#decomposition1#degradation1#deliberate-practice1#design1#diagnostics1#dimensions1#docker1#documentation1#embedding-migration1#encoding1#engineering-judgement1#engineering-tradeoffs1#error-propagation1#escalation1#eval1#event-driven1#evidence1#failure-analysis1#fairness1#faithfulness1#fan-out1#feedback-loop1#fencing-token1#few-shot1#filter-pushdown1#filtering1#fine-tuning1#forking1#four-elements1#framework-selection1#frontend1#global-market1#graph-rag1#guardrails1#hallucination1#handoff1#handoffs1#headless1#hnsw1#hooks1#human-in-the-loop1#hybrid1#hyde1#incremental-recompute1#incremental-sync1#index-maintenance1#index-routing1#indexing1#information-retrieval1#instruction-hierarchy1#integration1#intent-routing1#interrupt-merge1#invalidation1#isolation1#iterative-scan1#ivfflat1#json-parsing1#json-schema1#just-in-time1#jwt1#knowledge-organization1#labeling1#latency-budget1#lease1#least-privilege1#llm-output-quality1#long-session1#loop-guard1#maintenance1#mcp-basics1#mental-model1#messages-api1#metadata1#methodology1#metrics1#migration1#mobile1#model-selection1#moderation1#modularity1#multi-turn1#multimodal1#nodejs1#normalisation1#notifications1#ocr1#offline-testing1#openai1#overlap1#pagination1#parent-child1#pdf-parsing1#performance1#permissions1#persistence1#pgvector1#pipeline-reliability1#portfolio1#primitives1#priority-queue1#proactive-messaging1#product-engineering1#production-readiness1#prompt1#prompt-assembly1#prompt-bloat1#prompt-design1#prompt-limits1#prompt-surface1#prompt-template1#prompt-versioning1#prompting1#protocol-versions1#quality1#quality-check1#quantization1#query-transformation1#quiet-hours1#rag-basics1#rank-fusion1#reasoning1#reconnect1#redis1#reflection1#replay1#reporting1#retrieval-failure1#retrieval-metrics1#retry-semantics1#retry-strategy1#review1#risk-assessment1#rollback1#rollout1#rrf1#safety1#sandbox1#sandboxing1#scaling1#schema-design1#schema-validation1#scoping1#secrets-management1#self-assessment1#self-introduction1#self-presentation1#self-reflection1#server-design1#service-architecture1#session-management1#sessions1#similarity1#skill-authoring1#skill-description1#skill-design1#spec1#split-brain1#stakeholder-communication1#star1#state-persistence1#stateless1#stdio-transport1#stopping-criteria1#storytelling1#subagent1#subscriptions1#subtitles1#task-graph1#team-governance1#test-set1#test-strategy1#testing1#thresholds1#timezone1#token-accounting1#token-budget1#tool-budget1#tool-execution1#tool-naming1#tool-schema1#trust-boundary1#tuning1#validation1#vector-index1#workflow-design1#xml-tags1#zero-downtime1
MCP in 7 Days: Wire Tools Into Any Agent
D5 Writing an MCP Client: Discovering and Calling Tools Inside Your Own Agent Loop, Multi-Server Aggregation and Name Collisions
Your client is connected to five MCP servers and two of them expose a tool called search. How do you merge them into one tool list for the model, and why can't you just prefix with the server's name?你的客户端同时连了五个 MCP 服务端,其中两个都有一个叫 search 的工具。合并成一张工具表给模型时,重名该怎么处理?为什么不能直接拿服务端名做前缀?
Common in ChinaCommon overseasIntermediate#client#tool-namingHow to reason about it · think before answering
- The screen is whether you have actually aggregated multiple servers. 'Add a prefix' is half the answer; the real question is the second half, why the server's own name will not do.
- Set the premise straight: the spec guarantees tool-name uniqueness only within a single server, and explicitly says clients or proxies that aggregate multiple servers may hit collisions and should implement a disambiguation strategy. Collisions are permitted by design, and disambiguation is the client's job.
- Now the second half: the name a server reports in serverInfo is not guaranteed to be unique across servers, and the spec says it should not be relied upon for disambiguation. The server fills it in itself, two unrelated servers may both call themselves github, and worse, it is untrusted input, so a malicious server can impersonate another. The prefix must come from the client's own configuration, a local alias the user assigns per server, with duplicate aliases rejected at startup as a configuration error.
- Then the naming mechanics. MCP allows letters, digits, underscore, hyphen and dot with a suggested 128-character limit; model APIs are usually stricter, often letters, digits, underscore and hyphen with a 64-character cap. Take the intersection, and on overflow truncate plus append a short hash — say why: truncation itself creates new collisions, and the hash restores uniqueness.
- The conclusion, and the most likely follow-up: keep a reverse map from the prefixed name back to server plus original tool name. The call sent to the server must carry the original name, since the server has never heard of the prefixed one. Never recover it by string splitting, because original names may legitimately contain underscores and truncated names cannot be split back at all.
- Likely follow-ups: is the prefix enough? No, the model chooses by description, so put the source in the description too. And what about list changes? Servers declaring listChanged send a notification, on which the client refetches and rebuilds the map, keeping in mind that churning the tool list invalidates prompt caching because the tool array sits in the cached prefix.
分析过程 · 先想清楚再作答
- 这题在筛「有没有真的聚合过多个服务端」。只答「加个前缀」能拿一半分,题眼在后半句——为什么不能用服务端自报的那个名字。
- 先把前提摆正:规范只保证工具名在**单个服务端内**唯一,并且明确说聚合多个服务端的客户端或代理可能遇到重名,应当实现一套消歧策略。也就是说重名不是异常情况,是设计上就允许的,消歧责任在客户端这一层,服务端管不着。
- 再答后半句:服务端在 serverInfo 里自报的 name **不保证跨服务端唯一**,规范明说不应当拿它来消歧。它由服务端自己填,两个不相干的服务端都叫 github 完全合法;更糟的是它是不可信输入,一个恶意服务端可以故意把自己报成别人的名字,让模型把请求发到错的地方。所以前缀必须来自客户端自己的配置——用户在配置文件里给每个服务端起的本地别名,别名重复时在启动阶段直接报错,因为那是配置错误。
- 接着说名字怎么拼。MCP 允许字母数字下划线连字符和点、长度建议 128 以内;模型 API 那边通常更严,比如只允许字母数字下划线连字符、最长 64。取交集,超长就截断并缀一段短哈希——要主动说出为什么加哈希:截断本身会制造新的重名,哈希是把唯一性补回来的。
- 结论也是最容易被追问的一条:客户端必须留一张反查表,从带前缀的名字映射回「哪个服务端 + 原来的工具名」。调用时发给服务端的必须是**原名**,服务端根本不认识带前缀的那个。绝不能靠切字符串反推,因为工具原名里本来就允许有下划线,截断过的名字更是拆不回来。
- 可预期的追问一:光靠名字前缀够不够?答不够,模型选工具看的是描述,所以还应当把来源写进描述里。追问二:工具列表变了怎么办?服务端支持 listChanged 时会发通知,客户端收到就重新拉取并重建反查表;同时注意频繁增删工具会打掉提示缓存,因为工具表在缓存前缀里。
Key points
- Uniqueness holds only within one server; collisions are expected on aggregation and the client owns disambiguation
- The prefix must come from a client-configured local alias, since the server-reported name is neither unique nor trustworthy
- Build names from the intersection of MCP and model-API charset and length limits; truncate plus a short hash on overflow
- Keep a reverse map and send the original name on calls; never split the prefixed string, as original names contain underscores
答题要点
- 唯一性只在单个服务端内成立,聚合时重名是设计允许的,消歧责任在客户端
- 前缀必须来自客户端配置的本地别名,服务端自报的 name 不保证唯一且是不可信输入
- 名字取 MCP 与模型 API 的字符集与长度交集,超长截断并缀短哈希补回唯一性
- 留一张反查表,调用时发原名;不能靠切字符串反推,工具原名里本来就有下划线
One of your MCP servers times out in production. How should your agent loop react?线上一个 MCP 服务端超时了。你的 Agent 循环应该怎么反应?
Common in ChinaCommon overseasIntermediate#client#reliabilityHow to reason about it · think before answering
- This probes engineering instinct: can you separate 'one dependency is down' from 'this turn fails'. Answering 'retry three times' just moves the problem, and the interviewer will ask what the user is staring at meanwhile.
- Split by phase first. A timeout happens at two very different moments: discovery (server/discover or tools/list) and invocation (tools/call). The correct reaction differs, and blurring them shows you have not built this.
- Discovery: wrap each server in its own try/catch, record the failure with its reason in a down list, and continue to the next server. The tool table loses a few entries but the loop still starts. Record the reason, not a boolean, because afterwards you must be able to say what is missing and why.
- Invocation: translate the failure into a tool result with isError true and feed it back to the model rather than throwing. MCP already uses isError for 'the tool failed but the protocol succeeded', so the model can switch tools or arguments; throwing kills the turn and leaves the user with no explanation.
- Then three supporting points. Every request needs a timeout, because on stdio a silent server is silent forever. Idempotency decides whether a retry is safe, and the idempotentHint annotation is a hint, not a guarantee, so writes need a client-side dedup key. And outages must be visible, surfaced in the UI or in the system prompt, or the model will behave as if the capability never existed and confidently report nothing found.
- Conclusion: the worst outcome of one server timing out should be a few missing tools plus an explicit note, never a failed turn.
- Likely follow-ups: should you add a circuit breaker? Yes, after consecutive failures mark the server unusable for a while so you stop paying a timeout every turn, with recovery by health check or reconnect on the next session. And how do you set the timeout? Per tool rather than per server, since a thirty-second analysis tool and a cache lookup should not share a threshold.
分析过程 · 先想清楚再作答
- 这题看的是工程直觉:能不能把「一个依赖挂了」和「这一轮对话失败」分开。答「重试三次」是把问题往后推了一步,面试官会立刻追问重试期间用户在等什么。
- 先分阶段。超时发生在两个完全不同的时刻:发现阶段(server/discover 或 tools/list)和调用阶段(tools/call)。两个阶段的正确反应不一样,混着答就会露怯。
- 发现阶段:逐个服务端 try/catch,失败的记进一张掉线表并继续下一个。整张工具表少几个工具,但循环照常起得来。记的必须是原因而不是一个布尔值,因为事后你要能回答少了什么、为什么少。
- 调用阶段:把失败翻译成一条 isError 为真的工具结果喂回模型,不要抛。理由是 MCP 本来就用 isError 表达「工具执行失败但协议是成功的」,模型看得见这句话就有机会换个工具或换个参数;抛出去只会把整轮对话打断,而且用户什么解释都得不到。
- 接着补三件配套的事。一是**每条请求都必须有超时**,stdio 上服务端不回你就永远不回;二是**幂等性决定能不能重试**,工具注解里的 idempotentHint 是提示不是保证,写操作的重试要靠客户端自己的去重键;三是**掉线要让用户看得见**,把掉线的服务端标在界面上或写进系统提示,否则模型会表现得像那个能力从来不存在,一本正经地说查不到。
- 结论:一个服务端超时,最坏的后果应该是少几个工具加一条明确的说明,而不是这一轮对话失败。
- 可预期的追问:要不要熔断?连续失败到阈值就把这个服务端标记为不可用一段时间,避免每一轮都白等一次超时;恢复用探活或下一次会话重连。再追问会问到超时值怎么定——按工具而不是按服务端定,一个跑三十秒的分析工具和一个查缓存的工具不该共用一个阈值。
Key points
- Split by phase: per-server try/catch during discovery with a recorded reason, and never throw during invocation
- Translate call failures into isError tool results so the model can switch tools or arguments
- Every request needs a timeout; retry safety depends on idempotency, and the annotation is a hint, not a guarantee
- Outages must be visible to user and model, otherwise silent degradation makes the model deny the capability ever existed
答题要点
- 分阶段:发现阶段逐个服务端 try/catch 记进掉线表并继续,调用阶段一律不抛
- 调用失败翻译成 isError 为真的工具结果喂回模型,让它换工具或换参数
- 每条请求必须设超时;能不能重试取决于幂等性,注解只是提示不是保证
- 掉线必须对用户和模型可见,否则会变成静默降级,模型会假装那个能力不存在
When translating an MCP tool definition into a model API's tool parameters, what is most easily lost, and what goes wrong when it is?把 MCP 的工具定义翻译成模型 API 的工具参数时,最容易丢掉的是什么?丢了会怎样?
Common in ChinaCommon overseasDeep dive#client#tool-schemaHow to reason about it · think before answering
- This checks whether you know the step is lossy. Anyone answering 'just map the field names' has probably not written a client, because several parts of an MCP tool definition have no home on the model-API side.
- List first, then consequences. Three things go missing: annotations (readOnlyHint, destructiveHint, idempotentHint), outputSchema, and title. A fourth, often overlooked, is pagination — taking only the first page of tools/list silently drops whole batches of tools.
- Consequences one by one. Without annotations the model cannot tell which tool is destructive and the client has nothing to base a confirmation prompt on, so confirmation logic must live in the client and read the annotations directly. Without outputSchema, downstream code parses natural language, and code-mode generation cannot produce accurate return types. Without title, the UI can only show a prefixed machine name.
- Volunteer the most important caveat: annotations are untrusted input. The spec requires clients to treat tool annotations as untrusted unless they come from trusted servers. readOnlyHint being true is not proof of safety, only the server's own claim, so annotations may drive whether you ask the user, never whether the caller is authorized.
- Conclusion: the right posture is to know exactly what you dropped and compensate in the client — confirmation driven by annotations, structured results validated by you, title for the UI and description for the model, and pagination followed until nextCursor disappears.
- Likely follow-ups: may you rewrite the description? Light augmentation is fine, such as prefixing the source to help disambiguate collisions, but do not rewrite the meaning, since the description is what the server author tuned and their only lever on model choice. And what if outputSchema is absent? The official guidance is to accept a generic type and move on, or extract a typed result with a fast model outside loops and validate it.
分析过程 · 先想清楚再作答
- 这题在考「你知不知道这一步是有损的」。答「字段名对一下就行」的人多半没写过客户端,因为 MCP 的工具定义里有好几样东西在模型 API 那边根本没有对应位置。
- 先列清单再讲后果。丢的主要是三样:annotations(readOnlyHint、destructiveHint、idempotentHint 这类行为提示)、outputSchema(结构化返回的形状)、title(给人看的名字)。另外还有一样常被忽略的是分页——只取 tools/list 第一页等于把后面的工具整批丢掉。
- 逐条讲后果。annotations 丢了,模型不知道哪个工具是破坏性的,客户端也就没法自动决定要不要弹确认框——所以确认逻辑必须由客户端按注解自己做,不能指望模型自觉。outputSchema 丢了,下游只能靠解析自然语言拿数据,而且做代码模式(让模型写代码调工具)时生成不出准确的返回类型。title 丢了,界面上只能显示一串带前缀的机器名。
- 这里必须主动补一句最重要的:**注解本身是不可信输入**。规范要求客户端把工具注解当成不可信的,除非来自可信服务端。readOnlyHint 为真不是「这个工具安全」的证明,它只是服务端的自我声明。所以注解可以用来决定 UI 上要不要多问一句,但不能拿它当权限判据。
- 结论:翻译这一步的正确心态是「知道自己丢了什么,并在客户端补回来」。补法是——确认与拦截由客户端按注解做、结构化返回自己校验、界面用 title 而给模型用 description、分页翻到 nextCursor 消失为止。
- 可预期的追问:description 要不要改写?可以适度加工,比如在前面缀一句来源说明帮助模型在重名时选对,但不要重写语义——描述是服务端作者调过的,也是他们唯一能影响模型选择的地方。再追问可能是「outputSchema 缺失怎么办」,官方建议先用泛型接住往下游传,真需要类型时用一个小模型做一次抽取并校验,别在循环里做。
Key points
- Annotations, outputSchema and title are lost, plus every tool past the first page if pagination is ignored
- Without annotations there is nothing to drive a confirmation prompt, so that logic must live in the client
- Annotations are untrusted input: they may drive UI prompts, never authorization decisions
- Losing outputSchema forces downstream natural-language parsing; you may prefix the description but must not rewrite its meaning
答题要点
- 丢的是 annotations、outputSchema、title,外加只取第一页时整批丢掉的工具
- annotations 丢了就没法决定要不要弹确认框,确认逻辑必须由客户端按注解自己做
- 注解是不可信输入,只能驱动 UI 提示,不能当权限判据
- outputSchema 丢了下游只能解析自然语言;description 可以缀来源但不要重写语义
D6 Security and Governance: Prompt Injection in Tool Descriptions, the Confused Deputy, Least Privilege, Audit Logs, and a Tool Allowlist
Why is an MCP tool's description untrusted input, and what protections would you build as a client author?为什么说 MCP 工具的描述是不可信输入?作为客户端作者,你会做哪些防护?
Common in ChinaCommon overseasIntermediate#prompt-injection#clientHow to reason about it · think before answering
- The screen is whether you treat the model's context as a data ingress. Answering 'filter for keywords' collapses under follow-up, because text filters do not survive paraphrase.
- Establish why it is untrusted. The description is written by the server author and lands verbatim in the tool list handed to the model, at the same trust level as your own system prompt, with no quoting, boundary, or provenance. The precondition is absurdly low: no credentials, no man in the middle, no user click, just the ability to influence text that will be read into context. Three real paths are publishing a server and waiting for installs, taking over an already-trusted server's release rights and changing one field in a patch, or a clean server whose descriptions embed database content. The second is hardest to defend, since users audit only at install time and list-changed notifications say that something changed, not which sentence.
- Fold annotations in: the spec requires clients to treat tool annotations as untrusted unless they come from trusted servers. readOnlyHint being true is not proof of safety, only the server's own claim.
- Then the defenses, and the ordering is the point: block consequences first, entry second, because every text-based defense is probabilistic while the consequence layer is deterministic.
- Consequences: require human confirmation before destructive tools and show the actual arguments (the spec recommends showing tool inputs to the user precisely to catch an innocuous-looking tool exfiltrating via its arguments); render every tool call in the UI, or the injected 'do not tell the user' genuinely works; and decide what is destructive from local policy first, using annotations only to catch extra cases, never to waive one.
- Entry: render descriptions as external data with provenance and boundary markers, escaping the markers themselves; apply the same treatment plus a length cap to tool results; and on list changes show the user a diff of the descriptions rather than a bare 'the tool list changed'.
- Likely follow-ups: can you just instruct the model to ignore instructions in descriptions? That lowers the probability but cannot guarantee, so it must not be the only line. And do tool results count? Yes, and worse, because they change every call and are larger; official guidance also notes that one server's results are untrusted input to another.
分析过程 · 先想清楚再作答
- 这题在筛「有没有把模型上下文当成一条数据入口来看」。答「加个过滤器拦关键词」会被追问到崩,因为基于文本的过滤挡不住改写。
- 先讲清为什么不可信。工具描述由服务端作者写,会原封不动进入给模型的工具表,和你自己写的系统提示处在同一个信任层级——没有引号、没有边界、没有来源标注。它的前置条件低到离谱:攻击者不需要凭证、不需要中间人、不需要用户点任何东西,只要能影响一段会被读进上下文的文本。三条现实路径是发一个服务端等人装、拿下已被信任服务端的发布权限在小版本里改一个字段、或者服务端本身干净但描述里嵌了从数据库读出来的内容。第二条最难防,因为用户只在安装时审过一遍,清单变更通知只说变了、不说哪句话变了。
- 顺手把注解也归进来:规范要求客户端必须把工具注解当成不可信输入,除非来自可信服务端。readOnlyHint 为真不是安全证明,只是服务端的自我声明。
- 然后是防护,关键是**给出顺序**:先挡后果,再挡入口。因为所有基于文本的防御都是概率性的,没有一条能保证挡住,而后果那一层是确定性的。
- 挡后果的三条:破坏性工具执行前一律向人确认,且确认框展示**实际参数**(规范建议把工具输入展示给用户,正是为了挡住工具名人畜无害但参数在外发数据这一类);界面上必须显示每一次工具调用,否则注入里那句「不要告诉用户」是真的会生效的;判据用本地策略为主、注解为辅——注解只能用来多拦一个,不能用来放行。
- 挡入口的三条:把描述当外部数据渲染,加来源标注与边界标记,并把边界符本身转义掉;工具返回同样处理,还要加长度上限;服务端清单变更时把描述的 diff 展示给用户复核,而不是只提示「工具列表变了」。
- 可预期的追问一:那能不能干脆让模型别听描述里的指令?只能降低概率,不能保证,所以它不能是唯一防线。追问二:工具返回算不算同一类问题?算,而且更严重,因为它每次都不一样、量更大;多服务端场景里官方还专门说过,一个服务端的结果对另一个服务端来说是不可信输入。
Key points
- Descriptions are author-written, land verbatim in context at system-prompt trust level, and need no credentials to exploit
- Annotations are equally untrusted: the spec says treat them as such, and readOnlyHint proves nothing
- Order matters: block consequences first with human confirmation showing actual arguments, plus visible tool calls
- At the entry, wrap descriptions and results with provenance and escaped boundary markers, and diff descriptions on list changes
答题要点
- 描述由服务端作者写、原样进上下文,和系统提示同一个信任层级,前置条件低到不需要任何凭证
- 注解同样不可信:规范要求客户端把注解当不可信输入,readOnlyHint 不是安全证明
- 防护顺序是先挡后果再挡入口:破坏性操作人工确认(展示实际参数)、界面显示每次调用
- 入口侧给描述与返回加来源标注与边界标记并转义边界符;清单变更时展示描述的 diff