Explore these docs
For agentsDocumentation

Recurring work, approved by a person.

An automation is work a Ployed employee repeats on a schedule: "find every new model release once a day", "summarize open pull requests every weekday at 8:30". Your agent can propose one, read it, pause it, or retire it. A person in the organization always approves it first.

How it works

  1. Your agent proposes an automation with POST /v1/automations or the ployed_propose_automation MCP tool.
  2. Ployed sends an approval card to the person your credential belongs to, as a Slack direct message (or in the console). The card shows the schedule in plain words, the next run, what it does, which apps it uses, what it may send without asking, and the estimated cost.
  3. The person approves or declines the exact version on the card. An API client can never approve an automation: there is no approve route, no approve tool, and no scope that grants it.
  4. Once approved, the employee runs it on schedule. Each run posts its results where the card said (a new Slack thread per run by default) and records an outcome.

Until a person approves, nothing runs. An unanswered card expires after 7 days.

Schedules

Scroll sideways to see all three columns: Cadence, Fields, and Runs.

CadenceFieldsRuns
dailytimeEvery day
weekdaystimeMonday to Friday
weeklytime, days (1 = Monday … 7 = Sunday)The days you choose
monthlytime, day_of_month (1–28 or "last")Once a month
every_n_hoursn (1, 2, 3, 4, 6, 8 or 12), optional window_start/window_endEvery n hours
onceat (local YYYY-MM-DDTHH:MM)One time

The minimum interval is one hour for every organization. Times are local to the IANA timezone you give (the person's own timezone by default) and stay correct across daylight-saving changes. Unless you set exact_time, Ployed picks a fixed minute within the first quarter hour so many "daily at 9" automations do not all start at once; the card shows the real minute. A run that was missed during an outage is skipped, not run late.

Budgets and limits

  • Per run: $1.00 by default (max_cost_usd_per_run, up to $10). A run that reaches it is stopped and recorded as failed.
  • Per month: $30 by default (max_cost_usd_per_month, up to $500). Once reached, the remaining runs that month are skipped and the person is told once.
  • Per run time: 20 minutes by default (max_minutes_per_run, up to 40).
  • Failures: after 3 failed runs in a row (auto_pause_after) the automation pauses itself and tells the person.

Cost figures on the card are estimates and say "about". Lowering a budget applies at once; raising one needs a person's approval.

Only new results

With only_new, each run remembers which items it already reported (up to 5,000 keys, each kept at most 180 days) and reports only new ones. Use item_key_hint to say what identifies an item, such as "model id" or "pull request number". When a run finds nothing new it still posts a one-line note, so there is never doubt that it ran; set when_nothing_new to stay_quiet for a frequent monitor.

Sends that do not ask first

By default every send, reply, post, publish, share or submit an unattended run makes waits for a person. A proposal may list preapproved_effects: an exact tool, the exact destination it is bound to (a channel, a recipient address, a repository) and a per-run count. The card names each one, and only a call that matches exactly runs without asking. A different destination, an extra recipient, or one more than the count asks a person as usual.

Destructive steps can never be pre-approved: merge, delete, destroy, drop, erase, purge, truncate, revoke and archive always ask a person, every time.

Scopes

Scroll sideways to see all three columns: Scope, Allows, and Credentials.

ScopeAllowsCredentials
automations:readList automations, read one, list its runsOAuth grants and agent keys (pak_)
automations:proposePropose an automation; a person approves itOAuth grants only
automations:managePause, retire, and narrowing edits; a widening edit asks a personOAuth grants only

An OAuth grant is bound to the one person who consented, and every proposal or change is attributed to that person; approval cards go to them. Agent keys stay read-only for automations. Writes are limited to 30 per person per hour across all of that person's credentials; more returns 429 with code automation_rate_limited.

Routes

Scroll sideways to see all three columns: Route, Scope, and Effect.

RouteScopeEffect
GET /v1/automationsautomations:readList, with Ployed's own schedules read-only
GET /v1/automations/{id}automations:readSpec, revisions, next run, recent runs, cost
GET /v1/automations/{id}/runsautomations:readCursor page of runs
POST /v1/automationsautomations:propose202: proposed, approval card sent
PATCH /v1/automations/{id}automations:manage200 narrowing applied; 202 widening card sent
POST /v1/automations/{id}/pauseautomations:managePaused at once; only a person resumes
POST /v1/automations/{id}/retireautomations:manageStopped; a person can restore it for 30 days

The MCP tools ployed_list_automations, ployed_get_automation, ployed_list_automation_runs, ployed_propose_automation, ployed_update_automation, ployed_pause_automation and ployed_retire_automation take the same inputs and follow the same rules.

Propose

curl https://api.ployed.org/v1/automations \
  -H "authorization: Bearer $PLOYED_OAUTH_TOKEN" \
  -H 'content-type: application/json' \
  -d '{
    "employee": "chief-of-staff",
    "automation": {
      "title": "New model releases",
      "instruction": "Check for newly released models from the vendors we track and summarize each one: name, release date, what changed, link.",
      "cadence": { "kind": "daily", "time": "09:00" },
      "timezone": "America/New_York",
      "only_new": true,
      "item_key_hint": "model id"
    }
  }'

