Dayward AI

Interview Bank

328 questions total; 2 shown with current filters.

Tag
125 more tags
#abstention2#agent-loop2#behavioral2#claude-md2#coding-agent2#consistency2#context-engineering2#context-window2#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#state-machine1#system-prompt1#test-set1#token-budget1#tts1#workflow-engine1

From Frontend Engineer to Agent Engineer in 30 Days

D11 The Run State Machine, Streaming Output Back, Ordering by runId, SSE Waiters, Merging Interruptions Within 30 Seconds

  • How would you design the state machine for one agent run, and which failure states must it cover?怎么设计一次 Agent 执行(run)的状态机?需要覆盖哪些异常状态?
    Common in ChinaCommon overseasBasic#state-machine#distributed-systems

    How to reason about it · think before answering

    1. 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.
    2. 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.
    3. 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.
    4. 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.
    5. 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.
    6. 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.

    分析过程 · 先想清楚再作答

    1. 这题的区分度不在「能不能列出几个状态」,而在你有没有说出「为什么单进程时代不需要它」。答不出这一点,说明你只是抄过一张状态图。
    2. 先给动机:单进程里「执行到哪一步了」就是那个函数栈,状态存在于进程内存里,不需要名字。拆成 Gateway 与 Worker 之后,至少三方要同时回答同一个问题——接入层要判断还挂不挂 SSE,执行层要判断这条消息是否已被人领走,前端重开页面要判断上次的问题还在不在生成。三方不同进程,只能靠一张表对齐。
    3. 再给状态:pending 到 running 到 streaming 到 done 是正常路径,failed(重试耗尽)与 cancelled(被打断合并或用户取消)是两个随时可以走的异常出口。主动说明为什么 running 和 streaming 要分开:前者是「有人领走了但还没有一个字」,后者是「第一个字已出来」,这条线就是首字延迟的观测点,也是前端决定转圈还是打字机的依据。
    4. 结论要落到「状态机是用来挡写入的」:终态没有出边这一条最值钱。至少一次投递下「已经 done 的 run 又收到一个片段」是常态,没有转换表,那一笔会安静地写进库,用户看到回复末尾多出半句话,而日志里查不出是谁写的。
    5. 补一条纪律,这是有没有落地过的分水岭:所有写状态的地方都必须过同一个转换函数。绕过它直接执行一条更新语句,状态机就退化成注释了。
    6. 可以预期的追问:状态存哪、并发怎么办?答数据库那一行是唯一真相,转换用带条件的更新(更新时把当前状态写进 where 子句),失败说明有人抢先改过,这时候重读再决定,而不是覆盖。

    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

    答题要点

    • 单进程里状态就是函数栈;拆成 Gateway 与 Worker 后有三方要独立回答「这次执行到哪了」,必须落成一张表
    • 正常路径 pending 到 running 到 streaming 到 done;异常出口 failed(重试耗尽)与 cancelled(打断合并或用户取消)
    • running 与 streaming 分开,是为了观测首字延迟,也让前端知道该转圈还是该开始打字机效果
    • 终态没有出边是核心:至少一次投递下的迟到片段会被当场挡住,而不是安静写进库
    • 纪律:所有状态写入都过同一个转换函数,并用带当前状态条件的更新来处理并发

