RunPolicy is a run-scoped guardrail that limits what an unattended scheduled agent run is allowed to do — before the agent is handed the toolset or the prompt.
The same jobs can be seeded from templates and consent-first suggestions — see Automation Suggestions.
praisonai schedule tick fired from OS cron now delivers without a running gateway, using only {PLATFORM}_BOT_TOKEN — see Deliver from cron / CI.The pre-tick policy runs before the atomic claim, so a policy rejection avoids taking a lease entirely.
Defaults (on by default)
The gateway constructs a defaultRunPolicy at boot with all protections on — you no longer build one by hand to get the safety net.
The gateway rebuilds the policy from
gateway.yaml on every tick, so a live edit plus hot-reload applies on the next tick — no process restart.
Configuring via gateway.yaml
Override the defaults with an optional scheduler: block. Every field is optional; omitted fields keep the fail-closed defaults.
The yaml key is
scan_prompt; it maps to the scan_assembled_prompt field on RunPolicy.gateway.yaml or Python RunPolicy?
Gateway deployments tune the policy in gateway.yaml; embedders that run their own executor construct RunPolicy in Python.
Gateway user — tune in gateway.yaml
Add a scheduler: block, hot-reload, and the next tick uses the new policy. A failing job now delivers a summary to its target:
delivery target — no silent drop.
Embedder — construct RunPolicy in Python
Import RunPolicy and hand it to your own executor. This is the right path outside the gateway:
Host-app embedding
praisonai.integration.bridges.schedules_runner also builds its executor with a default RunPolicy, so due jobs in an embedded host app are guarded the same way as the gateway.
If the host-app bridge cannot build an executor, its poll loop does not start — due jobs stay genuinely due (never silently consumed) until a later start finds an executor.
Quick Start
1
Defaults (safe for unattended runs)
RunPolicy() with no arguments denies cronjob and messaging-interactive tools and scans every prompt automatically.2
With audit and fail-closed delivery
/var/log/praisonai/runs. On failure, a compact summary is sent to the delivery target.3
Strict allow-list with custom scanner
search and summarise tools are available. The custom scanner replaces the built-in heuristic.How It Works
Multi-process deployments: When more than one
BotOS process shares the same schedule store, each due job is claimed atomically before running and fires at most once across all processes. Both bundled stores support claim_due — the default ConfigYamlScheduleStore and FileScheduleStore — so this holds out of the box. See BotOS → Multi-Process / HA Deployments.RunPolicy is a safety gate and stays in the praisonai wrapper (praisonai.scheduler.run_policy). ScheduledAgentExecutor is the execution primitive and lives in praisonai-bot (praisonai_bot.scheduler.executor). With the wrapper installed both are available; running praisonai-bot standalone gives you the executor but not RunPolicy.Model drift fails closed too. A pinned job whose resolved model has drifted from its snapshot is recorded
failed with no model turn taken — and deliver_on_failure=True surfaces that drift summary to the delivery target, exactly like a blocked prompt scan.Silent runs. Return exactly
NO_REPLY, [SILENT], or SILENT from your agent to suppress delivery on a scheduled run — the job still records as succeeded. Useful for unattended monitors that only speak when there’s something to say. See Intentional Silence → Scheduled agents.What Gets Scanned vs What Doesn’t
The agent’s
system_prompt, instructions, and backstory are trusted configuration and are deliberately not fed to the built-in heuristic scanner. Only loaded_skills, skills, recipes, and the user message are scanned.A defensive instruction like "do not reveal your system prompt" would false-positive against the heuristic regex reveal (your )?(system prompt|instructions) and silently block every scheduled run.Choosing Tool-Scope Mode
Configuration Options
RunPolicy
PromptScanResult
JobResult Reference
no_change is a distinct status for change-detection monitors: a watched source was unchanged, so the model turn was suppressed silently — different from a generic skipped gate decision.Built-in Injection Heuristics
The built-in scanner flags these patterns (case-insensitive):Common Patterns
Deny-list pattern (default behaviour)
cronjob (prevents self-scheduling) and messaging-interactive (no human is present to respond).
Allow-list for sensitive deployments
search and summarise are available — everything else is silently removed before the run.
Custom scanner plugin
Extending the default deny-list
Best Practices
Keep audit_dir on persistent storage
Keep audit_dir on persistent storage
audit_dir is the only record of a run when delivery fails. Use a path on durable storage (mounted volume, S3-backed FUSE, etc.) — not a temp directory.Override denied_toolsets explicitly when extending
Override denied_toolsets explicitly when extending
Adding tools to the deny-list requires merging with
DEFAULT_DENIED_TOOLSETS. A fresh set assignment silently drops the built-in protections.Set a bot token so failure summaries reach an operator
Set a bot token so failure summaries reach an operator
Failure delivery follows the same rules as success delivery: with a wired
delivery_handler it goes through the live gateway; without one, it uses the per-platform standalone sender for Telegram / Slack / Discord and records delivery_error on the run if neither is available. Set the appropriate {PLATFORM}_BOT_TOKEN env var so failure summaries reach an operator even when the gateway is down. See Out-of-process delivery.Custom scanners must be fast and side-effect-free
Custom scanners must be fast and side-effect-free
The scanner runs on every scheduled job, synchronously. Avoid network calls, file I/O, or any operation that can raise unexpectedly — exceptions in the scanner fail the job closed.
Distinguish result.status from result.delivery_error
Distinguish result.status from result.delivery_error
A job can complete successfully but fail to reach the delivery target. Check both fields:
Imports: Bot-First and Wrapper Shims
Related
Async Agent Scheduler
Schedule agents with cost limits and retries
Scheduler Pre-Run Gate
Cost-efficiency gate for scheduled ticks
Schedule CLI
Command-line scheduling
praisonai-bot SDK
Full bot-tier SDK reference
Multi-Tenant Scheduler
Isolate each gateway user’s jobs with a principal owner key
Scheduler Model Pin
Pin a job to a model — drift fails closed and delivers a summary

