Skip to content

[Feature]: Add a generic outbound artifact delivery guard #77448

@sercada

Description

@sercada

Summary

Add a channel-neutral outbound artifact delivery guard that turns validated generated file/media references into real attachments and strips unsafe raw path/directive text from the final chat.

Problem to solve

File-generating agent workflows can end with text such as MEDIA:./exports/report.xlsx, File: /workspace/exports/report.xlsx, file://..., or structured assistant content/metadata that carries media URLs separately from final prose. If that path is not normalized and delivered through the channel attachment path, the user may see a raw local path or a claim that a file was attached when no attachment was actually sent.

Prompt-only guidance and per-skill conventions are not enough because this is a final-mile transport invariant: the system needs to know whether the attachment actually delivered before deciding whether to strip, keep, or replace the final text.

Proposed solution

Introduce an upstream, generic guard/hook near outbound reply rendering and channel delivery:

  • Inspect assistant final text, structured text blocks, and parsed media metadata for local generated-artifact references.
  • Validate references against narrow configurable roots, e.g. workspace exports plus explicit generated-media roots.
  • Deliver validated artifacts through the existing channel attachment/media adapter.
  • Strip raw MEDIA:/local-path delivery text only after concrete send success.
  • On delivery failure, avoid silently claiming success; emit a safe user-facing failure payload and retain useful logs/metadata for debugging.
  • Cover with a synthetic channel test that exercises raw text, structured text blocks, metadata media, success stripping, and failure fallback.

This should stay channel-neutral. Telegram can be one supported channel, but the core behavior should not be a Telegram-specific patch.

Alternatives considered

  • Prompt instructions: cheap but unreliable; models and skills still leak raw paths.
  • Per-skill wrappers only: helpful, but any new skill/tool can miss the contract.
  • Telegram-only middleware: fixes one transport while leaving the same bug class in other channels.
  • Leaving raw paths in final text: debuggable for developers, but wrong for end users and unsafe for hosted/sandboxed paths.

Impact

Affected users/systems/channels:

  • Agents that create documents, images, audio, PDFs, spreadsheets, or other artifacts.
  • Multi-channel deployments where the same agent can answer over Telegram, Slack, web chat, or other transports.

Severity: medium to high for artifact-heavy workflows because users can believe a file was sent when it was not, or receive unusable local paths.

Frequency: intermittent but recurring in workflows where tools emit final text plus file paths/media directives.

Consequence: failed deliveries, raw local path leakage, extra manual re-uploading, and brittle per-skill workarounds.

Evidence/examples

In a private OpenClaw deployment, a downstream guard proved useful by catching these cases before final chat delivery:

  • raw text MEDIA:./exports/...
  • final text blocks containing MEDIA:
  • parsed metadata.mediaUrls
  • local-path claims such as Archivo: /workspace/exports/file.xlsx
  • audio plus document delivery in the same assistant message

The implementation is deployment-specific today, so I am opening this as an upstream design issue first rather than proposing a direct copy into core.

Additional information

This pairs well with transcript hygiene: raw delivery directives are transport instructions, not durable assistant prose. A follow-up PR could start with a small generic parser/guard and synthetic-channel tests once the maintainers agree on the hook location.

Metadata

Metadata

Assignees

No one assigned

    Labels

    staleMarked as stale due to inactivity

    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