Skip to content

Commit f0e7d5e

Browse files
Guillermo Alejandro Gallardo DiezGuillermo Alejandro Gallardo Diez
authored andcommitted
fix: allow event:*:pattern as cadence
1 parent 34a65ee commit f0e7d5e

3 files changed

Lines changed: 15 additions & 5 deletions

File tree

crates/ironclaw_engine/prompts/codeact_preamble.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ This is much faster than calling tools sequentially. Use `asyncio.gather()` when
3333
- `llm_query_batched(prompts, context=None, model=None, models=None)` — Same but for multiple prompts in parallel. Returns a list of strings. Pass `model="gpt-4o"` to apply one model to every prompt, or `models=["gpt-4o", "claude-sonnet-4-20250514", ...]` (parallel array, must match `prompts` length) to send each prompt to a different model. The "LLM council" pattern is `prompts=[same_question]*N, models=[m1, m2, ...]`.
3434
- `rlm_query(prompt)` — Spawn a full sub-agent with its own tools and iteration budget. Use for complex sub-tasks that need tool access. Returns the sub-agent's final answer as a string. More powerful but more expensive than llm_query.
3535
- `FINAL(answer)` — Call this when you have the final answer. The argument is returned to the user.
36-
- `mission_create(name, goal, cadence, notify_channels=None, success_criteria=None, timezone=None, cooldown_secs=None, max_concurrent=None, dedup_window_secs=None, max_threads_per_day=None)` — Create a long-running mission that spawns threads over time. **`cadence` is required** — use "manual", a cron expression (e.g. "0 9 * * *"), "event:<channel>:<regex_pattern>" (e.g. "event:telegram:.*" to match all messages on the telegram channel), or "webhook:path". Cron expressions accept 5-field (`min hr dom mon dow`), 6-field (`sec min hr dom mon dow` — NOT Quartz-style with year), or 7-field (`sec min hr dom mon dow year`). Cron missions default to the user's timezone from `user_timezone`; pass an explicit `timezone` param to override. Guardrail params: `cooldown_secs` (minimum seconds between triggers, default 300 for event/webhook, 0 for cron/manual), `max_concurrent` (max simultaneous threads), `dedup_window_secs` (suppress duplicate events within window), `max_threads_per_day` (daily budget). Returns {"mission_id": "...", "name": "...", "status": "created"}. When telling the user about a created mission, refer to it by `name`, not by `mission_id` (the UUID is internal).
36+
- `mission_create(name, goal, cadence, notify_channels=None, success_criteria=None, timezone=None, cooldown_secs=None, max_concurrent=None, dedup_window_secs=None, max_threads_per_day=None)` — Create a long-running mission that spawns threads over time. **`cadence` is required** — use "manual", a cron expression (e.g. "0 9 * * *"), "event:<channel>:<regex_pattern>" (e.g. "event:telegram:.*" to match all messages on the telegram channel, or "event:*:.*" to match any channel), or "webhook:path". Cron expressions accept 5-field (`min hr dom mon dow`), 6-field (`sec min hr dom mon dow` — NOT Quartz-style with year), or 7-field (`sec min hr dom mon dow year`). Cron missions default to the user's timezone from `user_timezone`; pass an explicit `timezone` param to override. Guardrail params: `cooldown_secs` (minimum seconds between triggers, default 300 for event/webhook, 0 for cron/manual), `max_concurrent` (max simultaneous threads), `dedup_window_secs` (suppress duplicate events within window), `max_threads_per_day` (daily budget). Returns {"mission_id": "...", "name": "...", "status": "created"}. When telling the user about a created mission, refer to it by `name`, not by `mission_id` (the UUID is internal).
3737
- `mission_list()` — List all missions with their status, goal, cadence, guardrails, and current focus.
3838
- `mission_update(id, name=None, goal=None, cadence=None, notify_channels=None, timezone=None, cooldown_secs=None, max_concurrent=None, dedup_window_secs=None, max_threads_per_day=None, success_criteria=None)` — Update a mission's configuration. Only provided fields are changed.
3939
- `mission_delete(id)` — Delete a mission (sets status to completed).

