Back to End-of-day / Shift Handover

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

End-of-day / Shift Handover

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

This document gives the FullSpec build team everything needed to configure, connect, and ship the End-of-day / Shift Handover automation. It covers the current-state process map with bottleneck flags, full specifications for both agents, the end-to-end data flow, and the recommended build stack with time estimates. The process owner's responsibility is limited to supplying tool credentials, confirming PagerDuty escalation contacts, and reviewing the pilot shift output. All build, testing, and deployment work is handled by FullSpec.

01Process snapshot

Step
Name
Description
1
Prompt Outgoing Staff for Updates
Team lead verbally reminds staff to submit end-of-shift notes via Slack five to ten minutes before shift end. Reminders are inconsistent and easy to ignore. (5 min)
2
Collect Task Status Updates
Team lead visits each department channel or asks individuals directly to confirm task completion status. Responses trickle in at different times, creating a fragmented picture. (15 min) — BOTTLENECK
3
Review Incident and Equipment Log
Team lead checks the shared Google Sheet for incidents, equipment faults, or near-misses recorded during the shift. Entries are often incomplete or missing entirely. (10 min)
4
Chase Missing Entries
Team lead tracks down staff members to fill gaps in the log before they leave. This step frequently delays the entire handover and is the most common cause of late reports. (12 min) — BOTTLENECK
5
Write Handover Summary
Team lead drafts the handover document in Notion, pulling together tasks, incidents, open items, and priority flags. Format varies significantly by person. (20 min)
6
Attach Supporting Notes or Photos
Photos of equipment issues or screenshots of relevant logs are manually added to the document or pasted into the message thread. (8 min)
7
Distribute Report to Incoming Team
Completed summary is posted to the relevant Slack channel or emailed to the incoming manager and on-call staff. (5 min)
8
Confirm Receipt and Brief Incoming Lead
Outgoing lead confirms the incoming lead has read the report and answers immediate questions before leaving. Skipped entirely when the incoming lead is late. (10 min)
9
File Report for Records
Final handover document is saved to the correct Notion page or Google Drive folder for audit purposes. Frequently forgotten under time pressure. (5 min)
Time cost summary: Total manual time per cycle is 90 minutes. At approximately 10 handover reports per week (daily, across shifts), this equals roughly 900 minutes (15 hours) of team lead time per week at face value, though the confirmed benchmark is 5 hours per week of attributable overhead once overlap and parallel tasks are accounted for. The automation replaces steps 1, 2, 3, 4, 5, 6, 7, and 9. Step 8 (Confirm Receipt and Brief Incoming Lead) is retained as the sole human review step, estimated at 8 minutes per cycle in the automated state.
Developer Handover PackPage 1 of 4
FS-DOC-04Technical

02Agent specifications

Handover Collector Agent

Monitors the shift schedule and fires the end-of-shift data collection sequence to all outgoing staff at the moment the shift-end trigger activates. It sends a structured Slack message with a direct Google Forms link and a ten-minute response window, then polls the Google Sheets response log. Once the window closes, it marks any staff member who did not submit a response as missing, appends a flag row to the Sheets log, and signals the Handover Compiler Agent to proceed regardless. Estimated build time: 6 hours. Complexity: Moderate.

Trigger
Shift-end time reached (scheduled cron) or a shift-close event written to the designated trigger cell in Google Sheets (column: shift_close_flag = TRUE).
Tools
Slack (outbound message to outgoing shift channel), Google Forms (form link distribution), Google Sheets (response ingestion and missing-response flagging).
Replaces steps
1 (Prompt Outgoing Staff), 2 (Collect Task Status Updates), 3 (Review Incident and Equipment Log), 4 (Chase Missing Entries).
Estimated build
6 hours — Moderate
// Input
shift_end_trigger: { shift_id: string, shift_date: ISO8601, site_id: string, outgoing_channel_id: string, staff_list: [{ staff_id, slack_user_id, name }] }

