Security and data handling
Local by default. Sensitive by nature. Core scoring never leaves your machine; the calls it scores can carry a caller’s voice and whatever they said, so treat the output like the recording it came from.
What runs offline
The scorer itself makes no network call. Per-frame RMS, the energy VAD, and every yield/talk-over measurement run in the standard library, on the audio file you point at, on your own machine. See how it works for the pipeline.
What touches the network, and when
Everything below this line is offline: run, scan, analyze, trust, report, doctor and demo (both self-test paths, and doctor scoring your own recording), team, export, benchmark, compare, verify, diagnose, plan, patch, explain, fixture, every contract and trace subcommand, setup, describe, init, and the self-hosted fleet control plane scored from recordings you pass it. They read the local files you point them at and write local files. No sockets open.
| Command | Reaches | When |
|---|---|---|
connect | The stack’s API, one call | Unless --no-verify: a live auth check that lists one recent call, before storing credentials at 0600 in ~/.hotato/connections.json. |
capture, pull, sweep --stack <name> | The stack’s API | Always, to fetch (capture) or list-then-fetch (pull, sweep) the recordings you named. Full per-stack matrix, including the five mono stacks gated behind --allow-mono: capture overview. --demo scores bundled recordings instead, on every one of these: no network. |
capture --stack livekit|pipecat | Nothing from Hotato | The recording comes from your own infrastructure; setup only prints the scaffold. |
inspect | The stack’s API, GET only | Always, for Vapi and Retell: reads, never writes, the live turn-taking config. LiveKit and Pipecat parse a local config file instead. |
ingest | The stack’s API | Per event, only to fetch the one recording the webhook payload named. The payload itself is read as data; nothing in it is ever executed. |
issue create --yes, pr create --yes | GitHub, through your local gh auth | Only with --yes. Without it, both print what they would do and touch nothing. |
apply --clone --yes | The stack’s API (Vapi, Retell) | Only with --yes and credentials: creates a new staging assistant. Never mutates the source; without --yes it is a dry run that touches no network. |
--diarizer pyannoteai on run --mono --diarize or contract create --mono --diarize | pyannote.ai, hosted | Only with --egress-opt-in: uploads the mono audio for diarization. The default backend, pyannote, and the alternative sortformer, both stay local. |
--notify URL on sweep or fleet run | The URL you pass | Off by default. Posts one JSON summary: counts, top candidate ids, kinds, and timing numbers, local artifact paths. No audio, credential, or transcript text. A failed delivery is one stderr warning; it never breaks the run. |
Nothing here is ever uploaded to Hotato or Attention Labs. There is no telemetry, no phone-home, and no hosted service in the open-core CLI.
Proxies and TLS
Every networked call above goes through Python’s urllib and honors HTTP_PROXY, HTTPS_PROXY, and NO_PROXY, the same convention curl, pip, and git follow, so a corporate proxy works with no extra flags. Every credentialed endpoint is hardcoded https:// and certificate validation is never disabled: a proxy can see the target host and stall or refuse the connection, but cannot read or rewrite an Authorization header without also presenting a certificate your machine’s own trust store already accepts for that vendor’s domain. Set HOTATO_NO_PROXY=1, or unset the proxy variables, if you do not trust the ambient proxy for a given run.
What generated evidence may contain
A pulled recording, a rendered report, or an exported corpus fixture can contain the caller’s voice and anything they said on the call, including spoken PII. Hotato does not detect, redact, or flag PII on your behalf. That is a decision for the person handling the recording, not the scorer.
- Reports:
hotato demo, andhotato doctorscoring a real recording, embed the exact scored audio by default. The plainhotato reportcommand only embeds audio with an explicit--embed-audioflag. Either way the report stays one offline HTML file; the file itself now carries the call. - The research export (
events.csv,frames.csv,envelope.json) carries timing data, not audio, but references the source file by path. - Contract bundles (
hotato contract create) always include the clipped audio for the labeled moment (audio/event.wav). Default redaction hides a candidate reference and the source recording’s basename fromcontract.jsonand the SVG card; pass--include-identifiersto keep them. It never touches the audio itself, andcontract packzips the bundle, audio included, into one portable.hotatofile. - Corpus contributions are the one path where audio is meant to be redistributed publicly. See Contributing for the consent and PII rules that gate what goes in.
A packed contract or an embedded-audio report is easy to attach to an email, a chat, or a public issue, and that portability is a packaging property, not a review of what is inside it: give it the distribution judgment you would give the raw recording, because the raw recording is inside it. When a timing result is enough on its own, share the audio-free summary instead: the contract id, the measured values, the trust input-health result, your yield/hold label, the source audio hash (source_audio_sha256 in contract.json), and the pass or fail outcome. hotato contract inspect --format json and hotato contract verify --format json print all of it without embedding audio.
Your responsibility
Hotato does not set a retention, access, or sharing policy for you. Apply your own: who can see a pulled recording, how long a report stays reachable, and whether a caller consented to being recorded at all. That is unchanged by anything Hotato measures.
Determinism, scoped
Deterministic under pinned inputs: no learned score, no sampling. With the same supported Hotato version, the same audio, channel map, event onset, label, and scoring config, the reference (energy) backend gives the same timing numbers every run. A changed result means at least one pinned input, policy, or scorer component changed, most often the audio itself. Byte-identical re-runs are verified in CI on Linux x86_64 (Python 3.10, 3.11, 3.12); the same check now also runs in CI on macOS and Windows, not yet green. No claim is made about an unlisted platform or an unpinned config.
Reporting a security issue
Do not open a public GitHub issue for a vulnerability, or for anything involving a call recording, consent, PII, PHI, or private audio. Email security@attentionlabs.ai with what you found, how to reproduce it, and your hotato --version. Expect an acknowledgement within 3 business days; security fixes land in the latest release, so confirm an issue still reproduces there before reporting. Anything else, a bug or a feature request, is fine as a public issue: github.com/attenlabs/hotato →