📚Extensions Cookbook
Worked examples for the extensions adapters use most — WTF transcription, lawful basis, SIP signaling, agent session.
The vCon core spec is intentionally small. Most of what adapters actually care about — transcripts, recording consent, SIP signaling provenance, AI-agent session tracking — lives in extensions. This page is a recipe book for the four extensions adapters use in practice.
Each recipe shows the exact vcon library call, the resulting JSON shape, and links to the corresponding extension page for the full spec.
Spec target: draft-ietf-vcon-vcon-core-02, syntax "0.4.0". Library: vcon ≥0.9.4.
WTF Transcription
📄 Spec: WTF Transcription Extension · draft-howe-vcon-wtf-extension · Extension name: "wtf" (older code uses "wtf_transcription")
Use WTF when your adapter calls a speech-to-text provider — Whisper, Deepgram, AssemblyAI, ElevenLabs, AWS, Azure, Google. The point is that downstream tooling shouldn't have to special-case each provider's output.
Transcripts go in analysis[], not attachments[]. They're derived data, not supplied data.
Recipe
import json
from foo_adapter.vcon_builder import new_vcon
v = new_vcon(subject="Sales call", extensions=["wtf"])
v.add_party(tel="+15555550100", role="caller")
v.add_party(tel="+15555550200", role="agent")
v.add_dialog(
type="recording",
start="2026-05-19T14:32:00Z",
parties=[0, 1],
url="https://recordings.example/abc.wav",
content_hash="sha512-...",
mediatype="audio/wav",
)
wtf_document = {
"transcript": {"text": "Hello, this is Foo Corp..."},
"segments": [
{"start": 0.0, "end": 2.3, "speaker": 0, "text": "Hello, this is Foo Corp."},
{"start": 2.3, "end": 5.1, "speaker": 1, "text": "Hi, I'm calling about my account."},
],
"language": "en-US",
}
v.add_analysis(
type="transcript",
dialog=0,
vendor="openai-whisper",
product="whisper-large-v3",
body=json.dumps(wtf_document),
encoding="json",
schema="https://datatracker.ietf.org/doc/draft-howe-vcon-wtf-extension/",
)Resulting analysis[] entry
Common mistakes
❌ Putting the transcript in
attachments[]instead ofanalysis[]❌ Storing the WTF document as a Python dict in
body—bodyis always a string, paired withencoding="json"❌ Adding a separate plain-text transcript analysis — the WTF document already carries
transcript.text❌ Forgetting
vendor(the library will raiseTypeError)❌ Writing
schema_versioninstead ofschema
Lawful Basis (recording consent)
⚖️ Spec: Lawful Basis Extension · draft-howe-vcon-lawful-basis · Extension name: "lawful_basis"
Use this when your adapter handles conversations covered by GDPR, CCPA, HIPAA, TCPA, state-by-state recording consent laws, or when you're generating synthetic data for which you want auditable origin tracking.
Critical exception: the lawful_basis attachment is the one place where attachments use type instead of purpose. This is documented in the spec.
Recipe — consent-based (GDPR Article 6(1)(a))
The library's add_lawful_basis_attachment helper requires model objects for purpose_grants and proof_mechanisms. For most adapters it's easier to build the attachment dict directly and append it:
Recipe — synthetic data
When generating synthetic conversations (test fixtures, training data, demos), document the synthetic origin rather than forging a real consent record:
Also mark each synthetic party with validation: "synthetic". See the synthetic data section of the compliance checklist.
Common mistakes
❌ Using
purpose: "lawful_basis"instead oftype: "lawful_basis"— this attachment is the one core spec exception❌ Inventing an ad-hoc
synthetic_data_consentattachment shape instead of using lawful_basis withlegitimate_interests+external_systemproof❌ Omitting
"lawful_basis"from top-levelextensions[]❌ Treating
expirationas optional for consent-based grounds — GDPR consent without an expiry is brittle
SIP Signaling
📞 Spec: SIP Signaling Extension · draft-howe-vcon-sip-signaling · Extension name: "sip-signaling"
Use this when your adapter handles telephony — SignalWire, Twilio, Sippy, SIPREC streams, FreeSWITCH. The extension records the SIP-level facts (Call-ID, From/To URIs, P-Asserted-Identity, SDP fingerprints, signaling timestamps) that don't fit cleanly into a generic vCon party/dialog shape.
Recipe
Note this uses purpose=, not type= — SIP signaling follows the standard core attachment shape (only lawful_basis is the exception).
Agent Session
🤖 Spec: Agent Session Extension · draft-howe-vcon-agent-session · Extension name: "agent_session"
Use this when your adapter handles AI-agent conversations — Claude AI exports, LLM tool-use traces, voice-agent sessions. The extension carries the session-level facts the core spec doesn't model: model identity, tool invocations, system-prompt fingerprints, token counts.
Recipe
The vcon-anthropic-chats adapter is a reference implementation if you're building an LLM-export adapter.
Combining extensions
Most production adapters combine three or more. A contact-center adapter typically ships SIP signaling + WTF + lawful basis on every vCon. A voice-AI adapter combines agent session + WTF + lawful basis. Just list every extension you emit in the top-level extensions[]:
There's no ordering constraint and no limit. List them all, then add the corresponding attachments and analyses below.
Where to read the actual specs
When you need authoritative answers, read the drafts — not this cookbook:
Last updated
Was this helpful?