Growth & Digital/Lead Agent — Production Architecture — agent brief
EDIT VIA GITHUB · /content
DRAFT / NOT FINAL — content pending review
LiveIn productionAgent build

Lead Agent — Production Architecture

The live production lead agent — a Basecamp-owned orchestration service that converts authenticated Marketo intent signals into validated, policy-checked Gong Engage flow assignments. This page is the architecture doc, verbatim, with the operational links live.

AGENT BRIEF
edit content/agent-briefs/lead-agent.md · new agent? copy _TEMPLATE.md

*Verbatim from "Lead Agent — Current Production Architecture" (source PDF linked in the sidebar). Marketo intake → Basecamp orchestration → Glean package → Gong Engage. Canonical scope: current production delivery, operational recovery, analytics, and explicit legacy boundaries. The code paths and live production settings were verified before publication.*

1. Executive summary

Lead Agent is a Basecamp-owned orchestration service that converts authenticated Marketo intent signals into a validated, policy-checked Gong Engage flow assignment. Salesforce is the identity and CRM truth, Redis holds durable run and queue state, Glean currently generates the production outbound package, Gong executes the cadence, and Slack plus the Basecamp console provide operational visibility.

  • Production delivery: all three operational playbook lanes currently use Glean as the delivered generator, Gong as the engagement provider, and no shadow generator.
  • Active lanes: Form Handraiser, Events & Webinar Handraiser, and Attended / No-show; English/non-English or attended/no-show routing selects one of six Gong flows.
  • Named-account behavior: Basecamp no longer applies a named-account allowlist. The account policy blocks only Salesforce Team Type Partner; every other Team Type remains eligible unless another guard blocks it.
  • Safety: duplicate-priority arbitration, fresh Salesforce booking checks, exact person/owner refresh, generated-copy validation, and a direct Gong active-flow check all run before assignment.
  • Retry behavior: a push retry reuses the stored package but re-runs current delivery settings and all time-sensitive policy, owner, and active-flow checks. A generation retry explicitly rebuilds the package.
  • Replies: Gong and the SDR mailbox handle production replies today. Basecamp has no Gmail push/watch receiver in production; its automated reply classifier remains scoped to legacy Outreach events.

Current production defaults: generator = Glean; engagement provider = Gong; Outreach push = off; Gong cool-off override = off; five main-worker slots and five outbound-worker slots.

2. System context

+------------------+        +----------------------+        +-------------------+
| Marketo programs | ---->  | Basecamp Lead Agent  | ---->  | Gong Engage       |
| + smart lists    |        | routing + jobs       |        | six prod flows    |
+------------------+        +----------+-----------+        +---------+---------+
                                       |                              |
                            | exact CRM reads             | flow/activity sync
                                       v                              v
                            +----------+-----------+        +---------+---------+
                            | Salesforce           | <----  | Gong managed data |
                            | person/account/owner |        | in Salesforce     |
                            +----------+-----------+        +-------------------+
                                       |
                          +------------+-------------+
                          |                          |
                          v                          v
                 +--------+---------+       +--------+---------+
                 | Glean generator  |       | Redis control    |
                 | research + copy  |       | jobs/queues/state|
                 +------------------+       +--------+---------+
                                                     |
                                        +------------+-------------+
                                        |                          |
                                        v                          v
                                +-------+--------+        +-------+--------+
                                | Basecamp UI    |        | Slack alerts   |
                                | ops + analytics|        | success/failure|
                                +----------------+        +----------------+

Component responsibilities

  • Marketo: decides when an eligible person emits a lane-specific webhook; three smart lists independently reconcile eligible records against Basecamp runs.
  • Basecamp: authenticates intake, resolves lane/owner/priority, persists jobs, runs generation and policy gates, calls Gong, and exposes retry and observability surfaces.
  • Salesforce: authoritative Lead/Contact identity, Account Team Type, campaign evidence, booking evidence, current owner, lifecycle outcomes, and Gong-managed activity fields.
  • Glean: current production research-and-messaging generator. It receives the exact Salesforce Lead/Contact ID and returns the v2 outbound package.
  • Gong Engage: authoritative flow-enrollment and flow-instance execution system. It consumes flow-instance variables generated by Lead Agent.
  • Redis: durable job hash, FIFO priority queues, delayed retry sets, distributed locks, settings, dedupe reservations, failure observations, and analytics snapshots.
  • Neon/token vault: maps Basecamp users to Okta identities and stores user-scoped OAuth tokens used by Salesforce, Glean, and legacy Gmail draft paths.
  • Slack: successful-enrollment notifications and deduplicated intake/pipeline failure alerts.

Authority by question

  • Was the webhook received and processed? Redis LeadAgentJob state.
  • Who is the person, account, or current owner? A fresh Salesforce read.
  • Is the prospect active in a flow right now? Direct Gong /v2/flows/prospects lookup.
  • What does the Run page's Salesforce current flow card show? A live, no-store Salesforce read of Gong-managed CRM fields; it is informational and can lag Gong.
  • Was an eligible Marketo record missed? The latest smart-list snapshot reconciled against production jobs and intentional exclusions.

3. Routing model

Three independent routing dimensions must remain separate. The operational playbook lane controls intake priority and flow family; the generator selection controls who creates the package; the language/status result selects the concrete Gong flow.

Marketo trigger
   |
   v
[operational playbook lane] -> [pinned generator] -> [package route/language]
   |                                                        |
   +---------------- priority + analytics ------------------+
                                                            v
                                                  [concrete Gong flow]

Operational lane:  form_handraiser | campaign_handraiser | webinar_attendance
Generator:         Glean now; GPT/Claude/native registry available by controlled selection
Language/status:   standard | non_english, or attended | no_show

Webhook-to-lane routing

leadAgentWebhookTriggerType
  absent / not supplied
      -> form_handraiser
      -> priority 1 (Critical)

  event_requested_contact
      -> campaign_handraiser
      -> priority 1 (Critical)

  webinar_attended_no_show
      -> webinar_attendance
      -> priority 3 (Low)

  present but empty, or any unknown value
      -> persisted Intake failure when the base lead is valid
      -> never enters a worker queue

The machine-to-machine endpoint is POST /api/lead-agent/webhook. It validates the Marketo shared secret, enforces a 300-authenticated-request-per-minute rate limit, validates the JSON contract, resolves routing, and persists a job before returning.

Owner resolution

Webhook contains sdrEmail?
  yes -> validate owner email -> enqueue
  no  -> read exact Salesforce Lead/Contact Owner.Email
          |
          +-- User owner (005...) found -> enqueue
          |
          +-- queue owner / no owner / lookup error
                  -> waiting_for_owner
                  -> retry at 2, 5, 10, 12 ... 30 minutes
                  -> enqueue when valid, otherwise fail without Glean/Gong

