@nova.causticdrop nº 005(copy this prompt)
The Prompt
1. Scaffold the working files first You are setting up my personal call receptionist workflow. Before you create code, connect services, or make any external request, suggest this workspace folder path and ask me to confirm or rename it: `~/Documents/call-receptionist-workflow/`. After I confirm, create these files as your first act: - `plan.md` — write the full runbook here: the purpose, service architecture, setup choices, webhook routes, skill behavior, required accounts, allowed caller decisions, appointment rules, testing plan, and operating instructions. Re-read `plan.md` whenever context gets compacted or a new session starts. - `.env` — create this as the local secrets file and never print filled values back into chat. Put one placeholder per line, with no values yet: `PUBLIC_BASE_URL=`, `PUBLIC_WS_URL=`, `TWILIO_ACCOUNT_SID=`, `TWILIO_AUTH_TOKEN=`, `TWILIO_PHONE_NUMBER=`, `OPENAI_API_KEY=`, `GOOGLE_CLIENT_ID=`, `GOOGLE_CLIENT_SECRET=`, `GOOGLE_REDIRECT_URI=`, `GOOGLE_REFRESH_TOKEN=`, `GOOGLE_CALENDAR_ID=`, `OWNER_TIMEZONE=`, `DEFAULT_APPOINTMENT_MINUTES=`, and optional `HUMAN_REVIEW_SMS_TO=`. Ask me whether I want to paste each value into chat one at a time or open `.env` locally and fill it myself. Never store secrets in `plan.md`, `progress.md`, the skill file, source comments, or logs. - `.env.example` — create the same placeholder names with empty values so the project documents what it needs without containing secrets. - `progress.md` — track every completed step. Use this exact format whenever you update it: `## 2026-05-11 14:23 — completed: <step>` followed by `## next: <step>`. Re-read it before every new action so you know what remains. Also create `receptionist_data/` with `contacts_allowlist.csv`, `blocked_numbers.csv`, `call_logs.jsonl`, `appointments_pending_review.jsonl`, and `receptionist_policy.md`. Initialize the CSVs with headers only, initialize the JSONL files empty, and write the first policy draft into `receptionist_policy.md`. 2. What you connect up front Use SDK/API plus a small local backend service as the live runtime. Do not make MCP or a CLI-only flow the main runtime: inbound calls require public HTTPS webhooks, WebSocket audio, SMS sending, and server-side calendar enforcement. MCP may help an AI workspace edit files, but the backend must own live calls, validation, booking, duplicate prevention, and confirmations. Create a small custom skill for this project in my current AI workspace. Place it at `<workspace>/.agents/skills/personal-receptionist/SKILL.md` or the equivalent project skill folder this workspace uses. The skill must teach: workflow purpose; allowed decisions `spam_or_blocked`, `needs_human_review`, `legit_no_booking`, `legit_booking_requested`, and `booked`; required appointment fields; the rule that uncertain callers are logged or escalated instead of booked automatically; the rule that bookings may only use slots returned free by Google Calendar; SMS tone and privacy rules; and a runbook for editing `contacts_allowlist.csv`, `blocked_numbers.csv`, and `receptionist_policy.md`. Do not put API keys, OAuth refresh tokens, Twilio Auth Tokens, webhook signing secrets, or private calendar data in the skill. Set up the backend project with Node.js unless I explicitly choose Python. Run and record these setup commands in `plan.md`: ```bash mkdir personal-receptionist && cd personal-receptionist npm init -y npm install express twilio ws openai googleapis dotenv zod ``` Connect a Twilio account with a phone number that supports Voice and SMS/Messaging. Configure the Twilio number's Voice webhook to POST to `https://<PUBLIC_BASE_URL>/twilio/voice`. Configure the Messaging webhook to `https://<PUBLIC_BASE_URL>/twilio/sms` if callers can reply by text. If using live voice instead of a conservative first screening prompt, expose a secure WebSocket such as `wss://<PUBLIC_HOST>/twilio/media` for Twilio Media Streams. Use `TWILIO_ACCOUNT_SID`, `TWILIO_AUTH_TOKEN`, and `TWILIO_PHONE_NUMBER` from `.env` for server-side Twilio REST calls and request validation. Connect an OpenAI API project with access to Realtime API. The backend connects server-to-server to OpenAI Realtime, configures the session, and defines tool/function calls the model can request: `classify_caller`, `check_calendar_availability`, `create_calendar_event`, and `send_confirmation_sms`. The backend implements those tools, validates arguments with schemas, and applies policy before doing anything external. Keep `OPENAI_API_KEY` only in `.env` or a backend secret store. Connect a Google Cloud project with Google Calendar API enabled and OAuth consent configured for the calendar owner. Use OAuth user consent for a personal receptionist unless the calendar is in a Workspace domain with explicit sharing or delegated access. Use `GOOGLE_REDIRECT_URI` such as `https://<PUBLIC_BASE_URL>/oauth/google/callback`. Store the refresh token in `.env` or an encrypted backend secret store, not in chat, logs, `plan.md`, or the skill. For free/busy checks, request the minimum scope that works for the implementation, from the documented free/busy options: `https://www.googleapis.com/auth/calendar.freebusy`, `https://www.googleapis.com/auth/calendar.events.freebusy`, `https://www.googleapis.com/auth/calendar.readonly`, or broader `https://www.googleapis.com/auth/calendar`. For event creation, use a write-capable Calendar scope; the researched create-events guide recommends `https://www.googleapis.com/auth/calendar`. If you try to narrow event-write scope, verify it before production. Set owner rules in `receptionist_policy.md`: working hours, buffer time, minimum notice, maximum future booking date, default duration from `DEFAULT_APPOINTMENT_MINUTES`, appointment types that are allowed, appointment types that require human review, SMS wording rules, sensitive-data handling, and what to do if the AI, calendar, or SMS service fails. 3. What you watch, read, or trigger on Watch the primary trigger: every inbound call to the Twilio receptionist number. The input is Twilio's Voice webhook form payload to `/twilio/voice`, including call metadata such as caller number, Twilio number, and call SID, plus optional Twilio Media Streams events if live audio is enabled. Watch the optional trigger: every inbound SMS reply to the same Twilio number. The input is Twilio's Messaging webhook payload to `/twilio/sms`, used for reschedules, cancellations, and yes/no confirmations when a booking cannot finish by voice. Also support administrative file triggers inside the workspace: when I update `contacts_allowlist.csv`, `blocked_numbers.csv`, or `receptionist_policy.md`, reload those rules before the next call; when I ask for a review, read `appointments_pending_review.jsonl` and summarize uncertain cases. 4. What you do step-by-step at each event Build the backend around these routes and actions. For an inbound call: 1. Receive the Twilio Voice webhook at `/twilio/voice`. Validate `X-Twilio-Signature` using the exact URL Twilio requested and all form parameters. Reject unsigned or invalid requests before AI processing, calendar access, SMS sending, or logging private details. 2. Create a call record keyed by `CallSid`. Normalize the `From` number. Load `blocked_numbers.csv`, `contacts_allowlist.csv`, and `receptionist_policy.md`. 3. Run caller enrichment with Twilio Lookup v2 for `caller_name` and `line_type_intelligence`. Treat caller name and line type as triage signals, not conclusive spam proof. Non-fixed VoIP, missing CNAM, or unknown name should raise caution but should not automatically block every caller. 4. If the number is in `blocked_numbers.csv` or clearly disallowed by local policy, return TwiML that politely ends the call, do not open the calendar, do not send a booking text, and append `decision=spam_or_blocked` with the reason to `call_logs.jsonl`.
One email. We'll never message you again unless you ask.
Heads upRun this in a local AI workspace — browser chat can't reach your files.