Skip to main content

saa-pipecat-client

Pipecat / Daily client for SAA.

Tells your voice agent which speech is actually for it. SAA is the addressee layer: one decision per utterance about whether speech was meant for your agent, before STT, LLM, or TTS. The mental model is simple: audio in -> the SAA addressee gate -> only addressed audio out. No wake word, model-agnostic, drop-in for any Pipecat pipeline.

It adds attention-aware gating, barge-in, and proactive interjection to any Pipecat voice agent running on Daily, including bots deployed to Daily Bots and Pipecat Cloud.

The attention model runs on attention labs' service, so this is a thin Apache-2.0 client: it mints a Daily meeting token, starts a session, and listens for typed events. All inference runs server-side.

Install

pip install saa-pipecat-client

Requirements: Python 3.11+ (pipecat-ai 1.x dropped 3.10). macOS / Linux / WSL2 only

Quickstart: existing Pipecat bot

import os, asyncio
from pipecat.pipeline.pipeline import Pipeline
from pipecat.pipeline.runner import PipelineRunner
from pipecat.pipeline.task import PipelineTask
from pipecat.transports.daily.transport import DailyTransport, DailyParams

from saa_pipecat_client import (
    AttentionEngine, attention_agent_token, start_attention_session,
)


async def main() -> None:
    # 1. Mint a hidden-bot Daily meeting token using YOUR Daily API key.
    #    We never see it.
    agent_token = attention_agent_token(
        daily_api_key=os.environ["DAILY_API_KEY"],
        room_name="sess-xyz",
    )

    # 2. Summon the saa hosted bot into the room.
    session = await start_attention_session(
        api_key=os.environ["SAA_API_KEY"],
        room_url="https://your-org.daily.co/sess-xyz",
        agent_token=agent_token,
        participant_identity="user-omar",
        attention_config={"frames_per_turn": 3, "vad_threshold": 0.5},
    )

    # 3. Stand up your Pipecat pipeline, unchanged from your existing setup.
    transport = DailyTransport(
        "https://your-org.daily.co/sess-xyz",
        your_user_token,
        "Voice Agent",
        DailyParams(
            audio_in_enabled=True,
            video_in_enabled=True,
            audio_in_sample_rate=16000,
            audio_out_sample_rate=16000,
        ),
    )

    # 4. Attach the engine. Pass the PipelineTask so upstream actions
    #    (mute, set_threshold, ...) can be queued back to the SAA agent.
    engine = AttentionEngine(transport, agent_identity=session.agent_identity)

    @engine.on_prediction
    def _(p):
        # Gate your STT, only class 2 (talking-to-device) gets through.
        your_llm_gate.set_enabled(p.aligned_class == 2)

    @engine.on_interrupt
    async def _(ev):
        await your_tts.cancel()
        await engine.responding_stop()

    @engine.on_interjection
    async def _(ev):
        await your_tts.say("Want me to help with something?")

    pipeline = Pipeline([transport.input(), stt, llm, tts, transport.output()])
    task = PipelineTask(pipeline)
    engine.bind_task(task)
    await engine.start()

    runner = PipelineRunner()
    try:
        await runner.run(task)
    finally:
        await engine.stop()
        await session.stop()


if __name__ == "__main__":
    asyncio.run(main())

That's the full integration. Works with any Pipecat pipeline.

Greenfield: build_attention_runner

For new voice agents:

from saa_pipecat_client import build_attention_runner, TurnReadyEvent

async def handle_turn(event: TurnReadyEvent, transport):
    response_pcm = await my_llm.respond(event.audio_pcm16, frames=event.frames)
    await publish_response_audio(transport, response_pcm)

run = build_attention_runner(on_turn=handle_turn)
# pass `transport` and `task` you built; the factory mints the token,
# starts the session, and wires the engine.
engine, session = await run(room_url, room_name, human_identity, transport, task)

runner = PipelineRunner()
try:
    await runner.run(task)
finally:
    await engine.stop()
    await session.stop()

Environment: SAA_API_KEY, DAILY_API_KEY.

Event types

