DEV Community

Cover image for Add Tamper-Evident Audit Logs to Pipecat Voice Agents in 5 Minutes
Aditya Suresh
Aditya Suresh

Posted on

Add Tamper-Evident Audit Logs to Pipecat Voice Agents in 5 Minutes

EU AI Act Article 12 enforcement starts on August 2, 2026. Colorado AI Act enforcement started on February 1, 2026. FINRA's 2026 Annual Regulatory Oversight Report named AI agent auditability as a 2026 examination priority. HIPAA already requires audit trails for AI handling of PHI.

If your voice agent is going into healthcare, finance, insurance, or legal, an auditor will eventually ask: prove what your AI agent said, on what input, and that the log was not edited after the fact.

This post shows how to add tamper-evident, offline-verifiable audit logs to a Pipecat voice agent in about five minutes.

What we are building

A standard Pipecat pipeline: Twilio in, STT, LLM, TTS, Twilio out. We will add one extra FrameProcessor that signs every audit-relevant event - user utterance captured, model invoked, tool called, agent utterance spoken - with Ed25519, chained by SHA-256, written to a local NDJSON ledger. After the call, we will run a CLI tool to verify the ledger has not been tampered with.

Total install footprint: one pip package + one localhost binary.

Install

The Pipecat adapter is on PyPI:

pip install provedex-pipecat
Enter fullscreen mode Exit fullscreen mode

The signing daemon is a small Rust binary. Multi-arch container or pre-built binaries from GitHub Releases:

# Option A - prebuilt binary
curl -L https://github.com/provedex/provedex/releases/download/v0.1.0/provedex-agent-aarch64-apple-darwin.tar.gz | tar -xz
./provedex-agent &

# Option B - docker
docker run -d --network host ghcr.io/provedex/provedex-agent:v0.1.0
Enter fullscreen mode Exit fullscreen mode

The daemon binds to localhost only. It is not reachable from outside the machine. No port to firewall, no TLS to manage, no auth to provision.

Wire it into a Pipecat pipeline

from pipecat.pipeline.pipeline import Pipeline
from provedex_pipecat import ProvedexFrameProcessor, ProvedexConfig

# Standard Pipecat pieces (your existing setup)
transport = ...      # Twilio, LiveKit, Daily, whatever
stt = ...            # Deepgram, AWS Transcribe, Whisper
llm = ...            # OpenAI, Anthropic, Bedrock
tts = ...            # ElevenLabs, Cartesia, Piper

# One extra line
processor = ProvedexFrameProcessor(
    config=ProvedexConfig(
        session_id="patient-session-2026-05-24-abc",
    )
)

pipeline = Pipeline([
    transport.input(),
    stt,
    processor,                  # signs user transcriptions
    context_aggregator.user(),
    llm,
    processor,                  # signs LLM input and output
    tts,
    transport.output(),
])
Enter fullscreen mode Exit fullscreen mode

That is it. Run the pipeline as normal. Every relevant Pipecat Frame gets signed and appended to a local NDJSON ledger.

What gets signed

The ProvedexFrameProcessor maps Pipecat frames to the seven AgentEvent variants in event-schema-v1:

Pipecat Frame AgentEvent variant Fields
StartFrame SessionStarted session_id
TranscriptionFrame (final) UtteranceCaptured transcript_sha256, speaker
LLMMessagesFrame + LLMFullResponseEndFrame ModelInvoked prompt_sha256, response_sha256, token counts
FunctionCallInProgressFrame ToolCalled tool_name, args_sha256
FunctionCallResultFrame ToolReturned result_sha256, success
TextFrame at TTS boundary UtteranceSpoken speech_sha256
EndFrame SessionEnded session_id

Skipped: raw audio frames (too high frequency), interim STT (only the final), operational metrics.

A note on PII

The ledger stores SHA-256 commitments, not raw content. Transcripts, prompts, responses, and tool args are hashed at the binding boundary before they ever leave the Pipecat process. PII never enters the chain.

Operators who need raw content for replay keep it in their own observability stack alongside the signed receipt. Receipt + observability log together = provable + replayable. Two separate concerns.

Verify the log

After the call, the ledger file lives at ~/.provedex/ledger.ndjson (configurable via env). Run the CLI:

provedex-cli verify ~/.provedex/ledger.ndjson \
    --public-key ~/.provedex/keys/signing.pub
