Back to Budget Planning & Approval

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

Budget Planning and Approval

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

This document gives the FullSpec build team everything needed to implement the Budget Planning and Approval automation end to end. It covers the current-state step map with bottleneck flags, full agent specifications with IO contracts, the end-to-end data flow trace, and the recommended build stack. You, the process owner, do not need to act on the contents of this document. The FullSpec team owns all build decisions described here and will confirm any outstanding configuration choices with you before proceeding.

01Process snapshot

Step
Name
Description
1
Announce Budget Round and Deadline
Finance Manager manually emails all department heads with the planning round announcement, deadline, and a link to the shared spreadsheet template. No standard format enforced. Time cost: 30 min.
2
Distribute Budget Input Template
Finance attaches or shares the budget input spreadsheet with each department head. Version drift occurs when the master template is updated mid-cycle. Time cost: 20 min.
3
Chase Late Submissions
Finance manually tracks submission status and sends individual follow-up emails to departments that have missed the deadline, often requiring two to three rounds over several days. Time cost: 90 min.
4
Collect and Validate Submissions
Finance opens each returned spreadsheet, checks for missing line items, formula errors, and category mismatches, then manually corrects or re-queries the submitter. Repeats for every department. Time cost: 150 min.
5
Consolidate Into Master Budget
Finance copies validated figures from each departmental submission into the master workbook, mapping rows to cost centres and reconciling totals against the prior period. Time cost: 180 min.
6
Cross-Check Against Actuals in Xero
Finance pulls prior period actuals from Xero and manually compares them to the draft budget to flag significant variances for management review. Time cost: 60 min.
7
Prepare Budget Summary Report
Finance builds a summary PDF of the consolidated budget including department totals, variance commentary, and key assumptions. Time cost: 90 min.
8
Send Draft for Management Review
Finance emails the draft budget and summary to the CEO and relevant directors. No tracking of who has reviewed it. Time cost: 20 min.
9
Collect and Incorporate Feedback
Finance receives comments by email and in marked-up spreadsheets, manually updates the master budget, and re-sends the revised version for another round of review. Time cost: 120 min.
10
Obtain Final Sign-Off via DocuSign
Finance manually uploads the final budget document to DocuSign, configures the signing order, and sends it to the required signatories. Time cost: 30 min.
11
Archive Signed Budget and Notify Team
Finance saves the completed document to Google Drive, updates the master workbook with approved figures, and sends a confirmation email to all department heads. Time cost: 25 min.
Time cost summary: Total manual time per cycle is 815 minutes (approximately 13.6 hours). At 1 to 4 cycles per year and a blended 7 hours of ongoing manual overhead per week across the planning period, this process costs the Finance Manager roughly 350 hours per year. Steps 3, 4, and 5 account for over 60% of total manual time and are the primary bottlenecks. Steps 3 (Chase Late Submissions), 4 (Collect and Validate Submissions), 5 (Consolidate Into Master Budget), 8 (Send Draft for Management Review), 10 (Obtain Final Sign-Off via DocuSign), and 11 (Archive Signed Budget and Notify Team) are fully replaced by the three agents. Step 9 (Collect and Incorporate Feedback) is substantially reduced because the approval routing agent handles revision routing. Steps 1, 2, 7, and 9 (manual review of flagged lines only) are retained as intentional human touchpoints.
Developer Handover PackPage 1 of 4
FS-DOC-04Technical

02Agent specifications

Submission Coordinator Agent

Monitors the Google Forms submission tracker in the master Google Sheet, identifies department heads who have not submitted within 48 hours of the deadline, and dispatches targeted Slack reminders without any manual intervention from finance. The agent polls the submission status column on a scheduled basis and cross-references it against the department list and the deadline date stored in the planning calendar tab of the master sheet. It logs every reminder sent and the current submission status back to the tracking sheet so finance always has a live view of outstanding responses.

Trigger
Fires when the submission deadline is within 48 hours and one or more department responses are still marked as pending in the Google Sheets tracker.
Tools
Google Forms, Google Sheets, Slack
Replaces steps
Step 3: Chase Late Submissions (90 min manual)
Estimated build
8 hours | Simple
// Input
google_sheets.tracker_tab -> {
  department_name: string,
  submission_status: 'pending' | 'submitted' | 'overdue',
  slack_user_id: string,
  deadline_date: ISO8601,
  hours_until_deadline: number
}

