Skip to main content
The Agent Surface is the umbrella term for everything Mission Control exposes around AI-driven workflows: the Automations engine (triggers + actions), the Agent Builder (custom LangGraph agents), the Skills library (composable prompt+tool blocks), the Knowledge Bases (RAG storage with cosine kNN retrieval), and the Live Operations dashboard + Run History that surface what’s running and what just ran. These are gated as a single surface — superusers and elevated agency roles can access all of them; client-tenant users see none of them. See Permissions for the full access matrix.

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

┌─────────────────────────────────────────────────────────────────┐
│  TRIGGER  (note.created, schedule.tick, creative.hook_exhausted, │
│           webhook.incoming, agent.run_failed, ...)              │
└─────────────────────────────────────────────────────────────────┘


┌─────────────────────────────────────────────────────────────────┐
│  AUTOMATION RULE                                                 │
│   - filters / payload_match conditions                           │
│   - one or more ordered actions                                  │
│   - rate limit / dedup config                                    │
└─────────────────────────────────────────────────────────────────┘


┌─────────────────────────────────────────────────────────────────┐
│  ACTION  (send_slack, change_status, run_agent, add_to_kb, ...)  │
│                                                                  │
│  run_agent and run_agent_chain are the bridges into the agent    │
│  swarm — they invoke a registered agent with the trigger payload │
│  as initial context, optionally through a Skill.                 │
└─────────────────────────────────────────────────────────────────┘

                ┌──────────────┼──────────────┐
                ▼              ▼              ▼
┌──────────────────┐  ┌──────────────┐  ┌──────────────┐
│ Built-in agents  │  │ Custom agent │  │ Skill        │
│ Houston, Space   │  │ (CustomAgent │  │ (Skill model │
│ Bob, Social Sally│  │  model)      │  │  with prompt │
│                  │  │              │  │  + tool list)│
└──────────────────┘  └──────────────┘  └──────────────┘


┌─────────────────────────────────────────────────────────────────┐
│  Tool calls                                                      │
│   - get_creative_performance, find_similar_creatives,            │
│     analyze_hook_exhaustion, search_knowledge_base, ...          │
│   - knowledge_base/* tools retrieve from the KBs above           │
│   - tools_creative/* tools read the creative-analysis pipeline   │
└─────────────────────────────────────────────────────────────────┘


┌─────────────────────────────────────────────────────────────────┐
│  Run history + live ops                                          │
│   - automations.live consumes WebSocket events                   │
│   - automations.tasks logs every run / step / agent invocation   │
│   - failures fan out via agent.run_failed → user automations     │
└─────────────────────────────────────────────────────────────────┘

Triggers

15 triggers ship in automations/triggers/__init__.py. Each registers a payload schema that downstream actions can reference.
KeyFires when
note.createdA notes.Notes row is inserted.
note.status_changedA note’s status field changes.
note.status_unchangedA note has been in the same status for N days (sweep).
note.assignment_changedAn assignee is added or removed.
note.due_date_setA note gains a due_date value.
note.due_date_arrivedA note’s due_date is today (sweep).
note.custom_field_setA custom field on a note is set.
kb.document_addedA Document enters STATUS_READY in any knowledge base.
creative.hook_exhaustedA (client × archetype) transitions from healthy to exhausted. See Hook Exhaustion.
agent.run_succeededA LangGraph swarm run finishes successfully.
agent.run_failedA LangGraph swarm run errors out.
schedule.tickA user-defined recurring schedule fires (cron).
schedule.weeklyWeekly cron with day-of-week selector.
schedule.monthlyMonthly cron with day-of-month selector.
webhook.incomingAn inbound HTTP request hits the automation’s webhook URL.
Each trigger key has a 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 in automations/actions/. Each is decorated with @register_action(...).
KeyWhat it does
send_slackPost to a Slack channel via the connected workspace.
send_emailSend a transactional email via the configured SMTP.
change_statusSet a note’s status. Idempotent.
assign_usersAdd / remove assignees on a note.
set_due_dateSet or clear notes.Notes.due_date.
set_custom_fieldSet a custom field value on a note.
update_noteBulk-update fields on a note.
inline_comment_mentionPost a comment on a note (with @mentions).
apply_templateApply a note template (clones fields + creates subtasks).
create_subtasksCreate one or more subtasks under a parent note.
create_or_move_taskCreate a new note or move an existing one between folders.
add_to_kbWrite a Document into a knowledge base.
webhook_callOutbound HTTP call to a configured URL.
run_agentInvoke a LangGraph swarm with the trigger payload as initial context.
run_agent_chainInvoke 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:
from automations.engine import dispatch
dispatch('creative.hook_exhausted', {
    'client_id': '123',
    'archetype': 'before_after',
    ...
})
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).
The 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

ConcernPath
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/
All endpoints are gated by shared.permissions.AgentSurfaceAllowed (mirrors shared.auth.agent_surface_allowed).

Where the code lives

AreaPath
Engineautomations/engine.py, automations/registry.py
Triggersautomations/triggers/__init__.py (registry), automations/signals.py (emitters), automations/sweeps.py (cron-driven triggers)
Actionsautomations/actions/*.py (one file per action)
Live ops WebSocketautomations/consumers.py, automations/live.py
Run historyautomations/api/views.py, automations/models.py:AutomationRun
Agent swarm wiringai_chat/agents.py, ai_chat/graph.py
Custom agentscustom_agents/
Skillsskills/
Knowledge Basesknowledge_base/
Permission gateshared/auth.py:agent_surface_allowed, shared/permissions.py:AgentSurfaceAllowed, l5ui/.../agent-surface.guard.ts