Enter fullscreen mode Exit fullscreen mode

Output on a clean ledger:

Verified 247 events
Chain intact (parent_hash matches self_hash for all entries)
All signatures valid against public key 8f3a2e1b...
Session start: 2026-05-24 09:12:33 PDT
Session end:   2026-05-24 09:34:18 PDT
Duration:      21m 45s
Result: PASS
Enter fullscreen mode Exit fullscreen mode

Now try tampering. Open the NDJSON file in any text editor, change one byte in one event (flip a digit in a hash, change a single character in a transcript reference), save, run verify again:

ERROR: chain broken at event 47
ERROR: self_hash mismatch - computed=a4f1..., recorded=a4f0...
Result: FAIL
Enter fullscreen mode Exit fullscreen mode

That is the property. The chain rejects any silent edit, regardless of who has access to the file - including the operator.

The auditor angle

This is the part that matters for compliance buyers.

The verifier runs offline. It does not call any Provedex server. It does not call any of your servers. The auditor needs only the ledger file and the public key. If your company disappears tomorrow, the auditor can still verify the chain with the open-source CLI or any tool that implements the published spec.

That is what makes the receipts court-admissible in a way that signed Datadog logs are not. Logs from a vendor-controlled database are evidence only if the vendor cooperates. Logs from a cryptographic chain are evidence regardless of vendor cooperation.

Performance

Measured on Apple M4 Pro:

  • Per-event signing: 11.2 microseconds in-process
  • Per-event end-to-end including fsync: 3.8 milliseconds
  • Sidecar HTTP roundtrip: 4-5 ms p95 single concurrency
  • p99 added to your Pipecat pipeline: under 5 ms

For voice agents at typical 1-10 events/sec, the overhead is invisible to the user.

What is in scope, what is not

In scope:

  • Cryptographic signing of agent events
  • Hash-chained, tamper-evident NDJSON ledger
  • Offline verification with public key
  • Single-operator setup (one signing key)

Not in scope today:

  • Multi-party signing (multiple keys per receipt)
  • RFC 3161 timestamping (planned)
  • Hosted aggregator (planned, paid tier)
  • PII redaction (operator's job, not the signing layer's)
  • Policy enforcement / approval flow (different layer - see SidClaw for that)

Using LangChain instead?

The LangChain adapter ships alongside Pipecat. Same shared core, same signing path, same v1 event schema. Five lines:

from langchain.chains import LLMChain
from provedex_langchain import ProvedexCallbackHandler

handler = ProvedexCallbackHandler(session_id="my-session")
chain = LLMChain(llm=..., prompt=..., callbacks=[handler])
chain.invoke({"input": "..."})
Enter fullscreen mode Exit fullscreen mode

The handler hooks into LangChain's BaseCallbackHandler lifecycle - on_chain_start, on_chain_end, on_llm_start, on_llm_end, on_tool_start, on_tool_end. Each maps to the same v1 AgentEvent variants that the Pipecat adapter uses, so a ledger produced by either adapter verifies identically with the same CLI.

pip install provedex-langchain
Enter fullscreen mode Exit fullscreen mode

A separate walkthrough for LangChain-specific patterns (agents, tools, retrieval chains) is coming.

Where this is going

Pipecat and LangChain adapters shipped this weekend. LangGraph is next, then CrewAI and an MCP server adapter, all using the same provedex-client shared core.

Post-quantum signature migration is documented in ADR-0006 - hybrid Ed25519 + ML-DSA-65 mode for operators with long-term retention concerns, opt-in feature flag, default unchanged.

There is also a community RFC repo at github.com/provedex/compliance-backend-rfc for cross-implementation interoperability. Multiple backends are converging on cryptographic chains as the primitive. The spec discussion happens there.

Get started

pip install provedex-pipecat       # voice agents
pip install provedex-langchain     # text agents and chains
Enter fullscreen mode Exit fullscreen mode

Full Pipecat example: github.com/provedex/provedex/blob/main/examples/pipecat_voice_basic.py

Full LangChain example: github.com/provedex/provedex/blob/main/examples/langchain_basic.py

Spec stack: github.com/provedex/provedex/tree/main/docs/spec

I am building this in public. Open to questions, design feedback, integration partnership proposals, drop an issue on the repo or reply here.

Aditya

Top comments (0)