Skip to content

Admin — Automations

Automations is the admin app’s parent surface for everything that runs agent work without a human chat message — Step Functions routines, scheduled jobs, and webhook endpoints. It’s a real route group in the sidebar (not a label-only rename), with three children: Routines, Schedules, and Webhooks. The detail surfaces under Routines are where the operator watches a routine execute step by step, with a live graph of state transitions, per-step input/output/cost, and the agent-authored markdown summary that names HITL approval points by state name.

Automations is a parent group in the Work section, with three children:

Work
├── Dashboard
├── Agents
├── Threads
├── Inbox
└── Automations ← parent; expands to:
├── Routines ← /automations/routines
├── Schedules ← /automations/schedules
└── Webhooks ← /automations/webhooks

The previous top-level routes (/scheduled-jobs, /webhooks, /routines) survive as 301-redirect shims so existing deep-links and bookmarks still land. Webhooks moved out of the Manage group during the Phase D nav restructure; Manage now keeps pure config/infra surfaces — Analytics, People, Billing, Settings.

List route: /automations/routines Detail route: /automations/routines/:routineId Run-detail route: /automations/routines/:routineId/executions/:executionId New routine: /automations/routines/new

A routine is an Amazon States Language state machine the chat builder agent emits, validated and provisioned by the publishRoutineVersion GraphQL mutation. Each routine has:

  • An ASL state machine versioned via Step Functions PublishStateMachineVersion. The routine carries an alias ARN; the alias points at the current version, so triggering a routine always runs whatever the latest publish set as current.
  • An agent-authored markdown summary (documentationMd), regenerated on every publish, that names the steps the operator will see in the run-detail graph plus any HITL approval points.
  • A step manifest (step_manifest_json on routine_asl_versions) that maps ASL state names to v0 recipe ids — the run-detail graph derives nodes from this manifest so brand-new executions render their shape immediately.
  • A visibility modelvisibility = 'agent_private' (only the owning agent can invoke) or visibility = 'tenant_shared' (any agent in the tenant). Splits the conflated agentId field; owning_agent_id is the authoring/stewardship agent for private routines.

Filtered to engine = 'step_functions' so legacy_python rows don’t pollute the operator’s view. Columns: status badge, name, type, schedule, agent, last run, next run. Click a row to drill into the detail page.

The New Routine button routes to a thin form-based create page that mints a placeholder routine (no-op Succeed-state ASL) and drops the operator into the routine detail page. Iteration happens via the chat builder once that surface lands; until then, operators iterate via direct ASL edits.

Two tabs:

  • Runs — the ExecutionList component. Status filter pills (running / awaiting_approval / succeeded / failed / cancelled / timed_out / all) persist via URL search params, so reload preserves the filter. Cursor pagination keyed on started_at; explicit Previous/Next with a cursor stack. The list polls every 5s while at least one row is non-terminal AND the page is visible (no background polling). Click a row → run-detail page.
  • Scheduled Jobs — the routine_triggers rows that fire this routine on a schedule. Routine triggers go through the same scheduled_jobs substrate as agent triggers but with trigger_type = 'routine_schedule' or 'routine_one_time'.

Side card shows routine metadata: type, schedule, owning agent, team, last run, next run, created.

The customer-visible “watch the routine execute” surface. Three components combine:

  • ExecutionGraph — vertical-stepper visualization of the state machine. Nodes derive from the routine_asl_versions step manifest backing this specific execution (resolved via RoutineExecution.aslVersion); fall back to deriving from routine_step_events when the manifest isn’t fetchable. Latest-event-per-node selection collapses retry chatter into a single graph dot. Status icons: spinning loader for running, green check for succeeded, red X for failed, purple pause for awaiting_approval, amber clock for timed_out.
  • StepDetailPanel — click a step in the graph; this panel shows input/output JSON, recipe type, retry count, LLM cost, duration. For python recipe steps with S3-offloaded stdout/stderr, the inline 4KB preview surfaces with a “(truncated)” marker plus the S3 URI for full output.
  • MarkdownSummary — renders the routine’s documentationMd. HITL anchor links of the form [label](#step-NodeName) are intercepted and route to the parent’s step-selection handler so clicking the anchor jumps the graph + panel to the named state.

The page polls every 5s while non-terminal. Subscription wiring (AppSync OnRoutineExecutionUpdated) is a Phase E follow-up — current polling is fine at 4-tenant scale.

Route: /automations/schedules Detail: /automations/schedules/:scheduledJobId

The scheduled_jobs substrate that previously lived at /scheduled-jobs. Behavior is unchanged — same four trigger types (heartbeats, reminders, scheduled invocations, routine triggers), same EventBridge → job-schedule-managerjob-trigger provisioning chain. Routine triggers fire triggerRoutineRun GraphQL mutation, which calls SFN StartExecution against the routine’s alias ARN.

Route: /automations/webhooks Detail: /automations/webhooks/:webhookId

The webhook surface that previously lived at /webhooks. Behavior is unchanged — webhook tokens, target_type (agent | routine), enabled toggle, invocation history. Routine-target webhooks invoke triggerRoutineRun via the webhook handler.

  • Workspace HITL reviews — system-agent workspace reviews surface in Inbox, not Automations. Routine-driven HITL approvals (the inbox_approval recipe) also surface in Inbox; deciding an inbox item with type = 'routine_approval' resumes the paused Step Functions execution.
  • Per-thread agent invocations — those live in Threads. Routines are distinct: a routine execution has its own routine_executions row, not a thread_turns row, and is observable through the run-detail graph rather than a chat timeline.
  • Per-user OAuth or integration credentials — those live in the mobile app. Admin owns tenant-wide infra and config; users own their own integration auth on mobile.
  • Legacy Python routinesengine = 'legacy_python' rows are archived during the Phase E migration and excluded from the routines list. They’re not deleted (status flips to archived); they stop being actionable from this UI.
  • Routines: routines table holds the routine record; routine_asl_versions is the version history (one row per publishRoutineVersion); routine_executions records each SFN execution; routine_step_events is the per-step event log (running/succeeded/failed transitions, plus python stdout previews + LLM cost). EventBridge bridges SFN execution-state-change events into routine-execution-callback so the executions row tracks lifecycle even for agent_invoke-only routines that have no wrapper Lambda.
  • Schedules: scheduled_jobs table; job-schedule-manager reconciles to AWS Scheduler; job-trigger fires the wakeup or routine StartExecution.
  • Webhooks: webhooks table; webhooks handler authenticates the public endpoint and routes the payload.

rate() schedules treat the cadence as creation-time + interval, not wall-clock-aligned — a rate(1 hour) job created at 09:23 fires at 10:23, 11:23, … rather than on the hour. Use cron() for wall-clock alignment. The Schedule create form steers operators toward cron() for this reason.

User-initiated create and update Lambda invokes use RequestResponse so errors surface synchronously — no fire-and-forget paths.

  • Inbox — the operator queue for human-in-the-loop decisions, including routine inbox_approval waits.
  • Threads — the conversation surface for agent runs that aren’t routine-driven.
  • Scheduled and Event-driven — how schedules and event triggers feed routines and agent invocations.