devin: function_result conversion fails on structured, empty, and orphaned results

Author: luyishuiCreated Sep 17, 2026Updated Sep 17, 2026
LabelsFixed

Is it a request payload issue? [x] Yes. A function_result whose function_call was trimmed from the request history fails the whole upstream call.

Describe the bug

Three failure modes in parseInteractionsPayload when projecting tool results into Devin prompts (source=4).

  1. Structured results go up as raw JSON.

    When result/output/content is an array of content blocks or an object (the usual Claude tool_result shape), the raw JSON string becomes the prompt text, so the model reads [{"type":"text","text":"..."}] scaffolding instead of the tool output.

  2. Empty results go up as an empty string.

    If result, output, and content are all absent or empty, the prompt text is "". The upstream rejects empty tool-result text.

  3. Results with no matching call go up with a dangling tool_call_id.

    A function_result whose call_id/id has no pending emitted function_call (a compressed or truncated history) is emitted as source=4 with an empty or unresolvable tool_call_id, and the upstream rejects the whole request with invalid_argument. Pairing is positional upstream, so a result with nothing left to consume has to be sent as user text instead.

    The raw messages fallback has the same problem baked in: it ignores assistant.tool_calls, so every role=tool message on that path is an orphan by construction.

Request Information A chat request carrying a function_result (or role=tool message) whose preceding function_call was trimmed by history compaction reproduces bug 3: the upstream answers invalid_argument.

Expected behavior

  • structured results are projected to plain text
  • empty results get a placeholder instead of ""
  • results without a pending call are sent as user text, not a dangling source=4 prompt

Source: router-for-me/CLIProxyAPI