feat: add LangGraph example workflows - #183
Conversation
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Enterprise Run ID: 📒 Files selected for processing (10)
WalkthroughAdded shared configuration and two native LangGraph workflows. The calculator workflow uses per-user MCP-backed state. The phishing analyzer returns structured JSON. Added a local MCP math server, offline tests, CLI entry points, and documentation. ChangesLangGraph proof-of-concept workflows
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant CLI
participant PerUserReactAgent
participant MCPMathServer
participant LangGraph
CLI->>PerUserReactAgent: submit user ID and message
PerUserReactAgent->>MCPMathServer: create isolated MCP connection
PerUserReactAgent->>LangGraph: invoke user-specific graph
LangGraph-->>PerUserReactAgent: return graph state
PerUserReactAgent-->>CLI: print final message content
sequenceDiagram
participant CLI
participant EmailPhishingGraph
participant StructuredChatModel
participant PhishingAssessment
CLI->>EmailPhishingGraph: submit email body
EmailPhishingGraph->>StructuredChatModel: request structured assessment
StructuredChatModel->>PhishingAssessment: validate assessment
PhishingAssessment-->>EmailPhishingGraph: serialize assessment
EmailPhishingGraph-->>CLI: print JSON
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 7
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@examples/langgraph/calculator_mcp.py`:
- Around line 76-99: Update graph_for to serialize first-time graph creation per
user using a per-user initialization task or lock, then recheck _sessions before
constructing the MCP client, tools, graph, and InMemorySaver. Ensure concurrent
requests for the same user share one initialized graph and MCP client while
preserving the existing cached fast path. Add an asyncio.gather regression test
covering concurrent same-user requests and asserting single graph and MCP client
creation.
In `@examples/langgraph/email_phishing_analyzer.py`:
- Around line 62-66: Update analyze_email so the fixed analyzer policy is
supplied as a higher-priority instruction, while state["body"] is passed
separately as clearly delimited untrusted email content rather than interpolated
into the policy prompt. Preserve the existing PhishingAssessment validation and
returned assessment shape, and add a regression case using hostile
prompt-injection text to verify the policy remains authoritative.
In `@examples/langgraph/README.md`:
- Line 9: Define the acronym by changing the first “NVIDIA NeMo Agent Toolkit”
mention in the README to include “(NAT)”, so the later “NAT’s” reference is
properly introduced.
- Line 19: Update the product naming in the README: use “NVIDIA NeMo Fabric” for
the first product mention, “NeMo Fabric” for subsequent mentions, and replace
any standalone capitalized “Fabric” references, including the occurrences near
the noted lines.
- Line 37: Quote the <your-api-key> placeholder in both NVIDIA_API_KEY export
commands in the README, including the commands near lines 37 and 60, so Bash
treats the placeholder as a value rather than shell syntax.
- Around line 49-50: Update the README’s conversation-resumption description to
state that `InMemorySaver` state is process-local and that each CLI command
creates a new `PerUserReactAgent` and saver, so repeating `--user-id` across
commands does not resume prior conversation state; either document this
limitation clearly or replace the saver with persistent checkpoint storage.
In `@examples/README.md`:
- Line 40: Update the “LangGraph proofs of concept” heading to title case as
“LangGraph Proofs of Concept,” preserving the existing heading level.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Enterprise
Run ID: 7ac52e3c-c6aa-4388-be19-471a6dfb3782
📒 Files selected for processing (10)
examples/README.mdexamples/langgraph/README.mdexamples/langgraph/__init__.pyexamples/langgraph/calculator_mcp.pyexamples/langgraph/config.pyexamples/langgraph/configs/calculator_mcp.yamlexamples/langgraph/configs/email_phishing_analyzer.yamlexamples/langgraph/email_phishing_analyzer.pyexamples/langgraph/mcp_math_server.pytests/examples/test_langgraph_pocs.py
📜 Review details
🧰 Additional context used
📓 Path-based instructions (25)
**/*.{rs,py,pyi,json,yaml,yml}
📄 CodeRabbit inference engine (.agents/skills/contribute-api/SKILL.md)
Determine and update every affected public surface, including the CLI, PyO3 bindings, Python SDK, type stubs, schemas, and adapter contract, so they remain in parity.
Files:
examples/langgraph/__init__.pyexamples/langgraph/configs/calculator_mcp.yamlexamples/langgraph/mcp_math_server.pyexamples/langgraph/configs/email_phishing_analyzer.yamlexamples/langgraph/config.pyexamples/langgraph/email_phishing_analyzer.pyexamples/langgraph/calculator_mcp.pytests/examples/test_langgraph_pocs.py
**/*
📄 CodeRabbit inference engine (.agents/skills/karpathy-guidelines/SKILL.md)
**/*: Before implementing, explicitly state assumptions, surface ambiguity and tradeoffs, present multiple interpretations when relevant, and ask for clarification rather than silently deciding or proceeding when requirements are unclear.
Prefer the minimum code needed to solve the requested problem: avoid speculative features, unnecessary abstractions, unrequested flexibility, and handling of impossible scenarios; simplify overcomplicated solutions.
When editing existing code, make surgical changes only: do not modify unrelated code, comments, formatting, or pre-existing dead code; match the existing style, and remove only unused imports, variables, or functions introduced by your changes.
Define verifiable success criteria for each task, such as writing regression tests for bugs and invalid-input tests for validation, then verify the implementation against those criteria. For multi-step work, state a brief plan with a verification check for each step.
**/*: Always spellNVIDIAin all caps; do not useNvidia,nvidia,nVidia,nVIDIA, orNV.
Usean NVIDIAbefore a noun, because the name begins with an “en” sound.
Do not add a registered trademark symbol afterNVIDIAwhen referring to the company; use trademark symbols with product names only when required by the document type or legal guidance.
Verify official capitalization, spacing, hyphenation, and spelling for NVIDIA and third-party product names; do not rewrite official product names for grammar or title-case rules.
Precede NVIDIA product names withNVIDIAon first mention when natural and accurate, and link the first mention when the destination helps the reader.
On first use, include the company name and full model qualifier when it helps identify the model; preserve official capitalization and punctuation, and use shorter family names only after establishing the full name.
For learning-oriented and developer content, do not force trademark symbols unless explicitly required; for press, ...
Files:
examples/langgraph/__init__.pyexamples/langgraph/configs/calculator_mcp.yamlexamples/langgraph/mcp_math_server.pyexamples/README.mdexamples/langgraph/configs/email_phishing_analyzer.yamlexamples/langgraph/README.mdexamples/langgraph/config.pyexamples/langgraph/email_phishing_analyzer.pyexamples/langgraph/calculator_mcp.pytests/examples/test_langgraph_pocs.py
**/*.{rs,py}
📄 CodeRabbit inference engine (.agents/skills/prepare-pr/SKILL.md)
For native binding changes, run
cargo check -p fabric-python --locked.Use
snake_casefor functions and variables; usePascalCasefor Rust types and Python classes.
Files:
examples/langgraph/__init__.pyexamples/langgraph/mcp_math_server.pyexamples/langgraph/config.pyexamples/langgraph/email_phishing_analyzer.pyexamples/langgraph/calculator_mcp.pytests/examples/test_langgraph_pocs.py
**/*.{py,pyi}
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
If Python code or a Python-facing adapter changes, run
just test-python.In Python SDK, adapters, examples, and tests, follow the existing style, use type annotations for public APIs, and keep native binding declarations synchronized with their Rust implementations.
Files:
examples/langgraph/__init__.pyexamples/langgraph/mcp_math_server.pyexamples/langgraph/config.pyexamples/langgraph/email_phishing_analyzer.pyexamples/langgraph/calculator_mcp.pytests/examples/test_langgraph_pocs.py
**/*.{rs,py,pyi}
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
**/*.{rs,py,pyi}: If public configuration types change, confirm schema snapshot tests injust test-rustpass and review generated schema diffs.
For schema or public contract changes, run both language suites and review changes underschemas/and generated API references.
Files:
examples/langgraph/__init__.pyexamples/langgraph/mcp_math_server.pyexamples/langgraph/config.pyexamples/langgraph/email_phishing_analyzer.pyexamples/langgraph/calculator_mcp.pytests/examples/test_langgraph_pocs.py
**/*.{py,pyi,rs}
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
For Python SDK or PyO3 binding changes, use
python-tests, run focused pytest tests first, thenjust test-python; rebuild withjust build-pythonwhen native code or packaging changes.Public contract changes must keep native Python binding declarations synchronized with their Rust implementations.
Files:
examples/langgraph/__init__.pyexamples/langgraph/mcp_math_server.pyexamples/langgraph/config.pyexamples/langgraph/email_phishing_analyzer.pyexamples/langgraph/calculator_mcp.pytests/examples/test_langgraph_pocs.py
**/*.{rs,py,toml}
📄 CodeRabbit inference engine (.agents/skills/update-project-version/SKILL.md)
When editing version helpers, verify every
nemo-fabric-*workspace package through Cargo metadata and reject a static version inpython/pyproject.toml.
Files:
examples/langgraph/__init__.pyexamples/langgraph/mcp_math_server.pyexamples/langgraph/config.pyexamples/langgraph/email_phishing_analyzer.pyexamples/langgraph/calculator_mcp.pytests/examples/test_langgraph_pocs.py
**/*.{toml,rs,py}
📄 CodeRabbit inference engine (.agents/skills/update-project-version/SKILL.md)
Avoid blind repository-wide replacement of version-like strings; distinguish package-version references from examples and unrelated dependency versions.
Files:
examples/langgraph/__init__.pyexamples/langgraph/mcp_math_server.pyexamples/langgraph/config.pyexamples/langgraph/email_phishing_analyzer.pyexamples/langgraph/calculator_mcp.pytests/examples/test_langgraph_pocs.py
examples/{README.md,**/*}
📄 CodeRabbit inference engine (AGENTS.md)
Update examples documentation and relevant examples when public behavior, the package, or supported bindings change.
Files:
examples/langgraph/__init__.pyexamples/langgraph/configs/calculator_mcp.yamlexamples/langgraph/mcp_math_server.pyexamples/README.mdexamples/langgraph/configs/email_phishing_analyzer.yamlexamples/langgraph/README.mdexamples/langgraph/config.pyexamples/langgraph/email_phishing_analyzer.pyexamples/langgraph/calculator_mcp.py
**/*.{md,mdx,yml,py,rs,sh}
📄 CodeRabbit inference engine (.agents/skills/review-doc-style/SKILL.md)
Keep documentation aligned with current NeMo Fabric behavior, repository layout, entry points, commands, package names, APIs, bindings, and support claims.
Files:
examples/langgraph/__init__.pyexamples/langgraph/mcp_math_server.pyexamples/README.mdexamples/langgraph/README.mdexamples/langgraph/config.pyexamples/langgraph/email_phishing_analyzer.pyexamples/langgraph/calculator_mcp.pytests/examples/test_langgraph_pocs.py
{adapters/**,examples/**}
⚙️ CodeRabbit configuration file
{adapters/**,examples/**}: Review adapter and example changes for command correctness, config/schema consistency, artifact handling, and compatibility with the public NeMo Fabric contracts.
Files:
examples/langgraph/__init__.pyexamples/langgraph/configs/calculator_mcp.yamlexamples/langgraph/mcp_math_server.pyexamples/README.mdexamples/langgraph/configs/email_phishing_analyzer.yamlexamples/langgraph/README.mdexamples/langgraph/config.pyexamples/langgraph/email_phishing_analyzer.pyexamples/langgraph/calculator_mcp.py
**/*.{yml,yaml,toml,lock}
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
For CI or packaging changes, use
maintain-ciormaintain-packaging, then run recipes and checks whose behavior changed.
Files:
examples/langgraph/configs/calculator_mcp.yamlexamples/langgraph/configs/email_phishing_analyzer.yaml
**/*.{toml,yaml,yml,sh,bash}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
TOML, YAML, and shell files must use the specified
#SPDX copyright and Apache-2.0 license headers.
Files:
examples/langgraph/configs/calculator_mcp.yamlexamples/langgraph/configs/email_phishing_analyzer.yaml
**/*.{md,rst}
📄 CodeRabbit inference engine (.agents/skills/contribute-api/SKILL.md)
Update documentation and examples in the same branch as the public API change.
Files:
examples/README.mdexamples/langgraph/README.md
{README.md,docs/**/*.{md,mdx,yml},examples/**/*.{md,mdx,yml}}
📄 CodeRabbit inference engine (.agents/skills/contribute-docs/SKILL.md)
Keep package names, repository references, and build commands current in documentation and examples.
Files:
examples/README.mdexamples/langgraph/README.md
{docs/**/*.{md,mdx,yml},examples/**/*.{md,mdx,yml}}
📄 CodeRabbit inference engine (.agents/skills/contribute-docs/SKILL.md)
Update relevant getting-started, reference, adapter, and example documentation when the corresponding examples or adapters change.
Files:
examples/README.mdexamples/langgraph/README.md
**/*.{md,mdx,rst}
📄 CodeRabbit inference engine (.agents/skills/review-doc-style/assets/nvidia-style-guide.md)
**/*.{md,mdx,rst}: For NeMo Fabric documentation, verify technical claims against the current repository, public API, or documented command before reviewing style.
Always spellNVIDIAin all caps; do not useNvidia,nvidia, orNV.
Format commands, code elements, expressions, package names, file names, and paths as inline code.
Use descriptive link text; avoid raw URLs and weak anchors such ashereorread more.
Use title case consistently for technical documentation headings.
Introduce code blocks, lists, tables, and images with complete sentences.
Write procedures as imperative, parallel steps; split long procedures into smaller tasks.
Prefer active voice, present tense, short sentences, contractions, and plain English while preserving necessary technical precision.
Usecanfor possibility and reservemayfor permission.
Useafterfor temporal relationships instead ofonce, and preferrefer tooverseewhen directing readers to another resource.
Avoid culture-specific idioms, unnecessary Latinisms, jokes, and marketing exaggeration in technical documentation.
Spell out months in body text, avoid ordinal dates, and use clear time zones.
Spell out whole numbers from zero through nine unless they are technical values, parameters, versions, or UI values; use numerals for 10 or greater and commas in thousands.
Do not add trademark symbols to learning-oriented documentation unless the source, platform, or legal guidance explicitly requires them.
Do not replace precise technical terms with simpler words when doing so would lose precision.
Do not flag passive voice when the actor is unknown or the action is the important part.
Do not rewrite API names, package names, command flags, or code literals for style.
**/*.{md,mdx,rst}: Use consistent title case for technical-document headings and table headers; avoid quotation marks, ampersands, and exclamation marks in headings, while preserving official product, event, research, and whitepaper title ...
Files:
examples/README.mdexamples/langgraph/README.md
**/*.{md,rst,txt,adoc}
📄 CodeRabbit inference engine (.agents/skills/review-doc-style/assets/nvidia-style-language-mechanics.md)
**/*.{md,rst,txt,adoc}: For technical documentation, use professional, active, conversational, engaging, precise, and plain-English prose. Prefer active voice, present tense, short sentences, and scannable paragraphs. Avoid casual or imprecise language, swearing, threats, insults, jokes, puns, culture-specific idioms, marketing exaggeration, and unsupported third-party comparisons.
Usecanfor possibility and reservemayfor permission; useafterfor temporal order; userefer tofor cross-references; prefer short direct sentences and specific verbs; avoid unnecessarypleasein technical documentation.
Prefer active voice when the actor matters. Passive voice is acceptable when the actor is unknown or irrelevant, when the action or result is the focus, or in programmer documentation.
Use natural contractions in conversational technical prose, but do not force them in formal legal copy, API references, or generated text.
Prefer simpler English over Latinisms: usefor exampleorsuch asinstead ofe.g.,and so oninstead ofetc.,that isinstead ofi.e.,compared toinstead ofvs., andby,through, orusinginstead ofvia. Use industry-standard terms such as in silico, in vitro, and in vivo when appropriate, and italicize them in running text.
Usethatwithout commas for essential clauses, andwhichwith commas for nonessential clauses.
Format dates and times clearly: spell out months in body text; use forms such asJune 12, 2025; avoid numeric or ordinal dates; capitalize days; use 12-hour time when appropriate; include a space beforea.m.orp.m.; useETandPTfor needed time zones; avoid24/7; and preferfrom 12:30 to 1:00 p.m.for prose ranges.
Format numbers consistently: spell out zero through nine in body text, use numerals for 10 or greater and for technical values, use commas in thousands, do not begin a sentence with a numeral, spell out ordinals, and use numerals consistently within a category wh...
Files:
examples/README.mdexamples/langgraph/README.md
**/*.{md,mdx}
📄 CodeRabbit inference engine (.agents/skills/review-doc-style/SKILL.md)
**/*.{md,mdx}: Use the full product nameNVIDIA NeMo Fabricon first use, typically in the title and H1; useNeMo Fabricthereafter. Usefabricalone only for the CLI tool and surround it with backticks.
Treat incorrect or stale commands, package names, paths, APIs, support claims, procedures, examples, terminology, or public behavior documentation as blocking issues.
CapitalizeNVIDIAcorrectly and format code, commands, paths, and filenames as inline code where needed.
Use title case for technical-documentation headings.
Introduce code blocks, tables, and lists with complete lead-in sentences; ensure examples match current APIs and build commands.
Use descriptive anchor text, avoid raw URLs and generic labels such ashere, and use repository-relative.mdxpaths for links withindocs/.
Prefer active voice, present tense, short sentences, plain English, consistent terminology, and imperative, parallel, scannable procedures.
Useafterinstead ofoncewhen expressing temporal sequence, and usecanrather thanmaywhen describing possibility rather than permission.
Avoid ambiguous numeric dates and ordinal dates in body text.
For learning-oriented documentation, do not force trademark symbols unless the source document explicitly requires them.
When reporting documentation-review findings, lead withMust fix,Should fix, andNice to havecategories; include file path, line reference, current problem, rationale, and a concrete rewrite or direction.
Files:
examples/README.mdexamples/langgraph/README.md
**/*.md
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Update relevant SDK, API reference, adapter, example, integration, and support documentation when the corresponding public surface changes.
Files:
examples/README.mdexamples/langgraph/README.md
**/*.{html,md}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
HTML and Markdown files must use the specified SPDX HTML-comment header.
Files:
examples/README.mdexamples/langgraph/README.md
{*.md,**/*.md,**/*.mdx,**/*.ipynb}
⚙️ CodeRabbit configuration file
{*.md,**/*.md,**/*.mdx,**/*.ipynb}: Enforce the product name in user-facing prose: use "NVIDIA NeMo Fabric" on first use and "NeMo Fabric" thereafter. Flag standalone capitalized "Fabric" when it refers to the product. Do not flag the lowercasefabricCLI command, package/import/crate names, code identifiers, API symbols, configuration keys, file paths, or unrelated generic uses of the word.
Files:
examples/README.mdexamples/langgraph/README.md
tests/**/*.{rs,py}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
When adding functionality, include tests in the corresponding Rust crate or the relevant area under
tests/.
Files:
tests/examples/test_langgraph_pocs.py
tests/**/*.py
📄 CodeRabbit inference engine (.agents/skills/python-tests/SKILL.md)
tests/**/*.py: Use pytest to run Python tests.
Do not add@pytest.mark.asyncioto tests; async tests are automatically detected by the async runner.
Do not add-> Nonereturn type annotations to test functions.
When mocking a class, useunittest.mock.MagicMockorAsyncMock, using thespecargument when necessary, rather than defining a new class.
Prefix mocked class names withmock, notfake.
Prefer pytest fixtures over helper methods.
If a fixture is needed in multiple test files, define it once inconftest.pyrather than repeating it.
Define fixtures using@pytest.fixture(name="<fixture_name>"[, scope="<scope>"])and a<fixture_name>_fixturefunction; specifyscopeonly when it is notfunction.
Preferpytest.mark.parametrizeover separate tests for different input types.
Use@pytest.mark.usefixtureswhen a fixture is needed but its returned value is unused or it returns no value.
Avoid defensive programming in tests; access expected values directly so missing data raises a clear failure, such as usingresults["data"]instead ofresults.get("data").
When adapter installation metadata changes, packaging metadata tests must directly assert that the root project depends unconditionally on the exact-versionnemo-fabric-runtimedistribution.
Packaging metadata tests must verify that each root harness extra delegates to the matching version of the leaf adapter'sharnessextra.
Packaging metadata tests must verify that bare leaf dependencies remain adapter-owned and that the rootadapter-testsdependency group installs each leaf through itsharnessextra.
Packaging metadata tests must verify that every leaf providesfull; only adapters importing NeMo Relay Python APIs providerelay, while adapters using an external Relay executable havefullequal toharness.
Files:
tests/examples/test_langgraph_pocs.py
{tests/**,python/tests/**}
⚙️ CodeRabbit configuration file
{tests/**,python/tests/**}: Tests should cover the behavior promised by the changed API surface, including error paths, lifecycle cleanup, and SDK/native parity where relevant.
Files:
tests/examples/test_langgraph_pocs.py
🪛 ast-grep (0.45.0)
examples/langgraph/email_phishing_analyzer.py
[info] 87-87: use jsonify instead of json.dumps for JSON output
Context: json.dumps(result["assessment"], indent=2)
Note: [CWE-116] Improper Encoding or Escaping of Output.
(use-jsonify)
🪛 Ruff (0.16.1)
examples/langgraph/mcp_math_server.py
[warning] 41-41: Avoid specifying long messages outside the exception class
(TRY003)
examples/langgraph/config.py
[warning] 79-79: Remove quotes from type annotation
Remove quotes
(UP037)
[warning] 82-82: Avoid specifying long messages outside the exception class
(TRY003)
[warning] 88-88: Avoid specifying long messages outside the exception class
(TRY003)
[warning] 112-112: Prefer TypeError exception for invalid type
(TRY004)
[warning] 112-112: Avoid specifying long messages outside the exception class
(TRY003)
[warning] 121-123: Avoid specifying long messages outside the exception class
(TRY003)
examples/langgraph/email_phishing_analyzer.py
[warning] 50-50: Dynamically typed expressions (typing.Any) are disallowed in model
(ANN401)
[warning] 51-51: Dynamically typed expressions (typing.Any) are disallowed in build_email_phishing_analyzer
(ANN401)
[warning] 55-55: Avoid specifying long messages outside the exception class
(TRY003)
examples/langgraph/calculator_mcp.py
[warning] 64-64: Avoid specifying long messages outside the exception class
(TRY003)
[warning] 66-66: Avoid specifying long messages outside the exception class
(TRY003)
[warning] 68-68: Avoid specifying long messages outside the exception class
(TRY003)
[warning] 76-76: Dynamically typed expressions (typing.Any) are disallowed in graph_for
(ANN401)
[warning] 80-80: Avoid specifying long messages outside the exception class
(TRY003)
🔇 Additional comments (12)
examples/langgraph/config.py (2)
1-60: LGTM!Also applies to: 101-130
61-67: 🎯 Functional CorrectnessRetain the retry settings as documented adapter gaps.
The workflows intentionally do not apply
retry_parsing_errorsormax_retries. The README documents this limitation and explains that retrying calculator tool calls requires a defined policy. No implementation change is required for these proof-of-concept workflows.> Likely an incorrect or invalid review comment.examples/langgraph/configs/calculator_mcp.yaml (1)
1-33: LGTM!examples/langgraph/configs/email_phishing_analyzer.yaml (1)
1-14: LGTM!Also applies to: 18-24
examples/langgraph/calculator_mcp.py (1)
1-74: LGTM!Also applies to: 101-139
examples/langgraph/mcp_math_server.py (1)
1-58: LGTM!tests/examples/test_langgraph_pocs.py (1)
23-30: LGTM!Also applies to: 72-102
examples/langgraph/email_phishing_analyzer.py (1)
1-48: LGTM!Also applies to: 75-99
examples/langgraph/__init__.py (1)
1-4: LGTM!examples/README.md (1)
42-46: LGTM!examples/langgraph/README.md (2)
1-8: LGTM!Also applies to: 11-18, 23-36, 38-48, 55-59, 61-78, 79-81, 83-97, 100-108
109-112: 📐 Maintainability & Code QualityMake the adapter-proposal reference actionable.
If the proposal is not shipped with this repository, replace
supplied third-party adapter proposalwith a self-contained summary or a descriptive link.
| async def graph_for(self, user_id: str) -> Any: | ||
| """Return the user-owned graph, creating it and its MCP client on first use.""" | ||
|
|
||
| if not user_id.strip(): | ||
| raise ValueError("user_id must be a non-empty string") | ||
| graph = self._sessions.get(user_id) | ||
| if graph is not None: | ||
| return graph | ||
|
|
||
| server = self._config.mcp.servers["mcp_math"] # validated in __init__ | ||
| client = self._mcp_client_factory( | ||
| {"mcp_math": mcp_connection(server)}, tool_name_prefix=False | ||
| ) | ||
| mcp_tools = _selected_mcp_tools(list(await client.get_tools()), server) | ||
| model = self._model_factory(self._config.selected_model()) | ||
| graph = self._graph_factory( | ||
| model, | ||
| [current_timezone, *mcp_tools], | ||
| checkpointer=InMemorySaver(), | ||
| debug=bool(self._config.workflow.settings.get("verbose", False)), | ||
| name="per_user_calculator", | ||
| ) | ||
| self._sessions[user_id] = graph | ||
| return graph |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Serialize Initial Graph Creation Per User.
Two concurrent calls can both pass the cache check before await client.get_tools(). Each call then creates a different graph and checkpoint store. The last assignment replaces the cached graph, and later calls lose the other caller's conversation history.
Use a per-user initialization task or lock with a second cache check. Add an asyncio.gather regression test that verifies one graph and one MCP client are created for concurrent requests from the same user.
🧰 Tools
🪛 Ruff (0.16.1)
[warning] 76-76: Dynamically typed expressions (typing.Any) are disallowed in graph_for
(ANN401)
[warning] 80-80: Avoid specifying long messages outside the exception class
(TRY003)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@examples/langgraph/calculator_mcp.py` around lines 76 - 99, Update graph_for
to serialize first-time graph creation per user using a per-user initialization
task or lock, then recheck _sessions before constructing the MCP client, tools,
graph, and InMemorySaver. Ensure concurrent requests for the same user share one
initialized graph and MCP client while preserving the existing cached fast path.
Add an asyncio.gather regression test covering concurrent same-user requests and
asserting single graph and MCP client creation.
| async def analyze_email(state: EmailPhishingState) -> dict[str, Any]: | ||
| assessment = await structured_model.ainvoke(prompt.format(body=state["body"])) | ||
| if not isinstance(assessment, PhishingAssessment): | ||
| assessment = PhishingAssessment.model_validate(assessment) | ||
| return {"assessment": assessment.model_dump()} |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
Treat Email Content as Untrusted Data.
state["body"] is inserted into the same instruction string as the analyzer policy. A phishing email can include prompt-injection text that asks the model to return a false assessment.
Put fixed analyzer policy in a higher-priority instruction. Pass the email as explicitly delimited untrusted content. Add a regression case with hostile email text.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@examples/langgraph/email_phishing_analyzer.py` around lines 62 - 66, Update
analyze_email so the fixed analyzer policy is supplied as a higher-priority
instruction, while state["body"] is passed separately as clearly delimited
untrusted email content rather than interpolated into the policy prompt.
Preserve the existing PhishingAssessment validation and returned assessment
shape, and add a regression case using hostile prompt-injection text to verify
the policy remains authoritative.
| # Native LangGraph Proofs of Concept | ||
|
|
||
| These proofs of concept translate two | ||
| [NVIDIA NeMo Agent Toolkit examples](https://github.com/NVIDIA/NeMo-Agent-Toolkit/tree/develop/examples) |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Should fix: Define NAT before using the acronym.
Line 9 names NVIDIA NeMo Agent Toolkit, but it does not introduce (NAT). Line 51 then uses NAT's. Add the acronym to the first mention or use the full name at Line 51.
Proposed fix
-[NVIDIA NeMo Agent Toolkit examples]
+[NVIDIA NeMo Agent Toolkit (NAT) examples]As per coding guidelines, spell out terms on first use and define acronyms unless they are widely understood by the intended audience.
Also applies to: 51-51
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@examples/langgraph/README.md` at line 9, Define the acronym by changing the
first “NVIDIA NeMo Agent Toolkit” mention in the README to include “(NAT)”, so
the later “NAT’s” reference is properly introduced.
Source: Coding guidelines
|
|
||
| They use the NIM model requested for this experiment: | ||
| `meta/llama-3.1-70b-instruct` through the OpenAI-compatible NIM endpoint. These | ||
| are application POCs, not a registered NeMo Fabric adapter. The YAML files are |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Must fix: Use the required product name consistently.
Use NVIDIA NeMo Fabric on first mention. Use NeMo Fabric thereafter. Do not use standalone capitalized Fabric for the product.
As per coding guidelines and path instructions, use NVIDIA NeMo Fabric on first use, NeMo Fabric thereafter, and do not use standalone capitalized Fabric for the product.
Also applies to: 82-82, 98-99
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@examples/langgraph/README.md` at line 19, Update the product naming in the
README: use “NVIDIA NeMo Fabric” for the first product mention, “NeMo Fabric”
for subsequent mentions, and replace any standalone capitalized “Fabric”
references, including the occurrences near the noted lines.
Sources: Coding guidelines, Path instructions
| Set an NVIDIA API key and start the included MCP server in one terminal: | ||
|
|
||
| ```bash | ||
| export NVIDIA_API_KEY=<your-api-key> |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
bad='export NVIDIA_API_KEY=<your-api-key>'
good='export NVIDIA_API_KEY="<your-api-key>"'
if printf '%s\n' "$bad" | bash -n; then
echo "The unquoted placeholder parsed unexpectedly." >&2
exit 1
fi
printf '%s\n' "$good" | bash -nRepository: NVIDIA/NeMo-Fabric
Length of output: 268
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
file='examples/langgraph/README.md'
printf '%s\n' '--- matching lines ---'
rg -n -C 2 'NVIDIA_API_KEY|<your-api-key>' "$file"
printf '%s\n' '--- shell parse and assignment behavior ---'
python3 - <<'PY'
import subprocess
cases = {
"unquoted": "export NVIDIA_API_KEY=<your-api-key>\n",
"quoted": 'export NVIDIA_API_KEY="<your-api-key>"\n',
}
for name, script in cases.items():
parsed = subprocess.run(["bash", "-n"], input=script, text=True, capture_output=True)
executed = subprocess.run(
["bash", "-c", script + 'printf "<%s>\\n" "$NVIDIA_API_KEY"'],
text=True,
capture_output=True,
)
print(f"{name}: parse_rc={parsed.returncode}, execution_rc={executed.returncode}")
print(f"{name}: value={executed.stdout.strip()!r}")
if parsed.stderr:
print(f"{name}: parse_stderr={parsed.stderr.strip()!r}")
PYRepository: NVIDIA/NeMo-Fabric
Length of output: 822
Quote the API-key placeholder in both commands.
The unquoted < and > characters cause a Bash syntax error. Use export NVIDIA_API_KEY="<your-api-key>" at Lines 37 and 60.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@examples/langgraph/README.md` at line 37, Quote the <your-api-key>
placeholder in both NVIDIA_API_KEY export commands in the README, including the
commands near lines 37 and 60, so Bash treats the placeholder as a value rather
than shell syntax.
Sources: Coding guidelines, Path instructions
| --input "Reply with exactly: NeMo Fabric works" | ||
| ``` | ||
|
|
||
| ## LangGraph proofs of concept |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Must fix: Use title case in the heading.
Change the heading to ## LangGraph Proofs of Concept.
Proposed fix
-## LangGraph proofs of concept
+## LangGraph Proofs of ConceptAs per coding guidelines, technical-documentation headings must use title case.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| ## LangGraph proofs of concept | |
| ## LangGraph Proofs of Concept |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@examples/README.md` at line 40, Update the “LangGraph proofs of concept”
heading to title case as “LangGraph Proofs of Concept,” preserving the existing
heading level.
Source: Coding guidelines
Signed-off-by: Zhongxuan Wang <daniewang@nvidia.com>
6e8bee9 to
8b94df7
Compare
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
Overview
Adds two runnable native LangGraph examples: a per-user calculator with an MCP math server and a structured email-phishing analyzer. These examples run directly with LangGraph. NVIDIA NeMo Fabric does not yet ship a LangGraph adapter, and the example YAML files are not FabricConfig input.
Details
Validation
Where should the reviewer start?
Start with examples/langgraph/README.md for the support boundary and adapter requirements, then review the two graph factories and their focused offline tests.
Related Issues: (use one of the action keywords Closes / Fixes / Resolves / Relates to)
Relates to FABRIC-166
I confirm this contribution is my own work, or I have the right to submit it under this project's license.
I searched existing issues and open pull requests, and this does not duplicate existing work.
Summary by CodeRabbit
New Features
Documentation
Tests