Back to Contractor & Freelancer Management

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

Contractor & Freelancer Management

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

This document is the primary technical reference for the FullSpec team building the Contractor and Freelancer Management automation. It covers the current-state process map, both agent specifications, the end-to-end data flow, and the recommended build stack. All implementation decisions made during the discovery and mapping phase are recorded here so the build can proceed without ambiguity. Where a detail requires confirmation before build can start, it is explicitly flagged.

01Process snapshot

Step
Name
Description
1
Confirm Contractor Engagement
Hiring manager confirms verbally or by email that a contractor is approved to start. Details are noted informally with no system entry. Time cost: 10 min.
2
Create Contractor Record in Tracker
HR manually adds name, role, rate, and start date to a shared spreadsheet in Google Drive. This is the only source of truth until a formal system entry is created. Time cost: 15 min.
3
Email Document Checklist to Contractor
HR drafts and sends an onboarding email listing required documents: W-9, signed NDA, bank details, and certifications. Each document is requested as a separate attachment. Time cost: 20 min.
4
Chase Missing Documents
HR sends manual follow-up emails if documents are not returned within a few days. This step repeats two or three times per engagement and is the primary cause of delayed contractor starts. Time cost: 25 min. BOTTLENECK.
5
Review and File Completed Documents
HR reviews each returned document for completeness, renames files to a naming convention, and uploads them to the correct Google Drive folder. Incomplete documents are returned to the contractor. Time cost: 20 min.
6
Collect and Review DocuSign Agreement
HR sends the contract via DocuSign, monitors for completion, and downloads the signed copy. Manual chasing occurs when the contractor is slow to sign. Time cost: 30 min. BOTTLENECK.
7
Add Contractor as Payee in Gusto
Finance adds the contractor as a vendor in Gusto, entering bank details and rate from the spreadsheet manually. Dependent on steps 4 through 6 being complete. Time cost: 15 min.
8
Receive Contractor Invoice
Contractor emails a PDF invoice. Finance downloads it and checks it against the agreed rate, hours, and milestone before deciding whether to approve. Time cost: 20 min.
9
Route Invoice for Manager Approval
Finance emails the invoice to the relevant manager. No tracking system exists; the finance team has no visibility on whether the approval has been reviewed. Time cost: 10 min. BOTTLENECK.
10
Enter Approved Invoice into Xero
Finance manually enters invoice details into Xero, assigns the correct expense category, and attaches the PDF once email approval is received. Time cost: 15 min.
11
Schedule and Confirm Payment
Finance schedules the payment run in Xero or Gusto and notifies the contractor by email. If the run is missed, the contractor waits for the next cycle. Time cost: 10 min.
Time cost summary: Total manual time per contractor engagement cycle is 190 minutes (approximately 3 hours 10 minutes). At approximately 12 contractor engagements per month with recurring invoice steps, the process consumes roughly 22 manual hours every 30 days and 5.5 hours per week. Steps 2, 3, 4, 5, 6 (onboarding sequence) and steps 7, 8, 9, 10, 11 (invoice sequence) are fully replaced by the two agents. Step 1 (verbal engagement confirmation) is the only step that remains human-initiated; it acts as the trigger event.
Developer Handover PackPage 1 of 4
FS-DOC-04Technical

02Agent specifications

Contractor Onboarding Agent

Handles the full onboarding sequence from the moment a contractor is confirmed in HubSpot. The agent creates the contractor contact record, dispatches the correct DocuSign agreement based on role and rate, sends a structured document collection request with a Google Drive upload link, and monitors completion status on a schedule. If required documents have not been received within three business days, the agent sends a follow-up reminder to the contractor and posts an alert to the configured HR Slack channel. The agent repeats reminders on a configurable cadence and only escalates to the HR team when a document is flagged as unreadable, incorrect, or persistently missing beyond the escalation threshold. Once DocuSign is fully countersigned and all compliance documents are confirmed in the target Drive folder, the agent triggers payee creation in Gusto and marks the contractor record in HubSpot as onboarding complete. The agent does not auto-approve any document it cannot parse; it flags the record and holds the Gusto step until a human clears the exception.

Trigger
New contact record created in HubSpot with lifecycle stage or tag set to 'Contractor', OR a contractor engagement form submission received via the connected intake form endpoint.
Tools
HubSpot, DocuSign, Google Drive, Slack, Gusto
Replaces steps
2, 3, 4, 5, 6, 7
Estimated build
22 hours, Moderate complexity
// Input
hubspot.contact.id          : string
hubspot.contact.email       : string
hubspot.contact.role        : string   // e.g. 'Graphic Designer'
hubspot.contact.rate_usd    : number   // agreed hourly or project rate
hubspot.contact.start_date  : ISO8601
hubspot.contact.tag         : 'contractor'