// Output
sheets_log_row: { shift_id, staff_id, name, task_status: enum[complete|in_progress|blocked], incident_flag: boolean, incident_detail: string|null, equipment_flag: boolean, equipment_detail: string|null, response_received: boolean, submitted_at: ISO8601|null, missing_flag: boolean }
collector_status: { shift_id, total_staff: int, responses_received: int, missing_count: int, log_ready: boolean, critical_incidents_present: boolean }
  • Slack workspace must be on a paid plan (Pro or above) to allow the bot to post to private channels. Confirm the outgoing shift channel name and whether it is public or private before build. The Slack bot token requires the chat:write, channels:read, groups:read, and users:read OAuth scopes.
  • Google Forms must be connected to Google Sheets via the native Forms-to-Sheets link. Do not use a third-party connector for this step. The response sheet must be in the same Google account as the Sheets log; confirm shared Drive permissions if the account is a workspace account with Drive restrictions.
  • The Google Sheets log schema must be locked before the agent is built. Column names in the Sheets log are the source of truth for all downstream field references. Any post-launch form field rename requires a coordinated update to the Sheets header row and the Compiler Agent prompt.
  • Dedupe behaviour: if a staff member submits the form more than once within the response window, the agent must retain only the most recent submission, identified by submitted_at timestamp. Earlier rows for the same staff_id within the same shift_id must be marked superseded: true and excluded from the Compiler Agent input.
  • The response window default is 10 minutes from Slack message delivery. This value must be stored as a configurable parameter in the credential or config store, not hardcoded, so the operations manager can adjust it without a code change.
  • Confirm the shift-end trigger source before build. A fixed-time cron is acceptable for a single-site, consistent-schedule operation but will misfire on public holidays or schedule changes. If the business has shift scheduling software, connecting the trigger to a shift-close event in Google Sheets (manual flag by the team lead) is the more reliable fallback and is already supported by the agent design.
  • Missing-response handling: after the window closes, the agent appends one flag row per non-responding staff member with response_received: false and missing_flag: true. It does not send individual Slack chase messages (that behaviour is replaced by the automation). The Compiler Agent reads these flags and surfaces them in the report.
Handover Compiler Agent

Reads the completed Google Sheets log produced by the Handover Collector Agent, groups entries by category (tasks, incidents, equipment flags, open items, and missing responses), and writes a structured handover report in plain English using a consistent template. It evaluates whether any incident_flag or equipment_flag rows meet the PagerDuty escalation threshold defined in the config, raises an alert if so, then posts the report to the designated Slack operations channel, sends a copy via Gmail to the incoming manager and on-call contacts, and files the report to the correct Notion database page for the shift date. Estimated build time: 9 hours. Complexity: Moderate.

Trigger
Handover Collector Agent sets collector_status.log_ready = true in the shared Sheets log, OR the response window closes and collector_status is written regardless of completion.
Tools
Google Sheets (source log read), Notion (report filing to shift-date database), Slack (report post to operations channel), Gmail (email to incoming manager and on-call list), PagerDuty (alert creation for unresolved incidents).
Replaces steps
5 (Write Handover Summary), 6 (Attach Supporting Notes or Photos), 7 (Distribute Report to Incoming Team), 9 (File Report for Records).
Estimated build
9 hours — Moderate
// Input
collector_status: { shift_id, total_staff, responses_received, missing_count, log_ready, critical_incidents_present }
sheets_log_rows: [ { shift_id, staff_id, name, task_status, incident_flag, incident_detail, equipment_flag, equipment_detail, response_received, submitted_at, missing_flag, superseded } ]
config: { escalation_threshold: enum[any_incident|high_priority_only], pagerduty_service_id: string, incoming_manager_email: string, oncall_emails: [string], slack_ops_channel_id: string, notion_database_id: string, notion_parent_page_id: string }

// Output
handover_report: { shift_id, shift_date, site_id, generated_at: ISO8601, sections: { tasks_complete: [string], tasks_in_progress: [string], tasks_blocked: [string], incidents: [{ staff: string, detail: string, escalated: boolean }], equipment_flags: [{ staff: string, detail: string }], missing_responses: [string], priority_notes: string }, report_markdown: string }
slack_message_ts: string
gmail_message_id: string
notion_page_id: string
pagerduty_incident_id: string|null

// On escalation (critical_incidents_present = true OR any incident_flag row meets threshold)
pagerduty_payload: { service_id, title: 'Unresolved incident(s) on shift [shift_id]', body: string, severity: enum[critical|warning], dedup_key: shift_id }
  • Notion integration requires a Notion internal integration token with insert and update permissions on the target database. The database must have the following properties pre-created before build: Shift Date (date), Shift ID (text), Site (select), Report Status (select: draft|published), Report Body (rich text). Confirm property names with the operations manager; the agent writes to these by exact property name.
  • The AI compilation step must use a fixed system prompt stored in the config store, not generated dynamically. The prompt defines section order, label names, and the plain-English tone. The operations manager must review and sign off the prompt template during the pilot week before full rollout.
  • PagerDuty escalation threshold must be confirmed with the operations manager before the build goes to pilot. The default config is escalation on any row where incident_flag = true. If the team only wants pages for high-priority incidents, this must be set in config before testing, not after go-live, because changing it post-launch will affect dedup logic.
  • Gmail sending must use the OAuth 2.0 credential for the operations Gmail account, not a service account without SMTP delegation. Required scope: gmail.send. Confirm whether the sending address must match a specific domain alias used by the team.
  • Slack report post must use Block Kit formatting for readability. Define the block structure in a reusable template stored in the config store. Do not hardcode block structure inside the agent logic.
  • Notion filing must match the shift date to the correct database page. The agent must query the Notion database for an existing page where Shift Date equals the current shift_date before creating a new one. This prevents duplicate pages for the same shift if the workflow is re-run due to an error.
  • End-to-end test must use a sample Google Sheets log populated with a realistic mix of complete, blocked, and missing responses plus at least one incident_flag = true row, before any pilot shift is run live.
