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
Probation Period Management
[YourCompany.com] · HR Department · Prepared by FullSpec · [Today's Date]
This document gives the FullSpec build team everything needed to construct, wire, and validate the Probation Period Management automation end to end. It covers the current-state step map with bottleneck flags, full agent specifications with IO contracts, a field-level data flow trace, and the recommended build stack with estimated hours. The owner's responsibility is limited to the single manual step where HR Manager records the probation outcome in Notion. Every other step described here is handled by the automation.
01Process snapshot
02Agent specifications
Watches BambooHR for new employee records with a confirmed start date. On detection, calculates the 4-week, 8-week, and end-of-probation milestone dates from the start date field and writes a structured tracker row to the Notion probation database. Fires once per new hire and re-evaluates if the start date field in BambooHR is subsequently updated, overwriting the existing Notion row rather than creating a duplicate. This agent eliminates manual tracker creation and calendar reminder setup entirely.
// Input
BambooHR webhook payload {
employee_id: string,
first_name: string,
last_name: string,
hireDate: ISO8601 date,
department: string,
manager_id: string,
customProbationEndDate: ISO8601 date // may need custom field confirmation
}
// Computed fields (internal)
milestone_4wk = hireDate + 28 days
milestone_8wk = hireDate + 56 days
probation_end = customProbationEndDate OR hireDate + 90 days (fallback)
// Output
Notion database row {
employee_name: '{first_name} {last_name}',
employee_id: string,
manager_id: string,
hire_date: ISO8601 date,
milestone_4wk: ISO8601 date,
milestone_8wk: ISO8601 date,
probation_end: ISO8601 date,
status: 'Active',
feedback_4wk_received: false,
feedback_8wk_received: false,
outcome: null,
created_at: ISO8601 datetime
}- BambooHR must expose customProbationEndDate via the API before build starts. If this field is not present, the FullSpec team will default to hireDate + 90 days and flag the discrepancy to the process owner for confirmation.
- BambooHR API tier must support webhook event subscriptions (available on Essentials tier and above). Confirm tier before build starts.
- Notion integration requires a Notion internal integration token with insert and update permissions on the Probation Tracker database. The database ID must be provided before build.
- Dedupe logic: before creating a new Notion row, query the database for an existing row matching employee_id. If found, update in place rather than inserting. This prevents duplicate tracker entries on webhook replay.
- Manager lookup: manager_id from BambooHR must be resolved to an email address and Slack user ID at agent run time. A BambooHR employee lookup call (GET /employees/{manager_id}) provides the manager email. Slack user lookup by email provides the Slack user ID for the Feedback Chase Agent.
- If the BambooHR webhook fires before a start date is confirmed (i.e. hireDate is null), the agent must exit silently and log the event without creating a Notion row. A retry check should run after 24 hours.
Runs on a scheduled poll of the Notion probation tracker. At each milestone date (4-week and 8-week), it sends a personalised feedback request email to the responsible manager via Gmail. It then monitors for a response or form submission. If no response is recorded against the Notion tracker row within 48 hours of the email send, the agent posts a direct Slack message to the manager containing the feedback form link. If a second 48-hour window passes without response, it escalates by messaging the HR Slack channel directly. All chase events are timestamped in the Notion tracker row's chase log property.
// Input (from Notion tracker row)
probation_record {
employee_name: string,
employee_id: string,
manager_id: string,
manager_email: string,
manager_slack_id: string,
milestone_4wk: ISO8601 date,
milestone_8wk: ISO8601 date,
feedback_4wk_received: boolean,
feedback_8wk_received: boolean,
chase_log: array<{event: string, timestamp: ISO8601 datetime}>
}
// Output (per milestone cycle)
Gmail send: {
to: manager_email,
subject: 'Probation review due: {employee_name}',
body: personalised template with feedback form link,
timestamp_sent: ISO8601 datetime
}
// On no response after 48 hrs
Slack DM to manager_slack_id: {
text: 'Reminder: feedback outstanding for {employee_name} probation review.',
form_link: string
}
Notion chase_log append: { event: 'slack_reminder_sent', timestamp: ... }
// On no response after second 48 hrs
Slack channel post to #hr-alerts: {
text: 'Escalation: {manager_name} has not submitted probation feedback for {employee_name}. HR action required.',
}
Notion chase_log append: { event: 'escalated_to_hr', timestamp: ... }
// On feedback received
Notion update: { feedback_{milestone}_received: true, feedback_{milestone}_timestamp: ISO8601 datetime }- Gmail send requires a Google Workspace service account with domain-wide delegation, or a dedicated HR Gmail OAuth credential. The sending address must be agreed before build (e.g. hr@[YourCompany.com]).
- Feedback receipt detection: if feedback is collected via a Google Form, configure a Form submission trigger or a Google Sheets append event to update the Notion feedback_received flag via an intermediary step. If feedback is freeform email reply, the agent must poll the Gmail sent thread for a reply and update Notion on receipt.
- Slack integration requires the automation platform's Slack app to be installed in the workspace with chat:write and users:read.email OAuth scopes. The #hr-alerts channel ID must be stored in the credential store before build.
- The 48-hour window is calculated from the timestamp of the initial Gmail send stored in the Notion chase_log, not from the milestone date itself.
- Milestone poll logic must skip rows where status is not 'Active' (e.g. 'Outcome Logged', 'Closed') to prevent chase emails firing after an outcome has been recorded.
- Confirm with the process owner whether the feedback form is a Google Form (preferred for automated receipt detection) or an email-based questionnaire before finalising the Gmail template.
Listens for a Notion database property change where the outcome field on a probation tracker row is set to 'Pass', 'Extend', or 'Exit' by the HR Manager. On detection, it selects the correct Google Docs template based on the outcome value, performs a field merge to populate employee name, outcome type, effective date, and any extension conditions, exports the merged document to PDF, and creates a DocuSign envelope routing it to the manager for signature first and then the employee. Once DocuSign reports all signatures collected via its completion webhook, the agent writes the final probation status back to BambooHR and updates the Notion tracker row status to 'Closed', filing the signed PDF link in the Notion record.
// Input (from Notion outcome update event)
probation_record {
employee_name: string,
employee_id: string,
manager_email: string,
employee_email: string,
outcome: 'Pass' | 'Extend' | 'Exit',
probation_end: ISO8601 date,
extension_end_date: ISO8601 date | null, // required if outcome = 'Extend'
outcome_recorded_at: ISO8601 datetime,
notion_page_id: string
}
// Template selection logic
template_id = {
'Pass': GOOGLE_DOCS_TEMPLATE_ID_PASS,
'Extend': GOOGLE_DOCS_TEMPLATE_ID_EXTEND,
'Exit': GOOGLE_DOCS_TEMPLATE_ID_EXIT
}[outcome]
// Google Docs merge fields
merge_fields {
{{employee_name}}: string,
{{outcome_date}}: formatted date string,
{{outcome_type}}: string,
{{extension_end_date}}: string | 'N/A',
{{manager_name}}: string
}
// DocuSign envelope
envelope {
document: PDF export of merged Google Doc,
signers: [
{ name: manager_name, email: manager_email, routing_order: 1 },
{ name: employee_name, email: employee_email, routing_order: 2 }
],
subject: 'Probation outcome letter: {employee_name}',
status: 'sent'
}
// On approval (DocuSign completion webhook)
BambooHR PATCH /employees/{employee_id} {
customProbationStatus: outcome, // 'Pass' | 'Extend' | 'Exit'
customProbationClosedDate: ISO8601 date
}
Notion update {
status: 'Closed',
signed_letter_url: DocuSign completed document URL,
closed_at: ISO8601 datetime
}- Three separate Google Docs templates must be created and locked (Pass, Extend, Exit) before build starts. The agent will clone the correct template at run time using the Google Drive copy API and then perform the merge on the copy, leaving the original template unmodified.
- Google Docs merge is performed by replacing placeholder strings (e.g. {{employee_name}}) in the document body using the Google Docs API batchUpdate method. Templates must use exactly these placeholder strings, verified before go-live.
- DocuSign integration requires a DocuSign developer account promoted to production, with an integration key and RSA key pair configured for JWT grant authentication. The account ID and base URI must be stored in the credential store.
- DocuSign completion webhook (Connect) must be configured to POST to the automation platform's inbound webhook endpoint when envelope status changes to 'completed'. The endpoint URL is generated at build time.
- BambooHR write-back requires the customProbationStatus and customProbationClosedDate custom fields to exist and be writable via the API before build starts. Confirm field names and API write permissions with the process owner.
- If extension_end_date is null and outcome is 'Extend', the agent must pause and post a Slack alert to the #hr-alerts channel requesting the extension end date before proceeding. Do not generate a letter with a blank extension date.
- DocuSign signing order is manager first, employee second. If the process owner confirms a different order for any outcome type, a conditional branch must be added to the envelope creation logic before build is finalised.
03End-to-end data flow
// ── TRIGGER ──────────────────────────────────────────────────────────────────
// BambooHR fires a webhook on new employee record creation
BambooHR.webhook -> event {
event_type: 'employee.created',
employee_id: 'EMP-0042',
first_name: 'Jordan',
last_name: 'Hartley',
hireDate: '2024-05-06',
department: 'Operations',
manager_id: 'MGR-0011',
customProbationEndDate: '2024-08-04'
}
// ── AGENT 1: Probation Schedule Agent ────────────────────────────────────────
// Resolve manager email via BambooHR GET /employees/{manager_id}
BambooHR.GET('/employees/MGR-0011') -> {
manager_email: 'sarah.chen@[YourCompany.com]',
manager_name: 'Sarah Chen'
}
// Resolve manager Slack user ID via Slack users.lookupByEmail
Slack.users.lookupByEmail('sarah.chen@[YourCompany.com]') -> {
manager_slack_id: 'U04XXXX1234'
}
// Compute milestones
milestone_4wk = '2024-06-03' // hireDate + 28 days
milestone_8wk = '2024-07-01' // hireDate + 56 days
probation_end = '2024-08-04' // customProbationEndDate
// Write Notion probation tracker row
Notion.pages.create -> probation_page {
notion_page_id: 'abc123def456',
employee_name: 'Jordan Hartley',
employee_id: 'EMP-0042',
manager_email: 'sarah.chen@[YourCompany.com]',
manager_slack_id: 'U04XXXX1234',
hire_date: '2024-05-06',
milestone_4wk: '2024-06-03',
milestone_8wk: '2024-07-01',
probation_end: '2024-08-04',
status: 'Active',
feedback_4wk_received: false,
feedback_8wk_received: false,
outcome: null,
chase_log: [],
created_at: '2024-05-06T09:14:00Z'
}
// ── HANDOFF: Schedule Agent -> Feedback Chase Agent ──────────────────────────
// Chase Agent reads active Notion rows on 6-hour poll schedule
// ── AGENT 2: Feedback Chase Agent (milestone_4wk reached) ────────────────────
// Notion poll detects: current_date == milestone_4wk AND feedback_4wk_received == false
Notion.query -> probation_page { notion_page_id: 'abc123def456', ... }
// Send Gmail feedback request
Gmail.send -> {
to: 'sarah.chen@[YourCompany.com]',
subject: 'Probation review due: Jordan Hartley',
body: 'Hi Sarah, Jordan Hartley reached their 4-week review milestone...',
feedback_form_link: 'https://forms.gle/XXXX',
timestamp_sent: '2024-06-03T08:00:00Z'
}
Notion.update -> chase_log.append({ event: 'email_sent_4wk', timestamp: '2024-06-03T08:00:00Z' })
// 48-hour check: no feedback_4wk_received flag set -> post Slack DM
Slack.chat.postMessage -> {
channel: 'U04XXXX1234',
text: 'Reminder: feedback outstanding for Jordan Hartley probation review.',
feedback_form_link: 'https://forms.gle/XXXX'
}
Notion.update -> chase_log.append({ event: 'slack_reminder_sent', timestamp: '2024-06-05T08:00:00Z' })
// 96-hour check: still no response -> escalate to HR channel
Slack.chat.postMessage -> {
channel: '#hr-alerts',
text: 'Escalation: Sarah Chen has not submitted probation feedback for Jordan Hartley.'
}
Notion.update -> chase_log.append({ event: 'escalated_to_hr', timestamp: '2024-06-07T08:00:00Z' })
// On feedback received (Google Form submission or email reply detected)
Notion.update -> { feedback_4wk_received: true, feedback_4wk_timestamp: '2024-06-05T11:32:00Z' }
// ── MANUAL STEP (retained): HR Manager logs outcome in Notion ─────────────────
// HR Manager sets outcome field: 'Pass'
Notion.page_updated -> {
notion_page_id: 'abc123def456',
outcome: 'Pass',
outcome_recorded_at: '2024-08-02T14:05:00Z'
}
// ── HANDOFF: HR Manager Notion update -> Outcome and Documentation Agent ──────
// ── AGENT 3: Outcome and Documentation Agent ─────────────────────────────────
// Notion change event detected, outcome = 'Pass'
// Clone correct Google Docs template
GoogleDrive.files.copy(GOOGLE_DOCS_TEMPLATE_ID_PASS) -> {
new_doc_id: 'GDOC-COPY-789',
file_name: 'Probation_Letter_JordanHartley_Pass_2024-08-02'
}
// Merge fields into cloned document
GoogleDocs.batchUpdate(GDOC-COPY-789) -> replace {
'{{employee_name}}' -> 'Jordan Hartley',
'{{outcome_date}}' -> '2 August 2024',
'{{outcome_type}}' -> 'Pass',
'{{extension_end_date}}' -> 'N/A',
'{{manager_name}}' -> 'Sarah Chen'
}
// Export merged doc to PDF
GoogleDrive.export(GDOC-COPY-789, mimeType='application/pdf') -> letter.pdf
// Create and send DocuSign envelope
DocuSign.envelopes.create -> {
envelope_id: 'DSX-ENV-5566',
document: letter.pdf,
signers: [
{ name: 'Sarah Chen', email: 'sarah.chen@[YourCompany.com]', routing_order: 1 },
{ name: 'Jordan Hartley', email: 'jordan.hartley@[YourCompany.com]', routing_order: 2 }
],
subject: 'Probation outcome letter: Jordan Hartley',
status: 'sent'
}
Notion.update -> { docusign_envelope_id: 'DSX-ENV-5566', status: 'Awaiting Signatures' }
// ── ON APPROVAL: DocuSign completion webhook ──────────────────────────────────
DocuSign.Connect.webhook -> {
envelope_id: 'DSX-ENV-5566',
status: 'completed',
completed_at: '2024-08-03T10:21:00Z',
signed_document_url: 'https://docusign.net/signed/DSX-ENV-5566.pdf'
}
// Update BambooHR with final outcome
BambooHR.PATCH('/employees/EMP-0042') -> {
customProbationStatus: 'Pass',
customProbationClosedDate: '2024-08-03'
}
// Close Notion tracker row
Notion.update -> {
status: 'Closed',
signed_letter_url: 'https://docusign.net/signed/DSX-ENV-5566.pdf',
closed_at: '2024-08-03T10:22:00Z'
}04Recommended build stack
More documents for this process
Every document generated for Probation Period Management.