📜vCon Library Guide for LLMs
A compact, self-contained reference for language models that write or edit Python code against the vcon 0.10.0 library, with the field names and mistakes that matter.
Reference for models that generate code with the vcon Python library, version 0.10.0, which implements draft-ietf-vcon-vcon-core-04 ("vcon": "0.4.0"). Every code block below was run against vcon==0.10.0. For field semantics see the field reference. For the full method list see the API reference.
Rules for generated code
Install with
pip install vcon(Python 3.12 or later). Add"vcon[image]"for Pillow and pypdf.Import only
Vcon,compute_content_hashandparse_content_hash_algorithmfrom the package root. Usefrom vcon.party import Party, PartyHistory,from vcon.dialog import Dialog,from vcon.civic_address import CivicAddress.from vcon import Partyfails.Field names:
critical(notmust_support, notmust_understand),amended(notappended),purposeon attachments (nottype),mediatype(notmimetype),schemaon analysis (notschema_version).Attachments take
purpose=. Analysis takestype=,vendor=anddialog=, all keyword-only.The lawful basis attachment uses
purpose: "lawful_basis". Build it withvcon.add_lawful_basis_attachment(...), never by hand, and add one to every complete vCon you create.A
json-encodedbodyis the JSON value itself (dict, list, string), notjson.dumps(...). Read any entry withVcon.decoded_body(entry).content_hashissha512-plus unpadded base64url. Create it withcompute_content_hash(data)orDialog.calculate_content_hash().Put WTF transcripts in
analysis[]withadd_wtf_transcription_analysis(), not inattachments[].Give every dialog a
mediatype;is_valid()fails without one.Vconis not a dict. There is novcon.get(...)and novcon["parties"]. Use properties (vcon.parties) orvcon.to_dict()orvcon.vcon_dict.Dispositions are lowercase and hyphenated:
no-answer,congestion,failed,busy,hung-up,voicemail-no-message."NO_ANSWER"raisesValueError.Do not invent a lawful basis. If the source data has no consent record, say so and omit the attachment.
Minimal complete vCon
from datetime import datetime, timedelta, timezone
from vcon import Vcon
from vcon.dialog import Dialog
from vcon.party import Party
now = datetime.now(timezone.utc)
vcon = Vcon.build_new()
vcon.add_party(Party(tel="+15551230001", name="Alice", role="caller"))
vcon.add_party(Party(tel="+15551230002", name="Bob", role="agent"))
vcon.add_dialog(Dialog(type="text", start=now, parties=[0, 1],
body="Hello, I need help.", encoding="none",
mediatype="text/plain"))
vcon.add_lawful_basis_attachment(
lawful_basis="consent",
expiration=(now + timedelta(days=365)).isoformat(),
purpose_grants=[{"purpose": "recording", "granted": True,
"granted_at": now.isoformat()}],
party_index=0,
)
ok, errors = vcon.is_valid()
assert ok, errors
vcon.save_to_file("conversation.vcon.json")Vcon
New
Vcon.build_new()
Load
Vcon.load(path_or_url), Vcon.load_from_file(path), Vcon.load_from_url(url), Vcon.build_from_json(str)
Save, serialize
save_to_file(path), to_json(), to_dict(), post_to_url(url, headers=None)
Validate
is_valid() -> (bool, list), Vcon.validate_file(path), Vcon.validate_json(str)
Sign
Vcon.generate_key_pair(), sign(private_key), verify(public_key) -> bool
Read
properties uuid, vcon, subject, created_at, updated_at, parties (list of dicts), dialog, attachments, analysis, redacted, amended, group, meta, tags
Party objects
get_party_objects() returns Party instances; find_party_index(by, val)
subject is read-only: set it with vcon.vcon_dict["subject"] = "...". Vcon.load(..., property_handling="strict" | "meta" | "default") removes, relocates or keeps unknown properties.
Dialogs
Dialog.typeis one ofrecording,text,transfer,incomplete,audio,video; other values raiseValueError.Extra keyword arguments are accepted silently, so a wrong name such as
mimetype=ends up as a stray property. Check spelling.add_incomplete_dialog(start, disposition, details=None, parties=None, metadata=None).add_transfer_dialog(start, transfer_data, parties, metadata=None).add_external_data(url, filename, mediatype)downloads the URL and hashes it.add_inline_data(body, filename, mediatype)does not encode: pass a body that is already base64url.add_image_data(path, mediatype=None)needsvcon[image].add_video_data(...)needsffmpeg.Type tests:
is_text(),is_recording(),is_audio(),is_video(),is_transfer(),is_incomplete(),is_image(),is_pdf(),is_email(),is_external_data(),is_inline_data().Search:
vcon.find_dialogs_by_type("text"),vcon.find_dialog("type", "text").
Attachments, analysis, tags
encodingisjson,base64urlornone.Defaults on every attachment:
party0,dialog0,startfromcreated_at,mediatypeapplication/jsonforjsonbodies.Find helpers:
find_attachment_by_purpose(purpose)(notfind_attachment_by_type),find_analysis_by_type(type).
Extensions and critical
There are no must_support methods, no vcon.extensions or vcon.must_support properties and no appended property. Use get_extensions(), get_critical() and amended.
Lawful basis
Body shape:
lawful_basis,expiration(may be null),purpose_grants[](purpose,granted,granted_at, optionalconditions), optionalproof_mechanisms[](proof_type,timestamp,proof_data).Extra keywords reach
LawfulBasisAttachment:terms_of_service,status_interval,content_hash,registry,proof_mechanisms,metadata.proof_mechanismstakesProofMechanismobjects, not dicts.ProofType:verbal_confirmation,signed_document,cryptographic_signature,external_system.HashAlgorithm(for the lawful basisContentHashonly):SHA_256,SHA_3_256,BLAKE2B_256. This is not the dialogcontent_hash.Attestation registries:
SCITTRegistryClient(registry_url, auth_token=None)andRegistryManager()invcon.extensions.lawful_basis.registry;RegistryValidatorhas staticvalidate_scitt_receipt,validate_attestation_status,validate_registry_metadata.
WTF transcription
metadataneedscreated_at,processed_at,provider,model.Metadata(audio_quality=...)raisesTypeError:audio_qualitybelongs toQuality.add_wtf_transcription_analysis()writestype: "transcription"and a JSON-string body. The extension draft defineswtf_transcription. This is an upstream gap in 0.10.0. For draft-conformant output callvcon.add_analysis(type="wtf_transcription", dialog=0, vendor=..., product=..., body=wtf_dict, encoding="json").add_wtf_transcription_attachment(...)(same arguments withparty_index,dialog_index) writes toattachments[];find_wtf_attachments()searches only there.Provider conversion:
WhisperAdapter().convert(data),DeepgramAdapter,AssemblyAIAdapterreturn aWTFAttachmentwith.transcript,.segments,.metadata,export_to_srt(),export_to_vtt(),get_speaking_time(),find_low_confidence_segments(threshold=0.5),extract_keywords(min_confidence=0.8).WTFExtension(dict in, dict out):create_wtf_attachment,convert_from_provider(data, provider),validate_wtf_attachment,export_transcription(att, format),analyze_transcription,compare_transcriptions.WTFProcessorhas the same methods overWTFAttachmentobjects.
Content hashes and encoding
Dialog.verify_content_hash() recomputes over the stored body string, so for base64url image dialogs from add_image_data() (hash taken over raw bytes) it returns False. That is an upstream gap in 0.10.0.
Other public API
Errors
Invalid
type,disposition,encoding, party history event or lawful basis type raisesValueError.A missing file raises
FileNotFoundError; malformed JSON raisesjson.JSONDecodeError.is_valid()returns problems as strings and does not raise.add_party()needs aParty, not a dict (AttributeError).
Common mistakes
from vcon import Party, Dialog
from vcon.party import Party, from vcon.dialog import Dialog
add_attachment(type="notes", ...)
add_attachment(purpose="notes", ...)
find_attachment_by_type(...)
find_attachment_by_purpose(...)
Dialog(..., mimetype="audio/wav")
Dialog(..., mediatype="audio/wav")
vcon.add_must_support("x")
vcon.add_critical("x")
vcon.must_support, vcon.extensions
vcon.get_critical(), vcon.get_extensions()
vcon.appended
vcon.amended
vcon.get("parties")
vcon.parties or vcon.to_dict().get("parties")
body=json.dumps(obj), encoding="json"
body=obj, encoding="json"
disposition="NO_ANSWER"
disposition="no-answer"
{"type": "lawful_basis", ...} attachment
purpose: "lawful_basis" (not type) via add_lawful_basis_attachment()
WTF in attachments[]
add_wtf_transcription_analysis()
Metadata(audio_quality=...)
Quality(audio_quality=...)
sha256 hash without prefix
sha512-<base64url> from compute_content_hash()
Last updated
Was this helpful?