NVIDIANVIDIA-Certified Professional: Agentic AI2026-102.5 Develop dynamic conversation flows with real-time streaming and feedback mechanisms.
Recover dialog turns from execution state
Completed by the knowledge check
Learning objective
Manage multi-turn dialog state, interruptions, reconnections, and state recovery.
Core idea
A multi-turn conversation has at least three lifecycles: the conversation, the workflow execution answering a turn, and the connection displaying it. A connection can disappear while work continues. A user can correct a turn while an earlier response is still arriving. Recover by locating the execution and its saved state before deciding what to repeat.
See 1.4.1 for memory-store roles and 1.8.3 for shared state across replicas. This lesson adds the dialog decisions: which turn owns output, how interruption changes the active execution, and what the client does after losing contact.
How it works
Keep the identifiers separate
A WebSocket user_message carries the dialog in content.messages: user and assistant messages followed by the next user message. The schema says the running workflow processes only the last user message. In this integration, the client retains and resends the transcript each turn; conversation_id groups messages and parent_id associates updates with their originating message.
Interactive HTTP exposes an execution identity when the workflow pauses for human input or OAuth. Store that execution_id and, for a 202 response, the returned status_url; typed SSE pause events carry the ID but not status_url. An ordinary stream that drops before any pause has no documented execution ID to query. The API reference marks versioned HTTP paths experimental because of HITL and OAuth support.
For a LangGraph workflow, configurable.thread_id selects the checkpointed thread. LangGraph checkpointers persist graph state at super-step boundaries and support conversation continuity. An application’s association between this thread and the toolkit’s conversation or execution IDs is integration logic; create it explicitly rather than assuming similarly named identifiers are interchangeable.
NVIDIA documents integration through workflow._type: langgraph_wrapper and the graph configuration field, with the nvidia-nat-langchain package. That wrapper brings an existing graph into the toolkit. Choose and configure the graph’s persistence and dialog behavior as part of that integration; the wrapper’s configuration is not itself a checkpoint policy.
Advance a turn from committed state
The Checkpointers page describes sending conversational follow-up messages as ordinary input to the same thread. The Interrupts page reserves Command(resume=...) for answering a pending interrupt(). Select the input operation according to whether this is another turn or the response to a suspended one.
Inspect saved state with graph.get_state(config) when rebuilding the display. A StateSnapshot contains saved values and execution information. Render committed history from that state and keep any partially displayed answer labelled incomplete until the execution outcome is reconciled. A user’s copied transcript can help explain their intent, but it cannot establish which graph step completed.
Checkpoint retention and context selection remain the memory owner’s responsibility; see 1.4.2. Here the essential property is stable thread selection. Replacing thread_id during reconnect creates a different thread instead of locating the saved one. Using an in-memory saver also cannot satisfy recovery across a process restart; choose a durable checkpointer for that requirement.
Treat interruptions as explicit control changes
A planned pause uses LangGraph interrupt() and persists state through a checkpointer. Resume it with Command(resume=...) and the same thread ID. The interrupted node restarts from its beginning, so statements before the interrupt execute again. Keep a non-repeatable tool write out of that replayed prefix, or use the tool’s own duplicate-prevention mechanism. A pause is not a rollback of actions already performed.
A user pressing Stop is a different event from a planned prompt. In an application-owned Python execution task, asyncio.Task.cancel() requests cancellation; CancelledError is raised at the next opportunity. Use try/finally for cleanup and generally propagate CancelledError after cleanup. These are Python task semantics, not an assertion that a toolkit HTTP connection automatically cancels every downstream operation.
While cancellation is being resolved, retain the previous turn’s identity and reject its output from the replacement turn’s answer buffer. If a remote action has already completed, cancellation cannot make it un-happen. The workflow owner must reconcile that result before accepting a replacement action. See 1.5.2 for the broader specialist execution lifecycle.
Reconnect by querying, then decide
After a pause has exposed an interactive execution ID, query GET /executions/{execution_id}. Its lifecycle distinguishes running, interaction_required, oauth_required, completed, and failed. Rebuild the client around that status rather than resubmitting the original request.
If interaction is required, display the pending prompt and submit to its response_url. A response accepted with 204 returns the execution to running. A 400 indicates an interaction already resolved; a 404 means the execution or interaction was not found. Refresh status instead of repeatedly submitting a stale response. These routes require a locatable interactive execution, not merely a conversation ID.
For a token stream lost before any pause, reconcile the durable LangGraph thread through your integration. GET /executions/{execution_id} is unavailable without an ID. Inspect the saved graph position and any unresolved external action before starting replacement work, including after a process restart.
If reconnectable job identity matters more than token streaming, submit the turn through /v1/workflow/async with a client-chosen job_id. Repeating that submission with an existing ID returns the job’s status. This endpoint is non-streaming, requires nvidia-nat[async_endpoints], and defaults sync_timeout to 0, returning immediately. See 1.8.3 for Dask and persistent --db_url deployment; here the deciding trade-off is known job identity versus live token delivery.
Key distinctions and trade-offs
Choose the recovery mechanism by what was interrupted:
| Situation | Mechanism | Trade-off |
|---|---|---|
| Another WebSocket turn | Client-held history resent in content.messages | Restores dialog context, not graph execution position |
| Connection lost after an HTTP pause | Retained execution_id and status GET | Requires a pause that exposed the ID and a locatable execution |
| Stream lost before a pause | Durable graph thread reconciliation | Keeps token streaming but requires a recovery integration |
| Reconnectable background turn | /v1/workflow/async with a client-chosen job_id | Gives queryable job identity while giving up token streaming |
| Planned human pause | interrupt() and Command(resume=...) on the same thread | The interrupted node’s prefix runs again |
| User stops active work | Application task cancellation and outcome reconciliation | External effects need separate accounting |
| Process restart | Durable checkpointer and configurable.thread_id | Adds persistence operations and retention ownership |
A transcript restores conversational context. A checkpoint restores graph state. Neither should be mistaken for proof that a remote tool action was rolled back.
Architecture / decision scenario
A manufacturing procurement assistant lets buyers refine a supplier search over several turns. The business requires recovery after a service restart and allows at most one supplier-contact request for each buyer decision. In a test, the connection drops after a tool has recorded a contact request but before the final 120-word answer finishes.
A developer proposes reconnecting and replaying the complete transcript into a fresh thread. The workflow owner rejects that design: it can repeat the contact action and loses the recorded graph position. Because this stream had not paused, no interactive execution ID was returned. The integration retains the conversation-to-thread association and inspects the durable graph state and the tool’s recorded result before continuing, after either network loss or restart. Switching to /v1/workflow/async with a chosen job_id would give a different reconnect path, but the team keeps streaming and owns graph-based reconciliation.
The buyer then interrupts to change the delivery date. The application requests cancellation of active local work and keeps late output attached to the superseded turn. A planned clarification later uses interrupt() and resumes on the same thread. The team places the supplier-contact write outside the interrupted node’s replayed prefix. The owning team tests both a 3-second network loss and a process restart; those failures exercise different mechanisms despite producing a similar frozen chat screen.
Common exam traps
- Replacing the thread ID when reconnecting to an existing conversation.
- Treating a transcript as an execution checkpoint.
- Using
Command(resume=...)for every ordinary follow-up message. - Assuming code before
interrupt()runs only once. - Treating cancellation as immediate or as rollback of remote writes.
- Assuming every interrupted token stream supplies an interactive execution ID.
What to remember
Preserve conversation, turn, execution, and checkpoint identities separately. Reconcile execution status after connection loss, use durable checkpoints for restart recovery, and distinguish planned pauses from cancellation. Recovery is complete only when the display and workflow agree about which turn owns the outcome.
Knowledge check
A procurement assistant runs a LangGraph workflow with a durable checkpointer and streams each turn over HTTP. A connection drops after a supplier-contact tool has recorded a request but before the answer finishes; the run had not paused for input. The business allows at most one contact request per buyer decision. What should the integration do on reconnect?
GET /executions/{execution_id} for the interrupted streamA support workflow compiles its LangGraph graph with InMemorySaver and passes a stable configurable.thread_id on every turn. A new requirement says a conversation must continue from its saved graph position, including a pending interrupt, after the service process restarts. What change meets it?
thread_id after every restartlanggraph_wrapper in the toolkitA graph node creates a purchase order in an external system and then calls interrupt() to ask the buyer to approve the shipping method. After each Command(resume=...) on the same thread, the external system shows a second purchase order. Which change removes the duplicate?
Command(resume=...) on a new thread IDgraph.get_state(config) before every resumeinterrupt() runs again; a non-repeatable write belongs outside that prefix, or behind the tool’s own duplicate prevention. A new thread cannot find the pending interrupt, and reading state shows the position without changing what the node replays.A LangGraph conversation finished its last turn with no interrupt pending, and the user types a new question in the same chat. How should the application send it?
Command(resume=...) carrying the questionthread_idCommand(resume=...) answers a pending interrupt() ; another turn is ordinary input to the same thread, which already holds the conversation’s checkpointed state. Starting a new thread throws that state away and rebuilds only what the transcript happens to carry.A browser client receives interaction_required over HTTP SSE and stores its execution_id. The server accepts the user’s answer with 204, and the tab reloads before resumed output arrives. What should the client do first after the reload?
response_urlGET /executions/{execution_id} and render its statusconversation_id valuerunning , waiting for another interaction, completed or failed , and the status lookup says which. Resubmitting can run the work again, and re-posting the accepted response returns 400 because that interaction is resolved.References
- NVIDIA, NVIDIA NeMo Agent Toolkit API Server Endpoints
- NVIDIA, WebSocket Message Schema
- NVIDIA, HTTP Interactive Execution
- NVIDIA, Running Existing LangGraph Agents in NVIDIA NeMo Agent Toolkit
- LangChain, Checkpointers
- LangChain, Interrupts
- Python Software Foundation, Coroutines and Tasks