Developer Handover Pack
Everything needed to build the automation from scratch: current state, full agent specs, data flow, and the build stack.
Developer Handover Pack
Employee Offboarding Automation
[YourCompany.com] · HR Department · Prepared by FullSpec · [Today's Date]
This document is the complete technical reference for the Employee Offboarding automation. It covers the current-state process map, full agent specifications with IO contracts, the end-to-end data flow, and the recommended build stack. The FullSpec team owns all build, integration, and testing work described here. Your team's responsibility is to supply valid API credentials, confirm field mappings against live system data before testing begins, and sign off on each agent during the QA phase.
01Process snapshot
02Agent specifications
Handles all system access revocation the moment a departure is confirmed in BambooHR. Connects to Okta via the Users API to immediately suspend the employee's SSO session, revoking access to all downstream SaaS applications linked to Okta. Then calls the Google Workspace Admin SDK to disable the user account, set an automated out-of-office reply on the Gmail account, and transfer Google Drive ownership to the departing employee's line manager. All actions are logged to the automation platform's audit table. This agent produces a single structured confirmation payload that triggers the Task and Notification Agent. Complexity is Moderate because it spans two identity providers with different authentication models and requires a super-admin service account for Google Workspace.
// Input (from BambooHR webhook payload) employee_id: string // BambooHR internal employee ID full_name: string // employee display name email: string // work email address (primary identifier) last_working_day: date // ISO 8601 date, e.g. 2025-04-30 manager_email: string // line manager email for Drive transfer department: string // used to scope Jira project template employment_type: string // 'employee' | 'contractor' // Output (confirmation payload passed to Task and Notification Agent) okta_suspended: boolean // true if Okta account suspension confirmed okta_user_id: string // Okta user UID for audit log google_disabled: boolean // true if Workspace account disabled google_drive_transferred: boolean // true if Drive ownership moved auto_reply_set: boolean // true if Gmail out-of-office reply activated revocation_timestamp: datetime // UTC timestamp of completed revocation error_flags: string[] // list of any step-level errors encountered
- Okta API requires the token to have the okta.users.manage and okta.apps.manage scopes. Confirm the API token is generated from an Okta super-admin account, not a read-only service account. Standard Okta One App plan does not expose group management via API; confirm the org is on Okta Workforce Identity.
- Google Workspace Admin SDK Directory API calls for account disable and Drive transfer require a service account with domain-wide delegation enabled and the scopes https://www.googleapis.com/auth/admin.directory.user and https://www.googleapis.com/auth/drive set in the Google Admin console. A super-admin must authorise the service account before build begins.
- Dedupe behaviour: if the BambooHR webhook fires more than once for the same employee_id (duplicate webhook or retry), the agent must check Okta status before calling suspend. If already suspended, skip and log 'already_revoked' rather than returning an error.
- Fallback: if the Okta API call fails after two retries, the agent must post a high-priority alert to the designated HR Slack channel with the employee name, error code, and a direct link to the Okta admin panel. The workflow must not silently fail.
- Drive ownership transfer targets manager_email. If manager_email is null or the manager account is also inactive, transfer ownership to the HR Manager's Google account (configured as an environment variable HR_FALLBACK_EMAIL).
- The auto-reply message copy must be confirmed with the HR team before build. Store the template text as an environment variable OFFBOARD_AUTO_REPLY_BODY so it can be updated without a code change.
- Confirm before build: which BambooHR webhook event name is configured in the production instance ('Employee Status Changed' vs 'Custom Field Updated') and whether a webhook signing secret is enabled.
Triggered by the confirmed output of the Access Revocation Agent. Creates a structured Jira offboarding project board from a saved template, populating subtasks for equipment return, exit interview scheduling, and any outstanding manual items. Each subtask is assigned to the correct owner using department and manager data from the BambooHR payload. Sends a structured payroll notification to Xero via the Xero Accounting API, including the final working day and leave balance pulled from BambooHR. Dispatches the exit survey to the employee's personal email address via Google Workspace on the penultimate working day. Posts a completion summary to the HR Slack channel once all automated steps are confirmed. Closes the BambooHR record to 'offboarded' status after the Jira equipment return task is marked complete by the manager. Complexity is Moderate due to the number of tool integrations and the conditional logic around equipment return gating the final record closure.
// Input (from Access Revocation Agent output payload)
employee_id: string
full_name: string
email: string // work email
personal_email: string // for exit survey dispatch
last_working_day: date
manager_email: string
department: string
leave_balance_hours: number // pulled from BambooHR Time Off API
okta_suspended: boolean
google_disabled: boolean
revocation_timestamp: datetime
// Output (per action, aggregated into Slack summary payload)
jira_board_url: string // URL of the created Jira project
jira_equipment_task_id: string // Jira issue key for equipment return subtask
xero_notification_sent: boolean // true if payroll notification delivered
exit_survey_sent: boolean // true if survey email dispatched
exit_survey_send_date: date // penultimate working day date
slack_summary_posted: boolean
bamboohr_record_closed: boolean // set after Jira equipment task completed
bamboohr_close_timestamp: datetime
error_flags: string[]
// On approval (equipment return gate)
// Manager marks jira_equipment_task_id as Done in Jira
// Jira webhook fires to the automation platform
// Agent calls BambooHR PATCH /v1/employees/{employee_id}
// with status: 'offboarded' and offboard_date: today()- Jira board creation requires the Jira Software or Jira Work Management plan with API token authentication (Basic Auth with email and API token, or OAuth 2.0 three-legged for user-context actions). A Jira project template named 'HR-OFFBOARD-TEMPLATE' must exist in the target workspace before build. Confirm the template project key with the IT Admin.
- Xero integration uses the Xero Accounting API. The payroll notification is a structured note or invoice memo, not a direct payroll run. Confirm whether the Xero org has Payroll (AU/NZ/UK) or Accounting-only enabled, as the available API endpoints differ. The finance lead must validate the leave_balance_hours field mapping against Xero's own records before the first live run.
- Exit survey email must be sent to personal_email, not the work email which will have an auto-reply set. personal_email must be a confirmed field in BambooHR. If the field is empty, the step logs a warning and posts an alert to the HR Slack channel rather than failing the entire run.
- Exit survey send timing: calculate penultimate_working_day as last_working_day minus one business day. The automation must exclude weekends and public holidays. Configure a public holiday calendar for the relevant jurisdiction as an environment variable JURISDICTION_HOLIDAY_CALENDAR before build.
- Slack summary uses an Incoming Webhook URL stored as environment variable SLACK_HR_WEBHOOK. The summary message must list each completed task with a timestamp and flag any items still awaiting human action (equipment return, exit interview) with an amber indicator.
- BambooHR record closure (PATCH status to 'offboarded') is gated on the Jira equipment return task reaching 'Done' status. The Jira webhook that fires this must be scoped to only the 'HR-OFFBOARD' project to avoid false triggers from other Jira activity.
- Dedupe: if the Jira project for a given employee_id already exists (re-run scenario), the agent must skip project creation, log 'board_already_exists', and proceed to check task status rather than creating duplicate boards.
- Confirm before build: personal_email field name in BambooHR API response, the exact Jira project template key, whether Xero is on Payroll or Accounting plan, and the Slack channel name for HR summaries.
03End-to-end data flow
// ================================================================
// EMPLOYEE OFFBOARDING: END-TO-END DATA FLOW
// ================================================================
// TRIGGER
// BambooHR fires webhook on employee status change or last_working_day set
BambooHR.webhook.event = 'employeeStatusChanged' | 'lastWorkingDaySet'
payload.employee_id -> string // e.g. '4821'
payload.full_name -> string // e.g. 'Jane Smith'
payload.email -> string // e.g. 'jane.smith@yourcompany.com'
payload.personal_email -> string // e.g. 'jane.smith@gmail.com'
payload.last_working_day -> date // e.g. '2025-04-30'
payload.manager_email -> string // e.g. 'mark.jones@yourcompany.com'
payload.department -> string // e.g. 'Sales'
payload.employment_type -> string // e.g. 'employee'
// SUPPLEMENTAL FETCH (before agent 1 executes)
BambooHR.GET /v1/employees/{employee_id}/timeOff/calculator
-> leave_balance_hours: number // e.g. 24.5
// ================================================================
// AGENT HANDOFF 1: TRIGGER -> ACCESS REVOCATION AGENT
// ================================================================
// STEP 1: Suspend Okta SSO session
Okta.POST /api/v1/users/{okta_user_id}/lifecycle/suspend
match by: email == Okta.profile.login
-> okta_user_id: string // e.g. '00u1abc2defGHIJK'
-> okta_suspended: boolean // true on HTTP 200
// STEP 2: Disable Google Workspace account
GoogleAdmin.PATCH /admin/directory/v1/users/{userKey}
userKey: email
body: { suspended: true }
-> google_disabled: boolean // true on HTTP 200
// STEP 3: Transfer Google Drive ownership to manager
GoogleAdmin.POST /drive/v3/files/{fileId}/permissions
transferOwnership: true
newOwner: manager_email
-> google_drive_transferred: boolean
// STEP 4: Set Gmail auto-reply
Gmail.PUT /gmail/v1/users/{userId}/settings/vacation
body: {
enableAutoReply: true,
responseSubject: 'Out of Office',
responseBodyHtml: env.OFFBOARD_AUTO_REPLY_BODY
}
-> auto_reply_set: boolean
// STEP 5: Write revocation log entry
AuditLog.INSERT {
employee_id, okta_user_id, okta_suspended,
google_disabled, google_drive_transferred,
auto_reply_set, revocation_timestamp: now()
}
// Access Revocation Agent output confirmation payload assembled
agent1.output = {
employee_id, full_name, email, personal_email,
last_working_day, manager_email, department,
leave_balance_hours,
okta_suspended, okta_user_id,
google_disabled, google_drive_transferred, auto_reply_set,
revocation_timestamp,
error_flags: []
}
// ================================================================
// AGENT HANDOFF 2: ACCESS REVOCATION AGENT -> TASK & NOTIFICATION AGENT
// Condition: agent1.output.okta_suspended == true
// AND agent1.output.google_disabled == true
// On failure: retry every 5 min up to 30 min, then Slack alert
// ================================================================
// STEP 6: Create Jira offboarding board from template
Jira.POST /rest/api/3/project
templateKey: 'HR-OFFBOARD-TEMPLATE'
projectName: 'Offboarding - {full_name} - {last_working_day}'
-> jira_board_url: string
-> jira_project_key: string // e.g. 'OFF-142'
// STEP 7: Create equipment return subtask
Jira.POST /rest/api/3/issue
projectKey: jira_project_key
issuetype: 'Task'
summary: 'Equipment return - {full_name}'
assignee: manager_email
dueDate: last_working_day
-> jira_equipment_task_id: string // e.g. 'OFF-142-3'
// STEP 8: Send payroll notification to Xero
Xero.POST /api.xro/2.0/ManualJournals (Accounting) OR
Xero.POST /payroll.xro/1.0/Employees/{employeeId}/LeaveApplications (Payroll)
body: {
employee_id: xero_employee_id, // matched by email
final_working_day: last_working_day,
leave_balance_hours: leave_balance_hours,
notification_note: 'Offboarding triggered - final pay action required'
}
-> xero_notification_sent: boolean
// STEP 9: Dispatch exit survey email
// send_date = last_working_day - 1 business day (excl. env.JURISDICTION_HOLIDAY_CALENDAR)
Gmail.POST /gmail/v1/users/me/messages/send
to: personal_email
subject: 'We would love your feedback'
body: env.EXIT_SURVEY_BODY_TEMPLATE
scheduled_send_time: exit_survey_send_date
-> exit_survey_sent: boolean
-> exit_survey_send_date: date
// STEP 10: Post Slack summary to HR channel
Slack.POST env.SLACK_HR_WEBHOOK
payload: {
text: 'Offboarding complete for {full_name} ({last_working_day})',
blocks: [
{ okta_suspended, google_disabled, xero_notification_sent,
exit_survey_sent, jira_board_url },
{ pending: ['Equipment return (manager action in Jira)',
'Exit interview (HR action)'] }
]
}
-> slack_summary_posted: boolean
// ================================================================
// AGENT HANDOFF 3: EQUIPMENT RETURN GATE (human in loop)
// Manager marks jira_equipment_task_id Done in Jira
// Jira webhook fires to automation platform endpoint /webhooks/jira-equipment-done
// Condition: issue.key == jira_equipment_task_id AND status == 'Done'
// ================================================================
// STEP 11: Close BambooHR record
BambooHR.PATCH /v1/employees/{employee_id}
body: {
status: 'offboarded',
offboard_date: today() // ISO 8601
}
-> bamboohr_record_closed: boolean
-> bamboohr_close_timestamp: datetime
// STEP 12: Write final audit log entry
AuditLog.UPDATE {
employee_id,
bamboohr_record_closed, bamboohr_close_timestamp,
all_steps_complete: true
}
// ================================================================
// END OF FLOW
// ================================================================04Recommended build stack
More documents for this process
Every document generated for Employee Offboarding.