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
NDA Workflow
[YourCompany.com] · Legal Department · Prepared by FullSpec · [Today's Date]
This document gives the FullSpec build team everything needed to construct, wire, and hand over the three-agent NDA Workflow automation. It covers the current-state step map with bottleneck flags, full agent specifications with IO contracts, an end-to-end data flow trace, and the recommended build stack. The owner and their team are responsible for providing clean NDA templates, confirming API credentials, and designating the internal approval contact before build begins. FullSpec handles all orchestration, integration, and testing.
01Process snapshot
02Agent specifications
Receives the NDA intake form submission, reads the relationship type and party details fields, determines the correct NDA template variant (mutual, one-way, employee, or vendor), creates a new record in the Notion tracker database with status set to Draft, and populates a named Google Drive copy of the correct template with the merged party details. This agent is the entry point for the entire workflow and must complete successfully before any downstream agent is triggered. Complexity: Moderate. Estimated build time: 7 hours.
// Input
form_submission: {
party_name: string,
nda_type: 'mutual' | 'one-way' | 'employee' | 'vendor',
requester_email: string,
counterparty_address: string,
governing_law: string,
effective_date: date (ISO 8601)
}
// Classification logic
nda_type -> map to Google Drive template_id
'mutual' -> template_id: TMPL-MUT-v3
'one-way' -> template_id: TMPL-OW-v2
'employee' -> template_id: TMPL-EMP-v1
'vendor' -> template_id: TMPL-VND-v2
// Output
notion_record: {
record_id: string,
status: 'Draft',
party_name: string,
nda_type: string,
requester_email: string,
created_at: timestamp
}
drive_draft: {
file_id: string,
file_name: 'NDA_[party_name]_[nda_type]_[effective_date]',
folder_id: DRIVE_DRAFTS_FOLDER_ID,
shareable_link: string
}- Google Drive: The automation must target a pinned 'Templates (Live)' folder by folder ID, not by name, to avoid version confusion. Confirm the folder ID and lock it in the credential store before build. Template copies must be created via the Drive files.copy endpoint, not by downloading and re-uploading.
- Notion: The target database must have properties matching the field names above (party_name, nda_type, requester_email, status, created_at). Confirm the Notion database ID and integration token scope (insert and update) before build.
- NDA type classification: The intake form must present NDA type as a controlled dropdown, not a free-text field, so the agent can map it deterministically. Confirm this with the form owner before build begins.
- Duplicate handling: If a record with the same party_name and effective_date already exists in Notion with status Draft or Pending Approval, the agent must halt and post an alert to the error log rather than creating a duplicate.
- Fallback: If no template ID maps to the submitted nda_type, the agent must write an error status to Notion, send an alert to support@gofullspec.com, and stop the workflow without triggering downstream agents.
Picks up the Google Drive draft file link from the Intake and Classification Agent output, constructs a Slack Block Kit message addressed to the designated internal approver, and posts it to the configured approval channel. The message includes a direct link to the draft document and two interactive action buttons: Approve and Reject. If no response is recorded within 24 hours, the agent fires a single reminder message. On approval the agent passes the approved Drive file link downstream and updates the Notion record status to Approved. On rejection, the agent notifies the requester via Gmail and updates Notion status to Rejected, halting the workflow. Complexity: Moderate. Estimated build time: 6 hours.
// Input
drive_draft: {
file_id: string,
shareable_link: string
}
notion_record: {
record_id: string,
party_name: string,
nda_type: string,
requester_email: string
}
approver_slack_user_id: string // pulled from credential store
// Slack message payload (Block Kit)
blocks: [
section: 'NDA approval required for [party_name] ([nda_type])',
button: { text: 'Approve', action_id: 'nda_approve', value: record_id },
button: { text: 'Reject', action_id: 'nda_reject', value: record_id }
]
// On approval
notion_update: { record_id, status: 'Approved' }
downstream_payload: {
file_id: string,
shareable_link: string,
party_name: string,
nda_type: string,
requester_email: string,
notion_record_id: string
}
// On rejection
notion_update: { record_id, status: 'Rejected' }
gmail_send: {
to: requester_email,
subject: 'NDA request for [party_name] was not approved',
body: 'The internal reviewer has rejected this draft. Please review and resubmit.'
}- Slack: The approver must interact with the Approve or Reject buttons in the Slack message. A reply in thread does not advance the workflow. This must be communicated to the approver before go-live.
- Slack app configuration: The automation platform's Slack app must be installed in the workspace with chat:write and the interactivity payload URL configured to point to the orchestration layer's webhook receiver endpoint.
- 24-hour reminder: Implemented as a scheduled delay node triggered at message send time. If an action_id callback has been received before the delay fires, the reminder step must be skipped using a conditional branch checking Notion record status.
- Approver identity: The designated approver's Slack user ID must be stored in the shared credential store, not hardcoded in the workflow. Confirm the approver user ID and whether a fallback approver is required.
- Slack channel: Approval messages must post to a dedicated private channel (e.g. #nda-approvals) to maintain a clear audit trail. Confirm channel ID before build.
Receives the approved document reference from the Approval and Routing Agent, creates a DocuSign envelope using the pre-configured template envelope for the relevant NDA type, sets the signing order (internal signatory first, then counterparty), and sends the envelope. The agent listens for DocuSign webhook events: completed triggers filing and CRM update; declined or voided triggers an alert to the Notion record and a Gmail notification to the requester. On completion, the executed PDF is retrieved and saved to the correct Google Drive folder with a standardised filename, the HubSpot contact or deal record is updated with the execution date and Drive link, and a confirmation email is sent to the requester. Complexity: Complex. Estimated build time: 9 hours.
// Input
downstream_payload: {
file_id: string, // Google Drive draft file
shareable_link: string,
party_name: string,
nda_type: string,
requester_email: string,
notion_record_id: string
}
internal_signer_email: string // from credential store
counterparty_email: string // from original form_submission
// DocuSign envelope creation
envelope: {
templateId: DOCUSIGN_TMPL_ID[nda_type],
signers: [
{ routingOrder: 1, email: internal_signer_email, name: string },
{ routingOrder: 2, email: counterparty_email, name: party_name }
],
status: 'sent'
}
// DocuSign webhook events listened for
envelope_events: ['completed', 'declined', 'voided']
// On completed
drive_file_executed: {
file_name: 'NDA_EXECUTED_[party_name]_[nda_type]_[signed_date]',
folder_id: DRIVE_EXECUTED_FOLDER_ID,
source: DocuSign.getDocument(envelopeId)
}
hubspot_update: {
contact_or_deal_id: string, // looked up by counterparty_email
nda_status: 'Executed',
execution_date: signed_date,
drive_link: drive_file_executed.shareable_link
}
notion_update: { record_id: notion_record_id, status: 'Executed' }
gmail_send: {
to: requester_email,
subject: 'NDA executed: [party_name]',
body: 'The NDA is fully signed. Access the executed copy here: [drive_link]'
}
// On declined or voided
notion_update: { record_id: notion_record_id, status: 'Signature Failed' }
gmail_send: {
to: requester_email,
subject: 'DocuSign envelope declined or voided: [party_name]',
body: 'The signing envelope was not completed. Please review and restart the workflow.'
}- DocuSign: Pre-configured template envelopes must exist in the DocuSign account for each NDA type before build. Template IDs must be confirmed by a DocuSign admin and stored in the shared credential store. The automation cannot dynamically construct envelopes from scratch for this workflow.
- DocuSign Connect (webhook): Envelope event callbacks must be configured in DocuSign Connect pointing to the orchestration layer's inbound webhook URL. Events required: envelope-completed, envelope-declined, envelope-voided.
- Google Drive filing: The executed folder (DRIVE_EXECUTED_FOLDER_ID) must be a separate folder from the drafts folder and must be confirmed before build. Folder and file permissions must restrict write access to the automation service account only.
- HubSpot lookup: The agent looks up the HubSpot contact or deal by counterparty_email. If no matching record exists, the agent must create a new contact rather than failing silently. Confirm whether the HubSpot API key has contacts write and deals write scope.
- Envelope expiry: DocuSign envelopes are configured with a 7-day expiry. On the voided event (post-expiry), the agent follows the 'On declined or voided' branch above. A reminder is not re-sent by this agent; re-sending is a manual decision by the process owner.
- Counterparty redlines: If the counterparty returns a redlined document outside of DocuSign, the flow is paused. The agent cannot evaluate legal redlines. The Notion record is flagged as 'Pending Legal Review' and the process owner is notified via Gmail.
03End-to-end data flow
// ─────────────────────────────────────────────────────────────
// TRIGGER: NDA Intake Form Submitted
// ─────────────────────────────────────────────────────────────
INBOUND WEBHOOK POST /intake/nda
{
party_name: 'Acme Corp',
nda_type: 'mutual',
requester_email: 'tom@yourcompany.com',
counterparty_email: 'legal@acmecorp.com',
counterparty_address:'123 Main St, New York, NY 10001',
governing_law: 'New York',
effective_date: '2025-07-08'
}
// ─────────────────────────────────────────────────────────────
// AGENT 1 HANDOFF: Intake and Classification Agent
// ─────────────────────────────────────────────────────────────
nda_type 'mutual' -> template_id: TMPL-MUT-v3
Notion.createRecord({
database_id: NOTION_NDA_DB_ID,
party_name: 'Acme Corp',
nda_type: 'mutual',
requester_email: 'tom@yourcompany.com',
status: 'Draft',
created_at: '2025-07-08T09:00:00Z'
}) -> notion_record_id: 'abc-123'
GoogleDrive.files.copy({
fileId: TMPL-MUT-v3,
destination: DRIVE_DRAFTS_FOLDER_ID,
name: 'NDA_AcmeCorp_mutual_2025-07-08'
}) -> drive_draft.file_id: 'drv-456'
-> drive_draft.shareable_link: 'https://drive.google.com/file/d/drv-456'
// ─────────────────────────────────────────────────────────────
// AGENT 2 HANDOFF: Approval and Routing Agent
// ─────────────────────────────────────────────────────────────
Slack.postMessage({
channel: SLACK_APPROVAL_CHANNEL_ID,
user: APPROVER_SLACK_USER_ID,
blocks: [
section: 'NDA approval required: Acme Corp (mutual)',
link: 'https://drive.google.com/file/d/drv-456',
button: { text:'Approve', action_id:'nda_approve', value:'abc-123' },
button: { text:'Reject', action_id:'nda_reject', value:'abc-123' }
]
})
// -- 24h elapsed, no response --
Slack.postMessage({ channel: SLACK_APPROVAL_CHANNEL_ID, text: 'Reminder: NDA pending approval for Acme Corp' })
// -- Approver clicks Approve --
SLACK_CALLBACK: { action_id: 'nda_approve', value: 'abc-123' }
Notion.updateRecord({ record_id:'abc-123', status:'Approved' })
downstream_payload: {
file_id: 'drv-456',
shareable_link: 'https://drive.google.com/file/d/drv-456',
party_name: 'Acme Corp',
nda_type: 'mutual',
requester_email: 'tom@yourcompany.com',
notion_record_id: 'abc-123',
counterparty_email: 'legal@acmecorp.com'
}
// ─────────────────────────────────────────────────────────────
// AGENT 3 HANDOFF: Signature and Completion Agent
// ─────────────────────────────────────────────────────────────
DocuSign.envelopes.create({
templateId: DOCUSIGN_TMPL_ID['mutual'],
signers: [
{ routingOrder:1, email:'rachel@yourcompany.com', name:'Rachel Osei' },
{ routingOrder:2, email:'legal@acmecorp.com', name:'Acme Corp signatory' }
],
status: 'sent'
}) -> envelope_id: 'env-789'
// DocuSign Connect fires webhook on signing completion
DOCUSIGN_WEBHOOK POST /docusign/events
{ envelopeId:'env-789', status:'completed', completedDateTime:'2025-07-09T14:22:00Z' }
DocuSign.envelopes.getDocument(envelope_id:'env-789') -> executed_pdf: binary
GoogleDrive.files.create({
name: 'NDA_EXECUTED_AcmeCorp_mutual_2025-07-09',
parent: DRIVE_EXECUTED_FOLDER_ID,
content: executed_pdf
}) -> executed_file_id: 'drv-999'
-> executed_link: 'https://drive.google.com/file/d/drv-999'
HubSpot.contacts.update({
contact_id: HubSpot.contacts.findByEmail('legal@acmecorp.com').id,
nda_status: 'Executed',
execution_date: '2025-07-09',
drive_link: 'https://drive.google.com/file/d/drv-999'
})
Notion.updateRecord({ record_id:'abc-123', status:'Executed' })
Gmail.send({
to: 'tom@yourcompany.com',
subject: 'NDA executed: Acme Corp',
body: 'The NDA is fully signed. Access the executed copy here: https://drive.google.com/file/d/drv-999'
})
// ─────────────────────────────────────────────────────────────
// END STATE
// Notion status: Executed
// Google Drive (executed folder): NDA_EXECUTED_AcmeCorp_mutual_2025-07-09
// HubSpot contact: nda_status = Executed, drive_link attached
// Requester: completion email received
// ─────────────────────────────────────────────────────────────04Recommended build stack
More documents for this process
Every document generated for NDA Workflow.