automations/
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:
export default defineAgent({
model: "openai/gpt-5.4",
dynamicAutomations: {
dynamic: true,
approval: false
}
});
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 legacy runDueSchedules() and
/assembly-line/scheduler/tick names remain available during deprecation, and
the older /openeve/* route aliases stay served (same auth and rate limits)
during the rename compatibility window.
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. deliveryon 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.