6.5 KiB
Outbound Voice (demo)
Build spec for Paperclip. Status: last project. Do not start until the Hub, the phone app, and Artemis work. Follow the phases in section 11 in order.
1. Purpose and outcome
A demonstration of technology. Show that the system can hold an artificial voice conversation: MiniMax supplies the voice, an LLM supplies the words.
Sam sets a phone number, a topic, and a tone, then presses Call now.
Outcome (the single success statement):
Sam enters a number, a topic, and a tone, presses Call now, and listens to a short, natural conversation driven by the LLM in a MiniMax voice.
2. Scope
In scope
- Set the target number, the topic, the tone, and the goal.
- Start a call on demand ("Call now").
- Speech to text the other person; the LLM decides the reply; MiniMax text to speech speaks.
- Keep the conversation on topic and in tone.
- End the call gracefully.
- Store and show the transcript.
Out of scope
- Inbound calls.
- Production or unattended use.
- Anything safety-critical.
- WhatsApp, unless it turns out to be simple. Decide in Phase 2.
3. Users and roles
- Sam only. This is an operator tool.
4. Functional requirements
| ID | Requirement |
|---|---|
| FR-1 | Set a target: phone number, topic, tone, and goal. Choose the channel: a phone call, WhatsApp, or Sam's Aussie Broadband service. |
| FR-2 | Start a call on demand ("Call now"). |
| FR-3 | Loop: STT the callee → LLM plans the reply → MiniMax TTS speaks it. |
| FR-4 | Keep the reply on topic and in the chosen tone. |
| FR-5 | Detect the end and close the call gracefully. |
| FR-6 | Store the transcript: each turn, who spoke, and the time. |
| FR-7 | Show a live transcript during the call. |
| FR-8 | A hard time limit per call. The demo never runs away. |
| FR-9 | Log the call: number, topic, tone, duration, result. |
5. Screens and UX flow
Screen: control page
- Fields: target number, topic, tone, goal.
- A Call now button.
- A live transcript panel (speaker, text, time).
- A Hang up button.
- Call history with transcripts.
Main flow
Fill the form → Call now → watch the transcript → Hang up (or auto-end) → read the log
6. Look and feel
Reuse the Family Home Lab design system.
- Source:
/home/sam/Docker/Containers/family-home-lab/DESIGN.md - Tokens:
/home/sam/Docker/Containers/family-home-lab/portal/static/tokens.css - Copy
tokens.cssinto this project.
Canvas #f6f5f4, one action blue #0075de, Inter, 8px grid, pill CTAs. Dark mode.
7. Data model
SQLite inside the service. Suggested:
| Table | Holds |
|---|---|
calls |
number, topic, tone, goal, started-at, ended-at, duration, result |
turns |
call id, speaker (ai or human), text, created-at |
recordings |
optional audio paths |
Retention: keep transcripts for a bounded period. Recordings only if Sam asks.
8. Integrations
| System | Use |
|---|---|
| MiniMax | Text to speech, and speech to text. Keys already in environment.d. |
| OmniRoute | The LLM that plans each reply. |
| Telephony | To be decided — see section 13. |
| Hub | Optional. /ask is not required. A /notify on call end is optional. |
9. Technology (locked)
| Item | Value |
|---|---|
| Backend | Go |
| UI | HTMX + server-rendered HTML |
| Database | SQLite |
| Voice | MiniMax T2A and STT |
| LLM | OmniRoute |
| Telephony | Choose per call: phone call, WhatsApp, or Aussie Broadband. Providers decided in Phase 2. |
| Host | .13, Docker |
| Container | This project's own. |
| Port | Allocate one (suggest 8794). |
| URL | voice.lab.audasmedia.com.au via Caddy on .35 |
| Auth | Separate session login. |
10. Rules and constraints
- It is a demo. Keep calls short, and set a hard time limit.
- Never call a real person without Sam's explicit action. No bulk, no cold lists.
- Consider whether to disclose that the caller is an AI. Decide in section 13.
- Models go through OmniRoute, except MiniMax voice.
- Secrets come from
environment.d. - Own folder, own container, own port.
- This project writes its own docs.
11. Build order
Phase 1 — Skeleton and control page
Go service, SQLite, session login, the form, Docker, Caddy route.
DoD: the page runs on .13 and the form saves.
Phase 2 — Telephony (the risk phase) Prove that a call can be placed and that audio flows both ways. Decide the provider here. DoD: a real call connects and the app receives the other person's audio. If this fails, stop and report.
Phase 3 — The conversation loop STT → LLM → MiniMax TTS, turn by turn. DoD: a short real conversation happens, with the LLM replying in a MiniMax voice.
Phase 4 — Topic and tone Prompt the LLM from the form's topic, tone, and goal. DoD: two different tones produce clearly different conversations.
Phase 5 — Transcript Store and display each turn live. DoD: the transcript is complete after a call.
Phase 6 — Graceful end Detect the end, hang up, enforce the time limit. DoD: the call ends cleanly at the limit.
Phase 7 — Documentation DoD: project-docs run; docs updated.
12. Acceptance criteria
- Sam enters a number, topic, and tone, and presses Call now.
- A real call connects, and the LLM holds a short on-topic conversation.
- The tone setting measurably changes the conversation.
- The transcript is stored and readable.
- The call ends cleanly at the time limit.
- It runs in its own container on its own port.
13. Decisions and remaining questions
Resolved:
- It is a demo, not production.
- Last project. Do not start early.
- MiniMax voice, OmniRoute for the LLM.
Resolved:
- Channel is chosen per call: a phone call, WhatsApp, or Sam's Aussie Broadband service.
Remaining:
- Telephony providers. Three channels to prove in Phase 2:
- Phone call — a SIP/cloud provider (for example Twilio), or the Kotlin app places the call and routes audio.
- WhatsApp — no public API. Options: WhatsApp Business Cloud API, or screen
control through
artemis_control. - Aussie Broadband — mobile. Confirmed as a mobile service. Confirm whether it exposes an API, SIP, or only a SIM. Phase 2 proves at least one channel end to end.
- Which channel is the default?
- One-way (speak a message) or two-way (hold a conversation)? The demo implies two-way.
- Do we disclose that the caller is an AI? Recommend yes.
- Which number does it call from, and who pays for it?