> Source: https://wexa.ai/docs/automation/create-schedule

# create-schedule

[Can be held for approval](/docs/sdks-and-apis/how-every-tool-call-works#lifecycle-and-governance)

Schedule an agent or a process flow to run unattended, and return its `schedule_id`. Needs the `fabric:orchestrate.write` grant.

**Create a schedule**

**Wexa MCP server**

```bash
curl -sS -X POST https://fabric.wexa.ai/mcp/$FABRIC_PROJECT_ID \
  -H "authorization: Bearer $FABRIC_API_KEY" \
  -H "Mcp-Session-Id: $MCP_SESSION_ID" \
  -H "content-type: application/json" -H "accept: application/json" \
  -d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"create-schedule","arguments":{"agentflow_id":"6ab1945e7566f41b5c28e303","goal":"Created to capture delete-schedule, then deleted.","frequency":"0 9 * * 1"}}}'
```

```json
{
  "content": [
    {
      "type": "text",
      "text": "{\"lifecycle_id\":\"qlc_000211\",\"result\":{\"schedule_id\":\"6ab196817566f41b5c28e341\",\"agentflow_id\":\"6ab1945e7566f41b5c28e303\",\"goal\":\"Created to capture delete-schedule, then deleted.\",\"frequency\":\"0 9 * * 1\",\"type\":\"recurring\",\"status\":\"active\",\"run_count\":0}}"
    }
  ],
  "isError": false
}
```

**REST API**

```bash
curl -sS https://fabric.wexa.ai/v1/create-schedule \
  -H "authorization: Bearer $FABRIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"agentflow_id":"6ab1945e7566f41b5c28e303","goal":"Created to capture delete-schedule, then deleted.","frequency":"0 9 * * 1"}'
```

```json
{
  "lifecycle_id": "qlc_000211",
  "result": {
    "schedule_id": "6ab196817566f41b5c28e341",
    "agentflow_id": "6ab1945e7566f41b5c28e303",
    "goal": "Created to capture delete-schedule, then deleted.",
    "frequency": "0 9 * * 1",
    "type": "recurring",
    "status": "active",
    "run_count": 0
  }
}
```

**TypeScript SDK**

```ts
import { Fabric } from '@wexa-fabric/sdk'

const fabric = new Fabric()
const result = await fabric.createSchedule({
  agentflow_id: '6ab1945e7566f41b5c28e303',
  goal: 'Created to capture delete-schedule, then deleted.',
  frequency: '0 9 * * 1'
})
```

```ts
// result is the payload itself, with no `.result` to read
{
  schedule_id: '6ab196817566f41b5c28e341',
  agentflow_id: '6ab1945e7566f41b5c28e303',
  goal: 'Created to capture delete-schedule, then deleted.',
  frequency: '0 9 * * 1',
  type: 'recurring',
  status: 'active',
  run_count: 0
}
```

**Python SDK**

```python
from wexa import Fabric

fabric = Fabric()
out = fabric.create_schedule(
    agentflow_id="6ab1945e7566f41b5c28e303",
    goal="Created to capture delete-schedule, then deleted.",
    frequency="0 9 * * 1",
)
```

```python
# out is the result, already unwrapped
{
    "schedule_id": "6ab196817566f41b5c28e341",
    "agentflow_id": "6ab1945e7566f41b5c28e303",
    "goal": "Created to capture delete-schedule, then deleted.",
    "frequency": "0 9 * * 1",
    "type": "recurring",
    "status": "active",
    "run_count": 0
}
```

## Parameters

| Parameter | Type | Required | Notes |
| --- | --- | --- | --- |
| `agentflow_id` | string | Required | Id of the agent or process flow to run, the same id `run-agent` and `run-process-flow` take. For an agent from `list-agents`, use the part of its id before the dot. A malformed id is refused. An agent or process flow in this project; a compound agent id is accepted whole (see [identifiers](/docs/sdks-and-apis/identifiers)). |
| `goal` | string | Required | What the agent or process flow should do on each run. Non-empty. |
| `end_at` | integer | Optional | Unix seconds, in the future, after which a recurring schedule stops firing. Recurring only. |
| `frequency` | string | Optional | Cron expression "min hour day month weekday", repeating. Supply exactly one of `frequency` or `run_at`. |
| `limit` | integer | Optional | Stop after this many runs. Recurring only. |
| `run_at` | integer | Optional | Unix seconds for a single run, in the future. Supply exactly one of `frequency` or `run_at`. Refused together with `limit`, `end_at` or `time_zone`. |
| `table` | object | Optional | Bind to a [Data Table](/docs/data-tables/overview): each firing picks up the next matching row and substitutes it into the goal. Needs `table_id`; the filter shape is under More details. |
| `time_zone` | string | Optional | IANA zone the cron's wall-clock time was written in, e.g. Asia/Kolkata. Recurring only. |

**Show full response**

A real response, captured from a live call to `create-schedule`:

**Result of create-schedule**

**REST API**

```json
{
  "lifecycle_id": "qlc_000211",
  "result": {
    "agentflow_id": "6ab1945e7566f41b5c28e303",
    "conclusion": null,
    "created_at": 1790023297.717658,
    "created_by": "6a79a770b6c128ccc24bfca7",
    "end_at": null,
    "frequency": "0 9 * * 1",
    "goal": "Created to capture delete-schedule, then deleted.",
    "last_execution_id": null,
    "limit": null,
    "run_at": null,
    "run_count": 0,
    "schedule_id": "6ab196817566f41b5c28e341",
    "status": "active",
    "time_zone": null,
    "type": "recurring",
    "updated_at": null
  }
}
```

**TypeScript SDK**

```ts
// the object you get back IS the result — there is no `.result` to read
{
  agentflow_id: '6ab1945e7566f41b5c28e303',
  conclusion: null,
  created_at: 1790023297.717658,
  created_by: '6a79a770b6c128ccc24bfca7',
  end_at: null,
  frequency: '0 9 * * 1',
  goal: 'Created to capture delete-schedule, then deleted.',
  last_execution_id: null,
  limit: null,
  run_at: null,
  run_count: 0,
  schedule_id: '6ab196817566f41b5c28e341',
  status: 'active',
  time_zone: null,
  type: 'recurring',
  updated_at: null
}

// The TS SDK names these camelCase — lifecycleId, traceId — where Python uses
// lifecycle_id and trace_id. Both are non-enumerable: readable, but omitted by
// Object.keys() and JSON.stringify(). `result.lifecycleId` here is undefined.
result.lifecycleId // 'qlc_000211'
```

**Python SDK**

```python
# a dict subclass; `result` is already unwrapped
{
 "agentflow_id": "6ab1945e7566f41b5c28e303",
 "conclusion": None,
 "created_at": 1790023297.717658,
 "created_by": "6a79a770b6c128ccc24bfca7",
 "end_at": None,
 "frequency": "0 9 * * 1",
 "goal": "Created to capture delete-schedule, then deleted.",
 "last_execution_id": None,
 "limit": None,
 "run_at": None,
 "run_count": 0,
 "schedule_id": "6ab196817566f41b5c28e341",
 "status": "active",
 "time_zone": None,
 "type": "recurring",
 "updated_at": None
}

out.lifecycle_id  # 'qlc_000211' — an attribute, not a key
```

**More details**

A schedule runs the agent or process flow with its `goal` each time it fires. The result is the schedule: its `schedule_id`, `type` (`recurring` or `once`), `status` (`active`), a `run_count` of 0 and the `frequency` you set. The schedule is attributed to the user whose key was used.

Each schedule counts its runs in `run_count` and records the latest in `last_execution_id`, which `get-execution` takes unchanged. Read it back with [`get-schedule`](/docs/automation/get-schedule), pause, resume or retire it with [`update-schedule`](/docs/automation/update-schedule), and remove it with [`delete-schedule`](/docs/automation/delete-schedule).

**Binding to a table.** The `table` object takes a required `table_id` and an optional `search_filters` list. Each filter is `{column, operator, value, type}`: `column` is a column name or `column_id` as `get-table` reports it, `operator` is one of `eq`, `gt`, `gte`, `in`, `lt`, `lte`, `ne`, `nin`, `value` is an array for `in` and `nin`, and `type` is the column type, e.g. string, number or datetime.

A schedule is one way to start a run without a person asking. A [trigger](/docs/automation/set-triggers) starts one on an event or a time set on an agent, connector or table.

Marked consequential: it is audited in full, and a policy rule may hold it for a person to approve. See [Policy and approvals](/docs/governance/policy-and-approvals).

Every tool call works the same way: [How every tool call works](/docs/sdks-and-apis/how-every-tool-call-works).