Owner resolution protects the system from assigning Gong work to a Salesforce queue or stale Marketo owner. The owner is refreshed again immediately before Gong assignment because ownership can change while generation is running.

Prospect priority arbitration

  • Automated jobs reserve a SHA-256 email key for 48 hours; manual and Testbed jobs bypass this arbitration.
  • A lower numeric priority supersedes a higher numeric priority. At equal priority, the first reservation remains the winner.
  • A suppressed job remains stored for audit, is marked completed with a higher_priority_lead_agent_job policy reason, and does not run generation or engagement.
  • Current defaults are Form = 1, Events & Webinar = 1, Attended / No-show = 3.

4. Queue and worker execution

                   immediate dispatch
                          |
                          v
Marketo -> Redis main queue -> one-job main worker
           P1/P2/P3           |
                              +-> schedule v2 outbound package
                              +-> run v1 compatibility pipeline
                                        |
                                        v
                    Redis outbound queue -> one-job outbound worker
                          P1/P2/P3            |
                                              v
                          Salesforce -> generator -> policy -> Gong

Recovery alarms: main cron every 2 min | outbound cron every 2 min
  • Durability: lead-agent:jobs stores the complete serialized run; queue entries contain only job IDs or compact work items.
  • Ordering: workers always drain Critical, then legacy/Medium, then Low; each queue is FIFO.
  • Concurrency: main and outbound processing each have a five-slot Redis lease pool. Every invocation dequeues exactly one job so it retains the full serverless time budget.
  • Dispatch: enqueue calls the authenticated internal dispatcher immediately; the two-minute crons are recovery alarms, not normal scheduling.
  • Crash recovery: in-flight main or outbound work stale for 16 minutes is re-queued or failed according to its attempt budget.

Persisted state model

Main job
  waiting_for_owner
      -> pending -> researching -> qualifying -> writing_email -> notifying
      -> awaiting_review / awaiting_v2 / completed
      -> failed

Outbound package
  pending -> in_progress -> complete
      |            |
      v            v
    failed    engagement push
              pending -> in_progress
                  |            |
                  v            v
              complete    failed/skipped/disabled

The main status and outbound status are deliberately separate. A run can have a completed v1 path while the v2/Glean or Gong stage is still pending, failed, skipped, or complete.

5. Research and message generation

Authoritative production v2 path

Salesforce person ID
    -> exact Lead/Contact hydration
    -> pinned production generator
    -> normalize package
    -> parse structured output
    -> validate identity + four emails
    -> derive standard/non-English lane
    -> persist package + provenance
    -> engagement policy and Gong
  • Exact Salesforce preflight: the worker reloads the stored Lead/Contact and requires first name, last name, email, and company before calling the generator.
  • Generator selection: the playbook lane's delivered generator and optional shadow generator are pinned on the job at enqueue. All production lanes currently resolve to Glean with shadow off.
  • Glean call: Basecamp invokes the configured Glean agent with contact_id through /rest/api/v1/agents/runs/wait, using a client API token or assignee OAuth.
  • Package contract: the response may include Salesforce context, a research report, routing metadata, and a structured sequence. Delivery requires matching identity and exactly four usable email subjects/bodies; up to two call scripts are mapped when present.
  • Retries: retryable generator, Salesforce-preflight, incomplete-package, and transient HTTP failures get up to three attempts with delayed retries after two and ten minutes.
  • Persistence: the accepted package, derived language, generator route, evidence/provenance, duration, attempt history, and AI usage where applicable are stored on the job.

v1 compatibility path

Unless the deployment-wide v2-only flag is enabled, the main worker also runs the older v1 gather/synthesize/qualify/single-email path in parallel. This is why Run pages can show both v1 Lead agent and v2 Glean agent progress. The v2 package, not the v1 email, is authoritative for production Gong enrollment.

  • The v1 path gathers Salesforce plus Glean context, creates a research report, qualification, and a single draft.
  • The live general v1 Slack alert setting is off. A successful new Gong flow assignment still sends its dedicated Prospect Sequenced message.
  • The legacy approval action can create a Gmail draft with the SDR's user OAuth token; it is not the production Gong reply-ingestion mechanism.

Native agents, Testbed, and shadow comparisons

Basecamp has a typed registry for deterministic, GPT, Claude, Event, Webinar, and Asset Download generators. Production selection is controlled per playbook lane and pinned per job. Native Testbed and shadow runs are generation-only: persisted delivery flags are false and registry policy forbids engagement delivery.

6. Enrollment decision and Gong guardrails

Accepted package
  |
  +-> Prospect priority still owns the lead?
  |       no -> suppress
  |
  +-> Fresh Salesforce booking preflight succeeds?
  |       booked meeting -> intentional skip
  |       read failure   -> fail closed
  |
  +-> Salesforce Account Team Type = Partner?
  |       yes -> policy block
  |
  +-> Lane/push/flow settings enabled and flow ID present?
  |       no -> disabled or configuration failure
  |
  +-> Generated email copy still valid?
  |       no -> refuse assignment
  |
  +-> Direct Gong lookup: active Pending/Running/Paused flow?
  |       same target -> idempotent already-assigned success
  |       other flow  -> intentional skip; do not re-sequence
  |
  +-> Refresh exact Salesforce User owner email
  |       missing/queue -> fail
  |
  +-> Assign Gong flow with variables
          assigned          -> persist instance + Slack
          transient failure -> bounded retry
          license/config error -> fail

Sequencing policy

  • Booking protection: production delivery performs a fresh Salesforce Event and qualified CampaignMember check, with a three-day lookback around the job anchor through the current check. A detected prior booking blocks enrollment.
  • Fail-closed preflight: if no Salesforce-connected read identity can complete the required booking check, the push fails instead of assuming no booking.
  • Account policy: Team Type Partner is blocked. Strategic, Corporate, named, and other non-Partner values are not filtered by a Basecamp named-account allowlist.
  • Policy evidence is persisted with status, reason code, source, Team Type, and check timestamp.

Gong flow selection

form_handraiser
  standard    -> 2578787343818674556
                 Lead Agent HIL | Inbound Handraiser Corporate (English)
  non_english -> 1601520484787926268
                 Lead Agent HIL | Inbound Handraiser Corporate (Non-English)

campaign_handraiser
  standard    -> 5139000330086708116
                 Lead Agent HIL | Events & Webinar Handraiser Corporate (English)
  non_english -> 2134352308209459293
                 Lead Agent HIL | Events & Webinar Handraiser Corporate (Non-English)

webinar_attendance
  attended / visited booth -> 2475613234451028569
                              Lead Agent HIL | Attended
  no show                  -> 9057697751217304174
                              Lead Agent HIL | No-Show

