Several adjacent fix shapes that together drop 19 files from the pyrightconfig.json ignore list (96 → 77) and full-pyright errors from 605 → 580. Default pyright stays clean. TTS voice/context_id None handling — most files in this batch had a single error of the shape "value typed `T | None` passed where `T` is required" coming out of `assert_given(self._settings.voice)` (which strips `_NotGiven` but not `None`) or `get_active_audio_context_id()`. Two patterns: - For services where a missing voice means the request can't proceed (hume, openai, xtts, groq, kokoro, piper), added an explicit None check. Inside `run_tts` we yield an `ErrorFrame` and return — matching each service's existing error-emission style (a few wrap `Exception` broadly and were fine; openai/hume/xtts had narrower or no try blocks so a bare `raise ValueError` would have escaped uncaught). Piper validates in `__init__`, where failing fast at construction is the right shape. OpenAI also gained a `voice not in VALID_VOICES` guard with a clear message listing supported voices. - For services where a missing audio context just means "skip this message" (fish, lmnt, smallest, sarvam, neuphonic), widened `TTSService.append_to_audio_context`'s `context_id` signature to `str | None`. The function body already explicitly handled the None case with a debug log + early return, so the prior `str` annotation was a lie; making it honest cleared call sites without local guards. inworld's `_close_context` got the same treatment. google.genai imports — switched `from google import genai` to `import google.genai as genai` in google/image.py and google/llm.py. The dotted form sidesteps a PEP 420 namespace-package stub gap (the `google` namespace stubs come from a different distribution and don't declare `genai`), which means pyright now resolves `genai` to the real module rather than `Unknown`. IDE autocomplete on `genai.<x>` works for the first time. In image.py this surfaced three latent bugs that the `Unknown` resolution had been hiding (model was `str | _NotGiven | None` not narrowed before passing to the SDK; two spots accessed `.image_bytes` on an `Image | None` without a guard) — all fixed. llm.py's dotted import surfaced 8 errors (Content-list typing nuances, internal `_api_client` access, a few small Optionals); deferred to a future pass since they're outside this commit's scope, so the file stays in the ignore list with the dotted import. Latent bug fixes spotted along the way: - resembleai/tts.py was calling `push_error(ErrorFrame(...))`, but `push_error` takes a string — there's a separate `push_error_frame` for the frame case. Switched to the right method. - openai/base_llm.py: `max_completion_tokens` was the only sibling field on `OpenAILLMSettings` missing `| None` in its type, which caused the assignment in openai/llm.py from `params.max_completion_tokens` (`int | None`) to fail. Added `| None` for consistency with `max_tokens` etc. - heygen/base_api.py: `livekit_url: str = None` and `ws_url: str = None` declared `str` while defaulting to `None`. Removed the bogus defaults — both fields are required at construction in every in-tree call site, and the previous `str = None` was a Pydantic footgun. Other small ones: gladia/stt.py needed a None guard on `_session_url` before `websocket_connect`; openrouter/llm.py's `build_chat_completion_params` override widened to `dict[str, Any]` diverging from the parent's `OpenAILLMInvocationParams` — restored the parent's type; neuphonic/tts.py guarded the receive loop's `async for message in self._websocket` with a local-variable narrowing matching the pattern from 9e9b1f39e. groq/tts.py: tightened `output_format`'s typing to `Literal["flac","mp3","mulaw","ogg","wav"] | str = "wav"`. The literal side gives IDE autocomplete hints for the currently-supported set; the `| str` side keeps callers unblocked if groq adds a new format before this list is updated. A `cast` at the API boundary satisfies groq's stricter `Literal` parameter type. The literal alias mirrors the inlined Literal on `groq.resources.audio.speech.AsyncSpeech.create`'s `response_format` (the SDK doesn't export it as a named symbol). websocket_service.py: scoped `# pyright: ignore[reportAttributeAccessIssue]` on `websockets.WebSocketClientProtocol`. That alias is now a deprecated re-export from the legacy submodule and pyright doesn't surface it on the top-level `websockets` namespace; runtime is fine. Migrating to `websockets.ClientConnection` is a separate piece of work (transports/websocket/client.py uses the same alias four times) and left for a future commit. Files dropped from the ignore list: fish/tts.py, gladia/stt.py, google/image.py, groq/tts.py, heygen/base_api.py, hume/tts.py, inworld/tts.py, kokoro/tts.py, lmnt/tts.py, neuphonic/tts.py, openai/llm.py, openai/tts.py, openrouter/llm.py, piper/tts.py, resembleai/tts.py, sarvam/tts.py, smallest/tts.py, websocket_service.py, xtts/tts.py.
🎙️ Pipecat: Real-Time Voice & Multimodal AI Agents
Pipecat is an open-source Python framework for building real-time voice and multimodal conversational agents. Orchestrate audio and video, AI services, different transports, and conversation pipelines effortlessly—so you can focus on what makes your agent unique.
Want to dive right in? Run
pipecat init quickstartor follow the quickstart guide.
🚀 What You Can Build
- Voice Assistants – natural, streaming conversations with AI
- AI Companions – coaches, meeting assistants, characters
- Multimodal Interfaces – voice, video, images, and more
- Interactive Storytelling – creative tools with generative media
- Business Agents – customer intake, support bots, guided flows
- Complex Dialog Systems – design logic with structured conversations
🧠 Why Pipecat?
- Voice-first: Integrates speech recognition, text-to-speech, and conversation handling
- Pluggable: Supports many AI services and tools
- Composable Pipelines: Build complex behavior from modular components
- Real-Time: Ultra-low latency interaction with different transports (e.g. WebSockets or WebRTC)
🌐 Pipecat Ecosystem
🧩 Multi-agent systems
Need multiple AI agents working together? Pipecat Subagents lets you build distributed multi-agent systems where each agent runs its own pipeline and communicates through a shared message bus. Hand off conversations between specialists, dispatch background tasks, and scale agents across processes or machines.
📱 Client SDKs
Building client applications? You can connect to Pipecat from any platform using our official SDKs:
JavaScript | React | React Native | Swift | Kotlin | C++ | ESP32
🧭 Structured conversations
Looking to build structured conversations? Check out Pipecat Flows for managing complex conversational states and transitions.
🪄 Beautiful UIs
Want to build beautiful and engaging experiences? Checkout the Voice UI Kit, a collection of components, hooks and templates for building voice AI applications quickly.
🛠️ Create and deploy projects
Create a new project in under a minute with the Pipecat CLI. Then use the CLI to monitor and deploy your agent to production.
🔍 Debugging
Looking for help debugging your pipeline and processors? Check out Whisker, a real-time Pipecat debugger.
🖥️ Terminal
Love terminal applications? Check out Tail, a terminal dashboard for Pipecat.
🤖 Claude Code Skills
Use Pipecat Skills with Claude Code to scaffold projects, deploy to Pipecat Cloud, and more. Install the marketplace with:
claude plugin marketplace add pipecat-ai/skills
and install any of the available plugins.
🧩 Community Integrations
Build and share your own Pipecat service integrations! Browse existing community integrations or check out our guide to create your own.
📺️ Pipecat TV Channel
Catch new features, interviews, and how-tos on our Pipecat TV channel.
🎬 See it in action
🧩 Available services
📚 View full services documentation →
⚡ Getting started
You can get started with Pipecat running on your local machine, then move your agent processes to the cloud when you're ready.
-
Install uv
curl -LsSf https://astral.sh/uv/install.sh | shNeed help? Refer to the uv install documentation.
-
Install the module
# For new projects uv init my-pipecat-app cd my-pipecat-app uv add pipecat-ai # Or for existing projects uv add pipecat-ai -
Set up your environment
cp env.example .env -
To keep things lightweight, only the core framework is included by default. If you need support for third-party AI services, you can add the necessary dependencies with:
uv add "pipecat-ai[option,...]"
Using pip? You can still use
pip install pipecat-aiandpip install "pipecat-ai[option,...]"to get set up.
🧪 Code examples
- Foundational — small snippets that build on each other, introducing one or two concepts at a time
- Example apps — complete applications that you can use as starting points for development
🛠️ Contributing to the framework
Prerequisites
Minimum Python Version: 3.11 Recommended Python Version: >= 3.12
Setup Steps
-
Clone the repository and navigate to it:
git clone https://github.com/pipecat-ai/pipecat.git cd pipecat -
Install development and testing dependencies:
uv sync --group dev --all-extras \ --no-extra gstreamer \ --no-extra local \ -
Install the git pre-commit hooks:
uv run pre-commit install
Note
: Some extras (local, gstreamer) require system dependencies. See documentation if you encounter build errors.
Claude Code Skills
Install development workflow skills for contributing to Pipecat with Claude Code:
claude plugin marketplace add pipecat-ai/pipecat
claude plugin install pipecat-dev@pipecat-dev-skills
Running tests
To run all tests, from the root directory:
uv run pytest
Run a specific test suite:
uv run pytest tests/test_name.py
🤝 Contributing
We welcome contributions from the community! Whether you're fixing bugs, improving documentation, or adding new features, here's how you can help:
- Found a bug? Open an issue
- Have a feature idea? Start a discussion
- Want to contribute code? Check our CONTRIBUTING.md guide
- Documentation improvements? Docs PRs are always welcome
Before submitting a pull request, please check existing issues and PRs to avoid duplicates.
We aim to review all contributions promptly and provide constructive feedback to help get your changes merged.




