Skip to lesson

NVIDIANVIDIA-Certified Professional: Agentic AI2026-1010.1 Build intuitive UIs with user-in-the-loop interaction.

Keep review in session or park it as a task

Completed by the knowledge check

Learning objective

Choose synchronous versus asynchronous user-in-the-loop interactions.

Core idea

Choose synchronous interaction when the person can make the decision within the active session’s time budget. Choose asynchronous interaction when the task must wait independently of that session and the person needs to return later. The distinction is who waits for whom, not whether the Python function uses async def.

See 1.1.1 for task-inbox surfaces and 10.1.1 for review controls. Here, decide how long the waiting task must survive. See 5.4.2 for checkpoint implementation and replay-safe side effects.

How it works

Bound the live interaction

NeMo Agent Toolkit’s UserInteractionManager pauses a workflow through await user_input_manager.prompt_user_input(prompt). The function processes the returned response before proceeding. This supports a live clarification or review exchange, even though its implementation is an asynchronous Python call.

For the Toolkit’s supplied frontend, enable WebSocket mode. The server sends system_interaction_message, and the client answers with user_interaction_message. A bidirectional connection carries the exchange; it does not decide whether the business task survives a later process restart.

The WebSocket schema gives each prompt an optional timeout, expressed in seconds. Its default is null, meaning no timeout. A configured timeout makes the frontend show a countdown and dismiss an expired prompt; server enforcement raises TimeoutError to the workflow. Set the value from the remaining session budget rather than assuming the person can always respond in time.

For example, if a hypothetical application allows 60 seconds end to end, spends 8 seconds preparing a proposal, and reserves 12 seconds for execution and response, at most 40 seconds remain for synchronous review. These are application budgets, not Toolkit limits. A 5-minute human response cannot satisfy that design merely by enabling streaming or increasing model throughput.

Match waiting to the required lifetime

Toolkit HTTP Interactive Execution carries human prompts without an open WebSocket. In polling mode, an interaction returns 202 Accepted with status: "interaction_required", status_url containing the execution ID, interaction_id, prompt, and response_url. A client can disconnect and later poll GET /executions/{execution_id} or post its answer to POST /executions/{execution_id}/interactions/{interaction_id}/response while the execution waits on the server. See 2.5.2–2.5.3 for client recovery and resolved-interaction handling.

Interactive extensions are enabled by default on /v1/workflow and /v1/chat. For /v1/chat/completions, enable general.front_end.enable_interactive_extensions: true; its default is false. This path transports the same interactive prompts, but the HTTP Interactive Execution reference documents no persistence of a pending execution across a server restart or redeploy.

When review must survive a server restart, use a durable waiting task. LangGraph’s interrupt() surfaces a JSON-serializable payload to the caller while a checkpointer saves graph state. Production use requires a durable checkpointer and a stable configurable.thread_id. The graph waits until it receives a resume response.

With the default invoke() API, pending interrupts appear in result["__interrupt__"]. A service can turn that payload into a review task and later invoke the graph with Command(resume=...) using the same thread ID. The resume value becomes the return value of interrupt(). This is a framework-level mechanism; the application’s task inbox, notification delivery, authorization, and review deadline remain separate service responsibilities.

NeMo Agent Toolkit integrates existing LangGraph agents through workflow._type: langgraph_wrapper and a graph value in module_path:variable_name form. It requires nvidia-nat-langchain. The documented graph is a CompiledStateGraph or a callable returning one from RunnableConfig; complex state management can require additional configuration or code changes. Keep the framework resume service explicit in your design instead of assuming that importing a graph automatically exposes an inbox or a Command-accepting public route.

An application-owned review record can carry task_id, thread_id, proposal_revision, review_status, and review_deadline. Retrieve that pending proposal before accepting a decision.

Give the wait a business outcome

LangGraph’s documented interrupt wait is indefinite. That is a persistence behavior, not a business policy for how long approval remains valid. Define a deadline in the review task and have the response service check it before issuing Command(resume=...). If the proposal has expired, show the expired outcome and regenerate or close it according to the workflow’s decision rule.

A notification tells the person that work is waiting; it is not the authoritative proposal. When the person opens it, load the pending task and its revision. If another response has already resolved it, display that outcome rather than offering a second actionable form. The review service owns that acceptance check, while the graph owns continuation.

