Metadata-Version: 2.4
Name: earshot-observability
Version: 0.1.0
Summary: The open-source Voice Observability SDK for real-time voice AI
Project-URL: Homepage, https://github.com/Kkartik14/Earshot
Project-URL: Documentation, https://github.com/Kkartik14/Earshot/tree/main/docs
Project-URL: Repository, https://github.com/Kkartik14/Earshot.git
Project-URL: Issues, https://github.com/Kkartik14/Earshot/issues
Project-URL: Changelog, https://github.com/Kkartik14/Earshot/releases
Author: Earshot contributors
License: Apache-2.0
License-File: LICENSE
Keywords: llmops,observability,opentelemetry,sdk,voice-ai
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.11
Requires-Dist: protobuf<7,>=6.33.5
Requires-Dist: pydantic<3,>=2.9
Requires-Dist: rfc8785==0.1.4
Provides-Extra: dev
Requires-Dist: build<2,>=1.2; extra == 'dev'
Requires-Dist: fastapi<1,>=0.115; extra == 'dev'
Requires-Dist: grpcio-tools==1.81.1; extra == 'dev'
Requires-Dist: httpx<1,>=0.27; extra == 'dev'
Requires-Dist: hypothesis<7,>=6.120; extra == 'dev'
Requires-Dist: pytest-asyncio<1,>=0.24; extra == 'dev'
Requires-Dist: pytest-cov<7,>=6; extra == 'dev'
Requires-Dist: pytest<9,>=8.3; extra == 'dev'
Requires-Dist: pyyaml<7,>=6; extra == 'dev'
Requires-Dist: ruff<1,>=0.9; extra == 'dev'
Requires-Dist: uvicorn<1,>=0.30; extra == 'dev'
Provides-Extra: livekit
Requires-Dist: livekit-agents<1.7,>=1.6.5; extra == 'livekit'
Requires-Dist: opentelemetry-api<2,>=1.30; extra == 'livekit'
Requires-Dist: opentelemetry-sdk<2,>=1.30; extra == 'livekit'
Provides-Extra: otel
Requires-Dist: opentelemetry-api<2,>=1.30; extra == 'otel'
Requires-Dist: opentelemetry-sdk<2,>=1.30; extra == 'otel'
Provides-Extra: pipecat
Requires-Dist: opentelemetry-api<2,>=1.30; extra == 'pipecat'
Requires-Dist: opentelemetry-sdk<2,>=1.30; extra == 'pipecat'
Requires-Dist: pipecat-ai[tracing]<1.6,>=1.5.0; extra == 'pipecat'
Provides-Extra: pipecat-groq
Requires-Dist: opentelemetry-api<2,>=1.30; extra == 'pipecat-groq'
Requires-Dist: opentelemetry-sdk<2,>=1.30; extra == 'pipecat-groq'
Requires-Dist: pipecat-ai[groq,tracing]<1.6,>=1.5.0; extra == 'pipecat-groq'
Provides-Extra: server
Requires-Dist: fastapi<1,>=0.115; extra == 'server'
Requires-Dist: uvicorn<1,>=0.30; extra == 'server'
Description-Content-Type: text/markdown

# Earshot

**The open-source Voice Observability SDK.**

Earshot is an open-source SDK, semantic profile, and local backend for recording what
happened in a voice session—across Pipecat, LiveKit, browser/mobile, native
speech-to-speech, raw pipelines, and optional telephony—and turning it into a safe,
immutable artifact that can be validated, stored, shared, and projected into a
deterministic latency/causality analysis.

The core workflow:

> This session failed. Here is the portable evidence artifact and the deterministic
> projection needed to investigate it across runtimes.

Status: pre-v1 alpha. Backend-authored incident explanations are implemented;
cross-incident regression-fixture generation and a generic live OTLP receiver remain
later product milestones.

## What is implemented

- A pre-v1 `v1alpha1` voice-session contract with participants, streams, distributed clock domains,
  graph causality, explicit coverage, evidence/provenance, privacy policy, media refs,
  and optional exact caller-supplied raw OTLP chunks. Automatic OTLP interception is
  not implemented in M1.
- Deterministic protobuf plus strict JSON codecs and generated JSON Schema.
- Bundle-wide invariant and privacy validation with stable issue codes.
- Metadata-only capture policy and omission ledger.
- Explicit and global SDK clients with context ownership, deterministic whole-conversation
  sampling, lifecycle/loss status, fork/atexit recovery, bounded gzip export, and
  Pipecat/LiveKit normalization adapters.
- Deterministic analysis and backend explanation separating generated/sent/received/render timing, cross-clock
  uncertainty, parallel tool work, provider measurements, and measured failed-operation
  diagnoses. The viewer consumes authored points/intervals, provenance, coverage,
  omissions, and limitations without manufacturing durations.
- FastAPI backend with project-scoped API keys, immutable SQLite/content-addressed
  storage, JSON/protobuf negotiation, fleet Turn Facts, analysis caching, corruption
  checks, and privacy purge/tombstones.
- Signed finalized-delivery Connectors for ElevenLabs Agents (JSON and OTLP-shaped),
  Vapi, and Retell. Provider transcript/tool/dynamic-variable bodies are not retained.
