Skip to main content
Let a user approve the research plan, clarify scope or choose which sources to include before the task continues. These optional checkpoints are configured through hitl (human-in-the-loop). Enable only the decisions your user needs to make; an ordinary research task needs none.
HITL is for individual tasks only. It is not available for batch requests.

Checkpoints

Each pause sets the task status to awaiting_input. If you don’t respond within 5 minutes it becomes paused (state saved) - you can still respond later to resume; the task re-enqueues at highest priority with a brief cold-start delay. If you resume more than 24 hours after the pause, the task needs enough available balance for its mode price when it restarts; otherwise it fails with an Insufficient credits - ... error and is not charged.

Quick start

Pass an on_interaction callback to wait() to handle checkpoints. The example below shows the response shapes and automatically approves reviews. For human review, display the checkpoint in your application and submit the user’s decision through the respond endpoint.
Both SDKs also ship type-safe helpers: respond_planning_questions() / respondPlanningQuestions(), approve_plan() / approvePlan(), respond_source_review() / respondSourceReview(), and approve_outline() / approveOutline(). See the Python and TypeScript SDK references.

Where checkpoints fire

Query analysis

The agent analyzes the query.

planning_questions

Pause: clarifying questions before research starts. You answer to set scope.

plan_review

Pause: review the research plan. Approve or request changes.

Research execution

The agent searches and reads sources.

source_review

Pause: review sources grouped by domain. Include or exclude domains.

outline_review

Pause: review the report outline. Approve or request structural changes.

Report writing

The agent writes the final report and the task completes.

Checkpoint response shapes

When status is awaiting_input, status.interaction.data holds the checkpoint payload and you reply with a matching response.
The agent asks questions; you answer them.
answers is required: an array of { question, answer } strings.
Both share the same response shape - approve, or reject with free-text guidance.
approved (boolean) is required; modifications (string) is optional free-text guidance for the model. interaction.data contains the plan / outline and section breakdown for you to display.
interaction.data lists sources grouped by domain with a source_count, avg_relevance_score, and an ai_recommendation of include or exclude. You reply with explicit include/exclude lists.
Both arrays are required but may be empty. Domains you don’t list fall back to the AI recommendation.

Manual polling and the respond endpoint

If you poll yourself instead of using wait(), watch for awaiting_input (or paused), then POST your response:
When HITL is enabled, the status response also carries hitl_config (mirrors the request), interaction (present while awaiting_input/paused), and hitl_history (one entry per completed checkpoint with interaction_id, type, created_at, responded_at, auto_continued, and response).

Best practices

  • Poll faster around checkpoints - 2-3s when expecting input, 5-10s during research phases.
  • Handle both awaiting_input and paused - the UX is identical, only resume speed differs.
  • Enable selectively - each checkpoint adds latency equal to the user’s response time.
  • Review decisions that matter - enable checkpoints where user input can change scope, sources or report structure. Choose the research mode separately.

Next steps

Use the application guide to persist task IDs and display waiting states. For every request and response field, see the Python or TypeScript reference.