Getting started
Five commands, offline, no account. Catch a talk-over on a bundled call, score your own two-channel recording, pin the moment, and gate CI on it. Your audio and traces never leave your machine.
Install, then four steps: catch a failure on a bundled call, score your own recording, pin the moment as a contract, and open the pull request that gates CI. Each step below is the exact command. No forks.
1. Install
uvx fetches and runs hotato straight from PyPI with no install step, so every command on this page works as written. For daily use, install it once with pipx, uv, or pip.
# run without installing: uvx fetches hotato on first use uvx hotato --version # or install once for daily use pipx install hotato # or: uv tool install hotato, or: pip install hotato
2. See it catch a failure
The guided first run sweeps two bundled demo calls (a synthesized talk-over and a recorded provider-default call), ranks the strongest failing moment, freezes it as a portable contract, and re-scores it. It fails by design: the agent talks straight over a caller interruption. The run writes a shareable failure record and prints your next command.
hotato autopsy ./call.wav hotato start: swept the 2 bundled demo calls offline. ------------------------------------------------------------------ Conversation failed: Agent did not yield; measured talk-over was 2.66 s. ------------------------------------------------------------------ Two measured signals on this one call: talk-over 2.66s the agent kept talking while the caller held the floor response gap 2.18s dead air from the caller's turn end to the reply Share in a PR: hotato-failure-record/failure-record.md re-scored FAIL, by design: this call talked over the caller. Setup finished, so start --demo exits 0. Your next step, score a call: hotato autopsy contracts/demo-missed-interruption.hotato/audio/event.wav
3. Score your own call
Point investigate at a two-channel recording. It validates the file, checks it is scorable, and ranks the candidate turn-taking moments, printing the exact command to label each. Swap in your own call; until then, the demo just wrote an event.wav you can run this on.
# a two-channel WAV: caller on channel 0, agent on channel 1 hotato autopsy ./call.wav hotato autopsy [run 1]: call.wav most likely failure (top-ranked candidate): [1] t=7.63s agent_stop_no_caller trailing silence=0.37s the agent went quiet for 0.37 s with no caller energy nearby turn it into a CI contract (use --expect hold if the agent was right to keep talking): hotato investigate label '.hotato/investigate-state.json#1' --expect yield input health: eligible for scan verdict path: eligible (a labeled event here can carry a yield/hold verdict)
Separate tracks give every overlap an owner: you see who was already talking and who cut in. A mixed mono file cannot show that, so investigate refuses it (exit 2). If your stack exports one mixed file, switch on separated recording; the capture guides show the setting per stack.
Recording still in your stack? Pull and score it in the same step: hotato investigate --stack vapi --call-id <id>.
4. Pin the catch
Labeling is your decision on the moment: --expect yield means the agent should have stopped for the caller, --expect hold means it was right to keep talking. It writes a portable contract that freezes the moment as evidence and prints the command to open a pull request.
hotato investigate label '.hotato/investigate-state.json#1' --expect yield --id my-first-catch created hotato contract: my-first-catch dir: contracts/my-first-catch.hotato expect: yield scorable: yes passed: False measured: did_yield=False seconds_to_yield=n/a talk_over=0.00s open the pull request that adds it to your repo's CI gate: hotato pr create --fixtures contracts/my-first-catch.hotato --repo OWNER/REPO --title 'Add hotato contract my-first-catch'
5. Wire the CI gate
pr create opens a pull request that adds the contract as a regression test with a ready-made GitHub check. The gate command is contract verify: it re-measures the stored evidence and exits non-zero while a pinned call stays red, so a regression fails the build.
# open the PR that adds the contract and the CI check hotato pr create --fixtures contracts/my-first-catch.hotato --repo OWNER/REPO \ --title 'Add hotato contract my-first-catch' # the gate itself: re-score every pinned contract, non-zero on a regression hotato contract verify contracts/ hotato contract verify: contracts/ (2 contracts) [FAIL] demo-missed-interruption (expect yield): talk_over=2.65s | integrity: intact [FAIL] my-first-catch (expect yield): talk_over=0.00s | integrity: intact 0/2 contracts pass; exit_code=1
0 every contract passes · 1 a pinned failure is still red, the build fails · 2 a usage or input error, including an input that is not scorable. The GitHub Action and the pytest plugin run this same check on every push.
A pinned contract stays red until you fix the agent and recapture the call, the same way a snapshot test stays red until you update the snapshot. contract verify re-measures stored evidence and does not re-run your live agent. hotato prove composes every evidence lane into one fail-closed release proof. When you have a fix, close the loop: recapture and compare before and after → · see the whole loop run against twelve recorded calls →