Skip to main content

Challenge and Resume

When a SDK handler needs user input mid-flight (OTP, MFA, confirmation code), your customer.authorize() returns a challenge. Qefro suspends execution until the user replies, then sends tool.resume.

Flow

Authorize outcomes

kindMeaningQefro action
successCustomer authorizedRun handler
challengeNeed user inputShow message; wait for resume
deniedAuth failedUser-safe error
not_foundUnknown customerUser-safe error

Challenge payload

{
"type": "challenge",
"resume_token": "uuid",
"challenge": {
"type": "email_otp",
"message": "Enter the 6-digit code sent to your email.",
"destination_hint": "a***@example.com"
}
}

tool.resume

Qefro sends the user's next message as challenge_response (or structured field per protocol):

{
"type": "tool.resume",
"tool": "my_orders_list",
"resume_token": "uuid",
"challenge_response": "123456",
"conversation_id": "...",
"identity": { "email": "[email protected]" }
}

Your authorize function receives ctx.response on resume.

Channels

Challenge/resume works on:

  • Website Widget
  • WhatsApp (user reply becomes resume)
  • Admin Playground / Test Chat

Best practices

  • Keep OTP messages short — the LLM may paraphrase your message.
  • Use destination_hint masked (never full secrets).
  • Idempotent resume — duplicate OTP attempts should return denied, not throw.
  • Expire resume tokens quickly in production (framework stores in-memory in dev).