// Output
slack.direct_message -> {
  recipient: slack_user_id,
  message_template: 'budget_reminder_48h' | 'budget_reminder_24h',
  cycle_label: string,
  form_link: url
}
google_sheets.tracker_tab -> {
  reminder_sent_at: ISO8601,
  reminder_count: number,
  last_reminder_type: '48h' | '24h'
}
  • Google Sheets must be on Google Workspace Business Starter or above to support Apps Script triggers or the Sheets API v4 at the required poll frequency. Confirm the workspace tier before build.
  • The tracker tab must have a dedicated column for each of: department_name, slack_user_id, submission_status, and deadline_date. These column headers must be fixed at row 1 and must not be renamed after go-live.
  • Slack integration requires the bot to have the chat:write and users:read OAuth scopes. The bot must be invited to the finance channel and added as a contact by each department head before the first live cycle.
  • Dedupe logic: the agent must check reminder_count before sending. If a 48h reminder has already been sent for a given department in the current cycle, the 24h reminder fires but no additional 48h message is created. If a submission is received after a reminder is sent, the status column update suppresses any further messages for that department.
  • Fallback: if a slack_user_id cannot be resolved, the agent logs the failure to the error_log tab and sends a fallback Slack message to the finance channel naming the unresolved department.
  • The cycle_label field (e.g. Q1 2025) must be set at cycle open and stored in the config tab of the master sheet. This label is injected into every reminder message and every log entry.
  • Confirm with the finance manager: what is the correct Slack channel for the fallback alert? This must be agreed before build.
Budget Consolidation Agent

Ingests all validated Google Form responses once the submission deadline passes or all departments have submitted, whichever comes first. The agent maps each line item to the correct cost centre using a lookup table stored in the master sheet config tab, runs rule-based checks for missing required fields and variance thresholds against prior period actuals pulled from Xero via API, and writes the consolidated draft to the master budget tab. Lines that breach the configured variance threshold are flagged in a separate review_required column so the finance manager can inspect exceptions only, rather than checking every row.

Trigger
Fires when all submissions are received or the submission deadline timestamp passes, whichever comes first. Monitored via the submission_status column in the tracker tab.
Tools
Google Forms, Google Sheets, Xero
Replaces steps
Step 4: Collect and Validate Submissions (150 min); Step 5: Consolidate Into Master Budget (180 min); Step 6: Cross-Check Against Actuals in Xero (60 min)
Estimated build
22 hours | Complex
// Input
google_forms.response -> {
  department_name: string,
  cost_centre_code: string,
  line_items: [{ category: string, amount_usd: number, notes: string }],
  submitted_at: ISO8601,
  respondent_email: string
}
xero.api -> GET /reports/BalanceSheet | /reports/ProfitAndLoss -> {
  account_code: string,
  prior_period_actual_usd: number,
  period_label: string
}
google_sheets.config_tab -> {
  cost_centre_map: { category_label: string -> cost_centre_code: string },
  variance_threshold_pct: number,
  cycle_label: string
}

// Output
google_sheets.master_budget_tab -> {
  department_name: string,
  cost_centre_code: string,
  category: string,
  submitted_amount_usd: number,
  prior_period_actual_usd: number,
  variance_pct: number,
  review_required: boolean,
  validation_status: 'valid' | 'missing_fields' | 'flagged',
  consolidated_at: ISO8601
}
  • Xero API access requires OAuth 2.0 setup with the accounting.reports.read scope as a minimum. The Xero tenant ID must be stored in the credential store and confirmed before build begins. Do not proceed with agent build until OAuth is verified end to end.
  • The variance threshold percentage is a business decision that must be confirmed with the finance manager before build. The default placeholder during development is 15%. The final value is stored in the config tab and can be updated without a code change.
  • The cost centre mapping table in the config tab is the single source of truth for category-to-cost-centre resolution. If a form response contains a category label that does not exist in the map, the agent writes the row with validation_status set to missing_fields and flags it in the review_required column. It does not silently discard the row.
  • If the deadline passes before all submissions are received, the agent proceeds with available responses and logs each absent department in the error_log tab with status 'no_submission'. Finance is notified via Slack.
  • Xero API rate limit is 60 calls per minute per connection. The actuals pull should be batched by account code group, not made per line item, to stay within limits.
  • Google Forms responses are read via the Google Sheets integration (responses sheet), not via the Forms API directly. The responses tab name must be fixed and agreed before build.
  • Dedupe: the agent checks for a consolidated_at timestamp in the master_budget_tab before writing. If a row for a given department and cycle_label already exists, it overwrites rather than appending a duplicate.
  • Confirm with the finance manager: which Xero report type is the authoritative source for prior period actuals (Profit and Loss vs Balance Sheet by account code)? This determines the API endpoint used.
