feat(integration): add GuardrailsMiddleware for LangChain agent#1606
Merged
feat(integration): add GuardrailsMiddleware for LangChain agent#1606
Conversation
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
8ed8285 to
49c598e
Compare
Contributor
Greptile OverviewGreptile SummaryThis PR adds a new Major Changes:
Implementation Quality:
Issue Found:
|
| Filename | Overview |
|---|---|
| nemoguardrails/integrations/langchain/exceptions.py | New exception class for guardrail violations, simple and well-structured |
| nemoguardrails/integrations/langchain/middleware.py | New middleware implementation with input/output rails integration - has one naming inconsistency issue |
| tests/integrations/langchain/test_middleware.py | Comprehensive unit tests with mocks covering all middleware scenarios |
| tests/integrations/langchain/test_middleware_e2e.py | E2E tests with real guardrails configuration, thorough security scenario coverage |
Sequence Diagram
sequenceDiagram
participant User
participant Agent as LangChain Agent
participant GM as GuardrailsMiddleware
participant Rails as LLMRails
participant Model as LLM
User->>Agent: Send message
Agent->>GM: before_model(state, runtime)
GM->>GM: Check enable_input_rails
GM->>GM: Check _has_input_rails()
GM->>GM: Convert messages to dicts
GM->>Rails: check_async(messages)
Rails-->>GM: RailsResult (PASSED/BLOCKED)
alt Input Blocked
GM->>GM: _handle_guardrail_failure()
alt raise_on_violation=True
GM-->>Agent: Raise GuardrailViolation
else raise_on_violation=False
GM->>GM: Create blocked AI message
GM-->>Agent: Return {messages, jump_to: "end"}
end
else Input Passed
GM-->>Agent: Return None (continue)
Agent->>Model: Call LLM
Model-->>Agent: Generate response
Agent->>GM: after_model(state, runtime)
GM->>GM: Check enable_output_rails
GM->>GM: Check _has_output_rails()
GM->>GM: Get last AI message
GM->>GM: Convert messages to dicts
GM->>Rails: check_async(messages)
Rails-->>GM: RailsResult (PASSED/BLOCKED)
alt Output Blocked
GM->>GM: _handle_guardrail_failure()
alt raise_on_violation=True
GM-->>Agent: Raise GuardrailViolation
else raise_on_violation=False
GM->>GM: Replace last message with blocked message
GM-->>Agent: Return {messages: modified}
end
else Output Passed
GM-->>Agent: Return None (continue)
Agent-->>User: Return response
end
end
tgasser-nv
reviewed
Feb 3, 2026
Collaborator
tgasser-nv
left a comment
There was a problem hiding this comment.
Can you run a local integration test to make sure this works ?
Collaborator
Author
|
@tgasser-nv I've done proper e2e tests and verifications. Will share them with QA 👍🏻 |
tgasser-nv
reviewed
Feb 4, 2026
165b58e to
ce01f0d
Compare
tgasser-nv
approved these changes
Feb 5, 2026
Collaborator
tgasser-nv
left a comment
There was a problem hiding this comment.
Looks good, thanks for updating the Runtime argument. Can you make sure QA have good coverage on these methods for integration testing?
Add a new `check_async` method to `LLMRails` that allows standalone validation of messages against input/output rails without requiring a full conversation flow. **Key features:** - Automatically determines which rails to run based on message roles: - User messages only → input rails - Assistant messages only → output rails - Both user and assistant → input and output rails - Returns a simple `RailsResult` with status (PASSED/MODIFIED/BLOCKED), content, and blocking rail name
…age replacement - Add RailType enum (INPUT, OUTPUT) to options.py - Add optional rail_types parameter to check_async/check to override auto-detection - Middleware now passes rail_types=[RailType.INPUT] from abefore_model and rail_types=[RailType.OUTPUT] from aafter_model - Fix _replace_last_ai_message to find actual AIMessage index instead of assuming messages[-1] - Add unit tests for explicit rail type passing and message replacement
2618f46 to
cb62b05
Compare
Pouyanpi
added a commit
that referenced
this pull request
Feb 9, 2026
* feat(langchain): add GuardrailsMiddleware for LangChain agent integration * feat(middleware): add explicit rail_types to check_async and fix message replacement - Add RailType enum (INPUT, OUTPUT) to options.py - Add optional rail_types parameter to check_async/check to override auto-detection - Middleware now passes rail_types=[RailType.INPUT] from abefore_model and rail_types=[RailType.OUTPUT] from aafter_model - Fix _replace_last_ai_message to find actual AIMessage index instead of assuming messages[-1] - Add unit tests for explicit rail type passing and message replacement
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
## Description
Add a new
GuardrailsMiddlewareclass for seamless integration with LangChain's Agent Middleware system. The middleware intercepts agent conversations to apply NeMo Guardrails input/output validation before and after model calls.This follows the LangChain Middleware pattern introduced in LangChain 1.0, providing
before_modelandafter_modelhooks for precise control over the agent loop.Key features:
GuardrailsMiddleware- Full middleware with both input and output railsInputRailsMiddleware- Input-only validationOutputRailsMiddleware- Output-only validationGuardrailViolationexception for programmatic error handlingconfig_pathandconfig_yamlinitializationUsage example:
References