11 KiB
Integration: Twilio API for WhatsApp Interface (Multi-User)
Overview
Integrate Twilio's WhatsApp API to allow users to interact with Simba via WhatsApp. This requires multi-user support, linking WhatsApp numbers to existing or new user accounts.
Tasks
Phase 1: Infrastructure and Database Changes
- [TICKET-001] Update
Usermodel to includewhatsapp_number. - [TICKET-002] Generate and apply migrations for the database changes.
Phase 2: Twilio Integration Blueprint
- [TICKET-003] Create a new blueprint for Twilio/WhatsApp webhook.
- [TICKET-004] Implement Twilio signature validation for security.
- Decorator enabled on webhook. Set
TWILIO_SIGNATURE_VALIDATION=falseto disable in dev. SetTWILIO_WEBHOOK_URLif behind a reverse proxy.
- Decorator enabled on webhook. Set
- [TICKET-005] Implement User identification from WhatsApp phone number.
Phase 3: Core Messaging Logic
- [TICKET-006] Integrate
consult_simba_oraclewith the WhatsApp blueprint. - [TICKET-007] Implement outgoing WhatsApp message responses.
- [TICKET-008] Handle conversation context in WhatsApp.
Phase 4: Configuration and Deployment
- [TICKET-009] Add Twilio credentials to environment variables.
- Keys:
TWILIO_ACCOUNT_SID,TWILIO_AUTH_TOKEN,TWILIO_WHATSAPP_NUMBER.
- Keys:
- [TICKET-010] Document the Twilio webhook setup in
docs/whatsapp_integration.md.- Include: Webhook URL format, Twilio Console setup instructions.
Phase 5: Multi-user & Edge Cases
- [TICKET-011] Handle first-time users (auto-creation of accounts or invitation system).
- [TICKET-012] Handle media messages (optional/future: images, audio).
- [TICKET-013] Rate limiting and error handling for Twilio requests.
Implementation Details
Twilio Webhook Payload (POST)
SmsMessageSid,NumMedia,Body,From,To,AccountSid, etc.- We primarily care about
Body(user message) andFrom(user WhatsApp number).
Workflow
- Twilio receives a message -> POST to
/api/whatsapp/webhook. - Validate signature.
- Identify
UserbyFromnumber. - If not found, create a new
Useror return an error. - Get/create
Conversationfor thisUser. - Call
consult_simba_oraclewith the query and context. - Return response via TwiML
<Message>tag.
Integration: Obsidian Bidirectional Data Store
Overview
Integrate Obsidian as a bidirectional data store using the obsidian-headless npm package. SimbaRAG will be able to read/search Obsidian notes for RAG context and write new notes, research summaries, and tasks back to the vault via the LangChain agent.
Tasks
Phase 1: Infrastructure
- [OBS-001] Upgrade Node.js from 20 to 22 in
Dockerfile(required by obsidian-headless). - [OBS-002] Install
obsidian-headlessglobally via npm inDockerfile. - [OBS-003] Add
obsidian_vault_datavolume and Obsidian env vars todocker-compose.yml. - [OBS-004] Document Obsidian env vars in
.env.example(OBSIDIAN_AUTH_TOKEN,OBSIDIAN_VAULT_ID,OBSIDIAN_E2E_PASSWORD,OBSIDIAN_DEVICE_NAME,OBSIDIAN_CONTINUOUS_SYNC). - [OBS-005] Update
startup.shto conditionally runob sync --continuousin background whenOBSIDIAN_CONTINUOUS_SYNC=true.
Phase 2: Core Service
- [OBS-006] Create
utils/obsidian_service.pywithObsidianServiceclass.- Vault setup via
ob sync-setup(async subprocess) - One-time sync via
ob sync - Sync status via
ob sync-status - Walk vault directory for
.mdfiles (skip.obsidian/) - Parse Obsidian markdown: YAML frontmatter → metadata, wikilink conversion, embed stripping, tag extraction
- Read specific note by relative path
- Create new note with frontmatter (auto-adds
created_by: simbarag+ timestamp) - Create task note in configurable tasks folder
- Vault setup via
Phase 3: RAG Indexing (Read)
- [OBS-007] Add
fetch_obsidian_documents()toblueprints/rag/logic.py— usesObsidianServiceto parse all vault.mdfiles into LangChainDocumentobjects withsource=obsidianmetadata. - [OBS-008] Add
index_obsidian_documents()toblueprints/rag/logic.py— deletes existingsource=obsidianchunks, splits documents with sharedtext_splitter, embeds into sharedvector_store. - [OBS-009] Add
POST /api/rag/index-obsidianendpoint (@admin_required) toblueprints/rag/__init__.py.
Phase 4: Agent Tools (Read + Write)
- [OBS-010] Add
obsidian_search_notestool toblueprints/conversation/agents.py— semantic search via ChromaDB withwhere={"source": "obsidian"}filter. - [OBS-011] Add
obsidian_read_notetool toblueprints/conversation/agents.py— reads a specific note by relative path. - [OBS-012] Add
obsidian_create_notetool toblueprints/conversation/agents.py— creates a new markdown note in the vault (title, content, folder, tags). - [OBS-013] Add
obsidian_create_tasktool toblueprints/conversation/agents.py— creates a task note with optional due date. - [OBS-014] Register Obsidian tools conditionally (follow YNAB pattern:
obsidian_enabledflag). - [OBS-015] Update system prompt in
blueprints/conversation/__init__.pywith Obsidian tool usage instructions.
Phase 5: Testing & Verification
- [OBS-016] Verify Docker image builds with Node.js 22 + obsidian-headless.
- [OBS-017] Test vault sync: setup → sync → verify files appear in
/app/data/obsidian. - [OBS-018] Test indexing:
POST /api/rag/index-obsidian→ verify chunks in ChromaDB withsource=obsidian. - [OBS-019] Test agent read tools: chat queries trigger
obsidian_search_notesandobsidian_read_note. - [OBS-020] Test agent write tools: chat creates notes/tasks → files appear in vault → sync pushes to Obsidian.
Implementation Details
Key Files
utils/obsidian_service.py— new, core service (followsutils/ynab_service.pypattern)blueprints/conversation/agents.py— add tools (follows YNAB tool pattern at lines 101-279)blueprints/conversation/__init__.py— update system prompt (line ~94)blueprints/rag/logic.py— add indexing functions (reusevector_store,text_splitter)blueprints/rag/__init__.py— add index endpoint
Write-back Model
Files written to the vault directory are automatically synced to Obsidian Sync by the ob sync --continuous background process. No separate push step needed.
Environment Variables
| Variable | Required | Description |
|---|---|---|
OBSIDIAN_AUTH_TOKEN |
Yes | Auth token for Obsidian Sync (non-interactive) |
OBSIDIAN_VAULT_ID |
Yes | Remote vault ID or name |
OBSIDIAN_E2E_PASSWORD |
If E2EE | End-to-end encryption password |
OBSIDIAN_DEVICE_NAME |
No | Client identifier (default: simbarag-server) |
OBSIDIAN_CONTINUOUS_SYNC |
No | Enable background sync (default: false) |
Integration: WhatsApp to LangChain Agent Migration
Overview
Migrate the WhatsApp blueprint from custom LLM logic to the LangChain agent-based system used by the conversation blueprint. This will provide Tavily web search, YNAB integration, and improved message handling capabilities.
Tasks
Phase 1: Import and Setup Changes
- [WA-001] Remove dependency on
main.py'sconsult_simba_oracleimport inblueprints/whatsapp/__init__.py. - [WA-002] Import
main_agentfromblueprints.conversation.agentsinblueprints/whatsapp/__init__.py. - [WA-003] Add import for
query_vector_storefromblueprints.rag.logic(if needed for simba_search tool). - [WA-004] Verify
main_agentis already initialized as a global variable inagents.py(it is at line 295).
Phase 2: Agent Invocation Adaptation
- [WA-005] Replace
consult_simba_oracle()call (lines 171-178) with LangChain agent invocation. - [WA-006] Add system prompt with Simba facts, medical conditions, and recent events from
blueprints/conversation/__init__.py(lines 55-95). - [WA-007] Build messages payload with role-based conversation history (last 10 messages).
- [WA-008] Handle agent response extraction:
response.get("messages", [])[-1].content. - [WA-009] Keep existing error handling around agent invocation (try/except block).
Phase 3: Configuration and Logging
- [WA-010] Add YNAB availability logging (check
os.getenv("YNAB_ACCESS_TOKEN")is not None) in webhook handler. - [WA-011] Ensure
main_agenttools includesimba_search,web_search, and optionally YNAB tools (already configured inagents.py). - [WA-012] Verify
simba_searchtool usesquery_vector_store()which supportswhere={"source": "paperless"}filter (no change needed, works with existing ChromaDB collection).
Phase 4: Testing Strategy
- [WA-013] Test Simba queries (e.g., "How much does Simba weigh?") — should use
simba_searchtool. - [WA-014] Test general chat queries (e.g., "What's the weather?") — should use LLM directly, no tools.
- [WA-015] Test web search capability (e.g., "What's the latest cat health research?") — should use
web_searchtool with Tavily. - [WA-016] Test YNAB integration if configured (e.g., "How much did I spend on food?") — should use appropriate YNAB tool.
- [WA-017] Test conversation context preservation (send multiple messages in sequence).
- [WA-018] Test rate limiting still works after migration.
- [WA-019] Test user creation and allowlist still function correctly.
- [WA-020] Test error handling for agent failures (returns "Sorry, I'm having trouble thinking right now. 😿").
Phase 5: Cleanup and Documentation
- [WA-021] Optionally remove or deprecate deprecated
main.pyfunctions:classify_query(),consult_oracle(),llm_chat(),consult_simba_oracle()(keep for CLI tool usage). - [WA-022] Update code comments in
main.pyto indicate WhatsApp no longer uses these functions. - [WA-023] Document the agent-based approach in
docs/whatsapp_integration.md(if file exists) or create new documentation.
Implementation Details
Current WhatsApp Flow
- Twilio webhook →
blueprints/whatsapp/__init__.webhook() - Call
consult_simba_oracle(input, transcript)frommain.py consult_simba_oracle()uses customQueryGeneratorto classify query- Routes to
consult_oracle()(ChromaDB) orllm_chat()(simple chat) - Returns text response
Target WhatsApp Flow
- Twilio webhook →
blueprints/whatsapp/__init__.webhook() - Build LangChain messages payload with system prompt and conversation history
- Invoke
main_agent.ainvoke({"messages": messages_payload}) - Agent decides when to use tools (simba_search, web_search, YNAB)
- Returns text response from last message
Key Differences
- No manual query classification — Agent decides based on LLM reasoning
- Tavily web_search now available for current information
- YNAB integration available if configured
- System prompt consistency with conversation blueprint
- Message format — LangChain messages array vs transcript string
Environment Variables
No new environment variables needed. Uses existing:
LLAMA_SERVER_URL— for LLM modelTAVILY_API_KEY— for web searchYNAB_ACCESS_TOKEN— for budget integration (optional)
Files Modified
blueprints/whatsapp/__init__.py— Main webhook handler