Developer Handover PackPage 2 of 4
FS-DOC-04Technical

03End-to-end data flow

Full trigger-to-output data flow. Field names match Google Sheets column headers and Notion property names exactly.
// ============================================================
// END-TO-END DATA FLOW: End-of-day / Shift Handover
// ============================================================

// TRIGGER
// Source: Scheduled cron at shift_end_time OR Google Sheets cell shift_close_flag = TRUE
TRIGGER -> {
  shift_id: 'SHIFT-20240527-AM',
  shift_date: '2024-05-27',
  site_id: 'SITE-01',
  outgoing_channel_id: 'C04XYZSLACK',
  staff_list: [
    { staff_id: 'S01', slack_user_id: 'U01AAA', name: 'Jordan Lee' },
    { staff_id: 'S02', slack_user_id: 'U02BBB', name: 'Cam Riley' },
    { staff_id: 'S03', slack_user_id: 'U03CCC', name: 'Alex Kim' }
  ]
}

// ============================================================
// AGENT HANDOFF 1: Trigger -> Handover Collector Agent
// ============================================================

// ACTION: Post structured Slack message to outgoing_channel_id
Slack.chat.postMessage -> {
  channel: 'C04XYZSLACK',
  text: 'Shift end reached. Please complete your handover form: https://forms.gle/[form_id]',
  blocks: [ ShiftEndPromptBlock ],
  ts: '1716800000.000100'   // stored as slack_prompt_ts
}

// ACTION: Wait for Google Forms responses (response_window_minutes: 10)
// Google Forms -> Google Sheets (native linked sheet append)
GoogleForms.onResponse -> GoogleSheets.append -> {
  sheet: 'ShiftLog',
  row: {
    shift_id: 'SHIFT-20240527-AM',
    staff_id: 'S01',
    name: 'Jordan Lee',
    task_status: 'complete',
    incident_flag: false,
    incident_detail: null,
    equipment_flag: true,
    equipment_detail: 'Forklift battery low, needs charge before PM shift',
    response_received: true,
    submitted_at: '2024-05-27T14:08:33Z',
    missing_flag: false,
    superseded: false
  }
}

// ACTION: After response window closes, flag non-responding staff
// S03 (Alex Kim) did not submit
GoogleSheets.append -> {
  shift_id: 'SHIFT-20240527-AM',
  staff_id: 'S03',
  name: 'Alex Kim',
  task_status: null,
  incident_flag: false,
  incident_detail: null,
  equipment_flag: false,
  equipment_detail: null,
  response_received: false,
  submitted_at: null,
  missing_flag: true,
  superseded: false
}

// ACTION: Write collector_status to config cell in ShiftLog sheet
GoogleSheets.update -> collector_status_cell -> {
  shift_id: 'SHIFT-20240527-AM',
  total_staff: 3,
  responses_received: 2,
  missing_count: 1,
  log_ready: true,
  critical_incidents_present: false
}

// ============================================================
// AGENT HANDOFF 2: Handover Collector Agent -> Handover Compiler Agent
// Trigger: log_ready = true written to ShiftLog sheet
// ============================================================

// ACTION: Compiler Agent reads all ShiftLog rows for shift_id = 'SHIFT-20240527-AM'
GoogleSheets.read -> rows WHERE shift_id = 'SHIFT-20240527-AM' AND superseded = false

// ACTION: AI compilation step groups rows and writes report
AI.compile -> handover_report -> {
  shift_id: 'SHIFT-20240527-AM',
  shift_date: '2024-05-27',
  site_id: 'SITE-01',
  generated_at: '2024-05-27T14:22:07Z',
  sections: {
    tasks_complete: ['Jordan Lee: all zone-A picks completed'],
    tasks_in_progress: ['Cam Riley: goods-in count 80% done, remaining for PM shift'],
    tasks_blocked: [],
    incidents: [],
    equipment_flags: [{ staff: 'Jordan Lee', detail: 'Forklift battery low, needs charge before PM shift', escalated: false }],
    missing_responses: ['Alex Kim (S03) did not submit before window closed'],
    priority_notes: 'PM shift lead: confirm forklift battery status on arrival.'
  },
  report_markdown: '...'
}

