# Gogo Telefon — Product Specification (v1.0) **Product name:** Gogo Telefon **Market:** Bosnia and Herzegovina (architecture must support later expansion to Serbia and Kosovo) **Spec status:** Draft v1.4 — living document agreed in planning session; open questions in §17 **Intended reader:** Claude Code (implementation agent) and the founder --- ## 1. Product Overview Gogo Telefon is a **voice-first AI receptionist** for small service businesses in Bosnia and Herzegovina (beauty salons, hairdressers, pedicure/manicure studios, and similar businesses with up to ~15 employees). These businesses lose bookings because nobody can answer the phone while working, and especially outside working hours. The product: 1. **Voice agent** answers phone calls forwarded from the salon's existing number, speaks Bosnian/Serbian/Croatian, knows the salon's services and prices, checks real availability in the salon's scheduling system (Google Calendar or the salon's own booking software via Partner API), and collects a **booking request** from the caller. 2. **Chat agent** — an embeddable web widget on the salon's website that does the same over text, using the same backend logic. 3. **Crucially, the agent never books appointments itself.** It sends a **proposal** (booking request) to the owner by email. The primary flow: the owner contacts the client directly, arranges the appointment themselves, and marks the request as **resolved** with one click (no SMS is sent by us in that case). A secondary one-click option lets the owner confirm a proposed slot and have Gogo send the confirmation SMS to the client. Gogo never writes to the owner's calendar. 4. **Humans first:** before the agent answers, the call rings the salon staff's softphones (SIP clients on their mobile phones). The agent picks up only if nobody answers, or immediately outside working hours. **Business model:** flat rate ≈ **30 KM/month** per salon (target; annual prepay option ~300 KM/yr), with a fair-use limit on agent voice minutes (see §12). Payment is handled offline via B2B bank transfer — **no online payments / card processing in this product.** **Distribution:** word of mouth. There is **no public sign-up.** A super-admin creates and configures every salon. --- ## 2. Key Design Principles 1. **Propose, don't book.** The agent gathers intent + availability and produces a structured proposal. The owner is always the decision-maker. 2. **The owner keeps their tools.** Salon keeps its phone number (conditional call forwarding) and keeps its scheduling tool — Google Calendar (often multiple color-coded calendars per service type) or its own custom booking software (Gogo integrates via the Partner API, Appendix B). Proposals arrive where the owner already works: plain email, or directly inside their booking software. The dashboard is for setup and occasional review, not daily work. 3. **Voice is the primary product.** Chat is a secondary channel sharing the same backend. 4. **Own the infrastructure, minimize per-minute costs.** Self-hosted pipeline in the founder's own data center from day one. Only LLM and TTS remain paid APIs (both behind swappable interfaces). 5. **Short calls by design.** Target call length 60–120 seconds. The agent is efficient and polite, not chatty. 6. **Multi-country-ready foundations.** Currency, language, phone formats, and locale are per-tenant configuration, not hardcoded (BiH now; Serbia/Kosovo later). --- ## 3. System Architecture ``` Caller (PSTN, salon's customers) │ salon's own number (m:tel / BH Telecom / HT Eronet) │ conditional call forwarding │ (no answer / busy / out of hours) ▼ Our SIM number (per salon or pooled) │ GSM Gateway (multi-SIM device, e.g. GoIP/Yeastar class) — also used for outbound SMS to clients │ SIP ▼ SIP Server (Asterisk or FreeSWITCH) — founder's DC │ dial-plan: ring group first (staff softphones, │ N seconds, within working hours only) │ no answer → route to agent ▼ Voice Pipeline (Pipecat, Python) — founder's DC ┌──────────────────────────────────────────────┐ │ STT: faster-whisper (large-v3) on local GPU │ │ LLM: API (Claude Haiku class) — swappable │ │ TTS: API (Azure Neural or ElevenLabs Flash) │ │ — swappable, decided by Phase-0 PoC │ │ Turn-taking / barge-in: Pipecat built-ins │ └──────────────────────────────────────────────┘ │ tool calls (HTTP) ▼ Backend API (FastAPI, Python) — founder's DC ┌──────────────┬───────────────┬──────────────┬───────────────┐ │ Scheduling │ Proposal │ SMS sender │ Tenant config │ │ providers: │ engine + │ (via GSM │ services, │ │ GCal free/ │ email (.ics) │ gateway API) │ hours, limits │ │ busy or │ or partner │ │ │ │ Partner API │ push │ │ │ └──────────────┴───────────────┴──────────────┴───────────────┘ ▲ │ same tools API Chat Agent (web widget, WebSocket) ▲ Dashboard (owner) + Super-admin panel ``` **Deployment:** everything runs in the founder's own data center. GPU node for Whisper (one RTX 4090 / L4-class GPU handles 10–15 concurrent calls). Docker Compose for MVP (no Kubernetes). PostgreSQL as the primary database. --- ## 4. Tech Stack | Layer | Choice | Notes | |---|---|---| | Language | Python 3.12+ | one language across the whole repo | | Voice orchestration | Pipecat | open source; handles turn-taking, barge-in, SIP integration | | SIP server | Asterisk (or FreeSWITCH if Pipecat integration proves simpler) | dial-plan: ring group → agent fallback; call recording | | STT | faster-whisper, large-v3, on local GPU | language hint: `sr` (covers spoken bs/sr/hr); Phase-0 PoC validates | | LLM | Anthropic API, Haiku-class model | behind `LLMProvider` interface; model per-tenant configurable | | TTS | Azure Neural TTS **or** ElevenLabs Flash API | behind `TTSProvider` interface; Phase-0 PoC decides default voice | | Backend | FastAPI + SQLAlchemy + Alembic | REST + WebSocket (chat) | | DB | PostgreSQL 16 | | | Queue/scheduling | Built-in (arq or APScheduler) | proposal expiry, SMS dispatch retries | | Email | SMTP (configurable provider) + generated `.ics` attachments | one-click action links | | Dashboard | Server-rendered (FastAPI + Jinja2 + htmx) or lightweight React — implementer's choice, favor simplicity | Bosnian UI, Latin script for MVP | | Chat widget | Vanilla JS embeddable snippet + WebSocket | no framework requirements on salon's site | | Auth | Session-based; single account per salon + super-admin role | **no public registration** | --- ## 5. Telephony Layer ### 5.1 Inbound call path 1. Salon activates **conditional call forwarding** on its own number: forward on no-answer (~15s), on busy, and (if operator supports schedules — usually not, so handled by us) out of hours. Dashboard shows per-operator activation codes (m:tel, BH Telecom, HT Eronet) generated for the salon's assigned Gogo number. 2. Calls arrive at a **SIM in the GSM gateway** mapped to exactly one salon (MVP: 1 SIM = 1 salon; pooling with DID-style mapping is Phase 2). 3. GSM gateway converts to SIP → Asterisk. ### 5.2 Dial-plan logic (per salon, driven by tenant config) ``` IF within salon working hours AND ring_group not empty AND ring_first_enabled: ring staff softphones (strategy: ring-all or sequential; default ring-all) timeout: configurable, default 12s IF answered by human → bridge call, record, tag outcome = "human_answered" ELSE → route to AI agent ELSE (out of hours, or ring group empty/disabled): route to AI agent immediately ``` ### 5.3 Staff softphones - Staff use **off-the-shelf SIP clients** (Linphone / Zoiper / Groundwire). We build nothing mobile for MVP. - Dashboard: owner adds a worker (name) → system generates SIP credentials + QR code / config link for easy setup. - Workers have **no accounts** in the product — they exist only as SIP endpoints in the ring group. ### 5.4 Call recording & disclosure - All agent calls are recorded (audio) and transcribed. - The agent's greeting **must include a recording disclosure**, e.g.: > "Dobar dan, dobili ste salon {naziv}. Ja sam Gogo, virtuelni asistent. Razgovor se snima. Kako vam mogu pomoći?" - Recordings retention: default 90 days (configurable), then delete audio, keep transcript. ### 5.5 SMS (outbound, via GSM gateway) - The same GSM gateway sends SMS through the salon's assigned SIM (effectively free within SIM plan). - MVP SMS use cases: 1. **Missed-call SMS**: caller hung up before human or agent answered → "Poštovani, dobili ste {salon}. Možete zakazati i putem poruke ili chata: {link}. Nazvaćemo vas ili nas pozovite ponovo." 2. **Request received** (optional, config): "Primili smo vaš zahtjev za termin. Javićemo vam potvrdu u najkraćem roku." 3. **Confirmation**: "Potvrđen termin: {usluga}, {dan} {datum} u {vrijeme}h — {salon}." 4. **Rejection / new proposal**: "{salon}: nažalost traženi termin nije moguć. {alternativa ili molba da pozovu}." - SMS templates are per-tenant editable (with safe defaults), always in Bosnian. --- ## 6. Voice Agent ### 6.1 Language & voice - Understands and speaks **Bosnian/Serbian/Croatian** (treated as one spoken language; STT language hint `sr`). - TTS voice: 2–3 curated voices to choose from in dashboard (final list decided by Phase-0 PoC). - Agent persona name: "Gogo". Tone: warm, brief, professional. No small talk beyond politeness. ### 6.2 Conversation goals (in order) 1. Greet + recording disclosure (template with salon name). 2. Identify caller's need: **(a)** book an appointment, **(b)** ask a question (prices, hours, location, services), **(c)** cancel/reschedule → MVP: agent takes a message for the owner (full flow is Phase 2), **(d)** other → take a message. 3. For bookings, collect: **service** (match against tenant service list), **client name**, **callback phone number** (confirm digit by digit if unclear; default to caller ID with verbal confirmation), **home visit?** (only if the service is flagged as available at home — then also collect address/area), and **time preferences**. 4. Call the availability tool (§8.2) and offer **up to 3 concrete free slots** consistent with the caller's preference. The caller may also state their own preferred time — the agent checks it, and if busy, offers nearest alternatives. 5. Close explicitly: "Vaš zahtjev prosljeđujem salonu — kontaktiraće vas u najkraćem roku radi potvrde termina. Hvala i prijatno!" ### 6.3 Prompt composition (owners are never prompt engineers) - The agent's system prompt is built from a **global prompt template owned and maintained by the super-admin** (versioned; improving the template upgrades all salons at once). - The template contains placeholders filled from structured tenant data only: `{salon_profile}`, `{working_hours}`, `{services_table}`, `{notes}`, `{price_mode}`, `{greeting}`. - The greeting is auto-generated from the template + salon name (includes the recording disclosure). Owners do not edit prompt text anywhere. - **Per-tenant prompt overrides exist but are super-admin-only** (advanced escape hatch for unusual salons). - Owner-entered "notes" are plain informational fields injected as data, not free-form instructions to the model; the template instructs the model to treat them as facts about the salon. ### 6.4 Hard rules (system prompt requirements) - **Never state a booking as confirmed.** Always "zahtjev" / "prijedlog" until the owner approves. - Never invent services, prices, or free slots — only from tenant data and availability tool results. - Price answering mode per tenant config: exact prices / ranges only / "cijene na upit". - Include per-tenant custom notes in context (e.g., "ne primamo djecu ispod 7 godina", "parking iza zgrade"). - Target call duration 60–120s; the agent steers back to the goal politely if the caller drifts. - If the caller is abusive or the agent cannot understand after 2 clarification attempts → apologize, promise a callback, end call, log a message for the owner. - Escalation to human mid-call: **Phase 2** (see §14). ### 6.5 Tools exposed to the agent (LLM function-calling) Identical for voice and chat: | Tool | Purpose | |---|---| | `get_salon_info()` | working hours, address, services with duration/price/notes, custom notes | | `check_availability(service_id, date_range, preference)` | returns free slots via the tenant's `SchedulingProvider` (§8): Google Calendar free/busy computation, or the partner's `GET /availability`; buffers applied for GCal tenants, partner tenants return ready slots | | `submit_booking_request(...)` | creates the proposal: service, client name, phone, 1–3 slots (ordered by client preference), home-visit flag + address, free-text summary of the request/problem | | `take_message(text, client_name, phone)` | for non-booking intents; emailed to owner | --- ## 7. Chat Agent (web widget) - Embeddable JS snippet (one `