NVIDIANVIDIA-Certified Professional: Agentic AI2026-101.6 Apply logic trees, prompt chains, and stateful orchestration for multi-step reasoning.
Bound adaptive work inside explicit state graphs
Completed by the knowledge check
Learning objective
Model workflows as state graphs and choose predetermined versus adaptive control
Core idea
A state graph makes three things explicit: the information describing execution, the operations that update it, and the transitions that select what runs next. The presence of an LLM does not determine whether control is adaptive. The deciding question is whether code fixes the path or the model selects actions from observations.
Use predetermined control for known dependencies and adaptive control where the next useful operation cannot be selected beforehand. Keep both inside an execution model with defined state updates and terminal outcomes. Checkpoint persistence and safe resumption belong to 5.4.2; here the decision is the graph those checkpoints would preserve.
How it works
Separate state, work, and transitions
In Python LangGraph, StateGraph(State) defines a graph over a state schema. Nodes perform operations and return state updates. add_edge() defines fixed transitions, while add_conditional_edges() uses a routing function to select destinations from state. START and END identify entry and completion boundaries. Call compile() before invoking the graph; compilation performs basic structural checks, including checks for orphaned nodes.
Define state according to the decisions nodes must make. A research assistant might need the question, retrieved findings, unresolved questions, a draft, and an iteration counter. These are application-defined fields, not built-in LangGraph names. Keep a result separate from the field describing whether more work is required. Otherwise, the presence of a fluent draft can be mistaken for successful completion.
LangGraph accepts TypedDict schemas and also supports Pydantic BaseModel state for recursive data validation. The documentation notes a performance cost for Pydantic compared with TypedDict or dataclasses. Select validation where it protects a meaningful boundary; do not treat a Python type declaration alone as proof that a model-generated update has passed runtime checks. See 1.6.1 for typed intermediate results.
A graph state is an execution representation. It is not automatically the same thing as the prompt the model reads or the retained knowledge a later task should retrieve. Pass each node the fields it needs and construct model inputs deliberately. See 5.4.1 for the distinction between execution state, conversation memory, and retained task knowledge.
Choose how updates combine
Each state key has a reducer that determines how updates become the next state. Without an explicit reducer, an update replaces that key’s value. Nodes can return partial updates rather than reconstruct the whole state.
Use replacement for fields such as the selected route or accepted draft when only one value should govern the next step. Use an accumulating reducer when the state should preserve multiple findings. LangGraph documents Annotated[list, operator.add] as a list-accumulation pattern. The reducer expresses an execution decision: returning another list appends it instead of replacing the existing list.
That choice also determines failure modes. An accumulating list can retain stale findings after a revision, and returning an empty list does not clear a merging reducer’s existing content. LangGraph’s Overwrite type bypasses the reducer when explicit replacement is required. Prefer a field whose update semantics match its purpose rather than compensating for the wrong reducer in every prompt.
Through the reducer, an update replaces a key’s value or appends to it, unless Overwrite bypasses the reducer.
Locate the adaptive decision
LangChain distinguishes workflows with predetermined code paths from agents that dynamically determine their processes and tool use. A conditional edge can still be predetermined control: code checking whether all required fields exist is a fixed rule even when its input came from a model. Conversely, an agent node that chooses its next tool from observations introduces adaptive behavior inside an otherwise fixed graph.
Compare control choices at the boundary where they differ:
| Control | Deciding condition | Mechanism | Cost or failure mode |
|---|---|---|---|
| Fixed sequence | Every task has the same dependencies | NeMo sequential_executor and tool_list | Serial latency; no dynamic branch selection |
| Predetermined branching | Known predicates determine the path | add_conditional_edges() with code predicates | Rules must cover incomplete and exceptional state |
| Adaptive loop | Observations determine the next useful action | Model/tool node cycle with conditional termination | Variable tokens, latency, and repeated work |
| Hybrid graph | Most work is fixed, but one region needs exploration | Fixed outer edges around a bounded adaptive subflow | Both outer invariants and inner stopping rules need owners |
The branch classifier in 1.6.2 selects a handler. A state graph additionally specifies what information survives that choice, how results update it, and whether execution returns for another decision. Do not infer the latter behaviors merely from a router’s presence.
Define termination before adding a loop
An adaptive loop needs an accepted outcome and an exhaustion outcome. For example, a code predicate can route to END after all required source checks pass, or to an application-defined incomplete-result node after the iteration allowance is consumed. Increasing the allowance does not repair an acceptance predicate that can never become true.
LangGraph’s recursion_limit limits graph super-steps, not elapsed seconds or total tool calls. Parallel nodes can occupy the same super-step. Starting in LangGraph 1.0.6, the default limit is 1,000 super-steps; a runtime override belongs in the config dictionary passed to invoke or stream. Exceeding the limit raises GraphRecursionError. Use it as a backstop, and use the RemainingSteps managed value when the graph needs to take a completion path before exhausting that backstop. The task’s business counter and the graph’s execution limit answer different questions.
Avoid mixing competing transition mechanisms. LangGraph’s Command can update state and select a destination with goto, but its dynamic edges do not cancel static edges already defined on the same node. Defining both can run both destinations. Use one routing approach per node so an apparently exclusive completion path does not also launch another work step.
Connect the graph to NVIDIA execution
NVIDIA NeMo Agent Toolkit documents workflow._type: langgraph_wrapper for existing LangGraph agents. Its required graph parameter identifies the graph in module_path:variable_name form. Optional dependencies adds directories to the Python path, and env supplies an environment file or dictionary. The integration’s prerequisite package is nvidia-nat-langchain.
The wrapper adds the toolkit’s configuration, observability, and evaluation integration around the graph. For configurable components, NVIDIA documents replacing hardcoded component initialization with retrieval through the NeMo Agent Toolkit builder. Wrapping a graph does not make its control choices predetermined; those choices remain in its nodes and transitions.
Architecture / decision scenario
A manufacturing firm’s research assistant compares supplier qualification documents. The delivery team has a 45-second per-request budget. A measured fixed extraction-and-draft path takes 15 seconds, while one additional search-and-review round takes 8 seconds. The procurement engineering owner must choose a fixed three-search sequence, an unrestricted agent, or fixed intake and output stages surrounding bounded exploration.
Two thirds of trial requests need one search; one third need three. Always running three spends two unnecessary searches on most requests. An unrestricted loop can exceed the deadline. The owner chooses the hybrid graph: intake establishes the required supplier fields, a research node updates findings, and a conditional edge checks unresolved fields and an application-defined three-round allowance.
At three rounds, the modeled path consumes 39 seconds, leaving 6 seconds within the budget. This is a planning estimate, not a graph-enforced deadline. The acceptance predicate routes complete findings to drafting; exhaustion routes missing fields to an explicit incomplete result. Findings accumulate with a reducer, while each accepted draft replaces its predecessor. The team exposes this graph through langgraph_wrapper, using LangGraph 1.0.6 or later without a runtime override. The 1,000-super-step default remains a backstop for runaway graph execution, and RemainingSteps counts against that limit. The application-owned three-round predicate stops normal research work much earlier. The team records complete versus exhausted outcomes separately before tuning the exploration allowance.
Common exam traps
- Calling any graph containing an LLM adaptive.
- Assuming
TypedDictalone provides runtime validation. - Returning an empty list to clear a field with an accumulating reducer.
- Treating
recursion_limitas a wall-clock or tool-call limit. - Combining
Command(goto=...)and a static edge while expecting exclusive routing. - Assuming a wrapper supplies missing acceptance or exhaustion conditions.
What to remember
Model state, updates, transitions, and termination separately. Predetermined control fixes the path or predicates; adaptive control delegates action selection from observations. Keep exploration bounded, choose reducers intentionally, and distinguish business completion from graph exhaustion.
Knowledge check
A LangGraph state declares open_issues: Annotated[list, operator.add]. After a revision resolves every issue, the review node returns {"open_issues": []}, yet the graph keeps routing to another research round because the old issues are still in state. Which update clears the field while keeping the reducer for other nodes?
{"open_issues": None} from the review node{"open_issues": Overwrite([])} from the review nodeopen_issues from the review node’s updateopen_issues set to [] from reviewOverwrite bypasses the reducer for that one update. Omitting the key leaves the value as it is, and returning the whole state still sends open_issues through the same reducer.A research assistant’s requests usually need one search round and sometimes three. Whether another round is needed shows only after reviewing the previous round’s results, and the per-request budget fits three rounds but not an open-ended loop. The team also wants to avoid unnecessary search rounds. Which control design fits these constraints?
A claims graph has an LLM extraction node followed by a conditional edge whose code checks whether all required fields are present and routes to drafting or to manual review. A reviewer calls the workflow adaptive because a model runs in it. Which addition would actually make part of its control adaptive?
BaseModel state schema for the extracted fieldsA supplier-research graph loops between research and review until a code predicate finds every required field. For suppliers that never publish one required field, the loop runs until LangGraph raises GraphRecursionError. Which change gives those requests a defined outcome?
recursion_limit in the config passed to invokelanggraph_wrapper workflowrecursion_limit counts super-steps and is a backstop, so raising it only delays the same error; the wrapper adds configuration, observability, and evaluation without supplying missing stop conditions, and a model judging completeness changes who accepts without adding an exit for requests that can never pass.References
- LangChain, Graph API overview
- LangChain, Workflows and agents
- NVIDIA, Running Existing LangGraph Agents in NVIDIA NeMo Agent Toolkit
- NVIDIA, Configure With the Sequential Executor