// Output
hubspot.contact.stage       : 'onboarding_complete'
docusign.envelope.status    : 'completed'
docusign.envelope.id        : string
google_drive.folder_id      : string   // contractor-specific subfolder
google_drive.files[]        : { name, mime_type, upload_timestamp }
gusto.contractor.id         : string
gusto.contractor.status     : 'active'
slack.alert.channel         : '#hr-contractor-ops'
slack.alert.text            : string   // posted only on exception or escalation

// On exception (missing or unreadable document)
hubspot.contact.flag        : 'document_exception'
slack.alert.text            : 'ACTION REQUIRED: [contractor_name] document check failed'
gusto.step                  : HELD  // payee creation paused until cleared
  • HubSpot tier must support workflow triggers via API (Operations Hub Starter or above, or equivalent API access plan). Confirm tier before build starts.
  • DocuSign templates must be created, role-mapped (Contractor signer, Company countersigner), and activated in the DocuSign account before the agent can select and pre-fill them. Template IDs are passed as environment variables; the agent must not hard-code them.
  • Google Drive folder structure must be agreed and pre-created (e.g. /Contractors/{contractor_id}/Compliance and /Contractors/{contractor_id}/Agreements) before the document-filing step is wired. The agent uses the contractor's HubSpot contact ID as the folder name to ensure uniqueness.
  • Reminder cadence defaults to Day 3 and Day 6 after initial document request. A third reminder at Day 9 triggers Slack escalation to #hr-contractor-ops. Cadence values must be stored as environment variables, not hard-coded.
  • Gusto payee creation requires the Gusto Embedded Payroll or Plus API tier. Confirm the active Gusto plan includes contractor API write access before committing this step to the build.
  • Dedupe logic: the agent checks for an existing HubSpot contact with a matching email address before creating a new record. If a duplicate is found, the agent updates the existing record and posts a Slack alert to the HR channel rather than creating a second contact.
  • DocuSign completion webhook must be registered in the DocuSign Connect configuration to push envelope status events to the automation platform listener endpoint. Polling is not acceptable for this step.
  • Fallback for undeliverable document collection email: if the contractor email bounces, the agent flags the HubSpot record and posts a Slack alert immediately rather than continuing the onboarding sequence.
Invoice Processing Agent

Receives incoming contractor invoices submitted either by email to a monitored inbox or through a linked intake form, then validates the invoice amount against the agreed rate stored in HubSpot for the matching contractor record. If the amount matches within the configured tolerance (default: zero variance, or within 2% if a tolerance environment variable is set), the agent routes a Slack approval message to the assigned manager, including the invoice amount, contractor name, engagement period, and an approve or query action button. The manager's response is captured and written back to the HubSpot deal or activity record. On approval, the agent creates a bill in Xero with the correct expense category, attaches the invoice PDF, schedules payment for the next payment run, and sends a confirmation email to the contractor. If the invoice amount does not match the agreed rate, the agent flags the record in HubSpot, holds all payment steps, and posts a detailed mismatch alert to the #finance-ops Slack channel for manual review by the Finance Administrator. The agent never auto-approves a mismatched invoice.

Trigger
Contractor invoice received via monitored email inbox (PDF attachment parsed) OR form submission endpoint returns a new invoice payload.
Tools
HubSpot, Xero, Gusto, Slack
Replaces steps
8, 9, 10, 11
Estimated build
18 hours, Moderate complexity
// Input
invoice.contractor_email    : string
invoice.amount_usd          : number
invoice.invoice_number      : string
invoice.invoice_date        : ISO8601
invoice.period_start        : ISO8601
invoice.period_end          : ISO8601
invoice.pdf_attachment      : base64 | URL
hubspot.contact.rate_usd    : number   // pulled by matching contractor_email
hubspot.contact.id          : string

// Output (matched invoice, approved)
xero.bill.id                : string
xero.bill.status            : 'APPROVED'
xero.bill.account_code      : string   // e.g. '400' Contractor Expenses
xero.payment.scheduled_date : ISO8601
gusto.payment.reference     : string   // if Gusto payment run triggered
hubspot.activity.type       : 'invoice_approved'
hubspot.activity.timestamp  : ISO8601
email.contractor.subject    : 'Your invoice [invoice_number] has been approved'
slack.approval.response     : 'approved' | 'queried'

