Skip to main content

Sharing & summary digest

Statusspec โ€” client-built, no backend work required
OwnerAndroid
Depends onLLM analysis (GET /api/calls/{id}/analysis), Calls API (GET /api/calls/{id})

What it doesโ€‹

Turns a completed call's analysis into a clean, shareable text digest โ€” the Scryon equivalent of a Fathom / Otter "meeting summary" โ€” that the user can send over WhatsApp, email, or any share target straight from the call detail screen.

The reference layout we're matching:

๐Ÿ“ž Pricing discussion with Alex
6 Jun 2026 ยท 38 min ยท with Alex

SUMMARY
Customer asked for revised pricing by Friday and agreed to a follow-up demo.

KEY POINTS
โ€ข Pricing tier is the only remaining blocker
โ€ข Customer wants the 12-month discount reflected
โ€ข Demo locked for Friday 11am

ACTION ITEMS
โ˜ Send revised pricing sheet โ€” You ยท by 26 Jun
โ˜ Schedule follow-up call โ€” Alex

DECISIONS
โ€ข Demo will use the new pricing dashboard build

Shared via Scryon

Why it's client-built (not backend)โ€‹

We already return everything the digest needs in the analysis JSON and the call record. There is no new LLM call, no new field, and no new endpoint. The digest is a pure, deterministic transform of data the client already holds, so it lives in the client:

  • Zero round-trips โ€” share works offline once analysis is cached.
  • Localisable โ€” date formats, section headers, and the Shared via Scryon footer follow the device locale.
  • No backend coupling โ€” the share sheet (WhatsApp / Gmail / SMS) is an OS concern, same seam we drew for action-item intent chips: the backend classifies, the client launches.

If a second platform (iOS, web) ever needs byte-identical output, promote this spec to a backend shareDigest block in the analysis JSON. Until then, this doc is the contract โ€” keep platforms in sync by following it.

Inputsโ€‹

Digest pieceSourceField
TitleGET /api/calls/{id}title โ†’ fallback analysis.suggestedTitle
DateGET /api/calls/{id}recordedAt โ†’ fallback createdAt
DurationGET /api/calls/{id}durationSeconds
CounterpartyGET /api/calls/{id}contactName (omit the with โ€ฆ clause if null)
SUMMARY lineanalysisoneLineSummary โ†’ fallback first sentence of executiveSummary
KEY POINTSanalysisexecutiveSummaryBullets[].text (cap 5) โ†’ fallback top keyDiscussionPoints[].text
ACTION ITEMSanalysisactionItems[] โ†’ title, ownerDisplayName, dueDate, intent
DECISIONSanalysisdecisions[]
FOLLOW-UPS (expanded only)analysisfollowUps[]
TOPICS (expanded only)analysissections[] โ†’ items[].text

Composition rulesโ€‹

  1. Section order is fixed: header โ†’ SUMMARY โ†’ KEY POINTS โ†’ ACTION ITEMS โ†’ DECISIONS โ†’ footer. Expanded mode inserts TOPICS after KEY POINTS and FOLLOW-UPS after ACTION ITEMS.
  2. Drop empty sections entirely โ€” no "Decisions: none" lines. If only the header and footer survive, fall back to sharing oneLineSummary alone.
  3. Action items group by owner (ownerDisplayName); null-owner items go under an Unassigned group, listed last. Render the phone user's own name as You.
  4. Due dates: append ยท by {dueDate} only when dueDate is present. dueDate is a raw LLM string โ€” render verbatim, do not attempt to re-parse.
  5. Length cap (compact mode): โ‰ค 5 key points, โ‰ค 8 action items, โ‰ค 4 decisions, each line truncated to ~120 chars with โ€ฆ. Keeps the message under a single WhatsApp screen.
  6. Never invent. Only render fields the analysis actually returned. Old v1 calls have no executiveSummaryBullets โ€” fall back to keyDiscussionPoints, then to executiveSummary.
  7. Intent glyph (optional polish): prefix an action item with its intent emoji instead of โ˜ when intent is set โ€” meeting ๐Ÿ“…, email โœ‰๏ธ, call ๐Ÿ“ž, message ๐Ÿ’ฌ, reminder โฐ, task โœ…, none/unset โ†’ โ˜.

Two render targetsโ€‹

The body is identical; only the markup differs.

WhatsApp / generic text/plainโ€‹

WhatsApp honours *bold*. Make headers bold; everything else stays plain:

*๐Ÿ“ž Pricing discussion with Alex*
6 Jun 2026 ยท 38 min ยท with Alex

*SUMMARY*
Customer asked for revised pricing by Friday and agreed to a follow-up demo.

*KEY POINTS*
โ€ข Pricing tier is the only remaining blocker
โ€ข Customer wants the 12-month discount reflected

*ACTION ITEMS*
โ˜ Send revised pricing sheet โ€” You ยท by 26 Jun
โ˜ Schedule follow-up call โ€” Alex

_Shared via Scryon_

Emailโ€‹

  • Subject: {title} โ€” call summary (e.g. Pricing discussion with Alex โ€” call summary).
  • Body: the same digest without WhatsApp asterisks (plain text), or an HTML version mirroring the structure if the share target accepts text/html.

Share mechanism (Android, follow-up implementation)โ€‹

No backend involvement โ€” the digest string is dropped into a standard share intent:

// System share sheet โ€” WhatsApp, Gmail, SMS, etc. appear automatically
val send = Intent(Intent.ACTION_SEND).apply {
type = "text/plain"
putExtra(Intent.EXTRA_SUBJECT, "$title โ€” call summary")
putExtra(Intent.EXTRA_TEXT, digestPlain) // or digestWhatsApp
}
startActivity(Intent.createChooser(send, "Share summary"))

Direct targets, if the UI offers explicit WhatsApp / email buttons:

// WhatsApp
Uri.parse("https://wa.me/?text=" + Uri.encode(digestWhatsApp))
// Email
Uri.parse("mailto:?subject=" + Uri.encode(subject) + "&body=" + Uri.encode(digestPlain))

What this is NOTโ€‹

  • โŒ Not a new API or LLM call โ€” it reuses GET /api/calls/{id}/analysis.
  • โŒ Not a backend responsibility (today) โ€” the server never builds share text or knows the user's installed apps.
  • โŒ Not the full transcript โ€” it's the summary. Sharing raw transcripts is a separate feature with its own privacy review.