hermes - ✅(Solved) Fix Cron job deliver=['telegram'] fails: no delivery target resolved [4 pull requests, 1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
NousResearch/hermes-agent#17139Fetched 2026-04-29 06:37:08
View on GitHub
Comments
1
Participants
2
Timeline
10
Reactions
0
Author
Timeline (top)
cross-referenced ×4labeled ×4commented ×1referenced ×1

Error Message

This happens consistently across all cron jobs that target Telegram, including jobs that have been running successfully for weeks. The jobs complete successfully (output is saved to ~/.hermes/cron/output/), but the Telegram delivery step always fails with the same error.

Fix Action

Fixed

PR fix notes

PR #3: fix: resolve 7 identified issues [automated]

Description (problem / solution / changelog)

Summary

This PR resolves 7 issues identified in the NousResearch/hermes-agent upstream repository.

Issues Fixed

#17139 - Cron Telegram deliver=['telegram'] fails

File: cron/scheduler.py Problem: When deliver is specified as a list (e.g., ['telegram']), the scheduler used str(deliver).split(",") which converted it to "['telegram']" instead of parsing the list items. Fix: Added check isinstance(deliver, list) to properly handle list-format delivery targets.

#17086 - Custom endpoint URL rewrite strips /anthropic path

File: agent/auxiliary_client.py Problem: Custom endpoints with api_mode: anthropic_messages had URLs rewritten from /anthropic to /v1, causing 404 errors. Fix: Added api_mode != "anthropic_messages" guard to skip URL rewriting when using Anthropic-native message format.

#17054 - Slack manifest broken metadata

File: hermes_cli/slack_cli.py Problem: Slack manifest used "major_version": 1, "minor_version": 1 which is invalid for v1 manifests. Fix: Changed to use "version": "2.0.0" format.

#17049 - Windows wmic UnicodeDecodeError

File: hermes_cli/gateway.py Problem: wmic command output on Windows uses system code page, not UTF-8, causing UnicodeDecodeError and cascading AttributeError on result.stdout. Fix: Added encoding="utf-8", errors="replace" to subprocess call and OSError exception handling.

#17043 - TelegramFallbackTransport DoH drops IPs

File: gateway/platforms/telegram_network.py Problem: discover_fallback_ips() filtered out DoH-resolved IPs that matched system DNS, causing fallback to hardcoded seed IPs on networks where seed IPs aren't routable. Fix: Removed ip not in system_ips exclusion - DoH-confirmed IPs are now preserved.

#17140 - TTS tools use os.getenv() instead of get_env_value()

File: tools/tts_tool.py Problem: TTS providers (elevenlabs, minimax, mistral, xai, gemini) used os.getenv() which doesn't read values from ~/.hermes/.env loaded via the hermes config bridge. Fix: Replaced with get_env_value() calls for all TTS API keys.

hermes_cli/config.py - _sanitize_env_lines KEY= detection

File: hermes_cli/config.py Problem: _sanitize_env_lines matched KEY= patterns that appeared as substrings within other keys (e.g., LM_API_KEY matched inside GLM_API_KEY). Fix: Only treat KEY= as a separator when it appears at position 0 or after a non-identifier character.

Files Modified

  • agent/auxiliary_client.py (+289 lines)
  • cron/scheduler.py (+21 lines)
  • gateway/platforms/telegram_network.py (+9 lines)
  • hermes_cli/config.py (+259 lines)
  • hermes_cli/gateway.py (+21 lines)
  • hermes_cli/slack_cli.py (+3 lines)
  • tools/tts_tool.py (+43 lines)

Testing

All fixes are focused on bug corrections with minimal behavioral changes. The existing test suite should pass.


Automated PR created by Hermes Agent cron job

Changed files

  • .gitignore (modified, +1/-0)
  • Dockerfile (modified, +8/-3)
  • agent/auxiliary_client.py (modified, +344/-55)
  • agent/context_compressor.py (modified, +509/-54)
  • agent/credential_pool.py (modified, +6/-3)
  • agent/error_classifier.py (modified, +31/-0)
  • agent/image_routing.py (added, +236/-0)
  • agent/memory_manager.py (modified, +114/-5)
  • agent/model_metadata.py (modified, +51/-21)
  • agent/nous_rate_guard.py (modified, +142/-0)
  • agent/onboarding.py (added, +191/-0)
  • agent/prompt_builder.py (modified, +34/-0)
  • agent/shell_hooks.py (modified, +5/-1)
  • agent/skill_commands.py (modified, +2/-2)
  • agent/title_generator.py (modified, +33/-4)
  • agent/transports/chat_completions.py (modified, +11/-0)
  • cli-config.yaml.example (modified, +28/-8)
  • cli.py (modified, +466/-196)
  • cron/jobs.py (modified, +31/-3)
  • cron/scheduler.py (modified, +44/-6)
  • docker/entrypoint.sh (modified, +9/-7)
  • flake.nix (modified, +1/-0)
  • gateway/channel_directory.py (modified, +67/-14)
  • gateway/config.py (modified, +68/-2)
  • gateway/display_config.py (modified, +3/-1)
  • gateway/mirror.py (modified, +57/-11)
  • gateway/platforms/__init__.py (modified, +2/-0)
  • gateway/platforms/base.py (modified, +152/-5)
  • gateway/platforms/discord.py (modified, +24/-28)
  • gateway/platforms/email.py (modified, +3/-0)
  • gateway/platforms/feishu.py (modified, +26/-7)
  • gateway/platforms/helpers.py (modified, +9/-0)
  • gateway/platforms/matrix.py (modified, +73/-3)
  • gateway/platforms/slack.py (modified, +753/-70)
  • gateway/platforms/telegram.py (modified, +45/-0)
  • gateway/platforms/telegram_network.py (modified, +7/-2)
  • gateway/platforms/yuanbao.py (added, +4754/-0)
  • gateway/platforms/yuanbao_media.py (added, +647/-0)
  • gateway/platforms/yuanbao_proto.py (added, +1210/-0)
  • gateway/platforms/yuanbao_sticker.py (added, +558/-0)
  • gateway/run.py (modified, +745/-259)
  • gateway/session.py (modified, +11/-2)
  • gateway/status.py (modified, +8/-1)
  • gateway/stream_consumer.py (modified, +110/-0)
  • gateway/whatsapp_identity.py (modified, +21/-1)
  • hermes_cli/auth.py (modified, +28/-3)
  • hermes_cli/backup.py (modified, +177/-1)
  • hermes_cli/commands.py (modified, +113/-5)
  • hermes_cli/config.py (modified, +349/-34)
  • hermes_cli/copilot_auth.py (modified, +1/-1)
  • hermes_cli/debug.py (modified, +11/-5)
  • hermes_cli/doctor.py (modified, +2/-0)
  • hermes_cli/fallback_cmd.py (added, +361/-0)
  • hermes_cli/gateway.py (modified, +35/-10)
  • hermes_cli/main.py (modified, +577/-30)
  • hermes_cli/model_catalog.py (added, +329/-0)
  • hermes_cli/models.py (modified, +98/-6)
  • hermes_cli/nous_subscription.py (modified, +16/-8)
  • hermes_cli/platforms.py (modified, +1/-0)
  • hermes_cli/providers.py (modified, +11/-0)
  • hermes_cli/runtime_provider.py (modified, +31/-0)
  • hermes_cli/setup.py (modified, +69/-14)
  • hermes_cli/skills_hub.py (modified, +230/-20)
  • hermes_cli/slack_cli.py (added, +151/-0)
  • hermes_cli/status.py (modified, +2/-1)
  • hermes_cli/timeouts.py (modified, +4/-4)
  • hermes_cli/tips.py (modified, +2/-3)
  • hermes_cli/tools_config.py (modified, +14/-3)
  • hermes_cli/web_server.py (modified, +8/-10)
  • hermes_logging.py (modified, +3/-4)
  • hermes_state.py (modified, +319/-63)
  • model_tools.py (modified, +44/-13)
  • nix/checks.nix (modified, +30/-3)
  • nix/hermes-agent.nix (added, +186/-0)
  • nix/nixosModules.nix (modified, +81/-6)
  • nix/overlays.nix (added, +10/-0)
  • nix/packages.nix (modified, +6/-107)
  • nix/python.nix (modified, +2/-1)
  • nix/tui.nix (modified, +2/-1)
  • optional-skills/creative/touchdesigner-mcp/SKILL.md (modified, +7/-1)
  • optional-skills/creative/touchdesigner-mcp/references/audio-reactive.md (added, +175/-0)
  • optional-skills/creative/touchdesigner-mcp/references/geometry-comp.md (added, +121/-0)
  • optional-skills/creative/touchdesigner-mcp/references/glsl.md (added, +151/-0)
  • optional-skills/creative/touchdesigner-mcp/references/layout-compositor.md (added, +131/-0)
  • optional-skills/creative/touchdesigner-mcp/references/operator-tips.md (added, +106/-0)
  • optional-skills/creative/touchdesigner-mcp/references/pitfalls.md (modified, +221/-25)
  • optional-skills/creative/touchdesigner-mcp/references/postfx.md (added, +183/-0)
  • optional-skills/migration/openclaw-migration/scripts/openclaw_to_hermes.py (modified, +27/-2)
  • plugins/google_meet/README.md (added, +131/-0)
  • plugins/google_meet/SKILL.md (added, +148/-0)
  • plugins/google_meet/__init__.py (added, +103/-0)
  • plugins/google_meet/audio_bridge.py (added, +244/-0)
  • plugins/google_meet/cli.py (added, +478/-0)
  • plugins/google_meet/meet_bot.py (added, +852/-0)
  • plugins/google_meet/node/__init__.py (added, +54/-0)
  • plugins/google_meet/node/cli.py (added, +125/-0)
  • plugins/google_meet/node/client.py (added, +107/-0)
  • plugins/google_meet/node/protocol.py (added, +124/-0)
  • plugins/google_meet/node/registry.py (added, +112/-0)
  • plugins/google_meet/node/server.py (added, +193/-0)

PR #16165: fix: resolve 7 identified issues [automated]

Description (problem / solution / changelog)

Summary

This PR resolves 7 issues identified in the NousResearch/hermes-agent upstream repository.

Issues Fixed

#17139 - Cron Telegram deliver=['telegram'] fails

File: cron/scheduler.py Problem: When deliver is specified as a list (e.g., ['telegram']), the scheduler used str(deliver).split(",") which converted it to "['telegram']" instead of parsing the list items. Fix: Added check isinstance(deliver, list) to properly handle list-format delivery targets.

#17086 - Custom endpoint URL rewrite strips /anthropic path

File: agent/auxiliary_client.py Problem: Custom endpoints with api_mode: anthropic_messages had URLs rewritten from /anthropic to /v1, causing 404 errors. Fix: Added api_mode != "anthropic_messages" guard to skip URL rewriting when using Anthropic-native message format.

#17054 - Slack manifest broken metadata

File: hermes_cli/slack_cli.py Problem: Slack manifest used "major_version": 1, "minor_version": 1 which is invalid for v1 manifests. Fix: Changed to use "version": "2.0.0" format.

#17049 - Windows wmic UnicodeDecodeError

File: hermes_cli/gateway.py Problem: wmic command output on Windows uses system code page, not UTF-8, causing UnicodeDecodeError and cascading AttributeError on result.stdout. Fix: Added encoding="utf-8", errors="replace" to subprocess call and OSError exception handling.

#17043 - TelegramFallbackTransport DoH drops IPs

File: gateway/platforms/telegram_network.py Problem: discover_fallback_ips() filtered out DoH-resolved IPs that matched system DNS, causing fallback to hardcoded seed IPs on networks where seed IPs aren't routable. Fix: Removed ip not in system_ips exclusion - DoH-confirmed IPs are now preserved.

#17140 - TTS tools use os.getenv() instead of get_env_value()

File: tools/tts_tool.py Problem: TTS providers (elevenlabs, minimax, mistral, xai, gemini) used os.getenv() which doesn't read values from ~/.hermes/.env loaded via the hermes config bridge. Fix: Replaced with get_env_value() calls for all TTS API keys.

hermes_cli/config.py - _sanitize_env_lines KEY= detection

File: hermes_cli/config.py Problem: _sanitize_env_lines matched KEY= patterns that appeared as substrings within other keys (e.g., LM_API_KEY matched inside GLM_API_KEY). Fix: Only treat KEY= as a separator when it appears at position 0 or after a non-identifier character.

Files Modified

  • agent/auxiliary_client.py
  • cron/scheduler.py
  • gateway/platforms/telegram_network.py
  • hermes_cli/config.py
  • hermes_cli/gateway.py
  • hermes_cli/slack_cli.py
  • tools/tts_tool.py

Automated PR updated by Hermes Agent cron job

Changed files

  • .gitignore (modified, +1/-0)
  • Dockerfile (modified, +8/-3)
  • agent/auxiliary_client.py (modified, +344/-55)
  • agent/context_compressor.py (modified, +509/-54)
  • agent/error_classifier.py (modified, +31/-0)
  • agent/image_routing.py (added, +236/-0)
  • agent/memory_manager.py (modified, +114/-5)
  • agent/model_metadata.py (modified, +35/-16)
  • agent/onboarding.py (modified, +52/-5)
  • agent/prompt_builder.py (modified, +34/-0)
  • agent/shell_hooks.py (modified, +5/-1)
  • agent/title_generator.py (modified, +33/-4)
  • agent/transports/chat_completions.py (modified, +11/-0)
  • cli-config.yaml.example (modified, +6/-1)
  • cli.py (modified, +390/-58)
  • cron/jobs.py (modified, +31/-3)
  • cron/scheduler.py (modified, +41/-3)
  • flake.nix (modified, +1/-0)
  • gateway/channel_directory.py (modified, +67/-14)
  • gateway/config.py (modified, +68/-2)
  • gateway/display_config.py (modified, +3/-1)
  • gateway/mirror.py (modified, +57/-11)
  • gateway/platforms/__init__.py (modified, +2/-0)
  • gateway/platforms/base.py (modified, +117/-0)
  • gateway/platforms/discord.py (modified, +24/-23)
  • gateway/platforms/email.py (modified, +3/-0)
  • gateway/platforms/feishu.py (modified, +26/-7)
  • gateway/platforms/helpers.py (modified, +9/-0)
  • gateway/platforms/matrix.py (modified, +73/-3)
  • gateway/platforms/slack.py (modified, +753/-70)
  • gateway/platforms/telegram.py (modified, +45/-0)
  • gateway/platforms/telegram_network.py (modified, +7/-2)
  • gateway/platforms/yuanbao.py (added, +4754/-0)
  • gateway/platforms/yuanbao_media.py (added, +647/-0)
  • gateway/platforms/yuanbao_proto.py (added, +1210/-0)
  • gateway/platforms/yuanbao_sticker.py (added, +558/-0)
  • gateway/run.py (modified, +570/-60)
  • gateway/session.py (modified, +11/-2)
  • gateway/status.py (modified, +8/-1)
  • gateway/stream_consumer.py (modified, +110/-0)
  • gateway/whatsapp_identity.py (modified, +21/-1)
  • hermes_cli/auth.py (modified, +9/-0)
  • hermes_cli/backup.py (modified, +177/-1)
  • hermes_cli/commands.py (modified, +112/-2)
  • hermes_cli/config.py (modified, +358/-34)
  • hermes_cli/copilot_auth.py (modified, +1/-1)
  • hermes_cli/debug.py (modified, +11/-5)
  • hermes_cli/doctor.py (modified, +2/-0)
  • hermes_cli/gateway.py (modified, +35/-10)
  • hermes_cli/main.py (modified, +530/-28)
  • hermes_cli/models.py (modified, +70/-5)
  • hermes_cli/nous_subscription.py (modified, +16/-8)
  • hermes_cli/platforms.py (modified, +1/-0)
  • hermes_cli/providers.py (modified, +11/-0)
  • hermes_cli/runtime_provider.py (modified, +31/-0)
  • hermes_cli/setup.py (modified, +69/-14)
  • hermes_cli/skills_hub.py (modified, +170/-6)
  • hermes_cli/slack_cli.py (added, +151/-0)
  • hermes_cli/status.py (modified, +2/-1)
  • hermes_cli/timeouts.py (modified, +4/-4)
  • hermes_cli/tips.py (modified, +1/-1)
  • hermes_cli/tools_config.py (modified, +14/-3)
  • hermes_cli/web_server.py (modified, +8/-10)
  • hermes_logging.py (modified, +3/-4)
  • hermes_state.py (modified, +307/-62)
  • model_tools.py (modified, +44/-13)
  • nix/checks.nix (modified, +30/-3)
  • nix/hermes-agent.nix (added, +186/-0)
  • nix/nixosModules.nix (modified, +81/-6)
  • nix/overlays.nix (added, +10/-0)
  • nix/packages.nix (modified, +6/-107)
  • nix/python.nix (modified, +2/-1)
  • nix/tui.nix (modified, +2/-1)
  • optional-skills/creative/touchdesigner-mcp/SKILL.md (modified, +7/-1)
  • optional-skills/creative/touchdesigner-mcp/references/audio-reactive.md (added, +175/-0)
  • optional-skills/creative/touchdesigner-mcp/references/geometry-comp.md (added, +121/-0)
  • optional-skills/creative/touchdesigner-mcp/references/glsl.md (added, +151/-0)
  • optional-skills/creative/touchdesigner-mcp/references/layout-compositor.md (added, +131/-0)
  • optional-skills/creative/touchdesigner-mcp/references/operator-tips.md (added, +106/-0)
  • optional-skills/creative/touchdesigner-mcp/references/pitfalls.md (modified, +221/-25)
  • optional-skills/creative/touchdesigner-mcp/references/postfx.md (added, +183/-0)
  • optional-skills/migration/openclaw-migration/scripts/openclaw_to_hermes.py (modified, +27/-2)
  • plugins/google_meet/README.md (added, +131/-0)
  • plugins/google_meet/SKILL.md (added, +148/-0)
  • plugins/google_meet/__init__.py (added, +103/-0)
  • plugins/google_meet/audio_bridge.py (added, +244/-0)
  • plugins/google_meet/cli.py (added, +478/-0)
  • plugins/google_meet/meet_bot.py (added, +852/-0)
  • plugins/google_meet/node/__init__.py (added, +54/-0)
  • plugins/google_meet/node/cli.py (added, +125/-0)
  • plugins/google_meet/node/client.py (added, +107/-0)
  • plugins/google_meet/node/protocol.py (added, +124/-0)
  • plugins/google_meet/node/registry.py (added, +112/-0)
  • plugins/google_meet/node/server.py (added, +193/-0)
  • plugins/google_meet/plugin.yaml (added, +16/-0)
  • plugins/google_meet/process_manager.py (added, +326/-0)
  • plugins/google_meet/realtime/__init__.py (added, +10/-0)
  • plugins/google_meet/realtime/openai_client.py (added, +332/-0)
  • plugins/google_meet/tools.py (added, +348/-0)
  • plugins/memory/hindsight/__init__.py (modified, +154/-43)

PR #17222: fix(cron): accept list-shaped deliver in delivery target resolver (#17139)

Description (problem / solution / changelog)

What does this PR do?

_resolve_delivery_targets only handled the comma-separated-string shape of deliver ("telegram" / "telegram,discord"). Jobs whose deliver was persisted as a Python list (typical when the LLM cron tool wrote it as an array, or when older code paths in hermes_cli.cron already normalize to lists) reached str(["telegram"]).split(",") and produced the literal token "['telegram']" — no resolver branch matched, the job logged last_delivery_error="no delivery target resolved for deliver=['telegram']", and the user's daily briefing was saved to disk but never reached Telegram (#17139), even though manual delivery from inside an active Telegram session worked fine.

The fix branches on isinstance(deliver, (list, tuple)): in that case treat each element as a pre-tokenised delivery target; otherwise keep the existing comma-split string path. str(p).strip() plus an empty filter mirrors the comma-split path's whitespace handling.

Related Issue

Fixes #17139

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 🔒 Security fix
  • 📝 Documentation update
  • ✅ Tests (adding or improving test coverage)
  • ♻️ Refactor (no behavior change)
  • 🎯 New skill (bundled or hub)

Changes Made

  • cron/scheduler.py_resolve_delivery_targets: branch on isinstance(deliver, (list, tuple)). Updated docstring with an explicit reference to the issue's str(["telegram"]).split(",") failure mode.
  • tests/cron/test_scheduler.py — six new cases in TestResolveDeliveryTarget: list with single telegram (the exact reproducer), list with two platforms, list with stray empty entries, plus the two pre-existing string shapes pinned so the comma-split path doesn't regress.

How to Test

  1. Create a cron job whose deliver is persisted as a list (deliver: [telegram]):
    from cron.jobs import update_job
    update_job("daily-briefing", deliver=["telegram"])
  2. Set TELEGRAM_HOME_CHANNEL and let the job run.
  3. Before this fix: last_delivery_error="no delivery target resolved for deliver=['telegram']"; output saved to ~/.hermes/cron/output/<job_id>/, but no Telegram message arrives.
  4. After this fix: the message lands in the Telegram home channel as expected.

Automated:

pytest tests/cron/test_scheduler.py::TestResolveDeliveryTarget -q

Result on macOS 15.6 / Python 3.14: 29 passed. The two list-shape tests (test_deliver_as_list_with_single_telegram_target, test_deliver_as_list_with_multiple_targets) fail on origin/main without the fix.

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (fix(scope):, feat(scope):, etc.)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix/feature (no unrelated commits)
  • I've run pytest tests/cron/test_scheduler.py -q. The targeted TestResolveDeliveryTarget block (29 cases) passes; full tests/cron/test_scheduler.py shows 2 pre-existing failures in TestSilentDelivery that reproduce on origin/main without this change and are unrelated to the delivery-target resolver.
  • I've added tests for my changes (required for bug fixes, strongly encouraged for features)
  • I've tested on my platform: macOS 15.6 (Python 3.14)

Documentation & Housekeeping

  • I've updated relevant documentation (README, docs/, docstrings) — or N/A (updated _resolve_delivery_targets's docstring to document both shapes; no user-facing docs reference the resolver internals)
  • I've updated cli-config.yaml.example if I added/changed config keys — or N/A (N/A — no config keys touched; deliver is a per-job field whose accepted shapes are now broader)
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows — or N/A (N/A)
  • I've considered cross-platform impact (Windows, macOS) per the compatibility guide — or N/A (N/A — pure Python isinstance + iteration; identical across platforms)
  • I've updated tool descriptions/schemas if I changed tool behavior — or N/A (N/A — cronjob tool's deliver parameter schema still documents the string shape; this PR only makes the consumer accept the list shape that some upstream call sites already produce)