The response is 202 Accepted:

{
  "automation_id": "6f0c2c1e-8a8e-4f7e-9d4e-2b0d1c9a7f31",
  "revision": 1,
  "status": "proposed",
  "approval_required": true,
  "card": { "delivered": true, "where": "dm" },
  "schedule_words": "Every day at 9:07 AM Eastern",
  "next_runs": ["2026-10-06T13:07:00.000Z"],
  "estimate": { "per_run_usd": 0.12, "per_month_usd": 3.6, "fires_per_month": 30, "basis": "employee_runs_median", "fires_basis": "cadence", "samples": 14 },
  "detail": "Proposed. A person in the organization approves it in Slack or the console; nothing runs until they do. This credential cannot approve it."
}

Tell the person an approval card is waiting for them. Read the automation later to see whether it became active.

Change, pause, or retire

Narrowing (less often, fewer apps, a lower budget, quieter output) applies at once. Widening (more often, more apps, a higher budget, a new send without asking) creates a pending version and an approval card; the current version keeps running until a person approves:

curl -X PATCH "https://api.ployed.org/v1/automations/$AUTOMATION_ID" \
  -H "authorization: Bearer $PLOYED_OAUTH_TOKEN" \
  -H 'content-type: application/json' \
  -d '{ "changes": { "cadence": { "kind": "every_n_hours", "n": 4 } }, "base_revision": 1 }'
{
  "automation_id": "6f0c2c1e-8a8e-4f7e-9d4e-2b0d1c9a7f31",
  "applied": "pending_approval",
  "revision": 2,
  "widening_reasons": ["more_frequent"],
  "narrowings": [],
  "code": "automation_widening_requires_approval",
  "recovery": "An approval card was sent; the current version keeps running until a person approves the change."
}
curl -X POST "https://api.ployed.org/v1/automations/$AUTOMATION_ID/pause" \
  -H "authorization: Bearer $PLOYED_OAUTH_TOKEN" \
  -H 'content-type: application/json' \
  -d '{ "reason": "Paused while the team is offsite" }'

Resuming a paused automation and restoring a retired one are for people only, in Slack or the console.

Refusals

A refusal is a problem document with reason: "automation_refused" (or rate_limited), a closed code and a recovery that says what to do next. Common codes: automation_disabled_for_org (automations are not available for this workspace), automation_not_found (no automation with that id is visible to you), automation_invalid_spec (the errors list names the fields), automation_app_not_granted, automation_instruction_contains_secret (connect the app instead of pasting a key), automation_effect_not_preapprovable, automation_revision_superseded and automation_rate_limited.

Machine-readable contracts

Keep exploringAPI quickstart