Back to Training & Certification Tracking

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

Training & Certification Tracking

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

This document gives the FullSpec build team everything needed to configure, connect, and test the Training and Certification Tracking automation from scratch. It covers the current manual process and its bottlenecks, full specifications for both agents, the end-to-end data flow with exact field names, and the recommended build stack with estimated hours. The process owner's responsibilities are limited to confirming access credentials and approving go-live; FullSpec handles every build, integration, and test step.

01Process snapshot

Step
Name
Description
1
Pull Weekly Expiry Report
HR opens the master certification spreadsheet and manually filters rows to find certifications expiring in the next 90 days. Prone to filter errors and missed rows. Time cost: 20 min/cycle.
2
Cross-Check Employee Records in HRIS
HR checks BambooHR to confirm the employee is still active and to retrieve the correct manager and contact details before sending reminders. Time cost: 15 min/cycle.
3
Draft and Send Renewal Reminder Emails
BOTTLENECK. HR composes individual reminder emails to each employee and their manager, noting certification name and expiry date. Each email is written or edited manually. Time cost: 40 min/cycle.
4
Log Reminder Sent in Spreadsheet
After sending each email, HR updates the spreadsheet to note the date and type of reminder sent so follow-ups can be tracked. Time cost: 10 min/cycle.
5
Chase Non-Responders
BOTTLENECK. If no renewal confirmation is received within two weeks, HR sends a follow-up and notifies the employee's manager via Slack. Relies entirely on memory. Time cost: 25 min/cycle.
6
Receive and Review Completion Evidence
Employees email their completed certificate. HR reviews the document to confirm it covers the correct certification and period. Time cost: 15 min/cycle.
7
File Certificate in Google Drive
HR downloads the certificate and uploads it to the correct folder in Google Drive, renaming the file to match the naming convention. Time cost: 10 min/cycle.
8
Update HRIS With New Expiry Date
HR manually enters the new certification completion date and updated expiry date into BambooHR on the employee profile. Time cost: 10 min/cycle.
9
Update Master Spreadsheet
The Google Sheets tracking log is updated to reflect the new status, completion date, and next due date. Time cost: 8 min/cycle.
10
Produce Compliance Status Report
BOTTLENECK. Before audits or leadership reviews, HR manually compiles a summary of current certification status across all employees from the spreadsheet. Time cost: 30 min/cycle.
Time cost summary: Total manual time per cycle is 183 minutes (approximately 3 hours per full pass). At 5 hours of HR Coordinator time lost per week, the annualised cost is $10,400/year at $40/hour. Steps 1, 2, 3, 4 and 5 (scanning, cross-checking, drafting reminders, logging, and chasing) are replaced by the Certification Monitor Agent. Steps 6, 7, 8 and 9 (receipt, filing, HRIS update, and sheet update) are replaced by the Renewal Intake and Filing Agent. Step 5 partial escalation handling and Step 10 report sign-off remain human-in-the-loop tasks.
Developer Handover PackPage 1 of 4
FS-DOC-04Technical

02Agent specifications

Certification Monitor Agent

Runs on a daily schedule to scan all active employee certification records, classify each record into the correct reminder tier (90-day, 60-day, 30-day, or overdue), and prepare and dispatch personalised reminder payloads. It handles the branching logic for which employees need which message, fires Gmail reminder emails and Slack manager notifications, writes a timestamped log entry to Google Sheets for every action taken, and flags overdue records for priority escalation. This agent replaces the manual spreadsheet scan, HRIS cross-check, email drafting, and log-update steps that consume the bulk of the HR Coordinator's weekly time.

Trigger
Scheduled daily run at a configured time (recommended: 07:00 local business time). Fires regardless of whether any records are due, and exits cleanly when no qualifying records are found.
Tools
BambooHR (employee record read), Google Sheets (certification log read and write), Gmail (reminder email send), Slack (manager direct message)
Replaces steps
Step 1 (Pull Weekly Expiry Report), Step 2 (Cross-Check Employee Records in HRIS), Step 4 (Log Reminder Sent in Spreadsheet). Also automates the reminder send that was step 3 and the non-responder chase logic that was step 5.
Estimated build
14 hours / Moderate complexity
// Input
BambooHR.employees[] -> filter: status == 'Active'
  -> fields: employee_id, full_name, email, manager_id, manager_email, manager_slack_id
