---
slug: tasks
title: Tasks
---

# Tasks

Agents aren't limited to live conversations. With Tasks, you can run an agent on a schedule, fire it from an external event, have it pause mid-run for a human to sign off, and review the full record of every run it has ever made.

The **Agentic** section of the dashboard — accessible from the left nav — is where you manage all of this.

---

## What is a task?

A task is a reusable unit of work: a name, a prompt the agent follows, and optionally a set of agents, a schedule, or a webhook trigger attached to it. When a task fires, it produces a **run** — a timestamped record of what happened, which agents were involved, how many credits were used, and what the outcome was.

One task can fire many times. A "Nightly sales digest" task, for example, might fire every morning on a schedule, each fire producing its own run in the Activity log.

---

## Creating a task

Go to **Agentic > Tasks** and click **New task**. You can create a task in two ways:

| Option | When to use |
|---|---|
| **Manual** | You know exactly what the task should do. Give it a name and configure the prompt, agents, and triggers yourself. |
| **Create with AI** | Describe what you want in plain language. The AI wizard drafts the task, writes a plan, runs a test, and activates it — step by step. |

The AI wizard walks through six steps: create → requirements → add agents → set trigger → test run → publish. You can leave the wizard at any step and return to it later.

### Plan

Tasks have an optional **plan** — a structured description of what the agents should do, in what order, and what success looks like. The AI wizard generates a plan automatically and asks you to approve it before the task can be enabled.

You can also write a plan manually from the task's detail page. A task without an approved plan can still be test-run, but cannot be enabled for live scheduled or webhook-triggered runs.

---

## Trigger types

Every run has a trigger type that records how it was started:

| Type | How it fires |
|---|---|
| **Conversational** | A visitor's chat session invokes the task mid-conversation |
| **Scheduled** | A cron schedule fires it automatically |
| **Webhook** | An external system POSTs to the task's trigger URL |
| **Manual** | You clicked **Run** from the dashboard |

---

## Scheduled runs

Schedules fire a task automatically on a timetable you define. Go to **Agentic > Schedules** and click **New schedule**, or create one in the final step of the AI wizard.

See [Scheduled runs](/docs/ask/schedules) for full details — cron syntax, timezone handling, retry settings, and limits.

---

## Inbound webhook triggers

A webhook trigger gives a task a public URL that external systems can POST to — firing the task whenever something happens in your own infrastructure (a new Stripe payment, a GitHub PR, a nightly cron from your own server).

### Creating a trigger

