Skip to main content

Agent Automations

Automations run a configured agent without a human in the loop — on a cron schedule, or in response to a business event. Every automated run flows through the same durable headless run path as an API-initiated run, so it inherits:
  • Durability — a headless_agent_runs row you can poll or stream.
  • One-run-per-agent — a second dispatch while a run is executing is skipped (schedules) or 409 AGENT_BUSY (API/run-now).
  • Lifecycle webhooksagent_run.pending_approval, agent_run.completed, agent_run.failed (see Webhooks).
  • The approval loop — risky (require_approval) actions pause the run at pending_approval instead of executing unattended.
Triggers live under an agent and are managed with the agents.manage permission and the ai suite.

Trigger types

Supported event types today:
  • Scheduling: shift.started, shift.completed, shift.ncns, shift.first_approaching
  • Workforce / HR: staff.onboarded (a new staff member is created or an applicant/candidate is hired)
  • CRM: lead.qualified (a lead transitions to qualified)
  • Compliance: credential.expired (a credential expires, from the watchdog or a manual verification)
eventFilters are dot-path equality checks against the event payload (an empty filter matches everything) — e.g. { "facilityId": 3 } or { "type": "license" }.
A trigger’s failure streak (consecutiveFailures) now reflects run outcomes, not just dispatch failures: a run that errors mid-flight increments the streak, and a run that completes clears it. Once the streak hits the threshold the trigger is auto-disabled (audited as agent_trigger.auto_disabled). This means an agent that repeatedly errors — not merely one that fails to enqueue — is quarantined.

Create a schedule trigger

The dispatcher polls once a minute, computes the next occurrence in the trigger’s timezone (DST-aware), and writes lastRunAt / nextRunAt. A schedule trigger that raises 5 consecutive dispatch failures is auto-disabled (isActive: false).

Create an event trigger

Run identity and privilege-escalation guard

Each run acts as runAsUserId — this drives the tool scope and RBAC, so an automation can never do more than that user is permitted. It defaults to the caller. Binding a different user is only allowed for internal operators; otherwise the API returns 403 RUN_AS_FORBIDDEN.

Governance for unattended writes

Because nobody is at the keyboard, a scheduled/event agent that performs risky writes will pause at pending_approval and emit agent_run.pending_approval. Wire that webhook to an approver workflow (resolve via /api/approvals/{approvalId}/approve or /reject, requires agents:approve), or give the agent auto_execute autonomy if the writes are safe to run unattended. Every automated run start and every trigger mutation writes an audit entry.

Other operations

Run history for the fired runs is available via the headless run API (GET /api/agents/{id}/runs, agents:run scope).