Interview question
Diagnose an agent loop that repeats tools and exhausts its budget
Uses workflow traces to distinguish planning failure, stale observations, retry ambiguity, and missing terminal conditions in a looping agent.
TL;DR
Uses workflow traces to distinguish planning failure, stale observations, retry ambiguity, and missing terminal conditions in a looping agent.
Trace-driven debugging, state-machine reasoning, loop detection, retry classification, progress invariants, and safe containment.
Practice the problem like a real interview: restate, reason, implement, and test.
A support agent sometimes calls search_ticket and get_customer in the same sequence until its 20-step budget is exhausted. In other cases it submits update_ticket twice after a timeout. You have step traces with state version, tool arguments hash, observation hash, provider outcome, retry classification, remaining budget, and final status. Diagnose both loop types, contain the issue, and design regression tests.
Move to the linked follow-up, next path step, prerequisite, or deeper variant.
Move forward in the planned practice sequence.
Steps 4-11: identical state_version=7, search_ticket(args=A), get_customer(args=B), identical observation hashes
Step 12: update_ticket idempotency_key missing -> timeout
Step 13: planner sees no recorded success and emits update_ticket again with different request ID.
def guard_next_step(history: list[Step], proposal: Proposal, budget: Budget) -> GuardDecision:
budget.require_remaining_step()
signature = (
history[-1].state_version if history else 0,
proposal.tool_name,
stable_hash(proposal.arguments),
)
repetitions = sum(step.signature == signature for step in history[-8:])
if repetitions >= 2:
return GuardDecision.stop("repeated_action_without_state_progress")
if proposal.has_side_effect:
if not proposal.action_id or not proposal.idempotency_key:
return GuardDecision.stop("unsafe_side_effect_identity")
if history_has_ambiguous_outcome(history, proposal.action_id):
return GuardDecision.reconcile(proposal.action_id)
if workflow_complete(history):
return GuardDecision.stop("goal_already_satisfied")
return GuardDecision.allow()
Online guarding scans only a bounded recent history, so each decision is O(1) with respect to total workflow length. Offline grouping is linear in retained steps plus aggregation cost.
Aporeon is shaped by Aleksandar Tomovski, a software developer with experience on both sides of technical interviews. Content is reviewed for accuracy, natural spoken delivery, useful depth, and honest trade-offs.
Help improve the interview library.
Say thanks with a standalone, one-time $5 contribution. No account required.