Go to **Agentic > Triggers** (or the Triggers tab on a task's detail page) and click **New trigger**.

| Field | Description |
|---|---|
| **Name** | A human-readable label (e.g. *Stripe payment received*) |
| **Task** | The task to fire when this URL is called |
| **Agent** | Which agent runs the task. Defaults to the first assigned agent |

When you save, Elaras shows the **dispatch URL** and a **signing secret** — copy the secret immediately, it is only shown once. If you lose it, rotate it from the trigger settings to generate a new one (the old one stops working).

### Dispatching a trigger

Send a `POST` request to the dispatch URL with:
- A `Content-Type: application/json` body — any JSON object you want the agent to see
- An `X-Elaras-Signature` header containing an HMAC-SHA256 signature of the raw request body

The signature format is `sha256=<hex>`. Compute it by HMAC-signing the raw body bytes with your secret:

```js
// Node.js
import crypto from 'crypto';

const secret  = process.env.ELARAS_TRIGGER_SECRET;
const body    = JSON.stringify({ event: 'payment.succeeded', amount: 9900 });
const sig     = 'sha256=' + crypto.createHmac('sha256', secret).update(body).digest('hex');

await fetch('https://app.elaras.ai/api/v1/dispatch/<slug>', {
  method:  'POST',
  headers: { 'Content-Type': 'application/json', 'X-Elaras-Signature': sig },
  body,
});
```

```python
# Python
import hmac, hashlib, json, requests, os

secret = os.environ['ELARAS_TRIGGER_SECRET'].encode()
body   = json.dumps({'event': 'payment.succeeded', 'amount': 9900})
sig    = 'sha256=' + hmac.new(secret, body.encode(), hashlib.sha256).hexdigest()

requests.post(
    'https://app.elaras.ai/api/v1/dispatch/<slug>',
    headers={'Content-Type': 'application/json', 'X-Elaras-Signature': sig},
    data=body,
)
```

A successful dispatch returns `202 Accepted`:

```json
{
  "status": "accepted",
  "task_id": 1042
}
```

### Response codes

| Code | Meaning |
|---|---|
| `202` | Trigger fired — run is queued or running |
| `200` | Already processed — this `Idempotency-Key` was seen before (see below) |
| `401` | `X-Elaras-Signature` header missing |
| `403` | Signature mismatch — check secret and that you're signing the raw body |
| `404` | Trigger URL not found |
| `410` | Trigger exists but is disabled |
| `422` | Request body is not valid JSON |

### Idempotency

If your dispatch system might retry on failure (Stripe, GitHub, Slack, and most webhook providers all do), pass an `Idempotency-Key` header — a unique string for this event, up to 128 characters. Elaras will deduplicate: if the same key is received again within 24 hours, it returns `200` with the original `task_id` instead of firing again.

```
Idempotency-Key: evt_stripe_abc123def456
```

---

## Human approvals

Some actions are too high-stakes to run automatically — issuing a refund, sending a bulk email, making a booking that can't be cancelled. Approvals let you gate a flow state behind a human sign-off before the agent proceeds.

### Adding an approval gate to a flow

In your flow definition, add an `approval` block to any state that requires sign-off:

```json
{
  "states": {
    "confirm_refund": {
      "message": "I'm ready to issue the refund. This is waiting for admin approval.",
      "approval": {
        "required": true,
        "policy": "any_admin",
        "note_required": true,
        "expires_in_minutes": 1440
      },
      "transitions": {
        "approved": "refund_issued",
        "rejected": "refund_denied"
      }
    }
  }
}
```

| Field | Description |
|---|---|
| `required` | Must be `true` to enable the gate |
| `policy` | Who can approve — see policies below |
| `note_required` | If `true`, the reviewer must write a reason before approving or rejecting |
| `expires_in_minutes` | How long before the request auto-expires. Omit for no expiry |

### Reviewer policies

| Policy | Who can review |
|---|---|
| `any_admin` | Any team member with the Admin role |
| `user:<id>` | One specific user (e.g. `user:42`) |
| `role:<name>` | Any user holding a named role (e.g. `role:finance`) |

### The review flow

When an agent reaches an approval-gated state:

1. The session pauses and the agent tells the visitor the action is awaiting sign-off
2. Elaras sends an email to eligible reviewers with a link to the pending approval
3. The reviewer opens **Agentic > Approvals**, reads the context, and clicks **Approve** or **Reject** (with a note if required)
4. On **approve**: the session resumes and advances to the `approved` transition target
5. On **reject**: the session routes to the `rejected` transition target (or exits the flow if none is defined)

Every approval request and resolution is recorded on the run's Activity log, so you have a complete audit trail.

---

## Activity log

**Agentic > Activity** shows every run across all tasks and agents, in reverse chronological order.

Filter the list by:
- **Status** — queued, running, completed, failed, cancelled
- **Trigger** — scheduled, webhook, manual, conversational
- **Agent** — filter to a specific agent

Each row shows the agents involved, the run status, when it started, and how many credits it used. Click a row to open the run detail page — a full timeline of every step the agent took, including tool calls, sub-agent consults, skill results, and approval events.

### Run statuses

| Status | Meaning |
|---|---|
| **Queued** | The run has been accepted and is waiting to start |
| **Running** | The agent is actively working |
| **Completed** | The run finished successfully |
| **Failed** | The run encountered an error it could not recover from |
| **Cancelled** | The run was stopped before completion |

### Retrying a failed run

If a run fails and you want to try it again, open **Agentic > Activity**, find the failed run, and click **Retry**. This creates a new manual run against the same task and navigates you to the new run's detail page.

For automated retries on scheduled runs, configure the **Retries** setting on the schedule — see [Scheduled runs](/docs/ask/schedules).

---

## Credits

Each run deducts credits from your balance based on the model and number of tokens used. Multi-step runs (with multiple agent calls or sub-agent consults) deduct credits for each step. Retries — whether automatic or manual — each deduct credits independently.

You can see the credit cost for any run in the Activity log under the **Details** column.

---

## Plan limits

The number of tasks you can create depends on your plan:

| Plan | Tasks |
|---|---|
| Starter | 2 |
| Growth | 5 |
| Business | Unlimited |
