block / block/buzz

[Proposal] Scheduled-workflow precheck gate: skip runs with zero token/action cost

Open
#2,297 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
Rust
Stars
32.7k
Forks
4.3k
Avg merge
1d 13h
Merged PRs (30d)
253

Description

## Summary

Add an optional **precheck gate** to `Schedule`-triggered workflows so a recurring workflow can cheaply decide *whether there is work* before executing its steps (which may call agents, webhooks, or post messages). When the gate says "no work," the run is recorded as skipped and no actions fire — no agent turn, no webhook, no channel noise.

This mirrors a pattern we recently upstreamed to two other agent runtimes and would make Buzz's scheduled agent workflows materially cheaper and quieter.

## Problem

`TriggerDef::Schedule` fires a workflow on a cron/interval. Today the only convergence control is per-step `if:` (evalexpr) conditions evaluated against trigger context + prior step outputs. For a *poller* workflow ("every 15m, check X, and if there's something new, have an agent summarize it"), each tick still spins up the step chain (and any agent/webhook action) even when there is nothing to do. On a busy relay with many scheduled agent workflows, that is a large, silent cost and a source of empty-run channel noise.

## Prior art (why we think this is the right shape)

We contributed the same idea to OpenClaw (`job.precheck`) and Hermes (`NO_WORK` wake gate) cron systems: a cheap gate runs *before* the expensive work; exit `0` / `WORK_NEEDED` → run, exit `2` / `NO_WORK` → skip. The key lessons we'd carry over:

- The gate lives **inside** the scheduler run path (not a sidecar) so there's one source of truth and no double-firing.
- One documented **contract** (exit code + a `NO_WORK` stdout convention) with tests.
- Skipped runs are **recorded distinctly** (not errors) for observability.

## Proposed shape (seeking maintainer direction before implementing)

A workflow-level, evalexpr-based gate that reuses the existing `evaluate_condition` machinery (no new execution surface, no shell):

```yaml
name: pr-triage
trigger:
on: schedule
cron: "*/15 * * * *"
precheck: "trigger_open_pr_count > 0" # evalexpr, same vars as step if:
steps:
- action: { send_message: { text: "…" } }
```

- If `precheck` evaluates false → the run is **skipped** (distinct status, metric), zero actions.
- Purely additive: workflows without `precheck` behave exactly as today.
- Reuses `evaluate_condition` (already bounded: 4 KB expr cap + 100 ms timeout), so it inherits the same safety envelope — **no shell/command execution added to the relay**.

### Deliberately out of scope
- Arbitrary shell/command prechecks (security surface in the relay — not proposing that).
- Any change to non-schedule triggers.

## Open questions for maintainers
1. Is a workflow-level `precheck` (vs. telling authors to gate step 1 with `if:`) worth the ergonomics + the distinct skipped-run status/metric?
2. Preferred skipped-run surfacing: a workflow-run status value, a metric only, or both?
3. Would you want the gate to have access to any state beyond current trigger context (e.g., last-run state) — or keep it stateless in v1?

Happy to implement behind a small, additive PR with tests + docs once the shape is agreed. I recently shipped #2289 (agent `error_class`) and #2296 (offline-mention notice) in this area and can follow the same minimal-diff approach.

Contributor guide

Open the contributing guide

Research direction

Start by reviewing the TriggerDef::Schedule run path and the existing evaluate_condition machinery, including the current handling of step if: conditions. Before implementation, resolve the proposed contract for false prechecks, skipped-run status or metrics, and state access with maintainers; done should include agreed tests and documentation for schedule workflows without changing other triggers.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
backend
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.