sagetap-integration
Integrate Sagetap call transcripts into the extraction pipeline alongside Avoma.
Why
Sagetap is a second source of prospect evaluation calls. These are structured buyer-vendor sessions facilitated through the Sagetap platform — a distinct channel from Avoma's recorded meetings. Two sample transcripts are already in data/raw-sagetap/ and contain real prospect signals (game dev company evaluating discovery tooling, cybersecurity architect at global logistics enterprise looking for Linux visibility/SIEM integration).
However, these transcripts are much rawer than Avoma:
- CSV format with generic speaker labels (
Speaker 1,Speaker 2) — no names - Zero metadata (no date, company, attendees, subject)
- Poor transcription quality ("Centimeters" for SIEM, "Keypoint" for QPoint)
- Speaker numbering inconsistent across files
Objectives
Phase 1: Multi-source pipeline (make pipeline source-aware) — DONE
- Add
MeetingSourcetype to schema ('avoma' | 'sagetap') - Add
source?toCallMetadata,sourcetoCallIndexEntry - Detect Sagetap uploads in
avoma.tsviapurpose.label/type.label - Remove
sagetapfromVENDOR_PATTERNS, add early return in filter - Build sidecar attendees from
transcription.speakers(notmeeting.attendees) for uploads - Parse structured subject into
SagetapSubjectHints(contactName, role, industry, companySize, location) - Source-aware metadata injection in
extract.tsandbatch.ts(date shows "Unknown" for uploads) - Skip date backfill for sagetap in
extract.ts,batch.ts,build-index.ts - Propagate
sourcethrough all pipeline stages to index
Phase 2: Test end-to-end — DONE
- Fetch RobertK call via
npm run fetch -- --external - Verify sidecar:
source: "sagetap", correct attendees, parsed hints - Extract: metadata context shows Sagetap hints, date left as null
- Processed JSON:
metadata.source: "sagetap", attendees from transcript - Index: call appears with
source: "sagetap"(19 calls total)
Phase 3: Dashboard source indicators — DONE
- Add source column to calls list (AV grey / ST sky blue pills)
- Add source badge to call detail header
- Add
sourcetouseCallData.tsCallMetadatainterface - Backfill all 22 existing processed calls with
source: "avoma"
Phase 4: Automated upload script — DONE
-
pipeline/upload-sagetap.ts—npm run upload:sagetapautomates video upload to Avoma viaPOST /v1/calls/ - Parses structured filename for metadata (reuses
parseSagetapSubject()logic) - Local HTTP server + localtunnel for file access (zero config, no account)
- Subject prefixed with
Sagetap:for pipeline detection -
isSagetapUpload()updated to also matchsubject.startsWith('Sagetap: ') -
parseSagetapSubject()stripsSagetap:prefix before parsing -
--dry-runmode for testing,--rep/--dateflags, directory batch support -
SAGETAP_REP_EMAILenv var for default rep email
Phase 5: Remaining work
- Process second Sagetap call (Cliff — cybersecurity architect, logistics enterprise)
- Fix
locationdouble-space from subject parsing ("Location Poland"→"Poland") - Handle
company.name: nullgracefully in dashboard (Sagetap anonymity) - Consider: backfill actual call dates from Sagetap platform manually
- Consider: transcription correction dictionary for known errors in extraction prompt
- Consider: replace localtunnel with S3 presigned URLs (
--s3flag)
Current State Assessment
Pipeline is Avoma-centric. Key coupling points:
extract.ts/batch.tsinject metadata header as"from Avoma".meta.jsonsidecar assumes Avoma-shaped fields (avomaId,fetchedAt)CallMetadataschema hasavomaIdbut no genericsourcefield- No source attribution in aggregated index or dashboard
- Extraction prompt itself (
extract-call.md) is source-agnostic — good news
Sagetap has no public API. Help center and vendor portal docs show no API, export, webhook, or developer integration features. Metadata visible on the Sagetap platform page (dates, participant info) is only accessible through the UI. Options: manual metadata entry, or ask Sagetap support about programmatic access.
Approach Decision: Avoma-as-middleware (not CSV preprocessing)
Rather than building a separate CSV preprocessor, Sagetap calls are uploaded as video recordings to Avoma, which handles transcription and speaker assignment. The pipeline then fetches them via the existing Avoma API with source-aware routing.
Why this approach won:
- Avoma transcription + speaker assignment is already a solved problem
- No need for CSV parsing, speaker heuristics, or correction dictionaries
- Metadata encoded in structured subject line, parsed automatically
- Unified raw directory (
data/raw/) — no separatedata/raw-sagetap/needed for pipeline - Keeps the pipeline simple: one fetch path, source-aware branching
Manual steps required per Sagetap call:
- Download video from Sagetap platform
- Upload to Avoma → set purpose/type to "sagetap"
- Set structured subject:
{Name} - {Role}, Industry: {X}, Company Size: {X}, HQ: {Location} - Manually assign speakers in Avoma (names + is_rep flags)
Key Decisions & Learnings
Filter routing
isSagetapUpload()checksmeeting.purpose?.label,meeting.type?.labelfor "sagetap", andsubject.startsWith('Sagetap: ')(added in Phase 4)- Early return in
isExternalProspectCall()bypasses attendee count check (uploads only have uploader inmeeting.attendees)
Sidecar attendees
- Avoma uploads only populate
meeting.attendeeswith the uploader - After manual speaker assignment,
transcription.speakershas the correct participants withname,email,is_rep - The
transcriptionobject is already fetched before sidecar construction, so speakers are available
Date handling
- Upload timestamp ≠ actual call date; pipeline marks date as "Unknown" in Claude prompt context
- Date backfill skipped in all three paths (extract, batch, build-index) when
source === 'sagetap' - Claude extracted
date: nullas expected — validation warns but doesn't fail
Subject parsing
- Format:
"Name - Role, Industry: X, Company Size: Y, HQ: Location Z" - Regex parser splits on
-then comma-separated key-value pairs - Double-space in "HQ: Location Poland" is a data entry issue, not a parser bug
Extraction quality
- Claude correctly identified RobertK as cybersecurity persona, used industry hint
- Interest 3/5 seems right for an early evaluation call
- Company name extracted as
null(anonymous) — correct behavior for Sagetap - Avoma transcription quality is good enough without preprocessing corrections
Open Questions
Sagetap metadata access— Resolved: manual upload to Avoma is the workflowTranscript quality floor— Resolved: Avoma transcription is good enoughVolume— Resolved:upload-sagetap.tsautomates upload (supports directory batch). Manual step reduced to speaker assignment only.Speaker mapping confidence— Resolved: manual assignment in Avoma solves this- Actual call dates — Can we get the real dates from the Sagetap platform for backfill?
Dashboard SSR gotcha
v-ifconditions that depend on data not present in the server-rendered HTML can silently fail — the span never appears after hydration- Fix: use unconditional rendering with
:classbinding instead ofv-iffor source pills useCallData.tshas its own interface copies — new schema fields must be added there too
Files Changed
schemas/call.ts—MeetingSourcetype,sourceonCallMetadata+CallIndexEntrypipeline/avoma.ts—SagetapSubjectHints,isSagetapUpload(),parseSagetapSubject(), filter bypass, speaker-based sidecar, subject prefix detection (Phase 4)pipeline/upload-sagetap.ts— New (Phase 4) — automated Sagetap video upload to Avoma via APIpipeline/extract.ts— expanded sidecar type, source-aware metadata context, source propagation, date backfill guardpipeline/batch.ts— same source-aware metadata context and backfill guardspipeline/build-index.ts— date backfill guard, source in index entrysite/composables/useCallData.ts— addedsourcetoCallMetadatainterfacesite/pages/calls/index.vue— source column (AV/ST pills)site/pages/calls/[id].vue— source badge in header
Notes
- Sagetap sessions are anonymized buyer evaluations — the prospect came specifically to evaluate Qpoint. This is a higher-intent signal than cold outbound calls.
- The two sample CSV transcripts in
data/raw-sagetap/are kept for reference only — the actual pipeline path is through Avoma uploads. - Sagetap's own vendor page mentions "structured buyer feedback on relevance, clarity, timing, and trust" — worth checking if that structured feedback is available alongside transcripts.