Approval Routing Agent

Fires when the finance manager marks the consolidated draft as cleared for approval by updating a designated cell in the master sheet. The agent generates the final budget summary document, creates a DocuSign envelope with the correct signatories and signing order drawn from the config tab, monitors signing progress, and handles fallback if a signer is unavailable within the configured timeout window. Once all signatures are collected, it saves the completed document to the correct Google Drive folder for the current cycle and posts a Slack completion notice to the finance channel.

Trigger
Fires when the finance manager updates the approval_status cell in the master sheet to 'cleared_for_approval'.
Tools
Google Sheets, DocuSign, Google Drive, Slack
Replaces steps
Step 8: Send Draft for Management Review (20 min); Step 10: Obtain Final Sign-Off via DocuSign (30 min); Step 11: Archive Signed Budget and Notify Team (25 min)
Estimated build
14 hours | Moderate
// Input
google_sheets.master_budget_tab -> {
  approval_status: 'cleared_for_approval',
  cycle_label: string,
  consolidated_at: ISO8601
}
google_sheets.config_tab -> {
  signing_order: [{ signer_name: string, signer_email: string, order: number }],
  fallback_signer_email: string,
  signing_timeout_hours: number,
  drive_folder_id: string,
  slack_finance_channel: string
}

// On approval trigger
docusign.envelope -> {
  envelope_id: string,
  document_name: string,
  signers: [{ email: string, name: string, routing_order: number }],
  status: 'sent' | 'completed' | 'declined' | 'voided'
}

// Output
google_drive.file -> {
  file_id: string,
  file_name: string,
  folder_id: string,
  archived_at: ISO8601
}
google_sheets.master_budget_tab -> {
  approval_status: 'approved',
  docusign_envelope_id: string,
  signed_at: ISO8601,
  drive_file_id: string
}
slack.channel_message -> {
  channel: slack_finance_channel,
  message_template: 'budget_approved',
  cycle_label: string,
  drive_link: url
}
  • DocuSign account must be on an Individual plan or above with API access enabled. The integration key (client ID) and RSA private key must be generated in the DocuSign developer console and stored in the credential store before build. Confirm account tier with the process owner before starting this agent.
  • The signing order array in the config tab is the authoritative source for envelope construction. It must include at minimum: signer_name, signer_email, and order (integer, 1-based). The order must reflect the company delegation of authority policy confirmed by the finance manager.
  • Fallback behaviour: if a signer does not complete within signing_timeout_hours, the agent voids the envelope, logs the event to the error_log tab, and posts a Slack alert to the finance channel with the name of the blocking signer and the elapsed time. It does not automatically substitute the fallback signer without a human decision.
  • The budget summary document is generated as a PDF from the master_budget_tab using a templated export. The document name format must be: Budget_[cycle_label]_[ISO8601 date]_DRAFT.pdf before signing and Budget_[cycle_label]_[ISO8601 date]_SIGNED.pdf after envelope completion.
  • Google Drive folder structure must be agreed before build. The recommended structure is: /Budgets/[Year]/[cycle_label]/. The drive_folder_id in the config tab must point to the correct parent folder. The agent creates the cycle subfolder if it does not exist.
  • If the DocuSign envelope status returns 'declined', the agent sets approval_status back to 'review_required' in the master sheet, logs the declination reason (from the DocuSign webhook payload), and alerts the finance channel via Slack.
  • Confirm with the finance manager: how many signatories are required and in what order? This is the single most important configuration decision for this agent and must be resolved before build week 3 begins.
Developer Handover PackPage 2 of 4
FS-DOC-04Technical

03End-to-end data flow

Full trigger-to-output data flow: Budget Planning and Approval
// ── TRIGGER ──────────────────────────────────────────────────────────────
// Scheduled trigger fires at cycle open date stored in config_tab
google_sheets.config_tab -> {
  cycle_label: 'Q1 2025',
  cycle_open_date: '2025-01-08',
  submission_deadline: '2025-01-20T17:00:00Z',
  department_list: ['Finance', 'Operations', 'Sales', 'Marketing', 'Engineering', 'HR'],
  variance_threshold_pct: 15,
  signing_order: [{name:'Rachel Horton', email:'rh@...', order:1}, {name:'Daniel Chu', email:'dc@...', order:2}],
  drive_folder_id: '1AbcXYZ...',
  slack_finance_channel: '#finance-budget'
}

