Back to Risk Register Management

Integration and API Spec

The reference during the build: every tool connection, auth scope, field mapping, and error-handling rule.

4 pagesPDF · Technical
FS-DOC-05Technical

Integration and API Spec

Risk Register Management

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

This document is the authoritative integration reference for the Risk Register Management automation. It covers every tool in the stack, the exact authentication method and OAuth scopes required for each, field-level mappings between agent handoffs, orchestration layout, credential store contents, and defined failure behaviours for every integration point. The FullSpec team uses this specification during build and QA; it is also the reference for any future change requests or tool substitutions.

01Tool inventory

Tool
Role in automation
Auth method
Min plan required
Used by agent(s)
Orchestration layer
Workflow scheduling, trigger routing, credential management, retry logic
Internal service account / platform auth
Paid tier (approx. $49/month)
All agents
Google Forms
Risk intake submission form; fires trigger on new response
OAuth 2.0 (Google)
Free (Google Workspace or personal)
Agent 1
Google Sheets
Central risk register store; read and write across all agents
OAuth 2.0 (Google)
Free (Google Workspace or personal)
Agents 1, 2, 3
Slack
Owner notifications and 48-hour escalation nudges
OAuth 2.0 (Slack Bot Token)
Free tier sufficient; Pro recommended for message retention
Agent 2
Notion
Leadership report publishing; monthly page creation and archiving
OAuth 2.0 (Notion Integration Token)
Plus plan ($16/month) for full API access
Agent 3
Gmail
Escalation emails to risk manager and department heads; report distribution
OAuth 2.0 (Google)
Free (Google Workspace or personal)
Agents 2, 3
Before you connect anything: all integration credentials must be validated against sandbox or test environments before production credentials are issued. For Google services, use a dedicated service account in a non-production Google Workspace. For Slack, connect to a test workspace. For Notion, use a duplicate database. Only after each connection passes a live ping test should production credentials be stored in the credential store.

02Per-tool integration detail

Google Forms

Provides the new-risk intake trigger. Each form submission creates a new row event that the orchestration layer listens to via a push notification subscription. The form structure must match the field mapping defined in Section 03.

Auth method
OAuth 2.0. A Google service account JSON key is issued with domain-wide delegation, or a user OAuth token is granted with the scopes below. Store the token in the credential store as GOOGLE_FORMS_TOKEN.
Required scopes
https://www.googleapis.com/auth/forms.responses.readonly | https://www.googleapis.com/auth/drive.readonly
Webhook / trigger setup
Use the Google Forms API v1 watches endpoint (POST /v1/forms/{formId}/watches) to register a push notification. Set event_type to RESPONSES. The watch must be renewed every 7 days; the orchestration layer handles renewal automatically via a scheduled keep-alive step. The notification target is the orchestration platform's inbound webhook URL. Validate incoming payloads by checking the X-Goog-Channel-Token header against the stored FORMS_WEBHOOK_SECRET.
Required configuration
FORMS_FORM_ID stored in the credential store (not hardcoded). Form must contain fields matching the canonical schema: risk_title, risk_description, risk_category, risk_submitter_email, risk_submitter_name. Field IDs are retrieved at build time via GET /v1/forms/{formId} and mapped in the workflow configuration.
Rate limits
Google Forms API: 300 requests/minute per project. At approximately 40 new risk submissions per month, peak load is well under 1 request/minute. No throttling required.
Constraints
Push watch subscriptions expire after 7 days and must be renewed. If renewal fails, the fallback is a 15-minute polling step against the Sheets register. Form field order changes invalidate field ID mappings; notify FullSpec before editing the form structure.
// Output payload (on new response)
{
  "formId": "<FORMS_FORM_ID>",
  "responseId": "<string>",
  "createTime": "<ISO 8601>",
  "answers": {
    "<fieldId_title>": { "textAnswers": { "answers": [{ "value": "<risk_title>" }] } },
    "<fieldId_description>": { "textAnswers": { "answers": [{ "value": "<risk_description>" }] } },
    "<fieldId_category>": { "textAnswers": { "answers": [{ "value": "<risk_category>" }] } },
    "<fieldId_submitter_email>": { "textAnswers": { "answers": [{ "value": "<email>" }] } },
    "<fieldId_submitter_name>": { "textAnswers": { "answers": [{ "value": "<name>" }] } }
  }
}
Google Sheets

