quotes
Find where users quoted prior agent messages and what they commented, by matching verbatim text in session history.
Instructions
User quotes of prior in-session content — the quotes preset.
One call answers "where did the user quote something the agent said, and
what did they say about it?". When a user selects a chunk of a prior
message and comments on it (the "attach selection as context" flow), the
quoted text is embedded VERBATIM in their turn — no agent records it as a
structured field — so it is recovered by matching the user turn against the
text before it. A preset over the existing core, not a second engine:
query scans supply user turns + assistant turns, the reviewed text is
normalized (_normalize_rendered_text, reused from the plan-feedback
anchorer) and :func:difflib.SequenceMatcher finds the longest verbatim
run; a run below the minimum is not a quote (honest null), and text
pasted from OUTSIDE the session matches nothing (never fabricated).
This is the cross-agent, chat-wide generalization of plan(feedback)
(which surfaces «plan quote → user comment» only for Claude's plan-approval
flow): quotes surfaces «any prior message quote → user comment» for
every agent, operating on the normalized event stream, not client markup.
Filters (all parameters): agent, session (uuid or list),
since/until (ISO bounds on the user turn's ts), source_kind
(currently assistant — a user quoting the agent's prose; unknown values
fail loud), noise and project_dir (session-level, same as
query).
Each record carries the user_turn event id (context on-demand via
query(relative_to=...)), source_id (the quoted assistant turn),
source_kind, quote_chars, and the char-capped quote + comment
(the user's turn with the quote elided). count/by_source_kind
reflect the FULL matched set; limit (default 50, 0 = no cap) bounds
only the emitted records (truncated).
Caveat (documented): v1 sources are assistant prose (the common case —
quoting a tool's raw output is a future extension); the emitted
quote/comment come from the NORMALIZED text (markdown stripped), so
they are readable but not byte-identical to the raw turn (raw bodies stay
reachable via the event ids). redact=true (default) masks secrets only
in the emitted session_title/quote/comment. When count == 0
the response carries diagnostics so an empty result is explainable.
Thin wrapper over :func:ai_r.quotes.quotes that translates the core
ValueError contract into the {"error": "invalid_argument", "message": str(exc)} shape the MCP client expects.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| agent | No | ||
| limit | No | ||
| noise | No | include | |
| since | No | ||
| until | No | ||
| redact | No | ||
| session | No | ||
| project_dir | No | ||
| source_kind | No |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||