cd /news/ai-agents/my-ai-assistant-could-see-the-screen… · home topics ai-agents article
[ARTICLE · art-50678] src=dev.to ↗ pub= topic=ai-agents verified=true sentiment=· neutral

"My AI Assistant Could See the Screenshot. Feishu Still Got No Image"

A developer working on CliGate, a local control plane for AI assistants, discovered a bug where Feishu and Telegram failed to receive images even though the assistant confirmed sending them. The root cause was a capability check in the assistant tool layer that silently stripped image payloads before they reached the providers. The fix required aligning capability flags across layers and implementing local-first image upload logic.

read3 min views1 publishedJul 8, 2026

The most confusing delivery bug is not when an image upload fails loudly.

It is when the assistant can clearly see the screenshot, tells you it is sending it, and the chat still gets no image.

That is the bug I ran into while working on CliGate, my local control plane for a resident assistant, channel workflows, desktop automation, and AI tool routing.

The screenshot existed.

The assistant had the artifact.

DingTalk could already receive images.

But Feishu and Telegram still behaved like the image had vanished somewhere between "I have it" and "I sent it."

The obvious place to look was the channel provider layer.

That made sense at first.

Feishu needs image bytes uploaded first so it can return an image_key

. Telegram can accept a file upload through sendPhoto

. So the initial assumption was simple:

feishu-provider.js

telegram-provider.js

But that was only half the path.

The real outbound flow looked more like this:

assistant tool
  -> delivery sender
  -> provider
  -> channel chat

And the bug was hiding earlier than I expected.

CliGate has an assistant tool called send_message_to_channel

.

That tool decides whether a channel is image-capable before it forwards payloads into the delivery path.

The critical line was basically this:

const effectiveImages = imageSupported ? images : [];

That sounds harmless until your capability map is wrong.

In my case, the tool-level allowlist still treated only DingTalk as image-capable.

So even if I taught Feishu and Telegram providers how to upload and send images, the assistant tool was silently stripping the image array before the providers ever received it.

That is why this kind of bug is so misleading.

The model is not hallucinating the screenshot.

The provider is not necessarily broken.

The payload is being amputated one layer upstream.

There was a second detail that mattered.

CliGate runs locally on localhost

, and assistant-generated images can exist as:

data:

URLlocalhost

URLThat matters because Feishu and Telegram do not treat image inputs the same way.

Feishu wants uploaded bytes first, then an image_key

.

Telegram can fetch some public URLs remotely, but a localhost

URL is useless to Telegram's servers.

So "just pass the URL through" is not a reliable local-first strategy.

The safer rule became:

resolve image bytes locally
-> upload from CliGate itself
-> send the provider-specific image payload

That means:

image_key

, send image messagesendPhoto

In other words, the fix was not only "mark these channels as image-capable."

It was also "make the provider implementation match local-first reality."

The lesson was that channel capability is not one boolean in one file.

It is an agreement across layers.

For this bug, the useful fix had three parts:

Once those lined up, the behavior stopped being weird.

If the assistant has an image artifact, the delivery layer now keeps it intact long enough for the right provider to do the right thing.

That sounds small, but it changes the user experience a lot.

A screenshot is usually the proof that the task really happened.

If the text says "I sent the screenshot" but the image never arrives, trust drops immediately.

When an agent sends files, screenshots, or generated images into chat, do not debug only the provider.

Trace the whole delivery path:

That is now one of my standing checks for CliGate.

The bug looked like "Feishu and Telegram cannot send images."

The real problem was subtler:

the assistant pipeline and the provider capabilities had drifted apart.

The project is open source here: CliGate on GitHub.

If you are building local agents with chat delivery, where would you put the capability check: in the tool layer, the provider, or both?

── more in #ai-agents 4 stories · sorted by recency
── more on @cligate 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/my-ai-assistant-coul…] indexed:0 read:3min 2026-07-08 ·