Vortex Digital
Vortex Digital
VERA'S LIFECYCLE
How a message becomes a reply — traced from the real backend code
Infrastructure — exact services used
Database — Azure SQL Database
Accessed via SQLAlchemy 2.0 (mssql+pyodbc, ODBC Driver 18). No password in the connection string — auth is an Azure AD token from DefaultAzureCredential, injected per-connection. Tables: EmployeeRecord, CustomerRecord, DocumentMetadataRecord. Document content itself is not stored here, only metadata. src/database/sql.py, src/database/models.py
Document storage — Azure Blob Storage
Container documents. SQL only stores blob_container / blob_path pointers; get_document, get_policy and summarize_meeting fetch the actual text from here. src/azure/blob_client.py
Search index — Azure AI Search
Fields: title, content, content_vector (HNSW, 1536-dim, cosine), doc_type, department, tags. Embeddings from Azure OpenAI text-embedding-3-small. No Azure "semantic ranker" is configured — the semantic_search tool name refers to vector similarity, not that product feature. src/services/search_service.py, scripts/create_search_index.py
Agent runtime — Azure AI Foundry Agent Service
Reached through the OpenAI-compatible Responses API: client.responses.create(background=True, store=True), then polled with client.responses.retrieve(id). One LLM call per turn covers both tool selection and answer synthesis — the agent's model, instructions and MCP connection are configured in Azure, not in this repo's code. src/services/chat_service.py, src/azure/foundry_agent.py
MCP tool registration — Azure Functions Remote MCP
Each tool is a Python function decorated with @bp.mcp_tool(). 8 blueprints (documents, policies, meetings, employees, customers, search, health, chat) are registered in one func.FunctionApp(), exposing 23 MCP tools total. function_app.py
All 23 MCP tools, by category
Try a prompt
Retrieval strategies
Vera has three genuinely different ways to retrieve data — the agent decides which fits each question. Click a prompt to watch its actual path.
Exact
Direct SELECT ... WHERE column = :value against Azure SQL. Fast, deterministic, no matching logic at all.
SQL Search
SQL ILIKE '%term%' pattern matching against the title and department columns only. Fuzzy substring match, not semantic — no embeddings.
Vector / Hybrid
Embeds the query with text-embedding-3-small (1536-dim), then Azure AI Search runs BM25 keyword search and HNSW vector search in one call and fuses the two rankings automatically.
Prompt workflow steps
The robot icon marks the two moments the LLM is actually "thinking" — deciding which tool to call ("Tool choice") and turning results into an answer ("Synthesis"). Steps without it (Prompt sent, Async kickoff, Retrieval, Reply) are plain backend code: HTTP handling, SQL/Azure AI Search queries, and frontend rendering — no language model involved. Under the hood these are actually one single API round trip (responses.create → the same run read back by responses.retrieve), not two separate model calls — the icon marks two conceptual phases of that one call, not two invocations.