面试题库
共 328 题,当前筛选 1 题。
课程全部30 天从前端工程师到 Agent 工程师5 天提示词工程零基础Claude 高效使用:从对话到 Claude CodeCodex 与 OpenAI Agents SDK 高效使用7 天 MCP:把工具接进任何 Agent7 天 Agent Skills:把经验做成可复用能力5 天上下文工程14 天 RAG:从检索到可信回答14 天用 Agent 搭一条 AI 短剧生产线
标签
全部#state-machine1#architecture8#cost4#multi-agent4#agent-skills3#context3#evaluation3#llm-basics3#pipeline-design3#security3#system-design3#tool-design3
还有 125 个标签收起标签
#abstention2#agent-loop2#behavioral2#claude-md2#coding-agent2#consistency2#context-engineering2#context-window2#distributed-systems2#embeddings2#framework-design2#interview-prep2#interview-process2#mcp2#memory2#observability2#orchestration2#prompt-engineering2#provider-abstraction2#rag2#resume2#scalability2#scheduling2#skills2#sse2#streaming2#structured-output2#tool-calling2#agent-basics1#agent-design1#agent-sdk1#agentic-rag1#agents-md1#api-design1#async-task1#auth1#backoff1#bi-encoder1#build-vs-buy1#career1#chunking1#communication1#concurrency1#configuration1#consistent-hashing1#content-safety1#context-assembly1#context-management1#coreference1#cost-accounting1#cost-analysis1#cross-encoder1#data-quality1#encoding1#failure-analysis1#fairness1#few-shot1#ffmpeg1#fine-tuning1#frontend1#global-market1#golden-set1#hooks1#human-in-the-loop1#hybrid-search1#image-generation1#ingestion1#json-schema1#jwt1#langgraph1#long-context1#long-term-memory1#maintenance1#mcp-basics1#media-pipeline1#mental-model1#message-bus1#messages-api1#migration1#model-routing1#moderation1#modularity1#multi-turn1#normalisation1#openai1#operations1#ordering1#overlap1#primitives1#prioritization1#priority-queue1#proactive-messaging1#product-engineering1#project-storytelling1#prompt1#prompt-basics1#prompt-bloat1#prompt-design1#prompt-injection1#prompt-surface1#prompt-techniques1#prompting1#protocol1#query-rewriting1#rag-basics1#rate-limiting1#redis-streams1#reliability1#responses-api1#retrieval1#routing1#sampling1#schema-validation1#scripts1#server-design1#sharding1#similarity1#skill-design1#stakeholder-communication1#star1#system-prompt1#test-set1#token-budget1#tts1#workflow-engine1
30 天从前端工程师到 Agent 工程师
D11 run 状态机、输出流回传、按 runId 保序、SSE 等待者、30s 打断合并
怎么设计一次 Agent 执行(run)的状态机?需要覆盖哪些异常状态?How would you design the state machine for one agent run, and which failure states must it cover?
国内高频海外高频基础#state-machine#distributed-systems分析过程 · 先想清楚再作答
- 这题的区分度不在「能不能列出几个状态」,而在你有没有说出「为什么单进程时代不需要它」。答不出这一点,说明你只是抄过一张状态图。
- 先给动机:单进程里「执行到哪一步了」就是那个函数栈,状态存在于进程内存里,不需要名字。拆成 Gateway 与 Worker 之后,至少三方要同时回答同一个问题——接入层要判断还挂不挂 SSE,执行层要判断这条消息是否已被人领走,前端重开页面要判断上次的问题还在不在生成。三方不同进程,只能靠一张表对齐。
- 再给状态:pending 到 running 到 streaming 到 done 是正常路径,failed(重试耗尽)与 cancelled(被打断合并或用户取消)是两个随时可以走的异常出口。主动说明为什么 running 和 streaming 要分开:前者是「有人领走了但还没有一个字」,后者是「第一个字已出来」,这条线就是首字延迟的观测点,也是前端决定转圈还是打字机的依据。
- 结论要落到「状态机是用来挡写入的」:终态没有出边这一条最值钱。至少一次投递下「已经 done 的 run 又收到一个片段」是常态,没有转换表,那一笔会安静地写进库,用户看到回复末尾多出半句话,而日志里查不出是谁写的。
- 补一条纪律,这是有没有落地过的分水岭:所有写状态的地方都必须过同一个转换函数。绕过它直接执行一条更新语句,状态机就退化成注释了。
- 可以预期的追问:状态存哪、并发怎么办?答数据库那一行是唯一真相,转换用带条件的更新(更新时把当前状态写进 where 子句),失败说明有人抢先改过,这时候重读再决定,而不是覆盖。
How to reason about it · think before answering
- The discriminator is not listing states, it is explaining why a single-process service does not need them at all. Without that, you have only memorized a diagram.
- Start from motivation: in one process the call stack *is* the state. Once you split gateway and worker, three parties must answer the same question independently — the gateway decides whether to keep an SSE connection open, the worker decides whether someone already claimed the message, and a reopened browser tab asks whether the previous question is still generating. Different processes, so the answer has to live in a table.
- Then the states: pending to running to streaming to done on the happy path, with failed (retries exhausted) and cancelled (superseded by a merge, or user-cancelled) as exits available from anywhere. Volunteer why running and streaming are separate: running means claimed but no token yet, streaming means the first token is out. That boundary is your time-to-first-token probe and the frontend's cue to switch from spinner to typewriter.
- Land on the real purpose: the machine exists to reject writes. Terminal states having no outgoing edges is the most valuable row in the table. Under at-least-once delivery, a done run receiving one more chunk is routine, and without the table that chunk lands silently — the user sees half a sentence appended and the logs show nothing wrong.
- Add the discipline that separates shipped from read-about: every status write goes through one transition function. One raw UPDATE that bypasses it and the state machine is just a comment.
- Expect the follow-up on storage and concurrency: the database row is the single source of truth, and transitions are conditional updates that include the expected current status in the WHERE clause. Zero rows affected means someone moved first — re-read and decide, never blindly overwrite.
答题要点
- 单进程里状态就是函数栈;拆成 Gateway 与 Worker 后有三方要独立回答「这次执行到哪了」,必须落成一张表
- 正常路径 pending 到 running 到 streaming 到 done;异常出口 failed(重试耗尽)与 cancelled(打断合并或用户取消)
- running 与 streaming 分开,是为了观测首字延迟,也让前端知道该转圈还是该开始打字机效果
- 终态没有出边是核心:至少一次投递下的迟到片段会被当场挡住,而不是安静写进库
- 纪律:所有状态写入都过同一个转换函数,并用带当前状态条件的更新来处理并发
Key points
- In one process the call stack is the state; after splitting gateway and worker, three parties need the same answer, so it has to be a table
- Happy path pending, running, streaming, done; exits are failed (retries exhausted) and cancelled (merged or user-cancelled)
- Separating running from streaming gives you a time-to-first-token probe and tells the UI when to switch from spinner to typewriter
- Terminal states with no outgoing edges reject the late chunks that at-least-once delivery guarantees you will get
- Every status write goes through one transition function, implemented as a conditional update on the expected current status