{"slug": "my-ai-assistant-could-see-the-screenshot-feishu-still-got-no-image", "title": "\"My AI Assistant Could See the Screenshot. Feishu Still Got No Image\"", "summary": "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.", "body_md": "The most confusing delivery bug is not when an image upload fails loudly.\n\nIt is when the assistant can clearly see the screenshot, tells you it is sending it, and the chat still gets no image.\n\nThat is the bug I ran into while working on [CliGate](https://github.com/codeking-ai/cligate), my local control plane for a resident assistant, channel workflows, desktop automation, and AI tool routing.\n\nThe screenshot existed.\n\nThe assistant had the artifact.\n\nDingTalk could already receive images.\n\nBut Feishu and Telegram still behaved like the image had vanished somewhere between \"I have it\" and \"I sent it.\"\n\nThe obvious place to look was the channel provider layer.\n\nThat made sense at first.\n\nFeishu needs image bytes uploaded first so it can return an `image_key`\n\n. Telegram can accept a file upload through `sendPhoto`\n\n. So the initial assumption was simple:\n\n`feishu-provider.js`\n\n`telegram-provider.js`\n\nBut that was only half the path.\n\nThe real outbound flow looked more like this:\n\n``` php\nassistant tool\n  -> delivery sender\n  -> provider\n  -> channel chat\n```\n\nAnd the bug was hiding earlier than I expected.\n\nCliGate has an assistant tool called `send_message_to_channel`\n\n.\n\nThat tool decides whether a channel is image-capable before it forwards payloads into the delivery path.\n\nThe critical line was basically this:\n\n``` js\nconst effectiveImages = imageSupported ? images : [];\n```\n\nThat sounds harmless until your capability map is wrong.\n\nIn my case, the tool-level allowlist still treated only DingTalk as image-capable.\n\nSo 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.\n\nThat is why this kind of bug is so misleading.\n\nThe model is not hallucinating the screenshot.\n\nThe provider is not necessarily broken.\n\nThe payload is being amputated one layer upstream.\n\nThere was a second detail that mattered.\n\nCliGate runs locally on `localhost`\n\n, and assistant-generated images can exist as:\n\n`data:`\n\nURL`localhost`\n\nURLThat matters because Feishu and Telegram do not treat image inputs the same way.\n\nFeishu wants uploaded bytes first, then an `image_key`\n\n.\n\nTelegram can fetch some public URLs remotely, but a `localhost`\n\nURL is useless to Telegram's servers.\n\nSo \"just pass the URL through\" is not a reliable local-first strategy.\n\nThe safer rule became:\n\n``` php\nresolve image bytes locally\n-> upload from CliGate itself\n-> send the provider-specific image payload\n```\n\nThat means:\n\n`image_key`\n\n, send image message`sendPhoto`\n\nIn other words, the fix was not only \"mark these channels as image-capable.\"\n\nIt was also \"make the provider implementation match local-first reality.\"\n\nThe lesson was that channel capability is not one boolean in one file.\n\nIt is an agreement across layers.\n\nFor this bug, the useful fix had three parts:\n\nOnce those lined up, the behavior stopped being weird.\n\nIf the assistant has an image artifact, the delivery layer now keeps it intact long enough for the right provider to do the right thing.\n\nThat sounds small, but it changes the user experience a lot.\n\nA screenshot is usually the proof that the task really happened.\n\nIf the text says \"I sent the screenshot\" but the image never arrives, trust drops immediately.\n\nWhen an agent sends files, screenshots, or generated images into chat, do not debug only the provider.\n\nTrace the whole delivery path:\n\nThat is now one of my standing checks for CliGate.\n\nThe bug looked like \"Feishu and Telegram cannot send images.\"\n\nThe real problem was subtler:\n\nthe assistant pipeline and the provider capabilities had drifted apart.\n\nThe project is open source here: [CliGate on GitHub](https://github.com/codeking-ai/cligate).\n\nIf you are building local agents with chat delivery, where would you put the capability check: in the tool layer, the provider, or both?", "url": "https://wpnews.pro/news/my-ai-assistant-could-see-the-screenshot-feishu-still-got-no-image", "canonical_source": "https://dev.to/codekingai/my-ai-assistant-could-see-the-screenshot-feishu-still-got-no-image-2pej", "published_at": "2026-07-08 07:23:23+00:00", "updated_at": "2026-07-08 07:28:21.518142+00:00", "lang": "en", "topics": ["ai-agents", "developer-tools", "artificial-intelligence"], "entities": ["CliGate", "Feishu", "Telegram", "DingTalk", "GitHub"], "alternates": {"html": "https://wpnews.pro/news/my-ai-assistant-could-see-the-screenshot-feishu-still-got-no-image", "markdown": "https://wpnews.pro/news/my-ai-assistant-could-see-the-screenshot-feishu-still-got-no-image.md", "text": "https://wpnews.pro/news/my-ai-assistant-could-see-the-screenshot-feishu-still-got-no-image.txt", "jsonld": "https://wpnews.pro/news/my-ai-assistant-could-see-the-screenshot-feishu-still-got-no-image.jsonld"}}