buddie
Verifies claims about pull request merge status and CI success by querying the GitHub API for PR state, merge commit, and all check runs/statuses on a commit.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@buddieverify report.md's quotes and test claims against the transcript"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
buddie
Checks that what an AI agent tells you is true, before you read it. When Claude quotes a page, buddie looks the words up in a snapshot of that very page. When it states "merged", "CI is green" or "tests passed" with an anchor, buddie asks GitHub, git and the session log. No model takes part in the check, so the agent cannot talk its way past it, and every check ends in a receipt anyone can re-run.
In Claude Code the plugin checks each answer as it ends. A quote that is not on its page goes back to Claude with the closest real passage, before you see the answer:
buddie FAIL: quotes 1/2 found, 1 not found
- quote L3.1 not found in https://status.example.com/incidents/42: “elevated error rates on the API between 14:58 and 15:41 UTC” (closest 0.98: “elevated error rates on the API between 14:59 and 15:41 UTC”)An answer with nothing to check passes untouched. Why it matters: in 929 checkable quotations from published deep-research reports, one in five was altered or absent from the page it cited (What we found).
Receipts for agent work. In a multi-agent setup an executor reports to an orchestrator, and the orchestrator
reports to a human. Every hand-off restates claims such as "the source says X", "tests passed" or "PR merged", and a
wrong claim travels on. buddie checks those claims at the hand-off against primary evidence: the bytes of the cited
page, the repository, the GitHub API and the session transcript. No model takes part in the check, so the agent being
checked cannot talk its way past it. Every check ends in a receipt that anyone can re-run.
· Python ≥ 3.11 · no dependencies · Apache-2.0 · Claude Code and Codex plugin, Claude Desktop extension, MCP server
(stdio and HTTP) and CLI
This repository was called
verbatimuntil October 2026.verbatimis now buddie's quote module (buddie.verbatim, commandbuddie-verbatim; until 0.8 it was a top-levelverbatimpackage and command, which clashed with an unrelatedverbatimon PyPI); old links redirect.
Why this matters for oversight
An agent's account of its own work is easy to accept and expensive to re-check. A quote that was altered, a test run that never happened or a PR described as merged while it is still open all pass as evidence when the reader cannot re-open every source. This is a narrow but measurable form of unfaithful reporting. buddie checks the account against records the agent did not write, without access to its reasoning. That makes it a small piece of scalable oversight that still works when the overseer is weaker than, or not trusted by, the agent.
Related MCP server: evidence-lint
What it checks
Claim in a report | Checked against | Bad outcome |
A quotation with a link | the visible text of a SHA-256 snapshot of that link ( |
|
A repo anchor | the file's current bytes, or the file at that commit |
|
"Merged", "CI green": | the GitHub API: PR state and merge commit, all check runs and statuses on the commit |
|
"I ran it and got this": | the Claude Code session transcript: a tool call with CMD and OUTPUT in its result |
|
"Step N is done", "the user agreed", "next step is in the accepted plan" (opt-in, | the task queue at a commit, the accepted-plans list, the user's own messages |
|
A number or date in a sentence with a link | the visible text of the snapshot of that link ( |
|
The executor writes the anchors. Lines that state work in prose without an anchor ("merged", "CI is green", "tests
passed", "41 passed") are listed in the receipt (prose_work). In a project whose buddie.toml blocks prose, the
hook returns them in a final answer with ready anchors (PRs named in the text or tool output, the run that printed
the count), and a buddie: disclosure does not let them through (0.7.1). A negated claim ("not merged yet") is not
one.
Quick start
pip install buddie
cd examples/quickstart
buddie-verbatim add https://status.example.com/incidents/42 page.html # or let buddie fetch the page itself
buddie verify report.md --no-fetchBLOCK quote L3.1 not found in https://status.example.com/incidents/42: “elevated error rates on the API between 14:58 and 15:41 UTC” (closest 0.98: “elevated error rates on the API between 14:59 and 15:41 UTC”)
BLOCK quote L7.1 not found in https://status.example.com/incidents/42: “the root cause was a misconfigured load balancer” (closest 0.50: “. The rest of the article discusses unrelated bac”)
buddie FAIL: quotes 1/3 found, 2 not foundA claim about work, checked against the session transcript (examples/work):
cd examples/work
buddie verify report.md --transcript session.jsonl --no-githubBLOCK anchor line 3 ⚓ run:pytest -q => 41 passed: output has no '41 passed'; it ends: ….......................................... 1 failed, 40 passed in 3.1s
buddie FAIL: effects 0/1 hold, 1 brokenThe exit code is 1 on FAIL, so the check can gate a CI job, a hook or a hand-off. A wrong digit shows up as a close
passage (similarity ≈ 0.98), an invented sentence as a distant one (≈ 0.5).
In Claude Code
/plugin marketplace add tsyyan/buddie
/plugin install buddie@buddieThe plugin brings four things:
a hook (
hooks/hooks.json) onPreToolUsefor messages that leave the session (SendMessage) and onStop;examples/hooks/projects.jsonadds matchers for other reply tools. OnFAILit returns the report to the model with the reasons, before anyone reads it. Since 0.6 it also counts live subagents (SubagentStart/SubagentStop); when none is left, the orchestrator is asked once for a summary built by code and a choice card for the next steps, and the person's pick (AskUserQuestion) goes to the journal, where the anchorchoice:<id>=<step>is checked;an MCP server (stdio, no SDK):
verify_report,snap,source_text,summary;skills:
skills/buddiefor executors and orchestrators,skills/verbatimfor quoting from snapshots;commands you run yourself:
/buddie:check [file or text]checks a text now (your last answer by default),/buddie:statusshows what is checked in this project and what was returned lately,/buddie:initturns on the project's full checks (buddie.toml, starting in intro mode).
The hook runs through hooks/run.sh, which starts the first of python3, python and py -3 that is Python 3.11+,
so it works on Linux, macOS and Windows (Claude Code runs hooks there in Git Bash).
Optional setting: a GitHub token for pr:/ci: anchors (the plugin asks for it and stores it as a secret; it is
sent only to api.github.com). Without it GitHub allows 60 lookups an hour and private repos can't be checked.
Without Claude Code: python3 run.py verify REPORT.md --repo . from a clone works without installing anything.
Other clients
Client | How | What it gets |
Claude Desktop | the | MCP tools; no hook, |
Codex (CLI, IDE, app) |
| MCP tools, skills, a Stop hook; |
ChatGPT, claude.ai, the Claude API | a remote server you host: | quotes, numbers, |
any MCP client that starts a command |
| MCP tools over stdio |
CI |
| the receipt as a CI step |
Releases and catalog listings: docs/release.md, docs/catalogs.md.
Levels and the intro mode
Right after installing (no buddie.toml in the repo), the hook returns an answer only for what is false: a
quote that is not on the page it links to, or an anchor that does not hold. An answer with no quotes and no anchors
passes untouched, and so does one whose source could not be read. Numbers of cited sentences that are not on their
page only warn. Asking for anchors on every final answer, prose about work and the context limit are a project's
choice, made with buddie init.
buddie init writes buddie.toml in the repo with the default level of each class of claims and turns the intro
mode on. Each class is block (the text goes back to the model), warn (the text leaves; you see what the gate would
have said) or off:
Class | What | With | Without |
| a broken anchor: |
|
|
| a quote not on its source |
|
|
| a final answer with no anchor, or a count line without one |
|
|
| work claimed in prose ("merged", "tests passed") with no anchor on the line |
|
|
| a number of a cited sentence not in its source |
|
|
| a claim about the work queue that does not hold ( |
|
|
| return a |
|
|
| return a |
|
|
| a reply or a subagent launch past the context limit ( |
|
|
[gates]
prose = "block"
[intro]
finals = 20In the intro mode nothing is returned: each would-be return is a warning that says what it would have returned. It
ends by itself after finals final answers with no false return reported; buddie intro --false reports one and
restarts the count, buddie intro shows where it stands, buddie enforce ends it now. Without buddie.toml the
"Without" column applies and there is no intro: nothing that is merely unanchored is returned, so there is nothing
to get used to.
The loop
The hook also learns from its own returns; none of it is written by the model:
How the gate was passed. A return logs
reasons; the next attempt of the same tool in the session logsgate: per flagged lineproved,removedorkept, and the way through (proof,removal,mixed,disclosure,returned).Lessons at start. On
SessionStartthe hook prints a summary of past sessions' journal: how many messages came back, for what, and the shape of a line that passes (at most ten lines).Ready anchors. A return offers
pr:,ci:andrun:anchors that already hold (checked now), to copy onto the line instead of rewording it.Measure.
buddie journal measure --sessions 10: the share of sessions whose first checked message passed, and how returns were passed (proof vs removal).Context gate. Past
BUDDIE_CONTEXT_LIMITtokens of context a non-final reply is returned with a reminder to hand the result over; final answers, hand-offs to another session andStopare never held.
Receipt v0
Each check produces an in-toto Statement: the subject is the SHA-256 of the
report text; the predicate (predicateType: https://github.com/tsyyan/buddie#receipt-v0) lists the verdict of every
quote with the snapshot SHA-256 and offset, the status of every anchor, and the outcome:
Outcome | When | What the receiver does |
| a quote | does not pass it on as is: fix it, or add a line starting with |
| something could not be checked: source unavailable, quote without a link, anchor in another repo, GitHub offline | passes it on, naming what was not checked |
| all quotes found, all anchors hold | passes it on with the receipt line |
| nothing to check | knows that no check took place |
ci: and run: receipts carry a note: an anchor shows what happened (a PR in that state, checks on that commit, a
command and its output), not that the code is correct. A green CI on weak tests stays weak.
Receipt v1
receipt-v0's outcome describes the checks that ran: after a partial run (a profile, --anchors-only) it can say
PASS while quotes or anchors in the text were never looked at. receipt-v1
(predicateType: https://github.com/tsyyan/buddie#receipt-v1), given only when asked for (buddie verify --receipt v1, MCP "receipt": "v1", receipts.render(verify.assessment(...), "v1")), keeps apart the outcome of what ran,
the checks that ran, the ones that did not and why, the coverage (FULL, PARTIAL, UNKNOWN, NONE) and the
provenance of the evidence. Its reference, JSON Schema and v0 mapping: docs/receipts.md. PASS
in either never means that every statement of a report is true.
What we found
Deep-research reports quote wrongly. On 929 checkable quotations from published deep-research reports, labelled
blind, 212 (22.8 %, 95 % CI 20–26 %) were altered by the agent or absent from the cited source. verbatim flagged
207 of those 212.
Set (reports) | Systems | Checked quotes | Agent errors | False |
E008 (90, DeepResearch Bench II) | OpenAI o3 Deep Research, Perplexity, Grok, Doubao | 489 | 152 (31.1 %) | 19 (3.9 %) |
E010 (102, ydc-deep-research-evals) | OpenAI o3 | 147 | 40 (27.2 %) | 1 (0.7 %) |
E011 (50, DeepResearch Bench I) | Claude 3.7 Sonnet with web search | 249 | 20 (8.0 %) | 1 (0.4 %) |
E012 (350, DeepResearch Bench I) | fresh reports not seen before | 44 | 0 | 1 (2.3 %) |
All | 929 | 212 (22.8 %) | 22 (2.4 %, CI 1.6–3.6 %) |
Source: results/E013-stage2-summary/recount.json. "Checked" means the
cited page could be read and the quote is long enough to search (≥ 12 characters).
Numbers too. In 100 random sentences of DeepResearch Bench I reports (Gemini, Grok, OpenAI, Perplexity), 28 of 103 checkable cited numbers (27.2 %) were not in their source (E009; two blind labellers, κ 0.956).
Where the quote check is weak. Measured out of sample (each version on reports it was not tuned on), false
NOT_FOUND is 10 of 440 (2.3 %, CI 1.2–4.1 %). On a new genre, Search Arena answers of Perplexity, GPT-4o search and
Gemini grounding with the rules unchanged, it is 29 of 423 (6.9 %) (E014). Only 6 of
the 29 (1.4 %) are real quotations the search missed; the rest are words the agent itself put in quotation marks
(role-play lines, satire, example prompts). Telling "is this a quote" from the report text alone does not transfer
across genres; our ≤ 2 % target is not demonstrated for arbitrary answers. The same set had 69 agent errors (16.3 %).
On our own agents. We use buddie in a Claude-based multi-agent project (Claude Code threads, an orchestrator, GitHub Actions). There it found 4 automatic task launches that the orchestrator announced before the parent change had merged, and the launch rule was changed to start only from the post-merge record. All 8 claims about PRs and CI in earlier thread reports held, and 3 of 3 deliberately false anchors were caught in a live run. Before buddie, a two-hour audit of the same threads found 14 reporting errors, and none was fixed by reasoning without going back to the source. These runs use the project's private chat, so their raw data is not published; the numbers are reported as observed.
The labellers were Claude subagents working blind to the verdicts, not humans. Verdicts were committed before labelling and rules frozen by commit before each out-of-sample run. The protocol is in docs/verbatim-method.md.
The quote module: verbatim
verbatim saves the bytes of every cited source under their SHA-256, extracts the text a reader would see, and
searches each quotation in it. Each quote is checked against its own link, the citation next to it in the same
sentence, not just any link in the paragraph.
Command | Does |
| fetch and store the bytes (failures are recorded too) |
| print the visible text of a snapshot: quote from this, not from a summary |
| verdict for every quote in a Markdown or JSON report |
| run one access method, or merge another store into yours |
Verdicts: FOUND / FOUND_NORMALIZED, HIDDEN_ONLY (only in markup the reader does not see), FOUND_IN_COPY,
UNCERTAIN, NOT_A_QUOTE, NOT_FOUND, SOURCE_UNAVAILABLE / NO_SOURCE; see
docs/verbatim-verdicts.md. --access default tries lawful routes for unreadable pages in
order: a headless browser (pip install 'buddie[browser]'), the Wayback Machine and Common Crawl, open-access copies
by DOI, known syndicated copies. verbatim never bypasses paywalls, captchas or bot protection.
Configuration
Variable | Default | Effect |
|
| snapshot store |
| on |
|
| on |
|
| none | token for the GitHub API (public repos work without one, within rate limits) |
| git repos around the working directory |
|
|
| regex marking a final answer that must carry anchors at any event; with none, the last message at |
|
| hook run log; |
|
| second log, one file per session; |
| none |
|
|
|
|
|
| the intro mode's count per |
| from the |
|
|
|
|
| on |
|
|
| context tokens past which a non-final reply is returned; |
What leaves your machine
Cited pages. To check a quote the hook downloads the page it cites (
BUDDIE_FETCH=0: stored snapshots only). Snapshots go toVERBATIM_STORE. Only--access defaultin the CLI or MCP server also asks archive.org, Common Crawl and open-access copies by DOI.GitHub API.
pr:andci:anchors callapi.github.com, withBUDDIE_GITHUB_TOKENorGITHUB_TOKENif set (BUDDIE_GITHUB=0: no calls).Nothing else: no telemetry, no model calls. The full list of what is read, sent and kept is in PRIVACY.md.
The transcript and the journal
The transcript. The hook reads the current session's transcript (transcript_path, and its subagents' files next
to it) because a claim about a command can only be checked against what the session actually ran:
⚓ run:pytest -q => 41 passed holds only if the transcript shows that call with that output. It also takes the
token count for the context gate, snapshot stores the session named, and the commands behind ready anchors from
there; the final answer at Stop comes from the event itself (last_assistant_message), and from the transcript only
when the event has none. It reads the file in place; nothing from it is copied into the journal or sent anywhere. No
other session, no memory, no chat history is read. To turn it off, set the plugin's "Read the session transcript"
option to off, BUDDIE_TRANSCRIPT=0, or [transcript] read = false in buddie.toml: answers are still checked,
and run: anchors are reported as unchecked.
The journal. Each check appends one line to BUDDIE_LOG (~/.cache/buddie/hook.jsonl): time, session id, tool,
outcome, counts of verdicts, exit code and the SHA-256 of the checked text. It never holds the text. Promise lines
(«launch №N after PR #M») keep the row, the condition and the sentence's SHA-256; choice lines (the person's pick on a
summary card or an ask_decision card) keep hashes of the picked steps and the numbers of a typed answer, and a
decision card line keeps its options' label hashes and queue numbers, which is enough for choice:<id>=<step> to be
checked. [journal] text = true in buddie.toml (or BUDDIE_JOURNAL_TEXT=1) also keeps
those sentences and answers. BUDDIE_LOG=0 turns the journal off; lessons at SessionStart then have nothing to sum.
Scope and limits
It checks that words exist in the source, not that they support the claim around them. A real quote attached to the wrong date or event still passes.
Unquoted paraphrase is not checked. Numbers are checked only in a sentence with a link, and a missing one is a gap by default (out of sample 6 of 139 checkable numbers were false
NOT_FOUND).Pages change: a verdict holds for the snapshot hash and time it names.
pr:andci:judge the state now; writemerged@SHAandci:on a SHA for history.run:trusts the transcript, which the harness writes on the same machine as the agent. Its format (Claude Code jsonl) is undocumented; other agents are not supported. A command that prints a prepared file passes: the anchor says "the command answered this", not "the test passed".Work-claim and final-answer rules match Russian and English phrasing. By default the final answer is the last message at
Stop; setBUDDIE_FINALorfinal_markto mark it in replies sent earlier.The gates cost turns: in the E016 pilot (12 tasks with traps per configuration) a session took 6.1 turns on average without buddie and 15.1 and 12.6 with the 0.4 and 0.5 gates. That pilot did not measure the main effect: there were no false "done" claims in any configuration, traps were too easy. Whether buddie makes agents misstate less is not yet measured.
Reproduce
pip install -e . pytest && pytest # 314 self-contained tests; 44 more need third-party snapshots or the lab repo and skip
python results/E008-drb2-fresh/compare.py # scripts are kept as they ran; paths assume the lab layout, see results/README.mdDevelopment happens in this repository. Until 0.8.2 it was exported by script from a private lab repository, where
the experiments in results/ were run; results/PROVENANCE.json is the record of that
last export (lab@ed8d971): every file with its SHA-256 and lab path. We do not redistribute page
snapshots, because they are other people's pages; verdict files keep each page's URL and SHA-256, so a re-fetch shows
whether the page changed. Report text from DeepResearch Bench I/II is included under its Apache-2.0 license. Sets
whose answer text we may not redistribute (ydc-deep-research-evals: no license; Search Arena: answers under the
providers' terms) are published as ids, labels, verdicts and hashes only. See NOTICE and
results/README.md.
Plugin evals
evals/ runs claude plugin eval with the plugin and without it (2 runs per arm, Claude Opus 5.5,
2026-10-20). Each case is an orchestrator passing a subagent's report on to the person:
Case | With buddie | Without | What the person got with buddie |
altered quote (two words changed) | 1.0 | 0.25 | the page's real words, with the wrong quote named as wrong |
| 1.0 | 0.0 | "merged", with a fresh |
| 1.0 | 0.0 | that CI did not pass on that commit |
honest report (control) | 1.0 | 1.0 | the report unchanged |
With the plugin the person got the truth in every trap run; without it, in none. The cost is turns: 3.7 to 5 per run against 1, about twice the price. These are four hand-made cases, two runs each, where the report is told to be passed on as written: they show what the gate does when a false claim is there, not how often agents make one.
Status
buddie 1.1.1 with verbatim 0.3.8. 1.0 fixes the interfaces: the receipt (predicateType …#receipt-v0), the CLI,
the MCP tools and buddie.toml; changes to them follow semantic versioning. It checks claims about quotes, numbers,
PRs, CI and runs against primary data. Its effect on agent behaviour is still being measured: a gate that returns a
false report does not by itself show that agents misstate less. Next: current Claude models with web search and as coding
sub-agents, measured on how often their reports misstate sources, tests or merges; and an intervention study, where the
agent runs buddie before it reports and we check whether false claims drop or the agent shifts to unverifiable wording.
Cite
See CITATION.cff.
Available Tools
4 toolssnapARead-onlyIdempotent
Snapshot URLs (bytes by sha256) so quotes can be taken from and checked against them. Call it before quoting a page, then copy the words from source_text and link the same URL.
| Name | Required | Description | Default |
|---|---|---|---|
| urls | Yes | ||
| store | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so the safety profile is covered. The description usefully adds the content-addressed storage model (bytes keyed by sha256), which implies snapshot reuse/dedup, but says nothing about retention, size limits, or failure behavior for unreachable URLs. The 'store' parameter's effect is left undisclosed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, no filler, with the core action and the call-before-quoting precondition front-loaded. Every clause earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The workflow guidance is solid for a tool with no output schema, but with two parameters at zero schema coverage and no explanation of the optional 'store' argument, an agent cannot confidently invoke it beyond the simplest case.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must carry parameter meaning. It implies 'urls' is what gets snapshotted but never says it accepts multiple URLs, and it is entirely silent on the 'store' parameter, leaving half the inputs undocumented in both schema and prose.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Snapshot URLs') plus the storage model ('bytes by sha256') and the downstream purpose (quotes can be taken from and checked against them). It orients the agent against the source_text sibling via the quoting workflow, though it does not distinguish itself from verify_report or summary.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit precondition and sequencing: 'Call it before quoting a page, then copy the words from source_text.' That is actionable when-to-use guidance tied to a sibling tool, but there is no statement of when not to use it or of alternatives for non-quoting scenarios.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
source_textBRead-onlyIdempotent
Visible text of a snapshot (URL or sha256 prefix). With grep, only the matches with context. Copy quotes from here character for character, put them in quotation marks “…” or «…», and link the snapshot's URL right after the quote in the same sentence.
| Name | Required | Description | Default |
|---|---|---|---|
| ref | Yes | ||
| grep | No | ||
| store | No | ||
| context | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint=false, so the safety profile is covered. The description adds one genuinely behavioral fact – that supplying grep narrows output to matches with surrounding context – but says nothing about truncation, size limits, or what happens when ref is unknown.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The core definition is front-loaded in the first sentence and the citation instructions are actionable rather than filler. The second half is process guidance rather than tool description, but it earns its place by constraining how results should be reproduced.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description does reasonably well at describing the shape of the return value (visible text, or only grep matches with context). For a four-parameter read tool it leaves too much unexplained – notably store, context, and any limits – to be considered fully complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% with four parameters, so the description bears the full burden. It does explain ref (URL or sha256 prefix) and how grep alters output, but 'store' and 'context' (including its default of 160) are never mentioned anywhere, leaving half the parameter surface undocumented.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific resource (the visible text of a snapshot) and clarifies the ref format as URL or sha256 prefix, so an agent knows exactly what comes back. It does not, however, differentiate itself from siblings like summary or snap, so the agent must infer when this is the right source of text.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied through the citation workflow – copy quotes character for character, wrap in quotation marks, and link the snapshot URL in the same sentence. There is no explicit statement of when to pick this over summary or verify_report, and no preconditions are named.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
summaryCRead-onlyIdempotent
When no subagent is left: the summary built by code from the hook's records (what each subagent did with its receipt outcome, who was lost, the next steps with auto/ask verdicts, open PRs and red CI) and card, a ready AskUserQuestion input with at most three steps and «Ничего не запускать». Show text as is and ask with card unchanged; launch auto steps yourself and the picked ones with the anchor ⚓ choice:<summary_id>=.
| Name | Required | Description | Default |
|---|---|---|---|
| queue | No | add the queue's proposed rows | |
| repos | No | repo checkouts with buddie.toml for the queue (default: around the cwd) | |
| stale | No | minutes before a silent subagent is lost | |
| session | No | the session id (default: the one whose state changed last) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false, and openWorldHint=false, so the safety profile is covered. The description adds real context beyond that: the summary is built from the hook's records and returns both `text` and a ready `card`, and it clarifies that launching auto/ask steps is the agent's downstream action, not a mutation by this tool. It stops short of describing filtering behavior or failure modes.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single dense run-on containing parentheticals, Russian text, and an emoji anchor marker. The purpose is buried behind the trigger condition rather than front-loaded, and the instruction payload would be clearer as separate sentences; it is over-packed rather than economical.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description partially compensates by naming the returned `text` and `card` and their contents (verdicts, lost agents, PRs, CI). But parameters are left entirely to the schema and the behavior of the queue/repos/stale inputs is never tied back to the output, leaving the picture incomplete for a tool whose returns are undocumented.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% with all four parameters (queue, repos, stale, session) documented in the schema itself. The description adds nothing about those parameters, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description does reveal that the tool produces a summary assembled by code from hook records plus a `card` (AskUserQuestion input), but it opens with a trigger condition ('When no subagent is left') rather than a clean verb+resource statement. It is distinguishable from siblings only indirectly, and the mix of purpose with post-call instructions makes the core function fuzzy.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The condition 'When no subagent is left' gives an implied trigger for calling the tool, which is useful. However, it never names or contrasts with the sibling tools (source_text, verify_report, snap), and the rest of the sentence is guidance about what to do with the output rather than when to choose this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
verify_reportRead-onlyIdempotent
Check a report before accepting or passing it on: every quote must be in the bytes of the source it links to (verbatim), every ⚓ anchor must hold in the repos, on GitHub (pr:, ci:) or in the session transcript (run:). Returns a receipt with outcome FAIL / GAPS / PASS / EMPTY, the blocking items and a one-line summary. Only quotations in quotation marks with a link to their page in the same sentence, and ⚓ anchors in backticks, are checked: write e.g. Article 2.10 says «Юридическое лицо, присоединившее другое юридическое лицо, подлежит ответственности» (КоАП РФ, ст. 2.10). EMPTY means nothing was checkable, not that the text is right.
| Name | Required | Description | Default |
|---|---|---|---|
| path | No | a Markdown file to check instead of text | |
| text | No | the report itself (Markdown); or give path | |
| fetch | No | snapshot cited URLs not in the store yet | |
| repos | No | repo checkouts for anchors (default: the git repo at or under the server's cwd; in Codex none, so pass the workspace path) | |
| store | No | snapshot store (default $VERBATIM_STORE or ./.verbatim) | |
| access | No | verbatim --access for unreadable pages, e.g. 'default' | |
| checks | No | custom: these checks (quote, number, file_anchor, commit_anchor, fact_anchor, pr_anchor, ci_anchor, run_anchor, choice_anchor, work_claim, other_anchor) | |
| github | No | ask GitHub for pr:/ci: anchors | |
| modules | No | custom: these verification modules: sources (quotes, numbers), github (repo anchors, pr:, ci:), execution (run:, choice:, work claims) | |
| numbers | No | a number of a cited sentence not in its source: gap, fail or off | gap |
| profile | No | what to check (default: everything): developer (repo, PR, CI, run: and work claims), research (quotes and numbers), complete, or custom with modules and/or checks. What a profile leaves out is not checked, and the result says so | |
| receipt | No | receipt contract of the result: v0 (default) or v1, which also says what was checked, what was not and why (scope, coverage) | v0 |
| transcript | No | Claude Code session jsonl for run: anchors |
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
1 tool update
v1.1.1- Changed
verify_report4 fields changed- added
Input schema / properties / checksAdded value: +{ + "description": "custom: these checks (quote, number, file_anchor, commit_anchor, fact_anchor, pr_anchor, ci_anchor, run_anchor, choice_anchor, work_claim, other_anchor)", + "items": { + "type": "string" + }, + "type": "array" +} - added
Input schema / properties / modulesAdded value: +{ + "description": "custom: these verification modules: sources (quotes, numbers), github (repo anchors, pr:, ci:), execution (run:, choice:, work claims)", + "items": { + "enum": [ + "sources", + "github", + "execution" + ], + "type": "string" + }, + "type": "array" +} - added
Input schema / properties / profileAdded value: +{ + "description": "what to check (default: everything): developer (repo, PR, CI, run: and work claims), research (quotes and numbers), complete, or custom with modules and/or checks. What a profile leaves out is not checked, and the result says so", + "enum": [ + "developer", + "research", + "complete", + "custom" + ], + "type": "string" +} - added
Input schema / properties / receiptAdded value: +{ + "default": "v0", + "description": "receipt contract of the result: v0 (default) or v1, which also says what was checked, what was not and why (scope, coverage)", + "enum": [ + "v0", + "v1" + ], + "type": "string" +}
4 tool updates
v1.0.0- First observed
snap - First observed
source_text - First observed
summary - First observed
verify_report
TDQS
Scored across 4 tools
Each tool targets a different stage: snap creates snapshots, source_text retrieves quotable text, verify_report validates quotes/anchors, and summary reports subagent session outcomes. Their descriptions cross-reference each other, but the core actions are distinct enough to avoid misselection.
All names use lowercase snake_case and are readable, but the set mixes verb-led (verify_report), noun-phrase (source_text), bare verb (snap), and bare noun (summary) forms. There is no single predictable verb_noun pattern.
Four tools is a tight, well-scoped set for a snapshot/verification workflow. Each tool has a clear role and none appear redundant or missing for the stated purpose.
The set covers creating snapshots, extracting quotable text, verifying reports, and summarizing subagent sessions. It may lack explicit listing or searching of existing snapshots/reports, but the core lifecycle is present and workable.
Maintenance
Related MCP Connectors
Verifies AI agent work end to end: real artifacts and outcomes checked, not self-reported success.
Watchdog for unattended AI agents: alerts, evidence checks and a verifiable proof per run.
Deterministic fact verification for AI agents — checksums & curated data, not guesses.
Website checker for AI coding agents. Measures your site in a real browser, with evidence.
Related MCP Servers
- AlicenseAqualityBmaintenanceMCP server for verifying AI agent claims vs reality — single-transcript inline grounding-check that flags when an agent's response states facts not in the input context, when its code silently swallows exceptions and substitutes mock data, or when its multi-turn transcript contains contradictions or unverified completion claims. Sub-second, local, free, no API calls.458 PyPI1MIT
- AlicenseNot gradedqualityCmaintenanceEnables AI agents to run evidence QC gates mid-workflow—checking claims, sources, prose, and vault hygiene deterministically before research ships.MIT
- AlicenseAqualityAmaintenanceOpen-source verification for evidence-grounded AI. Runs deterministic grounding checks of AI outputs against source evidence, with no LLM judge.2161 npm1MIT
- AlicenseAqualityAmaintenanceEnables Claude to independently check an AI agent's work in a local git repository by recording a baseline, running only the checks relevant to the changed files, and cross-checking what the agent claimed. Returns a compact, evidence-labelled report with a verdict and a ready-to-paste next prompt, so unverified success claims can't slip through.8MIT