You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit dc2f2fc
Browse filesBrowse the repository at this point in the historyBrowse files
feat(message): carry a tool result's trusted-verbatim request into the transcript (#77)
* feat(message): carry a tool result's trusted-verbatim request into the transcript
A `ToolResult` can hold structured metadata in `raw`, but folding it into the
transcript goes through `Message::tool(call_id, content)`, which keeps only
those two fields. Everything else is dropped at that boundary, so a host has no
way to learn anything the tool wanted to say about its own output.
That matters for one property in particular: whether the content may be
reshaped. Hosts summarise, truncate, batch, and re-frame tool output, and
usually should — but some results are only useful intact. An input schema whose
argument names the model must copy exactly, a signature, a diff: rewriting those
produces content that still reads well and is wrong. Today a host can only guess
from the text, and guessing wrong is silent.
Add an explicit, opt-in request:
- `ToolResult::mark_trusted_verbatim()` / `is_trusted_verbatim()`, backed by
`raw` under `TRUSTED_VERBATIM_KEY`, so the opt-in costs nothing for results
that never use it and round-trips through a host's own serialization.
- `ToolMessage.trusted_verbatim: bool`, `#[serde(default)]` so transcripts
persisted before this field still deserialize (and read as not-trusted).
- `Message::tool_from_result(&ToolResult)`, which carries the flag across; the
agent-loop fold site now uses it.
The flag is advisory: the crate transports it, honouring it is the host's job.
`Message::tool` is unchanged and still sets `false`, so nothing moves for
callers that do not opt in.
Tests cover the opt-in being off by default, idempotent marking that preserves
unrelated `raw` metadata, non-boolean or non-object `raw` never tripping it,
`tool_from_result` matching `tool` for an unmarked result, and a pre-field
transcript still loading.
Verified: `cargo fmt --check`, `cargo clippy --all-targets -- -D warnings`,
`cargo build --all-targets`, `cargo test` (1205 lib tests + suites), and
`cargo run --example basic_graph`.
* fix(tool): report a refused trusted-verbatim request; omit the unset flag
Both review bots flagged the same defect, and they were right: when `raw`
already held a non-object value, `mark_trusted_verbatim` did nothing at all.
`get_or_insert_with` returns the existing scalar, `as_object_mut()` gives
`None`, and the insert was skipped — with no return value, no panic, and no
diagnostic. `is_trusted_verbatim()` then kept answering `false` while the tool
author believed the opt-in had taken effect.
The flag lives under a key in `raw`, so a scalar genuinely has nowhere to put
it, and clobbering a value the tool deliberately set would be worse. So the
request is now *refused and reported* rather than silently lost:
`mark_trusted_verbatim` returns `bool`, and is `#[must_use]` precisely because
the failure is otherwise invisible. A tool that wants both can move its value
under a key of its own and call again.
Second finding: the field serialized as `"trusted_verbatim":false` on every
tool message, which contradicts this change's own "costs nothing unless you opt
in" claim and diverges from the rest of the crate. Added
`skip_serializing_if`, reusing the `is_false` helper convention already used by
`graph::export::types` rather than an inline `std::ops::Not::not`.
Tests: a new regression case walks a string, an array, and a number `raw`,
asserting each refuses, leaves the tool's own value untouched, and that the
call succeeds once room is made; a new wire test pins that an unset flag is
omitted and a set one is present. The existing tests now assert the return
value instead of discarding it — `#[must_use]` caught all three call sites.
Verified: fmt, clippy (both feature sets), build (both), `cargo test` (1207),
`cargo test --all-features`, and `cargo run --example basic_graph`.
---------
Co-authored-by: user <user@localhost.localdomain>
0 commit comments