Developer Handover Pack
Everything needed to build the automation from scratch: current state, full agent specs, data flow, and the build stack.
Developer Handover Pack
Contract Generation & Management
[YourCompany.com] · Legal Department · Prepared by FullSpec · [Today's Date]
This document is the authoritative technical reference for building the Contract Generation and Management automation. It covers the current-state process map, full agent specifications with IO definitions, the end-to-end data flow, and the recommended build stack. The FullSpec team owns everything described here from initial configuration through to go-live testing. Your team's responsibility is limited to confirming HubSpot field enforcement, supplying clean contract templates, and completing the internal approval step during live operation. Questions should be directed to support@gofullspec.com.
01Process snapshot
02Agent specifications
Fires the moment a HubSpot deal stage transitions to Closed Won. The agent reads the full deal record, selects the correct contract template from the Google Drive template library based on the deal's service_type field, and merges all variable fields including party names, entity type, start date, fee schedule, and payment terms into a new document copy. If any mandatory field is missing or returns a null value the agent halts, logs the incomplete record, and sends a Gmail flag to the assigned account manager rather than producing a partial draft. Once population is complete the draft is saved to a standardised path in Google Drive and an approval request is dispatched to the responsible manager.
// Input hubspot.deal.id : string // unique deal ID from webhook payload hubspot.deal.dealname : string hubspot.deal.contact.email : string hubspot.deal.contact.name : string hubspot.deal.company.name : string hubspot.deal.company.entity_type : string hubspot.deal.service_type : string // used for template selection hubspot.deal.start_date : ISO8601 date hubspot.deal.fee_amount : number // USD hubspot.deal.payment_terms : string hubspot.deal.jurisdiction : string // Output (success path) gdrive.draft.file_id : string // Google Drive file ID of populated draft gdrive.draft.file_url : string // shareable review link gdrive.draft.file_name : string // e.g. DRAFT_AcmeCorp_ServiceAgreement_2025-06-01 gmail.approval_request.sent : boolean gmail.approval_request.to : string // manager email resolved from deal owner // Output (missing field path) agent.status : 'INCOMPLETE_RECORD' agent.missing_fields : string[] // list of null field names gmail.flag_sent_to : string // assigned account manager email
- HubSpot tier requirement: the workflow trigger requires HubSpot Sales Hub Starter or above. Free tier does not expose deal-stage webhook events. Confirm subscription before build starts.
- Template library: all contract templates must reside in a single designated Google Drive folder with a Notion index mapping service_type values to Drive file IDs. The agent reads the Notion index to resolve the correct template. Confirm folder path and Notion database ID before build.
- Mandatory field enforcement: the fields deal.contact.name, deal.company.name, deal.service_type, deal.start_date, deal.fee_amount, and deal.payment_terms must be marked required in HubSpot. If they are not enforced at the CRM level the agent must implement its own null-check guard before attempting population.
- Document copy approach: the agent creates a new Google Docs copy of the template file using the Drive API (files.copy) rather than modifying the master. The master template is never written to.
- Field merge: placeholder tokens in templates follow the convention {{FIELD_NAME}} in uppercase. Confirm this naming convention is applied consistently across all six templates before build. Any template using a different placeholder style requires a preprocessing normalisation step.
- Approval routing: manager email is resolved by reading the deal's hubspot_owner_id and looking up the owner record's manager field. If no manager field is populated in HubSpot the agent must fall back to a hardcoded default approver email stored in the automation platform's credential store.
- Dedupe guard: the agent checks whether a draft already exists in Google Drive for the same deal ID before creating a new file. If a file is found it skips creation and re-sends the approval link to avoid duplicate drafts on re-triggered webhooks.
- Notion dependency: Notion is used solely as a template index lookup. If the Notion integration is unavailable the agent must fail loudly and log to the error table rather than attempt template selection by filename heuristics.
Activated when the manager clicks the approve link embedded in the Gmail approval notification. The agent receives the approval signal, retrieves the draft file from Google Drive, creates a DocuSign envelope using a predefined signing template that auto-places signature and date fields, and dispatches the envelope to the client. DocuSign's built-in reminder rules are configured at envelope creation for Day 3 and Day 5 automated reminders, eliminating all manual chasing. On the 'envelope completed' webhook event from DocuSign, the agent downloads the executed PDF, saves it to the executed-contracts folder in Google Drive with a standardised filename, updates the HubSpot deal record with contract status and file link, and creates a draft invoice in Xero using the fee schedule and payment terms from the deal record.
// On approval (input from manager action)
approval.token : string // HMAC-signed token in approval URL
approval.deal_id : string // HubSpot deal ID passed in token payload
approval.gdrive_file_id : string // draft file ID passed in token payload
approval.approved_by : string // manager email
approval.timestamp : ISO8601 datetime
// Input from Google Drive (retrieved on approval)
gdrive.draft.file_url : string // link to approved draft PDF export
// DocuSign envelope creation input
docusign.recipient.name : string // from hubspot.deal.contact.name
docusign.recipient.email : string // from hubspot.deal.contact.email
docusign.template_id : string // predefined DocuSign signing template ID
docusign.reminders : { day3: true, day5: true }
// Output (envelope sent)
docusign.envelope.id : string
docusign.envelope.status : 'sent'
// Output (on DocuSign 'envelope_completed' webhook)
docusign.signed_pdf.url : string
gdrive.executed.file_id : string // filed in /executed-contracts/
gdrive.executed.file_name : string // e.g. EXECUTED_AcmeCorp_ServiceAgreement_2025-06-01
hubspot.deal.contract_status : 'Executed'
hubspot.deal.executed_doc_link : string
xero.invoice.id : string // draft invoice ID
xero.invoice.status : 'DRAFT'
xero.invoice.amount_due : number // from hubspot.deal.fee_amount
xero.invoice.due_date : ISO8601 date // derived from payment_terms- DocuSign tier requirement: envelope creation via API requires DocuSign eSignature Standard or above. The Personal plan does not expose the Envelopes API. Confirm account tier before build.
- DocuSign signing template: a reusable signing template must be created in the DocuSign admin panel with auto-place anchor tags matching the contract's signature block text (e.g. 'Authorised Signatory'). The agent references this template by its template_id. Confirm template_id before build.
- Approval token security: the one-click approve link must embed an HMAC-signed token containing deal_id and gdrive_file_id. The token must carry a 72-hour expiry. Verify the token on receipt; reject and log any expired or tampered tokens.
- Rejection path: if the manager clicks the request-changes link instead of approve, the agent sends a Gmail notification to the account manager with the manager's comment field and halts. No DocuSign envelope is created. The drafting agent is not re-triggered automatically; a manual restart is required.
- Google Drive filing path: the executed-contracts folder path must be confirmed and hardcoded in the credential store before build. Subfolder structure is recommended as /executed-contracts/YYYY/MM/. The agent must create the month subfolder if it does not yet exist using the Drive API (files.create with mimeType folder).
- HubSpot update scope: the agent writes to two deal properties: hs_deal_stage (set to 'Contract Executed' custom stage if it exists, otherwise a text property) and a custom property contract_executed_link. Confirm both property internal names in HubSpot before build.
- Xero invoice creation: the agent uses the Xero Invoices POST endpoint. The invoice LineItems array is built from the deal's fee_amount and a line item description derived from deal.service_type. Invoice due date is calculated by adding the payment_terms day count to the contract start_date. Xero OAuth 2.0 token refresh must be implemented; access tokens expire after 30 minutes.
- Dedupe guard on filing: before saving the executed PDF the agent checks for an existing file in the target folder matching the same deal_id in the filename. If found it skips the upload and logs a warning rather than creating a duplicate.
03End-to-end data flow
// ============================================================
// CONTRACT GENERATION & MANAGEMENT: END-TO-END DATA FLOW
// ============================================================
// TRIGGER
// HubSpot deal stage webhook fires on transition to 'Closed Won'
INBOUND_WEBHOOK {
event_type : 'deal.propertyChange'
property_name : 'dealstage'
property_value : 'closedwon'
object_id : deal.id // e.g. '123456789'
occurred_at : ISO8601 datetime
}
// ============================================================
// AGENT 1: CONTRACT DRAFTING AGENT
// ============================================================
// Step 1: Fetch full deal record from HubSpot
GET hubspot.deals/{deal.id}
-> deal.dealname
-> deal.contact.name
-> deal.contact.email
-> deal.company.name
-> deal.company.entity_type
-> deal.service_type // key for template lookup
-> deal.start_date // ISO8601
-> deal.fee_amount // USD float
-> deal.payment_terms // e.g. 'Net 30'
-> deal.jurisdiction
-> deal.hubspot_owner_id // used to resolve approver
// Step 2: Guard — null-check mandatory fields
IF ANY OF [contact.name, company.name, service_type,
start_date, fee_amount, payment_terms] IS NULL:
agent.status = 'INCOMPLETE_RECORD'
agent.missing_fields = [<null field names>]
-> Gmail: flag email to hubspot.deal.owner.email
-> HALT (no further processing)
// Step 3: Dedupe check
QUERY gdrive /drafts/ WHERE filename CONTAINS deal.id
IF file_found:
-> re-send existing approval_request_url to manager
-> HALT
// Step 4: Resolve template from Notion index
GET notion.database/{TEMPLATE_DB_ID}
filter: { service_type == deal.service_type }
-> notion.template_record.gdrive_file_id // master template file ID
// Step 5: Create draft document copy in Google Drive
POST gdrive.files.copy({
fileId : notion.template_record.gdrive_file_id,
name : 'DRAFT_{company.name}_{service_type}_{start_date}',
parents : [DRAFT_FOLDER_ID]
})
-> gdrive.draft.file_id
-> gdrive.draft.file_url
// Step 6: Merge variable fields into draft (Docs API batch update)
POST gdrive.documents/{gdrive.draft.file_id}.batchUpdate
replaceAllText: {{CONTACT_NAME}} -> deal.contact.name
replaceAllText: {{COMPANY_NAME}} -> deal.company.name
replaceAllText: {{ENTITY_TYPE}} -> deal.company.entity_type
replaceAllText: {{START_DATE}} -> deal.start_date
replaceAllText: {{FEE_AMOUNT}} -> deal.fee_amount
replaceAllText: {{PAYMENT_TERMS}} -> deal.payment_terms
replaceAllText: {{JURISDICTION}} -> deal.jurisdiction
replaceAllText: {{SERVICE_TYPE}} -> deal.service_type
// Step 7: Resolve manager email from HubSpot owner record
GET hubspot.owners/{deal.hubspot_owner_id}
-> owner.manager_email
IF owner.manager_email IS NULL:
-> fallback: credential_store.DEFAULT_APPROVER_EMAIL
// Step 8: Send approval request via Gmail
POST gmail.send({
to : manager_email,
subject : 'Contract ready for approval: {deal.dealname}',
body : approval_template with gdrive.draft.file_url,
approve_url = orchestration_layer/approve?token={HMAC_TOKEN},
changes_url = orchestration_layer/reject?token={HMAC_TOKEN}
})
// HMAC_TOKEN payload: { deal_id, gdrive_file_id, expires_at: now+72h }
// -- AGENT 1 HANDOFF -> HUMAN GATE -> AGENT 2 --
// ============================================================
// HUMAN GATE: MANAGER INTERNAL APPROVAL (STEP 4 - MANUAL)
// ============================================================
// Manager reviews draft at gdrive.draft.file_url
// Manager clicks approve_url or changes_url
// IF changes_url clicked:
// POST gmail.send to deal.owner.email with manager comment
// HALT — manual restart required
// IF approve_url clicked:
// orchestration_layer validates HMAC_TOKEN (expiry + signature)
// -> approval.token_valid = true
// -> triggers Signature and Filing Agent
// ============================================================
// AGENT 2: SIGNATURE AND FILING AGENT
// ============================================================
// Step 9: Export approved draft to PDF
GET gdrive.files/{gdrive.draft.file_id}/export?mimeType=application/pdf
-> draft_pdf.bytes
// Step 10: Create DocuSign envelope
POST docusign.envelopes({
templateId : credential_store.DOCUSIGN_TEMPLATE_ID,
document : { name: gdrive.draft.file_name, content: draft_pdf.bytes },
recipients : [{ name: deal.contact.name, email: deal.contact.email }],
reminders : { reminderEnabled: true, reminderDelay: 3,
reminderFrequency: 2 } // Day 3, then Day 5
})
-> docusign.envelope.id
-> docusign.envelope.status = 'sent'
// Step 11: Await DocuSign 'envelope_completed' webhook
INBOUND_WEBHOOK docusign.connect {
event : 'envelope-completed'
envelopeId : docusign.envelope.id
completedDateTime: ISO8601 datetime
documents[0].url : signed_pdf.download_url
}
// Step 12: Download signed PDF from DocuSign
GET docusign.envelopes/{envelope.id}/documents/combined
-> signed_pdf.bytes
// Step 13: File executed contract to Google Drive
// Ensure /executed-contracts/YYYY/MM/ subfolder exists
POST gdrive.files.create (folder if missing)
POST gdrive.files.create({
name : 'EXECUTED_{company.name}_{service_type}_{start_date}',
parents : [EXECUTED_CONTRACTS_FOLDER_ID/YYYY/MM],
content : signed_pdf.bytes
})
-> gdrive.executed.file_id
-> gdrive.executed.file_url
// Step 14: Update HubSpot deal record
PATCH hubspot.deals/{deal.id} ({
contract_status : 'Executed',
contract_executed_link: gdrive.executed.file_url,
dealstage : 'Contract Executed' // confirm custom stage name
})
// Step 15: Create draft invoice in Xero
POST xero.invoices({
Type : 'ACCREC',
Status : 'DRAFT',
Contact : { Name: deal.company.name },
LineItems : [{ Description: deal.service_type,
UnitAmount : deal.fee_amount,
Quantity : 1 }],
Date : deal.start_date,
DueDate : start_date + payment_terms_days // e.g. +30 for Net 30
})
-> xero.invoice.id
-> xero.invoice.status = 'DRAFT'
// ============================================================
// FLOW COMPLETE
// deal.contract_status = Executed | invoice created in Xero
// executed PDF filed to Google Drive with standardised name
// ============================================================04Recommended build stack
More documents for this process
Every document generated for Contract Generation & Management.