Acts as the central risk register. All three agents read from and write to the same spreadsheet. The register schema is fixed; column order must not be altered after go-live without a coordinated schema migration.

Auth method
OAuth 2.0 via the same Google service account used for Forms (scope extended). Store token as GOOGLE_SHEETS_TOKEN. Use the Sheets API v4.
Required scopes
https://www.googleapis.com/auth/spreadsheets | https://www.googleapis.com/auth/drive.file
Webhook / trigger setup
No native webhook for Sheets. Agent 2 (Review Chase and Escalation) polls the register on a 30-minute schedule using GET /v4/spreadsheets/{spreadsheetId}/values/{sheetName}!A:Z. The orchestration layer filters rows where review_due_date is today or earlier and status is not 'Closed' or 'Confirmed'.
Required configuration
SHEETS_SPREADSHEET_ID and SHEETS_SHEET_NAME stored in the credential store. Register must have the following named columns in row 1: risk_id, risk_title, risk_description, risk_category, submitter_email, submitter_name, date_raised, owner_email, review_due_date, likelihood_proposed, impact_proposed, risk_score_proposed, likelihood_confirmed, impact_confirmed, risk_score_confirmed, status, reviewer_name, reviewer_timestamp, escalation_flag, archive_snapshot_url. A second tab named 'Archive_Log' stores snapshot references.
Rate limits
Sheets API v4: 300 read/write requests per minute per project, 100 requests per 100 seconds per user. At 210 runs/month across three agents, peak is approximately 7 requests/minute during end-of-month report generation. No throttling required; add a 200ms delay between batch write calls as a precaution.
Constraints
All writes to the register must use append (POST .../values:append) for new rows and batchUpdate for existing row edits to avoid overwriting concurrent edits. Never write to column A (risk_id); IDs are assigned by the intake agent using a SHEETS_RISK_ID_COUNTER stored in a named range called 'RiskIDCounter'.
// Write new risk row (Agent 1 -> Sheets)
POST /v4/spreadsheets/{SHEETS_SPREADSHEET_ID}/values/{SHEETS_SHEET_NAME}!A:T:append
Body: { "values": [[risk_id, risk_title, risk_description, risk_category,
  submitter_email, submitter_name, date_raised, owner_email, review_due_date,
  likelihood_proposed, impact_proposed, risk_score_proposed, "", "", "",
  "Pending", "", "", "false", ""]] }

// Update confirmed scores (Agent 2 -> Sheets)
POST /v4/spreadsheets/{SHEETS_SPREADSHEET_ID}/values:batchUpdate
Body: { "valueInputOption": "RAW", "data": [
  { "range": "<row_range>", "values": [[likelihood_confirmed, impact_confirmed,
    risk_score_confirmed, "Confirmed", reviewer_name, reviewer_timestamp]] }
]}
Slack

Used exclusively by Agent 2 to deliver owner review prompts and 48-hour overdue nudges. Messages are sent to individual users by email lookup via the Slack users.lookupByEmail method before posting.