// ── STEP 1: Form distribution ────────────────────────────────────────────
// Automation sends personalised Google Form link to each department head
google_forms.form_id -> pre_populate({
  department_name: string,         // from department_list
  prior_period_actual_usd: number  // pulled from xero at cycle open
})
-> delivery: email + slack_direct_message to each department head

// ── AGENT HANDOFF 1: Submission Coordinator Agent ────────────────────────
// Polls tracker_tab every 6 hours from cycle open until deadline
google_sheets.tracker_tab -> read {
  department_name: string,
  submission_status: 'pending' | 'submitted',
  slack_user_id: string,
  hours_until_deadline: number   // computed field: deadline - now()
}
// At 48h before deadline: fire 48h reminder for all status='pending'
// At 24h before deadline: fire 24h reminder for all status='pending'
slack.direct_message -> {
  recipient: slack_user_id,
  message_template: 'budget_reminder_48h' | 'budget_reminder_24h',
  form_link: url,
  cycle_label: 'Q1 2025'
}
// Write back to tracker_tab
google_sheets.tracker_tab -> write {
  reminder_sent_at: ISO8601,
  reminder_count: number,
  last_reminder_type: '48h' | '24h'
}

// ── DEPARTMENT SUBMISSION ────────────────────────────────────────────────
// Each department submits via Google Form
google_forms.response -> {
  department_name: string,
  cost_centre_code: string,
  line_items: [{category: string, amount_usd: number, notes: string}],
  submitted_at: ISO8601,
  respondent_email: string
}
// Form response written automatically to responses_tab in master sheet
google_sheets.tracker_tab -> update { submission_status: 'submitted', submitted_at: ISO8601 }

// ── AGENT HANDOFF 2: Budget Consolidation Agent ──────────────────────────
// Fires when all status='submitted' OR deadline timestamp passes
google_forms.responses_tab -> read all rows for cycle_label
// Validate each row
validate({
  required_fields: ['department_name','cost_centre_code','line_items'],
  missing_field_action: 'flag_as missing_fields, set review_required=true'
})
// Pull Xero actuals
xero.api -> GET /reports/ProfitAndLoss?fromDate=...&toDate=... -> {
  account_code: string,
  prior_period_actual_usd: number
}
// Map categories to cost centres
google_sheets.config_tab.cost_centre_map -> resolve {
  category_label -> cost_centre_code
  // unresolved: validation_status='missing_fields', review_required=true
}
// Compute variance
variance_pct = ((submitted_amount_usd - prior_period_actual_usd) / prior_period_actual_usd) * 100
review_required = abs(variance_pct) > variance_threshold_pct
// Write consolidated output
google_sheets.master_budget_tab -> write {
  department_name, cost_centre_code, category,
  submitted_amount_usd, prior_period_actual_usd,
  variance_pct, review_required,
  validation_status: 'valid' | 'missing_fields' | 'flagged',
  consolidated_at: ISO8601
}
// Log absent departments
google_sheets.error_log_tab -> write {
  department_name: string,
  status: 'no_submission',
  logged_at: ISO8601
}

// ── HUMAN STEP: Finance Manager reviews flagged lines ────────────────────
// Finance Manager inspects rows where review_required=true
// Adjusts amounts or notes in master_budget_tab directly
// When satisfied, updates:
google_sheets.master_budget_tab -> write {
  approval_status: 'cleared_for_approval'   // triggers Approval Routing Agent
}