- A non-root single-image deployment with a persistent `/data` volume and hardened
  Compose example.
- Unit, property, integration, smoke, and end-to-end conformance tests.

## Quick start

Clone and run the whole thing — the API and the web viewer in one container:

```bash
docker compose up --build
# then open http://127.0.0.1:4319
```

That builds the viewer SPA, bakes it into the image, and serves the UI and the `/v1`
API from a single port. Compose publishes only to `127.0.0.1:4319` and persists the
catalog and evidence in the named `earshot-data` volume. The container runs with
`EARSHOT_TRUST_LOCAL_NETWORK=true`: the API is unauthenticated, but the loopback-only
port mapping is the trust boundary. To expose it beyond localhost, drop that line from
`compose.yaml` and instead set `EARSHOT_TOKEN` (a high-entropy secret) plus
`EARSHOT_BEHIND_TLS_PROXY=true`, and front it with your own TLS proxy.
On a protected deployment, the viewer exchanges the entered project API key or legacy
token for an expiring HttpOnly session cookie; it never saves the credential in browser
storage.

Load a session to look at:

```bash
curl -X POST http://127.0.0.1:4319/v1/incidents \
  -H 'Content-Type: application/json' --data-binary @fixtures/valid/minimal.json
```

### From source (no container)

```bash
python3.11 -m venv .venv
. .venv/bin/activate
pip install -e '.[dev]'
pytest
pnpm install && pnpm --filter @earshot/viewer bundle   # build the UI into the package
earshot serve --data-dir .earshot                       # http://127.0.0.1:4319
```

Applications that only emit Earshot evidence install the lightweight base package.
Running the local API/CLI server from a non-development installation requires the
server extra: `pip install 'earshot-observability[server]'`.

Without the `bundle` step the API still runs; it just serves no UI. During UI
development, run `pnpm --filter @earshot/viewer dev` for a hot-reloading server that
proxies `/v1` to the backend.

The Python distribution is named `earshot-observability`; the import package and
CLI remain `earshot`. The plain PyPI distribution name `earshot` belongs to an
unrelated VAD project and must not be used for this repository.

Instrument an application through the environment-configured process client:

```python
import earshot

earshot.init()  # EARSHOT_ENDPOINT, EARSHOT_TOKEN, EARSHOT_PROJECT_ID, ...

with earshot.conversation(session_id="opaque-session-id") as incident:
    with incident.operation("agent", turn_id="turn-1"):
        run_voice_agent()

assert earshot.flush(timeout=5.0)
earshot.shutdown(timeout=5.0)
```

`earshot.Client(...)` provides the same capture kernel with explicit ownership for
libraries, tests, and multi-project processes. Async delivery is bounded and
non-blocking; sync and disk-durable delivery are explicit opt-in modes. `status()` makes
sampling, queue pressure, retries, rejection, and evidence loss observable.

```bash
curl http://127.0.0.1:4319/healthz
earshot validate fixtures/valid/minimal.json
earshot ingest fixtures/valid/minimal.json --data-dir .earshot
```

## Architecture

```text
framework/runtime facts
  -> capture-policy filter
  -> existing OTel graph + earshot.* voice profile
  -> canonical incident bundle (protobuf; JSON debug export)
       -> local validation + immutable storage
       -> deterministic projection and evidence-linked diagnosis
       -> governed local API/CLI or portable file export
```

The application's normal OpenTelemetry exporter may continue sending telemetry to an
existing backend in parallel. Earshot accepts ElevenLabs' bounded, finalized OTLP-shaped
webhook, but does not expose a generic live OTLP receiver: OTLP alone does not define
voice-session completion, late-span revision, or multi-trace correlation.

The voice boundary is capture through render. Transport is optional evidence—not the
data-model center. Native speech-to-speech can legitimately omit STT/LLM/TTS stages.
Missing evidence is never encoded as zero.

Earshot distinguishes audio generated, sent, received, and rendered. It never claims
a system can prove a human **heard** the audio.

## Repository

| Path                                   | Purpose                                                           |
| -------------------------------------- | ----------------------------------------------------------------- |
| `proto/earshot/v1alpha1`               | Experimental canonical protobuf envelope.                         |
| `semconv/earshot.yaml`                 | Earshot OTel semantic-profile registry.                           |
| `spec/`                                | Generated JSON Schema.                                            |
| `packages/sdk-python`                  | Contract, SDK, adapters, analysis, storage, and API.              |
| `apps/ingest`                          | ASGI deployment entry point.                                      |
| `fixtures/`                            | Shared valid/invalid/golden/fault artifacts.                      |
| `examples/pipecat_headless`            | Roomless real STT → LLM → TTS evidence harness.                   |
| `docs/`                                | Public, self-reproducing architecture and contract documentation. |
| `packages/schema`, `packages/analysis` | Superseded M0 TypeScript prototype.                               |

Start with the [public documentation](docs/README.md).

## Non-goals

Earshot is not a voice runtime, carrier, hosted multi-tenant product, or another fleet
dashboard/evaluation suite. It creates the portable artifact those systems can ingest.
