System-design interview · Extended interviews
Design durable agent workflows
Run an AI-assisted business process across waits and crashes while keeping approved actions, saved progress and uncertain outcomes explicit.
You will learn to
- Distinguish a model recommendation from an authorized external action.
- Build a resumable workflow around durable states and activity results.
- Recover a lost provider response without blindly repeating a purchase.
Practice in this chapter
8 interview questions with model answers and follow-ups.
Go to interview practiceUseful foundations: Distributed transactions and sagas · Idempotency, retries, and timeouts · Authentication, authorization, and tenant isolation
Workload and timing examples are interview assumptions.
Dotted concept links open the relevant explanation in a new tab.
01Design a business process that uses a model
An agent workflow is a process that uses a model to interpret information or propose a next step. The application still decides which tools exist, which actions are permitted and what counts as completion. A conversational transcript alone is not a reliable record of a purchase, approval or retry.
Ask which actions the model may propose, which need human approval, and what should happen if the vendor receives an order but its reply is lost. This design permits a fixed purchasing process, approval of exact terms and an explicit uncertain-submission outcome.
Our example buys ten laptops from one of three approved vendors. The model compares quotes and drafts a proposal. A human approves an exact proposal, and only then may the service submit the order. The workflow may wait thirty minutes for approval, survive worker restarts and report the final order identity. Payment settlement and arbitrary browsing are outside this scope.
The complete flow is save task → research quotes → save proposal → wait for approval → submit approved order → save result. This fixed sequence is intentionally enough for the interview. The model helps with research and explanation; it does not invent new privileges or freely change the workflow. A durable workflow means that progress survives a process crash and execution resumes from recorded state rather than starting the business action again.
02Functional requirements
Agree on what the service must do before choosing its components.
- Create and inspect tasks. Create a tenant/requester-owned purchase task, return its durable identity and show its phase, current proposal and any external order result.
- Research an allowed purchase. Compare quotes from the three approved vendors and draft a proposal for ten laptops. The model supplies bounded interpretation; trusted code checks commercial terms and policy.
- Review and approve exact terms. Let an authorized human review and approve the exact current proposal, with a documented expiry. Replacing the proposal or changing its terms invalidates earlier approval.
- Submit and audit an order. Submit only the authorized proposal, preserve the external action identity, record the provider’s result and expose reconciliation when the result is uncertain.
- Cancel at a defined boundary. Before submission admission, cancellation prevents the action from starting. After the provider may have accepted, any cancellation is a separate business operation. Payment settlement and arbitrary browsing are outside scope.
03Non-functional requirements
Use these hypothetical requirements for the worked interview. Confirm the assumptions with the interviewer; the numerical targets require testing and are not measured results. For latency, p95 and p99 mean that 95% and 99% of measured delays, respectively, are no greater than the reported value.
- Workload. Assume 100,000 starts/day, ten model calls and fifteen ordinary tool calls per task, with a thirty-minute average approval wait. Account separately for bursts, retries and vendor limits.
- Responsive control. Target task creation and status p95 below 300 ms. Measure research, approval wait and submission completion separately; an approval that may take hours cannot share a tiny end-to-end latency target.
- Durable progress. Saved task state and activity results must survive the selected database-node failure. Waiting tasks consume durable state and timers rather than blocked workers. Retain activity results, approvals and provider reconciliation records through the declared recovery window, and keep unresolved action evidence available until reconciled.
- Exact authorization. Submission must use the exact currently approved proposal, a stable action identity and current permission/budget checks. Tenant isolation, allowed vendors, bounded quantities/spend and approval/quote expiry apply even when the model recommends otherwise.
- Honest external outcomes. Provider idempotency and lookup determine recovery after a lost response. Report
SubmissionUnknownwhen evidence is insufficient; do not claim canceled, completed or exactly-once remote execution merely because local workflow history is durable. - Bounded execution and privacy. Limit steps, tokens, retries, elapsed time and provider concurrency per tenant/task. Separate model calls, vendor reads and submission capacity; keep credentials and unrestricted network access outside model control.
04Save each completed step before moving forward
Begin with an API, a relational database and one background worker. Creating task T81 commits its owner, inputs and initial state before returning its ID. The worker claims ready work, loads T81 and performs the next activity. An activity is one bounded operation, such as fetching a vendor quote or asking the model to compare saved quotes.
Save each successful activity result and advance the workflow state in a transaction. If the worker restarts after that commit, it reads the saved result instead of making the same model call again. If it crashes before recording a harmless quote read, that read may run again. Re-execution is acceptable only when the operation’s effects permit it.
After research, save proposal P8 and enter WaitingApproval. No worker remains blocked for thirty minutes; the database records the wait. An approval request validates the actor and proposal version, then makes the submission step eligible. A worker submits it using a stable external action key and records the provider’s order ID.
The API returns task status from durable state. A browser disconnect does not cancel or erase the purchase process. This baseline already explains asynchronous execution, restart recovery and the difference between a waiting task and a running worker.
Workers perform ready activities; the database holds waiting tasks and saved results.
Read each connection in order
- syncCreate, inspect or approveRequester and approver → Task and approval API
- syncSave state and exact approvalTask and approval API → Task history and proposals
- asyncClaim ready stepTask history and proposals → Activity worker
- syncBounded activity or approved actionActivity worker → Model and approved vendors
- syncSave result and next stateActivity worker → Task history and proposals
05Separate running work from waiting tasks
Assume 100,000 task starts per day: approximately 1.16 starts/s on average. At ten model calls and fifteen ordinary tool calls per task, the averages are about 11.6 model calls/s and 17.4 tool calls/s. Peak bursts, retries and vendor rate limits require separate headroom.
With 3,000 input tokens and 500 output tokens per model call, average model demand is roughly 34,700 input tokens/s and 5,800 output tokens/s. Token volume and the number of active requests both matter when choosing provider quotas and worker concurrency. A fixed request count hides large prompts and long responses.
If approval takes thirty minutes on average, about 1.16 × 1,800 ≈ 2,083 tasks are waiting at any instant. They need durable rows and timers, not 2,083 blocked worker processes. The worker pool should scale with ready activities and external call latency.
At 200 saved events of 2 KB each, one task adds about 400 KB of history and 100,000 tasks add 40 GB/day before indexes and replication. Store large documents separately and reference immutable versions from history. Retention and redaction decisions should preserve the evidence needed for recovery without keeping every sensitive prompt forever.
06Give task, proposal and action separate identities
Create a task
POST /tasks
| Request information | Purpose |
|---|---|
| Scoped request key | Identify the intended creation; save it with the result so a client retry returns T81. |
| Purchase requirements | Describe the requested purchase, such as ten laptops in the worked example. |
Task control operations
| Operation | Request or result |
|---|---|
GET /tasks/T81 |
Return phase, current proposal, outstanding approval and any external result. |
POST /tasks/T81/approve |
Name the exact proposal version being approved. |
POST /tasks/T81/cancel |
Request the applicable cancellation behavior. |
Durable workflow records
| Record | Information retained | Purpose |
|---|---|---|
| Task | Current state and version | Coordinate the saved process. |
| ActivityResult | Workflow step, inputs and saved result | Recover completed work without unnecessarily executing it again. |
| Proposal | Immutable purchase terms | Identify the precise offer the human reviews. |
| Approval | Authenticated approver and exact proposal representation | Bind authority to those terms. |
| ExternalAction | Stable action key, payload, status and provider order ID | Recover one intended external purchase. |
Proposal fields
| Fields | What approval covers |
|---|---|
| Vendor and item identifiers | Who supplies which products. |
| Quantity | How many items are being purchased. |
| Total amount and currency | The commercial cost being approved. |
| Destination and quote expiry | Where the order goes and how long the offer remains valid. |
External action identity in the example
Task: T81
Proposal: P8
Action key: T81-P8-submit
The key identifies one intended purchase attempt, not a worker process. A replacement worker must reuse it when recovering that action.
Use expected task versions or a database lock to prevent two workers from advancing the same state concurrently. This protects local records. It does not undo an external effect already performed by a worker whose lease expired, so external action identity remains necessary even with careful scheduling.
07Keep model output inside an explicit workflow
Research first gathers quotes through permitted read-only tools. The model receives those saved facts and returns a structured comparison. Validate required fields and business constraints before constructing P8. Model output is a proposal; trusted application code calculates totals, checks approved vendors and determines whether the next step is allowed.
Waiting for approval is a durable state with an expiry timer. The approval endpoint checks the caller’s authority and the exact current proposal. A sentence saying “approved” in a document or chat message is not an authenticated approval. If a vendor changes the price or quote validity expires, produce a new proposal and request new approval.
Before contacting the provider
- Recheck permission and terms. Validate applicable permission, budget and proposal validity.
- Save intent. Persist the exact outgoing action and its stable key.
- Submit. Only then contact the provider.
This creates a recoverable account of what the worker intended to send even if the response never arrives.
The model may explain why one quote is preferable, but it does not receive raw production credentials or construct unrestricted network requests. Application code checks permission and saves progress; the model compares the supplied facts and explains its proposal. Each responsibility can be tested separately.
08Add workers without losing the saved process
A durable work queue separates task admission from execution. Publish ready work through a transactional outbox or an equivalent database-backed queue so a committed task cannot disappear between saving it and enqueueing it. An outbox is a table of pending dispatch records written in the same transaction as the state change; a relay forwards them and may retry.
Workers claim activities with bounded leases and renew while running. On expiry, another worker can recover the activity from durable state. Local version checks reject stale state updates. A duplicate queue message first inspects the recorded step outcome instead of assuming another complete execution is required.
Use separate concurrency limits for model calls, vendor reads and order submission. One slow vendor should not consume the entire pool. Apply tenant quotas and bound retry counts, token budgets and elapsed time per task. Waiting approval tasks consume neither provider concurrency nor busy workers.
A workflow engine can supply timers, history and retry scheduling once those requirements justify it. It does not automatically solve provider idempotency or business approval semantics. Keep the same saved-state and external-action contracts when adopting an engine, and pin workflow versions so a code deployment does not reinterpret an old task unpredictably.
An API transaction saves task or approval state with ready work. The relay can repeat delivery IDs; workers recover recorded outcomes before continuing. Model calls propose bounded results, while separately authorized vendor actions use stable action identities. Waiting approvals remain in storage.
Read each connection in order
- syncCreate, inspect or approveRequester and approver → Task and approval API
- syncCommit state and ready workTask and approval API → Workflow state and outbox
- asyncPending dispatch recordsWorkflow state and outbox → Outbox relay
- asyncPublish activity IDsOutbox relay → Ready activities
- asyncDispatch ready activitiesReady activities → Leased activity workers
- syncClaim, recover and save resultLeased activity workers → Workflow state and outbox
- syncBounded interpretationLeased activity workers → Approved language model
- syncPermitted read or approved actionLeased activity workers → Approved vendor APIs
09Recover the order whose response was lost
Lost-response trace for approved proposal P8
- Save the action. T81’s worker records
T81-P8-submit. - Send the purchase. The worker calls the vendor.
- The vendor accepts. It creates order O902.
- The response is lost. The connection breaks before the worker receives O902.
The saved action records what the worker was authorized to submit. It does not show whether the request reached the vendor or created an order.
If the provider supports durable idempotent submission, retry the same key and identical payload within its documented retention window. It should return the existing outcome instead of creating another order. If lookup by action key or client reference is available, query it and save the confirmed order identity. Provider guarantees must be verified; no generic HTTP retry supplies them.
If the provider cannot resolve the action safely, leave it SubmissionUnknown and reconcile through a controlled operator process. Do not invent a fresh key just to get a successful response. That would convert one uncertain purchase into a possible duplicate purchase.
This is the central recovery story. Saving workflow history prevents forgotten progress, but cannot make a remote side effect part of a local database transaction. The application needs provider cooperation or an honest uncertain state. “Exactly once” without that boundary obscures the business risk instead of solving it.
The replacement worker recovers the same purchase identity.
Read each connection in order
- syncSave T81-P8-submitWorker → Action record
- syncSubmit with stable keyWorker → Vendor
- returnCreates O902; reply lostVendor → Worker
- syncRecover unresolved actionWorker → Action record
- syncLookup or retry same supported keyWorker → Vendor
- returnReturn existing O902, or unresolvedVendor → Worker
10Handle changes while a task is in progress
Before the service authorizes submission, canceling T81 saves a terminal state that blocks the purchase. Submission checks the current task version. If cancellation and submission race, the database accepts one state change first; that order determines whether submission was authorized, and the UI reports the result.
Once submission may have reached the provider, cancellation becomes a request to stop or reverse an order, subject to the vendor’s API and business rules. A successful local cancel button cannot prove an in-flight remote purchase vanished. Resolve the original action first, then perform any supported cancellation under its own tracked identity.
Changing quantity, vendor or destination creates a new proposal version. Approval for P8 does not authorize P9 even if both belong to T81. Similarly, an expired quote may require research and approval again rather than silently purchasing at a new price.
Retry read-only activities with bounded backoff, but classify failures. Invalid input is not repaired by ten retries, and an uncertain purchase is not equivalent to a failed quote read. Escalation, compensation and human review are explicit workflow outcomes. The simplest safe design makes those states visible rather than hiding them behind a generic retry loop.
11Test business boundaries and recovery evidence
Trace task, activity, proposal and action IDs across logs while redacting credentials and unnecessary personal data. Measure queue age, ready versus waiting tasks, activity latency, provider error rate, token/spend budgets, approval age and unresolved submissions. A high completion rate can conceal dangerous duplicates or stale approvals, so inspect those outcomes separately.
Test a worker crash before saving a quote, after saving a model result, while waiting for approval and immediately after a provider accepts an order. The expected recovery differs at each point. Also test duplicate queue messages, changed proposals, revoked approvers, expired quotes and exhausted provider idempotency retention.
Treat retrieved content and vendor descriptions as untrusted input. Instructions embedded in them cannot authorize a tool or change the allowlist. Tool gateways validate schemas and permissions; secrets remain in trusted service integrations. Sandboxed computations may help comparison, but a sandbox is not a substitute for authorizing the eventual purchase.
Deploy workflow changes with compatibility for existing histories or explicitly migrate them. Practice operational reconciliation using realistic provider evidence. The strongest final design is one the operator can explain after a timeout: what was approved, what may have been sent, what was confirmed, and which action is still safe to take.
12Check the design against its requirements
Before closing, check the final design against the agreed requirements. FR means functional requirement and NFR means non-functional requirement; the numbers refer to the lists above. These are proposed validation checks, not test results.
| Requirement | Mechanism in the final design | Validation and remaining limit |
|---|---|---|
| FR 1, 2; NFR 1–3 | Transactional saved state, activity results, durable dispatch and waiting timers let workers resume. | Crash around an activity commit and leave 2,083 illustrative tasks awaiting approval. Verify no blocked worker per wait; load-test control p95 and recovery under node loss. |
| FR 3, 4; NFR 4 | Immutable proposals, authenticated approvals and guarded submission recheck exact terms. | Change quantity, expire a quote, revoke an approver and race workers. Require a valid current approval and one stable intended action. |
| FR 4; NFR 3, 5 | External action records preserve the provider key and uncertain result for reconciliation. | Lose O902’s reply; recover with the same supported key or lookup. If the provider cannot resolve it, require unknown status and operator review, not another purchase. |
| FR 5; NFR 4, 5 | The task state transition orders cancellation against submission admission. | Race cancellation before and after admission. Prevent a not-yet-admitted action; do not pretend a remote order already accepted has vanished. |
| NFR 6 | Tool validation and separate tenant/provider budgets constrain model-driven work. | Inject vendor-text instructions and exhaust one provider’s quota. Check credentials stay private and unrelated work can progress within measured capacity. |
13Rapid revision
Rehearse the numbered functional requirements and non-functional targets first. Use this table to recall the mechanisms, then close with the requirements check above.
Remember: Lost purchase reply → recover the same action.
| Prompt | Recall the mechanism and limit |
|---|---|
| What makes a workflow durable? | Saved state and activity results let replacement workers resume after a crash |
| Why save a waiting state? | A thirty-minute approval wait needs a record and timer, not a blocked worker |
| What can the model approve? | Nothing by itself; application policy and an authenticated person authorize actions |
| What does approval name? | The exact unchanging proposal, including purchase terms and expiry |
| Why a stable external action key? | Replacement workers must recover the same intended purchase |
| Does a lease prevent duplicate purchases? | No; it coordinates workers but cannot undo an external purchase |
| What follows a lost vendor reply? | Retry the provider-supported key or look up the result; otherwise report unknown |
| What does cancellation mean? | Before submission is authorized it blocks the purchase; afterward reversal needs its own tracked action |
| What limits cost? | Limit steps, tokens, retries, elapsed time and simultaneous provider calls |
Close with: “I use a fixed durable workflow around the model. Saved proposals and authenticated approvals authorize exact actions. Workers can restart, but external effects recover through stable identities and provider evidence. When that evidence is insufficient, the workflow reports uncertainty instead of blindly buying again.”
Practise the interview questions
Say your answer aloud before opening the model answer. Then answer the follow-up and compare the reasoning.
What makes this more reliable than replaying a chat transcript?
Reveal a model answer
The service stores explicit workflow state, bounded activity results, exact proposals, authenticated approvals and external action identities. A restarted worker resumes from those facts instead of asking the model to reconstruct what happened.
Interviewer follow-up
Can the model still choose tools?
Reveal the follow-up answer
It can propose permitted operations inside a bounded workflow, but trusted code validates and authorizes execution.
What the answer must demonstrate: The service stores explicit workflow state, bounded activity results, exact proposals, authenticated approvals and external action identities.
Do 2,083 tasks waiting for approval require 2,083 workers?
Reveal a model answer
No. Waiting tasks are durable records with timers. Workers run ready activities and release capacity while approval is pending. Worker sizing follows active call demand and latency rather than the number of open tasks.
Interviewer follow-up
What wakes a waiting task?
Reveal the follow-up answer
A validated approval, cancellation or expiry transition makes the appropriate next step ready.
What the answer must demonstrate: No. Waiting tasks are durable records with timers.
P8 was approved, but the vendor changes the price. May the agent submit?
Reveal a model answer
Not under the old approval. Validate the saved quote and exact proposal before admission; changed commercial terms require a new proposal and approval. Generated text saying the new price is acceptable does not authorize it.
Interviewer follow-up
What fields should approval bind?
Reveal the follow-up answer
Vendor, items, quantity, amount, currency, destination, validity and the immutable proposal identity.
What the answer must demonstrate: Not under the old approval. Validate the saved quote and exact proposal before admission; changed commercial terms require a new proposal and approval.
The worker crashes after saving a model result. Should it call the model again?
Reveal a model answer
It should reuse the saved activity result and resume the next state. If the result was never committed, repeating a bounded read or generation may be acceptable; external purchases require a different recovery contract.
Interviewer follow-up
Why preserve workflow versions?
Reveal the follow-up answer
A new deployment should not silently reinterpret saved state or reorder actions in an existing task.
What the answer must demonstrate: It should reuse the saved activity result and resume the next state.
The vendor accepted an order but its response was lost. What next?
Reveal a model answer
Recover the same action identity through the provider’s documented idempotent retry or lookup within its supported retention window. Save the confirmed order if found. If it cannot be resolved, report SubmissionUnknown and reconcile; a new key risks another order.
Interviewer follow-up
Does a transactional outbox solve this alone?
Reveal the follow-up answer
No. It reliably dispatches intended work but may dispatch again; the external effect still needs identity and recovery.
What the answer must demonstrate: Recover the same action identity through the provider’s documented idempotent retry or lookup within its supported retention window.
Why is a worker lease insufficient to guarantee one purchase?
Reveal a model answer
An expired worker may already have sent the request, and a remote provider can act after local ownership changes. Leases and task versions coordinate local progress; a stable external action key handles duplicate submission where the provider supports it.
Interviewer follow-up
What if the provider supports neither idempotency nor lookup?
Reveal the follow-up answer
Do not claim safe automatic recovery of an uncertain action; keep it unresolved for controlled reconciliation.
What the answer must demonstrate: An expired worker may already have sent the request, and a remote provider can act after local ownership changes.
Can cancel always promise that no order was created?
Reveal a model answer
Only before submission has been admitted and sent. Afterward the action may already exist remotely. Resolve that action and use the vendor’s cancellation or compensation process under a tracked identity. The UI must distinguish these states.
Interviewer follow-up
Can changing the proposal cancel the old one implicitly?
Reveal the follow-up answer
No. Track any admitted action separately and resolve it; new proposal state does not erase an external request.
What the answer must demonstrate: Only before submission has been admitted and sent.
A retrieved vendor document tells the model to send credentials elsewhere. What stops it?
Reveal a model answer
Retrieved text is untrusted data. Tool gateways allow only validated operations, enforce current permissions and keep secrets in trusted integrations. The model cannot authorize a destination or grant itself a credential.
Interviewer follow-up
What operational signal most deserves attention?
Reveal the follow-up answer
Unresolved external submissions and approval mismatches deserve direct inspection even when overall completion rates look healthy.
What the answer must demonstrate: Retrieved text is untrusted data. Tool gateways allow only validated operations, enforce current permissions and keep secrets in trusted integrations.
Blank-page exercise · 45 minutes
Build the answer yourself
Design an AI-assisted purchasing workflow that compares approved vendors, waits for human approval and safely handles a lost order response.
- Agree the numbered functional requirements and non-functional targets, including the model’s role, exact approval, response time, durability and external uncertainty.
- Draw the one-worker saved-state baseline.
- Separate waiting tasks from active concurrency.
- Model exact proposals and authenticated approvals.
- Trace an accepted purchase with a lost reply.
- Validate task control, approval, submission, cancellation, recovery, latency and budgets against the numbered requirements; state unresolved provider and retention limits.
Check that each component and design decision follows from your requirements and workload.
Recall the key ideas
Answer from memory before opening each card. Explain why the choice works and what it costs. Revisit missed cards tomorrow.
Design durable agent workflowsThe vendor creates O902 but its reply is lost. What may the replacement worker do?Recall first, then reveal
Recover the saved action using the same provider-supported key or a result lookup. If the provider cannot establish the outcome, keep it unknown for reconciliation rather than send a new purchase.
Lost purchase reply → recover the same action.
Return to lessonDesign durable agent workflowsWhy not use a fresh key after a purchase reply is lost?Recall first, then reveal
The first purchase may already exist. Recover its original action through the provider’s supported retry or lookup; a fresh key can create another order.
Unknown is a state
Return to lessonFinal revision
Summary and interview notes
Save progress so another worker can resume. Require approval for the exact purchase. If the vendor’s reply is lost, recover the original action through its supported retry or lookup; otherwise report the outcome as unknown.
Remember these points
- Agree the numbered functional requirements and non-functional targets before designing components; validate the final design against them.
- Saved activity results prevent unnecessary re-execution.
- Approval binds an exact proposal.
- Waiting tasks do not block workers.
- Remote uncertainty needs a visible recovery state.
Interview tips
- Use one lost-order-response story to defend the architecture.
- Never use exactly-once as a replacement for the external provider contract.
Important qualifications
- General autonomous planning and cross-system compensation protocols are optional extensions.
Continue after the core interview
Explore the advanced version
The advanced lesson keeps the full detailed design. Use these sections when you want to examine the stronger requirements and failure cases.
- Worker fencing across independent authorities
Useful for implementing concurrent recovery beyond the local state-version explanation.
- Budget reservation under parallel branches
A stronger parallel-action budget requires coordinated reservation and release.
- Compensation across multiple business systems
Reversing several completed actions needs explicit business-specific semantics.
- Workflow-engine replay compatibility
Engine-specific history and code-version rules matter during production migration.
Technical references
- Scaling Managed AgentsApril 2026 engineering account separating session history, orchestration, and execution environments.
- Building effective agentsPrimary engineering discussion of fixed workflows, model-directed agents, and when added complexity is justified.
- Temporal workflow versioningConcrete documentation of evolving durable workflows without breaking replay.
- OWASP prompt injectionDefines indirect instructions in untrusted sources and layered capability controls.
- Temporal Activity definitionRecorded Activity results support replay; retried execution still requires external idempotency.
Practice marks stay in this browser.