// On approval (Slack interaction payload)
slack.action.value          : 'approve' | 'query'
slack.action.user           : string   // manager Slack user ID
slack.action.timestamp      : ISO8601

// On mismatch (rate does not match)
hubspot.contact.flag        : 'invoice_mismatch'
slack.alert.channel         : '#finance-ops'
slack.alert.text            : 'MISMATCH: [contractor_name] invoiced $[amount] vs agreed $[rate]'
xero.step                   : HELD
gusto.step                  : HELD
  • Contractor rate data must be stored in a dedicated HubSpot contact property (suggested property name: contractor_agreed_rate_usd) and populated at the point of engagement. If rates are held in a spreadsheet and not migrated to HubSpot before build, the matching logic cannot function.
  • Invoice parsing: the agent extracts invoice_number, amount, period, and contractor email from the PDF using a structured parsing step. If parsing confidence is below threshold (suggested: 90%), the agent flags the invoice for manual review rather than proceeding with potentially incorrect data.
  • Slack approval message must include a direct link to the invoice PDF and display the HubSpot contractor record URL. The Slack app must be installed in the workspace with bot token scopes: chat:write, incoming-webhook, and interactive messages (block kit actions).
  • Xero account code for contractor expenses must be agreed with the Finance Administrator before build. Store as an environment variable (XERO_CONTRACTOR_ACCOUNT_CODE). Default suggestion: account code 400 (Contractor Services).
  • Gusto payment trigger is optional per engagement; some contractors may be paid via Xero only. Add a HubSpot contact property (payment_method: 'xero' | 'gusto') so the agent routes payment creation correctly per contractor.
  • Manager approval timeout: if no Slack response is received within 24 hours, the agent sends a reminder to the same manager. After 48 hours with no response, a secondary alert is posted to #finance-ops for escalation. Timeout values stored as environment variables.
  • Dedupe logic: the agent checks invoice_number against a logged Xero bill reference before processing. If a bill with the same reference already exists, the agent skips creation and posts a duplicate warning to #finance-ops.
  • Xero API uses OAuth 2.0 with a 30-minute access token and a 60-day refresh token. The orchestration layer must handle token refresh silently. Confirm that the Xero organisation is connected under the correct tenant ID before build.
Developer Handover PackPage 2 of 4
FS-DOC-04Technical

03End-to-end data flow

Full trigger-to-output data flow: Contractor and Freelancer Management automation
// ─────────────────────────────────────────────────────────────────
// TRIGGER: New contractor engagement confirmed
// ─────────────────────────────────────────────────────────────────
TRIGGER_SOURCE : 'hubspot_contact_created' | 'form_submission'
  -> payload.contact_email   : string
  -> payload.contact_name    : string
  -> payload.role            : string
  -> payload.rate_usd        : number
  -> payload.start_date      : ISO8601
  -> payload.tag             : 'contractor'

// ──────────────────────────���──────────────────────────────────────
// AGENT 1 HANDOFF: Contractor Onboarding Agent receives trigger
// ─────────────────────────────────────────────────────────────────

// Step A: HubSpot record creation / deduplication
HubSpot.contacts.search(email: payload.contact_email)
  IF existing_contact FOUND
    -> HubSpot.contacts.update(id, { tag: 'contractor', stage: 'onboarding' })
    -> Slack.post(channel: '#hr-contractor-ops', text: 'Duplicate contact updated: [name]')
  ELSE
    -> HubSpot.contacts.create({
         email, firstname, lastname, role,
         contractor_agreed_rate_usd: rate_usd,
         start_date, lifecyclestage: 'contractor',
         hs_lead_status: 'onboarding'
       })
    -> hubspot.contact.id : string  // stored for all downstream steps

// Step B: DocuSign agreement dispatch
DocuSign.envelopes.create({
  templateId: ENV.DOCUSIGN_TEMPLATE_ID_FOR_ROLE,
  signers: [{ email, name, role: 'Contractor' }],
  prefill: { rate_usd, start_date, role }
})
  -> docusign.envelope.id : string
  -> docusign.envelope.status : 'sent'
  -> HubSpot.activity.log({ type: 'docusign_sent', envelope_id })

// Step C: Document collection request
Email.send({
  to: payload.contact_email,
  template: 'contractor_onboarding_checklist',
  vars: {
    contractor_name, required_docs: ['W-9','NDA','Bank Details','Certification'],
    upload_link: google_drive.upload_url(folder: '/Contractors/{contact_id}/Compliance')
  }
})
  -> email.sent_timestamp : ISO8601