Screenshots / Logs

$ pytest tests/cron/test_scheduler.py::TestResolveDeliveryTarget -q
.............................                                            [100%]
29 passed, 29 warnings in 2.82s

Changed files

  • cron/scheduler.py (modified, +17/-2)
  • tests/cron/test_scheduler.py (modified, +58/-0)

PR #17270: fix(cron): resolve list delivery targets for platform cron jobs

Description (problem / solution / changelog)

What does this PR do?

Fixes gateway startup isolation so one blocked platform connection does not prevent later platforms from starting.

Platform adapter startup and reconnect attempts now use a bounded per-platform connect timeout. If Telegram hangs during initialization, it is treated as a retryable platform failure and queued for reconnect, while Feishu and other configured platforms continue starting normally.

The timeout defaults to 30 seconds and can be configured with HERMES_GATEWAY_PLATFORM_CONNECT_TIMEOUT. Setting it to 0 disables the timeout.

Related Issue

Fixes #17242

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 🔒 Security fix
  • 📝 Documentation update
  • ✅ Tests (adding or improving test coverage)
  • ♻️ Refactor (no behavior change)
  • 🎯 New skill (bundled or hub)

Changes Made

  • Added a bounded platform adapter connect helper in gateway/run.py.
  • Routed gateway startup platform connections through the timeout helper.
  • Routed platform reconnect attempts through the same timeout helper.
  • Added tests covering startup continuation when Telegram connect times out and Feishu still connects.