src/bridge/effect_adapter.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1237,7 +1237,11 @@ fn parse_cadence(
12371237
}
12381238
Ok(MissionCadence::OnEvent {
12391239
event_pattern: pattern.to_string(),
1240-
channel: Some(channel.to_string()),
1240+
channel: if channel == "*" {
1241+
None
1242+
} else {
1243+
Some(channel.to_string())
1244+
},
12411245
})
12421246
} else if lower.starts_with("webhook:") {
12431247
// Extract from original to preserve case in webhook paths.
@@ -1614,7 +1618,13 @@ fn cadence_to_round_trip_string(
16141618
use ironclaw_engine::types::mission::MissionCadence;
16151619
match cadence {
16161620
MissionCadence::Cron { expression, .. } => expression.clone(),
1617-
MissionCadence::OnEvent { event_pattern, .. } => format!("event:{event_pattern}"),
1621+
MissionCadence::OnEvent {
1622+
event_pattern,
1623+
channel,
1624+
} => match channel {
1625+
Some(ch) => format!("event:{ch}:{event_pattern}"),
1626+
None => format!("event:*:{event_pattern}"),
1627+
},
16181628
MissionCadence::OnSystemEvent {
16191629
source, event_type, ..
16201630
} => {

src/bridge/router.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -937,7 +937,7 @@ pub async fn init_engine(agent: &Agent) -> Result<(), Error> {
937937
"properties": {
938938
"name": {"type": "string", "description": "Short name for the mission/routine"},
939939
"goal": {"type": "string", "description": "What this mission should accomplish each run"},
940-
"cadence": {"type": "string", "description": "Required. How to trigger: 'manual', a cron expression (e.g. '0 9 * * *'), 'event:<channel>:<regex_pattern>' (e.g. 'event:telegram:.*'), or 'webhook:<path>'"},
940+
"cadence": {"type": "string", "description": "Required. How to trigger: 'manual', a cron expression (e.g. '0 9 * * *'), 'event:<channel>:<regex_pattern>' (e.g. 'event:telegram:.*', use 'event:*:<pattern>' for any channel), or 'webhook:<path>'"},
941941
"timezone": {"type": "string", "description": "IANA timezone for cron scheduling (e.g. 'America/New_York'). Defaults to the user's channel timezone."},
942942
"notify_channels": {"type": "array", "items": {"type": "string"}, "description": "Channels to deliver results to (e.g. ['gateway', 'repl']). Defaults to current channel."},
943943
"cooldown_secs": {"type": "integer", "minimum": 0, "description": "Minimum seconds between triggers (default: 300 for event/webhook, 0 for cron/manual)"},
@@ -1006,7 +1006,7 @@ pub async fn init_engine(agent: &Agent) -> Result<(), Error> {
10061006
"id": {"type": "string", "description": "Mission/routine ID to update"},
10071007
"name": {"type": "string", "description": "New name"},
10081008
"goal": {"type": "string", "description": "New goal"},
1009-
"cadence": {"type": "string", "description": "New cadence: 'manual', cron expression (e.g. '0 9 * * *'), 'event:<channel>:<regex_pattern>' (e.g. 'event:telegram:.*'), or 'webhook:<path>'"},
1009+
"cadence": {"type": "string", "description": "New cadence: 'manual', cron expression (e.g. '0 9 * * *'), 'event:<channel>:<regex_pattern>' (e.g. 'event:telegram:.*', use 'event:*:<pattern>' for any channel), or 'webhook:<path>'"},
10101010
"timezone": {"type": "string", "description": "IANA timezone for cron scheduling (e.g. 'America/New_York'). Defaults to the user's channel timezone."},
10111011
"notify_channels": {"type": "array", "items": {"type": "string"}, "description": "Channels to deliver results to (e.g. ['gateway', 'repl'])"},
10121012
"max_threads_per_day": {"type": "integer", "minimum": 0, "description": "Max threads per day (0 = unlimited)"},

0 commit comments

Comments
 (0)