AI coordination became opaque when vendors, prices, and exceptions changed asynchronously.
When the agent
gets stuck, who takes over?
I designed and built a multi-sided AI concierge that could coordinate 20+ vendors at once—while keeping consequential states traceable and humans in control.

Product design, interaction model, frontend, and HITL operator surfaces.
Expose operational states and make human takeover deliberate and reversible.
Four connected customer, vendor, admin, and operator experiences.
A four-step booking flow with explicit escalation and recovery paths.
01 / The system
A concierge is easy—until it touches the real world.
A customer can ask for a tow in one sentence. Behind that sentence sit changing availability, parallel vendor calls, pricing, location, payment, and exceptions. The product had to feel calm to the customer without hiding the operational uncertainty underneath.
02 / Customer journey
Operational progress needs explicit states.
The customer experience translated the agent’s asynchronous work into understandable decisions: what was happening, which vendors responded, why an option was recommended, and what would happen next.
Visible stages
Replace indefinite loading with specific operational progress.
Comparable options
Present trade-offs in price, rating, distance, and arrival time.
One status language
Keep booking states consistent across customer and operator views.




03 / AI safety
Human takeover is a designed product state.
The operator surface prioritized calls by urgency and made escalation reasons explicit: a time threshold was exceeded, the agent reached its capability limit, or the vendor requested a human. Operators could inspect the full context before acting.
Hold for 1.5 seconds to take over.
A consequential action should not happen through an accidental tap. The circular progress state makes the commitment visible, remains cancellable on release, and confirms when the operator is live.
04 / Design engineering
The takeover control runs in production code.
The React and TypeScript implementation connects a visible progress ring to a cancellable hold gesture. Mouse and touch paths share the same state model, active operators receive a confirmed state, and the control exposes an accessible name.
const startHold = useCallback(() => {
if (isActive) return
setIsHolding(true)
animate(progress, 1, {
duration: 1.5,
ease: 'linear',
onComplete: () => {
setIsHolding(false)
onTakeOver()
},
})
}, [isActive, progress, onTakeOver])
const cancelHold = useCallback(() => {
if (isActive) return
setIsHolding(false)
animate(progress, 0, { duration: 0.3 })
}, [isActive, progress])
Validated onboarding
Authenticated routes validate required fields, conditional phone and insurance data, and return explicit error codes.
Transactional writes
Identity, vendor configuration, compliance documents, and onboarding progress update inside a database transaction.
Failures stay actionable
Loading, permission, validation, empty, escalation, and completion states are represented in the interface.
Semantics included
Tab roles, alerts, input labels, focus states, reduced-motion handling, and control names are present in the implementation.
05 / Outcome
From open-ended request to a clear four-step booking flow.
The final experience made parallel agent work understandable to customers and actionable to operators. It reduced the booking journey to four steps while preserving intervention, verification, and recovery paths for the moments automation could not safely resolve alone.
What I would test next: operator response time by escalation reason, false-positive escalation rate, takeover completion and cancellation rates, and whether customers understand when control moves from agent to human.
Next case study
Claussal.aiEvery answer, traceable.