D13 Cron Scheduling (Central Scheduler → Stream Delivery) + Cost Metering (Token → USD Ledger, Usage Report)

  • When a service runs multiple replicas, why not let each replica start its own cron? What would you do instead?服务部署了多个实例,定时任务为什么不能让每个实例各自起一个 cron?你会怎么做?
    Common in ChinaCommon overseasBasic#scheduling#distributed-systems#cost

    How to reason about it · think before answering

    1. The hinge is the phrase multiple replicas. Saying it would run twice is only the symptom; the interviewer wants the business and dollar consequence.
    2. Make the cost concrete: three replicas each running cron means the job fires three times, users get three identical pushes, and you pay for three model calls. The multiplier tracks replica count, so scaling to ten makes both the bill and the spam tenfold, with no alert firing, because from each process's own point of view it ran exactly once.
    3. Give the right shape: move the decision of who runs when into one central scheduler whose only job, on a cron match, is to publish a task message onto the bus; the execution side keeps using a consumer group so one message reaches exactly one consumer. The key insight is that a scheduled task is not a new execution path, it just swaps the user for a clock as the thing pressing the button, so the worker code stays untouched.
    4. Volunteer the obvious follow-up: doesn't the scheduler become a single point of failure? Two layers. It is stateless, so a crash costs you a few minutes of task delay; if you truly need HA, run two instances and dedupe on the idempotency key at publish time rather than bolting a distributed lock onto the scheduler.
    5. Close with sizing: a central scheduler plus a bus is enough at modest volume. At high volume, or when tasks have dependencies, teams move to a dedicated workflow scheduler with dependency graphs, retry policy and backfill, but the underlying central-decision-plus-queue shape is identical.
    6. Expect: the scheduler was down for 90 seconds and skipped a minute — now what? Replay the last N minutes on startup, one minute at a time. The idempotency key makes redundant publishes harmless, which is exactly what makes at-least-once plus idempotency the easy combination.

    分析过程 · 先想清楚再作答

    1. 题眼在「多个实例」四个字。只答「会重复执行」拿不到分,因为那是现象;面试官想看你能不能把现象换算成业务后果和钱。
    2. 先把重复的代价说具体:3 个副本各起 cron,同一个任务被执行 3 次,用户收到 3 份一样的推送,你付 3 份模型调用的钱。而且这个倍数会跟着副本数走——扩容到 10 个副本,账单和骚扰量一起变成十倍,却不会触发任何告警,因为从每个进程自己的视角看它只是老实地执行了一次。
    3. 然后给出正确的形状:把「谁该在什么时候被执行」收进一个中心调度器,它命中 cron 之后只做一件事——往消息总线投递一条任务消息;执行侧照旧靠消费组分摊,一条消息只会被一个消费者拿到。关键认知是「定时任务不是一种新的执行方式,只是把按按钮的人从用户换成了钟表」,所以执行侧一行代码都不用改。
    4. 接着主动补上「那调度器自己不就成单点了吗」——这是必被追问的一句。答案分两层:调度器无状态、崩了拉起来就行,短暂不可用的代价只是几分钟内的任务延迟;真要高可用就起两个实例,靠投递时的幂等键去重,而不是靠给调度器加分布式锁。
    5. 最后点一句选型:任务量不大时中心调度器加消息总线足够;量大或者任务本身有依赖关系时,业界会换成专门的调度框架(带任务依赖、重试策略、补数),但底层的「中心决定 + 队列分发」结构是一样的。
    6. 可以预期的追问:调度器崩溃 90 秒,中间跨过的那一分钟怎么办?答启动时回看最近 N 分钟逐分钟重放,因为有幂等键兜底,重复投递无害——这正是 at-least-once 加幂等这组搭配能成立的地方。

    Key points

    • Per-replica cron means the job runs N times: N duplicate pushes, N times the model spend, scaling linearly with replica count and silently
    • The right shape is a central scheduler that publishes one message to the bus on a cron match, with a consumer group ensuring exactly one worker picks it up
    • A scheduled task is not a new execution path — only the trigger changed from a user to a clock, so worker code is unchanged
    • The scheduler is stateless: restart on crash, and if you need HA run two and dedupe on the idempotency key rather than adding a distributed lock
    • Missed minutes are recovered by replaying the last N minutes at startup, which is safe because the idempotency key absorbs duplicates

    答题要点

    • 每个实例各自起 cron 等于同一个任务被执行 N 次:用户收到 N 份重复推送,模型调用花 N 倍的钱,倍数随副本数线性增长且不会触发告警
    • 正确形状是中心调度器命中 cron 后只往消息总线投递一条消息,执行侧靠消费组保证一条消息只被一个 Worker 拿到
    • 定时任务不是新的执行路径,只是把触发者从用户换成了钟表,所以 Worker 侧不需要任何改动
    • 调度器是无状态的,崩了拉起来即可;需要高可用就起两个实例靠投递时的幂等键去重,不要给它加分布式锁
    • 崩溃期间跨过的时间点靠启动时回看最近 N 分钟重放补上,幂等键保证重复投递无害