Skip to main content
Schedule lifecycle hooks fire when a scheduled job is persisted, deleted, or triggered — so your audit log or metrics endpoint sees the whole life of every job, no matter who created it.

Quick Start

1

Register a hook

Register one hook on the default registry for SCHEDULE_ADD.
2

Give an Agent the tool

Hand the agent the schedule_add tool — the store fires your hook when the agent persists a job.

How It Works

SCHEDULE_ADD and SCHEDULE_REMOVE are emitted by the schedule store — the one chokepoint every add/remove path funnels through — after its locks release.

What Fires (and What Doesn’t)

Events fire only on a real change.

Payload Reference

ScheduleAddInput (fires on SCHEDULE_ADD): ScheduleRemoveInput (fires on SCHEDULE_REMOVE): Both inherit session_id, cwd, event_name, timestamp, and agent_name from HookInput (agent_name is the job’s agent_id if set, else "scheduler").
Both types are importable from praisonaiagents.hooks: from praisonaiagents.hooks import ScheduleAddInput, ScheduleRemoveInput.

Common Patterns

Audit log

Append every add and remove to a JSONL file.

Per-tenant quota

Count active schedules per principal.

One-shot metric

Push a metric when a spent one-shot is auto-removed.

Emission Discipline

  • Hooks fire after the store releases its locks — safe to call back into the store.
  • Zero cost when nothing is registered: a single has_hooks lookup and the emitter returns.
  • A raising hook cannot roll back the mutation and is logged at debug.
  • Do not rely on ordering across processes; a SCHEDULE_ADD from one gateway process and a SCHEDULE_REMOVE from another may arrive in any order.
Inside a running asyncio loop, emission is fire-and-forget; asyncio.run(...) around your code works because the emitter handles both loop states.

Best Practices

Hooks may run inside an async event loop. Avoid blocking I/O; offload heavy work to a queue.
For multi-tenant setups, check event_data.principal at the top of the hook and return HookResult.allow() immediately when it doesn’t match.
These events are observability-only — the store proceeds regardless of HookResult.deny(...). To control who can create schedules, gate the callers: guardrails on the tool, auth on the CLI.
Use event_data.job_id, not event_data.job_name, as the stable key — names can be reused.

Hook Events

Full event reference for every lifecycle hook.

Schedule Tools

The agent-callable tools that trigger these hooks.

Schedule CLI

The CLI that triggers these hooks.

Bot Lifecycle Hooks

Sibling gateway lifecycle events.