Language is read from the accepted package for Form and Events & Webinar lanes. Attended / No-show routing instead reloads eligible EV/TS/WB Salesforce CampaignMember evidence: Attended or Visited Booth selects Attended; No Show selects No-Show. Exact campaign ID/name is preferred; an ambiguous time-window fallback fails closed. Non-English attendance routing is disabled.

Assignment payload and owner

  • Variables: four email subjects, four email bodies, and up to two call bodies create the normal ten Lead Agent flow-instance variables. Attendance flows also receive the resolved event name.
  • Owner: Basecamp refreshes Salesforce Owner.Email immediately before assignment and passes it as Gong flowInstanceOwnerEmail.
  • License boundary: the Salesforce owner must exist in Gong with an Engage license. Gong 403 license errors are genuine assignment failures and are not rerouted to another SDR.
  • Cool-off: the production cool-off override is off; normal Gong rules apply.
  • Transient retries: Gong assignment retries up to five total attempts with one-, two-, four-, and eight-second backoff for rate limits, timeouts, server errors, and recognized transient CRM-sync errors.

Existing-flow semantics

  • Open means Pending, Running, or Paused. Finished, FinishedNoReply, and FinishedResponse are not treated as active.
  • Same flow already open: return idempotent success and retain the existing flow instance; no duplicate assignment or success Slack post.
  • Different flow already open: skip assignment, mark blocked-by-existing-flow, and do not write a new Lead Agent flow ID/state.
  • Gong's assignment endpoint is a second guard. If it reports an existing-flow conflict after preflight, Basecamp refreshes Gong state and records the same intentional skip.

7. State, status, and reconciliation

Direct Gong API              Redis job                    Salesforce managed fields
(enrollment guard)           (persisted run truth)        (CRM display/sync)
      |                            |                            |
      +---- checked on push ------+                             |
      |                            +---- Run API ---------------+
      |                            |
      +---- 15-min status poll --->+---- UI combines both sources

Run-page status semantics

  • Gong Engage sync shows persisted result fields from the job: provider status, target flow, instance ID/status, owner, variable count, and errors.
  • Salesforce current flow is fetched live when the page requests includeGongSalesforce=true. The API is dynamic and returns Cache-Control: private, no-store.
  • The Salesforce card is not a point-in-time snapshot of the original run and is not the enrollment guard. It can change between page loads and can lag direct Gong state.
  • A person showing Finished (removed manually) is not active and may be eligible for a later assignment if every current policy gate passes. A person showing In progress should also be present in direct Gong and will be blocked.

Scheduled reconciliation

  • Every 15 minutes: poll every stored open Gong flow instance and update status, owner, and workspace in Redis.
  • Hourly at minute 7: rebuild the Gong call-task snapshot used by Flow activity.
  • Hourly: refresh Gong booking and MQL-to-SQL snapshots; the mutable 90-day tail is refreshed hourly and full history is rebuilt during the daily Chicago 2 a.m. run or when snapshots are missing.
  • Flow activity excludes failed, skipped, incomplete, and off-configuration attempts. Intake failures is the canonical page for those records.

8. Failure detection and recovery

Failure model

Eligible Marketo record
   |
   +-- no matching production job ----------> missing webhook
   |
   +-- owner never resolves ----------------> owner-resolution failure
   |
   +-- main pipeline fails -----------------> main-pipeline failure
   |
   +-- package fails / exhausts retries ----> generator failure
   |
   +-- booking read cannot complete --------> sequencing-preflight failure
   |
   +-- policy intentionally blocks ---------> expected exclusion / warning
   |
   +-- Gong rejects or no state is stored --> engagement / missing-flow failure
   |
   +-- no progress for 45 min --------------> stale-processing warning

Expected exclusions are separated from technical failures. A prior meeting, a higher-priority winning job, Partner Team Type, or an already-active Gong flow should not be interpreted as a broken assignment pipeline.

Automatic recovery

  • Main pipeline exceptions re-queue the job up to three times. Stuck in-flight jobs are recovered after 16 minutes.
  • Generator work has three attempts with delayed retry and its own 16-minute stuck-work recovery.
  • Gong assignment performs its short bounded transient retry loop inside the push.
  • Owner resolution retries for up to 30 minutes without sending the lead to Glean, Gong, Outreach, or success Slack.

Admin retry semantics

Retry requested from Intake failures
  |
  +-- already enrolled or active in another flow -> retry refused
  |
  +-- generator failed / stored package invalid
  |       -> regenerate v2 package
  |
  +-- generator complete and no enrollment
          -> reuse stored package
          -> re-read current lane flow settings
          -> fresh Salesforce booking + Team Type + owner checks
          -> fresh direct Gong active-flow check
          -> assign only if every gate still passes

A push retry does not replay Marketo intake, rerun the v1 pipeline, or call Glean again. It does re-evaluate every condition that can change over time. The failed vendor/category is appended to sequencing failure history before the retry.

Marketo smart-list reconciliation

Every 20 minutes
  Form MQL smart list --------------------+
  Requested-contact smart list -----------+-> export snapshot
  Attendance/no-show smart list ----------+        |
                                                   v
                                    match lane + identity + time
                                                   |
                          +------------------------+------------------+
                          |                                           |
                  resolved run /                              unresolved or
                  intentional exclusion                       failed handoff
                          |                                           |
                        ignore                              failure observation
                                                            + deduped Slack
  • The smart lists are an observability and reconciliation layer, not the primary dispatch path. They detect eligible records whose webhook/run/enrollment chain is missing.
  • Matching uses playbook lane plus Marketo ID or normalized email, with event-time bounds. Sequence evidence or an intentional exclusion resolves the record.
  • The monitor filters Disqualified for all lanes and applies additional post-MQL status/exclusion rules to the campaign-driven lanes. It does not use the retired named-account filter in Basecamp.
  • Failures are stored as observations, surfaced in Intake failures, and alerted in production with Redis-backed deduplication.

9. Notifications and reply handling

Slack notifications

  • New Gong assignment: only a newly assigned production webhook flow posts Lead Agent Prospect Sequenced with prospect, owner, lane, campaign, Salesforce link, and Run link.
  • No duplicate post: already-assigned same-flow results and active-other-flow skips do not send the success message.
  • Failures: the 20-minute reconciliation job posts deduplicated missing-intake and job-stage alerts. These are operational alerts, separate from the v1 general Slack-alert toggle.

Current production reply lifecycle