Event Fires Payload
PredictionEvent every 250 ms raw_class, aligned_class (0/1/2), confidence, source, num_faces, responding
VADEvent every 250 ms is_speech, probability
warmup_complete model warmed up, predictions begin (callback on_warmup) none
listening_start / listening_cancelled state edges none
TurnReadyEvent end of user turn audio_pcm16, duration, frames, context
InterruptEvent user barges in during AI playback confidence
InterjectionEvent humans went quiet after side-chat reason, audio_pcm16, duration
ErrorEvent out-of-band errors code, message

Classes: 0=silent, 1=human-to-human, 2=human-to-device. responding is True while the AI is mid-playback.

Each is delivered through an @engine.on_* callback: on_prediction, on_vad, on_warmup, on_listening_start, on_listening_cancelled, on_turn_ready, on_interrupt, on_interjection, on_error.

Upstream actions

await engine.mute()                  # stop feeding mic into the hosted processor
await engine.unmute()
await engine.responding_start()      # AI is now speaking
await engine.responding_stop()
await engine.set_threshold(0.65)     # model class-2 confidence threshold

Each call constructs a DailyOutputTransportMessageUrgentFrame addressed to the SAA agent's participant_id and queues it onto the bound PipelineTask. Pipecat's DailyTransport does not expose a public send_app_message(); the frame-queue path is the only supported send mechanism. Calls issued before the bot has joined are buffered and flushed once its participant id resolves.

Data plane

JSON envelopes on the Daily app-message topic "saa", same shapes as saa-livekit-client, so a single consumer-side event handler can serve both transports:

Type Direction Carries
started down bot online
warmup_complete down (edge) none — model warmed up, first real prediction
prediction down (4 Hz) class, aligned_class, confidence, source, num_faces
vad down (4 Hz) is_speech, probability
state down (edge) state ∈ {listening, cancelled}
turn_ready / interjection down (edge) envelope: stream_id, total_chunks, byte_len, duration, context, …
turn_chunk down stream_id, index, data_base64 (base64-chunked binary PCM + JPEGs)
interrupt down (edge) confidence
error down code, message
mute / unmute / responding_start / responding_stop / set_threshold up scoped to participant_id=agent_pid

Binary turn payload (PCM + JPEGs) uses the same layout as saa-livekit-client, see _wire.py. Chunk reassembly is handled inside AttentionEngine; consumers see typed events only.

Daily Bots compatibility

saa-pipecat-client is a pure pip dependency, so any Pipecat pipeline that runs locally also runs on Daily Bots and Pipecat Cloud. No extra deployment knobs.

Requirements

  • Python 3.11+ (pipecat-ai 1.x dropped 3.10 support)
  • pipecat-ai[daily] >= 1.0.0
  • daily-python >= 0.19.0
  • macOS / Linux / WSL2 only, daily-python ships no Windows wheels.
  • Daily room URL must be publicly reachable from our cloud (no private VPC)
  • Audio + video tracks must both be available (the model is multimodal)
  • Customer voice agent and hosted attention bot share the same Daily room

Docs

License

Apache-2.0. © Socero Inc.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

saa_pipecat_client-0.3.4.tar.gz (25.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

saa_pipecat_client-0.3.4-py3-none-any.whl (26.1 kB view details)

Uploaded Python 3

File details

Details for the file saa_pipecat_client-0.3.4.tar.gz.

File metadata

  • Download URL: saa_pipecat_client-0.3.4.tar.gz
  • Upload date:
  • Size: 25.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for saa_pipecat_client-0.3.4.tar.gz
Algorithm Hash digest
SHA256 a565eae83e87a2b83712221456d6bce34a1c2e5ed0a3324aab13031dad014167
MD5 63c7ae21003c88b5d4e223813bb57967
BLAKE2b-256 9d4d0e5317bc01fe9f1a3d6122ed2fa9b4c2ff2dc0cfc4cd2d014eb280b55214

See more details on using hashes here.

File details

Details for the file saa_pipecat_client-0.3.4-py3-none-any.whl.

File metadata

File hashes

Hashes for saa_pipecat_client-0.3.4-py3-none-any.whl
Algorithm Hash digest
SHA256 8c82eee881f5dfc4150da88856999a9f60a9fc8fa260ecfe9f10aed812d993bd
MD5 a3054f07eee2961fdcc7163ca38fd267
BLAKE2b-256 00b98619868015fbaf0a0ad36a3271d1d034f6fa7a7ce22c7ea52f78427cb4d0

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.3.4 This release

2 files

0.3.3

2 files

0.3.1

2 files

0.3.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page