Back to Staff Scheduling & Rostering

Developer Handover Pack

Everything needed to build the automation from scratch: current state, full agent specs, data flow, and the build stack.

4 pagesPDF · Technical
FS-DOC-04Technical

Developer Handover Pack

Staff Scheduling & Rostering

[YourCompany.com] · Operations Department · Prepared by FullSpec · [Today's Date]

This document is the primary technical reference for the FullSpec team building the Staff Scheduling and Rostering automation. It maps the current nine-step manual process, specifies all three agents in full, traces the end-to-end data flow with exact field names, and recommends the build stack with time estimates. The FullSpec team owns delivery of everything in this document. [YourCompany.com] is responsible for providing tool access, confirming award and overtime rules, and approving the draft roster at the single retained human step.

01Process snapshot

Step
Name
Description
1
Send Availability Request to Staff
Manager sends availability request via Gmail to each staff member. Responses arrive over one to two days. Time cost: 20 min/cycle.
2 BOTTLENECK
Collect and Log Availability Responses
Manager manually records each reply into Google Sheets and repeatedly follows up with non-responders until a complete picture emerges. Time cost: 40 min/cycle.
3
Review Demand and Shift Requirements
Manager reviews upcoming workload and service commitments to determine staffing levels required per shift. Time cost: 20 min/cycle.
4 BOTTLENECK
Draft Roster Against Availability
Manager hand-builds the roster in Google Sheets, matching available staff to required shifts and balancing hours across the team. Time cost: 60 min/cycle.
5
Check for Award and Overtime Conflicts
Manager reviews the drafted roster for award breaches, consecutive-day violations, or overtime triggers and adjusts shifts manually. Time cost: 25 min/cycle.
6 BOTTLENECK
Resolve Scheduling Conflicts
Manager contacts staff individually by phone to negotiate swaps or find cover wherever gaps or double-ups remain. Time cost: 30 min/cycle.
7
Publish Roster to Staff
Finalised roster is uploaded to Deputy and staff are expected to confirm they have seen their shifts. Time cost: 15 min/cycle.
8
Handle Last-Minute Change Requests
In the days following publication, manager fields shift-swap requests and call-outs and manually updates the roster in Google Sheets. Time cost: 30 min/cycle.
9
Export Approved Hours to Payroll
At pay-period close, manager manually re-enters or exports approved shift hours from Deputy into Xero for payroll processing. Time cost: 20 min/cycle.
Time cost summary: Total manual time per cycle is 260 minutes (4 hours 20 min), running approximately 4 cycles per month, equal to roughly 4.5 hours per week and 225 hours per year. The automation replaces steps 1, 2 (Availability Collection Agent), steps 3, 4, 5, and 6 (Roster Drafting Agent), and steps 7 and 9 (Roster Publication and Payroll Agent). Step 8 (last-minute change requests) is reduced in frequency by proactive staff notifications but remains a human-managed exception. The single retained human step is manager review and approval before publication.
Developer Handover PackPage 1 of 4
FS-DOC-04Technical

02Agent specifications

Availability Collection Agent

Sends the weekly availability request to all active staff via Gmail at the start of each scheduling period. Monitors for form responses written into Google Sheets, identifies any staff who have not responded within 24 hours, and sends a single automated follow-up reminder via Gmail. Once all responses are logged or the collection window closes, marks the Google Sheet as complete to trigger the Roster Drafting Agent. This agent eliminates the most time-intensive and repeat-labour steps in the current process, replacing manual chasing and scattered reply logging with a structured, timestamped data record.

Trigger
Recurring weekly timer fires at the configured schedule-period start time (e.g. Monday 07:00 local time). Timer managed via the orchestration platform's built-in scheduler.
Tools
Gmail (send availability request email + follow-up reminder), Google Sheets (log responses, mark collection complete)
Replaces steps
Step 1: Send Availability Request to Staff; Step 2: Collect and Log Availability Responses
Estimated build
6 hours, Moderate complexity
// Input
trigger: weekly_timer_event { scheduled_at: ISO8601, period_label: 'Week of YYYY-MM-DD' }
staff_list: Google Sheets tab 'Staff' { staff_id, full_name, email, employment_status }

// Processing
FOR each staff WHERE employment_status = 'active':
  Gmail.send({ to: staff.email, template: 'availability_request', period_label })
  log to Sheets tab 'Availability_Log': { staff_id, sent_at, response_status: 'pending' }
WAIT 24 hours
FOR each row WHERE response_status = 'pending':
  Gmail.send({ to: staff.email, template: 'availability_reminder', period_label })
  update Sheets: { reminder_sent_at: now() }
WAIT until collection_window_closes OR all response_status = 'received'
Sheets.setCell('Control', 'availability_complete', TRUE)

// Output
Google Sheets tab 'Availability_Log' fully populated:
  { staff_id, full_name, available_days[], preferred_hours, notes, submitted_at, reminder_sent }
Control cell 'availability_complete' = TRUE (triggers Roster Drafting Agent)
  • Gmail must be connected via OAuth 2.0 with scopes gmail.send and gmail.readonly. Confirm the sending address is a monitored [YourCompany.com] inbox, not a personal account.
  • The availability form must produce structured, parseable output. A Google Form writing to the 'Availability_Log' sheet is the simplest approach. A poorly designed form producing free-text responses will break parsing logic and must be corrected before build begins.
  • The staff list source of truth is the 'Staff' tab in the central Google Sheet. Any staff member with employment_status != 'active' must be excluded from both the send list and the roster. Confirm the field name and values with the operations team before build.
  • The follow-up reminder fires exactly once per non-responder at T+24 hours. There is no second reminder. After the collection window closes, the agent marks the sheet complete regardless of any outstanding responses; those staff are flagged as 'no_response' in the Availability_Log.
  • De-duplication: if a staff member submits the form more than once, the agent takes the most recent submission by submitted_at timestamp and discards earlier rows.
  • Confirm the collection window duration with the operations manager before encoding it. Default assumption is 48 hours from initial send.
  • Google Sheets API tier required: standard read/write access via service account credentials. No Sheets advanced tier is needed.
Roster Drafting Agent

Triggered when the Availability Collection Agent marks the Google Sheet as complete. Reads the populated availability log and the week's shift demand requirements from a separate 'Demand' tab in Google Sheets. Applies the configured award rules (maximum daily hours, minimum rest between shifts, maximum consecutive days, overtime thresholds) to allocate staff to shifts and produce a draft roster. Any shift slot that cannot be filled, or any allocation that would breach a rule, is flagged in a conflict summary. The conflict summary is posted to the manager's Slack channel. The draft roster is written back to the 'Draft_Roster' tab in Google Sheets and a row is added to the 'Approval_Control' tab with status set to 'pending_review'. If no conflicts exist, an approval prompt is also sent to Slack.

Trigger
Google Sheets Control cell 'availability_complete' changes to TRUE (polled by the orchestration platform on a short interval, or via a Sheets webhook if the platform supports it).
Tools
Google Sheets (read availability and demand, write draft roster and conflict log), Deputy (read current shift template and staff profile data), Slack (post conflict summary and approval prompt to manager channel)
Replaces steps
Step 3: Review Demand and Shift Requirements; Step 4: Draft Roster Against Availability; Step 5: Check for Award and Overtime Conflicts; Step 6: Resolve Scheduling Conflicts
Estimated build
10 hours, Complex complexity
// Input
Google Sheets 'Availability_Log': { staff_id, available_days[], preferred_hours, no_response_flag }
Google Sheets 'Demand': { shift_date, shift_label, start_time, end_time, min_staff, max_staff, role_required }
Google Sheets 'Award_Rules': { rule_id, rule_type, threshold_value, breach_action }
Deputy API GET /api/v1/operationalunit: { location_id, shift_templates[] }
Deputy API GET /api/v1/employee: { employee_id, deputy_staff_id, role, contracted_hours }

// Processing
FOR each shift in Demand WHERE shift_date in period_label:
  candidates = Availability_Log WHERE shift_date in available_days[]
  ranked_candidates = sort by (contracted_hours_remaining DESC, last_rostered_date ASC)
  FOR each candidate in ranked_candidates:
    IF award_rules_pass(candidate, shift): assign candidate to shift; break
  IF no_candidate_assigned: add to conflicts { shift_date, shift_label, reason: 'no_available_staff' }
  IF rule_breach detected: add to conflicts { staff_id, rule_id, breach_type, suggested_action }
Write Sheets 'Draft_Roster': { staff_id, shift_date, shift_label, start_time, end_time, role, status: 'draft' }
Write Sheets 'Conflict_Log': { conflict_id, shift_date, shift_label, staff_id, breach_type, suggested_action }
Write Sheets 'Approval_Control': { period_label, draft_created_at, conflict_count, approval_status: 'pending_review' }

// Output
Slack POST to #roster-approvals: conflict summary message with conflict_count, breach_type list, and approval link
Slack POST: approval prompt if conflict_count = 0
Google Sheets 'Draft_Roster' fully populated for manager review
Google Sheets 'Approval_Control'.approval_status = 'pending_review'
  • Award and overtime rules must be fully documented and signed off by the operations manager before this agent is built. Ambiguous or jurisdiction-specific rules cannot be inferred and will block build progress. Rules are stored in the 'Award_Rules' tab and read at runtime, not hard-coded.
  • Deputy API authentication uses OAuth 2.0 with scopes: employee:read, roster:write, operationalunit:read. Confirm the Deputy subscription tier supports API access (Deputy Premium or above required). Deputy's API rate limit is 200 requests per minute; the drafting logic must batch shift writes accordingly.
  • The demand schedule ('Demand' tab) must be populated by the operations manager for each period before the agent runs. The agent does not generate demand; it reads it. Confirm who owns updating the Demand tab and whether that step can be pre-loaded or templated.
  • The conflict-flagging Slack message must include a direct link to the Draft_Roster Google Sheet and a clear list of each unresolved conflict. The Slack bot token must have chat:write scope and be added to the #roster-approvals channel before build.
  • The agent does not contact staff directly. All output at this stage is to the manager only. No Deputy shifts are created until the Roster Publication and Payroll Agent fires post-approval.
  • If staff_id values in Google Sheets do not match deputy_staff_id in Deputy, a mapping table must be created and maintained. Confirm this mapping exists and is accurate before build.
Roster Publication and Payroll Agent

Triggered when the manager marks the draft roster as approved by updating the 'Approval_Control' tab in Google Sheets (or, if Deputy's approval workflow is used, by a Deputy webhook event). Reads the finalised Draft_Roster and creates each shift record in Deputy via the API. Once Deputy confirms successful shift creation, sends a personalised shift notification to each staff member via both Slack and Gmail. At pay-period close (a separate recurring timer), reads confirmed shift hours from Deputy and posts timesheet entries to Xero ready for payroll processing. This agent completes the end-to-end loop and eliminates all remaining manual publication and payroll data-entry steps.

Trigger
Primary: Google Sheets 'Approval_Control'.approval_status changes to 'approved' (polled or webhook). Secondary (payroll export): separate recurring timer aligned to pay-period close date.
Tools
Deputy (create and publish shifts), Slack (personalised staff shift notifications), Gmail (shift confirmation emails to staff), Xero (create timesheet entries at pay-period close)
Replaces steps
Step 7: Publish Roster to Staff; Step 9: Export Approved Hours to Payroll
Estimated build
8 hours, Moderate complexity
// Input (on approval trigger)
Google Sheets 'Approval_Control': { approval_status: 'approved', approved_by, approved_at }
Google Sheets 'Draft_Roster': { staff_id, deputy_staff_id, shift_date, start_time, end_time, role, shift_label }
Staff contact data from Sheets 'Staff': { staff_id, full_name, email, slack_user_id }

// On approval: Deputy shift creation
FOR each row in Draft_Roster WHERE status = 'draft':
  Deputy API POST /api/v1/roster:
    { employee: deputy_staff_id, startTime: shift_date+start_time ISO8601,
      endTime: shift_date+end_time ISO8601, operationalUnit: location_id,
      published: true, comment: shift_label }
  IF Deputy response = 200: update Sheets Draft_Roster.status = 'published'
  IF Deputy response != 200: log to 'Error_Log', alert Slack #roster-approvals

// On approval: staff notifications
FOR each staff_id in published shifts:
  Slack POST to staff.slack_user_id (DM):
    personalised message listing each shift_date, start_time, end_time, shift_label
  Gmail.send({ to: staff.email, template: 'shift_confirmation',
    shifts: [ { shift_date, start_time, end_time, shift_label } ] })

// Output (on approval)
Deputy: all shifts created and published for the period
Slack DMs: personalised shift confirmations sent to each staff member
Gmail: shift confirmation emails sent to each staff member
Sheets 'Draft_Roster'.status = 'published' for all rows

// Input (on payroll timer trigger)
Deputy API GET /api/v1/roster?startTime=period_start&endTime=period_end&published=true
Response: { employee_id, startTime, endTime, totalHours, approved }

// Output (payroll export)
FOR each approved shift in Deputy roster response:
  Xero API POST /api.xro/2.0/Timesheets:
    { EmployeeID: xero_employee_id, StartDateUTC: period_start,
      EndDateUTC: period_end, TimesheetLines: [
        { EarningsRateID: standard_rate_id, NumberOfUnits: totalHours,
          TrackingItemName: shift_label } ] }
Xero timesheet entries created and ready for payroll run
  • Deputy API for shift creation uses POST /api/v1/roster. The 'published: true' flag must be set on creation to notify staff via Deputy's own notification layer in addition to the Slack and Gmail notifications this agent sends. Confirm with the operations manager whether Deputy's built-in notifications should be suppressed to avoid duplicate alerts.
  • Xero API authentication uses OAuth 2.0 with scopes: payroll.timesheets, payroll.employees. The Xero tenant ID must be stored in the credential store. Confirm whether the Xero subscription includes payroll (Xero Payroll is not included in all tiers).
  • The xero_employee_id must be mapped against deputy_staff_id and staff_id before the payroll export step is built. A three-way mapping table (Sheets staff_id, Deputy employee_id, Xero EmployeeID) must be created and validated before build.
  • The EarningsRateID in Xero must be confirmed for each pay classification (standard hours, overtime, weekend penalty). Do not hard-code a single rate; fetch or map rates per shift_label.
  • If a Deputy shift creation call returns a non-200 response, the failed shift must be logged to the 'Error_Log' tab and a Slack alert sent to #roster-approvals immediately. The agent must not silently skip failed shifts.
  • Slack DMs require the Slack bot to have users:read.email scope to resolve staff email addresses to slack_user_id values if the mapping is not stored in the Staff sheet. Confirm which field is the join key.
  • Gmail shift confirmation emails must be sent from the same address used by the Availability Collection Agent to ensure consistent sender identity for staff.
Developer Handover PackPage 2 of 4
FS-DOC-04Technical

03End-to-end data flow

Full data flow: Staff Scheduling and Rostering, trigger to Xero payroll export
// ============================================================
// STAFF SCHEDULING & ROSTERING: END-TO-END DATA FLOW
// ============================================================

// TRIGGER: Orchestration platform weekly timer
trigger_event = {
  scheduled_at: '2024-06-17T07:00:00+10:00',  // ISO8601 local time
  period_label: 'Week of 2024-06-17'
}

// ============================================================
// AGENT 1: Availability Collection Agent
// ============================================================

// Read staff list
Sheets.read('Staff') ->
  [{ staff_id, full_name, email, slack_user_id, employment_status }]
  FILTER: employment_status = 'active'

// Send availability request emails
FOR each active_staff:
  Gmail.send({
    to: staff.email,
    subject: 'Your availability for Week of 2024-06-17',
    body_template: 'availability_request',
    form_link: 'https://forms.google.com/[availability_form_id]',
    period_label: 'Week of 2024-06-17'
  })
  Sheets.append('Availability_Log', {
    staff_id, full_name, period_label,
    sent_at: now(), response_status: 'pending',
    reminder_sent: FALSE, reminder_sent_at: NULL
  })

// Wait 24 hours, then send follow-up reminder to non-responders
WAIT 24h
non_responders = Sheets.read('Availability_Log')
  FILTER: response_status = 'pending'
FOR each non_responder:
  Gmail.send({ to: staff.email, template: 'availability_reminder', period_label })
  Sheets.update('Availability_Log', staff_id, {
    reminder_sent: TRUE, reminder_sent_at: now()
  })

// Google Form responses write to Availability_Log (Sheets native integration)
// Each submission row:
// { staff_id, full_name, available_days[], preferred_hours,
//   notes, submitted_at, response_status: 'received' }

// De-duplication: if duplicate staff_id exists, keep max(submitted_at)
// Non-responders at window close: response_status = 'no_response'

// Collection window closes (T+48h from initial send)
Sheets.setCell('Control', 'availability_complete', TRUE)
// -> Triggers Agent 2

// ============================================================
// AGENT 1 -> AGENT 2 HANDOFF
// Handoff field: Sheets 'Control'.availability_complete = TRUE
// Handoff data: Sheets 'Availability_Log' fully populated
// ============================================================

// ============================================================
// AGENT 2: Roster Drafting Agent
// ============================================================

// Read inputs
availability = Sheets.read('Availability_Log') ->
  [{ staff_id, available_days[], preferred_hours, response_status }]

demand = Sheets.read('Demand') ->
  [{ shift_date, shift_label, start_time, end_time, min_staff, max_staff, role_required }]
  FILTER: shift_date in period_label range

award_rules = Sheets.read('Award_Rules') ->
  [{ rule_id, rule_type, threshold_value, breach_action }]
  // Examples: max_daily_hours=10, min_rest_between_shifts=10h,
  //           max_consecutive_days=5, overtime_threshold_weekly=38h

deputy_staff = Deputy.GET('/api/v1/employee') ->
  [{ employee_id: deputy_staff_id, display_name, role, contracted_hours }]

// Drafting logic
FOR each shift in demand:
  candidates = availability
    FILTER: shift.shift_date in staff.available_days[]
    AND staff.response_status != 'no_response'
    SORT: contracted_hours_remaining DESC, last_rostered_date ASC
  FOR each candidate in candidates:
    pass = award_rules_check(candidate, shift, award_rules)
    IF pass: assign { staff_id, shift_date, shift_label, start_time, end_time, role }; break
  IF no assignment:
    Conflict_Log.append({
      conflict_id: UUID, shift_date, shift_label,
      staff_id: NULL, breach_type: 'no_available_staff',
      suggested_action: 'Find casual cover'
    })
  IF rule_breach:
    Conflict_Log.append({
      conflict_id: UUID, shift_date, shift_label, staff_id,
      breach_type: rule.rule_type, suggested_action: rule.breach_action
    })

// Write draft roster
Sheets.write('Draft_Roster',
  [{ staff_id, deputy_staff_id, shift_date, shift_label,
     start_time, end_time, role, status: 'draft' }]
)
Sheets.write('Conflict_Log',
  [{ conflict_id, shift_date, shift_label, staff_id,
     breach_type, suggested_action }]
)
Sheets.write('Approval_Control', {
  period_label, draft_created_at: now(),
  conflict_count: Conflict_Log.count(),
  approval_status: 'pending_review'
})

// Post to Slack
Slack.POST('#roster-approvals', {
  text: 'Draft roster ready for Week of 2024-06-17.',
  conflict_count: N,
  conflict_summary: Conflict_Log[],
  draft_link: 'https://docs.google.com/spreadsheets/[roster_sheet_id]'
})

// ============================================================
// AGENT 2 -> AGENT 3 HANDOFF (via manager approval action)
// Handoff field: Sheets 'Approval_Control'.approval_status = 'approved'
// Set by: Manager updates cell manually OR via Deputy approval webhook
// ============================================================

// ============================================================
// AGENT 3: Roster Publication and Payroll Agent
// ============================================================

// On approval trigger
approved_roster = Sheets.read('Draft_Roster')
  FILTER: status = 'draft'   // all rows approved in batch

// Create shifts in Deputy
FOR each row in approved_roster:
  Deputy.POST('/api/v1/roster', {
    employee: row.deputy_staff_id,
    startTime: row.shift_date + 'T' + row.start_time + '+10:00',
    endTime: row.shift_date + 'T' + row.end_time + '+10:00',
    operationalUnit: location_id,
    published: true,
    comment: row.shift_label
  })
  IF response.status = 200:
    Sheets.update('Draft_Roster', row.staff_id, { status: 'published' })
  ELSE:
    Sheets.append('Error_Log', {
      error_id: UUID, agent: 'Publication', staff_id: row.staff_id,
      shift_date: row.shift_date, error_code: response.status,
      error_message: response.body, logged_at: now()
    })
    Slack.POST('#roster-approvals', { alert: 'Shift creation failed', details: row })

// Send staff notifications
staff_shifts = GROUP approved_roster BY staff_id
FOR each staff_member in staff_shifts:
  Slack.POST_DM(staff.slack_user_id, {
    text: 'Your shifts for Week of 2024-06-17:',
    shifts: [{ shift_date, shift_label, start_time, end_time }]
  })
  Gmail.send({
    to: staff.email,
    subject: 'Your shifts for Week of 2024-06-17',
    template: 'shift_confirmation',
    shifts: [{ shift_date, shift_label, start_time, end_time }]
  })

// ============================================================
// PAYROLL EXPORT (separate pay-period close timer)
// ============================================================

// Read confirmed hours from Deputy
deputy_timesheets = Deputy.GET('/api/v1/roster', {
  startTime: period_start_ISO8601,
  endTime: period_end_ISO8601,
  published: true
}) -> [{ employee_id, startTime, endTime, totalHours, approved }]
  FILTER: approved = true

// Map Deputy employee_id to Xero EmployeeID
mapping = Sheets.read('ID_Mapping') ->
  [{ staff_id, deputy_staff_id, xero_employee_id }]

// Post timesheets to Xero
FOR each timesheet_entry in deputy_timesheets:
  xero_id = mapping LOOKUP deputy_staff_id -> xero_employee_id
  earnings_rate_id = LOOKUP earnings_rates BY shift_label
  Xero.POST('/api.xro/2.0/Timesheets', {
    EmployeeID: xero_id,
    StartDateUTC: period_start_ISO8601,
    EndDateUTC: period_end_ISO8601,
    TimesheetLines: [{
      EarningsRateID: earnings_rate_id,
      NumberOfUnits: totalHours,
      TrackingItemName: shift_label
    }]
  })

// END OF FLOW
Developer Handover PackPage 3 of 4
FS-DOC-04Technical

04Recommended build stack

Orchestration layer
A workflow automation platform configured with one workflow (sequence of nodes) per agent: Availability Collection Workflow, Roster Drafting Workflow, and Roster Publication and Payroll Workflow. All three workflows share a single credential store scoped to the project. No platform-specific tool is mandated at this stage; the logic is platform-agnostic and the field mappings and API payloads in this document apply regardless of which tool is selected.
Webhook and polling configuration
Agent 1 to Agent 2 handoff: the orchestration platform polls the Google Sheets 'Control' tab for the availability_complete cell change on a 5-minute interval (or uses a Sheets webhook trigger if the platform supports it). Agent 2 to Agent 3 handoff: polls 'Approval_Control'.approval_status for the value 'approved' on a 5-minute interval. Payroll export: a separate scheduled trigger aligned to the configured pay-period close date and time. All inbound webhooks from Deputy (if used for approval confirmation) must be registered at the Deputy developer portal with the POST endpoint provided by the orchestration platform.
Templating approach
Email body templates for availability_request, availability_reminder, and shift_confirmation are stored as plain-text or HTML templates within the orchestration platform's template store (or as a dedicated Google Doc per template, read at send time). Templates include variable placeholders: {{full_name}}, {{period_label}}, {{form_link}}, {{shifts[]}}. Slack messages use Slack Block Kit JSON for structured formatting of conflict summaries and shift confirmations. All templates must be reviewed and approved by the operations manager before go-live.
Error logging
All agent errors (API failures, mapping mismatches, timeout events) are written to a dedicated Google Sheets tab named 'Error_Log' with fields: error_id (UUID), agent_name, step_description, staff_id (where applicable), shift_date (where applicable), error_code, error_message, logged_at. On any Error_Log write, an immediate Slack alert is posted to #roster-approvals with a summary of the failure. A daily digest of unresolved Error_Log rows is sent to the operations manager via Gmail at 08:00. The FullSpec team will configure an additional email alert to support@gofullspec.com for any error that causes a workflow to halt entirely.
Testing approach
All agents are built and tested in a sandbox environment before any credentials touching live Deputy, Xero, or staff Gmail accounts are used. Sandbox testing uses a duplicate Google Sheet, a Deputy sandbox account (available on Deputy Premium), a Xero demo company, and a test Slack workspace. Two full simulated roster cycles are run end to end in sandbox before UAT with the operations manager. UAT uses live credentials in a controlled test with a small subset of real staff data and a non-published Deputy roster. Go-live only proceeds after both simulated cycles and UAT pass all test cases defined in the Test and QA Plan.
Credential store structure
Google Sheets: service account JSON key (project-scoped, read/write on roster spreadsheet only). Gmail: OAuth 2.0 client credentials (scopes: gmail.send, gmail.readonly). Deputy: OAuth 2.0 token (scopes: employee:read, roster:write, operationalunit:read). Slack: Bot token (scopes: chat:write, users:read, users:read.email, channels:read). Xero: OAuth 2.0 token (scopes: payroll.timesheets, payroll.employees) plus Xero tenant ID. All credentials stored encrypted in the orchestration platform's native credential store. No credentials are stored in Google Sheets or in any workflow node directly.
Estimated total build time
Availability Collection Agent: 6 hours. Roster Drafting Agent: 10 hours. Roster Publication and Payroll Agent: 8 hours. End-to-end integration testing, sandbox simulation (two cycles), and UAT: 6 hours. Discovery, rules mapping, and credential setup (pre-build): included in delivery week 1. Total estimated build effort: 30 hours across weeks 2 to 4 of the 4-week delivery schedule.
Before any build node is started, the following must be confirmed in writing by the operations manager: (1) all award and overtime rules documented and signed off; (2) Deputy API access verified and subscription tier confirmed as Premium or above; (3) Xero Payroll add-on confirmed active and EarningsRateIDs for each pay classification provided; (4) three-way staff ID mapping table (staff_id, deputy_staff_id, xero_employee_id) created and validated; (5) the availability form structure reviewed and approved to ensure structured, parseable output; (6) Slack bot added to #roster-approvals channel and staff Slack user IDs available in the Staff sheet. Contact the FullSpec team at support@gofullspec.com for any blockers on these items.
Developer Handover PackPage 4 of 4

More documents for this process

Every document generated for Staff Scheduling & Rostering.

Launch Plan
Operations · Owner
View
ROI and Business Case
Finance · Owner
View
Process Runbook / SOP
Operations · Owner
View
Integration and API Spec
Technical · Developer
View
Test and QA Plan
Quality · Developer
View