Make every Bot say where its answer came from - #153
Merged
Conversation
Asked what the obligation was for twelve cash deposits under the reporting threshold, the compliance Bot answered at length: file a SAR, $5,000 or more, within 30 calendar days of initial detection, retain for 5 years. The audit trail for that turn holds one row, the routing decision. No tool call, no source, and no sentence saying the answer came from the model rather than from anything the deployment can reach. Several of those numbers may well be right. That is the problem. A confident, plausible, unsourced answer is indistinguishable from a confident, plausible, wrong one, on a question about whether to file, against what threshold, inside what deadline. One package's knowledge Bot had a rule against this, written into its YAML by whoever thought of it. The Bot whose entire subject is regulatory obligation did not, because a remote-ag-ui agent gets its role description and nothing else. That asymmetry is the bug: a rule this important living in one agent's YAML is a rule the next agent will not have. So it lives in the shared prompt and every Bot gets it, through the built-in prompt and through the standing role message that is a remote Bot's only instruction. The rule is to say where an answer came from, not to go and find one. An earlier attempt told Bots to find a source and they went hunting the open web and looped on a government 404 page, which is worse than the problem it was fixing. An unsourced answer that says it is unsourced is honest; a search that never ends is a Bot that never answers. Also says in the configuration docs that role_description is the whole brief for a remote agent, which is not obvious beside a built-in one that gets a prompt. Closes #142.
davidmckayv
requested review from
MikeRyanDev,
guidovizoso and
tylerslaton
as code owners
August 22, 2026 04:29
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.
Closes #142.
What happened
Risk Analyst answered at length and with confidence: aggregate for CTR purposes, do not tip off the customer, escalate to AML/BSA, "the institution generally must file a SAR", "$5,000 or more", "file within 30 calendar days of initial detection", retain documentation "for 5 years".
The audit trail for that turn:
One row. No tool call, no source, and nothing saying the answer came from the model rather than from anything this deployment can reach.
Several of those numbers may well be right. That is the problem — a confident, plausible, unsourced answer is indistinguishable from a confident, plausible, wrong one, on a question about whether to file, against what threshold, inside what deadline.
Why it belongs in the deployment, not in a package
One package's
knowledgeBot already had a rule against exactly this, in its YAML. The Bot whose entire subject is regulatory obligation did not, because aremote-ag-uiagent gets itsrole_descriptionand nothing else — in this case the single sentence "Investigate policies, transaction monitoring, and control evidence."That asymmetry is the bug, and the issue names the fix: a rule this important sitting in one agent's YAML is a rule that will be missing from the next agent somebody adds. So it lives in the shared prompt, and reaches both paths — the built-in prompt, and the standing role message that is a remote Bot's only instruction.
It is unconditional, unlike the tool and computer guidance beside it. A Bot with no tools and no computer needs it most: it has nothing to read, so everything it says comes from its own knowledge.
What it does not do
It does not tell Bots to go and find a source.
An earlier attempt at this did, and Bots went hunting the open web and looped on a government 404 page — worse than the problem it was fixing. That attempt never left a branch, and the guidance now says so explicitly:
An unsourced answer that says it is unsourced is honest. A search that never ends is a Bot that never answers.
Driven in Chrome, same question
Rebuilt the Bot container, restarted through
scripts/start.sh, asked the identical question through the@picker. The answer now opens:And the trail behind it is no longer one row:
So "Source checked" is a fact the audit trail confirms, not a claim the model made about itself. It checked what it could reach, twice, stopped, and answered.
The body changed too, and this is the part that matters most. Where the original asserted $5,000, 30 calendar days and 5 years, this one says "Likely obligation", "may need to be aggregated depending on the rule and timing", and "In many regimes, suspected structuring is reportable even if no single deposit reaches the cash reporting threshold". The invented figures and deadlines — the parts somebody would have acted on — are gone, without the answer becoming useless.
Also
docs/configuration.mdnow says thatrole_descriptionis the whole brief for aremote-ag-uiagent. It is not obvious sitting beside abuilt-inagent that gets a prompt, and it is the reason this Bot had no rule to begin with.Tests
Four added, two of them proven to fail with the wiring removed:
Three existing exact-prompt assertions were updated to include it, referencing the exported constant rather than restating the prose, so they stay exact without pinning the wording twice.