Back to Insurance Renewal 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

Insurance Renewal Management

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

This document is the authoritative technical reference for the Insurance Renewal Management automation build. It covers the current-state process map with bottleneck identification, full specifications for each of the three agents, an end-to-end data flow trace, and the recommended build stack. The FullSpec team is responsible for the entire build, test, and deployment cycle. Your team's input is limited to confirming tool access, supplying broker contact data, and validating the policy register schema before build begins.

01Process snapshot

Step
Name
Description
1
Check Policy Register for Upcoming Expiries
Compliance Manager manually scans the Notion database for policies expiring within 90 days. Often done monthly, sometimes skipped entirely. Time cost: 20 min/cycle.
2
Email Broker to Request Renewal Quote
Renewal request email drafted and sent manually to the broker per policy. No standard template; wording and detail vary each time. Time cost: 15 min/cycle.
3
Chase Broker If No Quote Received
Follow-up email sent manually if the broker has not replied within a week. Frequently forgotten, allowing deadlines to creep. BOTTLENECK. Time cost: 10 min/cycle.
4
Receive and File Broker Quote
Quote arrives by email, downloaded, renamed, saved to shared drive, and cross-referenced with prior year policy. Time cost: 15 min/cycle.
5
Compare New Quote Against Prior Coverage
Manager reads both documents and manually records changes in premium, excess, exclusions, or coverage limits. BOTTLENECK. Time cost: 25 min/cycle.
6
Prepare Approval Summary for Sign-Off
Short summary email or document prepared for the CFO outlining premium change, coverage differences, and recommendation. Time cost: 20 min/cycle.
7
Route to CFO or Owner for Approval
Summary emailed to approver. No response within 48 hours requires manual chase. Approval sometimes given verbally with no written record. BOTTLENECK. Time cost: 30 min/cycle.
8
Notify Broker of Acceptance
Manager replies to broker confirming acceptance once CFO approval received. Time cost: 10 min/cycle.
9
Receive and Review Policy Documents
New policy documents reviewed against the quote; discrepancies flagged back to broker. Time cost: 20 min/cycle.
10
Arrange Payment with Accounts
Invoice forwarded to accounts with due date note. Tight payment terms can make this disruptive. Time cost: 15 min/cycle.
11
Update Policy Register with New Details
Notion database updated with new policy number, premium, coverage dates, and next renewal date. Time cost: 15 min/cycle.
12
File Signed Policy Documents
Finalised documents saved to Google Drive and linked in the policy register. Time cost: 10 min/cycle.
Time cost summary: Total manual time per renewal cycle is 205 minutes (approximately 3 hours 25 minutes). At a run rate of 6 to 20 policies per year clustered into 2 to 4 peak periods, this produces a weekly average of 3.5 manual hours and an annual cost of $9,100 at $50/hour. The automation replaces steps 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, and 12 entirely. Step 9 (Receive and Review Policy Documents) remains a human touchpoint only where a material coverage discrepancy is flagged by the Quote Comparison Agent.
Developer Handover PackPage 1 of 4
FS-DOC-04Technical

02Agent specifications

Renewal Tracker Agent

Monitors the Notion policy register on a daily schedule and identifies any policy record whose expiry date falls within the 90-day, 60-day, 30-day, or 7-day warning windows. For each matching record, the agent fires a staged outreach email to the designated broker contact via Gmail, logs the outreach event in HubSpot as a contact activity against the broker record, starts a 7-day chase timer in HubSpot, and posts a Slack notification to the compliance channel confirming outreach status. If the chase timer expires with no quote logged, the agent sends a follow-up email automatically and resets the timer. This cycle repeats until a quote document is received or the policy is manually marked as resolved. Complexity: Moderate. Estimated build: 8 hours.

Trigger
Notion daily schedule poll; policy record expiry_date enters a 90-day, 60-day, 30-day, or 7-day window.
Tools
Notion (read/write), Google Workspace Gmail (send), HubSpot (contact activity log + chase timer), Slack (post message)
Replaces steps
1, 2, 3
Estimated build
8 hours — Moderate
// Input
Notion DB row: { policy_id, policy_name, insurer, broker_email, expiry_date, last_outreach_date, status }
Trigger condition: (expiry_date - today) IN [90, 60, 30, 7] days AND status NOT IN ['quote_received', 'resolved']