Auth method
OAuth 2.0 Bot Token. Create a Slack App in the target workspace, install it to the workspace, and store the bot token as SLACK_BOT_TOKEN. Do not use legacy webhook URLs.
Required scopes
chat:write | users:read | users:read.email | channels:read | im:write
Webhook / trigger setup
No inbound webhook required for this process. Slack is write-only; the orchestration layer calls chat.postMessage after resolving the owner's Slack user ID via users.lookupByEmail using the owner_email value from the Sheets register.
Required configuration
SLACK_BOT_TOKEN in the credential store. SLACK_ESCALATION_CHANNEL_ID stored for posting escalation summaries (not hardcoded). Message templates for review prompt and overdue nudge are stored as workflow configuration variables, not hardcoded strings, so they can be updated without a code change.
Rate limits
Slack API Tier 3: 50 calls/minute for chat.postMessage. At 40 risk items per month with up to two nudges each, maximum burst is 80 messages per month, well within limits. No throttling required. Add a 500ms delay between consecutive postMessage calls during batch nudge runs.
Constraints
The Slack App must be invited to any private channel used for escalation summaries before it can post. If a risk owner's email is not found in the workspace, the agent falls back to a Gmail escalation to the risk manager with a flag indicating the Slack lookup failed. This fallback path is logged to the 'Archive_Log' sheet tab.
// Review prompt message (Agent 2 -> Slack)
POST https://slack.com/api/chat.postMessage
Headers: { "Authorization": "Bearer <SLACK_BOT_TOKEN>" }
Body: {
  "channel": "<resolved_user_id>",
  "text": "Risk review required: <risk_title> (ID: <risk_id>). Please confirm or update your likelihood and impact score by <review_due_date>. Register link: <SHEETS_ROW_URL>"
}
Integration and API SpecPage 1 of 3
FS-DOC-05Technical
Notion

Used by Agent 3 to create the monthly leadership risk report as a new Notion page inside a designated parent database. Each month's report is a discrete page; the database view shows all monthly reports in chronological order.

Auth method
Notion Internal Integration Token. Create an integration at notion.so/my-integrations, share the target database with the integration, and store the token as NOTION_API_TOKEN. API version: 2022-06-28.
Required scopes
Notion integrations use capability flags rather than OAuth scope strings. Required capabilities: Read content, Insert content, Update content. Set these on the integration before connecting.
Webhook / trigger setup
No inbound webhook. Agent 3 is triggered by a monthly cron schedule in the orchestration layer (last business day of the month, 07:00 UTC). The agent calls the Notion API to create a new page.
Required configuration
NOTION_API_TOKEN, NOTION_PARENT_DATABASE_ID, and NOTION_REPORT_TEMPLATE_PAGE_ID stored in the credential store. The parent database must have the following properties: Report Month (title), Status (select: Draft / Published), Risk Count (number), Critical Count (number), Created By (text), Distribution Sent (checkbox). The template page is duplicated each month; its block structure defines the report layout and must be agreed with the leadership team before go-live.
Rate limits
Notion API: 3 requests/second average, burst up to 10 requests/second. Report generation involves approximately 15 to 25 API calls (one page create, multiple block appends). This runs once per month and poses no rate limit risk. No throttling required.
Constraints
Notion block content is write-once per automation run; if the report generation fails mid-page, the partial draft page must be deleted and recreated. Implement an idempotency check: before creating a new page, query the database for an existing page with the same Report Month property value. If found, skip creation and log a warning.
// Create monthly report page (Agent 3 -> Notion)
POST https://api.notion.com/v1/pages
Headers: { "Authorization": "Bearer <NOTION_API_TOKEN>",
           "Notion-Version": "2022-06-28" }
Body: {
  "parent": { "database_id": "<NOTION_PARENT_DATABASE_ID>" },
  "properties": {
    "Report Month": { "title": [{ "text": { "content": "<YYYY-MM>" } }] },
    "Status": { "select": { "name": "Draft" } },
    "Risk Count": { "number": <total_risk_count> },
    "Critical Count": { "number": <critical_count> },
    "Created By": { "rich_text": [{ "text": { "content": "FullSpec Automation" } }] },
    "Distribution Sent": { "checkbox": false }
  }
}
Gmail

Used by Agents 2 and 3 for escalation emails and report distribution respectively. All outbound email is sent from a designated automation sender address configured in Google Workspace. Replies from recipients are not processed by the automation.

