Skip to main content
Robust phone-agent integrations are not the ones that never fail - they are the ones that classify every failure correctly and know the recovery move. There are three error layers and nine terminal outcomes; this page gives the move for each.

Know which layer you’re in

The task-level error object (holding error.control_type and error.prompt) is part of the task status payload - distinct from the JSON-RPC envelope.

A move for every terminal

Retry discipline

  • Retry the task, not blindly. timeout, agent_error, and device_offline are worth one retry after addressing the cause. Retrying iteration_limit without splitting, or queue_wait_exceeded without checking the device, just repeats the failure.
  • Never construct task IDs. Use exactly what phone_run_task returned; after a handoff, monitor the continuation_task_id, not the original. task_not_found usually means an expired or wrong-session ID - start a replacement task.
  • Cancellation races are benign. A cancel that arrives after completion returns already_completed: true; act on the task’s real terminal.
  • Repeating the same answer to a needs_user_control task is safe; sending a different second answer is rejected.

Design failure into the workflow

  • Split workflows into per-errand tasks so a failure only costs one step - see Task design.
  • Ask prompts to report “not found” explicitly, so an empty result is never ambiguous.
  • Treat monitor_timed_out: true as keep waiting, never as failure.

Task lifecycle

Where each terminal comes from

Troubleshooting

Symptom-based debugging