Manage automations through the API
The public API lets an integration create and inspect automations, then pause, resume, delete, or restore them. Edit and manual-run controls remain in the app and agent tools. Create an automation with the same trigger and run configuration used by the app. It starts enabled unless you send"enabled": false; requestId is the caller-stable idempotency key, so retries converge on the same automation:
incoming_webhook, the first successful response also carries webhookUrl; save it immediately because retries and later reads never return that credential. If that response is lost, delete the original by its returned or listed id and create a replacement with a new requestId.
List every automation your API-key principal can access, or narrow the page to one project:
deleted state. A service-user key with read_only access can only list; creating or changing state requires read_write or admin. Project allowlists apply to every automation operation, and an inaccessible id returns the same 404 as an unknown id.
See Common flows for a script-friendly sequence and the generated API reference for complete request and response schemas.
Triggers
An automation has 1 to 20 triggers, OR’d together: any one of them firing starts at most one run per event. At most one each of schedule, incoming webhook, and on-demand.
Each trigger can also carry additional conditions: repositories, branches, authors, and labels for GitHub; channels, authors, and text filters for Slack; substring and regex filters for webhooks. A condition matches when the event matches any of its listed values.
Schedules
Schedules are five-field cron and a IANA timezone, validated at save. The floor is one run per five minutes. DST follows wall-clock semantics in your timezone: a local time that doesn’t exist (spring forward) fires once at the next valid instant, and a local time that happens twice (fall back) fires once. If the scheduler falls behind, missed occurrences coalesce into a single run rather than a backlog.Slack bursts
A burst of Slack messages becomes a single run. Each matched message extends a sliding window (1–300 seconds, default 10); the group closes when the window elapses, a different author posts, or the burst hits its bounds (20 messages, 100 KB). The run gets the joined messages in order. The agent’s normal reply channel writes to the run’s thread. If you want the automation to post in Slack, say so in the prompt and Capy will use an explicit Slack message tool.The run-when gate
Trigger conditions are exact filters. For fuzzy conditions like “only when the message is a bug report”, add arun_when sentence to an event trigger. A fast model checks each matching event against it before the run starts. You are not billed for the fast model check.
Thread mode
thread_mode decides where runs land:
new: every run starts a fresh thread. The default, and right for independent jobs like a nightly check.single: the automation owns one standing thread, and every run delivers its event into it. The thread keeps its machine and its context across runs, so it’s right for accumulating work like triaging a channel.
Who the automation runs as
Every automation stores one explicit run-as principal, and every run executes as it: the person who saved the automation, or a service user an admin selected. The triggering actor (the Slack author, the GitHub sender) is never the principal; they appear only inside the event context.- Eligibility is re-verified on every run: live user, live membership, live service-user state, project access.
- If the principal is offboarded (user removed, service user disabled), the run fails naming the check that failed, and the automation is disabled with a visible reason. Re-enabling requires picking an eligible principal.
- Commits attribute to the principal: a human’s runs commit as their interactive threads do; a service user’s runs commit under its display name with Capy’s bot address.
- Model rights are the principal’s: a pinned model the principal can’t use fails at save, and rights lost later fail the run visibly, never a silent substitution.
The webhook trigger
An incoming-webhook automation gets a URL of the form:Authorization header. Treat it like a password: it’s generated server-side, shown once at creation or rotation, and stored only as a digest. Rotation is an immediate cutover; the old URL stops working in the same instant the new one is shown.
Idempotency-Keydeduplicates: retries with the same key start one run. Without it, every delivery is distinct.- Bodies are capped at 256 KB (413 above that), and the first 8,000 characters reach the agent as context.
- Responses:
202withaccepted,duplicate, orno-matchin the body (a body your trigger’s filters reject is a valid delivery that starts no run; don’t retry it);404for an unknown or disabled automation, deliberately indistinguishable;500means retry.
Limits
max_runs_per_day is an opt-in daily cap counting runs admitted across all triggers. An over-cap event records a skipped run naming the cap, so throttling is visible in run history, never silent. Unset means no cap.
Examples
- Nightly dependency check. Schedule
0 3 * * *, prompt: audit dependencies for security advisories and open a PR bumping anything vulnerable. - Follow-up on every merged PR. GitHub
pull_request_merged, prompt: check the merged change for docs that now lie and fix them. - CI failure fixer. GitHub
workflow_runwith conclusionfailureon your main branch, prompt: read the failing job, fix the cause, open a PR. - Slack support triage. Slack messages in
#supportwith arun_whenof “the message reports a bug”,singlethread mode, prompt: reproduce, file the issue, link it back. - Deploy-failure investigation. Incoming webhook from your deploy pipeline, prompt: read the payload, find the regressing commit, report with evidence.