supafone-labs 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- supafone_labs-0.3.0/.gitignore +30 -0
- supafone_labs-0.3.0/LICENSE +21 -0
- supafone_labs-0.3.0/PKG-INFO +470 -0
- supafone_labs-0.3.0/README.md +428 -0
- supafone_labs-0.3.0/pyproject.toml +51 -0
- supafone_labs-0.3.0/src/supafone_labs/__init__.py +105 -0
- supafone_labs-0.3.0/src/supafone_labs/_json.py +28 -0
- supafone_labs-0.3.0/src/supafone_labs/config.py +53 -0
- supafone_labs-0.3.0/src/supafone_labs/facade.py +489 -0
- supafone_labs-0.3.0/src/supafone_labs/llm/__init__.py +16 -0
- supafone_labs-0.3.0/src/supafone_labs/llm/base.py +87 -0
- supafone_labs-0.3.0/src/supafone_labs/llm/hosted_provider.py +67 -0
- supafone_labs-0.3.0/src/supafone_labs/llm/openai_provider.py +41 -0
- supafone_labs-0.3.0/src/supafone_labs/llm/registry.py +59 -0
- supafone_labs-0.3.0/src/supafone_labs/models.py +121 -0
- supafone_labs-0.3.0/src/supafone_labs/oracle/__init__.py +13 -0
- supafone_labs-0.3.0/src/supafone_labs/oracle/belief_state.py +73 -0
- supafone_labs-0.3.0/src/supafone_labs/oracle/directive.py +204 -0
- supafone_labs-0.3.0/src/supafone_labs/oracle/policy.py +35 -0
- supafone_labs-0.3.0/src/supafone_labs/oracle/session.py +73 -0
- supafone_labs-0.3.0/src/supafone_labs/postcall.py +68 -0
- supafone_labs-0.3.0/src/supafone_labs/runtime/__init__.py +36 -0
- supafone_labs-0.3.0/src/supafone_labs/runtime/adapters/__init__.py +31 -0
- supafone_labs-0.3.0/src/supafone_labs/runtime/adapters/base.py +89 -0
- supafone_labs-0.3.0/src/supafone_labs/runtime/adapters/bland.py +232 -0
- supafone_labs-0.3.0/src/supafone_labs/runtime/adapters/cartesia.py +102 -0
- supafone_labs-0.3.0/src/supafone_labs/runtime/adapters/deepgram.py +270 -0
- supafone_labs-0.3.0/src/supafone_labs/runtime/adapters/elevenlabs.py +236 -0
- supafone_labs-0.3.0/src/supafone_labs/runtime/adapters/generic.py +157 -0
- supafone_labs-0.3.0/src/supafone_labs/runtime/adapters/gpt_realtime.py +215 -0
- supafone_labs-0.3.0/src/supafone_labs/runtime/adapters/grok.py +199 -0
- supafone_labs-0.3.0/src/supafone_labs/runtime/adapters/inworld.py +119 -0
- supafone_labs-0.3.0/src/supafone_labs/runtime/adapters/livekit.py +182 -0
- supafone_labs-0.3.0/src/supafone_labs/runtime/adapters/pipecat.py +225 -0
- supafone_labs-0.3.0/src/supafone_labs/runtime/adapters/retell.py +197 -0
- supafone_labs-0.3.0/src/supafone_labs/runtime/adapters/ultravox.py +188 -0
- supafone_labs-0.3.0/src/supafone_labs/runtime/adapters/vapi.py +235 -0
- supafone_labs-0.3.0/src/supafone_labs/runtime/core/__init__.py +12 -0
- supafone_labs-0.3.0/src/supafone_labs/runtime/core/capabilities.py +15 -0
- supafone_labs-0.3.0/src/supafone_labs/runtime/core/decision.py +83 -0
- supafone_labs-0.3.0/src/supafone_labs/runtime/core/events.py +71 -0
- supafone_labs-0.3.0/src/supafone_labs/runtime/core/policies/__init__.py +1 -0
- supafone_labs-0.3.0/src/supafone_labs/runtime/core/policies/consent.py +27 -0
- supafone_labs-0.3.0/src/supafone_labs/runtime/core/policies/recovery.py +49 -0
- supafone_labs-0.3.0/src/supafone_labs/runtime/core/policies/scheduling.py +53 -0
- supafone_labs-0.3.0/src/supafone_labs/runtime/core/policies/truth.py +31 -0
- supafone_labs-0.3.0/src/supafone_labs/runtime/core/policies/watchdog.py +59 -0
- supafone_labs-0.3.0/src/supafone_labs/runtime/core/runtime.py +134 -0
- supafone_labs-0.3.0/src/supafone_labs/runtime/core/state.py +314 -0
- supafone_labs-0.3.0/src/supafone_labs/runtime/replay/__init__.py +5 -0
- supafone_labs-0.3.0/src/supafone_labs/runtime/replay/event_log.py +19 -0
- supafone_labs-0.3.0/src/supafone_labs/runtime/replay/inspector.py +18 -0
- supafone_labs-0.3.0/src/supafone_labs/runtime/replay/snapshot.py +14 -0
- supafone_labs-0.3.0/src/supafone_labs/runtime/workflows/__init__.py +4 -0
- supafone_labs-0.3.0/src/supafone_labs/runtime/workflows/generic_support.py +21 -0
- supafone_labs-0.3.0/src/supafone_labs/runtime/workflows/tool_contracts.py +14 -0
- supafone_labs-0.3.0/src/supafone_labs/stt/__init__.py +29 -0
- supafone_labs-0.3.0/src/supafone_labs/stt/deepgram_live.py +277 -0
- supafone_labs-0.3.0/src/supafone_labs/stt/language.py +188 -0
- supafone_labs-0.3.0/src/supafone_labs/telemetry.py +180 -0
- supafone_labs-0.3.0/src/supafone_labs/tiers.py +55 -0
- supafone_labs-0.3.0/src/supafone_labs/tts/__init__.py +32 -0
- supafone_labs-0.3.0/src/supafone_labs/tts/base.py +58 -0
- supafone_labs-0.3.0/src/supafone_labs/tts/cartesia_tts.py +60 -0
- supafone_labs-0.3.0/src/supafone_labs/tts/deepgram_tts.py +47 -0
- supafone_labs-0.3.0/src/supafone_labs/tts/elevenlabs_tts.py +45 -0
- supafone_labs-0.3.0/src/supafone_labs/tts/hosted_tts.py +49 -0
- supafone_labs-0.3.0/src/supafone_labs/tts/http_base.py +40 -0
- supafone_labs-0.3.0/src/supafone_labs/tts/inworld_tts.py +66 -0
- supafone_labs-0.3.0/src/supafone_labs/tts/registry.py +65 -0
- supafone_labs-0.3.0/src/supafone_labs/tts/supafone_labs_tts.py +75 -0
- supafone_labs-0.3.0/src/supafone_labs/types.py +213 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
.eggs/
|
|
6
|
+
build/
|
|
7
|
+
dist/
|
|
8
|
+
.venv/
|
|
9
|
+
venv/
|
|
10
|
+
.env
|
|
11
|
+
|
|
12
|
+
# Tooling
|
|
13
|
+
.pytest_cache/
|
|
14
|
+
.ruff_cache/
|
|
15
|
+
.mypy_cache/
|
|
16
|
+
.coverage
|
|
17
|
+
htmlcov/
|
|
18
|
+
|
|
19
|
+
# Docs
|
|
20
|
+
site/
|
|
21
|
+
|
|
22
|
+
# OS / editor
|
|
23
|
+
.DS_Store
|
|
24
|
+
.idea/
|
|
25
|
+
.vscode/
|
|
26
|
+
|
|
27
|
+
# LaTeX build artifacts
|
|
28
|
+
paper/*.aux
|
|
29
|
+
paper/*.log
|
|
30
|
+
paper/*.out
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Sam Savage
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,470 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: supafone-labs
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Give any voice agent a second mind — in one line.
|
|
5
|
+
Project-URL: Homepage, https://labs.supafone.ai
|
|
6
|
+
Project-URL: Documentation, https://labs.supafone.ai/docs.html
|
|
7
|
+
Project-URL: Repository, https://github.com/samthedataman/supafone-labs
|
|
8
|
+
Project-URL: Issues, https://github.com/samthedataman/supafone-labs/issues
|
|
9
|
+
Author-email: Sam Savage <samatcrispy@gmail.com>
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: agents,gpt-realtime,oracle,prompt-optimization,ultravox,vapi,voice-ai
|
|
13
|
+
Requires-Python: >=3.11
|
|
14
|
+
Requires-Dist: pydantic>=2.0.0
|
|
15
|
+
Provides-Extra: all
|
|
16
|
+
Requires-Dist: anthropic>=0.40.0; extra == 'all'
|
|
17
|
+
Requires-Dist: email-validator>=2.0.0; extra == 'all'
|
|
18
|
+
Requires-Dist: fastapi>=0.115.0; extra == 'all'
|
|
19
|
+
Requires-Dist: httpx>=0.27.0; extra == 'all'
|
|
20
|
+
Requires-Dist: openai>=1.0.0; extra == 'all'
|
|
21
|
+
Requires-Dist: stripe>=10.0.0; extra == 'all'
|
|
22
|
+
Requires-Dist: uvicorn>=0.30.0; extra == 'all'
|
|
23
|
+
Requires-Dist: websockets>=12.0; extra == 'all'
|
|
24
|
+
Provides-Extra: anthropic
|
|
25
|
+
Requires-Dist: anthropic>=0.40.0; extra == 'anthropic'
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
|
|
28
|
+
Requires-Dist: pytest>=8.0.0; extra == 'dev'
|
|
29
|
+
Requires-Dist: ruff>=0.3.0; extra == 'dev'
|
|
30
|
+
Provides-Extra: http
|
|
31
|
+
Requires-Dist: httpx>=0.27.0; extra == 'http'
|
|
32
|
+
Provides-Extra: openai
|
|
33
|
+
Requires-Dist: openai>=1.0.0; extra == 'openai'
|
|
34
|
+
Provides-Extra: server
|
|
35
|
+
Requires-Dist: email-validator>=2.0.0; extra == 'server'
|
|
36
|
+
Requires-Dist: fastapi>=0.115.0; extra == 'server'
|
|
37
|
+
Requires-Dist: stripe>=10.0.0; extra == 'server'
|
|
38
|
+
Requires-Dist: uvicorn>=0.30.0; extra == 'server'
|
|
39
|
+
Provides-Extra: stt
|
|
40
|
+
Requires-Dist: websockets>=12.0; extra == 'stt'
|
|
41
|
+
Description-Content-Type: text/markdown
|
|
42
|
+
|
|
43
|
+
<div align="center">
|
|
44
|
+
|
|
45
|
+
# Supafone Labs
|
|
46
|
+
|
|
47
|
+
**The voice-agent framework behind Supafone.** Create complete inbound and
|
|
48
|
+
outbound agents with managed numbers, voices, stages, tools, artifacts, and
|
|
49
|
+
Supafone Pro watcher built in — or attach the same second mind to any platform.
|
|
50
|
+
|
|
51
|
+
[](https://github.com/samthedataman/supafone-labs/actions/workflows/ci.yml)
|
|
52
|
+
[](https://pypi.org/project/supafone-labs/)
|
|
53
|
+
[](https://pypi.org/project/supafone-labs/)
|
|
54
|
+
[](LICENSE)
|
|
55
|
+
[](https://api.labs.supafone.ai/healthz)
|
|
56
|
+
|
|
57
|
+
[**Website**](https://labs.supafone.ai) ·
|
|
58
|
+
[**Docs**](https://labs.supafone.ai/docs.html) ·
|
|
59
|
+
[**Console**](https://labs.supafone.ai/console.html) ·
|
|
60
|
+
[**Get a free API key**](https://labs.supafone.ai/get-key.html) ·
|
|
61
|
+
[**API reference**](https://api.labs.supafone.ai/docs)
|
|
62
|
+
|
|
63
|
+
</div>
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
import supafone_labs
|
|
69
|
+
|
|
70
|
+
brain = supafone_labs.supercharge(my_agent) # that's the whole integration
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
import { Supafone } from "@supafone/labs";
|
|
75
|
+
|
|
76
|
+
const supafone = new Supafone({ apiKey: process.env.SUPAFONE_API_KEY! });
|
|
77
|
+
|
|
78
|
+
const agent = await supafone.labs.agents.createInboundWithNumber({
|
|
79
|
+
agentKey: "northline-intake",
|
|
80
|
+
name: "Northline intake",
|
|
81
|
+
assistantName: "Maya",
|
|
82
|
+
websiteUrl: "https://northline.example",
|
|
83
|
+
number: { search: { areaCode: "415" } },
|
|
84
|
+
labs: { enabled: true, model: "gemma" },
|
|
85
|
+
});
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
The TypeScript package is also the canonical client for the Supafone hosted
|
|
89
|
+
agent API at `https://api.supafone.ai/api/v1/labs`. The default path buys and
|
|
90
|
+
routes Supafone-managed numbers, so developers do not need to create Twilio,
|
|
91
|
+
Ultravox, Cartesia, Inworld, ElevenLabs, or Deepgram accounts just to ship an
|
|
92
|
+
agent. BYOK remains available when a team already owns those provider accounts.
|
|
93
|
+
|
|
94
|
+
## Why this exists
|
|
95
|
+
|
|
96
|
+
**A voice agent is one mind on a stopwatch.** To sound human it must answer in
|
|
97
|
+
well under a second — which means the model that *talks* can never afford to
|
|
98
|
+
*think*. And everything that decides whether a call succeeds is thinking:
|
|
99
|
+
reading distress in a caller's voice, noticing they just switched to Spanish,
|
|
100
|
+
catching the agent about to promise something the API failed to do, remembering
|
|
101
|
+
that this firm never quotes fees on the phone. The latency budget forbids all
|
|
102
|
+
of it. That's not a prompt-engineering problem; it's an architecture problem.
|
|
103
|
+
|
|
104
|
+
**Humans solved this decades ago.** Every great call floor has a supervisor
|
|
105
|
+
with a headset — listening to the call, saying nothing to the customer, sliding
|
|
106
|
+
a note across the desk: *"she's scared, slow down"*, *"stop — don't quote the
|
|
107
|
+
fee"*, *"the booking didn't go through, don't say it did."* The agent keeps
|
|
108
|
+
talking; the note changes the call. Nobody expects the person speaking to also
|
|
109
|
+
be the person supervising. Yet that's exactly what we ask of every voice agent
|
|
110
|
+
shipped today.
|
|
111
|
+
|
|
112
|
+
**Supafone Labs is the supervisor.** A second, slower mind that runs *beside* the
|
|
113
|
+
call instead of inside its latency budget: it taps every turn, maintains a
|
|
114
|
+
live belief state — who's calling, what they want, how they feel, what language
|
|
115
|
+
they're speaking — and slides its note across the desk through your platform's
|
|
116
|
+
native silent channel. The caller never hears it. The agent reads it mid-call.
|
|
117
|
+
|
|
118
|
+
**Why silent injection, not a better prompt?** Because prompts are frozen at
|
|
119
|
+
call-start and calls are alive. The moment that matters — the caller starts
|
|
120
|
+
crying, the summary contradicts the tool result, the language flips — is by
|
|
121
|
+
definition the moment your prompt didn't anticipate.
|
|
122
|
+
|
|
123
|
+
**Why every platform?** Because teams switch voice stacks constantly, and the
|
|
124
|
+
coaching layer is exactly the part you can't afford to rewrite. One canonical
|
|
125
|
+
contract in, one whisper out, compiled to whatever you run this quarter.
|
|
126
|
+
|
|
127
|
+
**Why open source with a cloud?** Because a system that whispers into your
|
|
128
|
+
calls must be inspectable — every directive is in the audit log, and the whole
|
|
129
|
+
brain is MIT. The cloud exists for one reason: one key that runs the models,
|
|
130
|
+
the voices, and the transcription is more convenient than five vendor accounts.
|
|
131
|
+
|
|
132
|
+
**And when the second mind fails?** Nothing happens. It runs behind a timeout,
|
|
133
|
+
off the hot path; a stalled oracle yields no note and the call proceeds exactly
|
|
134
|
+
as it would have without us. Degrade-safety is tested, not promised.
|
|
135
|
+
|
|
136
|
+
## Every platform, one whisper
|
|
137
|
+
|
|
138
|
+
<div align="center">
|
|
139
|
+
<table>
|
|
140
|
+
<tr>
|
|
141
|
+
<td align="center" width="110"><img src="https://www.google.com/s2/favicons?domain=vapi.ai&sz=128" width="36" alt="Vapi"><br><sub><b>Vapi</b></sub></td>
|
|
142
|
+
<td align="center" width="110"><img src="https://www.google.com/s2/favicons?domain=retellai.com&sz=128" width="36" alt="Retell"><br><sub><b>Retell AI</b></sub></td>
|
|
143
|
+
<td align="center" width="110"><img src="https://www.google.com/s2/favicons?domain=elevenlabs.io&sz=128" width="36" alt="ElevenLabs"><br><sub><b>ElevenLabs</b></sub></td>
|
|
144
|
+
<td align="center" width="110"><img src="https://www.google.com/s2/favicons?domain=ultravox.ai&sz=128" width="36" alt="Ultravox"><br><sub><b>Ultravox</b></sub></td>
|
|
145
|
+
<td align="center" width="110"><img src="https://www.google.com/s2/favicons?domain=openai.com&sz=128" width="36" alt="OpenAI"><br><sub><b>GPT-Realtime</b></sub></td>
|
|
146
|
+
<td align="center" width="110"><img src="https://www.google.com/s2/favicons?domain=x.ai&sz=128" width="36" alt="xAI"><br><sub><b>Grok Voice</b></sub></td>
|
|
147
|
+
<td align="center" width="110"><img src="https://www.google.com/s2/favicons?domain=deepgram.com&sz=128" width="36" alt="Deepgram"><br><sub><b>Deepgram</b></sub></td>
|
|
148
|
+
</tr>
|
|
149
|
+
<tr>
|
|
150
|
+
<td align="center"><img src="https://www.google.com/s2/favicons?domain=bland.ai&sz=128" width="36" alt="Bland"><br><sub><b>Bland</b></sub></td>
|
|
151
|
+
<td align="center"><img src="https://www.google.com/s2/favicons?domain=pipecat.ai&sz=128" width="36" alt="Pipecat"><br><sub><b>Pipecat</b></sub></td>
|
|
152
|
+
<td align="center"><img src="https://www.google.com/s2/favicons?domain=livekit.io&sz=128" width="36" alt="LiveKit"><br><sub><b>LiveKit</b></sub></td>
|
|
153
|
+
<td align="center"><img src="https://www.google.com/s2/favicons?domain=cartesia.ai&sz=128" width="36" alt="Cartesia"><br><sub><b>Cartesia</b></sub></td>
|
|
154
|
+
<td align="center"><img src="https://www.google.com/s2/favicons?domain=inworld.ai&sz=128" width="36" alt="Inworld"><br><sub><b>Inworld</b></sub></td>
|
|
155
|
+
<td align="center"><img src="https://www.google.com/s2/favicons?domain=anthropic.com&sz=128" width="36" alt="Anthropic"><br><sub><b>Claude</b></sub></td>
|
|
156
|
+
<td align="center"><img src="https://www.google.com/s2/favicons?domain=twilio.com&sz=128" width="36" alt="Twilio"><br><sub><b>Twilio</b></sub></td>
|
|
157
|
+
</tr>
|
|
158
|
+
<tr>
|
|
159
|
+
<td align="center"><img src="https://www.google.com/s2/favicons?domain=telnyx.com&sz=128" width="36" alt="Telnyx"><br><sub><b>Telnyx</b></sub></td>
|
|
160
|
+
<td align="center"><img src="https://www.google.com/s2/favicons?domain=signalwire.com&sz=128" width="36" alt="SignalWire"><br><sub><b>SignalWire</b></sub></td>
|
|
161
|
+
<td align="center"><img src="https://www.google.com/s2/favicons?domain=vonage.com&sz=128" width="36" alt="Vonage"><br><sub><b>Vonage</b></sub></td>
|
|
162
|
+
<td align="center"><img src="https://www.google.com/s2/favicons?domain=plivo.com&sz=128" width="36" alt="Plivo"><br><sub><b>Plivo</b></sub></td>
|
|
163
|
+
<td align="center"><img src="https://www.google.com/s2/favicons?domain=jambonz.org&sz=128" width="36" alt="Jambonz"><br><sub><b>Jambonz</b></sub></td>
|
|
164
|
+
<td align="center"><img src="https://www.google.com/s2/favicons?domain=freeswitch.com&sz=128" width="36" alt="FreeSWITCH"><br><sub><b>FreeSWITCH</b></sub></td>
|
|
165
|
+
<td align="center"><img src="https://www.google.com/s2/favicons?domain=asterisk.org&sz=128" width="36" alt="Asterisk"><br><sub><b>Asterisk</b></sub></td>
|
|
166
|
+
</tr>
|
|
167
|
+
</table>
|
|
168
|
+
</div>
|
|
169
|
+
|
|
170
|
+
## Get started in 60 seconds
|
|
171
|
+
|
|
172
|
+
**1 — Get a key** (5 free minutes, no card):
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
curl -X POST https://api.labs.supafone.ai/v1/signup \
|
|
176
|
+
-H "Content-Type: application/json" -d '{"email": "you@company.com"}'
|
|
177
|
+
# -> { "key": "sl_live_…", "free_minutes": 5.0 } (also emailed to you)
|
|
178
|
+
|
|
179
|
+
export SUPAFONE_LABS_API_KEY=sl_live_…
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
**2 — Install and supercharge:**
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
pip install supafone-labs[all]
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
```python
|
|
189
|
+
import supafone_labs
|
|
190
|
+
|
|
191
|
+
brain = supafone_labs.supercharge(my_agent, scenario="legal_intake")
|
|
192
|
+
result = await brain.observe(raw_event) # feed your platform's events
|
|
193
|
+
# result.actions -> the compiled native whisper (or [] if the oracle is quiet)
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
With the key set, the oracle, TTS, and live multilingual STT all run on
|
|
197
|
+
Supafone Labs' hosted infrastructure. Without it, everything runs on **your own
|
|
198
|
+
vendor keys** — or fully offline on deterministic fakes. Same code, all three
|
|
199
|
+
modes.
|
|
200
|
+
|
|
201
|
+
**3 — Watch it work** in the [console](https://labs.supafone.ai/console.html):
|
|
202
|
+
your balance, usage, and an auditable log of every instruction your second
|
|
203
|
+
mind whispered.
|
|
204
|
+
|
|
205
|
+
## Hosted Supafone agents
|
|
206
|
+
|
|
207
|
+
Use `@supafone/labs` when you want Supafone to host the whole agent:
|
|
208
|
+
|
|
209
|
+
```ts
|
|
210
|
+
const inbound = await supafone.labs.agents.createInboundWithNumber({
|
|
211
|
+
agentKey: "northline-intake",
|
|
212
|
+
name: "Northline intake",
|
|
213
|
+
assistantName: "Maya",
|
|
214
|
+
websiteUrl: "https://northline.example",
|
|
215
|
+
number: { search: { areaCode: "415" } },
|
|
216
|
+
tools: { callRouting: true, scheduling: true, sms: true, voicemail: true },
|
|
217
|
+
labs: { enabled: true, model: "gemma" },
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
const outbound = await supafone.labs.agents.createOutboundWithNumber({
|
|
221
|
+
agentKey: "northline-sales",
|
|
222
|
+
name: "Northline sales team",
|
|
223
|
+
number: { search: { areaCode: "415" } },
|
|
224
|
+
labs: { enabled: true, model: "gemma" },
|
|
225
|
+
});
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
What Supafone handles in the default path:
|
|
229
|
+
|
|
230
|
+
- Supafone-managed phone number search, purchase, assignment, and routing.
|
|
231
|
+
- Managed voice provider accounts for Cartesia, Inworld, ElevenLabs-compatible,
|
|
232
|
+
Ultravox, and Deepgram-backed paths.
|
|
233
|
+
- Multistage inbound and outbound presets instead of one flat prompt.
|
|
234
|
+
- Built-in tools for routing, scheduling, SMS, email, voicemail, knowledge,
|
|
235
|
+
escalation, transcripts, recordings, and summaries.
|
|
236
|
+
- Supafone Pro live watcher/call coach.
|
|
237
|
+
|
|
238
|
+
BYOK is advanced, not required:
|
|
239
|
+
|
|
240
|
+
```ts
|
|
241
|
+
await supafone.labs.telephony.configure({
|
|
242
|
+
mode: "byok",
|
|
243
|
+
provider: "twilio",
|
|
244
|
+
credentials: {
|
|
245
|
+
accountSid: process.env.TWILIO_ACCOUNT_SID!,
|
|
246
|
+
authToken: process.env.TWILIO_AUTH_TOKEN!,
|
|
247
|
+
fromNumber: "+14155550123",
|
|
248
|
+
},
|
|
249
|
+
});
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
## How it works
|
|
253
|
+
|
|
254
|
+
```
|
|
255
|
+
┌─────────────────────────────────────────────┐
|
|
256
|
+
your live call ────▶│ TAP 13 platform adapters + │
|
|
257
|
+
(any platform) │ Deepgram nova-3 multilingual │
|
|
258
|
+
│ STT for audio-only stacks │
|
|
259
|
+
├─────────────────────────────────────────────┤
|
|
260
|
+
│ THINK belief state + coaching oracle │
|
|
261
|
+
│ (off the latency path, timeout- │
|
|
262
|
+
│ bounded, degrade-safe) │
|
|
263
|
+
├─────────────────────────────────────────────┤
|
|
264
|
+
silent whisper ◀────│ WHISPER compiled to the platform's │
|
|
265
|
+
(native channel) │ native control — never spoken │
|
|
266
|
+
└─────────────────────────────────────────────┘
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
## The Cloud API
|
|
270
|
+
|
|
271
|
+
One key fronts the whole stack — hosted oracle models, four TTS engines under
|
|
272
|
+
one voice namespace, and live multilingual transcription. Billed by the
|
|
273
|
+
minute; every request itemized.
|
|
274
|
+
|
|
275
|
+
| Endpoint | What it does |
|
|
276
|
+
|---|---|
|
|
277
|
+
| `POST /v1/signup` | Self-serve key — 5 free minutes, no card |
|
|
278
|
+
| `POST /v1/oracle/complete` | Hosted LLM completion (Claude / GPT / Grok, prefix-routed) |
|
|
279
|
+
| `GET /v1/models` | Live model catalog, fetched hourly from vendors — **never stale** |
|
|
280
|
+
| `POST /v1/tts` | Hosted TTS: Deepgram Aura, Cartesia, ElevenLabs, Inworld |
|
|
281
|
+
| `GET /v1/voices` | The hosted voice catalog |
|
|
282
|
+
| `POST /v1/stt` | Prerecorded transcription (nova-3, 10-language code-switching) |
|
|
283
|
+
| `WS /v1/stt/live` | Live streaming STT — the multilingual tap, zero Deepgram account |
|
|
284
|
+
| `GET /v1/usage` | Today's request counts |
|
|
285
|
+
| `GET /v1/billing/balance` | Minutes remaining + top-up links |
|
|
286
|
+
| `GET /v1/logs` | The audit trail: every whisper, timestamped and billed |
|
|
287
|
+
|
|
288
|
+
<details>
|
|
289
|
+
<summary><b>Python</b></summary>
|
|
290
|
+
|
|
291
|
+
```python
|
|
292
|
+
import httpx
|
|
293
|
+
|
|
294
|
+
API, KEY = "https://api.labs.supafone.ai", os.environ["SUPAFONE_LABS_API_KEY"]
|
|
295
|
+
|
|
296
|
+
r = httpx.post(f"{API}/v1/oracle/complete",
|
|
297
|
+
headers={"Authorization": f"Bearer {KEY}"},
|
|
298
|
+
json={"model": "supafone-labs-oracle", "messages": [...]})
|
|
299
|
+
directive = r.json()["text"] # the silent coaching line
|
|
300
|
+
|
|
301
|
+
audio = httpx.post(f"{API}/v1/tts",
|
|
302
|
+
headers={"Authorization": f"Bearer {KEY}"},
|
|
303
|
+
json={"voice": "supafone-labs-calm-en", "text": "Right away."}).content
|
|
304
|
+
```
|
|
305
|
+
</details>
|
|
306
|
+
|
|
307
|
+
<details>
|
|
308
|
+
<summary><b>TypeScript</b></summary>
|
|
309
|
+
|
|
310
|
+
```ts
|
|
311
|
+
const API = "https://api.labs.supafone.ai";
|
|
312
|
+
const auth = { Authorization: `Bearer ${process.env.SUPAFONE_LABS_API_KEY}` };
|
|
313
|
+
|
|
314
|
+
const { text } = await fetch(`${API}/v1/oracle/complete`, {
|
|
315
|
+
method: "POST",
|
|
316
|
+
headers: { ...auth, "Content-Type": "application/json" },
|
|
317
|
+
body: JSON.stringify({ model: "supafone-labs-oracle", messages: [...] }),
|
|
318
|
+
}).then(r => r.json());
|
|
319
|
+
|
|
320
|
+
// live multilingual STT — language-tagged Results, 10 languages, code-switching
|
|
321
|
+
const ws = new WebSocket(`${API.replace("https","wss")}/v1/stt/live` +
|
|
322
|
+
`?api_key=${KEY}&language=multi&encoding=linear16&sample_rate=16000`);
|
|
323
|
+
```
|
|
324
|
+
</details>
|
|
325
|
+
|
|
326
|
+
Full reference with every endpoint, WebSocket framing, and error shapes:
|
|
327
|
+
[**docs**](https://labs.supafone.ai/docs.html) · interactive
|
|
328
|
+
[OpenAPI](https://api.labs.supafone.ai/docs).
|
|
329
|
+
|
|
330
|
+
## Pricing
|
|
331
|
+
|
|
332
|
+
| | |
|
|
333
|
+
|---|---|
|
|
334
|
+
| **Signup** | 5 free minutes, no card |
|
|
335
|
+
| **Pay as you go** | [$10 → 400 minutes](https://buy.stripe.com/7sY00d4Mz4yoaiF9003VC01) |
|
|
336
|
+
| **Subscription** | [$49/mo → 2,000 minutes](https://buy.stripe.com/14A28l6UH4yo3Uh4JK3VC00) |
|
|
337
|
+
| **Metering** | oracle call = 1s · TTS ≈ seconds of speech · live STT = session time |
|
|
338
|
+
| **Self-host** | free forever — the gateway (`cloud/`) is in this repo, MIT |
|
|
339
|
+
|
|
340
|
+
Every billed second is itemized in [`/v1/logs`](https://labs.supafone.ai/console.html).
|
|
341
|
+
BYO vendor keys always win when present — leaving the cloud is deleting one
|
|
342
|
+
environment variable.
|
|
343
|
+
|
|
344
|
+
## Works with every voice platform
|
|
345
|
+
|
|
346
|
+
Speech-to-speech models, STT→LLM→TTS pipelines, frameworks, and raw speech
|
|
347
|
+
engines each get the injection channel they actually have:
|
|
348
|
+
|
|
349
|
+
| Platform | Kind | Whisper delivery |
|
|
350
|
+
|---|---|---|
|
|
351
|
+
| Ultravox | S2S agent | `inject_message` |
|
|
352
|
+
| OpenAI GPT-Realtime · xAI Grok | S2S agents | `session.update` prompt patch |
|
|
353
|
+
| Vapi | pipeline agent | `assistant_override` |
|
|
354
|
+
| Retell | custom-LLM WS | system message into your LLM turn |
|
|
355
|
+
| ElevenLabs Agents | pipeline agent | `contextual_update` |
|
|
356
|
+
| Deepgram Voice Agent | pipeline agent | `UpdatePrompt` |
|
|
357
|
+
| Pipecat · LiveKit Agents | frameworks | context frame / chat-context append |
|
|
358
|
+
| Bland · Cartesia · Inworld | tap-only | observed, honestly not injectable |
|
|
359
|
+
| Anything else | webhook | `GenericWebhookAdapter`, configurable |
|
|
360
|
+
|
|
361
|
+
Five providers are verified against **live APIs** in the repeatable test suite
|
|
362
|
+
(`pytest -m live`); the rest are built to current official docs with citations
|
|
363
|
+
— [docs/providers.md](docs/providers.md) marks which is which. Telephony is
|
|
364
|
+
transport-agnostic: Twilio, Telnyx, SignalWire, Vonage, Plivo, LiveKit SIP,
|
|
365
|
+
Jambonz, FreeSWITCH/Asterisk, and SIPREC forks all feed the same tap
|
|
366
|
+
([SIP matrix](https://labs.supafone.ai/docs.html#sip)).
|
|
367
|
+
|
|
368
|
+
Runnable integrations for every permutation live in [`examples/`](examples/).
|
|
369
|
+
|
|
370
|
+
## Live multilingual transcription
|
|
371
|
+
|
|
372
|
+
Callers switch languages mid-sentence; the tap keeps up. Deepgram nova-3
|
|
373
|
+
`language=multi` code-switches live across en/es/fr/de/hi/ru/pt/ja/it/nl,
|
|
374
|
+
every utterance arrives language-tagged, and the coaching comes back in the
|
|
375
|
+
caller's language — Spanish callers get Spanish guardrails, silently, mid-call.
|
|
376
|
+
|
|
377
|
+
```python
|
|
378
|
+
from supafone_labs.stt import MultilingualCallTap, recommended_setup
|
|
379
|
+
|
|
380
|
+
recommended_setup("vapi") # -> use Vapi's transcripts, skip the tap
|
|
381
|
+
recommended_setup("ultravox", multilingual=True) # -> tap becomes the language authority
|
|
382
|
+
|
|
383
|
+
tap = MultilingualCallTap(brain, session_id=call_sid) # any SIP/audio fork
|
|
384
|
+
await tap.feed(track="inbound", payload_b64=frame)
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
One rule prevents every bad combination: **exactly one transcript source per
|
|
388
|
+
call** — `recommended_setup()` picks it, so you never double-ingest or
|
|
389
|
+
double-pay. With `SUPAFONE_LABS_API_KEY` set and no Deepgram account, the tap
|
|
390
|
+
routes through the hosted proxy automatically.
|
|
391
|
+
|
|
392
|
+
## Pick your model. Write your prompts.
|
|
393
|
+
|
|
394
|
+
```python
|
|
395
|
+
brain = supafone_labs.SupafoneLabs(
|
|
396
|
+
provider="ultravox",
|
|
397
|
+
oracle_model="claude-sonnet-4-6", # provider auto-inferred (Anthropic/OpenAI/xAI/hosted)
|
|
398
|
+
oracle_instructions="Coach for a bilingual intake desk. Empathy before logistics.",
|
|
399
|
+
)
|
|
400
|
+
|
|
401
|
+
models = await supafone_labs.discover_oracle_models() # live vendor catalogs, cached hourly
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
Model routing is prefix-based and the catalogs are fetched from vendor APIs at
|
|
405
|
+
runtime — **a model released tomorrow works today**, no package update. The
|
|
406
|
+
static table in `config.py` is an offline fallback only.
|
|
407
|
+
|
|
408
|
+
## Built for production
|
|
409
|
+
|
|
410
|
+
- **Degrade-safe by construction** — the oracle runs behind a timeout off the
|
|
411
|
+
hot path; a stalled LLM, a dead STT socket, or a failed TTS backend can never
|
|
412
|
+
take down the call it's shadowing. The TTS chain fails downward
|
|
413
|
+
(hosted → your keys → offline audio); the tap no-ops without credentials.
|
|
414
|
+
- **Auditable** — every whispered instruction is in `/v1/logs` with a
|
|
415
|
+
timestamp and its exact cost. No black box.
|
|
416
|
+
- **Tested like infrastructure** — 200+ offline tests (every adapter's parse,
|
|
417
|
+
injection compile, and capability honesty; end-to-end facade runs per
|
|
418
|
+
provider; billing; tiering) plus live contract checks against Deepgram,
|
|
419
|
+
Ultravox, ElevenLabs, Cartesia, and Inworld.
|
|
420
|
+
- **No lock-in** — MIT package, MIT gateway. Self-host the whole cloud:
|
|
421
|
+
`cd cloud && uvicorn app:app`.
|
|
422
|
+
|
|
423
|
+
## The research behind it
|
|
424
|
+
|
|
425
|
+
The architecture is an assembly of five peer-reviewed threads — dual-process
|
|
426
|
+
talker/reasoner agents (DeepMind's [Talker-Reasoner](https://arxiv.org/abs/2410.08328)),
|
|
427
|
+
the evidence that models [can't reliably self-correct](https://arxiv.org/abs/2310.01798)
|
|
428
|
+
(hence an *external* supervisor), generator/verifier splits
|
|
429
|
+
([Cobbe 2021](https://arxiv.org/abs/2110.14168), [Lightman 2023](https://arxiv.org/abs/2305.20050),
|
|
430
|
+
[Baker 2025](https://arxiv.org/abs/2503.11926)), inference-time multi-model oversight
|
|
431
|
+
(Sakana AI's [AB-MCTS](https://arxiv.org/abs/2503.04412)), and feedback-driven prompt
|
|
432
|
+
optimization ([OPRO](https://arxiv.org/abs/2309.03409), [DSPy](https://arxiv.org/abs/2310.03714),
|
|
433
|
+
[TextGrad](https://arxiv.org/abs/2406.07496)). All 22 citations, verified and annotated:
|
|
434
|
+
[**the research page**](https://labs.supafone.ai/research.html), and the full synthesis —
|
|
435
|
+
meta-analysis plus the formal runtime treatment — is the
|
|
436
|
+
[**whitepaper (PDF)**](https://labs.supafone.ai/whitepaper.pdf)
|
|
437
|
+
([LaTeX source](paper/whitepaper.tex)).
|
|
438
|
+
|
|
439
|
+
## Repo layout
|
|
440
|
+
|
|
441
|
+
```
|
|
442
|
+
src/supafone_labs/ the package — facade, oracle, runtime + 13 adapters, tts, stt, tiers
|
|
443
|
+
cloud/ Supafone Labs Cloud — the hosted gateway (FastAPI)
|
|
444
|
+
landing/ the website (landing, get-key, console, docs)
|
|
445
|
+
examples/ one runnable integration per platform + TypeScript client
|
|
446
|
+
tests/ 200+ offline tests · live contract checks (pytest -m live)
|
|
447
|
+
docs/ provider capability matrix + quickstart
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
## Development
|
|
451
|
+
|
|
452
|
+
```bash
|
|
453
|
+
make install # editable install + dev tools
|
|
454
|
+
make test # offline suite (live tests skip without keys)
|
|
455
|
+
pytest -m live # live provider contract checks
|
|
456
|
+
make lint # ruff
|
|
457
|
+
cd cloud && uvicorn app:app --reload # run the gateway locally
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
## Security
|
|
461
|
+
|
|
462
|
+
Keys are bearer credentials — treat `sl_live_…` like a password. The gateway
|
|
463
|
+
stores no call audio; logs keep a 240-char excerpt per request (last 1,000 per
|
|
464
|
+
key) for your own auditability. Report vulnerabilities via
|
|
465
|
+
[SECURITY.md](SECURITY.md).
|
|
466
|
+
|
|
467
|
+
## License
|
|
468
|
+
|
|
469
|
+
MIT © 2026 Sam Savage. Free tier is free forever; the cloud exists because one
|
|
470
|
+
key that runs everything is more convenient than five vendor accounts.
|