pre_run shell hook; the agent only runs when the gate script reports work to do.
The gate fires after the atomic claim and before the actual run, so only the worker that won the lease evaluates the gate.
Quick Start
1
YAML (simplest)
Add
pre_run to your agents.yaml schedule block. The agent only runs when the script exits 0 with output.2
Python
Set
pre_run directly on a ScheduleJob.3
CLI
Pass
--pre-run when adding a scheduled job.How It Works
The gate runs inasyncio.to_thread so a slow check does not block other scheduled ticks. If the gate itself raises an exception, the executor falls back to running the agent (defensive default).
Configuration Options
ScheduleJob fields
ScheduledAgentExecutor parameter
ShellConditionGate options
Gate decision table
Pre-Run Gate vs RunPolicy
Two complementary gates apply on every tick when both are configured:Common Patterns
Inbox watcher
Only fire when new mail arrives — cuts 288 daily runs to just the count of mail bursts.scripts/new_mail.sh exits 0 and prints new messages when mail is present; exits non-zero when the inbox is quiet.
CI babysitter
Alert a channel only when a build breaks.Custom Python gate
Use a callable resolver for richer logic than a shell exit code.Best Practices
Keep the gate cheap and deterministic
Keep the gate cheap and deterministic
The gate runs on every tick. Aim for under 1 second — a fast file check, an API ping, or a database row count. Avoid heavy computation.
Always set a sensible timeout
Always set a sensible timeout
The default
timeout=30.0 is conservative. A runaway gate stalls that tick’s slot. Set it to match your gate’s expected worst case.Use stdout to seed the prompt
Use stdout to seed the prompt
The same check that gates the run can feed it the data — the gate’s stdout is automatically appended to the message.The agent then receives:
"Summarise these new emails... <new mail subjects>".Don't put secrets in pre_run
Don't put secrets in pre_run
The
pre_run string is stored verbatim in the job record. Use environment variables or a secrets manager instead of inline credentials.pre_run is CLI/YAML/Python-only — never LLM-callable
pre_run is CLI/YAML/Python-only — never LLM-callable
The agent-callable
schedule_add tool deliberately does not accept pre_run. This prevents a prompt-injected agent from persisting arbitrary shell commands on the host. Always configure pre_run through the CLI, YAML, or Python code.Understand skipped vs failed
Understand skipped vs failed
A gate returning non-zero records the tick as
skipped (not failed) — this is expected normal operation when there’s nothing to do. Check your run history with praisonai schedule logs to see skip rates.Skip and Failure Reasons
When a tick is skipped or fails, theJobResult.error field contains one of these reasons:
When
deliver_on_failure is enabled on the RunPolicy, a failure summary is delivered to the channel:
⚠️ Scheduled job '<name>' failed: <error>
JobResult Reference
Every tick yields a JobResult from praisonai_bot.scheduler:
Session Routing
session_target on ScheduleJob controls whether a scheduled tick reuses an existing channel session or gets its own isolated context.
session_id is passed only when the resolved agent.chat accepts a session_id keyword argument. The executor inspects the signature before passing it.
Imports: Bot-First and Wrapper Shims
Related
Async Agent Scheduler
The scheduler this gate plugs into
Scheduler Delivery
Push scheduled results to Telegram/Discord/Slack/WhatsApp
Scheduled Run Policy
Safety gate — tool scoping, prompt scan, and audit
Schedule CLI
CLI surface — where
--pre-run and --condition are configuredpraisonai-bot SDK
Full bot-tier SDK reference

