feat: allow configured remote cron commands

Add tools.cron.command_allowed_remotes so remote channels can be
explicitly allowlisted for command-executing cron jobs. Entries support
channel names, channel:chat_id pairs, and a literal * to allow every
non-empty channel while preserving the default deny posture.

The existing allow_command and command_confirm checks still apply after the
channel gate. Update tests, config examples, and cron documentation for the
new option.
This commit is contained in:
jp39
2026-06-16 15:25:30 +02:00
parent 083e68b49a
commit 3056a540bf
9 changed files with 271 additions and 35 deletions
+21 -5
View File
@@ -43,7 +43,8 @@ the original prompt, delivery target, or command payload.
Remote channel access is scoped to the current `channel/chat_id`: remote callers
can only list, get, or update jobs whose saved `payload.channel` and `payload.to`
match the current conversation. Command jobs include a shell command payload, so
they can only be listed, inspected, or updated from internal channels.
they can only be listed, inspected, or updated from internal channels or remote
channels allowed by `tools.cron.command_allowed_remotes`.
Example tool calls:
@@ -59,7 +60,7 @@ Example tool calls:
(`at_seconds`, `every_seconds`, or `cron_expr`).
Omit `command` to preserve it, set `command` to a non-empty string to replace
it, or set `command` to `""` to clear it. Command updates require the same
internal channel and confirmation gates as command creation.
channel allowlist and confirmation gates as command creation.
## Execution Modes
@@ -104,7 +105,7 @@ If `tools.exec.enabled` is `false`:
- new command jobs are rejected by the cron tool
- existing command jobs publish a `command execution is disabled` error when they fire
`tools.exec.allow_remote` is still enforced by the exec tool, but cron command scheduling already requires an internal channel when the job is created. In practice, reminder jobs can be scheduled from remote channels, while scheduled command jobs are limited to internal channels.
`tools.exec.allow_remote` is still enforced by the exec tool, but cron command scheduling has its own channel gate when the job is created. In practice, reminder jobs can be scheduled from remote channels, while scheduled command jobs are limited to internal channels and configured remote channels.
### `allow_command`
@@ -112,7 +113,19 @@ If `tools.exec.enabled` is `false`:
This is not a hard disable switch. If you set `allow_command` to `false`, PicoClaw still allows a command job when the caller explicitly passes `command_confirm: true`.
Command jobs also require an internal channel. Non-command reminders do not have that restriction.
Command jobs also require either an internal channel or a remote channel allowed by `tools.cron.command_allowed_remotes`. Non-command reminders do not have that restriction.
### `command_allowed_remotes`
`tools.cron.command_allowed_remotes` defaults to an empty list. With the default empty list, remote channels cannot schedule command jobs.
Entries can be either a channel name or a channel plus chat id:
- `telegram` allows command jobs from any Telegram chat.
- `telegram:1234567890` allows command jobs only from that exact Telegram chat id.
- `*` allows command jobs from every non-empty channel.
This setting only controls the remote-channel gate. It does not bypass `tools.cron.allow_command`, `command_confirm`, `tools.exec.enabled`, or the exec tool's command safety checks.
Example:
@@ -122,7 +135,10 @@ Example:
"cron": {
"enabled": true,
"exec_timeout_minutes": 5,
"allow_command": true
"allow_command": true,
"command_allowed_remotes": [
"telegram:1234567890"
]
},
"exec": {
"enabled": true
+6 -5
View File
@@ -311,11 +311,12 @@ as containers, VMs, or an approval flow around build-and-run commands.
The cron tool is used for scheduling periodic tasks.
| Config | Type | Default | Description |
|------------------------|------|---------|------------------------------------------------|
| `enabled` | bool | true | Register the agent-facing cron tool |
| `allow_command` | bool | true | Allow command jobs without extra confirmation |
| `exec_timeout_minutes` | int | 5 | Execution timeout in minutes, 0 means no limit |
| Config | Type | Default | Description |
|---------------------------|----------|---------|----------------------------------------------------------------|
| `enabled` | bool | true | Register the agent-facing cron tool |
| `allow_command` | bool | true | Allow command jobs without extra confirmation |
| `command_allowed_remotes` | string[] | [] | Remote channels or `channel:chat_id` values allowed for command jobs; `*` allows every channel |
| `exec_timeout_minutes` | int | 5 | Execution timeout in minutes, 0 means no limit |
For schedule types, execution modes (`deliver`, agent turn, and command jobs), persistence, and the current command-security gates, see [Scheduled Tasks and Cron Jobs](cron.md).