How to Test

  1. Run:
    uv run --with pytest --with pytest-asyncio python -m pytest tests/gateway/test_platform_reconnect.py -q -o addopts=''
  2. Verify the startup isolation test passes.
  3. Optionally set HERMES_GATEWAY_PLATFORM_CONNECT_TIMEOUT=0.001 to verify hanging adapter connections become retryable timeout failures.

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (fix(scope):, feat(scope):, etc.)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix/feature (no unrelated commits)
  • I've run pytest tests/ -q and all tests pass
  • I've added tests for my changes (required for bug fixes, strongly encouraged for features)
  • I've tested on my platform: Ubuntu/Linux

Documentation & Housekeeping

  • I've updated relevant documentation (README, docs/, docstrings) — or N/A
  • I've updated cli-config.yaml.example if I added/changed config keys — or N/A
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows — or N/A
  • I've considered cross-platform impact (Windows, macOS) per the compatibility guide — or N/A
  • I've updated tool descriptions/schemas if I changed tool behavior — or N/A

Screenshots / Logs

16 passed in 2.86s

## Changed files

- `gateway/run.py` (modified, +30/-2)
- `tests/gateway/test_platform_reconnect.py` (modified, +88/-2)
RAW_BUFFERClick to expand / collapse

Bug Description

