How to Email a Daily Deputy Roster Summary to Managers
Build a Spojit workflow that runs every morning, pulls the day's Deputy rosters, has an Agent-mode Connector node write a per-location shift summary, and emails it to your location managers.
What This Integration Does
Location managers usually start the day by opening Deputy and squinting at a grid of shifts to work out who is on, when, and where. This workflow does that reading for them. Each morning it fetches the scheduled rosters from Deputy, groups them by location, and asks the agent to write a short plain-language summary for each site: how many people are rostered, the first and last shift times, and anything that looks thin or unusual. The result lands in their inbox before they sit down, so coverage problems surface early instead of at the lunch rush.
The workflow runs on a Schedule trigger, so nothing needs to happen for it to fire: it wakes on a cron expression in your timezone, reads the current rosters and locations from Deputy through a Connector node in Direct mode, narrows the rosters down to today, hands the grouped data to a Connector node in Agent mode for the write-up, and sends the formatted text with a Send Email node. It writes nothing back to Deputy and keeps no state between runs, so each morning starts fresh and re-running it simply produces another email from the same live data.
Prerequisites
- A Deputy connection added under Connections with permission to read rosters and locations. See the Deputy connector reference for setup.
- Your managers' email addresses. If any recipient is outside your organization, add them to the allowlist under Settings → General → Email recipients first.
- The IANA timezone your sites run in (for example
Australia/Sydney), so "today" and the send time line up with local mornings. - An AI model available in your workspace for the Agent mode summary step. This step costs AI credits.
Step 1: Add a Schedule trigger that fires each morning
Create a new workflow and set its trigger to Schedule. A Schedule trigger uses a 5-field Unix cron expression plus an IANA timezone. To run at 6:00 AM on weekdays in Sydney, set the cron to 0 6 * * 1-5 and the timezone to Australia/Sydney. If your sites do not operate on weekends, weekday-only is the right scope; use 0 6 * * * for every day. The trigger output is simply { scheduledAt }, which you can reference later as {{ trigger.scheduledAt }} to stamp the email with the run date.
Step 2: Fetch the rosters and locations from Deputy
Add a Connector node in Direct mode, choose your Deputy connection, and select the list-rosters tool. This tool takes no inputs and returns every scheduled shift in your account. Name its output variable rosters. Add a second Connector node, again Direct mode on Deputy, and select list-locations (also input-free); name its output locations. You will use the location list to turn the location IDs on each roster into readable site names. Direct mode is deliberate here: these are predictable single-tool reads, so they cost no AI credits and always return the same shape.
Step 3: Narrow the rosters down to today
Because list-rosters returns all upcoming shifts, add a Transform node to keep only those starting on the run date and to attach a friendly location name to each. Compute today in your timezone from the trigger time, then filter and group the rosters. A structured transform like the one below produces one entry per location with the shifts sorted by start time:
const day = new Date({{ trigger.scheduledAt }})
.toLocaleDateString("en-CA", { timeZone: "Australia/Sydney" });
const siteName = Object.fromEntries(
{{ locations }}.map(l => [l.Id, l.CompanyName])
);
const todays = {{ rosters }}
.filter(r => (r.Date || "").startsWith(day))
.map(r => ({
location: siteName[r.OperationalUnit] || "Unassigned",
employee: r.EmployeeName,
start: r.StartTimeLocalized,
end: r.EndTimeLocalized
}));
return { day, todays };
Name the output variable roster. If your Deputy field names differ, open the raw output of the list-rosters step in the run logs and map the actual date, employee, and start/end fields. You can also ask Miraxa "what fields does my rosters step return?" while editing the node.
Step 4: Have the agent write a per-location summary
Add a Connector node in Agent mode. Agent mode lets the agent reason over the data and return a written summary, and it supports a Response Schema so the output comes back as predictable JSON. Pass {{ roster.todays }} into the prompt and ask for a short brief per location. A prompt like this works well:
Here are today's rostered shifts grouped by location: {{ roster.todays }}.
For each location, write a 2 to 3 sentence manager brief: how many people
are rostered, the earliest start and latest finish, and flag any location
with fewer than 2 people or a gap longer than 3 hours between shifts.
Keep it factual and concise. Do not invent shifts that are not listed.
Set a Response Schema so each location returns as an object, for example an array of { location, headcount, firstStart, lastEnd, summary }. Name the output variable brief. The "do not invent" instruction matters: it keeps the summary anchored to the real rosters rather than filling gaps.
Step 5: Format the email body
Add a Transform node to turn the structured brief into a readable plain-text body. Join each location block into a section with a heading and the summary text:
const lines = {{ brief }}.map(b =>
`${b.location} (${b.headcount} rostered, ${b.firstStart}-${b.lastEnd})\n${b.summary}`
);
return { body: `Roster summary for ${ {{ roster.day }} }\n\n` + lines.join("\n\n") };
Name the output variable email. Keeping the formatting in a Transform node (rather than asking the Agent for final layout) means the Agent only has to produce facts, which is cheaper and more reliable.
Step 6: Send the summary to managers
Add a Send Email node, which sends from Spojit's built-in mail service with no extra connection needed. Set Recipients to your managers as a comma-separated list, set Subject to a templated line such as Daily roster summary - {{ roster.day }}, and set Body to {{ email.body }}. Leave Reply-To as the workflow owner or point it at your scheduling lead. Set If sending fails to Fail the workflow so a delivery problem shows up as a failed run rather than passing silently. If you would rather send from your own domain, swap this node for a Connector node using the Resend or SMTP connector and its send-email tool.
Tips
- To route each location's brief to a different manager, replace the single Send Email node with a Loop node over
{{ brief }}and look up the recipient per location inside the loop. - Set the cron time early enough that the email is waiting before the first shift, but late enough that any overnight roster edits in Deputy are already saved.
- A Schedule trigger can hold multiple schedules: add a second cron entry if a few sites need an earlier or later send time.
- Reference
{{ trigger.scheduledAt }}rather than computing "now" inside the Agent prompt, so the date in the email always matches the run that produced it.
Common Pitfalls
- Timezone drift. If the cron timezone and the timezone in your Transform filter disagree, "today" can resolve to yesterday or tomorrow. Use the same IANA timezone in both places.
- Empty roster days. On a day with no shifts,
{{ roster.todays }}is empty and the Agent may pad the summary. Add a Condition node before the Agent to skip the email when the list is empty, or instruct the Agent to state plainly that no shifts are rostered. - Field name mismatches. Deputy roster records use its own field names for the date, location, and shift times. Confirm them in the run logs before trusting the filter, since a wrong field name silently produces an empty result.
- Recipient allowlist. External manager addresses must be on the org allowlist or the Send Email node will be blocked. Add them under Settings → General → Email recipients first.
Testing
Before relying on the schedule, validate the flow manually. Temporarily set the trigger to Manual, or add a one-off cron a few minutes out, and run it. Point the Send Email recipient at yourself, confirm the list-rosters step returns shifts, check that the Transform node correctly filters to today and attaches location names, and read the Agent summary against the raw rosters to be sure the counts and times are accurate. Once a real morning's email looks right, switch the trigger back to Schedule and add your managers as recipients.