Skip to content

Feishu: read image tool result loses media before final outbound payload #41744

@wangyaok1

Description

@wangyaok1

Feishu: read image tool result loses media before final outbound payload

Summary

When an agent uses the read tool to read a local image and then replies in a Feishu conversation, the image can be successfully read, but the final outbound reply may lose the media attachment before delivery.

In the affected environment:

  • read successfully returned image content for /absolute/path/to/test.png
  • the runtime successfully extracted the media path
  • Feishu sendMedia works and can send the image successfully
  • but the final reply payload originally ended up with mediaUrl: null

This points to a failure inside OpenClaw's internal tool-result-to-final-payload pipeline, not a Feishu permission or bot capability problem.

Environment

  • OpenClaw CLI/Gateway version: 2026.2.26
  • Node.js: v22.22.0
  • OS: macOS darwin 25.2.0
  • Channel: Feishu websocket mode

Reproduction

  1. Start OpenClaw Gateway with Feishu enabled.
  2. In a Feishu DM, ask the agent to use the read tool on a local image and send that image back directly.
  3. Observe:
    • the read tool returns image content successfully
    • the assistant may even mention a MEDIA: path in text
    • but the user receives only text, and no image

Expected

Once read returns an image tool result with a resolvable local media path, the final reply payload delivered to Feishu should contain that media path and trigger Feishu sendMedia.

Actual

Before the local patch, the final result payload looked like this:

{
  "text": "",
  "mediaUrl": null
}

Even though the tool result had already identified the image and the runtime could extract the media path.

Root Cause

The core issue appears to be in the embedded run / final payload assembly path.

OpenClaw correctly extracts tool-result media during tool handling, but that media was not reliably preserved into the final outbound payload that is later delivered to Feishu.

In practice, this means:

  1. read image tool result exists
  2. media path extraction succeeds
  3. final payload assembly drops the tool-result media
  4. Feishu delivery receives text-only payload or mediaUrl: null

Relying on MEDIA:/absolute/path as a text fallback is not sufficient, because the runtime security policy blocks absolute MEDIA:/... directives in normal reply parsing.

Local Fix That Worked

The runtime bundle in use was patched so that:

  1. tool-result media paths are stored in run state when extracted
  2. final payload assembly merges those stored media paths into the final assistant reply payload

After this patch, the final result contained:

{
  "mediaUrl": "/absolute/path/to/test.png",
  "mediaUrls": [
    "/absolute/path/to/test.png"
  ]
}

And Feishu logs showed:

[FEISHU-MEDIA] tool=read mediaPaths=["/absolute/path/to/test.png"]
[feishu] sendMedia 调用: mediaUrl=/absolute/path/to/test.png...
[feishu] sendMedia 成功

Suggested Upstream Fix

In the embedded run pipeline, preserve tool-result media independently of model-generated final text.

Specifically:

  • when emitToolResultOutput() extracts media paths from a trusted tool result, keep them in per-run state
  • when buildEmbeddedRunPayloads() constructs final reply items, merge any pending tool-result media into the final payload

This avoids depending on:

  • whether onToolResult is wired in a specific path
  • whether the model echoes a MEDIA: directive
  • whether text parsing strips or blocks absolute local paths

Why This Should Be Fixed Upstream

This is not just a local Feishu setup issue. The runtime behavior itself loses media between tool result handling and final reply construction.

That makes image-returning tools unreliable for Feishu delivery unless the install is manually patched.

Related context

This appears related to other Feishu/local-media delivery issues, but the failure here is specifically about read tool media being lost before final outbound payload assembly, rather than a direct message tool upload failure.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions