> ## Documentation Index
> Fetch the complete documentation index at: https://arden.timganiev.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Automations

> Create and manage scheduled, event, idle, count, and message automations.

## Create automation

```bash theme={null}
curl -X POST http://localhost:6877/automations \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Morning briefing",
    "prompt": "Summarize unread emails and today's calendar. Report the briefing in the automation channel.",
    "description": "Weekday morning briefing",
    "trigger_type": "time",
    "at": "09:00",
    "days": "weekdays",
    "idempotency_key": "automation:morning-briefing",
    "idempotency_scope": "global"
  }'
```

Notifier configuration is separate from automation creation. Use the notification/notifier settings or `/notifiers/*` endpoints.

### Idempotent creation

Every standalone `POST /automations` request must include a stable semantic `idempotency_key` and `idempotency_scope: "global"`. Reuse that exact key only to retry an ambiguous create. If an automation with that key already exists, inspect it and use `PATCH /automations/{task_id}` for changes; do not create a versioned replacement key. Deleting the automation releases its global key, allowing the same job to be recreated without renaming the key.

## Trigger options

**Scheduled:**

```json theme={null}
{"trigger_type": "time", "at": "09:00", "days": "weekdays"}
{"trigger_type": "time", "at": "22:00", "days": "mon,wed,fri"}
{"trigger_type": "time", "at": "08:00"}
```

**Interval:**

```json theme={null}
{"trigger_type": "time", "every": "2h"}
{"trigger_type": "time", "every": "30m", "start": "09:00", "end": "18:00"}
```

**Event-driven:**

```json theme={null}
{"trigger_type": "event", "event_type": "event_approaching", "lead_minutes": 15}
```

**Idle:**

```json theme={null}
{"trigger_type": "idle", "idle_minutes": 5}
```

**Count:**

```json theme={null}
{"trigger_type": "count", "every_n": 3}
```

## Multiple and message triggers

Pass a `triggers` array to combine triggers with OR logic. Each item uses
`type`, not the top-level `trigger_type` field:

```bash theme={null}
curl -X POST http://localhost:6877/automations \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Extract facts",
    "prompt": "Extract durable facts from recent conversation.",
    "description": "Conversation fact extraction",
    "triggers": [
      {"type": "count", "every_n": 5},
      {"type": "idle", "idle_minutes": 10}
    ],
    "cooldown_minutes": 10,
    "idempotency_key": "automation:extract-facts",
    "idempotency_scope": "global"
  }'
```

Slack message triggers also use `triggers`. Supply channel names; Arden
resolves and stores stable Slack IDs when it saves the automation.

```json theme={null}
{
  "triggers": [{
    "type": "message",
    "source": "slack",
    "channels": ["alerts"],
    "from_user": "incident-bot",
    "contains": ["incident"]
  }]
}
```

## Tool scoping and approval

`tool_scope` grants only the write/action tools an automation needs; read-only
tools remain available. `auto_approve=true` skips per-run approvals for those
already-granted tools and never expands the scope.

For example, a wiki-producing automation can use
`"tool_scope": ["create_wiki_page", "edit_wiki_page"]` with
`"auto_approve": true`.

Its prompt should list the target directory before creating a page, and read
the exact path before editing one. The backend protects a fresh read from being
overwritten; on a write conflict, list/read again before retrying. Ordinary
automation pages belong under `automations/`. `publish_wiki_generated` is
separate: use it only for a section owned by that automation.

If `tool_scope` is omitted, the run gets only the read-only tool floor.

## List automations

```bash theme={null}
curl http://localhost:6877/automations \
  -H "Authorization: Bearer $API_KEY"
```

## Get automation

```bash theme={null}
curl http://localhost:6877/automations/1 \
  -H "Authorization: Bearer $API_KEY"
```

## Update automation

```bash theme={null}
curl -X PATCH http://localhost:6877/automations/1 \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"prompt": "New standalone task instructions"}'
```

## Toggle enable/disable

```bash theme={null}
curl -X POST http://localhost:6877/automations/1/toggle \
  -H "Authorization: Bearer $API_KEY"
```

## Toggle auto-approve

Allow a headless automation to skip per-call approval for mutating/external
tools already granted by its `tool_scope`. This setting does not grant tools:

```bash theme={null}
curl -X POST http://localhost:6877/automations/1/auto-approve \
  -H "Authorization: Bearer $API_KEY"
```

The response includes the updated `auto_approve` value.

## Run immediately

```bash theme={null}
curl -X POST http://localhost:6877/automations/1/run \
  -H "Authorization: Bearer $API_KEY"
```

## Runs and events

```bash theme={null}
curl http://localhost:6877/automations/1/runs \
  -H "Authorization: Bearer $API_KEY"

curl http://localhost:6877/automations/events \
  -H "Authorization: Bearer $API_KEY"
```

## Delete automation

```bash theme={null}
curl -X DELETE http://localhost:6877/automations/1 \
  -H "Authorization: Bearer $API_KEY"
```

## Loops

Loops run repeatedly in an existing chat and stop when their condition is met.
They do not create a separate automation channel.

| Method   | Endpoint                | Purpose                                          |
| -------- | ----------------------- | ------------------------------------------------ |
| `POST`   | `/loops`                | Create a loop for a `session_id`                 |
| `GET`    | `/loops?session_id=...` | List one chat's loops                            |
| `PATCH`  | `/loops/{task_id}`      | Change prompt, cadence, limits, or enabled state |
| `DELETE` | `/loops/{task_id}`      | Stop and remove a loop                           |
