Assembly LineDocs

automations/

Run agents from time-based schedules or normalized external events.

Edit

Automations start durable agent work without a conversational prompt. Every automation declares a trigger and may invoke the default agent, a skill, an agent target, or a playbook. Triggers are either time-based schedules or normalized external events.

Scheduled Automation

// automations/morning_brief.ts
import { defineAutomation } from "@assemblyline-agents/core";

export default defineAutomation({
  description: "Run a daily brief.",
  trigger: {
    type: "schedule",
    cron: "0 8 * * *",
    timezone: "America/Chicago"
  },
  idempotencyKey: "starter-agent:morning-brief",
  message: "Prepare the morning brief.",
  target: { type: "skill", name: "morning-brief" }
});

Schedule automations require idempotencyKey. The runtime appends the due timestamp to this prefix, reserves the resulting key before dispatch, and records one durable run for each cron occurrence.

Event Automation

// automations/process_client_email.ts
import { defineAutomation } from "@assemblyline-agents/core";

export default defineAutomation({
  description: "Process important client email.",
  trigger: {
    type: "event",
    source: "gmail",
    event: "email.received",
    connection: "gmail",
    filter: {
      label: "important"
    }
  },
  message: "Review the email and extract the required actions.",
  target: { type: "skill", name: "process-client-email" }
});

Event filters use recursive JSON-subset matching. Every key in filter must exist with the same value in the normalized event payload; extra payload keys are allowed. Event automations default their idempotency prefix to automation:<filename>, then append the provider's stable eventId.

Trusted hosts can submit normalized events directly:

POST /assembly-line/automations/events
Authorization: Bearer <ASSEMBLY_LINE_ADMIN_TOKEN>
Content-Type: application/json

{
  "source": "gmail",
  "event": "email.received",
  "eventId": "provider-message-id",
  "occurredAt": "2026-07-24T13:30:00Z",
  "payload": {
    "label": "important",
    "subject": "Contract follow-up"
  }
}

Provider channel modules can return { kind: "event", event } from normalizeHttp() after verifying the provider signature. Long-lived channel listeners can call emit.automation(event). Both paths use the same filtering, capacity, idempotency, and durable run path as direct host dispatch through runtime.dispatchAutomationEvent(event).

Lifecycle Handlers

Trusted prepare/finalize code lives in automation-handlers/. A lifecycle handler can prepare memory and resources before the model turn, select a target, and finalize application state afterward without exposing orchestration tools to the model.

// automation-handlers/llm_wiki_dream.ts
import { defineAutomationHandler } from "@assemblyline-agents/core";

export default defineAutomationHandler({
  async prepare(ctx) {
    const bundle = await ctx.resources.collect({
      sources: ["memory", "history", "connections"],
      limit: 100
    });

    return {
      target: { type: "skill", name: "personal-wiki-update" },
      promptContext: {
        triggerKind: ctx.trigger.kind,
        sourceBundle: bundle.markdown
      }
    };
  },

  async finalize(ctx, result) {
    await ctx.emit("wiki.automation_finished", {
      ok: result.ok,
      status: result.status ?? "unknown"
    });
  }
});

Reference it from either trigger kind:

export default defineAutomation({
  trigger: {
    type: "schedule",
    cron: "15 8 * * *",
    timezone: "UTC"
  },
  idempotencyKey: "system-routine:wiki-dream",
  lifecycle: { handler: "llm_wiki_dream" },
  target: { type: "skill", name: "personal-wiki-update" }
});

The handler context exposes run identity, trigger metadata, memory, resources, blob storage, environment access, routine-run bookkeeping, durable events, idempotency keys, and replayable ctx.step() execution. For event automations, ctx.trigger.event contains the normalized event envelope.

Dynamic Automations

dynamicAutomations in agent.ts controls runtime-created automations:

import { defineAgent, useModel } from "@assemblyline-agents/core";

export default defineAgent({
  dynamicAutomations: {
    dynamic: true,
    approval: false
  },
  setup() {
    useModel("openai/gpt-5.4");
  }
});

Tools use ctx.automationManager:

await ctx.automationManager?.createAutomation({
  message: "Prepare a weekly review.",
  cron: "0 16 * * 5",
  timezone: "America/Chicago"
});

Dynamic automation creation currently supports time-based schedules. Event automation definitions remain reviewed source because provider subscription, authentication, and filtering policy are trusted application concerns.

Hosts trigger due time-based work through runtime.runDueAutomations() or GET/POST /assembly-line/automations/tick. The deprecated runDueSchedules() method alias still works (it forwards to runDueAutomations()). The legacy /openeve/* route aliases return 404.

Delivery And Reliability

  • Provider event IDs and schedule occurrence IDs are reserved durably.
  • Capacity is checked before consuming an event's idempotency key.
  • Provider delivery is at least once, so external side effects must still use ctx.idempotencyKey() or destination-level deduplication.
  • delivery on a normalized event can route the final result through an originating provider. Omitting it runs the automation silently.
  • Channels remain conversational ingress. Automations are operational ingress and do not require a conversation or reply.

Legacy Compatibility

schedules/, triggers/, defineSchedule(), defineTriggerHandler(), dynamicSchedules, and ctx.scheduleManager remain accepted for compatibility and emit compiler deprecation warnings where applicable. New agents should use automations/, automation-handlers/, defineAutomation(), defineAutomationHandler(), dynamicAutomations, and ctx.automationManager.

On this page