Auth method
OAuth 2.0. Use the same Google service account as Sheets and Forms (domain-wide delegation enabled). Impersonate the designated sender address (e.g. risk-automation@[YourCompany.com]) using the sub claim in the JWT. Store the impersonation address as GMAIL_SENDER_ADDRESS in the credential store.
Required scopes
https://www.googleapis.com/auth/gmail.send | https://www.googleapis.com/auth/gmail.compose
Webhook / trigger setup
Gmail is write-only in this automation. No inbound webhook or watch subscription is required. Emails are constructed in the orchestration layer and sent via the Gmail API v1 users.messages.send endpoint. Email bodies are base64url-encoded RFC 2822 MIME messages.
Required configuration
GMAIL_SENDER_ADDRESS, GMAIL_RISK_MANAGER_EMAIL, GMAIL_STAKEHOLDER_LIST (comma-separated), and GMAIL_DEPT_HEAD_MAP (JSON object mapping risk_category to department head email) stored in the credential store. Email subject and body templates are stored as workflow configuration variables. The Notion report URL is injected at send time.
Rate limits
Gmail API: 250 quota units per user per second; users.messages.send costs 100 units. Effective rate: 2.5 send operations per second per user. At approximately 40 escalation emails plus 1 monthly distribution email (up to 10 recipients as individual sends), total monthly email volume is under 90 API calls. No throttling required.
Constraints
Gmail API does not support batch send to multiple recipients via a single API call in all configurations; send to each stakeholder address individually using a loop to ensure delivery logging per recipient. If a send fails for one recipient, the remaining sends must still proceed. Failures are logged and retried once after a 5-minute delay.
// Escalation email (Agent 2 -> Gmail)
POST https://gmail.googleapis.com/gmail/v1/users/me/messages/send
Headers: { "Authorization": "Bearer <GOOGLE_SHEETS_TOKEN>" }
Body: {
  "raw": "<base64url(RFC2822 MIME message)>"
}
// MIME structure:
// From: <GMAIL_SENDER_ADDRESS>
// To: <GMAIL_RISK_MANAGER_EMAIL>
// CC: <dept_head_email resolved from GMAIL_DEPT_HEAD_MAP>
// Subject: [ACTION REQUIRED] Overdue Risk: <risk_title> (ID: <risk_id>)
// Body: risk_title, risk_id, owner_email, review_due_date, risk_score_proposed, register_url

03Field mappings between tools

The tables below define the exact field-level data movement at each agent handoff. All field names are canonical; deviations require a schema change in both the source and destination system.

Agent 1 handoff: Google Forms to Google Sheets (Risk Intake and Scoring Agent)

Source tool
Source field
Destination tool
Destination field
Google Forms
answers[fieldId_title].textAnswers.answers[0].value
Google Sheets
risk_title
Google Forms
answers[fieldId_description].textAnswers.answers[0].value
Google Sheets
risk_description
Google Forms
answers[fieldId_category].textAnswers.answers[0].value
Google Sheets
risk_category
Google Forms
answers[fieldId_submitter_email].textAnswers.answers[0].value
Google Sheets
submitter_email
Google Forms
answers[fieldId_submitter_name].textAnswers.answers[0].value
Google Sheets
submitter_name
Google Forms
createTime
Google Sheets
date_raised
Orchestration layer
computed: risk_matrix_score(risk_description, risk_category)
Google Sheets
likelihood_proposed
Orchestration layer
computed: risk_matrix_score(risk_description, risk_category)
Google Sheets
impact_proposed
Orchestration layer
computed: likelihood_proposed * impact_proposed
Google Sheets
risk_score_proposed
Orchestration layer
computed: SHEETS_RISK_ID_COUNTER + 1
Google Sheets
risk_id
Orchestration layer
lookup: owner_routing_map[risk_category]
Google Sheets
owner_email
Orchestration layer
computed: date_raised + 14 days
Google Sheets
review_due_date
Orchestration layer
constant: 'Pending'
Google Sheets
status

Agent 2 handoff: Google Sheets to Slack (Review Chase and Escalation Agent, owner nudge)