// Output
Gmail: templated outreach email -> broker_email (policy_id, expiry_date, coverage_type in body)
HubSpot: create activity { contact: broker_email, type: 'renewal_outreach', policy_id, outreach_stage, timestamp }
HubSpot: set follow-up task { due: now + 7 days, policy_id, action: 'chase_email' }
Slack: post to #compliance-renewals { text: 'Outreach sent for [policy_name] expiring [expiry_date]. Stage: [outreach_stage].' }
Notion: update row { last_outreach_date: today, outreach_stage: '90d|60d|30d|7d' }
  • Notion API tier required: Notion integration with read and write access to the policy register database. The database must have a dedicated date property named expiry_date and a single-select status property. Confirm schema before build starts.
  • HubSpot tier required: Starter or above for contact activity logging and task creation via the CRM API. Free tier does not support task creation by API. Confirm tier before build.
  • Gmail send credentials must use a dedicated service account or OAuth token scoped to the sending mailbox. The token must have the gmail.send scope only. Do not use a personal account token.
  • Broker email addresses must be present on the Notion policy record or mapped to a HubSpot contact before build. A data-prep task is required to verify and populate these fields for all active policies.
  • Dedupe behaviour: if the daily poll fires and the policy has already received outreach at the current window stage today (last_outreach_date = today AND outreach_stage matches), the agent must skip that record without sending a duplicate email.
  • Fallback: if broker_email is null on a Notion record, post a Slack alert to #compliance-renewals with the policy_id and skip the outreach step. Do not fail silently.
  • Chase timer reset: after each follow-up email the HubSpot task due date is extended by 7 days. Maximum of 3 automated chases per window before escalating to a Slack alert for manual review.
Quote Comparison Agent

Activates when a broker quote document arrives in the designated Gmail intake label or is uploaded to the designated Google Drive intake folder. The agent reads the document using an AI extraction step, pulls premium, excess, exclusions, and coverage limit fields, and compares them line by line against the matching prior policy record stored in Notion. If any premium increase exceeds the configured threshold (default 10%) or any coverage term changes materially, the agent flags the record as requiring human review. Regardless of flag status, the agent assembles a structured comparison summary and posts it to the Slack compliance channel and attaches it to the approval workflow. The Notion record status is updated to quote_received. Complexity: Complex. Estimated build: 10 hours.