Lead Agent variables -> Gong flow sends from SDR-connected mailbox
                              |
                     prospect replies
                              |
             +----------------+----------------+
             |                                 |
             v                                 v
     SDR Gmail / Gong UI                Gong reply rules
             |                          pause/finish flow
             +----------------+----------------+
                              |
                              v
                   Gong/Salesforce activity
                              |
                              v
                   SDR follow-up + analytics
  • Gong and the connected SDR mailbox are the production systems for receiving and responding to replies.
  • Basecamp currently has no Gmail watch, Pub/Sub push receiver, Gmail history consumer, or Gong reply webhook for these production inboxes.
  • The existing Basecamp reply pipeline starts from Outreach mailing.replied webhooks, hydrates Outreach data, polls Salesforce for the inbound task, posts Slack, and classifies with Glean. Because production Outreach enrollment is off, new Gong enrollments do not enter that scope.
  • Current Gmail API use is limited to creating a draft from an approved v1 email with a user's OAuth token; it does not monitor replies.

Future Gmail push boundary — not yet implemented

Google Workspace authorization
    -> Gmail mailbox watch registration
    -> Google Pub/Sub topic
    -> Basecamp HTTPS push endpoint
    -> Gmail history/message hydration
    -> Lead Agent run/thread matching
    -> dedupe + classify + Slack/console
    -> watch renewal + replay/recovery

This future path requires an actual Basecamp HTTPS receiver plus mailbox authorization and Pub/Sub publishing permissions. The Google service identity that publishes Gmail notifications only authenticates delivery into Pub/Sub; it does not grant Basecamp access to read an SDR mailbox.

10. Security and configuration boundaries

Authentication and authorization

  • Marketo webhook: shared-secret authentication, authenticated rate limiting, request-size bounds, and strict schema validation.
  • Internal workers and crons: CRON_SECRET bearer authentication; production fails closed when the secret is missing.
  • Basecamp UI/API: signed-in session; Run access is limited to assigned SDR, manual initiator, or admin. Admin settings and failure retries require admin role.
  • Production settings: environment-scoped keys isolate local/preview/test, and production writes require explicit authorization from the production hostname.
  • External credentials: Salesforce and optional Glean OAuth are user/token-vault based; headless Glean may use a client token; Gong uses server-side access key credentials; Slack uses the configured bot.
  • Testbed safety: native Testbed and shadow jobs cannot deliver even if stale UI toggles are malformed; the registry and persisted job flags both enforce no-push behavior.

Pinned versus live configuration

Pinned when the job enters the queue
  playbook lane | queue priority | delivered/shadow generator
  generator config snapshot | engagement provider

Re-read at delivery or push retry
  lane enabled/push/flow switches | target flow ID
  fresh booking evidence | Team Type | current Salesforce owner
  direct Gong active-flow state

Persisted after the attempt
  package/provenance | policy decision | provider result
  flow/instance IDs | errors | timestamps | retry history

This split prevents an active job from silently changing generator while still ensuring enrollment uses current safety and operational state.

11. Current production configuration

Delivery provider: Gong
Delivered generator: Glean for all three playbook lanes
Shadow generator: off for all three lanes
Outreach push/sequence: off for Form, Events & Webinar, and Attendance
Gong cool-off override: off
General v1 Slack alerts: off
Dedicated Gong enrollment success + failure alerts: active

Lane                    Priority   Variants enabled
form_handraiser         1          English + Non-English
campaign_handraiser     1          English + Non-English
webinar_attendance      3          Attended + No-Show
                                   Non-English disabled

The configured but disabled attendance non-English flow ID is not part of production routing. Changing a flow ID or enablement switch in the Production Lanes console affects subsequent delivery attempts and push retries; it does not rewrite prior job history.

12. Operating model

Ownership

  • Marketing Operations: Marketo trigger programs, campaign 300 wait logic, smart-list eligibility, trigger payload fields, and campaign identifiers/statuses.
  • Basecamp Engineering: webhook contract, Redis queues/state, generator orchestration, policy gates, Gong API integration, retries, monitoring, and admin surfaces.
  • Salesforce/RevOps: Lead/Contact owner correctness, Account Team Type, booking/lifecycle evidence, Gong managed-package fields, and CRM synchronization.
  • Gong Administration: flow/ruleset content, variable names, mailbox connection, owner Engage licensing, reply-stop behavior, and flow-folder hygiene.
  • SDR: connected mailbox, valid Salesforce ownership, execution of manual steps, and human response to replies.

Fast triage

  • Eligible lead but no Run: inspect Intake failures and the matching Marketo smart-list snapshot first.
  • Run exists but no package: inspect owner state, Salesforce ID/preflight, generator status, attempts, and next retry.
  • Package exists but no flow: read Sequencing policy, then Gong Engage sync; do not infer failure from the live Salesforce card alone.
  • Gong 403 names an SDR without Engage: fix the current Salesforce owner's Gong license or ownership, then retry the push.
  • Salesforce says In progress but retry seems possible: direct Gong preflight is the actual guard. If Gong reports an open flow, Basecamp skips assignment even if Salesforce is stale.
  • Salesforce says Finished (removed manually): Finished is not open; a later push may enroll only after every fresh guard passes.

13. Known constraints and deliberate debt

  • Dual-path complexity: v1 and v2 can run together, but only v2 controls production Gong delivery. The UI must continue to label them separately.
  • Gmail reply gap: production reply ingestion/classification out of Gong-connected inboxes is not implemented in Basecamp. Waiting on Gmail API access.
  • Salesforce sync lag: the current-flow card is useful CRM context, not a safe replacement for direct Gong flow-state checks.
  • Attendance correlation: exact campaign metadata is preferred; the time-window fallback rejects ambiguous multi-campaign matches rather than guessing.
  • Mutable operations: flow enablement and IDs are deliberately re-read at delivery/retry, so configuration changes can affect an old failed job when it is retried.

Appendix A — Key interfaces

POST /api/lead-agent/webhook
  Marketo machine intake

POST /api/cron/lead-agent-dispatch
  immediate authenticated worker kick

GET  /api/cron/lead-agent
GET  /api/cron/lead-agent-glean
  two-minute recovery workers

GET  /api/cron/lead-agent-marketo-missed
  20-minute smart-list reconciliation

GET  /api/cron/lead-agent-gong-flows
  15-minute stored flow-status refresh

GET  /api/lead-agent/runs/{id}?includeGongSalesforce=true
  authorized run + live Salesforce Gong fields

POST /api/admin/lead-agent/failures/{jobId}/retry
  admin-only generation or push retry

Appendix B — Reading one run

Lead / source / lane
  -> confirms intake identity and operational route

v1 Lead agent
  -> compatibility research/qualification/draft progress

v2 Glean agent
  -> authoritative package generation progress

Sequencing policy
  -> latest stored booking/Team Type/priority decision

Gong Engage sync
  -> persisted assignment attempt and flow instance

Salesforce current flow
  -> live CRM reflection of Gong-managed fields, not run-time evidence

*Verbatim from "Lead Agent — Current Production Architecture" (source PDF linked in the sidebar). Marketo intake → Basecamp orchestration → Glean package → Gong Engage. Canonical scope: current production delivery, operational recovery, analytics, and explicit legacy boundaries. The code paths and live production settings were verified before publication.*