Cron jobs configured with deliver=['telegram'] fail to deliver output to Telegram. When the job completes, the last_delivery_error field shows: "no delivery target resolved for deliver=['telegram']".

This happens consistently across all cron jobs that target Telegram, including jobs that have been running successfully for weeks. The jobs complete successfully (output is saved to ~/.hermes/cron/output/), but the Telegram delivery step always fails with the same error.

Steps to Reproduce

  1. Create a cron job with deliver=['telegram'] (e.g., a daily briefing)
  2. Wait for the scheduled run — it saves output to file but Telegram delivery fails with "no delivery target resolved"
  3. Manually trigger the job with cronjob run — same result
  4. Run the same briefing task in an active Telegram session — works correctly

Expected Behavior

Cron job output should be delivered to the user's Telegram channel/chat when deliver=['telegram'] is set.

Actual Behavior

  • Job completes successfully (output saved to ~/.hermes/cron/output/<job_id>/)
  • last_delivery_error = "no delivery target resolved for deliver=['telegram']"
  • No message arrives in Telegram
  • Running manually in an active Telegram session works fine

Environment

  • Hermes Agent v0.11.0 (2026.04.23)
  • macOS
  • Telegram gateway connected and working (real-time messages work fine)
  • Cron jobs run on schedule, output saved correctly, only Telegram delivery fails

