What’s in the surface
Automations
Trigger → conditions → action chains. 15 triggers (note lifecycle, schedule, agent runs, creative.hook_exhausted, …) and 15 actions (Slack, Notes, KB writes, run an agent, webhooks).
Agent Builder
Define custom LangGraph agents with their own system prompts, tool sets, and avatars. Agents live alongside Houston / Space Bob / Social Sally in the multi-agent swarm.
Skills
Reusable, composable prompt + tool bundles. Agents pull skills in as building blocks (e.g., “summarize a campaign”, “explain a creative”).
Knowledge Bases
Per-account RAG stores. Documents are chunked, embedded into pgvector, and retrieved via cosine kNN. Includes a Google Drive ingestion path.
Live Operations
Real-time dashboard of running automation runs, agent runs, and worker health. WebSocket-pushed via the
automations consumer.Run History
Paginated, filterable history of every automation run (success / failure / replay). Each row links to the input payload, the action chain, and the resulting log lines.
How the pieces fit
Triggers
15 triggers ship inautomations/triggers/__init__.py. Each registers a payload schema that downstream actions can reference.
| Key | Fires when |
|---|---|
note.created | A notes.Notes row is inserted. |
note.status_changed | A note’s status field changes. |
note.status_unchanged | A note has been in the same status for N days (sweep). |
note.assignment_changed | An assignee is added or removed. |
note.due_date_set | A note gains a due_date value. |
note.due_date_arrived | A note’s due_date is today (sweep). |
note.custom_field_set | A custom field on a note is set. |
kb.document_added | A Document enters STATUS_READY in any knowledge base. |
creative.hook_exhausted | A (client × archetype) transitions from healthy to exhausted. See Hook Exhaustion. |
agent.run_succeeded | A LangGraph swarm run finishes successfully. |
agent.run_failed | A LangGraph swarm run errors out. |
schedule.tick | A user-defined recurring schedule fires (cron). |
schedule.weekly | Weekly cron with day-of-week selector. |
schedule.monthly | Monthly cron with day-of-month selector. |
webhook.incoming | An inbound HTTP request hits the automation’s webhook URL. |
config_schema (the form fields the UI shows) and a payload shape (the keys the trigger emits when it fires). The dispatcher passes the payload to actions verbatim — actions reference {{ payload.something }} in their templates.
Actions
15 actions ship inautomations/actions/. Each is decorated with @register_action(...).
| Key | What it does |
|---|---|
send_slack | Post to a Slack channel via the connected workspace. |
send_email | Send a transactional email via the configured SMTP. |
change_status | Set a note’s status. Idempotent. |
assign_users | Add / remove assignees on a note. |
set_due_date | Set or clear notes.Notes.due_date. |
set_custom_field | Set a custom field value on a note. |
update_note | Bulk-update fields on a note. |
inline_comment_mention | Post a comment on a note (with @mentions). |
apply_template | Apply a note template (clones fields + creates subtasks). |
create_subtasks | Create one or more subtasks under a parent note. |
create_or_move_task | Create a new note or move an existing one between folders. |
add_to_kb | Write a Document into a knowledge base. |
webhook_call | Outbound HTTP call to a configured URL. |
run_agent | Invoke a LangGraph swarm with the trigger payload as initial context. |
run_agent_chain | Invoke another automation rule (chained workflows). |
run_agent is the action that bridges the automation engine into the agent swarm. Pair it with the agent.run_succeeded / agent.run_failed triggers to build retry / fallback / Slack-on-failure chains.
Engine
automations/engine.py is the single entry point:
dispatch(trigger_key, payload) finds matching automation rules for the tenant, evaluates each rule’s filters / payload_match conditions, and enqueues the action chain on the automations_standard Celery queue. Every step writes a row in automations.AutomationRun for the Run History view.
Live Operations + Run History
- Live Operations is at
/automations/operations. WebSocket consumer (automations/consumers.py) pushes events: run started, action completed, run failed. The dashboard shows in-flight automation runs alongside in-flight agent runs. - Run History is at
/automations/history. Server-side paginated, filterable by trigger, action, status, date range, client. Each row deep-links to the run detail (input payload + action chain + per-step logs).
agent.run_failed trigger fires automatically on any errored swarm run, so you can wire a Slack alert to surface failures back to the team.
API + WebSocket reference
| Concern | Path |
|---|---|
| Automation CRUD | /api/automations/automations/ |
| Run history | /api/automations/runs/ |
| Run replay | /api/automations/runs/<id>/replay/ |
| Cancel run | /api/automations/runs/<id>/cancel/ |
| Operations history | /api/automations/operations/history/ |
| Agent surface system check | /api/automations/system-checks/ (returns agent_surface.W001 / W002) |
| Live operations websocket | /ws/automations/live/ |
| Trigger / action registry | /api/automations/registry/ |
shared.permissions.AgentSurfaceAllowed (mirrors shared.auth.agent_surface_allowed).
Where the code lives
| Area | Path |
|---|---|
| Engine | automations/engine.py, automations/registry.py |
| Triggers | automations/triggers/__init__.py (registry), automations/signals.py (emitters), automations/sweeps.py (cron-driven triggers) |
| Actions | automations/actions/*.py (one file per action) |
| Live ops WebSocket | automations/consumers.py, automations/live.py |
| Run history | automations/api/views.py, automations/models.py:AutomationRun |
| Agent swarm wiring | ai_chat/agents.py, ai_chat/graph.py |
| Custom agents | custom_agents/ |
| Skills | skills/ |
| Knowledge Bases | knowledge_base/ |
| Permission gate | shared/auth.py:agent_surface_allowed, shared/permissions.py:AgentSurfaceAllowed, l5ui/.../agent-surface.guard.ts |
.png?fit=max&auto=format&n=Frm2GFbmok4D-yJA&q=85&s=93c3ebd47542af65d1cd06d8563a7f6e)