1. Executive summary

Lead Agent is a Basecamp-owned orchestration service that converts authenticated Marketo intent signals into a validated, policy-checked Gong Engage flow assignment. Salesforce is the identity and CRM truth, Redis holds durable run and queue state, Glean currently generates the production outbound package, Gong executes the cadence, and Slack plus the Basecamp console provide operational visibility.

  • Production delivery: all three operational playbook lanes currently use Glean as the delivered generator, Gong as the engagement provider, and no shadow generator.
  • Active lanes: Form Handraiser, Events & Webinar Handraiser, and Attended / No-show; English/non-English or attended/no-show routing selects one of six Gong flows.
  • Named-account behavior: Basecamp no longer applies a named-account allowlist. The account policy blocks only Salesforce Team Type Partner; every other Team Type remains eligible unless another guard blocks it.
  • Safety: duplicate-priority arbitration, fresh Salesforce booking checks, exact person/owner refresh, generated-copy validation, and a direct Gong active-flow check all run before assignment.
  • Retry behavior: a push retry reuses the stored package but re-runs current delivery settings and all time-sensitive policy, owner, and active-flow checks. A generation retry explicitly rebuilds the package.
  • Replies: Gong and the SDR mailbox handle production replies today. Basecamp has no Gmail push/watch receiver in production; its automated reply classifier remains scoped to legacy Outreach events.

Current production defaults: generator = Glean; engagement provider = Gong; Outreach push = off; Gong cool-off override = off; five main-worker slots and five outbound-worker slots.

2. System context

+------------------+        +----------------------+        +-------------------+
| Marketo programs | ---->  | Basecamp Lead Agent  | ---->  | Gong Engage       |
| + smart lists    |        | routing + jobs       |        | six prod flows    |
+------------------+        +----------+-----------+        +---------+---------+
                                       |                              |
                            | exact CRM reads             | flow/activity sync
                                       v                              v
                            +----------+-----------+        +---------+---------+
                            | Salesforce           | <----  | Gong managed data |
                            | person/account/owner |        | in Salesforce     |
                            +----------+-----------+        +-------------------+
                                       |
                          +------------+-------------+
                          |                          |
                          v                          v
                 +--------+---------+       +--------+---------+
                 | Glean generator  |       | Redis control    |
                 | research + copy  |       | jobs/queues/state|
                 +------------------+       +--------+---------+
                                                     |
                                        +------------+-------------+
                                        |                          |
                                        v                          v
                                +-------+--------+        +-------+--------+
                                | Basecamp UI    |        | Slack alerts   |
                                | ops + analytics|        | success/failure|
                                +----------------+        +----------------+

Component responsibilities

  • Marketo: decides when an eligible person emits a lane-specific webhook; three smart lists independently reconcile eligible records against Basecamp runs.
  • Basecamp: authenticates intake, resolves lane/owner/priority, persists jobs, runs generation and policy gates, calls Gong, and exposes retry and observability surfaces.
  • Salesforce: authoritative Lead/Contact identity, Account Team Type, campaign evidence, booking evidence, current owner, lifecycle outcomes, and Gong-managed activity fields.
  • Glean: current production research-and-messaging generator. It receives the exact Salesforce Lead/Contact ID and returns the v2 outbound package.
  • Gong Engage: authoritative flow-enrollment and flow-instance execution system. It consumes flow-instance variables generated by Lead Agent.
  • Redis: durable job hash, FIFO priority queues, delayed retry sets, distributed locks, settings, dedupe reservations, failure observations, and analytics snapshots.
  • Neon/token vault: maps Basecamp users to Okta identities and stores user-scoped OAuth tokens used by Salesforce, Glean, and legacy Gmail draft paths.
  • Slack: successful-enrollment notifications and deduplicated intake/pipeline failure alerts.

Authority by question

  • Was the webhook received and processed? Redis LeadAgentJob state.
  • Who is the person, account, or current owner? A fresh Salesforce read.
  • Is the prospect active in a flow right now? Direct Gong /v2/flows/prospects lookup.
  • What does the Run page's Salesforce current flow card show? A live, no-store Salesforce read of Gong-managed CRM fields; it is informational and can lag Gong.
  • Was an eligible Marketo record missed? The latest smart-list snapshot reconciled against production jobs and intentional exclusions.

3. Routing model

Three independent routing dimensions must remain separate. The operational playbook lane controls intake priority and flow family; the generator selection controls who creates the package; the language/status result selects the concrete Gong flow.

Marketo trigger
   |
   v
[operational playbook lane] -> [pinned generator] -> [package route/language]
   |                                                        |
   +---------------- priority + analytics ------------------+
                                                            v
                                                  [concrete Gong flow]

Operational lane:  form_handraiser | campaign_handraiser | webinar_attendance
Generator:         Glean now; GPT/Claude/native registry available by controlled selection
Language/status:   standard | non_english, or attended | no_show

Webhook-to-lane routing

leadAgentWebhookTriggerType
  absent / not supplied
      -> form_handraiser
      -> priority 1 (Critical)

  event_requested_contact
      -> campaign_handraiser
      -> priority 1 (Critical)

  webinar_attended_no_show
      -> webinar_attendance
      -> priority 3 (Low)

  present but empty, or any unknown value
      -> persisted Intake failure when the base lead is valid
      -> never enters a worker queue

The machine-to-machine endpoint is POST /api/lead-agent/webhook. It validates the Marketo shared secret, enforces a 300-authenticated-request-per-minute rate limit, validates the JSON contract, resolves routing, and persists a job before returning.

Owner resolution

Webhook contains sdrEmail?
  yes -> validate owner email -> enqueue
  no  -> read exact Salesforce Lead/Contact Owner.Email
          |
          +-- User owner (005...) found -> enqueue
          |
          +-- queue owner / no owner / lookup error
                  -> waiting_for_owner
                  -> retry at 2, 5, 10, 12 ... 30 minutes
                  -> enqueue when valid, otherwise fail without Glean/Gong

Owner resolution protects the system from assigning Gong work to a Salesforce queue or stale Marketo owner. The owner is refreshed again immediately before Gong assignment because ownership can change while generation is running.

Prospect priority arbitration

  • Automated jobs reserve a SHA-256 email key for 48 hours; manual and Testbed jobs bypass this arbitration.
  • A lower numeric priority supersedes a higher numeric priority. At equal priority, the first reservation remains the winner.
  • A suppressed job remains stored for audit, is marked completed with a higher_priority_lead_agent_job policy reason, and does not run generation or engagement.
  • Current defaults are Form = 1, Events & Webinar = 1, Attended / No-show = 3.

4. Queue and worker execution

                   immediate dispatch
                          |
                          v
