FS-DOC-04Technical
Developer Handover Pack
Proposal & SOW Creation
Process
Proposal & SOW Creation
Build option
Standard (recommended)
Total build effort
60 hours across 4 weeks
Automation volume
~25 proposals/month
Annual saving
$17,200/year
01Process snapshot
The current-state process runs across six manual steps totalling 245 minutes per proposal. At ~25 proposals/month the Account Lead role absorbs the majority of that time. Three steps are flagged as bottlenecks: effort estimation, proposal drafting, and SOW drafting. These three steps account for 165 of the 245 minutes and are the primary automation targets. One manual review gate (Internal Pricing Review) is retained by design.
#
Step
Owner
Tool
Time (min)
Bottleneck
Automated by
1
Review Scoping Notes
Account Lead
HubSpot
25
No
Scope Extraction Agent
2
Build Effort Estimate
Account Lead
Google Sheets
40
Yes
Estimate & Proposal Agent
3
Write Proposal Draft
Account Lead
Google Docs
70
Yes
Estimate & Proposal Agent
4
Draft Statement Of Work
Delivery Lead
Google Docs
55
Yes
Estimate & Proposal Agent
5
Internal Pricing Review
Studio Owner
None
30
No
Human gate (retained)
6
Format And Send
Account Lead
PandaDoc
25
No
Send & Track Agent
Metric
Current state
After automation
Time per proposal
8 hrs
1.5 hrs
Annual staff cost
$22,900
$5,700
Pricing consistency
Varies
Rate-card locked
Manual steps
6 of 6
1 of 6 (review only)
Steps eliminated: 5 of 6. Steps retained with human ownership: 1 (Internal Pricing Review). The 6-hour/week saving and $17,200/year figure are derived from 25 proposals/month at $55/hour.
Developer Handover PackPage 1 of 4
FS-DOC-04Technical
02Agent specifications
Scope Extraction Agent
Reads the scoping notes recorded against a HubSpot deal and extracts modules, assumptions, constraints, and any open questions into a structured JSON scope object. The output is stored back on the HubSpot deal record and passed to the Estimate & Proposal Agent. No LLM hallucination risk on pricing at this stage as no numbers are produced here.
Trigger
Deal stage in HubSpot transitions to 'Scoping Call Done' (webhook or polling interval: 5 min)
Tools
HubSpot (read deal notes), FullSpec Automation (orchestration)
Replaces steps
Step 1: Review Scoping Notes (25 min)
Build time
Week 1 to 2 (approx. 12 hours)
Implementation notes
Map HubSpot note body field to extraction prompt. Store output as a custom deal property (scope_json). Validate that all required keys are present before triggering downstream agent. Flag incomplete extractions for manual review.
// Input
HubSpot deal ID + associated note body text
deal.properties.hs_latest_meeting_activity (note body)
deal.properties.dealname
// Processing
LLM extraction prompt -> structured scope object
Keys: modules[], assumptions[], constraints[], open_questions[]
// Output
deal.properties.scope_json = { modules, assumptions, constraints, open_questions }
deal.properties.scope_status = 'ready' | 'incomplete'
Trigger: POST /estimate-agent with deal_id and scope_jsonEstimate & Proposal Agent
Receives the structured scope object, applies the stored rate card to each module, produces a line-item effort estimate, and then generates a full proposal document and matching SOW using the approved Google Docs templates. Outputs two drafted documents on the deal record. If the calculated total falls outside the pricing range threshold a flag is raised for the Studio Owner review gate before the Send & Track Agent is triggered.
Trigger
scope_json written to HubSpot deal with scope_status = 'ready'
Tools
Google Docs (proposal and SOW templates), FullSpec Automation (orchestration and rate-card logic)
Replaces steps
Step 2: Build Effort Estimate (40 min), Step 3: Write Proposal Draft (70 min), Step 4: Draft Statement Of Work (55 min)
Build time
Week 2 to 3 (approx. 22 hours)
Implementation notes
Rate card must be stored as a versioned config file (JSON or Google Sheet). Use Google Docs template copy-and-fill approach via the Docs API (not Drive copy alone). Implement a pricing ceiling threshold (configurable, default: +20% above rate-card midpoint) to trigger the human review gate. SOW template must use named placeholders matching the scope_json keys.
// Input
deal_id + scope_json from Scope Extraction Agent
rate_card config: { module_name, hours_low, hours_high, day_rate }
Google Docs template IDs: proposal_template_id, sow_template_id
// Processing
rate_card.apply(scope_json.modules) -> line_item_estimate[]
total_price = sum(line_item_estimate[].price)
pricing_in_range = total_price <= rate_card.ceiling
Google Docs API: copy template -> fill placeholders -> return doc_url
// Output
deal.properties.proposal_doc_url = '<Google Docs URL>'
deal.properties.sow_doc_url = '<Google Docs URL>'
deal.properties.estimate_total = total_price
deal.properties.pricing_flag = 'in_range' | 'review_required'
Trigger (if in_range): POST /send-track-agent with deal_id
Trigger (if review_required): Notify Studio Owner via HubSpot taskSend & Track Agent
Takes the approved proposal document, uploads it to PandaDoc, assigns signatories, and sends it to the prospect. Polls PandaDoc for document status updates (opened, signed, declined) and writes status back to the HubSpot deal record in real time. Triggers a follow-up task on the deal if the document has not been opened within 48 hours.
Trigger
Human review approved (pricing_flag = 'approved') OR pricing_flag = 'in_range' with no override pending
Tools
PandaDoc (document send and e-signature tracking), FullSpec Automation (orchestration and status sync)
Replaces steps
Step 6: Format And Send (25 min)
Build time
Week 3 to 4 (approx. 10 hours)
Implementation notes
Use PandaDoc API to create document from uploaded PDF or via template. Pull contact email from HubSpot deal contact association. Configure webhook endpoint in PandaDoc to push status events. Map PandaDoc status values (document.viewed, document.completed, document.declined) to HubSpot deal properties. 48-hour no-open follow-up task should be created via HubSpot Tasks API.
// Input
deal_id + proposal_doc_url + contact email from HubSpot
PandaDoc API key (workspace-scoped)
Signatory: deal.contacts[0].email, deal.contacts[0].firstname
// Processing
PandaDoc: POST /documents { file_url: proposal_doc_url, recipients: [contact] }
PandaDoc: POST /documents/{id}/send
PandaDoc webhook -> FullSpec listener -> parse event.type
// Output
deal.properties.pandadoc_document_id = '<PandaDoc doc ID>'
deal.properties.proposal_status = 'sent' | 'viewed' | 'signed' | 'declined'
deal.properties.proposal_sent_at = ISO8601 timestamp
HubSpot Task (if no open after 48 hrs): 'Follow up on proposal: {dealname}'Developer Handover PackPage 2 of 4
FS-DOC-04Technical
03End-to-end data flow
Full trigger-to-proposal data flow: Proposal & SOW Creation automation
// ============================================================
// TRIGGER
// ============================================================
HubSpot deal.stage -> 'Scoping Call Done'
Webhook: POST https://app.fullspec.io/hooks/inbound/proposal-sow
Payload: { deal_id, dealname, stage, timestamp }
// ============================================================
// STAGE 1: Scope Extraction Agent
// ============================================================
FullSpec receives webhook
-> HubSpot GET /deals/{deal_id}/notes
response: { note_body: '<raw scoping notes text>' }
-> LLM extraction prompt:
input: note_body
output: scope_json {
modules: ['Module A', 'Module B', ...],
assumptions: ['Assumption 1', ...],
constraints: ['Timeline: 6 weeks', ...],
open_questions: ['Q1', ...]
}
-> Validate: all keys present AND modules.length > 0
if INVALID -> HubSpot task: 'Scope extraction incomplete, manual review needed'
if VALID -> HubSpot PATCH /deals/{deal_id} { scope_json, scope_status: 'ready' }
// ============================================================
// STAGE 2: Estimate & Proposal Agent
// ============================================================
Trigger: scope_status = 'ready' on deal record
-> Load rate_card config (versioned JSON)
rate_card: [{ module, hours_low, hours_high, day_rate }, ...]
-> Apply rate card to scope_json.modules
line_items = modules.map(m => rate_card.match(m))
total_price = sum(line_items[].price)
-> Pricing gate:
if total_price <= rate_card.ceiling
pricing_flag = 'in_range'
else
pricing_flag = 'review_required'
-> HubSpot Task: 'Review pricing for {dealname}'
-> PAUSE until deal.properties.pricing_approval = 'approved'
-> Google Docs API:
POST /documents/{proposal_template_id}/copy -> new_proposal_doc_id
POST /documents/{sow_template_id}/copy -> new_sow_doc_id
Batch update: fill named placeholders with scope_json + line_items
-> HubSpot PATCH /deals/{deal_id} {
proposal_doc_url, sow_doc_url,
estimate_total, pricing_flag
}
// ============================================================
// STAGE 3: Human Review Gate (retained by design)
// ============================================================
Studio Owner reviews proposal_doc_url + sow_doc_url
Sets: deal.properties.pricing_approval = 'approved' | 'rejected'
if 'rejected' -> process terminates, task created for Account Lead
if 'approved' -> pipeline continues to Send & Track Agent
// ============================================================
// STAGE 4: Send & Track Agent
// ============================================================
Trigger: pricing_approval = 'approved' OR pricing_flag = 'in_range'
-> HubSpot GET /deals/{deal_id}/contacts
contact: { email, firstname, lastname }
-> PandaDoc POST /documents {
file_url: proposal_doc_url,
recipients: [{ email, firstname, lastname, role: 'signer' }]
}
response: { pandadoc_document_id }
-> PandaDoc POST /documents/{pandadoc_document_id}/send
-> HubSpot PATCH /deals/{deal_id} {
pandadoc_document_id,
proposal_status: 'sent',
proposal_sent_at: ISO8601
}
// ============================================================
// STAGE 5: Status Tracking (PandaDoc -> HubSpot sync)
// ============================================================
PandaDoc webhook -> POST https://app.fullspec.io/hooks/pandadoc/status
event.type = 'document.viewed' -> deal.proposal_status = 'viewed'
event.type = 'document.completed'-> deal.proposal_status = 'signed'
event.type = 'document.declined' -> deal.proposal_status = 'declined'
-> HubSpot Task: 'Proposal declined: {dealname}'
48-hour check (scheduled job):
if proposal_status = 'sent' AND now - proposal_sent_at > 172800s
-> HubSpot Task: 'Follow up on proposal: {dealname}'
// ============================================================
// TERMINAL OUTPUT
// ============================================================
deal.stage -> 'Proposal Sent'
deal.properties: { proposal_status, pandadoc_document_id, estimate_total, proposal_sent_at }04Security and compliance requirements
#
Requirement
Detail
Tool / Layer
Status
1
OAuth 2.0 for HubSpot
Use HubSpot private app token with minimum required scopes: crm.objects.deals.read, crm.objects.deals.write, crm.objects.contacts.read, crm.objects.notes.read
HubSpot
To confirm
2
Google OAuth scopes
Request only: https://www.googleapis.com/auth/documents and https://www.googleapis.com/auth/drive.file. Do not request full Drive access.
Google Docs API
To confirm
3
PandaDoc API key rotation
Workspace-level API key stored in secrets manager. Rotate every 90 days. Never hardcode in workflow config.
PandaDoc
To confirm
4
Secrets management
All credentials stored in FullSpec Automation credential vault or equivalent (e.g. environment variables on the host). No credentials in workflow JSON or version control.
FullSpec Automation
To confirm
5
Proposal document access control
Generated Google Docs set to 'restricted' (no link sharing). Access granted only to deal owner and Studio Owner. Revoke after signing.
Google Docs
To confirm
6
Scoping note data residency
HubSpot note body may contain prospect PII (name, company, budget). Confirm that LLM extraction endpoint does not persist input data beyond the API call. Use a zero-data-retention API tier if available.
LLM provider
To confirm
7
Webhook endpoint authentication
FullSpec inbound webhook URLs must be protected by a shared secret header (X-FullSpec-Signature). Validate HMAC-SHA256 signature on all inbound payloads.
FullSpec Automation
To confirm
8
PandaDoc webhook verification
Validate PandaDoc webhook payloads using the X-Pandadoc-Signature header and the workspace webhook secret. Reject unsigned payloads with HTTP 401.
PandaDoc / FullSpec
To confirm
9
Rate card config access
Rate card JSON must be stored in a version-controlled, access-controlled location. Only Studio Owner role can modify. Changes should trigger a config reload event, not a full redeploy.
FullSpec Automation
To confirm
10
Audit logging
Log all agent trigger events, document creation events, and status changes with timestamp, deal_id, and actor (agent name or user). Retain logs for minimum 12 months.
FullSpec Automation
To confirm
11
Error and failure alerting
Failed extraction, document generation errors, or PandaDoc send failures must trigger an immediate notification to the Account Lead and create a HubSpot task. No silent failures permitted.
FullSpec Automation / HubSpot
To confirm
12
Data minimisation
Scope extraction output (scope_json) must not include free-text budget figures or personal financial data from notes. Strip or mask before writing to deal properties.
Scope Extraction Agent
To confirm
All rows are marked 'To confirm' pending a security review with [YourCompany.com]. The developer must walk through each row with the process owner before going to production.
Developer Handover PackPage 3 of 4
FS-DOC-04Technical
05Pre-build checklist
The checklist below is split into two groups. Items in the first group must be provided by the client before the developer can begin. Items in the second group are the developer's responsibility to configure and verify during the foundation week.
Client to provide: the following items must be ready before Week 1 begins. Delays in access or assets will push the build timeline.
HubSpot private app token : Created by a HubSpot Super Admin. Scopes required: crm.objects.deals.read/write, crm.objects.contacts.read, crm.objects.notes.read, timeline events.
Existing rate card document : Provide the current rate card in any format (Google Sheet, spreadsheet, PDF). Developer will convert to config JSON.
Google Docs proposal template : Share the master proposal template Google Doc with the service account or OAuth app. Named placeholders should be agreed in advance.
Google Docs SOW template : Share the master SOW template Google Doc. Confirm all variable fields (client name, modules, price, dates) are identified.
PandaDoc workspace API key : Generated from PandaDoc Settings > API. Confirm the PandaDoc subscription tier supports API access (Business tier or above).
HubSpot deal stage naming : Confirm the exact deal stage label that represents a completed scoping call (e.g. 'Scoping Call Done'). Developer will configure the webhook filter against this label.
Pricing ceiling threshold : Confirm the numeric threshold above which proposals require Studio Owner review before sending (e.g. $10,000 or +20% of midpoint estimate).
Signatory contact field confirmation : Confirm which HubSpot contact association field holds the primary prospect signatory email (default: associated contact primary email).
Developer to set up: the following items are the developer's responsibility during the foundation and build phases.
Provision FullSpec Automation workspace : Create a dedicated workspace for [YourCompany.com]. Do not reuse a shared workspace. Set environment to Production after QA is complete.
Configure HubSpot credential in FullSpec : Add HubSpot private app token to the FullSpec credential vault. Label: 'HubSpot - YourCompany Production'. Test connection before building workflows.
Configure Google OAuth in FullSpec : Set up Google OAuth 2.0 with the minimum scopes listed in Section 04. Verify token refresh is working. Store refresh token in credential vault.
Configure PandaDoc API credential : Add PandaDoc API key to credential vault. Label: 'PandaDoc - YourCompany Production'. Test by fetching document list via GET /documents.
Register inbound webhook endpoint : Create the FullSpec inbound webhook URL for the HubSpot deal stage trigger. Copy the HMAC secret and provide it to the client for HubSpot webhook registration.
Register PandaDoc outbound webhook : In PandaDoc Settings > Webhooks, register the FullSpec listener URL for document.viewed, document.completed, and document.declined events.
Build rate card config JSON : Convert the client-provided rate card into the versioned config JSON format. Store in a version-controlled repository and load path into FullSpec config.
Clone and parameterise Google Docs templates : Make working copies of the proposal and SOW templates. Replace variable fields with named placeholders matching scope_json keys. Test copy-and-fill via Docs API before connecting to the agent.
Configure 48-hour follow-up scheduled job : Set up the scheduled polling job in FullSpec that checks for proposals with status 'sent' and no open event after 48 hours, then creates a HubSpot follow-up task.
Verify audit logging is enabled : Confirm FullSpec audit log is active for the workspace. Test that trigger events, document creation, and status sync events all appear in the log with correct metadata.
06Recommended build stack
Tool
Role in build
Monthly cost
Auth method
Notes
FullSpec Automation
Orchestration, agent hosting, scheduling, credential vault, audit logging
$159/month
Platform login + HMAC webhook secrets
Primary build environment. Standard tier recommended.
HubSpot
CRM trigger source, deal and contact data, task creation, status sync
$0 (existing)
Private app token (OAuth-scoped)
Confirm Super Admin access before build starts.
Google Docs
Proposal and SOW template generation via Docs API
$0 (existing)
OAuth 2.0, documents + drive.file scopes
Template IDs required before Stage 2 build.
PandaDoc
E-signature send, document status tracking via webhooks
$25/month
Workspace API key
Business tier or above required for API access.
LLM provider (via FullSpec)
Scope extraction from unstructured note text
Included in FullSpec tier
Managed by FullSpec Automation
Zero-data-retention mode required. Confirm with provider.
Google Sheets (config)
Rate card storage during initial build; migrated to JSON config post-QA
$0 (existing)
OAuth 2.0 (same credential as Docs)
Optional: replace with versioned JSON file in repo.
Total estimated build effort
60 hours
Recommended build option
Standard
Build timeline
4 weeks (Weeks 1 to 4)
Week 1
Foundation and integrations: provision environment, connect all tools, verify credentials and webhooks (approx. 10 hours)
Weeks 1 to 2
Scope Extraction Agent: build, prompt tuning, HubSpot integration, output validation (approx. 12 hours)
Weeks 2 to 3
Estimate & Proposal Agent: rate card logic, Google Docs template fill, pricing gate, human review routing (approx. 22 hours)
Weeks 3 to 4
Send & Track Agent: PandaDoc send, webhook status sync, 48-hour follow-up job (approx. 10 hours)
Week 4
End-to-end QA and launch: regression testing, stakeholder sign-off, go-live, monitoring setup (approx. 6 hours)
Build cost (Standard)
$4,200 one-off
The 60-hour estimate assumes all client-provided assets (credentials, templates, rate card) are ready at Week 1 kickoff. Delays in access will extend the timeline proportionally. The LLM extraction prompt will require a short tuning period against real scoping notes before QA sign-off.
Developer Handover PackPage 4 of 4