fix: deliver cron MEDIA tags as native attachments#4517
Conversation
- extract MEDIA tags in cron scheduler before platform delivery - pass cleaned text and media_files into send_message_tool - add regression test for cron MEDIA extraction
8596488 to
700dc40
Compare
Investigation findings (Apr 3, 2026)Test setup pitfall discoveredThe MEDIA extraction fix is correct, but test/validation cron jobs were failing completely (not just showing raw text) because Gateway restartAfter patching Argus cron job behaviorThe Status
|
|
Your core fix (adding extract_media to the delivery path) was already merged in PR #5598. The remaining live adapter path issue was fixed in PR #5921 with credit to all contributors. Thanks @boobutler! |
Summary
Cron-scheduled deliveries to Telegram were sending raw
MEDIA:/path/to/filetext instead of native image attachments. This fix routes cron delivery through the same media extraction path used by live chat responses.Root Cause
_deliver_result()incron/scheduler.py(line 209) passeddelivery_contentdirectly to_send_to_platform()without extractingMEDIA:tags first. The live chat path handles this viaBasePlatformAdapter.extract_media(), but the cron delivery path bypassed it entirely — so Telegram users received the literal tag string instead of an attached image.Evidence from gateway.error.log:
The error log shows the path was mangled into one long string with embedded newlines, proving the raw content was sent instead of extracting individual MEDIA lines.
Investigation
The 2026-04-03 Argus morning scan (job
d7d7376d595b) ran at 10:06 AM and produced a valid report with 4 charts generated in/tmp/analyst/charts/:oil_30min.pngnear_7d.pnggrass_7d.pngsilver_30min.pngThe response saved to
cron/output/d7d7376d595b/2026-04-03_10-06-05.mdshows proper MEDIA tags in the output (lines 386-389). The agent did its part perfectly — the failure was entirely in the delivery plumbing.Fix
BasePlatformAdapter.extract_mediain_deliver_result()and call it ondelivery_contentafter optional wrapping.cleaned_content(tags stripped) andmedia_files(extracted paths) into_send_to_platform()for both the normalasyncio.runpath and theThreadPoolExecutorfallback.Testing
test_delivery_extracts_media_before_sendingintests/cron/test_scheduler.pyto verifyMEDIA:tags are stripped from sent text and forwarded asmedia_files.media_files == []when no tags are present.source venv/bin/activate && python -m pytest tests/cron/test_scheduler.py -q -n0 -k \"TestDeliverResultWrapping\"6 passed, 34 deselectedNotes
deliver: "telegram"(no chat ID) are silently skipped whenTELEGRAM_HOME_CHANNELenv var is not set — usedeliver: "origin"ordeliver: "telegram:<chat_id>"for explicit targeting.