Vibe Engines is free, interactive AI engineering & system design — runs in your browser. Pick a learning path →
The Sierra Agent
Engineer interview
Sierra’s version of forward-deployed work is the Agent Engineer: someone who builds, tunes and operates customer-specific agents. The loop is built around one question — do you actually understand how an agent works, or do you import one? Candidate reports describe a take-home and a debugging round built to answer it, and in April 2026 Sierra rebuilt its engineering onsite around building with AI.
What an Agent Engineer is
Sierra has written publicly about the Agent Engineer role: building and tuning agents against a customer’s real workflows, owning their behaviour in production, and iterating on them as the customer’s needs change.first-party28
Functionally this is a builder FDE with an agent-shaped mandate: the customer is real and named, the deployment is theirs, and adoption is the measure.
The current posting titles the job Software Engineer, Agent and frames it as owning the Agent Development Life Cycle, “from initial pilot through deployment and continuous iteration”, for customers including The GAP, Rocket Mortgage, SoFi, Sutter Health and SoftBank.first-party42
What differs from a generic FDE role is the depth expected on one specific technical surface. You are expected to reason precisely about tool schemas, escalation paths, guardrails, failure handling, evaluation of non-deterministic behaviour, and what happens when the agent is confidently wrong in front of a customer’s customer.
The reported loop
From a named first-hand account, an aggregated guide and Sierra’s own April 2026 post. The two candidate sources disagree in places, so both are shown. Verify with your recruiter.
Technical screen, reported two ways
One first-hand account describes a CoderPad problem that grows — an endpoint that fails intermittently, then fallback product IDs to resolve — each part built on the last.named first-hand24 An aggregated guide reports a single 60-minute data-structures problem instead, such as detecting circular references between spreadsheet cells, extended to a faster approach on request.aggregated25 Sierra says this phone screen is now a system design interview.first-party41
Prepare: write the simple, extensible version first and narrate before you type. Section 04 works the spreadsheet version end to end.
Take-home: a support agent for a fictional client
Candidates report an API key and a brief to build an agent that performs several functions.named first-hand24 The aggregated guide adds an OpenAI key, a feature list to prioritise, written questions on observability and metrics, and interviewers looking for a loop that calls tools directly, with no reliance on an agent framework.aggregated25
Prepare: build one agent loop from scratch before you need to — section 06 has a minimal one. It is a two-hour exercise that permanently changes how you talk about agents.
Debugging an unfamiliar codebase
About three bugs in a four-to-five-file agent codebase, with a diagram of intended behaviour as the source of truth, in one account;named first-hand24 a TypeScript and React app, each bug traced to its customer impact, in another.aggregated25 Sierra is piloting a version built around improving a colleague’s draft pull request with coding agents.first-party41
Prepare: practise a stated method — read fully, form a hypothesis, add the smallest instrument that confirms or kills it, fix, verify. Announce each step aloud; the method is what is being scored.
Presentation, customer judgement and fit
A presentation split between your take-home and a technical topic explained to a non-technical audience, then a hiring-manager round.aggregated25 Sierra evaluates values alignment alongside capability; its postings name Trust, Customer Obsession, Craftsmanship, Intensity and Family.first-party4442
Prepare: have a concrete answer for evaluating non-deterministic behaviour. “We would look at the transcripts” is not one. Agent evals →
What Sierra changed in April 2026
Sierra published its redesign: the coding and algorithms interviews are gone, and the onsite is built around building with AI. Ask your recruiter whether your loop has moved to it.
Sierra’s loop had been “two coding interviews plus interviews for algorithms, system design, and culture fit, followed by reference checks.” Finding the signal mostly about mechanics, it replaced the coding and algorithms rounds with an AI-native onsite.first-party41
Define a product in your own domain
You drive the ideation; the interviewers question it to strengthen it. Prepare: bring two ideas, each with a user, a painful workflow and a definition of done.
Two hours, alone, with your own tools
The interviewer leaves and you build with the AI tooling and frameworks of your choice. Criteria are shared in advance, and cutting scope or skipping boilerplate such as CRUD and auth is fine. Prepare: rehearse your setup until starting a project costs five minutes.
Demo it, then defend the code
A debate on the product flows, a code review of the data model, abstractions and extensibility, the path to production, and how you used AI. Prepare: keep a running note of scope cuts and rejected AI suggestions while you build.
The phone screen became system design, because “vibe-coding an app is easy” and production is the hard part;41 the aggregated guide reports an agentic subscription-cancellation flow as one prompt.25 The debugging pilot has you improve a colleague’s draft PR with coding agents, and interviews run in pairs against criteria that do not depend on what you build.41
Recalling an algorithm under time pressure is worth less than it was; scoping a two-hour build, steering coding agents and defending a data model are worth more. Keep the agent-loop drill either way — every round rewards knowing what happens inside an agent.
The spreadsheet problem, worked
A practice problem in the style of the reported question, not Sierra’s own: three stages, each of which breaks the previous design.
Cells hold a number or a formula such as =A1+B1+2. Agree that small a grammar out loud, so the hour goes on the graph rather than on a parser.
| Stage | New requirement | What breaks, said before you refactor |
|---|---|---|
| 1 | set(cell, raw), get(cell) | Nothing. Recursive evaluation on every read is correct — ship it, and say each read costs the cell’s whole dependency tree. |
| 2 | Reject a circular reference; leave the sheet unchanged | The recursive evaluator never terminates. An edit creates a cycle exactly when one of the new formula’s inputs can already reach the edited cell, so check that before mutating anything. |
| 3 | Instant reads; a change recomputes only what it affects | Read-time evaluation repeats shared work. Cache values, keep a reverse index of readers, and recompute only the downstream cells — each once, in dependency order. |
import re
REF = re.compile(r"[A-Z]+[0-9]+")
class CycleError(ValueError):
pass
class Sheet:
def __init__(self):
self.raw = {} # cell -> "7" or "=A1+B1+2"
self.deps = {} # cell -> cells its formula reads
self.users = {} # cell -> cells whose formulas read it
self.value = {} # cell -> cached number; get() never computes
def _reaches(self, start, target):
# stage 2: can we walk from start to target along deps? (iterative DFS)
stack, seen = [start], set()
while stack:
c = stack.pop()
if c == target:
return True
if c not in seen:
seen.add(c)
stack.extend(self.deps.get(c, ()))
return False
def set(self, cell, raw):
new = set(REF.findall(raw)) if raw.startswith("=") else set()
if any(self._reaches(d, cell) for d in new): # reject before mutating anything
raise CycleError(f"{cell} would depend on itself")
for d in self.deps.get(cell, ()):
self.users[d].discard(cell)
for d in new:
self.users.setdefault(d, set()).add(cell)
self.raw[cell], self.deps[cell] = raw, new
self._recompute(cell)
def _eval(self, cell):
raw = self.raw.get(cell, "0")
if not raw.startswith("="):
return int(raw)
return sum(self.value.get(t, 0) if REF.fullmatch(t) else int(t)
for t in (p.strip() for p in raw[1:].split("+")))
def _recompute(self, start):
# stage 3: only cells downstream of the edit, each evaluated once, in dependency order
affected, stack = {start}, [start]
while stack:
for u in self.users.get(stack.pop(), ()):
if u not in affected:
affected.add(u)
stack.append(u)
waiting = {c: sum(d in affected for d in self.deps.get(c, ())) for c in affected}
ready = [c for c in affected if waiting[c] == 0] # Kahn's algorithm on the affected subgraph
while ready:
c = ready.pop()
self.value[c] = self._eval(c)
for u in self.users.get(c, ()):
if u in affected:
waiting[u] -= 1
if waiting[u] == 0:
ready.append(u)
def get(self, cell):
return self.value.get(cell, 0)
Cost: get is O(1); a write costs one depth-first search plus O(A + E) over the A downstream cells and the E edges among them. Running Kahn’s algorithm on the affected subgraph only is what makes a diamond — A1 feeds B1 and C1, both feed D1 — evaluate D1 once rather than twice.
A write that touches half the sheet: mark cells dirty and recompute lazily on read. Many writes in a row: batch them and recompute once. A formula that cannot be evaluated: store the error as its value and let it propagate, the way a spreadsheet shows #VALUE! downstream. Topological sort, step by step →
Why the no-framework constraint matters
Candidate reports say interviewers look for it, and it is the cleanest signal-extraction device in any reported FDE loop — worth understanding beyond this one company.
An agent framework hides exactly the parts that break in production. Build one by hand and you are forced to make every decision the framework was making for you:
| Decision the framework hides | What goes wrong in production |
|---|---|
| Termination condition | The agent loops forever, or stops one step before finishing. Both are common; both are your bug, not the model’s. |
| Tool-result formatting | A raw 400-row API response floods the context and the model loses the thread of the task. |
| Error handling inside the loop | A failed tool call becomes an exception instead of an observation the agent can recover from. |
| Tool schema design | Vague parameter descriptions produce confidently wrong arguments. Most “the model is bad” reports are schema bugs. |
| Context management | Unbounded history means rising cost, rising latency and degrading quality as the conversation grows. |
| Escalation to a human | Never handing off is worse than being wrong — and this is a product decision, not a technical one. |
Not whether your agent works — whether you can say why you made each of those six decisions and what you would change under a different constraint. Candidates who have only ever configured a framework cannot, and the gap is audible within two minutes.
A minimal support-agent loop, by hand
About forty lines against the OpenAI Responses API, the key the aggregated guide says the take-home provides. Each of the six decisions above is a line you can point at.
import json
MODEL = "the-model-your-brief-names"
POLICY = "You are Acme's support agent. Look orders up before answering. Never promise refunds."
MAX_STEPS, MAX_RESULT_CHARS = 8, 2_000
HANDOFF = "I'm handing you to a teammate who can help with this."
def lookup_order(order_id):
return {"order_id": order_id, "status": "shipped", "eta": "2026-10-24"} # the client's API goes here
TOOLS = [
{"type": "function", "name": "lookup_order", "strict": True,
"description": "Fetch one order by id. Call this before answering anything about an order.",
"parameters": {"type": "object", "additionalProperties": False, "required": ["order_id"],
"properties": {"order_id": {"type": "string", "description": "Like 'A-10293'."}}}},
{"type": "function", "name": "escalate_to_human", "strict": True,
"description": "Hand off to a person: refunds, anything policy forbids, or when you are unsure.",
"parameters": {"type": "object", "additionalProperties": False, "required": ["reason"],
"properties": {"reason": {"type": "string"}}}},
]
HANDLERS = {"lookup_order": lookup_order}
def run_turn(client, history):
"""One customer turn. Extends history in place; returns (reply, status)."""
for _ in range(MAX_STEPS):
resp = client.responses.create(model=MODEL, instructions=POLICY, input=history, tools=TOOLS)
history += resp.output # the model's calls (and any reasoning) stay in context
calls = [item for item in resp.output if item.type == "function_call"]
if not calls:
return resp.output_text, "answered" # exit 1: the model answered
handoff = None
for call in calls:
try:
args = json.loads(call.arguments)
if call.name == "escalate_to_human":
handoff, output = args["reason"], "handed off"
else:
output = json.dumps(HANDLERS[call.name](**args))[:MAX_RESULT_CHARS]
except Exception as e: # a failed call is an observation, not a crash
output = json.dumps({"error": type(e).__name__, "detail": str(e)[:200]})
history.append({"type": "function_call_output", "call_id": call.call_id, "output": output})
if handoff:
return HANDOFF, "escalated" # exit 2: a person takes over
return HANDOFF, "step_limit" # exit 3: the budget ran out; never loop forever
Three exits, each with a status you can count; MAX_RESULT_CHARS as a crude bound on what enters context (summarise or paginate in a real build); an except that turns a timeout, malformed arguments or a hallucinated tool name into an observation; strict schemas whose descriptions say when to call a tool; a history you should say how you would trim; and escalation as a tool, so handing off is a decision rather than a crash.
Two details interviewers notice. Every function_call is answered by a function_call_output with the same call_id, the escalation included, so the transcript stays valid next turn. And history += resp.output keeps the model’s own items in context, which OpenAI’s guide requires for reasoning models.45
Then measure it the way Sierra does: run each scenario several times. Sierra Research introduced pass^k with τ-bench — the chance that all k attempts at a task succeed — and found state-of-the-art function-calling agents succeeding on under 50% of tasks, with pass^8 below 25% in retail.first-party43 One working demo is the evidence that metric was built to replace.
The exercise that fixes this permanently
Implement the loop yourself: prompt, tool schema, dispatch, observation, termination, recovery. Then break it deliberately and watch what happens.
The picture: the hand-written loop and its three exits
function_call needs its matching function_call_output: next step, the model reads the whole transcript again.Cost and trade-offs: the sheet and the loop
For the three spreadsheet stages, Time and Space mean the usual thing. Here V is the number of cells and E the number of formula references, and A is the set of cells downstream of an edit. For the agent knobs, Time is latency and Space is what enters the context window.
| Case | Time | Space | Why |
|---|---|---|---|
| Sheet stage 1: evaluate on read | set O(1); get walks the cell’s whole dependency tree, with shared cells walked again | O(V) formulas, plus recursion depth | Correct and quick to write. Never terminates on a cycle. |
| Sheet stage 2: reject cycles | set adds a DFS: O(V + E) worst case | seen set, O(V) | The check runs before anything changes, so a rejected edit leaves nothing behind. |
| Sheet stage 3: cache + reverse index | get O(1); set = DFS + O(A + EA) | deps, users, value: O(V + E) | Memory for both directions of every edge buys instant reads. |
Raise MAX_STEPS | Worst-case turn latency grows with each extra model call | History grows by every call and output | Fewer step_limit exits, but a stuck agent burns more before it gives up. |
Lower MAX_RESULT_CHARS | Faster, cheaper calls | Less of each tool result enters context | A hard cut can drop the one field that mattered. Select fields or paginate instead. |
| Measure pass^k, not one run | k times the API calls per scenario | None | At 80% per run (if runs are independent), pass^8 is 0.88 ≈ 0.17. |
Common mistakes in this loop
- Recursive cycle detection in Python
A recursive DFS crashes with
RecursionErroron a chain longer than about 1,000 cells, Python’s default recursion limit. That is why_reachesuses an explicit stack. Say this out loud when you write it. - Retrying a tool that changes things
A timeout does not mean the action failed. Retry a refund or a cancellation blindly and the customer may be charged or credited twice. Send an idempotency key, or look up the state before you retry.
- Slicing a JSON string
[:MAX_RESULT_CHARS]can cut through the middle of a value, so the model reads broken JSON. That is acceptable in a drill. In a real build, pick the fields the task needs before you serialise, or return one page of results and a cursor. - Fixing a schema bug in the prompt
When the model passes a name where an order id belongs, adding more rules to
POLICYtreats the symptom. Fix the parameter description and give an example value, as in"Like 'A-10293'.". The page notes that most “the model is bad” reports turn out to be schema bugs. - Stopping at the first bug
The debugging round reportedly plants about three bugs. Fixing one and announcing that you are done shows you stopped looking. After each fix, check the intended-behaviour diagram again and look for the same class of bug elsewhere.
Check yourself
A1 = 1, B1 = =A1+1, C1 = =B1+1. You call set("A1", "=C1+1"). What happens?
new is {C1}. _reaches("C1", "A1") walks C1 → B1 → A1 and returns true, so CycleError is raised before any index changes. A1 is still 1 and every cached value stands.
A1 feeds B1 and C1; both feed D1. You set A1 = 5. How many evaluations run, and what decides the order?
Four: A1, B1, C1, D1, one each. Kahn’s count gives D1 two waiting inputs, so it becomes ready only after both B1 and C1 are done. B1 and C1 can go in either order.
The model calls a tool named cancel_order that is not in HANDLERS. What does the loop do?
HANDLERS[call.name] raises KeyError inside the try, so the output becomes {"error": "KeyError", ...} under the same call_id. It goes back into history, the loop continues, and the model can recover. It uses up one of the 8 steps.
A scenario passes 80% of runs. You demo it once and it passes. What have you shown?
Very little. One pass happens 80% of the time anyway. If runs are independent, the chance that all 8 of 8 pass is 0.88 ≈ 0.17. That gap is what pass^k is built to expose, so run every scenario several times and report the rate.
Quick answers
What is the Sierra Agent Engineer interview process?
Candidate accounts describe a recruiter call, a technical screen, a take-home in which you build a customer-support agent, a debugging round on an unfamiliar codebase, a presentation, and a hiring-manager round that also checks alignment with Sierra’s values. In April 2026 Sierra published a redesign: a system design phone screen and an AI-native onsite in which you plan a product, build it for two hours with your own AI tools, then defend it. Ask your recruiter which version you will get.
Can you use an agent framework in the Sierra take-home?
Sierra has not published take-home rules. An aggregated candidate guide says interviewers look for a loop that calls tools directly with no reliance on a framework, while the April 2026 onsite lets candidates use the frameworks of their choice. Writing the loop by hand is still the safest preparation, because it forces every decision a framework hides: termination, tool-result formatting, error handling inside the loop, schema design, context management and escalation to a human.
What is the Sierra spreadsheet interview question?
An aggregated candidate guide reports a technical-screen problem about detecting circular references between spreadsheet cells, extended to a more efficient approach on request. Prepare it in three stages: evaluate formulas recursively, reject any edit whose new inputs can already reach the edited cell, then cache values and recompute only downstream cells in topological order. Sierra says its phone screen has since moved to system design, so confirm the format.
How do I prepare for a debugging round with planted bugs?
Practise a stated method rather than speed: read the code fully before editing, form a specific hypothesis, add the smallest instrument that confirms or kills it, fix, then verify the fix and check whether the same class of bug appears elsewhere. Announce each step aloud — the method is what is being scored, not the number of bugs found in the first ten minutes.
What is an AI agent engineer?
A builder role focused on constructing, tuning and operating agents against a specific customer’s workflows, owning their behaviour in production. Sierra has written publicly about the role. Functionally it is a forward deployed engineer with an agent-shaped mandate, requiring unusual depth on tool schemas, escalation design, guardrails and evaluating non-deterministic behaviour.
Sources
Every number on this page traces to one of these. Where a figure is self-reported or crowd-sourced rather than first-party, it is labelled inline.
Cited on this page
- Gaijineer — Sierra software engineer (agent) interview experience — named first-hand candidate account. gaijineer.co/sierra-software-engineer-agent-interview-experience
- Exponent — Sierra Agent Engineer interview guide — www.tryexponent.com/guides/sierra-agent-engineer-interview
- Sierra — “Meet the AI agent engineer” (first-party) — sierra.ai/blog/meet-the-ai-agent-engineer
- Sierra — “The AI-native interview” (22 Apr 2026, first-party) — the redesigned engineering loop: plan, build and review onsite; system design phone screen; debugging pilot. sierra.ai/blog/the-ai-native-interview
- Sierra — Software Engineer, Agent (job posting, first-party) — Agent Development Life Cycle ownership, named customers, the five values. jobs.ashbyhq.com/Sierra/e9f5fdb6-91ee-4c55-9230-41ec8865650e
- Yao, Shinn, Razavi & Narasimhan — “τ-bench: A Benchmark for Tool-Agent-User Interaction in Real-World Domains” (arXiv 2406.12045, Jun 2024) — Sierra Research (code at github.com/sierra-research/tau-bench); introduces the pass^k metric. arxiv.org/abs/2406.12045
- Sierra — Careers: “Interviewing at Sierra” (first-party) — values alignment is evaluated; interviews are held in person at an office. sierra.ai/careers
- OpenAI API docs — Function calling — the function_call / function_call_output round trip and passing reasoning items back. developers.openai.com/api/docs/guides/function-calling
Explore the topic
See this alongside everything else on the same subject — handbooks, system designs, challenges and tools, in one place.
More Handbooks
- The Agentic AI Interview HandbookTwenty topics every senior AI engineer should be able to reason about live — from eval pipelines to reliability patterns for generative systems.Read →
- The Senior AI Engineer Interview Handbook60 questions across architecture, production incidents, agentic systems, RAG, evals, cost, safety, and leadership — what staff-level AI interviewers actually probe for.Read →
- 50 Angular Interview QuestionsA visual handbook covering components, change detection, RxJS, signals, routing, forms, performance, and testing — what interviewers actually probe for in senior Angular roles.Read →
- 50 Python Interview QuestionsFundamentals to advanced: data structures, OOP, iterators & generators, the GIL, asyncio, memory, testing, and the standard library — a visual walk through everything a Python interview touches.Read →
- 51 LLM Evals Interview QuestionsGolden sets, LLM-as-judge, regression testing, offline vs online evals, RAG evals, agent evals, red-teaming, and observability — demystified for interviews and production.Read →
- The Agent Evaluations HandbookA self-contained handbook on evaluating AI agents — theory, interactive widgets, and practical guidance. Trajectory evals, tool-use scoring, LLM-as-judge, observability, and reliability for PMs, engineers, and founders.Read →