// Step D: Document chase loop
SCHEDULE.check(after: '3 business days', condition: google_drive.folder_complete == false)
  IF incomplete
    -> Email.send(to: contact_email, template: 'doc_reminder_1')
  SCHEDULE.check(after: '6 business days', condition: google_drive.folder_complete == false)
    -> Email.send(to: contact_email, template: 'doc_reminder_2')
  SCHEDULE.check(after: '9 business days', condition: google_drive.folder_complete == false)
    -> Slack.post(channel: '#hr-contractor-ops',
                  text: 'ESCALATION: [name] documents still incomplete after 9 days')
    -> HubSpot.contacts.update(id, { hs_lead_status: 'document_exception' })

// Step E: DocuSign completion webhook received
WEBHOOK: DocuSign.Connect -> platform_listener_url
  -> docusign.envelope.status : 'completed'
  -> Google_Drive.files.upload({
       folder: '/Contractors/{contact_id}/Agreements',
       file: docusign.signed_pdf,
       name: '{contact_id}_agreement_signed_{timestamp}.pdf'
     })
  -> HubSpot.contacts.update(id, { docusign_status: 'completed' })

// Step F: Gusto payee creation (fires when Drive folder complete AND DocuSign complete)
CONDITION: google_drive.folder_complete == true AND docusign.status == 'completed'
  -> Gusto.contractors.create({
       first_name, last_name, email,
       wage: rate_usd,
       wage_type: 'Fixed'  // or 'Hourly' per ENV.GUSTO_WAGE_TYPE
     })
  -> gusto.contractor.id : string
  -> HubSpot.contacts.update(id, {
       gusto_contractor_id: gusto.contractor.id,
       hs_lead_status: 'onboarding_complete'
     })

// ─────────────────────────────────────────────────────────────────
// AGENT 2 HANDOFF: Invoice Processing Agent receives invoice
// ─────────────────────────────────────────────────────────────────

// Step G: Invoice intake and parsing
TRIGGER_SOURCE : 'email_inbox_monitor' | 'invoice_form_submission'
  -> invoice.from_email      : string
  -> invoice.pdf_attachment  : base64 | URL
  -> invoice.invoice_number  : string   // parsed from PDF
  -> invoice.amount_usd      : number   // parsed from PDF
  -> invoice.period_start    : ISO8601  // parsed from PDF
  -> invoice.period_end      : ISO8601  // parsed from PDF

// Step H: Contractor record lookup and rate match
HubSpot.contacts.search(email: invoice.from_email)
  -> hubspot.contact.id                   : string
  -> hubspot.contractor_agreed_rate_usd   : number

CONDITION: abs(invoice.amount_usd - hubspot.rate_usd) <= ENV.RATE_TOLERANCE
  IF mismatch
    -> HubSpot.contacts.update(id, { flag: 'invoice_mismatch' })
    -> Slack.post(channel: '#finance-ops',
                  text: 'MISMATCH: [name] invoiced $[amount] vs agreed $[rate]')
    -> HALT  // all Xero and Gusto steps held

// Step I: Slack approval routing (match confirmed)
Slack.message.send({
  channel: hubspot.contact.assigned_manager_slack_id,
  blocks: [
    { type: 'section', text: 'Invoice from [name]: $[amount] for [period]' },
    { type: 'actions', elements: [
        { action_id: 'approve_invoice', text: 'Approve' },
        { action_id: 'query_invoice',   text: 'Query'   }
    ]}
  ]
})
  -> slack.message.ts : string  // stored for interaction callback

WEBHOOK: Slack.InteractivePayload -> platform_listener_url
  -> slack.action.value     : 'approve' | 'query'
  -> slack.action.user.id   : string
  -> slack.action.timestamp : ISO8601
  -> HubSpot.activity.log({ type: 'invoice_approval_decision', value, user, ts })

// Step J: Xero bill creation and payment scheduling (on approve)
CONDITION: slack.action.value == 'approve'
  -> Xero.invoices.create({
       type: 'ACCPAY',
       contact: { email: invoice.from_email },
       lineItems: [{
         description: 'Contractor services [period_start] to [period_end]',
         quantity: 1,
         unitAmount: invoice.amount_usd,
         accountCode: ENV.XERO_CONTRACTOR_ACCOUNT_CODE
       }],
       reference: invoice.invoice_number,
       attachments: [{ filename, content_base64: invoice.pdf_attachment }]
     })
  -> xero.bill.id     : string
  -> xero.bill.status : 'APPROVED'

  -> Xero.payments.create({
       invoice_id: xero.bill.id,
       date: next_payment_run_date,
       account_id: ENV.XERO_BANK_ACCOUNT_ID
     })
  -> xero.payment.scheduled_date : ISO8601