Trigger
New email in Gmail label 'Renewals/Intake' with attachment, OR new file in Google Drive folder '/Renewals/Intake/{year}'.
Tools
Google Workspace Gmail (read + label), Google Drive (read), Notion (read/write), Slack (post message)
Replaces steps
4, 5, 6
Estimated build
10 hours — Complex
// Input
Gmail attachment OR Drive file: { filename, mime_type ('application/pdf' | 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'), raw_bytes }
Notion prior policy record: { policy_id, prior_premium, prior_excess, prior_exclusions[], prior_coverage_limits{}, insurer, expiry_date }

// Output
Extracted quote fields: { quote_premium, quote_excess, quote_exclusions[], quote_coverage_limits{}, quote_effective_date, insurer_name }
Comparison delta: { premium_delta_pct, coverage_changes[], excess_delta, material_flag: true|false }
Slack: post to #compliance-renewals { comparison_summary_block, material_flag, policy_id, recommendation }
Notion: update row { status: 'quote_received', quote_file_url, comparison_summary_url, material_flag, quote_premium }

// On approval trigger
Passes { policy_id, comparison_summary_url, quote_file_url, approver_email, material_flag } to Approval and Completion Agent
  • AI document extraction must handle PDF (text-layer) and .docx formats reliably. Image-scanned PDFs (no text layer) require an OCR fallback step. During QA, test at least three real broker quote formats to confirm extraction confidence before go-live.
  • Premium threshold for material flag is configurable in the workflow as a variable (default: 10%). This must be exposed as a named parameter so the compliance team can update it without touching the workflow logic.
  • Coverage change detection compares string arrays for exclusions and numeric ranges for coverage limits. Any new exclusion string not present in the prior record triggers a material_flag regardless of premium delta.
  • Notion prior policy record must contain structured fields for prior_premium, prior_excess, and prior_coverage_limits. If any of these fields are empty, the agent must halt and post a Slack alert rather than producing an inaccurate comparison.
  • Google Drive intake folder path must be confirmed and the automation platform service account granted Editor access before build. Confirm folder naming convention with the client before build starts.
  • Fallback for unreadable documents: if AI extraction confidence score falls below 0.75, move the file to a /Renewals/Manual-Review folder, update the Notion record status to 'manual_review_required', and post a Slack alert.
  • The comparison summary document must be saved back to Google Drive and the URL stored in the Notion record so the Approval and Completion Agent can attach it to the DocuSign envelope.
Approval and Completion Agent

Triggered when the Quote Comparison Agent updates the Notion record to quote_received and posts the comparison summary to Slack. This agent routes the comparison summary and broker quote to the designated approver via DocuSign, attaches both documents to the envelope, and monitors for a signed response. On sign-off, the agent sends a confirmation acceptance email to the broker via Gmail, creates a draft bill in Xero assigned to the correct supplier record and account code, and writes all new policy details back to the Notion policy register, including the new policy number, premium, coverage dates, and the next renewal trigger date. The final Notion status is set to renewed. Complexity: Moderate. Estimated build: 8 hours.

Trigger
Notion policy record status transitions to 'quote_received' AND comparison_summary_url is populated.
Tools
DocuSign (envelope create + status poll), Google Workspace Gmail (send), Xero (bill create), Notion (read/write)
Replaces steps
7, 8, 10, 11, 12
Estimated build
8 hours — Moderate
// Input
Notion record: { policy_id, policy_name, approver_email, comparison_summary_url, quote_file_url, quote_premium, broker_email, insurer, xero_supplier_id, xero_account_code }

// Output (DocuSign sent)
DocuSign envelope: { signer: approver_email, documents: [comparison_summary, broker_quote], subject: 'Approval required: [policy_name] renewal', expiry: +48h }
Notion: update row { docusign_envelope_id, status: 'pending_approval' }

// On approval (DocuSign webhook: envelope status = 'completed')
Gmail: send to broker_email { body: 'We confirm acceptance of the renewal quote for [policy_name]. Please issue final policy documents and invoice.' }
Xero: POST /invoices { type: 'ACCPAY', contact_id: xero_supplier_id, line_items: [{ description: policy_name, unit_amount: quote_premium, account_code: xero_account_code }], status: 'DRAFT' }
Notion: update row { status: 'renewed', new_policy_number, new_expiry_date, next_renewal_trigger_date: new_expiry_date - 90d, renewed_premium: quote_premium, docusign_signed_url }
Slack: post to #compliance-renewals { text: '[policy_name] renewal confirmed. Xero bill drafted. Notion record updated.' }
  • DocuSign account must have API access enabled (eSignature REST API v2.1). The approver must have an active DocuSign user account or must be configured as a recipient who can sign via email link. Confirm with the client before build.
  • DocuSign envelope expiry should be set to 48 hours. If the envelope expires unsigned, the agent must post a Slack escalation alert to #compliance-renewals tagging the compliance manager and reset the envelope.
  • Xero bill creation requires the insurer to exist as a Supplier contact in Xero with a valid contact_id, and the correct account code to be confirmed for insurance expense. A data-prep task must verify and create these records for all active insurers before launch.
  • The Xero bill is created in DRAFT status only. Accounts payable staff retain responsibility for approving and scheduling payment in Xero. Do not configure the automation to submit or approve bills.
  • DocuSign webhook must be configured to POST the envelope completion event to the automation platform's webhook receiver endpoint. Do not use polling as the primary sign-off detection method; polling may be used as a fallback only.
  • next_renewal_trigger_date written to Notion must be exactly new_expiry_date minus 90 calendar days. This is the value the Renewal Tracker Agent reads on its next daily poll to initiate the following year's renewal cycle.
  • If DocuSign returns a declined status (approver declines to sign), update the Notion record status to 'approval_declined', post a Slack alert, and halt. Do not re-send the envelope automatically.
Developer Handover PackPage 2 of 4
FS-DOC-04Technical

03End-to-end data flow

Full trigger-to-output data flow — Insurance Renewal Management
// ─── TRIGGER ─────────────────────────────────────────────────────────────────
// Orchestration layer polls Notion daily at 07:00 UTC
Notion.query_database({
  filter: { property: 'expiry_date', date: { on_or_before: today + 90d } },
  filter_and: { property: 'status', select: { does_not_equal: 'renewed' } }
}) -> List<PolicyRecord>

// ─── AGENT 1: RENEWAL TRACKER AGENT ─────────────────────────────────────────
// Input fields consumed
PolicyRecord: {
  policy_id,         // Notion page ID
  policy_name,       // e.g. 'Public Liability 2025'
  insurer,           // e.g. 'Allianz'
  broker_email,      // e.g. 'renewals@brokerco.com'
  expiry_date,       // ISO 8601 date
  last_outreach_date,
  outreach_stage,    // '90d' | '60d' | '30d' | '7d'
  status             // 'active' | 'outreach_sent' | 'chasing' | ...
}

// Dedupe check: skip if outreach_stage matches today's window AND last_outreach_date = today
if (dedupe_check == false) {
  Gmail.send({ to: broker_email, template: 'renewal_request', vars: { policy_id, expiry_date, coverage_type } })
  HubSpot.create_activity({ contact: broker_email, type: 'renewal_outreach', policy_id, outreach_stage, timestamp: now })
  HubSpot.create_task({ due: now + 7d, policy_id, action: 'chase_email' })
  Slack.post({ channel: '#compliance-renewals', text: 'Outreach sent for [policy_name] expiring [expiry_date]. Stage: [outreach_stage].' })
  Notion.update_page({ policy_id, last_outreach_date: today, outreach_stage })
}

// Chase loop: HubSpot task fires at due date if status != 'quote_received'
// Maximum 3 chases per window; escalate to Slack on breach

// ─── AGENT HANDOFF 1 -> 2 ────────────────────────────────────────────────────
// Trigger: new email in Gmail label 'Renewals/Intake' OR new file in Drive '/Renewals/Intake/{year}'
// Extracted from email/file metadata: { policy_id (parsed from subject/filename), filename, mime_type, raw_bytes }

// ─── AGENT 2: QUOTE COMPARISON AGENT ────────────────────────────────────────
// AI extraction step
ai_extract(raw_bytes) -> QuoteFields: {
  quote_premium,         // numeric, e.g. 4200.00
  quote_excess,          // numeric
  quote_exclusions[],    // string array
  quote_coverage_limits, // object { public_liability, employers_liability, ... }
  quote_effective_date,  // ISO 8601
  insurer_name,
  extraction_confidence  // float 0.0 - 1.0
}

// Confidence gate: if extraction_confidence < 0.75 -> move to /Renewals/Manual-Review, Slack alert, halt

// Prior policy lookup
Notion.get_page(policy_id) -> PriorRecord: {
  prior_premium, prior_excess, prior_exclusions[], prior_coverage_limits{}
}

// Comparison delta
delta: {
  premium_delta_pct: ((quote_premium - prior_premium) / prior_premium) * 100,
  new_exclusions: quote_exclusions[].filter(e => !prior_exclusions[].includes(e)),
  limit_changes: diff(quote_coverage_limits, prior_coverage_limits),
  excess_delta: quote_excess - prior_excess
}
material_flag = (delta.premium_delta_pct > THRESHOLD_PCT) || (delta.new_exclusions.length > 0)

// Outputs
comparison_summary_doc -> saved to Google Drive '/Renewals/Summaries/{policy_id}_{date}.pdf'
Slack.post({ channel: '#compliance-renewals', blocks: [comparison_summary_block], material_flag })
Notion.update_page({ policy_id, status: 'quote_received', quote_file_url, comparison_summary_url, material_flag, quote_premium })

// ─── AGENT HANDOFF 2 -> 3 ────────────────────────────────────────────────────
// Trigger: Notion page status == 'quote_received' AND comparison_summary_url != null
// Passed fields: { policy_id, policy_name, approver_email, comparison_summary_url,
//                  quote_file_url, quote_premium, broker_email, insurer,
//                  xero_supplier_id, xero_account_code }

// ─── AGENT 3: APPROVAL AND COMPLETION AGENT ─────────────────────────────────
// DocuSign envelope creation
DocuSign.create_envelope({
  signer: { email: approver_email, name: 'CFO' },
  documents: [comparison_summary_url, quote_file_url],
  subject: 'Approval required: [policy_name] renewal',
  expiry_hours: 48
}) -> { envelope_id }
Notion.update_page({ policy_id, docusign_envelope_id, status: 'pending_approval' })

// DocuSign webhook fires on envelope completion
DocuSign.webhook_event: { envelope_id, status: 'completed', signed_document_url }

// On approval
Gmail.send({ to: broker_email, template: 'broker_acceptance', vars: { policy_name, policy_id } })
Xero.create_invoice({
  type: 'ACCPAY',
  contact_id: xero_supplier_id,
  line_items: [{ description: policy_name, unit_amount: quote_premium, account_code: xero_account_code }],
  status: 'DRAFT'
}) -> { xero_bill_id }
Notion.update_page({
  policy_id,
  status: 'renewed',
  renewed_premium: quote_premium,
  new_expiry_date: quote_effective_date + 365d,
  next_renewal_trigger_date: new_expiry_date - 90d,
  docusign_signed_url,
  xero_bill_id
})
Slack.post({ channel: '#compliance-renewals', text: '[policy_name] renewal confirmed. Xero bill drafted. Notion record updated.' })

// ─── TERMINAL STATE ──────────────────────────────────────────────────────────
// Notion status: 'renewed'
// Renewal cycle complete. next_renewal_trigger_date feeds Agent 1 in the following year.
Developer Handover PackPage 3 of 4
FS-DOC-04Technical

04Recommended build stack

Orchestration layer
A workflow automation tool configured with one discrete workflow per agent (three workflows total): Renewal Tracker Workflow, Quote Comparison Workflow, and Approval and Completion Workflow. All three workflows share a single credential store scoped per integration. No cross-workflow state is passed via the tool's internal data store; Notion serves as the shared state layer between agents, with the policy_id as the primary key across all records and handoff triggers.
Webhook configuration
Two inbound webhooks are required. (1) Gmail/Drive intake webhook: the Quote Comparison Workflow is triggered by a watch on the Gmail label 'Renewals/Intake' using the Gmail API push notification endpoint (pub/sub topic), with a fallback poll every 15 minutes. (2) DocuSign Connect webhook: the Approval and Completion Workflow listens on a registered DocuSign Connect endpoint for envelope status events (specifically: 'completed' and 'declined'). Both webhook receiver URLs must be HTTPS with a static path and must validate an HMAC signature header before processing. The credential store must hold the DocuSign Connect HMAC key and the Gmail pub/sub verification token.
Templating approach
All outbound emails (broker outreach, chase, and acceptance confirmation) use named templates stored as workflow variables, not hardcoded strings. Template variables include: policy_name, policy_id, expiry_date, outreach_stage, and broker_email. The comparison summary document is generated from a structured template that accepts the delta object fields and renders a PDF via a document generation step before being saved to Google Drive. The DocuSign envelope subject line and recipient name are also parameterised from the Notion record.
Error logging
All agent errors (extraction confidence failures, null broker_email, DocuSign API errors, Xero bill creation failures, Notion write failures) are written to a dedicated Supabase table with the columns: error_id (UUID), policy_id, agent_name, error_type, error_message, timestamp, resolved (boolean). A Slack alert is posted to #compliance-alerts for any new unresolved error row. The Supabase table is polled every 10 minutes; any error row with resolved = false and age > 60 minutes triggers a second Slack escalation. The FullSpec team will configure the Supabase project and share read access credentials with the process owner at handoff.
Testing approach
All three agents are built and validated in sandbox mode first. Notion: a parallel test database replicating the production schema is used for all build and QA runs. Gmail/Drive: a dedicated test Gmail account and Drive folder are used to inject test quote documents without affecting live broker communications. HubSpot: a sandbox environment or a dedicated test pipeline is used. DocuSign: the DocuSign Developer Sandbox is used for all approval flow testing before switching credentials to the production environment. Xero: the Xero Demo Company is used for bill creation tests. No production credentials are used until end-to-end QA is signed off.
Estimated total build time
Renewal Tracker Agent: 8 hours. Quote Comparison Agent: 10 hours. Approval and Completion Agent: 8 hours. End-to-end integration testing and QA: 2 hours. Total: 28 hours. This matches the confirmed build effort in the project spec. Build is scoped across 4 weeks per the delivery plan, with agents built in parallel from week 2 onward.
Pre-build confirmation checklist: (1) Notion policy register schema must be confirmed and all active policies migrated to it before Agent 1 build starts. (2) Broker email addresses must be populated on all Notion records. (3) HubSpot tier must be Starter or above (API task creation required). (4) DocuSign account must have eSignature API access enabled and the approver's account confirmed. (5) Xero must have a Supplier contact and account code for every active insurer. (6) Google Drive intake folder path and Gmail label name must be confirmed. (7) Supabase project must be provisioned before end-to-end testing begins. Raise any blockers to support@gofullspec.com before the build window opens.
Developer Handover PackPage 4 of 4

More documents for this process

Every document generated for Insurance Renewal 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