Repository navigation
feat(guardrails): give post-execution guardrails only the files the output references [AL-611] #1144
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
feat(guardrails): give post-execution guardrails only the files the output references [AL-611] #1144
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
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
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
Oops, something went wrong.
Oops, something went wrong.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why for LLM guardrail node we pass None for PRE exec?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the None is attachment_source=None, which means "no single payload to read files from". It doesn't mean "send no files". At LLM PRE the guardrail still gets every file in the run, exactly as on main.
How the code reads it: in _resolve_attachments (guardrail_nodes.py:212-238), there are two cases:
Why PRE and POST differ:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At LLM pre, the guardrail is sent references to every file the run has registered so far.
attachment_source=Noneonly means there is no single payload to search for file mentions; the files come from the run's attachment registry,inner_state.job_attachments.1. The registry is filled as the run goes. It is a dict from attachment id to
Attachment, typed in types.py:27 with amerge_dictsreducer, so writes only add entries. Three places write to it:2. Without a source, the node reads the whole registry. In guardrail_nodes.py:224-226,
_resolve_attachmentscallsresolve_guardrail_attachments(state.inner_state.job_attachments, guardrail). That function, in attachment_refs.py:81-95, returns one of three things:Noneif the guardrail'sappliesTois Text only. The backend then checks only the text.[]if the run has no files yet. A Files-only guardrail then passes without a provider call (D6).{id, fileName, mimeType}each, built from the registry entries.3. Only references go to the backend, never file content. The node sends the list as the
attachmentsfield of the validate call. The Agents backend resolves each id through Orchestrator, downloads the file, and works out its type (the #6598 sniffing). It then appends the file's text to what the provider checks.So at LLM pre the guardrail sees every file the model could have in its context at that point: the input files plus whatever earlier tools returned. It doesn't read the last message for mentions, because a file attached at the start of the run is still in the model's context many turns later. This part is unchanged from main.
At LLM post, the source is the tool-call arguments, so only the files those arguments mention are sent. They are still looked up in the same registry, so an id the run never held is dropped.
One limit: the registry only knows files that came in through schema-typed job-attachment fields. A file id that appears only in a message's free text, with no schema-typed field behind it, is never registered, so no guardrail sees it at LLM pre.