Asana Stuck-in-Section SLA Escalation
On a schedule, the flow finds Asana tasks that have sat in a workflow section (e.g. In Review, QA) longer than that section's SLA, nudges the owner in Teams, adds a comment, and escalates tasks far past the limit to the lead. Stops work from stalling silently between stages.
Provided as-is, without warranty of any kind. Review and test each pattern in a non-production environment before deploying it to live automations. See our Terms.
Overview
This flow stops Asana work stalling silently between workflow stages. On a daily schedule it lists the tasks in a monitored Asana project, reads each open task's activity stories to find which section it currently sits in and when it entered that section, and compares that dwell time against a per-section SLA. Tasks past their section SLA get a timestamped comment on the task and a nudge to the team's Teams channel; tasks past the SLA by an escalation multiplier (e.g. 2x) are additionally escalated to the lead by email.
Why it matters: Tasks rot in interim sections (In Review, QA, Blocked) where no due date applies, so deadline-based alerts miss them. Section-level SLAs catch the silent stalls that deadlines can't.
Status: Built; ships Off (demo). Going live requires only connection authorization, the Asana API token, and env-var configuration - the wiring is complete.
Use Case
A team that runs an Asana board with workflow sections (e.g. To Do -> In Progress -> In Review -> QA -> Done) wants any task lingering in a stage longer than that stage's agreed SLA to be surfaced, nudged, and - if badly overdue - escalated, without anyone manually policing the board.
Flow Architecture
SLA Sweep Daily 0900
RecurrenceDaily SLA sweep at 09:00 ET.
Initialize Variables (x9)
Initialize VariableLoad every env var into a working variable (workspace, project, SLA map, multiplier, lead email, Teams group/channel, Asana API base + token).
List Tasks In Project
Asana — ListTasksList all tasks in the monitored project.
Filter Incomplete Tasks
Filter ArrayKeep only open tasks (completed = false).
For Each Stuck Candidate
Apply to each (Sequential)Evaluate every open task.
Get Task Activity Stories
HTTP (Asana REST)Read the task's stories incl. section_changed events (secure inputs).
Filter Section Change Stories
Filter ArrayKeep only resource_subtype = section_changed events.
Has Section History
ConditionOnly evaluate tasks that have actually been moved into a section.
Compose Section Entry / Name / Hours In Section / Section SLA
Compose (x4)Latest section move -> current section, entry time, hours in section, and the section's SLA from the map.
Over SLA
ConditionTrue when hours-in-section > the section SLA.
Environment Variables
| Schema name | Type | Default | Description |
|---|---|---|---|
| flowlibs_AsanaWorkspaceId | String | <configure> | Asana workspace GID that owns the project. |
| flowlibs_AsanaSlaProjectId | String | <configure> | GID of the Asana project to sweep. |
| flowlibs_SectionSlaMap | String | {"In Review":24,"QA":48,"Blocked":12} | JSON map of section name to SLA in hours. |
| flowlibs_EscalateMultiplier | String | 2 | Multiple of SLA past which a task is escalated to the lead. |
| flowlibs_SlaLeadEmail | String | lead@yourcompany.com | Escalation email recipient. |
| flowlibs_SlaTeamsGroupId | String | <your-team-id> | Teams group/team ID for owner nudges. |
| flowlibs_SlaTeamsChannelId | String | <your-channel-id> | Teams channel ID for owner nudges. |
| flowlibs_AsanaApiBaseUrl | String | https://app.asana.com/api/1.0 | Base URL for the direct Asana REST call. |
| flowlibs_AsanaApiToken | String | <configure> | Asana Personal Access Token (Bearer) — back with Azure Key Vault in production. |
Connectors & Connections
| Connector | API name | Actions used |
|---|---|---|
| Asana | shared_asana | ListTasks AddComment |
| Microsoft Teams | shared_teams | PostMessageToConversation |
| Office 365 Outlook | shared_office365 | SendEmailV2 |
Note — All connections are referenced as solution connection references; the flow is portable between environments as long as a connection is mapped at import time.
Customization Guide
Almost every realistic variant of this flow can be implemented by changing environment variable values. A few cases require small edits inside the flow definition — those are called out explicitly below.
- Tune the section SLAs
- Edit flowlibs_SectionSlaMap; any section not listed is never flagged (it gets an effectively-infinite SLA), so you can scope the flow to just the stages you care about.
- Change the escalation threshold
- Raise/lower flowlibs_EscalateMultiplier (e.g. 3 = escalate at 3x the section SLA).
- Re-time the sweep
- Adjust the Recurrence trigger (e.g. twice daily, or hourly for fast-moving boards).
- Add WIP limits
- Combine with a per-section task-count check to flag overloaded stages.
- Auto-reassign
- Extend the Far Past SLA branch to reassign stuck QA tasks via Asana.
- Trend reporting
- Log each breach to Dataverse to report average time-in-section per stage over time.
Key Expressions
The flow is intentionally light on Power Fx / WDL gymnastics — the heaviest expressions are the branch-name concatenation and the approval outcome check. They are listed below in the order they appear in the flow.
EXPR.01Latest section entry
Current section + entry time from the most recent section move.
EXPR.02Current section name
Reads the section the task currently sits in.
EXPR.03Hours in section
Dwell time in hours since entering the current section.
EXPR.04Section SLA lookup (unmapped -> never flagged)
Looks up the section's SLA; unmapped sections get an effectively-infinite SLA.
EXPR.05Over SLA
True when dwell time exceeds the section SLA.
EXPR.06Far past SLA (escalate)
True when dwell time exceeds SLA x multiplier.
Customize & download
Generate a ready-to-import copy of this solution with your environment-variable values baked in — available on Base, Pro, or Team.
Upgrade to customize
Comments
Sign in to join the conversation.
Sign inNo comments yet. Be the first to share your experience with this flow.