// Step K: Gusto payment trigger (if contractor.payment_method == 'gusto')
CONDITION: hubspot.contact.payment_method == 'gusto'
  -> Gusto.contractor_payments.create({
       contractor_id: hubspot.gusto_contractor_id,
       amount: invoice.amount_usd,
       date: xero.payment.scheduled_date
     })
  -> gusto.payment.reference : string

// Step L: Contractor confirmation email
Email.send({
  to: invoice.from_email,
  template: 'invoice_approved_confirmation',
  vars: {
    invoice_number: invoice.invoice_number,
    amount_usd: invoice.amount_usd,
    payment_date: xero.payment.scheduled_date
  }
})
// ─────────────────────────────────────────────────────────────────
// END OF FLOW
// ─────────────────────────────────────────────────────────────────
Developer Handover PackPage 3 of 4
FS-DOC-04Technical

04Recommended build stack

Orchestration layer
A workflow automation platform with native HTTP request nodes, webhook listener endpoints, and a shared credential store. One workflow per agent: 'Contractor Onboarding Agent' and 'Invoice Processing Agent'. Credentials for HubSpot, DocuSign, Google Drive, Slack, Xero, and Gusto are stored centrally in the platform credential vault and referenced by name in each node, never hard-coded in workflow logic. Environment variables (DocuSign template IDs, Xero account codes, reminder cadence days, rate tolerance) are stored as platform-level variables accessible across both workflows.
Webhook configuration
Two inbound listener endpoints are required: (1) DocuSign Connect webhook for envelope status events (target: platform listener URL, event types: envelope-completed, envelope-declined, envelope-voided); (2) Slack Interactive Payload endpoint for approval button callbacks (target: platform listener URL, verified using Slack signing secret). Both endpoints must use HTTPS. The invoice email monitor uses an IMAP or forwarding-rule-based trigger connected to a dedicated monitored inbox (e.g. invoices@[YourCompany.com]) rather than a personal inbox.
Templating approach
Email templates (document collection request, reminder 1, reminder 2, invoice confirmation) are authored as HTML templates stored in the automation platform's template library. Variable substitution uses named tokens: {{contractor_name}}, {{upload_link}}, {{invoice_number}}, {{payment_date}}. DocuSign templates are managed inside DocuSign itself; the automation passes templateId and signer data via API. Slack messages use Block Kit JSON with action elements for the approval flow; block payloads are authored inline in the workflow node for maintainability.
Error logging
All caught exceptions (HubSpot lookup failures, DocuSign API errors, Xero bill creation failures, Gusto API errors, PDF parse confidence below threshold, undeliverable emails) are written to a Supabase table named automation_error_log with columns: id (uuid), workflow_name (text), step_name (text), error_message (text), payload_snapshot (jsonb), created_at (timestamptz). A Slack alert is posted to #automation-errors on every error log write. The Supabase table is indexed on workflow_name and created_at for efficient querying. Error rows are retained for 90 days then archived.
Testing approach
All integrations are wired and tested against sandbox or test-mode environments before any live data is touched: HubSpot sandbox account, DocuSign Developer environment, Xero Demo Company tenant, Gusto staging environment, and Google Drive test folder tree. Slack testing uses a private internal channel (#automation-test). Full end-to-end test runs use a sample contractor profile (name: Test Contractor, email: test-contractor@example.com, rate: $500) and a sample invoice PDF. Mismatch and exception scenarios are tested before go-live per the Test and QA Plan.
Estimated total build time
Contractor Onboarding Agent: 22 hours. Invoice Processing Agent: 18 hours. End-to-end integration testing, edge-case QA, error logging wiring, and handoff documentation: 10 hours. Total: 50 hours across the 5-week delivery schedule. (The 40-hour build effort figure in the snapshot excludes the 10-hour QA and testing allocation which is tracked separately in the Test and QA Plan.)
Three pre-build blockers must be resolved before workflow construction begins: (1) DocuSign templates must be created, role-mapped, and live in the target DocuSign account, with template IDs recorded in the environment variable store. (2) The HubSpot contact property contractor_agreed_rate_usd must be created and populated for all active contractors before the Invoice Processing Agent can validate amounts. (3) Gusto API access tier must be confirmed as supporting contractor write endpoints; if the current plan does not include this, the Gusto payee creation and payment steps must be scoped as a manual fallback until the plan is upgraded. Contact the FullSpec team at support@gofullspec.com to confirm these items are resolved before build week 2 begins.
Developer Handover PackPage 4 of 4

More documents for this process

Every document generated for Contractor & Freelancer Management.

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