# 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** 1. Fields: target number, topic, tone, goal. 2. A **Call now** button. 3. A live transcript panel (speaker, text, time). 4. A **Hang up** button. 5. 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.css` into 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 1. **It is a demo.** Keep calls short, and set a hard time limit. 2. **Never call a real person without Sam's explicit action.** No bulk, no cold lists. 3. Consider whether to disclose that the caller is an AI. Decide in section 13. 4. Models go through **OmniRoute**, except MiniMax voice. 5. Secrets come from `environment.d`. 6. Own folder, own container, own port. 7. 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: 1. It is a **demo**, not production. 2. **Last project.** Do not start early. 3. MiniMax voice, OmniRoute for the LLM. Resolved: 1. **Channel is chosen per call:** a phone call, WhatsApp, or Sam's Aussie Broadband service. Remaining: 1. **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.** 2. Which channel is the default? 3. One-way (speak a message) or two-way (hold a conversation)? The demo implies two-way. 4. Do we disclose that the caller is an AI? Recommend yes. 5. Which number does it call from, and who pays for it?