Google Sheets[CertificationLog] -> rows where cert_expiry_date <= today + 90 days
  -> fields: employee_id, cert_type, cert_name, cert_expiry_date, last_reminder_tier, last_reminder_date, status

// Classification logic
days_until_expiry = cert_expiry_date - today
if days_until_expiry <= 0            -> tier = 'OVERDUE'
if days_until_expiry <= 30           -> tier = 'TIER_30'
if days_until_expiry <= 60           -> tier = 'TIER_60'
if days_until_expiry <= 90           -> tier = 'TIER_90'
skip record if last_reminder_tier == tier AND last_reminder_date >= today - 6 days

// Output (per qualifying record)
Gmail.send -> { to: employee_email, template: reminder_[tier].html,
  vars: { full_name, cert_name, cert_expiry_date, typeform_submission_url } }
Slack.postMessage -> { channel: manager_slack_id,
  text: '[employee full_name] cert [cert_name] is [tier] — expires [cert_expiry_date]' }
Google Sheets[CertificationLog].update -> { row: employee_id + cert_type,
  fields: { last_reminder_tier: tier, last_reminder_date: today,
            status: tier == 'OVERDUE' ? 'Escalation Required' : 'Reminder Sent' } }
  • BambooHR API tier: The BambooHR API is available on all paid plans. Confirm that the account has API key access enabled under Settings > API Keys before build begins. The integration must use the v1 REST API (https://api.bamboohr.com/api/gateway.php/{companyDomain}/v1/).
  • Custom fields: BambooHR may not have cert_type, cert_name, cert_expiry_date, or last_reminder_tier as standard fields. These must be created as custom employee fields in BambooHR admin before the agent can read or write them. Confirm field names and slugs with the process owner at the start of Week 1.
  • Google Sheets structure: The CertificationLog sheet must have stable, named column headers. The agent references columns by header name, not index. If the existing sheet does not match the expected schema, a data migration or header rename is required before build.
  • Reminder deduplication: The agent must check last_reminder_tier and last_reminder_date before sending. A record that already received a TIER_30 reminder within the last 6 days must be skipped to prevent duplicate sends. This logic is critical and must be tested explicitly.
  • Gmail send identity: Confirm whether reminders should be sent from a shared HR inbox (e.g. hr@[YourCompany.com]) or an individual address. OAuth must be configured for the correct sending account. A Gmail alias or Google Workspace shared mailbox both work but require different OAuth setup.
  • Slack manager mapping: The agent requires a Slack user ID for each manager, not just an email. The Google Sheets log or BambooHR custom field must store manager_slack_id, or the agent must perform a Slack users.lookupByEmail call at runtime using the manager's BambooHR email. Confirm the lookup approach before build.
  • Escalation flag behaviour: When tier is OVERDUE, the agent updates the status field to 'Escalation Required' and sends the Slack notification but does NOT send a further reminder email. The HR Coordinator receives the Slack alert and handles the conversation directly. This must not be changed without explicit sign-off.
Renewal Intake and Filing Agent

Monitors incoming Typeform submissions for certificate uploads and processes each submission end-to-end without human involvement. On receipt of a valid submission, the agent validates that all required fields are present and the file upload is non-empty, constructs a standardised file name, files the certificate to the correct named folder in Google Drive, writes the new completion and expiry dates back to BambooHR on the employee's profile, and marks the certification record as complete in the Google Sheets log. If validation fails, the agent logs the error and sends an alert to the HR Coordinator via Slack. This agent replaces four consecutive manual steps that together consumed over 40 minutes per certificate received.

Trigger
Typeform webhook fires on each new form submission (event: form_response). The automation platform receives the webhook payload at a registered HTTPS endpoint and begins processing immediately.
Tools
Typeform (webhook source), Google Drive (file upload and folder routing), BambooHR (employee profile write), Google Sheets (certification log write), Slack (error alert on validation failure)
Replaces steps
Step 6 (Receive and Review Completion Evidence), Step 7 (File Certificate in Google Drive), Step 8 (Update HRIS With New Expiry Date), Step 9 (Update Master Spreadsheet)
Estimated build
10 hours / Moderate complexity
// Input (Typeform webhook payload)
Typeform.form_response -> {
  answers: {
    employee_id:        string,   // hidden field pre-populated from Typeform link
    cert_type:          string,   // dropdown: mapped to BambooHR cert type values
    cert_name:          string,   // free text or dropdown
    completion_date:    date,     // format: YYYY-MM-DD
    new_expiry_date:    date,     // format: YYYY-MM-DD
    certificate_file:   file_url  // Typeform-hosted temporary download URL (expires 1 hour)
  },
  submitted_at: ISO8601 timestamp
}

// Validation checks (abort and alert if any fail)
assert employee_id is not null
assert cert_type is not null
assert completion_date is valid date
assert new_expiry_date > today
assert certificate_file URL returns HTTP 200 and Content-Type in ['application/pdf','image/jpeg','image/png']

// File naming convention
file_name = '{employee_id}_{cert_type}_{new_expiry_date}.{extension}'
// Example: EMP042_FirstAid_2026-05-15.pdf

// Output
Google Drive.upload -> {
  folder_path: '/HR/Certifications/{cert_type}/{employee_id}/',
  file_name: file_name,
  source_url: certificate_file
}
BambooHR.employee[employee_id].customFields.update -> {
  cert_completion_date: completion_date,
  cert_expiry_date:     new_expiry_date,
  cert_status:          'Current'
}
Google Sheets[CertificationLog].update -> {
  row: employee_id + cert_type,
  fields: {
    status:           'Complete',
    completion_date:  completion_date,
    new_expiry_date:  new_expiry_date,
    drive_file_url:   Google Drive file URL,
    last_updated:     submitted_at
  }
}

// On validation failure
Slack.postMessage -> { channel: HR_COORDINATOR_SLACK_ID,
  text: 'Typeform submission failed validation for employee_id [employee_id]: [error reason]. Manual review required.' }
  • Typeform tier: Webhook delivery requires Typeform Basic plan or higher. Confirm the account tier before build. The webhook endpoint must be registered in the Typeform admin under Connect > Webhooks with the automation platform's HTTPS listener URL.
  • Typeform hidden fields: The employee_id field must be passed as a hidden field in the Typeform URL so submissions are pre-attributed to the correct employee without requiring manual entry. The Certification Monitor Agent must append ?employee_id={employee_id} to the typeform_submission_url it includes in each reminder email.
  • Typeform file upload URL expiry: Typeform-hosted file URLs expire approximately one hour after submission. The agent must download and upload the file to Google Drive within that window. If the workflow queue is delayed, the file fetch will fail. Build a retry with a maximum of 3 attempts at 5-minute intervals; if all attempts fail, alert the HR Coordinator via Slack.
  • Google Drive folder structure: The target folder path /HR/Certifications/{cert_type}/{employee_id}/ must exist before the agent attempts to write to it. Build a folder-creation step that checks for the path and creates missing folders programmatically on first encounter.
  • BambooHR write-back field slugs: The exact custom field slugs for cert_completion_date, cert_expiry_date, and cert_status must be confirmed from the BambooHR admin panel before the write step is coded. Slugs are case-sensitive and cannot be inferred from display names.
  • Duplicate submission handling: If a second Typeform submission arrives for the same employee_id and cert_type within 24 hours, the agent must overwrite the existing Google Sheets row rather than appending a new row, and must update the BambooHR record to the latest values. Log both submissions to a separate audit sheet.
  • Error alerting recipient: The Slack alert on validation failure must go to HR_COORDINATOR_SLACK_ID, which should be stored as an environment variable in the automation platform's credential store, not hardcoded in the workflow.
Combined estimated build time across both agents: 14 hours (Certification Monitor Agent) + 10 hours (Renewal Intake and Filing Agent) = 24 hours of agent build. Add 4 hours for end-to-end integration testing and QA, bringing total build effort to 28 hours, consistent with the confirmed build effort in the project snapshot.
Developer Handover PackPage 2 of 4
FS-DOC-04Technical

03End-to-end data flow

Full trigger-to-output data flow for both agents. Field names match the Google Sheets column headers and BambooHR custom field slugs to be confirmed in Week 1.
// ============================================================
// TRAINING & CERTIFICATION TRACKING: END-TO-END DATA FLOW
// ============================================================

// TRIGGER: Scheduled daily run (07:00 local time)
// ============================================================
SCHEDULER.fire -> timestamp: today_date

// --- AGENT HANDOFF 1: Certification Monitor Agent begins ---

// STEP 1: Pull active employees from BambooHR
BambooHR.GET /employees?fields=id,firstName,lastName,workEmail,supervisorId
  -> employees[]: { employee_id, full_name, email, manager_id }

// STEP 2: Resolve manager contact details
BambooHR.GET /employees/{manager_id}?fields=workEmail
  -> manager_email: string
Slack.GET users.lookupByEmail?email={manager_email}
  -> manager_slack_id: string

// STEP 3: Read certification records from Google Sheets
Google Sheets[CertificationLog].GET rows
  -> filter: cert_expiry_date <= today + 90 days AND status != 'Complete'
  -> fields per row: {
       employee_id, cert_type, cert_name,
       cert_expiry_date,         // format: YYYY-MM-DD
       last_reminder_tier,       // TIER_90 | TIER_60 | TIER_30 | OVERDUE | null
       last_reminder_date,       // format: YYYY-MM-DD or null
       status                    // Pending | Reminder Sent | Escalation Required | Complete
     }

// STEP 4: Classify each record
FOR each record in filtered_rows:
  days_until_expiry = cert_expiry_date - today
  tier = classify(days_until_expiry)
    // classify: <= 0 -> OVERDUE; <= 30 -> TIER_30; <= 60 -> TIER_60; <= 90 -> TIER_90
  skip IF last_reminder_tier == tier AND last_reminder_date >= today - 6 days

// STEP 5: Send Gmail reminder (non-OVERDUE records only)
Gmail.send -> {
  to:       record.email,
  subject:  '[Action Required] {cert_name} renewal due in {days_until_expiry} days',
  template: reminder_{tier}.html,
  vars: {
    full_name:              record.full_name,
    cert_name:              record.cert_name,
    cert_expiry_date:       record.cert_expiry_date,
    typeform_submission_url: TYPEFORM_BASE_URL + '?employee_id=' + record.employee_id
  }
}

// STEP 6: Notify manager via Slack (all tiers including OVERDUE)
Slack.postMessage -> {
  channel: manager_slack_id,
  text:    '{full_name} | {cert_name} | Status: {tier} | Expiry: {cert_expiry_date}',
  blocks:  [ summary_card with action button: 'View Record' ]
}

// STEP 7: Write log entry to Google Sheets
Google Sheets[CertificationLog].UPDATE row matching employee_id + cert_type -> {
  last_reminder_tier:  tier,
  last_reminder_date:  today,
  status:              tier == 'OVERDUE' ? 'Escalation Required' : 'Reminder Sent'
}

// --- Certification Monitor Agent complete for this cycle ---

// ============================================================
// PARALLEL PATH: Typeform submission received (event-driven)
// ============================================================

// TRIGGER: Typeform webhook POST to automation platform endpoint
Typeform.webhook.POST -> /webhook/cert-intake
  -> payload: {
       form_id:          string,
       submitted_at:     ISO8601,
       answers: {
         employee_id:       string,
         cert_type:         string,
         cert_name:         string,
         completion_date:   YYYY-MM-DD,
         new_expiry_date:   YYYY-MM-DD,
         certificate_file:  url  // Typeform CDN, expires ~1 hour
       }
     }

// --- AGENT HANDOFF 2: Renewal Intake and Filing Agent begins ---

// STEP 8: Validate payload
ASSERT employee_id != null
ASSERT cert_type    != null
ASSERT completion_date is valid ISO date
ASSERT new_expiry_date > today
ASSERT HTTP.GET(certificate_file).status == 200
ASSERT Content-Type IN ['application/pdf','image/jpeg','image/png']
ON FAILURE -> Slack.alert(HR_COORDINATOR_SLACK_ID, reason) -> EXIT

// STEP 9: Download certificate file
file_bytes  = HTTP.GET(certificate_file)  // attempt within 5 min of submission
extension   = derive_extension(Content-Type)
file_name   = '{employee_id}_{cert_type}_{new_expiry_date}.{extension}'
  // Example: EMP042_FirstAid_2026-05-15.pdf

// STEP 10: Upload to Google Drive
Google Drive.ensureFolder('/HR/Certifications/{cert_type}/{employee_id}/')
Google Drive.upload -> {
  folder_path: '/HR/Certifications/{cert_type}/{employee_id}/',
  file_name:   file_name,
  content:     file_bytes
}
  -> drive_file_id:  string
  -> drive_file_url: string

// STEP 11: Write back to BambooHR employee profile
BambooHR.POST /employees/{employee_id}/customTabFields -> {
  customField_cert_completion_date: completion_date,
  customField_cert_expiry_date:     new_expiry_date,
  customField_cert_status:          'Current'
}

// STEP 12: Update Google Sheets log
Google Sheets[CertificationLog].UPDATE row matching employee_id + cert_type -> {
  status:           'Complete',
  completion_date:  completion_date,
  new_expiry_date:  new_expiry_date,
  drive_file_url:   drive_file_url,
  last_updated:     submitted_at
}

// --- Renewal Intake and Filing Agent complete ---

// ============================================================
// HUMAN STEP: Escalation review (OVERDUE records only)
// HR Coordinator reviews Slack alert and contacts employee directly
// No automation action; HR updates status manually in Google Sheets
// ============================================================
Developer Handover PackPage 3 of 4
FS-DOC-04Technical

04Recommended build stack

Orchestration layer
A workflow automation tool (platform to be confirmed at project kick-off). One workflow per agent: 'cert-monitor-daily' for the Certification Monitor Agent and 'cert-intake-filing' for the Renewal Intake and Filing Agent. Both workflows share a single credential store for all service connections. No cross-workflow calls; each workflow is fully self-contained with its own error handling.
Credential store entries
BAMBOOHR_API_KEY, BAMBOOHR_COMPANY_DOMAIN, GOOGLE_OAUTH_TOKEN (scopes: sheets.readwrite, drive.file, gmail.send), SLACK_BOT_TOKEN (scopes: chat:write, users:read.email), TYPEFORM_WEBHOOK_SECRET, HR_COORDINATOR_SLACK_ID, TYPEFORM_BASE_URL. All credentials stored as environment variables, never hardcoded in workflow nodes.
Webhook configuration
The automation platform exposes an HTTPS POST endpoint for the Renewal Intake and Filing Agent. Register this URL in the Typeform admin under Connect > Webhooks. Enable webhook signature verification using TYPEFORM_WEBHOOK_SECRET (SHA-256 HMAC header: Typeform-Signature). The Certification Monitor Agent uses a cron-based internal scheduler, not a webhook.
Templating approach
Gmail reminder emails are built from HTML templates stored within the workflow (one per tier: reminder_TIER_90.html, reminder_TIER_60.html, reminder_TIER_30.html, reminder_OVERDUE_manager.html). Templates use mustache-style variable substitution: {{full_name}}, {{cert_name}}, {{cert_expiry_date}}, {{typeform_submission_url}}. Templates must be reviewed and approved by the process owner before go-live. Slack messages use Block Kit JSON for structured card layout.
Error logging
All agent errors (validation failures, API call failures, file fetch timeouts, BambooHR write errors) are written to a dedicated error log table (Supabase table: cert_automation_errors, columns: id, timestamp, agent_name, employee_id, cert_type, error_code, error_message, resolved). A Slack alert to HR_COORDINATOR_SLACK_ID fires on every error entry. FullSpec reviews the error log during the first two weeks post-launch as part of the hypercare period.
Testing approach
All integrations are tested in sandbox mode first: BambooHR sandbox account (separate company domain), a dedicated Typeform test form, a sandboxed Google Sheets tab (CertificationLog_TEST), and a separate Google Drive test folder (/HR/Certifications/_TEST/). Gmail sends during testing go to an internal FullSpec test inbox only. Slack notifications during testing use a private #cert-automation-test channel. No production data is touched until end-to-end QA passes all test cases in the Test and QA Plan.
Estimated total build time
Certification Monitor Agent: 14 hours. Renewal Intake and Filing Agent: 10 hours. End-to-end integration testing and QA: 4 hours. Total: 28 hours across a 4-week delivery schedule (Week 1: discovery and data audit; Week 2: Certification Monitor Agent build; Week 3: Renewal Intake and Filing Agent build; Week 4: testing and QA).
Before any build work begins, the following must be confirmed with the process owner: (1) BambooHR custom field names and slugs for certification data; (2) the Google Sheets CertificationLog column schema and whether a data clean is required; (3) the Gmail sending identity (shared inbox vs individual address) and OAuth consent; (4) the Slack workspace ID and confirmation that the bot has been added to the relevant channels; (5) Typeform account tier and whether the existing form can be modified or a new form must be built. FullSpec will run a credential and access check in Week 1 before any workflow nodes are connected.
Developer Handover PackPage 4 of 4

More documents for this process

Every document generated for Training & Certification Tracking.

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