Lightyear LogoLightyear Docs

Automations

Write, test, and deploy scripts that run on a schedule or webhook trigger

Automations

Automations let you write TypeScript scripts that run in the cloud on a schedule or in response to a webhook. They use the same secure credential system as unscrambled curl, so your automations can call any authenticated API without managing tokens.

Create an automation

unscrambled action create daily-github-summary

This scaffolds a new automation project:

daily-github-summary/
├── action.ts          # Your automation code
├── action.config.ts   # Configuration (schedule, environment)
└── package.json

Write the code

The generated action.ts gives you a starting point:

import { unscrambled } from "@unscrambled/sdk";
 
export default async function run() {
  // Fetch your GitHub notifications
  const notifications = await unscrambled.curl(
    "https://api.github.com/notifications",
  );
 
  // Fetch open PRs across your repos
  const prs = await unscrambled.curl(
    "https://api.github.com/search/issues?q=is:pr+is:open+author:@me",
  );
 
  // Send a summary to Slack
  await unscrambled.curl("https://slack.com/api/chat.postMessage", {
    method: "POST",
    body: {
      channel: "#daily-summary",
      text: formatSummary(notifications, prs),
    },
  });
}
 
function formatSummary(notifications: any[], prs: any) {
  const prCount = prs.total_count;
  const notifCount = notifications.length;
  return [
    `*Daily GitHub Summary*`,
    `📬 ${notifCount} unread notifications`,
    `🔀 ${prCount} open PRs`,
  ].join("\n");
}

The unscrambled.curl() function works exactly like the CLI command — it uses your stored credentials automatically.

Configure the automation

Edit action.config.ts to set the schedule and other options:

import { defineConfig } from "@unscrambled/sdk";
 
export default defineConfig({
  name: "daily-github-summary",
  title: "Daily GitHub summary",
 
  // Run every weekday at 9am ET
  schedule: "0 9 * * 1-5",
  timezone: "America/New_York",
 
  // Services this automation needs
  services: ["github", "slack"],
 
  // Timeout after 30 seconds
  timeout: 30_000,
});

Test locally

Run your automation in the development sandbox:

unscrambled action test daily-github-summary
Testing daily-github-summary...
→ GET https://api.github.com/notifications (200, 142ms)
→ GET https://api.github.com/search/issues (200, 89ms)
→ POST https://slack.com/api/chat.postMessage (200, 203ms)
✓ Completed in 434ms

The test environment uses your real credentials but marks requests so downstream services can distinguish test from production traffic.

Deploy to production

When you're happy with the automation, deploy it:

unscrambled action deploy daily-github-summary
Building daily-github-summary...
✓ Built successfully (1.2s)
✓ Deployed to production
✓ Schedule active: 0 9 * * 1-5 (America/New_York)

Next run: Tomorrow at 9:00 AM ET

Your code runs in an isolated Lambda sandbox. Each execution gets its own environment with no shared state.

Schedule options

Cron expressions

Set or update the schedule from the CLI:

unscrambled action schedule daily-github-summary --cron "0 9 * * 1-5"

Common patterns:

CronDescription
0 9 * * *Every day at 9am
0 9 * * 1-5Weekdays at 9am
*/15 * * * *Every 15 minutes
0 */6 * * *Every 6 hours
0 0 1 * *First of every month

Webhook triggers

Instead of a schedule, trigger your automation via webhook:

unscrambled action webhook daily-github-summary
Webhook URL: https://api.unscrambled.com/hooks/abc123def456

Send a POST to this URL to trigger the automation. The request body is available as context.payload in your code:

import { unscrambled, type Context } from "@unscrambled/sdk";
 
export default async function run(context: Context) {
  const { event, repository } = context.payload;
  // Handle the webhook payload
}

Manual triggers

Run a deployed automation on demand:

unscrambled action trigger daily-github-summary

Managing automations

List automations

unscrambled action list
NAME                     STATUS    SCHEDULE          LAST RUN
daily-github-summary     Active    0 9 * * 1-5      2 hours ago (✓)
sync-contacts            Active    */30 * * * *      12 minutes ago (✓)
weekly-report            Paused    0 10 * * 1        3 days ago (✓)

View run history

unscrambled action runs daily-github-summary
RUN ID      TRIGGERED        DURATION    STATUS
run_abc123  Today 9:00 AM    434ms       ✓ Success
run_def456  Yesterday 9:00   512ms       ✓ Success
run_ghi789  Mar 17 9:00 AM   1.2s        ✗ Failed (timeout)

View run logs

unscrambled action logs daily-github-summary --run run_abc123

Pause and resume

unscrambled action pause daily-github-summary
unscrambled action resume daily-github-summary

Delete an automation

unscrambled action delete daily-github-summary

Environment variables

Automations can use environment variables for configuration that isn't a credential:

unscrambled action env set daily-github-summary SLACK_CHANNEL "#daily-summary"

Access them in your code:

const channel = process.env.SLACK_CHANNEL ?? "#general";

Execution environment

  • Runtime: Node.js 20
  • Timeout: Configurable, default 60 seconds, maximum 15 minutes
  • Memory: 256 MB (configurable up to 1 GB)
  • Sandbox: Each execution runs in an isolated Lambda environment
  • Networking: Outbound HTTPS only, through Unscrambled's proxy for credential injection