Initial spec: AGENTS.md build spec + archived original notes
This commit is contained in:
187
AGENTS.md
Normal file
187
AGENTS.md
Normal file
@@ -0,0 +1,187 @@
|
||||
# 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?
|
||||
Reference in New Issue
Block a user