Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 20 additions & 2 deletions skills/base44-cli/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ my-app/
│ ├── entities/ # Entity schema definitions
│ │ ├── task.jsonc
│ │ └── board.jsonc
│ ├── functions/ # Backend functions (optional)
│ ├── functions/ # Backend functions (optional); automations live in function.jsonc
│ │ └── my-function/
│ │ ├── function.jsonc
│ │ └── index.ts
Expand All @@ -120,6 +120,7 @@ my-app/
**Key files:**
- `base44/config.jsonc` - Project name, description, site build settings
- `base44/entities/*.jsonc` - Data model schemas (see Entity Schema section)
- `base44/functions/*/function.jsonc` - Function config and optional `automations` (CRON, simple triggers, entity hooks)
- `base44/agents/*.jsonc` - Agent configurations (optional)
- `src/api/base44Client.js` - Pre-configured SDK client for frontend use

Expand Down Expand Up @@ -237,7 +238,8 @@ For complete documentation, see [entities-create.md](references/entities-create.
| Action / Command | Description | Reference |
| ------------------------- | --------------------------------------------- | ------------------------------------------------------- |
| Create Functions | Define functions in `base44/functions` folder | [functions-create.md](references/functions-create.md) |
| `base44 functions deploy` | Deploy local functions to Base44 | [functions-deploy.md](references/functions-deploy.md) |
| Configure Automations | CRON, simple triggers, entity hooks in `function.jsonc` | [automations.md](references/automations.md) |
| `base44 functions deploy` | Deploy local functions (and automations) to Base44 | [functions-deploy.md](references/functions-deploy.md) |

### Agent Management

Expand Down Expand Up @@ -283,6 +285,22 @@ Agents are conversational AI assistants that can interact with users, access you
- **Entity tools**: `entity_name` + `allowed_operations` (array of: `read`, `create`, `update`, `delete`)
- **Backend function tools**: `function_name` + `description`

#### Automation Quick Reference

Automations are triggers defined in the `automations` array inside `function.jsonc`. They deploy with the function via `base44 functions deploy`. Four types:

**Common fields (all types):** `name` (required), `description`, `function_args`, `is_active` (default: true)

**Scheduled One-Time:** `type: "scheduled"`, `schedule_mode: "one-time"`, `one_time_date` (ISO string)

**Scheduled CRON:** `type: "scheduled"`, `schedule_mode: "recurring"`, `schedule_type: "cron"`, `cron_expression`, optional `ends_type` / `ends_on_date` / `ends_after_count`

**Scheduled Simple:** `type: "scheduled"`, `schedule_mode: "recurring"`, `schedule_type: "simple"`, `repeat_unit` (`"minutes"` \| `"hours"` \| `"days"` \| `"weeks"` \| `"months"`), optional `repeat_interval`, `start_time`, `repeat_on_days` (0–6), `repeat_on_day_of_month` (1–31), `ends_type` / `ends_on_date` / `ends_after_count`

**Entity Hook:** `type: "entity"`, `entity_name` (matches entity schema name), `event_types`: array of `"create"` \| `"update"` \| `"delete"` (at least one)

For full schemas and examples, see [automations.md](references/automations.md).

### Site Deployment

| Command | Description | Reference |
Expand Down
343 changes: 343 additions & 0 deletions skills/base44-cli/references/automations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,343 @@
# Function Automations

Automations are triggers attached to backend functions. They cause a function to run automatically on a schedule (CRON, simple interval, or one-time) or when entity data changes (create, update, delete). Automations are defined in the `automations` array inside each function's `function.jsonc` and are deployed together with the function via `npx base44 functions deploy`.

## Overview

- **Where**: `base44/functions/<function-name>/function.jsonc` — optional `automations` array
- **Deploy**: Automations are deployed with the function; no separate command
- **Types**: Scheduled (one-time, CRON, simple interval) and entity hooks

## Common Fields (All Automation Types)

Every automation shares these base fields:

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `name` | string | Yes | Display name for the automation (min 1 char) |
| `description` | string \| null | No | Optional description |
| `function_args` | object \| null | No | Key-value args passed to the function when it runs |
| `is_active` | boolean | No | Whether the automation is active (default: `true`) |

## Automation Types

### 1. Scheduled One-Time

Runs the function once at a specific date/time.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `type` | `"scheduled"` | Yes | Must be `"scheduled"` |
| `schedule_mode` | `"one-time"` | Yes | One-time execution |
| `one_time_date` | string | Yes | ISO date/time when the function should run (e.g. `"2024-01-15T10:00:00"`) |

**Example:**

```jsonc
{
"name": "my-function",
"entry": "index.ts",
"automations": [
{
"name": "Launch reminder",
"type": "scheduled",
"schedule_mode": "one-time",
"one_time_date": "2026-03-01T09:00:00.000Z",
"description": "One-time reminder on launch day"
}
]
}
```

### 2. Scheduled CRON (Recurring)

Runs the function on a cron schedule. **Minimum interval is 5 minutes.**

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `type` | `"scheduled"` | Yes | Must be `"scheduled"` |
| `schedule_mode` | `"recurring"` | Yes | Recurring execution |
| `schedule_type` | `"cron"` | Yes | Use cron expression |
| `cron_expression` | string | Yes | Standard cron: `minute hour day-of-month month day-of-week` |
| `ends_type` | `"never"` \| `"on"` \| `"after"` | No | When the schedule stops (default: `"never"`) |
| `ends_on_date` | string \| null | No | When `ends_type` is `"on"`, ISO date to stop |
| `ends_after_count` | number \| null | No | When `ends_type` is `"after"`, number of runs then stop |

**End conditions** (apply to both CRON and simple recurring):
- `ends_type="never"` — Run indefinitely (default)
- `ends_type="on"` — Run until a date: set `ends_on_date` (e.g. `"2024-12-31T23:59:59"`)
- `ends_type="after"` — Run N times: set `ends_after_count` (e.g. `10`)

**Cron format:** `minute hour day-of-month month day-of-week`

**Examples:**
- `"*/5 * * * *"` — every 5 minutes (minimum interval)
- `"0 9 * * *"` — 9am daily
- `"0 9 * * 1-5"` — 9am every weekday (Mon–Fri)

**Example:**

```jsonc
{
"name": "daily-report",
"entry": "index.ts",
"automations": [
{
"name": "Daily Report",
"type": "scheduled",
"schedule_mode": "recurring",
"schedule_type": "cron",
"cron_expression": "0 9 * * *",
"description": "Run every day at 9:00 UTC",
"is_active": true
}
]
}
```

### 3. Scheduled Simple (Recurring Interval)

Runs the function on a simple repeat (every N minutes/hours/days/weeks/months). **Minimum interval for minutes is 5** (e.g. every 5 minutes).

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `type` | `"scheduled"` | Yes | Must be `"scheduled"` |
| `schedule_mode` | `"recurring"` | Yes | Recurring execution |
| `schedule_type` | `"simple"` | Yes | Use simple interval |
| `repeat_unit` | `"minutes"` \| `"hours"` \| `"days"` \| `"weeks"` \| `"months"` | Yes | Unit of repetition |
| `repeat_interval` | number | No | Positive integer; interval within the unit (default 1). For minutes, minimum is 5. |
| `start_time` | string \| null | No | Time of day (e.g. `"09:00"`, `"00:00"`) |
| `repeat_on_days` | number[] \| null | No | For weeks: 0–6 (0 = Sunday, 6 = Saturday) |
| `repeat_on_day_of_month` | number \| null | No | For months: 1–31 |
| `ends_type` | `"never"` \| `"on"` \| `"after"` | No | When the schedule stops (default: `"never"`) |
| `ends_on_date` | string \| null | No | When `ends_type` is `"on"`, ISO date to stop |
| `ends_after_count` | number \| null | No | When `ends_type` is `"after"`, number of runs then stop |

**End conditions:** Same as for CRON — `ends_type` / `ends_on_date` / `ends_after_count` (see Scheduled CRON above).

**Simple schedule examples:**
- Every 5 minutes: `repeat_interval=5`, `repeat_unit="minutes"` (minimum)
- Hourly: `repeat_interval=1`, `repeat_unit="hours"`
- Daily at specific time: `repeat_interval=1`, `repeat_unit="days"`, `start_time="09:00"`
- Weekly on specific days: `repeat_unit="weeks"`, `repeat_on_days=[1, 5]`, `start_time="10:00"` (e.g. Mon and Fri)
- Monthly on specific day: `repeat_unit="months"`, `repeat_on_day_of_month=15`, `start_time="00:00"`

**Example:**

```jsonc
{
"name": "weekly-cleanup",
"entry": "index.ts",
"automations": [
{
"name": "Weekly Cleanup",
"type": "scheduled",
"schedule_mode": "recurring",
"schedule_type": "simple",
"repeat_unit": "weeks",
"repeat_interval": 1,
"repeat_on_days": [1],
"start_time": "02:00",
"description": "Every Monday at 2:00"
}
]
}
```

### 4. Entity Hook

Runs the function when entity records are created, updated, or deleted.

**Required:** `entity_name`, `event_types` (array of `"create"`, `"update"`, `"delete"` — at least one).

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `type` | `"entity"` | Yes | Must be `"entity"` |
| `entity_name` | string | Yes | Entity name (matches entity schema name, e.g. `Order`, `Task`) |
| `event_types` | `("create" \| "update" \| "delete")[]` | Yes | At least one; which events trigger the function |

**Example use cases:**
- Send email on new order: `entity_name="Order"`, `event_types=["create"]`
- Track status changes: `entity_name="Order"`, `event_types=["update"]`
- Cleanup on delete: `entity_name="User"`, `event_types=["delete"]`
- Multiple events: `entity_name="Order"`, `event_types=["create", "update"]`

**Example config:**

```jsonc
{
"name": "on-order-created",
"entry": "index.ts",
"automations": [
{
"name": "On Order Created",
"type": "entity",
"entity_name": "Order",
"event_types": ["create"],
"description": "Run when a new order is created"
},
{
"name": "On Order Update or Delete",
"type": "entity",
"entity_name": "Order",
"event_types": ["update", "delete"]
}
]
}
```

**Note:** `entity_name` must match the entity schema `name` in `base44/entities/` (e.g. entity file `order.jsonc` with `"name": "Order"` → use `"entity_name": "Order"`).

#### Entity hook payload

The function receives a JSON body with:

| Field | Description |
|-------|-------------|
| `event` | `{ type, entity_name, entity_id }` — event type, entity name, and record id |
| `data` | Current entity data. `null` if `payload_too_large` is true |
| `old_data` | Previous entity data (only for `"update"` events). `null` if `payload_too_large` is true or for create/delete |
| `payload_too_large` | `true` when entity data exceeded 200KB and was omitted. Use the Base44 SDK to fetch: `await base44.entities.<EntityName>.get(entity_id)` (or the dynamic API) to load the record. |

**Authentication / user identity:** When an automation runs (scheduled or entity hook), the request is authenticated as the **user who created the automation**, not as the user who performed the action. So `await base44.auth.me()` returns the automation creator. **There is no way to get the user who triggered the entity change** (e.g. who created, updated, or deleted the record). If you need to attribute actions, store a user reference on the entity (e.g. `created_by`, `updated_by`) and read it from `data` / `old_data` in the payload.

## Full Examples

### Daily CRON report

**base44/functions/daily-report/function.jsonc:**

```jsonc
{
"name": "daily-report",
"entry": "index.ts",
"automations": [
{
"name": "Daily Report",
"type": "scheduled",
"schedule_mode": "recurring",
"schedule_type": "cron",
"cron_expression": "0 9 * * *",
"is_active": true
}
]
}
```

**base44/functions/daily-report/index.ts:**

```typescript
import { createClientFromRequest } from "npm:@base44/sdk";

Deno.serve(async (req) => {
const base44 = createClientFromRequest(req);
// Scheduled runs get auth context; use asServiceRole if you need full access
const base44Admin = base44.asServiceRole;

const orders = await base44Admin.entities.Orders.list({ limit: 100 });
const summary = { total: orders.length, date: new Date().toISOString() };

// e.g. send to Slack, email, or store in another entity
return Response.json({ success: true, summary });
});
```

### Entity hook: on order created

**base44/functions/on-order-created/function.jsonc:**

```jsonc
{
"name": "on-order-created",
"entry": "index.ts",
"automations": [
{
"name": "On Order Created",
"type": "entity",
"entity_name": "Order",
"event_types": ["create"],
"is_active": true
}
]
}
```

**base44/functions/on-order-created/index.ts:**

```typescript
import { createClientFromRequest } from "npm:@base44/sdk";

Deno.serve(async (req) => {
const base44 = createClientFromRequest(req);
const payload = await req.json();
const { event, data, old_data, payload_too_large } = payload;

// event: { type, entity_name, entity_id }
const entityId = event.entity_id;
const eventType = event.type;

// If payload was too large, data/old_data are null — fetch via SDK
let current = data;
if (payload_too_large && eventType !== "delete") {
current = await base44.asServiceRole.entities.Orders.get(entityId);
}

// e.g. send confirmation email on create, or compare old_data vs data on update
return Response.json({ success: true, orderId: entityId, eventType });
});
```

### Weekly cleanup (simple schedule)

**base44/functions/weekly-cleanup/function.jsonc:**

```jsonc
{
"name": "weekly-cleanup",
"entry": "index.ts",
"automations": [
{
"name": "Weekly Cleanup",
"type": "scheduled",
"schedule_mode": "recurring",
"schedule_type": "simple",
"repeat_unit": "weeks",
"repeat_interval": 1,
"repeat_on_days": [1],
"start_time": "02:00",
"description": "Every Monday at 2:00"
}
]
}
```

## Common Patterns

| Pattern | Use | Automation type |
|--------|-----|------------------|
| Daily report / digest | Email or Slack at 9am | CRON with `cron_expression`: `0 9 * * *` |
| On new record | Notify, sync, or validate when entity is created | Entity hook with `event_types`: `["create"]` |
| On update/delete | Audit, cache invalidation, or cleanup | Entity hook with `event_types`: `["update"]` or `["delete"]` |
| Weekly job | Cleanup or aggregation every Monday | Simple with `repeat_unit`: `"weeks"`, `repeat_on_days`: `[1]` |
| One-time run | Launch task or migration at a fixed time | One-time with `one_time_date` |

## Deploying

Automations are deployed with their function. There is no separate automation deploy command.

```bash
npx base44 functions deploy
```

This deploys all functions in `base44/functions/` and their `automations` arrays. For more on deployment, see [functions-deploy.md](functions-deploy.md).

## Common Mistakes

| Wrong | Correct | Why |
|-------|---------|-----|
| `entity_name: "order"` when schema name is `Order` | `entity_name: "Order"` | Entity name must match schema `name` exactly |
| `event_types: []` or missing | `event_types: ["create"]` (at least one) | At least one event type is required for entity hooks |
| Assuming `base44.auth.me()` is the user who triggered the entity change | Use `data` / `old_data` (e.g. `created_by`, `updated_by`) if you need who did the action | In automations, `auth.me()` is the user who **created the automation**. The triggering user is not available. |
| `schedule_type: "cron"` without `cron_expression` | Always set `cron_expression` for cron | Cron schedules require a valid cron expression |
| Putting automations in a separate file | Put `automations` inside `function.jsonc` | Automations are part of the function config |
| Expecting a separate `base44 automations deploy` | Use `npx base44 functions deploy` | Automations deploy with the function |
Loading