// ── AGENT HANDOFF 3: Approval Routing Agent ──────────────────────────────
// Fires on approval_status change to 'cleared_for_approval'
// Generate PDF summary from master_budget_tab
document.generate -> {
  file_name: 'Budget_Q1 2025_2025-01-28_DRAFT.pdf',
  source: google_sheets.master_budget_tab
}
// Create DocuSign envelope
docusign.api -> POST /envelopes -> {
  envelope_id: string,
  document: { name: 'Budget_Q1 2025_DRAFT.pdf', file_base64: string },
  signers: [
    { email: 'rh@...', name: 'Rachel Horton', routing_order: 1 },
    { email: 'dc@...', name: 'Daniel Chu',   routing_order: 2 }
  ],
  status: 'sent'
}
// DocuSign webhook fires on envelope status change
docusign.webhook -> {
  envelope_id: string,
  status: 'completed' | 'declined' | 'voided'
}
// On 'completed':
docusign.api -> GET /envelopes/{envelope_id}/documents -> signed_pdf_blob
// Archive to Google Drive
google_drive.api -> POST /files -> {
  file_name: 'Budget_Q1 2025_2025-01-30_SIGNED.pdf',
  parent_folder_id: drive_folder_id,
  file_id: string
}
// Update master sheet
google_sheets.master_budget_tab -> write {
  approval_status: 'approved',
  docusign_envelope_id: string,
  signed_at: ISO8601,
  drive_file_id: string
}
// Notify finance channel
slack.channel_message -> {
  channel: '#finance-budget',
  message_template: 'budget_approved',
  cycle_label: 'Q1 2025',
  drive_link: 'https://drive.google.com/file/d/{file_id}'
}

// ── END ──────────────────────────────────────────────────────────────────
Developer Handover PackPage 3 of 4
FS-DOC-04Technical

04Recommended build stack

Orchestration layer
A workflow automation tool configured with one workflow per agent (three workflows total): Submission Coordinator, Budget Consolidation, and Approval Routing. All three workflows share a single credential store holding the Google Workspace service account key, Xero OAuth 2.0 tokens, DocuSign integration key and RSA private key, and the Slack bot token. Credentials are referenced by name within each workflow and are never hardcoded inline. A fourth utility workflow handles error log writes and Slack alert dispatch, called by the other three workflows via an internal webhook.
Webhook configuration
Two inbound webhooks are required. First: a DocuSign Connect webhook registered in the DocuSign admin console, pointing to the orchestration layer's public webhook URL, subscribed to the envelope-completed, envelope-declined, and envelope-voided event types. The payload must include envelope_id and status. Second: a Google Sheets onChange trigger (via Apps Script or the Sheets API push notification channel) on the master_budget_tab to detect when approval_status is updated to 'cleared_for_approval', firing the Approval Routing Agent workflow. Both webhook endpoints must be secured with a shared secret verified in the workflow before processing the payload.
Templating approach
Slack message templates (budget_reminder_48h, budget_reminder_24h, budget_approved) are stored as plain-text templates in the config tab of the master sheet with named placeholders (e.g. {{cycle_label}}, {{form_link}}, {{drive_link}}). The orchestration layer performs string interpolation at send time. The budget summary PDF is generated using a Google Slides or Google Docs template stored in Google Drive, with named placeholders replaced via the Google Docs API before export to PDF. The template document ID is stored in the config tab.
Error logging
All agent errors, fallback events, and unresolved lookups are written to a dedicated error_log_tab in the master Google Sheet with columns: logged_at (ISO8601), agent_name, error_type, affected_record, error_detail, resolved (boolean). In addition, any error that blocks a downstream agent (e.g. Xero API failure, DocuSign envelope creation failure) triggers an immediate Slack alert to the #finance-budget channel via the utility workflow. A Supabase table named budget_automation_error_log mirrors critical errors for longer-term audit and is updated by the utility workflow after each Slack alert.
Testing approach
All three agents are built and tested in a sandbox environment first. The Google Sheets master file is duplicated into a test workspace. Xero API calls use the Xero demo company tenant during development. DocuSign envelopes are sent using the DocuSign sandbox (demo.docusign.net) with test signer accounts. Slack messages are sent to a private #budget-automation-test channel. Once all three agents pass sandbox testing individually, a full dry-cycle test is run using historical submission data from a prior budget period, simulating the complete trigger-to-archive journey before any live cycle is processed.
Estimated total build time
Submission Coordinator Agent: 8 hours. Budget Consolidation Agent: 22 hours. Approval Routing Agent: 14 hours. End-to-end integration testing and dry-cycle run: 4 hours. Total: 48 hours across a 4-week delivery schedule.
Three items must be confirmed before any agent build begins: (1) Xero OAuth 2.0 credentials and tenant ID verified end to end with the Xero account administrator. (2) The variance threshold percentage agreed with the finance manager and entered into the config tab. (3) The DocuSign signing order and fallback timeout policy confirmed against the company delegation of authority. If any of these three items is unresolved at the start of build week 2, the Budget Consolidation and Approval Routing agents will be blocked. Contact support@gofullspec.com if access confirmation is delayed.
Developer Handover PackPage 4 of 4

More documents for this process

Every document generated for Budget Planning & Approval.

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