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, or commit them under Sub-agent, Sub-agent, Sub-agent,
.dinoai/agents/. The orchestrator and all three sub-agents must exist before the first trigger.Orchestrator, incident-commander.dinoai/agents/incident-commander.yml
log-analyzer.dinoai/agents/log-analyzer.yml
query-profiler.dinoai/agents/query-profiler.yml
owner-notifier.dinoai/agents/owner-notifier.yml
None of the sub-agents have
invoke_agent in their tool allowlist. 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, passing an incident summary as the message. To fire triage automatically the moment a task fails, wire one of the trigger paths below instead.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 YAMLs are merged on the workspace branch and 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.