Source tool
Source field
Destination tool
Destination field
Google Sheets
risk_id
Slack
message body: risk_id
Google Sheets
risk_title
Slack
message body: risk_title
Google Sheets
risk_score_proposed
Slack
message body: risk_score_proposed
Google Sheets
review_due_date
Slack
message body: review_due_date
Google Sheets
owner_email
Slack
users.lookupByEmail: email -> channel (user DM)
Orchestration layer
computed: SHEETS_ROW_URL(risk_id)
Slack
message body: register_link

Agent 2 handoff: Google Sheets to Gmail (Review Chase and Escalation Agent, escalation email)

Source tool
Source field
Destination tool
Destination field
Google Sheets
risk_id
Gmail
email body: risk_id
Google Sheets
risk_title
Gmail
email subject and body: risk_title
Google Sheets
owner_email
Gmail
email body: owner_email
Google Sheets
review_due_date
Gmail
email body: review_due_date
Google Sheets
risk_score_proposed
Gmail
email body: risk_score_proposed
Google Sheets
escalation_flag
Gmail
conditional send trigger
Google Sheets
risk_category
Gmail
lookup: GMAIL_DEPT_HEAD_MAP[risk_category] -> CC address
Orchestration layer
computed: SHEETS_ROW_URL(risk_id)
Gmail
email body: register_url

Agent 3 handoff: Google Sheets to Notion (Risk Reporting Agent)

Source tool
Source field
Destination tool
Destination field
Google Sheets
risk_id (all rows)
Notion
page property: Risk Count (count)
Google Sheets
risk_score_confirmed (filter: >= critical_threshold)
Notion
page property: Critical Count (count)
Google Sheets
risk_title, risk_score_confirmed, status, owner_email
Notion
page block: top risks table
Google Sheets
risk_category (grouped)
Notion
page block: risk heat map narrative
Google Sheets
reviewer_timestamp (latest)
Notion
page block: last updated timestamp
Orchestration layer
computed: current month label (YYYY-MM)
Notion
page property: Report Month
Orchestration layer
constant: 'Draft'
Notion
page property: Status

Agent 3 handoff: Notion to Gmail (Risk Reporting Agent, report distribution)

Source tool
Source field
Destination tool
Destination field
Notion
page.url (returned by create page response)
Gmail
email body: notion_report_url
Orchestration layer
computed: current month label
Gmail
email subject: report month
Orchestration layer
GMAIL_STAKEHOLDER_LIST
Gmail
To: recipients (individual sends)
Google Sheets
risk_score_confirmed (top 3 by score)
Gmail
email body: top_risks_excerpt
Integration and API SpecPage 2 of 3
FS-DOC-05Technical

04Build stack and orchestration

Orchestration layout
Three discrete workflows, one per agent, all sharing a single credential store. Workflows do not call each other directly; they share state exclusively through the Google Sheets register. This decoupling means a failure in one workflow does not block the others.
Agent 1 trigger: Risk Intake and Scoring Agent
Webhook (push). Google Forms API watch subscription fires an HTTP POST to the orchestration platform's inbound webhook URL on each new form response. The platform validates the X-Goog-Channel-Token header against FORMS_WEBHOOK_SECRET before processing. Fallback: 15-minute polling of the Sheets register for new rows with an empty date_raised if the watch subscription has lapsed.
Agent 2 trigger: Review Chase and Escalation Agent
Scheduled poll. The orchestration platform runs the workflow every 30 minutes. It queries the Sheets register for rows where review_due_date <= today and status is 'Pending' or 'Nudged'. A second condition fires immediately when a row's escalation_flag is set to 'true' (written by Agent 1 for critical scores). No inbound webhook; all state is read from Sheets.
Agent 3 trigger: Risk Reporting Agent
Cron schedule. Fires once per month on the last business day at 07:00 UTC. The orchestration platform evaluates whether the current date is the last business day using a built-in calendar utility. If the scheduled run falls on a weekend or public holiday, it fires on the preceding business day. No webhook.
Webhook signature validation
Google Forms push notifications include X-Goog-Channel-Token (a shared secret) and X-Goog-Resource-State headers. The orchestration layer must verify X-Goog-Channel-Token === FORMS_WEBHOOK_SECRET on every inbound request and return HTTP 400 for mismatches without processing the payload.
Credential store
All secrets are stored in the orchestration platform's encrypted environment variable store (no secrets in workflow code or configuration files). See the code block below for the full list of required entries.
Shared state mechanism
Google Sheets acts as the shared state layer between workflows. Agent 1 writes; Agent 2 reads and writes; Agent 3 reads. No direct inter-workflow messaging. All writes use row-level locking via sequential batchUpdate calls with a pessimistic retry on HTTP 429.
Logging
Each workflow writes a structured execution log entry to the 'Archive_Log' tab in the Sheets register on completion or failure. Fields: execution_id, workflow_name, run_timestamp, status (success/failure/partial), error_message, rows_affected.
All values are injected at runtime from the encrypted credential store. No secret is hardcoded in workflow logic or committed to version control.
// Credential store contents (orchestration platform environment variables)
// Google (shared service account, domain-wide delegation enabled)
GOOGLE_SERVICE_ACCOUNT_JSON   = <base64-encoded service account JSON key>
GOOGLE_IMPERSONATION_EMAIL    = risk-automation@[YourCompany.com]