Marketo -> Redis main queue -> one-job main worker
           P1/P2/P3           |
                              +-> schedule v2 outbound package
                              +-> run v1 compatibility pipeline
                                        |
                                        v
                    Redis outbound queue -> one-job outbound worker
                          P1/P2/P3            |
                                              v
                          Salesforce -> generator -> policy -> Gong

Recovery alarms: main cron every 2 min | outbound cron every 2 min
  • Durability: lead-agent:jobs stores the complete serialized run; queue entries contain only job IDs or compact work items.
  • Ordering: workers always drain Critical, then legacy/Medium, then Low; each queue is FIFO.
  • Concurrency: main and outbound processing each have a five-slot Redis lease pool. Every invocation dequeues exactly one job so it retains the full serverless time budget.
  • Dispatch: enqueue calls the authenticated internal dispatcher immediately; the two-minute crons are recovery alarms, not normal scheduling.
  • Crash recovery: in-flight main or outbound work stale for 16 minutes is re-queued or failed according to its attempt budget.

Persisted state model

Main job
  waiting_for_owner
      -> pending -> researching -> qualifying -> writing_email -> notifying
      -> awaiting_review / awaiting_v2 / completed
      -> failed

Outbound package
  pending -> in_progress -> complete
      |            |
      v            v
    failed    engagement push
              pending -> in_progress
                  |            |
                  v            v
              complete    failed/skipped/disabled

The main status and outbound status are deliberately separate. A run can have a completed v1 path while the v2/Glean or Gong stage is still pending, failed, skipped, or complete.

5. Research and message generation

Authoritative production v2 path

Salesforce person ID
    -> exact Lead/Contact hydration
    -> pinned production generator
    -> normalize package
    -> parse structured output
    -> validate identity + four emails
    -> derive standard/non-English lane
    -> persist package + provenance
    -> engagement policy and Gong
  • Exact Salesforce preflight: the worker reloads the stored Lead/Contact and requires first name, last name, email, and company before calling the generator.
  • Generator selection: the playbook lane's delivered generator and optional shadow generator are pinned on the job at enqueue. All production lanes currently resolve to Glean with shadow off.
  • Glean call: Basecamp invokes the configured Glean agent with contact_id through /rest/api/v1/agents/runs/wait, using a client API token or assignee OAuth.
  • Package contract: the response may include Salesforce context, a research report, routing metadata, and a structured sequence. Delivery requires matching identity and exactly four usable email subjects/bodies; up to two call scripts are mapped when present.
  • Retries: retryable generator, Salesforce-preflight, incomplete-package, and transient HTTP failures get up to three attempts with delayed retries after two and ten minutes.
  • Persistence: the accepted package, derived language, generator route, evidence/provenance, duration, attempt history, and AI usage where applicable are stored on the job.

v1 compatibility path

Unless the deployment-wide v2-only flag is enabled, the main worker also runs the older v1 gather/synthesize/qualify/single-email path in parallel. This is why Run pages can show both v1 Lead agent and v2 Glean agent progress. The v2 package, not the v1 email, is authoritative for production Gong enrollment.

  • The v1 path gathers Salesforce plus Glean context, creates a research report, qualification, and a single draft.
  • The live general v1 Slack alert setting is off. A successful new Gong flow assignment still sends its dedicated Prospect Sequenced message.
  • The legacy approval action can create a Gmail draft with the SDR's user OAuth token; it is not the production Gong reply-ingestion mechanism.

Native agents, Testbed, and shadow comparisons

Basecamp has a typed registry for deterministic, GPT, Claude, Event, Webinar, and Asset Download generators. Production selection is controlled per playbook lane and pinned per job. Native Testbed and shadow runs are generation-only: persisted delivery flags are false and registry policy forbids engagement delivery.

6. Enrollment decision and Gong guardrails

Accepted package
  |
  +-> Prospect priority still owns the lead?
  |       no -> suppress
  |
  +-> Fresh Salesforce booking preflight succeeds?
  |       booked meeting -> intentional skip
  |       read failure   -> fail closed
  |
  +-> Salesforce Account Team Type = Partner?
  |       yes -> policy block
  |
  +-> Lane/push/flow settings enabled and flow ID present?
  |       no -> disabled or configuration failure
  |
  +-> Generated email copy still valid?
  |       no -> refuse assignment
  |
  +-> Direct Gong lookup: active Pending/Running/Paused flow?
  |       same target -> idempotent already-assigned success
  |       other flow  -> intentional skip; do not re-sequence
  |
  +-> Refresh exact Salesforce User owner email
  |       missing/queue -> fail
  |
  +-> Assign Gong flow with variables
          assigned          -> persist instance + Slack
          transient failure -> bounded retry
          license/config error -> fail

Sequencing policy

  • Booking protection: production delivery performs a fresh Salesforce Event and qualified CampaignMember check, with a three-day lookback around the job anchor through the current check. A detected prior booking blocks enrollment.
  • Fail-closed preflight: if no Salesforce-connected read identity can complete the required booking check, the push fails instead of assuming no booking.
  • Account policy: Team Type Partner is blocked. Strategic, Corporate, named, and other non-Partner values are not filtered by a Basecamp named-account allowlist.
  • Policy evidence is persisted with status, reason code, source, Team Type, and check timestamp.

Gong flow selection

form_handraiser
  standard    -> 2578787343818674556
                 Lead Agent HIL | Inbound Handraiser Corporate (English)
  non_english -> 1601520484787926268
                 Lead Agent HIL | Inbound Handraiser Corporate (Non-English)

campaign_handraiser
  standard    -> 5139000330086708116
                 Lead Agent HIL | Events & Webinar Handraiser Corporate (English)
  non_english -> 2134352308209459293
                 Lead Agent HIL | Events & Webinar Handraiser Corporate (Non-English)

webinar_attendance
  attended / visited booth -> 2475613234451028569
                              Lead Agent HIL | Attended
  no show                  -> 9057697751217304174
                              Lead Agent HIL | No-Show

Language is read from the accepted package for Form and Events & Webinar lanes. Attended / No-show routing instead reloads eligible EV/TS/WB Salesforce CampaignMember evidence: Attended or Visited Booth selects Attended; No Show selects No-Show. Exact campaign ID/name is preferred; an ambiguous time-window fallback fails closed. Non-English attendance routing is disabled.

Assignment payload and owner

  • Variables: four email subjects, four email bodies, and up to two call bodies create the normal ten Lead Agent flow-instance variables. Attendance flows also receive the resolved event name.
  • Owner: Basecamp refreshes Salesforce Owner.Email immediately before assignment and passes it as Gong flowInstanceOwnerEmail.
  • License boundary: the Salesforce owner must exist in Gong with an Engage license. Gong 403 license errors are genuine assignment failures and are not rerouted to another SDR.
  • Cool-off: the production cool-off override is off; normal Gong rules apply.
  • Transient retries: Gong assignment retries up to five total attempts with one-, two-, four-, and eight-second backoff for rate limits, timeouts, server errors, and recognized transient CRM-sync errors.

