Metadata-Version: 2.4
Name: voicematic
Version: 0.1.0
Summary: A vendor-neutral phone voice agent: a telephony transport in, a voice engine, a brain with tools and call control, each part from the vendor you choose.
Author: Flowmatic, UniForceMusic
License-Expression: MIT
Project-URL: Homepage, https://github.com/Flowmatic-AI/flowmatic-toolkit
Project-URL: Repository, https://github.com/Flowmatic-AI/flowmatic-toolkit
Project-URL: Documentation, https://github.com/Flowmatic-AI/flowmatic-toolkit/tree/main/packages/python/voicematic/project/docs
Project-URL: Issues, https://github.com/Flowmatic-AI/flowmatic-toolkit/issues
Keywords: voice,agent,telephony,genesys,audiohook,openai,anthropic,mistral,mcp
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Communications :: Telephony
Classifier: Topic :: Multimedia :: Sound/Audio :: Speech
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
Classifier: Typing :: Typed
Requires-Python: >=3.14
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: openai
Requires-Dist: openai[realtime]>=3.19; extra == "openai"
Provides-Extra: anthropic
Requires-Dist: anthropic>=1.8; extra == "anthropic"
Provides-Extra: mistral
Requires-Dist: mistralai>=2.10; extra == "mistral"
Provides-Extra: mcp
Requires-Dist: mcp>=2.2; extra == "mcp"
Provides-Extra: genesys
Requires-Dist: httpx>=0.28; extra == "genesys"
Provides-Extra: testing
Requires-Dist: websockets>=15; extra == "testing"
Provides-Extra: all
Requires-Dist: openai[realtime]>=3.19; extra == "all"
Requires-Dist: anthropic>=1.8; extra == "all"
Requires-Dist: mistralai>=2.10; extra == "all"
Requires-Dist: mcp>=2.2; extra == "all"
Requires-Dist: httpx>=0.28; extra == "all"
Requires-Dist: websockets>=15; extra == "all"
Provides-Extra: dev
Requires-Dist: build>=1.2; extra == "dev"
Requires-Dist: twine>=5.0; extra == "dev"
Requires-Dist: pytest>=9.0; extra == "dev"
Requires-Dist: mypy>=2.0; extra == "dev"
Requires-Dist: ruff>=0.16; extra == "dev"
Requires-Dist: openai[realtime]>=3.19; extra == "dev"
Requires-Dist: anthropic>=1.8; extra == "dev"
Requires-Dist: mistralai>=2.10; extra == "dev"
Requires-Dist: mcp>=2.2; extra == "dev"
Requires-Dist: httpx>=0.28; extra == "dev"
Requires-Dist: websockets>=15; extra == "dev"
Dynamic: license-file

# voicematic

A phone voice agent, assembled from independent parts: a telephony transport
brings the call in (Genesys Cloud AudioHook out of the box), a voice engine
hears and speaks, a brain with tools does the thinking, and call control hands
the call back to the platform for a transfer. Each AI role picks its vendor:
OpenAI, Anthropic and Mistral are built in, and any vendor that speaks the
OpenAI or Anthropic protocol is configuration.

```bash
pip install "voicematic[openai]"        # or [anthropic], [mistral], [mcp], [genesys], [testing], [all]
```

The core is standard library only. Each vendor's SDK is an extra and loads only
when that provider is used.

```python
from fastapi import FastAPI, WebSocket

from voicematic import DUTCH, AgentProfile, VoiceAgent
from voicematic.telephony import StarletteWebSocket
from voicematic.telephony.genesys import AudioHookTransport
from voicematic.voice import EchoEngine

agent = VoiceAgent(
    AgentProfile(
        name="Voorbeeld",
        persona="Je bent de telefonische assistent van Voorbeeld BV.",
        instructions="Beantwoord vragen kort en eerlijk.",
        greeting="Goedendag, waarmee kan ik u helpen?",
        language=DUTCH,
    ),
    engine=EchoEngine,
)

app = FastAPI()


@app.websocket("/audiohook")
async def audiohook(ws: WebSocket) -> None:
    await ws.accept()
    await agent.handle(AudioHookTransport(StarletteWebSocket(ws), languages=[agent.profile.language.tag]))
```

`EchoEngine` needs no model: two tones, then the caller's own audio back. Swap
it for a speech-to-speech engine (`voicematic.providers.openai.GPTLiveEngine`)
or a `PipelineEngine` of ears, brain and mouth from any vendor.

## Packages

| Package | What it holds |
|---|---|
| `voicematic` | `VoiceAgent`, `CallSession`, `AgentProfile`, `Tool`, `drain_on_signals` |
| `voicematic.telephony` | `TransportABC`, `CallControlABC`; `genesys/` for AudioHook, Architect flow and Platform API transfers |
| `voicematic.voice` | `VoiceEngineABC`, `PipelineEngine`, `EchoEngine` |
| `voicematic.reasoning` | `ReasonerABC`, `ToolLoopReasoner`, `CallableReasoner` |
| `voicematic.llm` / `speech` | `ChatModelABC`, `SpeechToTextABC`, `TextToSpeechABC` and the neutral conversation types |
| `voicematic.providers` | the `PROVIDERS` registry; `openai/`, `anthropic/`, `mistral/` |
| `voicematic.tools` | tool registry, parallel tool calls, the transfer tool, MCP |
| `voicematic.prompts` | `AgentProfile`, `Language`, prompt assembly |
| `voicematic.audio` | formats, G.711, resampling, WAV |
| `voicematic.testing` | an AudioHook simulator (`python -m voicematic.testing`) and a browser test phone |

The library reads no environment and knows no application: settings, profile
and tools come from the project. `tests/test_boundary.py` enforces that, and
that each vendor SDK is imported only in its own `providers/<vendor>/`.

A complete application, with settings, a Dutch profile, tools, MCP, transfers,
Docker images and the full documentation, is in [`../project`](../project).

## Development

```bash
./test.sh                # ruff, mypy and pytest in .venv, with voicematic[dev] installed editable
./publish.sh             # the checks, a build, and an upload to PyPI (PYPI_API_KEY in .env)
```