// Google Forms
FORMS_FORM_ID                 = <Google Forms form ID string>
FORMS_WEBHOOK_SECRET          = <random 32-char secret for X-Goog-Channel-Token>
FORMS_WATCH_ID                = <watch ID returned by Forms API, refreshed every 7 days>

// Google Sheets
SHEETS_SPREADSHEET_ID         = <Google Sheets spreadsheet ID string>
SHEETS_SHEET_NAME             = RiskRegister
SHEETS_ARCHIVE_SHEET_NAME     = Archive_Log
SHEETS_RISK_ID_NAMED_RANGE    = RiskIDCounter

// Slack
SLACK_BOT_TOKEN               = xoxb-<your-slack-bot-token>
SLACK_ESCALATION_CHANNEL_ID   = <Slack channel ID for escalation summaries>

// Notion
NOTION_API_TOKEN              = secret_<your-notion-integration-token>
NOTION_PARENT_DATABASE_ID     = <Notion database ID for monthly reports>
NOTION_REPORT_TEMPLATE_PAGE_ID= <Notion page ID used as structural template>

// Gmail
GMAIL_SENDER_ADDRESS          = risk-automation@[YourCompany.com]
GMAIL_RISK_MANAGER_EMAIL      = <risk manager email address>
GMAIL_STAKEHOLDER_LIST        = <comma-separated leadership distribution list>
GMAIL_DEPT_HEAD_MAP           = { "Operational": "ops-head@[YourCompany.com]",
                                  "Financial": "finance-head@[YourCompany.com]",
                                  "Compliance": "compliance-head@[YourCompany.com]",
                                  "Strategic": "ceo@[YourCompany.com]" }

// Orchestration
CRITICAL_SCORE_THRESHOLD      = 15
ESCALATION_WINDOW_HOURS       = 48
REVIEW_CYCLE_DAYS             = 14
MONTHLY_REPORT_RUN_TIME_UTC   = 07:00

05Error handling and retry logic

Every integration point has a defined failure behaviour. Unhandled exceptions must never fail silently; every failure path writes a log entry to the Archive_Log sheet and, where appropriate, sends an alert to the risk manager via Gmail.

