How to Schedule a Daily Stale-Lead Report from Monday to Slack
Build a Spojit workflow that runs every morning, pulls open leads from a Monday.com board, flags rows untouched past your SLA window, summarizes the worst offenders into an owner-by-owner digest, and posts it to your sales channel in Slack with a CSV attached.
What This Integration Does
Sales pipelines leak from the middle: a lead lands, an owner starts working it, and then it goes quiet. Nobody notices until the deal is cold. This workflow gives your team a standing 9am nudge. It reads the open leads on a Monday.com board, measures how long each one has gone since its last activity, and surfaces only the rows that have crossed your service-level window. The intelligent layer across your automation, Miraxa, then turns that raw list into a readable digest grouped by owner, with a short suggested next action for the worst offenders, and drops it into the sales channel in Slack along with a full CSV so reps can work the list line by line.
A Schedule trigger starts the run on a cron expression in your own timezone, so the report lands at a predictable local time every business day. Each run is stateless: it reads the board fresh, computes staleness against the current date, and posts a new message. Nothing is written back to Monday.com, so re-running is safe and idempotent (you simply get another identical digest for the same snapshot). If the board has no stale leads on a given day, you can short-circuit and skip the Slack post entirely, so the channel only hears from the workflow when there is something to act on.
Prerequisites
- A Monday.com connection added under Connections, with access to the board that holds your leads. You will need the board's numeric ID.
- A Slack connection authorized to post to your sales channel, plus the channel ID or name (for example
#sales). - On the Monday.com board: an owner column (person), a status column that marks open leads, and a date column that records last activity (a "Last contacted" or "Last activity" date column). Note the column titles so you can read them from the item's
column_values. - A defined SLA window in days (for example, a lead is "stale" after 5 days with no activity).
- The date and csv utility connectors are built in and need no setup.
Step 1: Start with a Schedule trigger
Create a new workflow and set the Trigger type to Schedule. Add a 5-field Unix cron expression and an IANA timezone. To run at 9am on weekdays in Sydney, use the cron expression 0 9 * * 1-5 with the timezone Australia/Sydney. The timezone field is what guarantees the report lands at 9am local time rather than UTC. A single Schedule trigger can hold more than one schedule, so you could add a second entry if some regions need a different hour.
The trigger output is {{ scheduledAt }}, the timestamp the run fired. You will not usually need it, because the next step computes "now" independently, but it is available if you want to stamp the report header.
Step 2: Pull open leads from Monday.com (Direct mode)
Add a Connector node on the monday connector in Direct mode and choose the list-items tool. Direct mode is the right choice here: it is a single, predictable read with no AI cost. Map the inputs:
boardId: "1234567890"
limit: 200
Save the result to a variable such as leads. The tool returns the board's items, each with its id, name, and a column_values array where every entry has an id, a text (the human-readable value), and a raw value. Boards larger than your limit return a pagination cursor; see Tips for how to page. If your board mixes won and lost deals with open ones, you will filter to open leads in the next step rather than asking Monday.com to filter, which keeps the query simple.
Step 3: Compute the staleness cutoff with the date connector
Add a Connector node on the date connector in Direct mode. First, call now to get the current moment, saving it to today. Then add a second date node using subtract to build the cutoff date: subtract your SLA window from today. For a 5-day SLA:
date: "{{ today.iso }}"
amount: 5
unit: "days"
Save this as cutoff. Any lead whose last-activity date is earlier than cutoff has crossed the SLA window. Computing the cutoff once, up front, keeps the comparison in the next step cheap and consistent across every row in the batch. You can also use the date connector's diff tool later if you prefer to report the exact number of days each lead has been idle.
Step 4: Flag stale rows with a Transform node
Add a Transform node to reshape the raw Monday.com items into a clean, flagged list. Read the owner, status, and last-activity values out of each item's column_values by their column id or title, keep only items whose status marks them open, and compare each last-activity date against {{ cutoff }}. Emit a tidy array of stale leads, for example:
[
{
"lead": "Acme Corp - Q3 expansion",
"owner": "Jordan Lee",
"status": "Working",
"lastActivity": "2026-06-12",
"daysIdle": 9
}
]
Save this as staleLeads. Doing the date comparison and the field extraction here, deterministically, means the AI step in the next stage only has to write prose, not crunch dates. If you would rather express the day-count math in code, you can swap this for a Connector node on the code connector using execute-javascript, but the Transform node is enough for straightforward filtering and flagging.
Step 5: Skip the run when there is nothing to report
Add a Condition node that checks whether {{ staleLeads }} is empty. If the array length is zero, route to a path that ends the workflow quietly so the Slack channel stays silent on clean days. If there is at least one stale lead, continue down the true branch to build and post the digest. This single guard is what keeps the report meaningful: the team only hears from it when there is real work waiting.
Step 6: Summarize the worst offenders with a Connector node in Agent mode
Add a Connector node in Agent mode. Agent mode lets Miraxa, the intelligent layer across your automation, read the flagged list and write an owner-by-owner digest with judgment about which leads matter most and what to do next. Pass {{ staleLeads }} into the prompt, for example:
You are preparing a daily stale-lead digest for a sales team.
Here are the leads that have gone past the SLA window:
{{ staleLeads }}
Group them by owner. For each owner, list their stale leads
sorted by daysIdle (most idle first). Call out the three worst
offenders across the whole list at the top. For each of those
three, suggest one concrete next action (a call, a follow-up
email, or a re-qualification). Keep it concise and scannable.
Use Slack-friendly formatting with short lines.
To keep the output reliable, set a Response Schema so the node returns structured JSON, for example a headline string, a worstOffenders array, and an ownerSections array. Save the result to digest. Because Agent mode costs AI credits, it earns its place here by doing the one task that is genuinely judgment-based: ranking and recommending. Everything deterministic was already handled in Direct mode and the Transform node.
Step 7: Build a CSV and post to Slack
Add a Connector node on the csv connector in Direct mode and choose from-json to turn the flagged list into a downloadable file. Pass {{ staleLeads }} as the data input and pin the column order so the file is readable:
data: "{{ staleLeads }}"
columns: ["owner", "lead", "status", "lastActivity", "daysIdle"]
header: true
Save the CSV string to leadCsv. Then add a Connector node on the slack connector in Direct mode using send-message. Set the channel to your sales channel and build the message text from the digest, for example:
channel: "#sales"
text: "*Daily stale-lead report* ({{ today.date }})
{{ digest.headline }}
{{ digest.ownerSections }}"
Attach {{ leadCsv }} as the file so reps can open the full list in a spreadsheet. If your Slack workspace formats the long digest poorly in a single message, post the headline and worst offenders in the main message and let the attached CSV carry the full detail.
Tips
- Keep the heavy lifting in Direct mode and the Transform node. Only the digest in Step 6 needs Agent mode, which keeps each run's AI cost small and predictable.
- If your board can exceed the
limityou set onlist-items, wrap the read in a Loop node that re-callslist-itemswith the returnedcursoruntil no cursor comes back, appending each page toleads. - Report the idle gap explicitly. Adding
daysIdle(from the date connector'sdifftool) to each row makes the digest and the CSV far more actionable than a bare "stale" flag. - Use the same SLA constant in Step 3 and Step 4 by defining it once in a variable, so the cutoff math and the report wording never drift apart.
Common Pitfalls
- Timezone drift. A Schedule trigger without an explicit timezone fires on UTC, so a 9am report can arrive in the middle of the night. Always set the IANA timezone (for example
Australia/Sydney) alongside the cron expression. - Reading the wrong column. Monday.com returns each value inside
column_valueskeyed by columnid, not by the title you see in the UI. Confirm the exact column id for your last-activity date before comparing, or you will flag every lead as stale. - Empty or malformed dates. Leads with no last-activity date will not compare cleanly against
cutoff. Decide in the Transform node whether a missing date counts as stale (often it should) and handle it explicitly rather than letting it fall through. - Noisy channel on quiet days. Skipping the Condition node in Step 5 means the workflow posts an empty report every morning. The guard is what keeps the team paying attention to it.
Testing
Before switching the schedule on, validate against a small slice. Temporarily lower the limit on the list-items node and point it at a test board, or tighten the SLA to a value you know will match a handful of rows. Use the Run button to fire the workflow manually and inspect each node's output in the execution log: confirm staleLeads contains the rows you expect, that digest reads cleanly, and that the CSV columns are in order. Post the first few runs to a private test channel in Slack rather than #sales. Once the digest and attachment look right, point the Slack node at the real channel and enable the Schedule trigger.