← Back to PRs

#8097: fix: auto-convert one-shot reminders for reliable delivery

by Gerrald12312 open 2026-02-03 15:56 View on GitHub →
agents stale
## Problem When agents set reminders using cron jobs with: - `schedule.kind: 'at'` (one-shot) - `sessionTarget: 'main'` - `payload.kind: 'systemEvent'` The reminder fires but only injects text into the agent's session context. If the agent isn't actively processing at that moment, **the user never receives a message**. This leads to the frustrating experience where the agent says "I'll remind you in 5 minutes" but the reminder never arrives. ## Solution When creating a one-shot reminder and the agent has channel context (e.g., WhatsApp, Telegram), automatically convert: | Before | After | |--------|-------| | `sessionTarget: 'main'` | `sessionTarget: 'isolated'` | | `payload.kind: 'systemEvent'` | `payload.kind: 'agentTurn'` | | - | `payload.deliver: true` | | - | `payload.channel: <current>` | | - | `payload.to: <recipient>` | This spawns an isolated agent when the reminder fires, which sends the message to the user via the messaging channel. ## Changes 1. **`src/agents/tools/cron-tool.ts`** - Added `currentChannel` and `currentChannelTo` to `CronToolOptions` - Added auto-conversion logic in the 'add' action 2. **`src/agents/openclaw-tools.ts`** - Pass `agentChannel` and `agentTo` to the cron tool ## Testing Manually tested by setting a reminder via WhatsApp - the reminder now actually arrives as a message instead of being silently injected into session context. ## Notes - Only applies to one-shot (`at`) reminders, not recurring crons - Only triggers when channel context is available - Preserves existing behavior for systemEvent crons without channel context <!-- greptile_comment --> <h2>Greptile Overview</h2> <h3>Greptile Summary</h3> This PR improves reliability of one-shot (`schedule.kind: "at"`) reminders created via the cron tool when an agent is operating on an external messaging channel (e.g., WhatsApp/Telegram). It threads channel context (`agentChannel`/`agentTo`) into `createCronTool` and, on `cron add`, auto-converts jobs that would have injected a `systemEvent` into the main session into an isolated `agentTurn` with `deliver: true` and explicit `channel`/`to`, ensuring a message is sent even when the main agent is idle. The core change lives in `src/agents/tools/cron-tool.ts`, where the `add` action rewrites eligible jobs prior to calling `cron.add`. `src/agents/openclaw-tools.ts` is updated to supply the current channel information to the cron tool. <h3>Confidence Score: 3/5</h3> - Reasonably safe to merge, but conversion heuristics and typing should be tightened to avoid unintended behavior changes. - The change is localized and addresses a real delivery gap, but the current auto-conversion triggers when `sessionTarget` is omitted (treating it as main) and fully replaces the payload, which can change semantics for some jobs. There is also a likely type mismatch between `GatewayMessageChannel` and the cron tool’s `currentChannel: string`, which could break builds or routing depending on actual types. - src/agents/tools/cron-tool.ts (conversion conditions/payload rewrite), src/agents/openclaw-tools.ts (types passed into cron tool) <!-- greptile_other_comments_section --> <sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub> **Context used:** - Context from `dashboard` - CLAUDE.md ([source](https://app.greptile.com/review/custom-context?memory=fd949e91-5c3a-4ab5-90a1-cbe184fd6ce8)) - Context from `dashboard` - AGENTS.md ([source](https://app.greptile.com/review/custom-context?memory=0d0c8278-ef8e-4d6c-ab21-f5527e322f13)) <!-- /greptile_comment -->

Most Similar PRs