Integration
Scenario
Required behaviour
Google Forms watch subscription
Watch expires or renewal fails
Orchestration layer falls back to 15-minute Sheets polling for new rows with empty date_raised. Alert email sent to GMAIL_RISK_MANAGER_EMAIL. Watch renewal retried with exponential backoff: 5 min, 15 min, 30 min (max 3 attempts). Log to Archive_Log.
Google Forms webhook
Inbound payload fails X-Goog-Channel-Token validation
Return HTTP 400. Do not process the payload. Log the rejection with the received token value (masked) and source IP to Archive_Log. No retry; wait for the next legitimate event.
Google Sheets write (new risk row)
HTTP 429 rate limit or 503 service unavailable
Retry with exponential backoff: 2 s, 8 s, 32 s (max 3 attempts). If all retries fail, write the pending row payload to a dead-letter queue in the orchestration platform and alert GMAIL_RISK_MANAGER_EMAIL with the failed submission details for manual entry.
Google Sheets read (Agent 2 poll)
Spreadsheet returns empty or malformed data
Log a warning to Archive_Log with the raw response. Skip this polling cycle and resume at the next 30-minute interval. Do not send any Slack or Gmail messages based on an empty or malformed read. Alert GMAIL_RISK_MANAGER_EMAIL if three consecutive polls return malformed data.
Google Sheets batchUpdate (score write)
Conflict or stale revision error (HTTP 400)
Re-fetch the current row state, reconcile with the intended write, and retry once. If the conflict persists, log the conflict details to Archive_Log and alert GMAIL_RISK_MANAGER_EMAIL for manual resolution. Do not overwrite confirmed scores with proposed scores.
Slack users.lookupByEmail
Owner email not found in workspace
Log a warning to Archive_Log noting the risk_id and owner_email. Fall back to sending a Gmail escalation to GMAIL_RISK_MANAGER_EMAIL flagging that the Slack owner lookup failed. Do not block the rest of the escalation workflow.
Slack chat.postMessage
HTTP 429 rate limit
Retry after the retry_after value returned in the Slack response header (typically 1 to 60 seconds). Maximum 3 retries. If all retries fail, fall back to sending a Gmail notification to the owner's email address directly and log the Slack failure to Archive_Log.
Slack chat.postMessage
Invalid channel or user ID (channel_not_found, user_not_found)
Do not retry. Log the error with the attempted channel or user ID to Archive_Log. Send a Gmail fallback notification to the owner's email and alert GMAIL_RISK_MANAGER_EMAIL that Slack routing is misconfigured for this risk owner.
Notion pages API (create report page)
Duplicate report page detected for current month
Skip page creation. Log a warning to Archive_Log. Continue the workflow using the existing page URL for distribution. Do not create a second page for the same month under any circumstances.
Notion pages API (create report page)
HTTP 502 or 503 gateway error
Retry with exponential backoff: 30 s, 2 min, 5 min (max 3 attempts). If all retries fail, alert GMAIL_RISK_MANAGER_EMAIL and GMAIL_STAKEHOLDER_LIST that the automated report failed to generate with a plain-text summary of key register stats pulled directly from Sheets as a temporary substitute.
Gmail send (escalation or distribution)
HTTP 429 or quota exhausted
Retry after 60 seconds. Maximum 3 retries per recipient. If retries are exhausted for a specific recipient, log the failure to Archive_Log and flag the unsent recipient in the report distribution record. Alert GMAIL_RISK_MANAGER_EMAIL of any unsent distribution emails.
Gmail send (escalation or distribution)
Invalid recipient address (4xx bounce)
Do not retry. Log the failed address and the associated risk_id or report month to Archive_Log. Alert GMAIL_RISK_MANAGER_EMAIL immediately. Remove the address from future sends until it is corrected in the credential store by the process owner.
General exception rule: any unhandled exception anywhere in the three agent workflows must be caught by the orchestration platform's global error handler, logged to Archive_Log with a full stack trace, and trigger an alert email to support@gofullspec.com as well as GMAIL_RISK_MANAGER_EMAIL. Workflows must never exit silently on an unhandled exception.
For build support or questions about this specification, contact the FullSpec team at support@gofullspec.com.
Integration and API SpecPage 3 of 3

More documents for this process

Every document generated for Risk Register Management.

Launch Plan
Operations · Owner
View
ROI and Business Case
Finance · Owner
View
Process Runbook / SOP
Operations · Owner
View
Developer Handover Pack
Technical · Developer
View
Test and QA Plan
Quality · Developer
View