Existing-flow semantics

  • Open means Pending, Running, or Paused. Finished, FinishedNoReply, and FinishedResponse are not treated as active.
  • Same flow already open: return idempotent success and retain the existing flow instance; no duplicate assignment or success Slack post.
  • Different flow already open: skip assignment, mark blocked-by-existing-flow, and do not write a new Lead Agent flow ID/state.
  • Gong's assignment endpoint is a second guard. If it reports an existing-flow conflict after preflight, Basecamp refreshes Gong state and records the same intentional skip.

7. State, status, and reconciliation

Direct Gong API              Redis job                    Salesforce managed fields
(enrollment guard)           (persisted run truth)        (CRM display/sync)
      |                            |                            |
      +---- checked on push ------+                             |
      |                            +---- Run API ---------------+
      |                            |
      +---- 15-min status poll --->+---- UI combines both sources

Run-page status semantics

  • Gong Engage sync shows persisted result fields from the job: provider status, target flow, instance ID/status, owner, variable count, and errors.
  • Salesforce current flow is fetched live when the page requests includeGongSalesforce=true. The API is dynamic and returns Cache-Control: private, no-store.
  • The Salesforce card is not a point-in-time snapshot of the original run and is not the enrollment guard. It can change between page loads and can lag direct Gong state.
  • A person showing Finished (removed manually) is not active and may be eligible for a later assignment if every current policy gate passes. A person showing In progress should also be present in direct Gong and will be blocked.

Scheduled reconciliation

  • Every 15 minutes: poll every stored open Gong flow instance and update status, owner, and workspace in Redis.
  • Hourly at minute 7: rebuild the Gong call-task snapshot used by Flow activity.
  • Hourly: refresh Gong booking and MQL-to-SQL snapshots; the mutable 90-day tail is refreshed hourly and full history is rebuilt during the daily Chicago 2 a.m. run or when snapshots are missing.
  • Flow activity excludes failed, skipped, incomplete, and off-configuration attempts. Intake failures is the canonical page for those records.

8. Failure detection and recovery

Failure model

Eligible Marketo record
   |
   +-- no matching production job ----------> missing webhook
   |
   +-- owner never resolves ----------------> owner-resolution failure
   |
   +-- main pipeline fails -----------------> main-pipeline failure
   |
   +-- package fails / exhausts retries ----> generator failure
   |
   +-- booking read cannot complete --------> sequencing-preflight failure
   |
   +-- policy intentionally blocks ---------> expected exclusion / warning
   |
   +-- Gong rejects or no state is stored --> engagement / missing-flow failure
   |
   +-- no progress for 45 min --------------> stale-processing warning

Expected exclusions are separated from technical failures. A prior meeting, a higher-priority winning job, Partner Team Type, or an already-active Gong flow should not be interpreted as a broken assignment pipeline.

Automatic recovery

  • Main pipeline exceptions re-queue the job up to three times. Stuck in-flight jobs are recovered after 16 minutes.
  • Generator work has three attempts with delayed retry and its own 16-minute stuck-work recovery.
  • Gong assignment performs its short bounded transient retry loop inside the push.
  • Owner resolution retries for up to 30 minutes without sending the lead to Glean, Gong, Outreach, or success Slack.

Admin retry semantics

Retry requested from Intake failures
  |
  +-- already enrolled or active in another flow -> retry refused
  |
  +-- generator failed / stored package invalid
  |       -> regenerate v2 package
  |
  +-- generator complete and no enrollment
          -> reuse stored package
          -> re-read current lane flow settings
          -> fresh Salesforce booking + Team Type + owner checks
          -> fresh direct Gong active-flow check
          -> assign only if every gate still passes

A push retry does not replay Marketo intake, rerun the v1 pipeline, or call Glean again. It does re-evaluate every condition that can change over time. The failed vendor/category is appended to sequencing failure history before the retry.

Marketo smart-list reconciliation

Every 20 minutes
  Form MQL smart list --------------------+
  Requested-contact smart list -----------+-> export snapshot
  Attendance/no-show smart list ----------+        |
                                                   v
                                    match lane + identity + time
                                                   |
                          +------------------------+------------------+
                          |                                           |
                  resolved run /                              unresolved or
                  intentional exclusion                       failed handoff
                          |                                           |
                        ignore                              failure observation
                                                            + deduped Slack
  • The smart lists are an observability and reconciliation layer, not the primary dispatch path. They detect eligible records whose webhook/run/enrollment chain is missing.
  • Matching uses playbook lane plus Marketo ID or normalized email, with event-time bounds. Sequence evidence or an intentional exclusion resolves the record.
  • The monitor filters Disqualified for all lanes and applies additional post-MQL status/exclusion rules to the campaign-driven lanes. It does not use the retired named-account filter in Basecamp.
  • Failures are stored as observations, surfaced in Intake failures, and alerted in production with Redis-backed deduplication.

9. Notifications and reply handling

Slack notifications

  • New Gong assignment: only a newly assigned production webhook flow posts Lead Agent Prospect Sequenced with prospect, owner, lane, campaign, Salesforce link, and Run link.
  • No duplicate post: already-assigned same-flow results and active-other-flow skips do not send the success message.
  • Failures: the 20-minute reconciliation job posts deduplicated missing-intake and job-stage alerts. These are operational alerts, separate from the v1 general Slack-alert toggle.

Current production reply lifecycle

Lead Agent variables -> Gong flow sends from SDR-connected mailbox
                              |
                     prospect replies
                              |
             +----------------+----------------+
             |                                 |
             v                                 v
     SDR Gmail / Gong UI                Gong reply rules
             |                          pause/finish flow
             +----------------+----------------+
                              |
                              v
                   Gong/Salesforce activity
                              |
                              v
                   SDR follow-up + analytics
  • Gong and the connected SDR mailbox are the production systems for receiving and responding to replies.
  • Basecamp currently has no Gmail watch, Pub/Sub push receiver, Gmail history consumer, or Gong reply webhook for these production inboxes.
  • The existing Basecamp reply pipeline starts from Outreach mailing.replied webhooks, hydrates Outreach data, polls Salesforce for the inbound task, posts Slack, and classifies with Glean. Because production Outreach enrollment is off, new Gong enrollments do not enter that scope.
  • Current Gmail API use is limited to creating a draft from an approved v1 email with a user's OAuth token; it does not monitor replies.

Future Gmail push boundary — not yet implemented

