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
Exit Interview & Knowledge Capture
[YourCompany.com] · Management Department · Prepared by FullSpec · [Today's Date]
This document gives the FullSpec build team everything required to construct, configure, and connect the Exit Interview and Knowledge Capture automation from first trigger to final Slack alert. It covers the current-state step map, full agent specifications with IO contracts, the end-to-end data flow trace, and the recommended build stack. The process owner's responsibilities are limited to reviewing AI-generated summaries and confirming the Typeform question set before go-live. Every other step described here is handled by FullSpec.
01Process snapshot
02Agent specifications
Monitors BambooHR for confirmed departures by listening to the employee status-change webhook. On detecting a status transition to 'Leaving' or equivalent, it retrieves the employee record, selects the appropriate Typeform form variant based on role type, generates a personalised share link, and sends it to the employee via email. Simultaneously it duplicates the Notion knowledge transfer template into the employee's named page, pre-fills name, role, and responsibility areas, and shares the page with both the departing employee and their line manager. If the Typeform has not been submitted 48 hours before the confirmed last day, the agent fires a reminder email. If submission is still absent at the deadline, it raises a fallback manual flag to the HR Manager via Slack rather than silently failing. The agent logs every action with a timestamp to a Supabase events table.
// Input
bamboohr.webhook.payload {
employee_id: string, // BambooHR numeric employee ID
employee_name: string, // Full display name
employee_email: string, // Work or personal email from record
department: string, // Used for Typeform variant selection
job_title: string, // Written into Notion template header
manager_email: string, // Receives Notion share and fallback alerts
last_day_date: date (ISO8601) // Drives reminder and deadline logic
status_new: string // e.g. 'Leaving', 'Terminated'
}
// Output
typeform.response {
form_id: string, // Selected variant ID
respondent_email: string,
share_url: string, // Personalised prefilled link
sent_at: timestamp
}
notion.page {
page_id: string, // Newly duplicated page ID
page_url: string,
employee_id: string, // Written to page property for lookup
created_at: timestamp
}
supabase.exit_events {
event_type: 'intake_triggered' | 'reminder_sent' | 'fallback_raised',
employee_id: string,
timestamp: timestamp
}- BambooHR must be on a tier that exposes outbound webhooks. Confirm webhook availability before build starts. The webhook URL must be registered in BambooHR Settings > Integrations > Webhooks, scoped to the 'Employment Status' event type.
- Typeform must be on the Basic plan or above to enable the API-generated prefilled links and programmatic form variant selection. Confirm the account tier before build.
- Three Typeform form variants should be created before agent wiring: one for operations/admin roles, one for client-facing/sales roles, and one for technical roles. The agent selects the variant by matching the BambooHR 'department' field value against a lookup table stored in the automation platform's credential/config store.
- Notion integration must use an internal integration token with 'Insert content' and 'Read content' permissions on the HR workspace. The knowledge transfer master template page ID must be stored as a named config variable (NOTION_TEMPLATE_PAGE_ID). Template duplication uses the Notion 'Duplicate page' API endpoint.
- Notion page pre-fill must write employee_name, job_title, last_day_date, and manager_email into designated page properties before sharing. Do not share the page until all properties are written.
- Reminder timing: schedule a reminder email 48 hours before last_day_date. If no Typeform submission is received by 24 hours before last_day_date, fire the Slack fallback alert to the HR Manager channel (channel name to be confirmed by process owner before build). Do not retry indefinitely.
- All Supabase log writes are non-blocking. A failed log write must not halt the main sequence. Wrap in a try/catch and surface errors to the error-logging alert only.
Triggered by a Typeform webhook on form submission. The agent retrieves the full response payload, maps each answer to a structured schema (role knowledge, client relationships, process risks, suggested handoffs), and passes the structured data to an AI summarisation step using a system-level prompt that enforces plain-English output, consistent section headers, and a professional tone suitable for an HR record. It then scores knowledge transfer completeness by checking whether key sections of the Notion knowledge transfer page have been populated (using the Notion API to read block content). Sections below a completeness threshold are flagged as gaps. The agent generates a formatted PDF exit summary, saves both the PDF and the raw Typeform response JSON to the designated Google Drive HR folder, writes the summary text and Notion page URL back to the employee's BambooHR record via the BambooHR API, and posts a Slack message to the line manager's channel listing any flagged gaps. Every step is logged to the Supabase events table.
// Input
typeform.webhook.payload {
form_id: string,
response_id: string,
submitted_at: timestamp,
hidden_fields: {
employee_id: string, // Passed via prefilled link hidden field
notion_page_id: string, // Passed via prefilled link hidden field
manager_email: string // Passed via prefilled link hidden field
},
answers: [ // Array of question/answer pairs
{ field_id: string, type: string, value: string | string[] }
]
}
// Output
ai_summary {
sections: {
role_knowledge: string,
client_relationships: string,
process_risks: string,
suggested_handoffs: string
},
gap_flags: [ // Array of flagged incomplete areas
{ section: string, severity: 'high' | 'medium', note: string }
],
completeness_score: number // 0-100, derived from Notion page check
}
google_drive.file {
pdf_file_id: string, // Uploaded PDF summary
json_file_id: string, // Raw Typeform response archive
folder_id: string // Configured HR exits folder
}
bamboohr.custom_field_update {
employee_id: string,
exit_summary_text: string,
notion_page_url: string,
google_drive_pdf_url: string
}
slack.message {
channel: string, // Manager's designated channel
blocks: [ // Formatted gap-alert block kit message
{ type: 'section', text: string },
{ type: 'divider' },
{ type: 'section', fields: gap_flags[] }
]
}
// On approval (manager review)
// No automated output. Manager reviews the AI summary in Google Drive
// and decides independently whether a live conversation is required.
// If gaps are critical, the Slack alert includes a 'Schedule call' action
// button that opens the manager's calendar link (pre-configured).- The AI summarisation step must use a structured system prompt that enforces exactly four output sections: Role Knowledge, Client Relationships, Process Risks, and Suggested Handoffs. The prompt must explicitly instruct the model to use plain English, avoid jargon, and write in third person (e.g. 'The departing employee noted...'). Store the system prompt as a named config variable (AI_SUMMARY_SYSTEM_PROMPT) so it can be updated without a code change.
- Knowledge gap detection: after summarisation, query the Notion page blocks via the Notion API. Count populated blocks against expected sections. If any section has fewer than 50 words of content, flag it as a gap. The 50-word threshold should be a named config variable (NOTION_GAP_THRESHOLD_WORDS) to allow tuning.
- Google Drive: the destination folder ID must be stored as a named config variable (GDRIVE_HR_EXITS_FOLDER_ID). The PDF is generated from the AI summary using the automation platform's PDF render step or an HTTP call to a PDF generation service. File naming convention: EXIT_SUMMARY_{employee_id}_{YYYY-MM-DD}.pdf.
- BambooHR write-back uses the BambooHR v1 API PUT /v1/employees/{id}. Confirm which custom fields are available on the client's BambooHR account for exit_summary_text and notion_page_url before build. If custom fields do not exist, they must be created in BambooHR Settings > Custom Fields before wiring.
- Slack alert: only fire if gap_flags array contains at least one 'high' severity item. Medium-severity gaps are included in the Slack message body but do not trigger the alert independently. Confirm the target Slack channel name with the process owner before build (default assumption: #people-ops).
- The fallback for a non-submitted Typeform (handled by Exit Intake Agent) must be documented in the Supabase log so the Knowledge Synthesis Agent does not attempt to run on a null payload. Add a guard check at the start of the Knowledge Synthesis Agent: if no valid response_id is present in the trigger payload, abort and log 'synthesis_skipped_no_submission'.
- AI API rate limits: if using an external LLM API, implement a retry with exponential backoff (max 3 attempts, starting at 2 seconds). Log failures to Supabase and send an error alert to support@gofullspec.com if all retries fail.
03End-to-end data flow
// ── TRIGGER ─────────────────────────────────────────────────────────────────
// BambooHR fires outbound webhook on employment status change
// Registered event: 'Employment Status'
// Endpoint: POST https://{automation_platform_host}/webhook/bamboohr-exit
RECEIVE bamboohr.webhook.payload {
employee_id, // e.g. '1042'
employee_name, // e.g. 'Sarah Chen'
employee_email, // e.g. 'sarah.chen@[YourCompany.com]'
department, // e.g. 'Operations'
job_title, // e.g. 'Operations Coordinator'
manager_email, // e.g. 'david.osei@[YourCompany.com]'
last_day_date, // e.g. '2025-03-14'
status_new // e.g. 'Leaving'
}
// GUARD: check status_new in ['Leaving','Terminated','Resigned']
// If status_new not in list -> log 'trigger_ignored' to supabase.exit_events -> END
// ── AGENT HANDOFF 1: EXIT INTAKE AGENT ──────────────────────────────────────
LOOKUP typeform_variant_id FROM config.role_variant_map
WHERE department = bamboohr.webhook.payload.department
// e.g. 'Operations' -> form_id: 'XgT7kQpO'
// Default fallback form_id stored in config as TYPEFORM_DEFAULT_FORM_ID
CALL typeform.API POST /forms/{form_id}/links
body: {
email: employee_email,
hidden: {
employee_id: employee_id,
notion_page_id: '[pending — set after Notion step]',
manager_email: manager_email
}
}
-> RETURNS typeform.share_url
SEND email TO employee_email
subject: 'Your exit questionnaire — please complete by {last_day_date minus 2 days}'
body_vars: { employee_name, typeform.share_url, last_day_date }
CALL notion.API POST /pages
body: {
parent: { page_id: config.NOTION_TEMPLATE_PAGE_ID },
properties: {
title: '{employee_name} — Exit Knowledge Transfer',
employee_id: employee_id,
job_title: job_title,
last_day: last_day_date,
manager_email: manager_email
}
}
-> RETURNS notion.page_id, notion.page_url
UPDATE typeform hidden field notion_page_id = notion.page_id
// Re-issue personalised link with updated hidden field if platform requires
SHARE notion.page_id WITH [employee_email, manager_email] (can_edit)
LOG TO supabase.exit_events {
event_type: 'intake_triggered',
employee_id, typeform_form_id, notion_page_id, timestamp: now()
}
SCHEDULE reminder AT (last_day_date minus 48 hours)
IF no typeform.submission WHERE hidden.employee_id = employee_id
-> SEND reminder email TO employee_email
-> LOG 'reminder_sent' TO supabase.exit_events
SCHEDULE fallback AT (last_day_date minus 24 hours)
IF still no typeform.submission WHERE hidden.employee_id = employee_id
-> POST slack.message TO config.SLACK_HR_CHANNEL
text: 'FALLBACK: {employee_name} has not submitted exit questionnaire.'
-> LOG 'fallback_raised' TO supabase.exit_events
-> END (no synthesis attempted)
// ── TRIGGER 2: TYPEFORM SUBMISSION WEBHOOK ───────────────────────────────────
// Typeform fires webhook on form submission
// Registered in Typeform Connect > Webhooks
// Endpoint: POST https://{automation_platform_host}/webhook/typeform-exit-response
RECEIVE typeform.webhook.payload {
form_id, response_id, submitted_at,
hidden_fields: { employee_id, notion_page_id, manager_email },
answers: [ { field_id, type, value } ... ]
}
// GUARD: if employee_id is null or response_id is null -> log
// 'synthesis_skipped_no_submission' -> END
// ── AGENT HANDOFF 2: KNOWLEDGE SYNTHESIS AGENT ──────────────────────────────
MAP answers[] TO structured_schema {
role_knowledge: answers WHERE field_id IN config.ROLE_KNOWLEDGE_FIELD_IDS,
client_relationships: answers WHERE field_id IN config.CLIENT_REL_FIELD_IDS,
process_risks: answers WHERE field_id IN config.PROCESS_RISK_FIELD_IDS,
suggested_handoffs: answers WHERE field_id IN config.HANDOFF_FIELD_IDS
}
CALL AI_API
system_prompt: config.AI_SUMMARY_SYSTEM_PROMPT
user_message: JSON.stringify(structured_schema)
// Retry: max 3 attempts, exponential backoff starting 2s
-> RETURNS ai_summary { sections, gap_flags, completeness_score }
CALL notion.API GET /blocks/{notion_page_id}/children
-> COUNT words per section block
-> FLAG sections WHERE word_count < config.NOTION_GAP_THRESHOLD_WORDS
-> MERGE with ai_summary.gap_flags
RENDER pdf FROM ai_summary.sections
filename: 'EXIT_SUMMARY_{employee_id}_{YYYY-MM-DD}.pdf'
CALL google_drive.API POST /upload
folder_id: config.GDRIVE_HR_EXITS_FOLDER_ID
files: [ pdf_file, raw_typeform_response.json ]
-> RETURNS pdf_file_id, pdf_webViewLink
CALL bamboohr.API PUT /v1/employees/{employee_id}
body: {
customFields: {
exit_summary_text: ai_summary.sections (plaintext concat),
notion_page_url: notion.page_url,
google_drive_pdf_url: pdf_webViewLink
}
}
IF ai_summary.gap_flags WHERE severity = 'high' EXISTS:
POST slack.message TO manager_channel
blocks: [
section: '{employee_name} exit summary is ready. {n} high-priority gap(s) flagged.',
divider,
fields: gap_flags[].section + gap_flags[].note
]
LOG TO supabase.exit_events {
event_type: 'synthesis_complete',
employee_id, response_id, completeness_score,
gap_count: gap_flags.length, timestamp: now()
}
// ── END OF AUTOMATED SEQUENCE ────────────────────────────────────────────────
// Manager reviews PDF summary in Google Drive and decides
// whether a live conversation is required. No further automated steps.04Recommended build stack
More documents for this process
Every document generated for Exit Interview & Knowledge Capture.