The review service owns the acceptance check, while the graph owns continuationThe graph surfaces an interrupt payload to the review service while a checkpointer saves graph state. The service turns the payload into a review task and notifies the person that work is waiting. When the person opens the notification, the service loads the pending task, and a task another response has already resolved only displays that outcome. For a pending task, the person's decision arrives and the service checks the deadline. An expired proposal gets the expired outcome, and only an unexpired one resumes the graph with Command(resume=...).PersonReview serviceGraphcheckpointer saves statereview taskload the pending taskcheck the deadlinealt[proposal has expired]alt[already resolved][pending task]payloadwork is waitingopens notificationdisplay that outcomedecisionexpired outcomeCommand(resume=...)

Resume also restarts the interrupted node from its beginning. Keep that fact in mind when placing the review step, and use the replay-safe design in 5.4.2 for external writes. A durable review task can outlive the browser without making every operation around it safe to repeat.

Key distinctions and trade-offs

Compare the interaction choices against the human wait:

ChoiceRequired lifetimeMechanismMain costOwner
Synchronous reviewThe active sessionToolkit prompt_user_input over WebSocket or HTTP with a bounded timeoutSession occupancy and timeout riskInteractive workflow team
Asynchronous review on the running serverClient disconnect and returnToolkit HTTP polling with execution_id and interaction_idStatus retrieval, expiry, and response coordinationHTTP client and workflow teams
Durable asynchronous reviewServer restart or redeployLangGraph interrupt(), durable checkpointer, stable thread_id, and Command(resume=...)Persistent storage and a review serviceWorkflow and review-service teams

Transport and interaction are different dimensions. HTTP polling lets a person return without keeping a connection open; durable checkpoints address server restarts. Setting timeout: null only removes the prompt deadline.

Asynchronous review adds a return journey and potentially stale proposals. Measure completion time as well as acknowledgment; fast acceptance can hide review backlog.

Architecture / decision scenario

A publishing company’s research assistant prepares campaign briefs. In this hypothetical service, source retrieval and drafting take 8 seconds. An editor’s short clarification takes a median of 10 seconds, while brand review takes a median of 20 minutes. The interactive application has a 60-second completion budget and reserves 12 seconds after the decision to validate and deliver the brief.

One proposal keeps every decision inside the WebSocket conversation with no prompt timeout. That avoids a review-service implementation, but the 20-minute brand review exceeds the 40-second remaining synchronous allowance. Closing the browser would also leave the editor without a durable review-task return path in that design.

The product owner chooses a mixed workflow. Short clarifications use prompt_user_input with an application-selected 40-second timeout. An unanswered clarification produces an expired interaction and an option to restart it. For brand review, the team assumes the 4-hour review window spans a server redeploy. It therefore chooses a durable graph interrupt and stable thread ID behind the task inbox rather than relying on HTTP polling alone.

The review service stores an application-selected 4-hour deadline and proposal revision. When brand review finishes, it verifies that the task is still pending and unexpired, then resumes the graph with Command(resume=...). An expired brief returns for refreshed source checks rather than publishing from a stale approval. The team measures clarification timeouts separately from review age, so it can distinguish a poor live interaction from an understaffed review queue.

Common exam traps

  • Assuming Toolkit human-in-the-loop interaction requires an open WebSocket.
  • Calling an interaction asynchronous solely because it uses await.
  • Equating streamed progress with durable background execution.
  • Holding a live interaction open for a reviewer whose response exceeds the session budget.
  • Treating timeout: null as persistent task storage.
  • Resuming with a different configurable.thread_id and expecting the pending checkpoint.
  • Assuming a graph wrapper creates the review service, notification channel, and business expiry policy.

Where the exam guide differs

Note:

The study guide lists “NVIDIA Agent Intelligence Toolkit” among its suggested readings. NVIDIA documents the integration as NeMo Agent Toolkit’s langgraph_wrapper. For the guide’s “user-in-the-loop” objective, Toolkit prompts support WebSocket or HTTP polling. A durable checkpoint is a separate framework-level choice when the required waiting lifetime spans server restarts.

What to remember

Fit synchronous review inside the remaining session budget. Use HTTP polling for client return and durable checkpoints for restart survival. Give the task an identity, an expiry rule, and a controlled resume path. Measure human wait separately from model execution; faster inference cannot remove review backlog.

Knowledge check

References