Google Workspace authorization
    -> Gmail mailbox watch registration
    -> Google Pub/Sub topic
    -> Basecamp HTTPS push endpoint
    -> Gmail history/message hydration
    -> Lead Agent run/thread matching
    -> dedupe + classify + Slack/console
    -> watch renewal + replay/recovery

This future path requires an actual Basecamp HTTPS receiver plus mailbox authorization and Pub/Sub publishing permissions. The Google service identity that publishes Gmail notifications only authenticates delivery into Pub/Sub; it does not grant Basecamp access to read an SDR mailbox.

10. Security and configuration boundaries

Authentication and authorization

  • Marketo webhook: shared-secret authentication, authenticated rate limiting, request-size bounds, and strict schema validation.
  • Internal workers and crons: CRON_SECRET bearer authentication; production fails closed when the secret is missing.
  • Basecamp UI/API: signed-in session; Run access is limited to assigned SDR, manual initiator, or admin. Admin settings and failure retries require admin role.
  • Production settings: environment-scoped keys isolate local/preview/test, and production writes require explicit authorization from the production hostname.
  • External credentials: Salesforce and optional Glean OAuth are user/token-vault based; headless Glean may use a client token; Gong uses server-side access key credentials; Slack uses the configured bot.
  • Testbed safety: native Testbed and shadow jobs cannot deliver even if stale UI toggles are malformed; the registry and persisted job flags both enforce no-push behavior.

Pinned versus live configuration

Pinned when the job enters the queue
  playbook lane | queue priority | delivered/shadow generator
  generator config snapshot | engagement provider

Re-read at delivery or push retry
  lane enabled/push/flow switches | target flow ID
  fresh booking evidence | Team Type | current Salesforce owner
  direct Gong active-flow state

Persisted after the attempt
  package/provenance | policy decision | provider result
  flow/instance IDs | errors | timestamps | retry history

This split prevents an active job from silently changing generator while still ensuring enrollment uses current safety and operational state.

11. Current production configuration

Delivery provider: Gong
Delivered generator: Glean for all three playbook lanes
Shadow generator: off for all three lanes
Outreach push/sequence: off for Form, Events & Webinar, and Attendance
Gong cool-off override: off
General v1 Slack alerts: off
Dedicated Gong enrollment success + failure alerts: active

Lane                    Priority   Variants enabled
form_handraiser         1          English + Non-English
campaign_handraiser     1          English + Non-English
webinar_attendance      3          Attended + No-Show
                                   Non-English disabled

The configured but disabled attendance non-English flow ID is not part of production routing. Changing a flow ID or enablement switch in the Production Lanes console affects subsequent delivery attempts and push retries; it does not rewrite prior job history.

12. Operating model

Ownership

  • Marketing Operations: Marketo trigger programs, campaign 300 wait logic, smart-list eligibility, trigger payload fields, and campaign identifiers/statuses.
  • Basecamp Engineering: webhook contract, Redis queues/state, generator orchestration, policy gates, Gong API integration, retries, monitoring, and admin surfaces.
  • Salesforce/RevOps: Lead/Contact owner correctness, Account Team Type, booking/lifecycle evidence, Gong managed-package fields, and CRM synchronization.
  • Gong Administration: flow/ruleset content, variable names, mailbox connection, owner Engage licensing, reply-stop behavior, and flow-folder hygiene.
  • SDR: connected mailbox, valid Salesforce ownership, execution of manual steps, and human response to replies.

Fast triage

  • Eligible lead but no Run: inspect Intake failures and the matching Marketo smart-list snapshot first.
  • Run exists but no package: inspect owner state, Salesforce ID/preflight, generator status, attempts, and next retry.
  • Package exists but no flow: read Sequencing policy, then Gong Engage sync; do not infer failure from the live Salesforce card alone.
  • Gong 403 names an SDR without Engage: fix the current Salesforce owner's Gong license or ownership, then retry the push.
  • Salesforce says In progress but retry seems possible: direct Gong preflight is the actual guard. If Gong reports an open flow, Basecamp skips assignment even if Salesforce is stale.
  • Salesforce says Finished (removed manually): Finished is not open; a later push may enroll only after every fresh guard passes.

13. Known constraints and deliberate debt

  • Dual-path complexity: v1 and v2 can run together, but only v2 controls production Gong delivery. The UI must continue to label them separately.
  • Gmail reply gap: production reply ingestion/classification out of Gong-connected inboxes is not implemented in Basecamp. Waiting on Gmail API access.
  • Salesforce sync lag: the current-flow card is useful CRM context, not a safe replacement for direct Gong flow-state checks.
  • Attendance correlation: exact campaign metadata is preferred; the time-window fallback rejects ambiguous multi-campaign matches rather than guessing.
  • Mutable operations: flow enablement and IDs are deliberately re-read at delivery/retry, so configuration changes can affect an old failed job when it is retried.

Appendix A — Key interfaces

POST /api/lead-agent/webhook
  Marketo machine intake

POST /api/cron/lead-agent-dispatch
  immediate authenticated worker kick

GET  /api/cron/lead-agent
GET  /api/cron/lead-agent-glean
  two-minute recovery workers

GET  /api/cron/lead-agent-marketo-missed
  20-minute smart-list reconciliation

GET  /api/cron/lead-agent-gong-flows
  15-minute stored flow-status refresh

GET  /api/lead-agent/runs/{id}?includeGongSalesforce=true
  authorized run + live Salesforce Gong fields

POST /api/admin/lead-agent/failures/{jobId}/retry
  admin-only generation or push retry

Appendix B — Reading one run

Lead / source / lane
  -> confirms intake identity and operational route

v1 Lead agent
  -> compatibility research/qualification/draft progress

v2 Glean agent
  -> authoritative package generation progress

Sequencing policy
  -> latest stored booking/Team Type/priority decision

Gong Engage sync
  -> persisted assignment attempt and flow instance

Salesforce current flow
  -> live CRM reflection of Gong-managed fields, not run-time evidence
DAILY OWNER
Basecamp Engineering
Ownership split across MOps · Basecamp Eng · Salesforce/RevOps · Gong Admin · SDR (§12)
BUILDER
Basecamp (Redis-owned)
AUTONOMY
Autonomous pipeline, HIL delivery — every production flow is human-in-the-loop in Gong; policy gates fail closed
SYSTEMS
Marketo (intake)Basecamp (orchestration)Salesforce (identity + CRM truth)Glean (package generation)Gong Engage (cadence execution)Redis (run + queue state)Slack (ops visibility)Neon/token vault (identity + OAuth)
TRIGGERS
Marketo lane webhooks — form handraiser · events & webinar handraiser · attended / no-show
NORTH STAR
Validated Gong flow assignments from intent signals
Guardrail: fail-closed policy gates, zero unsafe assignments
CADENCE
Real-time on webhook · 2-min recovery crons · 15-min Gong sync · 20-min smart-list reconciliation