recipes/agent-voice/skills/voice-post-call/SKILL.md
--- name: voice-post-call version: 0.1.0 description: Post-call handling for a voice session — turn the transcript into a brain page, post the summary to the operator's messaging surface, archive the audio. Belt-and-suspenders: fires both from a tool the voice persona can call mid-call AND from the automatic call-end handler in server.mjs. triggers: - "after the call" - "call ended" - "summarize the call" - "call transcript" - "voice call summary" - "post call summary" mutating: true
npx skillsauth add garrytan/gbrain recipes/agent-voice/skills/voice-post-callInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Convention: see conventions/quality.md for citation rules + back-link enforcement.
Convention: see _brain-filing-rules.md for filing decision protocol.
Every call gets processed, even on tool-call failure. The voice persona MAY call a log_call_summary tool mid-session, OR the call may end without that tool firing (model forgot, WebRTC dropped, browser crashed). The automatic call-end handler in services/voice-agent/code/server.mjs posts a structured signal regardless so the brain still gets the transcript + audio reference.
If both paths fire (the tool call AND the call-end handler), the second one is idempotent — it sees the brain page already exists and updates instead of duplicating.
1. CAPTURE → MediaRecorder on the host repo's voice-agent service captures
the full call audio (webm/opus) to /tmp/calls/<ts>-<persona>.webm.
The browser client at /call?test=1 also captures via WebAudio-tee
for E2E asserts; production /call uses server-side capture only.
2. TRANSCRIBE → Whisper (via gbrain transcription) processes the audio. Output:
full transcript (timestamped) + speaker labels where possible.
3. SUMMARIZE → A separate LLM call produces a 3-5 sentence summary covering
key topics, decisions, and unresolved items.
4. WRITE → Create or update meetings/YYYY-MM-DD-call-<persona>.md with:
- frontmatter (date, persona, duration, ratings)
- full transcript in a "Transcript" block-quote section
- summary in a "Summary" section
- audio link (file://, or signed URL if uploaded to storage)
- any entity cross-links (people, companies mentioned)
5. CROSS-LINK → For each entity in the transcript (person, company), append a
timeline entry to people/<slug>.md or companies/<slug>.md pointing
back to this call page. Iron Law: per conventions/quality.md.
6. POST → Send the summary to the operator's messaging surface (Telegram,
Slack, Discord — whichever is wired in $TARGET_REPO/.env).
Path A — Persona-initiated mid-call:
The voice persona calls log_call_summary via the WebRTC data channel. The host-repo /tool endpoint dispatches to tools.mjs. Note: log_call_summary is in OPTIONAL_OPS, not READ_ONLY_OPS, so this only works if the operator's tools-allowlist.local.json opts in.
Path B — Automatic call-end (default):
When the WebSocket / WebRTC connection closes, server.mjs fires a call_end event. The host repo's post-call handler (operator-implemented; the recipe ships a stub) reads the captured audio + transcript, runs the pipeline above. This path requires NO operator opt-in to work — the call-end handler is part of the shipped server.
---
type: meeting
subtype: voice-call
persona: venus
date: 2026-05-17
duration_sec: 124
caller: operator
rating: 7
issues: []
audio_url: "file:///tmp/calls/2026-05-17-1029-venus.webm"
created: 2026-05-17
---
# Voice call: 2026-05-17 with Venus
> Brief 3-5 sentence summary of what was discussed and any decisions made.
## Summary
[Agent-authored 3-5 sentence summary covering topics, decisions, action items.]
## Transcript
> [Verbatim per-turn transcript with speaker labels and timestamps. Pure quote
> — do not paraphrase. Block-quoted because the exact wording matters more
> than a cleaned-up version.]
🔊 [Audio](file:///tmp/calls/2026-05-17-1029-venus.webm)
## Entities mentioned
- [Person](people/<slug>.md)
- [Company](companies/<slug>.md)
## Timeline
- **2026-05-17 10:29 PT** | voice call with Venus, 124s, rating 7 — [topic]
[Source: voice call with <persona>, YYYY-MM-DD HH:MM PT]
This skill guarantees:
meetings/ or voice-calls/ (consistent with _brain-filing-rules.md).quality.md, _brain-filing-rules.md) are followed.---
type: meeting
subtype: voice-call
persona: <mars|venus>
date: YYYY-MM-DD
duration_sec: N
caller: <identity>
rating: 0-10
audio_url: "<file:// or signed URL>"
---
# Voice call: <date> with <persona>
> <Summary>
## Summary
<body>
## Transcript
> <verbatim>
🔊 [Audio](<url>)
## Timeline
- **<date> <time> <tz>** | voice call with <persona>, <duration>s — <topic>
tools
--- name: query-helper triggers: - find a page tools: - search - query writes_pages: false --- # query-helper This skill helps you query the brain. The first prose line becomes the description when no `description:` frontmatter is present.
testing
# broken This SKILL.md has no YAML frontmatter fence. It must still be listed (with the directory name as its name and empty triggers), never throw.
documentation
Read, enrich, and write brain pages with source attribution.
testing
Migrate a brain from gbrain-base (or any pack) to gbrain-base-v2's 14-canonical-type taxonomy via gbrain onboard --check + the unify-types Minion handler. Collapses 94 noisy types to 15 canonical with subtypes, alias rows, and link rows. Triggers when an agent notices pack_upgrade_available, type_proliferation, or asks "what is the canonical taxonomy / how do I clean up my page types".