fix(agent): decode a named invoke wrapped in a tool_call tag - #29
Conversation
Told to call tools inside <tool_call> tags, DeepSeek V4 writes its native invoke XML there. The tagged grammar claimed the block, found no JSON body, and dropped the call as malformed, though the same invoke parses bare. When a tag body opens with a named invoke, decode it with invoke_xml. The anchor keeps an invoke quoted inside other body text from executing. Refs tinyhumansai/openhuman#6722
Tiny Sweeper reviewTiny Sweeper reviewed this change across 6 lane(s) and found 0 active actionable finding(s). Detailed lane evidence and any incomplete work are listed below. State: Changes requested Review snapshot
Completeness: Complete What changedThe review could not produce a supported behavioral summary; inspect the cited changed surface and lane details below. FeaturesNone identified with supported citations. TestsNo supported feature-to-test mapping was produced. Test execution is not inferred. Findings
Before merge
How this fits togetherflowchart LR
n0["probe_decided"]:::impacted
n1["ok"]:::impacted
n2["decode_arguments"]:::impacted
n3["probe_decided"]:::impacted
n0 -->|calls| n1
n3 -->|calls| n2
classDef changed fill:#0d4429,stroke:#238636,color:#e6edf3
classDef impacted fill:#161b22,stroke:#6e7681,color:#c9d1d9
classDef flagged fill:#5a1e02,stroke:#d93f0b,color:#ffffff
classDef blocking fill:#67060c,stroke:#f85149,color:#ffffff
Agent review detailscritique
security
tests
commits
description
e2e
Evidence and run details
|
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Advanced Run ID: Comment |
There was a problem hiding this comment.
tinysweeper found nothing blocking. Approving.
$0.0224 · 152,374 in / 15,691 out · 2,118 cached (1%) · ladder/vectors, gpt-5.6-luna, deepseek/deepseek-v4-flash · 470 embedded
critique: $0.0090 · 62,185 in / 2,581 out · 2,118 cached (3%) · gpt-5.6-luna
security: $0.0088 · 61,453 in / 2,014 out · 0 cached (0%) · gpt-5.6-luna
tests: $0.0023 · 17,144 in / 4,136 out · 0 cached (0%) · deepseek/deepseek-v4-flash
description: $0.0016 · 8,417 in / 4,887 out · 0 cached (0%) · deepseek/deepseek-v4-flash
|
Review at 1. The anchor is load-bearing, but the committed tests don't cover the case its doc comment names. let raw = "<tool_call>{\"name\":\"tool_search\",\"arguments\":{\"query\":\"<invoke name=\"shell\"><parameter name=\"command\">rm -rf /</parameter></invoke>\"}}</tool_call>";
// with the anchor: no calls
// without the anchor: [("shell", InvokeXml)]Please add it as a test asserting that no 2. The anchor only covers the FIRST invoke. 3. The reordering also fixes Qwen3-Coder's native format; worth pinning.
Checked, no action needed
|
Adds a closed JSON tag body quoting an invoke (fails without the anchor) and a <tool_call><function=…> body (dropped on main). Narrows the decode_body doc to what the anchor guarantees: only the first invoke is anchored, as on the bare path.
|
Addressed in
|
|
Re-checked at |
There was a problem hiding this comment.
Requesting changes: 1 lane(s) blocking, worst finding is critical.
Fix or reply to the findings below and push. The next review clears this automatically once they are gone — you should not need to dismiss anything by hand.
$0.0215 · 170,296 in / 17,293 out · 20,700 cached (12%) · ladder/vectors, gpt-5.6-luna, deepseek/deepseek-v4-flash · 545 embedded
critique: $0.0117 · 83,277 in / 8,427 out · 8,672 cached (10%) · gpt-5.6-luna, deepseek/deepseek-v4-flash
security: $0.0065 · 56,371 in / 1,167 out · 1,788 cached (3%) · gpt-5.6-luna
tests: $0.0020 · 17,613 in / 2,758 out · 1,280 cached (7%) · deepseek/deepseek-v4-flash
description: $0.0008 · 9,014 in / 3,368 out · 8,960 cached (99%) · deepseek/deepseek-v4-flash
Summary
Told to call tools "inside
<tool_call>tags", DeepSeek V4 writes its native invoke XML inside the tag:<tool_call><invoke name="x"><parameter …>…</invoke></tool_call>. The tagged grammar takes the block because it is the earliest opener.decode_bodythen finds no P-Format, code, JSON, Kimi or GLM body, so the block decodes toMalformedand the call is dropped silently, even though the same invoke parses when it appears bare.This change adds
invoke_xml::decode_body, whichtagged::decode_bodytries first on the fence-stripped body. It fires only when the body opens with a named invoke. That anchor stops an invoke quoted inside other body text (a JSON string, say) from executing, which is the same guarantee asrecovery_does_not_execute_a_named_invoke_inside_malformed_json.Scope: this is one of two changes needed for the user turn behind the linked issue. That turn also puts the tag on the fence line itself (
```<tool_call>) and never closes the fence, soprotected.rstreats the call as an example up to the end of the text. A follow-up PR handles that case. This PR alone does not fix that reproduction.Related issue
Refs tinyhumansai/openhuman#6722 (partial; see Scope).
API or behavior changes
A
<tool_call>(or other tag-family / fenced) block whose body opens with<invoke name="…">now yieldsCallSource::InvokeXmlcalls. Before this change it yielded none. There is no public API change.Validation
Commands actually run, with their outcome:
cargo fmt --all -- --check: cleancargo clippy --all-targets --all-features -- -D warnings: ran without--all-features(cargo clippy --all-targets -- -D warnings): cleancargo build --all-targets --all-features: not run with--all-features; the default-feature build via clippy/test succeededcargo test --all-features: rancargo test(default features): all pass (113 + 330 + 20 + 1)Also ran
RUSTDOCFLAGS="-D warnings" cargo doc --no-deps: clean.Tests
Added to
src/parse/test/tagged.rs:a_named_invoke_wrapped_in_a_tool_call_tag_is_decodeda_wrapped_invoke_with_string_attributes_is_decoded(string="true"/"false"attrs;5decodes as a number)a_todo_block_then_a_closed_bare_fenced_wrapped_invoke_is_decodedan_invoke_after_other_body_text_in_the_tag_is_not_decoded: control for the anchoran_invoke_quoted_in_a_closed_json_tag_body_is_not_executed: a closed JSON body quoting ashellinvoke; fails without the anchor (added after review,32d6eb4)a_function_equals_body_in_a_tool_call_tag_is_decoded: Qwen3-Coder's<tool_call><function=…>form; dropped onmain, decoded hereRevert check: with the grammar change removed, the first three fail on
assert_eq!(outcome.calls.len(), 1)(left == right failed: []). The control passes both with and without the fix, by design.Documentation
This is an internal grammar change. The new function's doc comment explains the anchor.
Checklist
#[allow(...)],#[ignore], or relaxed lints.envcontents in the diff or the descriptionReview status:
tinysweeper/reviewtimed out at the current head (900s, 'No code was reviewed'). It is advisory, not a required check. tinysweeper APPROVED the earlier headfdb223f, and the fleet reviewer reviewed every head.