diff --git a/docs/automation/cron-jobs.md b/docs/automation/cron-jobs.md index bf8caa127c0..422640e7b5f 100644 --- a/docs/automation/cron-jobs.md +++ b/docs/automation/cron-jobs.md @@ -125,22 +125,19 @@ retries, cron aborts instead of looping forever. ## Delivery and output -| Mode | What happens | -| ---------- | -------------------------------------------------------- | -| `announce` | Deliver summary to target channel (default for isolated) | -| `webhook` | POST finished event payload to a URL | -| `none` | Internal only, no delivery | +| Mode | What happens | +| ---------- | ------------------------------------------------------------------- | +| `announce` | Fallback-deliver final text to the target if the agent did not send | +| `webhook` | POST finished event payload to a URL | +| `none` | No runner fallback delivery | Use `--announce --channel telegram --to "-1001234567890"` for channel delivery. For Telegram forum topics, use `-1001234567890:topic:123`. Slack/Discord/Mattermost targets should use explicit prefixes (`channel:`, `user:`). -For cron-owned isolated jobs, the runner owns the final delivery path. The -agent is prompted to return a plain-text summary, and that summary is then sent -through `announce`, `webhook`, or kept internal for `none`. `--no-deliver` -does not hand delivery back to the agent; it keeps the run internal. - -If the original task explicitly says to message some external recipient, the -agent should note who/where that message should go in its output instead of -trying to send it directly. +For isolated jobs, chat delivery is shared. If a chat route is available, the +agent can use the `message` tool even when the job uses `--no-deliver`. If the +agent sends to the configured/current target, OpenClaw skips the fallback +announce. Otherwise `announce`, `webhook`, and `none` only control what the +runner does with the final reply after the agent turn. Failure notifications follow a separate destination path: @@ -406,15 +403,15 @@ openclaw doctor ### Cron fired but no delivery -- Delivery mode is `none` means no external message is expected. +- Delivery mode `none` means no runner fallback send is expected. The agent can + still send directly with the `message` tool when a chat route is available. - Delivery target missing/invalid (`channel`/`to`) means outbound was skipped. - Channel auth errors (`unauthorized`, `Forbidden`) mean delivery was blocked by credentials. - If the isolated run returns only the silent token (`NO_REPLY` / `no_reply`), OpenClaw suppresses direct outbound delivery and also suppresses the fallback queued summary path, so nothing is posted back to chat. -- For cron-owned isolated jobs, do not expect the agent to use the message tool - as a fallback. The runner owns final delivery; `--no-deliver` keeps it - internal instead of allowing a direct send. +- If the agent should message the user itself, check that the job has a usable + route (`channel: "last"` with a previous chat, or an explicit channel/target). ### Timezone gotchas diff --git a/docs/cli/cron.md b/docs/cli/cron.md index 82d91d104d1..4cb695998b4 100644 --- a/docs/cli/cron.md +++ b/docs/cli/cron.md @@ -19,9 +19,9 @@ Tip: run `openclaw cron --help` for the full command surface. Note: isolated `cron add` jobs default to `--announce` delivery. Use `--no-deliver` to keep output internal. `--deliver` remains as a deprecated alias for `--announce`. -Note: cron-owned isolated runs expect a plain-text summary and the runner owns -the final send path. `--no-deliver` keeps the run internal; it does not hand -delivery back to the agent's message tool. +Note: isolated cron chat delivery is shared. `--announce` is runner fallback +delivery for the final reply; `--no-deliver` disables that fallback but does +not remove the agent's `message` tool when a chat route is available. Note: one-shot (`--at`) jobs delete after success by default. Use `--keep-after-run` to keep them. diff --git a/docs/help/faq.md b/docs/help/faq.md index 9320589deda..bcc1759e07e 100644 --- a/docs/help/faq.md +++ b/docs/help/faq.md @@ -1094,15 +1094,14 @@ for usage/billing and raise limits as needed. Check the delivery mode first: - - `--no-deliver` / `delivery.mode: "none"` means no external message is expected. + - `--no-deliver` / `delivery.mode: "none"` means no runner fallback send is expected. - Missing or invalid announce target (`channel` / `to`) means the runner skipped outbound delivery. - Channel auth failures (`unauthorized`, `Forbidden`) mean the runner tried to deliver but credentials blocked it. - A silent isolated result (`NO_REPLY` / `no_reply` only) is treated as intentionally non-deliverable, so the runner also suppresses queued fallback delivery. - For isolated cron jobs, the runner owns final delivery. The agent is expected - to return a plain-text summary for the runner to send. `--no-deliver` keeps - that result internal; it does not let the agent send directly with the - message tool instead. + For isolated cron jobs, the agent can still send directly with the `message` + tool when a chat route is available. `--announce` only controls the runner + fallback path for final text that the agent did not already send. Debug: diff --git a/src/cli/cron-cli/register.cron-add.ts b/src/cli/cron-cli/register.cron-add.ts index 3c0ec6b11e4..dd7a0271c7c 100644 --- a/src/cli/cron-cli/register.cron-add.ts +++ b/src/cli/cron-cli/register.cron-add.ts @@ -95,9 +95,9 @@ export function registerCronAddCommand(cron: Command) { .option("--timeout-seconds ", "Timeout seconds for agent jobs") .option("--light-context", "Use lightweight bootstrap context for agent jobs", false) .option("--tools ", "Tool allow-list (e.g. exec,read,write or exec read write)") - .option("--announce", "Announce summary to a chat (subagent-style)", false) - .option("--deliver", "Deprecated (use --announce). Announces a summary to a chat.") - .option("--no-deliver", "Disable announce delivery and skip main-session summary") + .option("--announce", "Fallback-deliver final text to a chat", false) + .option("--deliver", "Deprecated (use --announce). Fallback-delivers final text to a chat.") + .option("--no-deliver", "Disable runner fallback delivery") .option("--channel ", `Delivery channel (${getCronChannelOptions()})`, "last") .option( "--to ", diff --git a/src/cli/cron-cli/register.cron-edit.ts b/src/cli/cron-cli/register.cron-edit.ts index 9fac949b152..d9c98f5e069 100644 --- a/src/cli/cron-cli/register.cron-edit.ts +++ b/src/cli/cron-cli/register.cron-edit.ts @@ -66,9 +66,9 @@ export function registerCronEditCommand(cron: Command) { .option("--no-light-context", "Disable lightweight bootstrap context for agent jobs") .option("--tools ", "Tool allow-list (e.g. exec,read,write or exec read write)") .option("--clear-tools", "Remove tool allow-list (use all tools)", false) - .option("--announce", "Announce summary to a chat (subagent-style)") - .option("--deliver", "Deprecated (use --announce). Announces a summary to a chat.") - .option("--no-deliver", "Disable announce delivery") + .option("--announce", "Fallback-deliver final text to a chat") + .option("--deliver", "Deprecated (use --announce). Fallback-delivers final text to a chat.") + .option("--no-deliver", "Disable runner fallback delivery") .option("--channel ", `Delivery channel (${getCronChannelOptions()})`) .option( "--to ",