// ACTION: Evaluate escalation threshold
// critical_incidents_present = false AND equipment_flag escalated = false -> no PagerDuty alert
pagerduty_incident_id: null

// ACTION: Post report to Slack operations channel
Slack.chat.postMessage -> {
  channel: slack_ops_channel_id,   // 'C09OPSXYZ'
  blocks: [ HandoverReportBlock(handover_report) ],
  ts: '1716800540.000200'   // stored as slack_message_ts
}

// ACTION: Send Gmail to incoming manager and on-call contacts
Gmail.send -> {
  to: [ incoming_manager_email, ...oncall_emails ],
  subject: 'Handover Report: SHIFT-20240527-AM | Site 01',
  body: handover_report.report_markdown,
  message_id: 'msg_abc123'   // stored as gmail_message_id
}

// ACTION: Query Notion for existing page on shift_date, create if absent
Notion.databases.query -> { database_id: notion_database_id, filter: { Shift Date: '2024-05-27' } }
// No existing page found -> create new
Notion.pages.create -> {
  parent: { database_id: notion_database_id },
  properties: {
    'Shift Date': '2024-05-27',
    'Shift ID': 'SHIFT-20240527-AM',
    'Site': 'SITE-01',
    'Report Status': 'published'
  },
  children: [ ParagraphBlock(handover_report.report_markdown) ],
  page_id: 'notion_page_abc456'   // stored as notion_page_id
}

// ============================================================
// REMAINING HUMAN STEP (Step 8)
// Incoming lead reads Slack/email report and confirms receipt
// Estimated: 8 minutes. No automation required.
// ============================================================
Developer Handover PackPage 3 of 4
FS-DOC-04Technical

04Recommended build stack

Orchestration layer
A workflow automation platform with webhook and cron trigger support. Run one workflow per agent: 'Handover Collector' and 'Handover Compiler'. Both workflows share a single credential store holding all service tokens and config values. No credentials are hardcoded in workflow nodes.
Webhook configuration
The Collector Agent exposes a webhook endpoint to receive the shift-close signal from Google Sheets (via a Sheets Apps Script onEdit trigger or a form submission hook). The endpoint must be HTTPS with a shared-secret header (X-FullSpec-Secret) validated on every inbound request. Endpoint path convention: /handover/shift-close/{site_id}. The Compiler Agent is triggered internally by a polling check on the ShiftLog sheet's collector_status_cell every 60 seconds, not by an external webhook, to avoid race conditions.
Templating approach
All user-facing message content (Slack Block Kit payloads, Gmail subject and body, AI system prompt) is stored as named templates in the credential/config store. Templates reference field variables using double-brace notation (e.g. {{shift_id}}, {{site_id}}, {{missing_responses}}). The Compiler Agent's AI system prompt is versioned: version number and last-reviewed date are stored alongside the prompt string. No template content lives inside workflow node configuration.
Error logging
All workflow execution errors are written to a Supabase table named handover_error_log with columns: error_id (uuid), shift_id, agent_name, step_name, error_message, occurred_at (timestamptz), resolved (boolean). On any unhandled error, a Slack alert is posted to the internal FullSpec monitoring channel (#ops-automation-alerts) with the error_id and a link to the Supabase row. Errors are NOT silently swallowed; if a Notion page save fails, the workflow retries once after 30 seconds and logs on second failure.
Testing approach
All agents are built and tested against sandbox credentials first: a test Google Sheets log, a test Slack channel (#handover-qa), a test Notion database, and a PagerDuty test service. The sandbox mirrors the production schema exactly. No workflow node is pointed at production credentials until the pilot-week test cases (defined in the Test and QA Plan) have passed in sandbox. Pilot runs use real shift data with the Slack post redirected to #handover-qa until sign-off.
Handover Collector Agent build time
6 hours
Handover Compiler Agent build time
9 hours
End-to-end integration testing
3 hours (covering full flow, edge cases, and escalation path)
Estimated total build time
18 hours (matches confirmed build_effort_hours in project snapshot)
Before any build node is connected to a live tool, confirm the following with the process owner: (1) Google Sheets log column names are finalised and locked. (2) PagerDuty escalation threshold (any incident vs high-priority only) is agreed in writing. (3) Notion database properties exist with the exact names listed in this document. (4) The Gmail sending account and any domain aliases are confirmed. (5) The shift-end trigger method (cron vs Sheets flag) is decided based on whether the schedule is fixed or variable. Contact support@gofullspec.com if any of these items are unresolved at build start.
Developer Handover PackPage 4 of 4

More documents for this process

Every document generated for End-of-day / Shift Handover.

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