Synaplan
开源 AI 软件平台,面向企业:自托管 AI 代理,符合 GDPR 的聊天机器人小部件,RAG 知识库,WhatsApp 与 Outlook AI,MCP,多模型路由。支持 Docker、Kubernetes 或在 Germ 托管。
AI 翻译
尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证Aangan Studio phone enquiry agent: qualify, book, hand off (Gemini + Vaani + Supabase)
翻译准备中
取自仓库 README
正在加载完整 README。 以下为已保存的摘录。
This agent answers Aangan Studio's inbound phone enquiries 24/7. It qualifies each caller against the studio's five criteria. Then it does one of four things:
• books a consultation and sends the designer a handoff note
• declines the caller gracefully
• escalates the call to the studio head
• queues a callback
The agent never quotes a price.查看完整 README ↗This agent answers Aangan Studio's inbound phone enquiries 24/7. It qualifies each caller against the studio's five criteria. Then it does one of four things:
The agent never quotes a price.
phone ─► Vaani (vaanivoice.ai: telephony, STT/TTS, Hindi + English)
│ BYOL WebSocket, one per call ──► server/vaani-ws.ts (always-on call server)
│ call-event webhooks ───────────► Vercel /api/voice/vaani (caller number, missed-call safety net)
▼
adapters/voice/vaani.ts ──► core/ (channel-agnostic) ──► adapters/actions.ts
load context ├─ handoff: Telegram (primary) + Resend email
NLU (Gemini | rules) ├─ booking: Cal.com prefilled link
policy decides next step └─ store: Supabase (enquiries, turns,
NLG words it (Gemini | tmpl) qualifications, handoffs, bookings,
PRICING GUARDRAIL (hard) callbacks, cost)
classify outcome │
build handoff note ▼
emit actions app/ dashboard (Next.js)
The brain is separate from the channel. core/ takes a normalized Enquiry and has no knowledge of telephony, Telegram or Supabase. To add WhatsApp or a web form later, you write one new adapter that produces Enquiry turns and calls Session.onCallerTurn() / finalize(). The Vaani adapter is about 100 lines and is the template for that.
DASHBOARD_PUBLIC=1); unset that to require DASHBOARD_PASSWORD. It shows the 21 September calls as sample data.https://aangan-studio-five.vercel.app/api/voice/vaani?token=<VAANI_WEBHOOK_SECRET>npm run voice-server. This needs an always-on host or a tunnel; see step 7 below.main auto-deploys (Vercel project aangan-studio, region bom1).npm install
npm test
npm run harness -- --all
npm run harness -- T13
npm run chat -- --rules
npm run dev
Each command:
npm test runs 94 tests: T01–T20, the guardrail, Hinglish, actions, voice and metrics.npm run harness -- --all replays every transcript and shows its outcome against its label.npm run harness -- T13 shows one call in full: generated conversation, criteria, outcome, handoff note and actions.npm run chat -- --rules lets you be the caller in your terminal. Drop --rules to use Gemini once a key is set.npm run dev starts the dashboard. Without Supabase it replays T01–T20 in demo mode.| Rule | Where | How |
|---|---|---|
| Never quote pricing | core/guardrail.ts | A hard check runs over every agent reply after the model. If the caller's turn is a pricing question, the reply is replaced with the scripted deflection from pricing.md, word for word, whatever the model wrote. Any other reply containing ₹/Rs/lakh/crore, a per-sq-ft rate, a number range, a pricing.md figure or "it'll cost around / rates start at / typically" is also replaced. Handoff notes go through the same scan (assertNoPricing). pricing.md is never put in the model prompt, and money figures are redacted from the other files before they reach the model. A test runs all 20 calls with a deliberately leaky model; no price reaches a caller. |
| Five criteria + boundary rules | core/qualify.ts, core/policy.ts | These are deterministic. The model extracts facts; code decides the outcome. If criteria 1, 2 or 3 are unclear, the agent asks one direct question per criterion and never repeats it. If criterion 4 or 5 is unclear, the lead counts as qualified and the uncertainty goes in the note. The agent never probes for budget. A volunteered budget is checked internally against pricing.md floors, and is flagged only when it is under 50% of the floor ("clearly too low"). Any failed criterion means a decline. Two or more failures use the rubric's generic wording. |
| Outcomes | core/session.ts (classify, finalize) | QUALIFIED: book plus handoff. DECLINED: studio wording per reason. ESCALATED: studio head, 15-minute callback. CALLBACK: missed or dropped calls are queued for the next business opening. A recovery flag (T16) means: book directly and mark "handle with care". |
| Never a dead end | tests | Every outcome carries a nextStep and at least one action. This is asserted for all 21 calls. |
| Source of truth | knowledge/ | npm run knowledge embeds the markdown into core/knowledge/generated.ts, and a test fails if that copy goes stale. The service-area lists, deflection wording and multi-fail wording are all parsed from the files. |
21 of 21 calls match the brief's labels (T17 counts as two calls). T02 and T13 get the exact deflection on both of their pricing questions, and both still book. Run npm run harness -- --all, or npm run eval:live to run the same set through Gemini.
With Gemini (gemini-3.5-flash-lite, run on 10 Oct 2026): 21 of 21 match, with 0 model fallbacks and 0 prices reaching a caller. Each call cost about ₹0.38, at about 2.7 s per caller turn (extract + reply). Prices are from third-party listings ($0.30 / $2.50 per 1M tokens); confirm them on Google's pricing page.
A volunteered budget ("my budget is X, is that possible?") is treated as a budget-sanity turn (qualified.md §4), not a pricing question. The agent addresses it without echoing the figure, and the guardrail still blocks any number.
Judgement calls I made where the files leave room:
core/knowledge/index.ts is editable, and handoff notes mark adjoining areas "please confirm".core/config.ts.PRICING_DEFLECTION_HINGLISH) with the same meaning and no figures. The studio should sign off on that wording..env.example to .env.local, or to Vercel project env vars. Everything below is optional; each missing piece degrades to a stub.GEMINI_API_KEY. The default model is gemini-3.5-flash-lite: about 1 s per call with no hidden "thinking". gemini-3.8-flash measured about 4 s per call, which is too slow for a phone turn. gemini-2.5-* is closed to new accounts. The ₹ cost uses GEMINI_USD_PER_M_INPUT/OUTPUT and USD_TO_INR, so check current pricing. Each caller turn makes 2 small calls (extract + word), with a 4-second timeout that falls back to the rules brain.supabase/migrations/0001_init.sql in the SQL editor. Set SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY (server-only; RLS is on with no policies).TELEGRAM_BOT_TOKEN. Add the bot to the designers' group and set TELEGRAM_DESIGNER_CHAT_ID. Optionally set TELEGRAM_STUDIO_HEAD_CHAT_ID for escalations; otherwise escalations go to the designer chat.RESEND_API_KEY, HANDOFF_EMAIL_TO and STUDIO_HEAD_EMAIL. You need a verified sending domain for HANDOFF_EMAIL_FROM; otherwise Resend only delivers to your own address.CALCOM_BOOKING_URL to the consultation event page. Links are prefilled with name, phone and notes. On the event's Booking form, set Confirmation to Phone. This makes the built-in attendeePhoneNumber question required, and links prefill it.server/vaani-ws.ts runs separately.
npm run voice-server on your Mac and expose port 8787 with a tunnel (cloudflared tunnel --url http://localhost:8787 or ngrok http 8787).Dockerfile to an always-on host. Fly.io Mumbai costs about $2–5/month.| Piece | Status |
|---|---|
| Core: qualification, policy, guardrail, handoff note, outcomes | Live, and fully tested offline |
| Rules brain (regex NLU + studio-wording templates) | Live. Used by tests and as the runtime fallback |
Gemini brain (gemini-3.5-flash-lite) | Live. On T01–T20: 21 of 21 correct, ₹0.38 per call, about 2.7 s per reply. Falls back to rules on timeout or error |
| Supabase store | Live |
| Telegram | Live (Aangan Leads group) |
| Resend email | Built, off. Needs RESEND_API_KEY and recipient addresses; stubs to console until then |
| Dashboard | Live on Vercel (basic auth), auto-deploys from GitHub |
| Cal.com | Link generation is live. Picking a slot on the call (Cal.com API v2 bookings) is not built: the caller picks the slot from the link |
| Sending the booking link to the caller | Stub. Phone has no channel for it yet. It needs an SMS/WhatsApp adapter, or Vaani's own SMS if it has one. The link is stored and is in the designer's note |
| Vaani voice adapter | Built to Vaani's documented protocol (BYOL WebSocket + call-event webhooks). Tested with a fake Vaani client over a real local WebSocket: every September call gets its labelled outcome on the voice path. Also checked live: Gemini + Supabase over a WebSocket, ₹0.36 per call. Not yet connected to Vaani itself. That needs the call server running somewhere Vaani can reach and a Vaani agent configured (step 7). No paid voice or phone APIs are called in tests |
| Phone number + always-on call-server hosting | Paid, not bought. Vobiz number: ₹100 setup + ₹500–999/month. Hosting: about $2–5/month. Vaani's in-browser calls (₹100 trial balance) work without a number |
| Callback execution (someone actually calling back) | Human step. Callbacks are queued in callbacks and announced on Telegram. A caller ringing back resolves their pending callback automatically (T17) |
| Abandoned voice sessions | Handled. A WebSocket close finalises the call. If the call server was unreachable, Vaani's webhook logs a missed call and queues a callback |
knowledge/ services.md, qualified.md, pricing.md (internal), transcripts PDF + extracted text
core/ types, session pipeline, nlu, policy, qualify, guardrail, nlg, prompt, handoff, timeline
adapters/ brain.ts, llm/gemini.ts, voice/vaani.ts, handoff/{telegram,email}.ts, booking/calcom.ts, actions.ts
server/ vaani-ws.ts: always-on BYOL WebSocket call server (`npm run voice-server`, Dockerfile)
store/ Store port, memory + Supabase implementations
dashboard/ metrics (pure) + data loading
app/ Next.js: dashboard page, /api/voice/vaani (Vaani call-event webhook)
cli/ harness.ts (transcripts), chat.ts (interactive)
tests/ fixtures/transcripts.json (generated by scripts/build-fixtures.ts) + suites
wss://<call-server-host>/vaani. Vaani appends /<call_id> itself.VAANI_BYOL_TOKEN.Hello, Aangan Studio. How can I help you today? Vaani speaks this before our server is called, and it's recorded as the first agent turn.https://<vercel-app>/api/voice/vaani?token=<VAANI_WEBHOOK_SECRET>.
call_started gives us the caller's number.call_postprocessing acts as a safety net: if the call server never handled a call, it's logged as missed and a callback is queued, like T08.DASHBOARD_PASSWORD; the page is behind basic auth. In production it refuses to serve without a password.main auto-deploys. vercel.json pins the functions to Mumbai (bom1) for latency.call_postprocessing