Prerequisites
- Slack connected (the orchestrator and sub-agents post to
#incidents). - Familiarity with programmable agents and agent-to-agent delegation (this recipe uses
invoke_agent,notify_parent_session, andchild_session_ids). - To trigger from Airflow or a script: a Paradime API endpoint, key, and secret with
DinoAI agent APIcapabilities enabled (Workspace Settings, API; requires Admin access).
Steps
1
Create the agents
Build the four agents in the Agent UI: the three specialists first, then the commander (its Squad picker needs the sub-agents to exist). For each, fill the builder fields below, leave Model on Auto, then select Deploy and choose Just here (live in the workspace immediately) or Open a pull request (committed under
.dinoai/agents/<name>.yml and governed as code, exactly the same definition the builder holds).Sub-agent 1, log-analyzer-
Role:
Bolt log specialist. -
Goal:
-
Backstory:
-
Allowed tools:
list_bolt_schedules,get_bolt_run_logs,notify_parent_session
query-profiler-
Role:
Warehouse query specialist. -
Goal:
-
Backstory:
-
Allowed tools:
run_sql_query,list_all_snowflake_databases,notify_parent_session
owner-notifier-
Role:
People-routing specialist. -
Goal:
-
Backstory:
-
Allowed tools:
read_file,search_files_and_directories,ripgrep_search,post_slack_message,notify_parent_session
incident-commander-
Role:
-
Goal:
-
Backstory:
-
Allowed tools:
post_slack_message,invoke_agent -
Squad:
log-analyzer,query-profiler,owner-notifier -
Output: Slack channel
#incidents
None of the sub-agents have
invoke_agent in their allowed tools. This keeps the delegation graph exactly two levels deep: the commander is the only delegator. Sub-agents cannot spawn further children, which makes incident response predictable and prevents runaway chains.2
Trigger the commander
The simplest path is to run the agent with Bolt: trigger Then attach the callback to your DAG:Trigger manually from a scriptFor teams not running Airflow, or for ad-hoc triage when a failure is spotted manually, create Run it from your terminal:
incident-commander on demand or on a schedule with the native Run Paradime DinoAI Agent command, passing an incident summary as the task, with no API keys to configure. Airflow is external to Paradime, though, so to fire triage automatically the moment a DAG task fails you need the API: wire one of the trigger paths below.Trigger from Airflow (on_failure_callback)The callback fires when any task in your DAG fails, extracts the task and DAG context from Airflow’s context dict, and hands it directly to the incident commander so the triage message is pre-populated with real incident details. Create dags/callbacks/incident_commander.py:dags/callbacks/incident_commander.py
dags/hourly_marts.py
The callback runs in a daemon thread so it does not block Airflow’s task runner while the agent session runs (which can take several minutes). The original task failure is always surfaced normally in Airflow regardless of whether the triage agent succeeds or fails. To scope triage to a single high-priority model, set
on_failure_callback=trigger_incident_commander on that operator instead of the whole DAG. Store the three PARADIME_* values as Airflow Variables or in an Airflow Connection rather than hardcoding them.scripts/trigger_incident.py:scripts/trigger_incident.py
Your Paradime API endpoint, key, and secret are available under Workspace Settings, API. Make sure the key has
DinoAI agent API capabilities enabled. Set INCIDENT_SLACK_CHANNEL (defaults to #incidents) and, on the Airflow path, SUSPECT_MODEL (defaults to the failed task ID) to override the defaults.3
Watch the triage
Both trigger paths block until the full triage is complete. Open the
#incidents thread and watch the commander spawn its three specialists, each posting updates as it works, then post the unified summary once all three have reported.To stream sub-agent progress in real time instead of waiting, use the non-blocking trigger_run pattern and poll child_session_ids:scripts/watch_incident.py
child_session_ids populates progressively as the orchestrator spawns each sub-agent. The first poll may return an empty list, which is expected. The three child sessions appear within the first 30 to 60 seconds as the commander issues its invoke_agent calls.The commander posts a single structured message to
#incidents with ROOT CAUSE, IMPACT, OWNER, and NEXT ACTION, each populated by the matching sub-agent. If the post never arrives, confirm all four agents are deployed and visible on the Agents page, and that the API key has DinoAI agent API capabilities. The full triage typically completes in 3 to 8 minutes depending on log volume and warehouse query history depth.How it works
When the incident commander receives the trigger message, it callsinvoke_agent three times in parallel (one per specialist), passing its own session ID as the callback target. Each sub-agent runs independently, posting updates to the #incidents Slack thread as it works, then calls notify_parent_session with its findings when complete. The commander resumes once all three callbacks have arrived, then composes and posts the unified triage report. The commander never investigates itself: it only delegates and composes, and because no sub-agent has invoke_agent, the graph stays exactly two levels deep.
Next steps
Run an agent with Bolt
Trigger this orchestrator on demand or on a schedule.
Self-healing Dagster pipelines
Dispatch failures to a healer from a Dagster hook.
Build an agent in the UI
Create these agents visually instead of by hand.
Agent-to-agent delegation
How invoke_agent and notify_parent_session work.