Additional Context

The issue appears to be in the cron worker context — when a cron job runs (whether scheduled or manually triggered via cronjob run), the Telegram platform context is not available to the delivery system, even though the user's Telegram bot and chat ID are properly configured. The delivery system can only resolve Telegram targets when running inside an active Telegram session context.

This suggests the cron worker spawns in a context that lacks the messaging platform resolution needed for deliver=['telegram']. A potential fix might involve explicitly passing the user's Telegram chat_id or home channel configuration into the cron worker context so delivery can resolve the target.

extent analysis

TL;DR

Passing the user's Telegram chat_id or home channel configuration to the cron worker context may resolve the delivery target issue.

Guidance

  • Verify that the Telegram gateway is properly connected and working by checking real-time messages.
  • Investigate how to pass the user's Telegram chat_id or home channel configuration to the cron worker context, potentially through environment variables or job configuration.
  • Check the Hermes Agent documentation (v0.11.0) for any settings or options related to cron job delivery contexts.
  • Test modifying the cron job configuration to include explicit Telegram target resolution, if possible.

Example

No code snippet is provided due to lack of specific implementation details.

Notes

The issue seems to be related to the cron worker context lacking the necessary messaging platform resolution. The provided information suggests that passing the user's Telegram configuration to the cron worker might resolve the issue, but the exact implementation is unclear.

Recommendation

Apply workaround: Pass the user's Telegram chat_id or home channel configuration to the cron worker context, as this is the most likely solution based on the provided information.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING