Format. A technical screen for Mercor's Applied AI role, from one report posted in September 2026: a debugging exercise, and a list of rapid-fire questions on LLM applications and idempotency that ends with two questions about a project you lead. The report doesn't give the length, whether you run the code, or the outcome.
1. Debug an async refund function. The code, as the candidate posted it:
async def refund_money(request_id: str):
refund = await get_db_record(request_id)
if refund.status == "done":
return
for i in range(3):
try:
await stripe_api_call(
refund.request_id,
refund.amount
)
break
except Error:
continue
await mark_db_as_done(request_id)
The report sums it up as debugging an async refund/payment function with retries and database state updates.
What's wrong with it (ours, not from the report). We ran it against a fake database and a fake Stripe; the first four of these reproduce:
except Error: names a class Python doesn't have (unless the codebase defines one). The first time the Stripe call raises, evaluating Error raises NameError, so nothing is ever retried. Catch the client library's real exception types.mark_db_as_done runs anyway, so the customer is never refunded but the record says they were.stripe_api_call already sends an idempotency key, which the snippet doesn't show). If Stripe processes the refund but the response is lost, the retry sends a second refund. Send an idempotency key derived from the request, the same on every attempt.done, then both call Stripe. Claim the work with an atomic state change (pending → processing, as a compare-and-set or a row lock) before calling out.mark_db_as_done leaves a refunded record that isn't marked; the next run refunds again unless the idempotency key is there. A processing claim also needs a lease or a reconciler, so a worker that dies doesn't hold it forever.refund is None) raises an unclear AttributeError.How Stripe's idempotency keys behave (from Stripe's API v1 docs): Stripe saves the first response for a key, errors included, and returns it for any repeat within about 24 hours; reusing a key with different parameters is an error, and so is a repeat that arrives while the first request is still running. So a retry after a timeout is safe, but after a saved 5xx the same key just replays the error: check the refund's status at Stripe instead of resending.
A fixed version (ours). Tested against the fakes: every attempt failing, success on a later retry, a lost reply, every reply lost, two concurrent calls, an invalid request, a charge already refunded, an unexpected exception, retrying a failed refund, a repeat call and a missing record.
import asyncio
import logging
import random
log = logging.getLogger("refunds")
class RetryableError(Exception): # timeout, 5xx, rate limit: may succeed later
pass
class PermanentError(Exception): # invalid request: retrying won't help
pass
class AlreadyRefundedError(Exception): # the provider says this charge is already refunded
pass
async def refund_money(request_id: str, max_attempts: int = 3) -> str:
refund = await get_db_record(request_id)
if refund is None:
raise KeyError(f"no refund record for {request_id}")
if refund.status == "done":
return "done"
# Claim the work with an atomic update (pending or failed -> processing), so a
# second concurrent call does not also send a refund. A worker that dies here
# leaves the claim behind, so the claim needs a lease or a reconciler.
if not await claim_for_processing(request_id):
return "in_progress"
try:
for attempt in range(max_attempts):
try:
await stripe_api_call(
refund.request_id,
refund.amount,
idempotency_key=f"refund-{request_id}", # same key on every retry
)
await mark_db_as_done(request_id)
return "done"
except AlreadyRefundedError:
await mark_db_as_done(request_id)
return "done"
except PermanentError:
log.warning("refund %s rejected", request_id, exc_info=True)
await mark_db_as_failed(request_id)
return "failed"
except RetryableError:
log.info("refund %s attempt %d failed", request_id, attempt + 1, exc_info=True)
if attempt < max_attempts - 1:
await asyncio.sleep(min(2 ** attempt, 30) * random.uniform(0.5, 1.0))
# Every attempt timed out: Stripe may or may not have refunded. Don't guess;
# flag it so a reconciler checks the refund at Stripe before retrying or failing it.
await mark_db_as_needs_check(request_id)
return "unknown"
except BaseException:
await mark_db_as_needs_check(request_id) # never leave the claim stuck in processing
raise
When every attempt times out, the refund may or may not have gone through, so the record is flagged for a reconciler to check at Stripe rather than marked failed.
2. Rapid-fire questions (word for word from the report), each with a short answer (ours):
3. Ownership (word for word, listed with the rapid-fire questions):
Our advice: pick a project where you set the goal, made the trade-offs, unblocked others and answered for the result, and say which decisions were yours, with a number for the outcome.