Signal Layer OS is a self-hosted outbound Voice AI and revenue intelligence platform for B2B deal teams.
It solves a common operating problem in enterprise sales: important stakeholder conversations happen over calls, but the resulting knowledge is fragmented, manual, and hard to turn into action. A rep or founder may know that a buyer is stalled, that procurement is blocked, or that the economic buyer is still missing, but that signal rarely becomes a structured, searchable system of record.
This platform closes that gap by:
- placing outbound AI calls through Bolna
- ingesting webhook and polling updates reliably
- persisting transcripts and call events
- extracting structured deal intelligence with Gemini
- updating deal, stakeholder, and risk snapshots
- generating next-step recommendations and follow-up drafts
- storing semantic memory in Postgres with pgvector for retrieval
The current implementation includes the full core pipeline through Phase 12:
- authentication and org-scoped access control
- deal and stakeholder management
- outbound call initiation with throttling and cooldowns
- Bolna webhook ingestion with idempotency and polling fallback
- transcript persistence and timeline views
- extraction, evidence anchoring, and append-only snapshots
- deterministic deal risk scoring
- recommendation and draft generation
- semantic memory generation and retrieval with pgvector
- realtime delivery with WebSockets plus polling fallback
- audit logging, dead-letter handling, and transcript redaction/retention
This is intentionally built as a modular monolith that can run on a single node, while keeping clean seams for later extraction.
web: Next.js frontend on port3000api: FastAPI backend on port8000worker: Dramatiq worker for asynchronous pipelinesmaintenance: periodic scheduler for low-frequency maintenance jobs such as transcript retention sweepspostgres: Postgres with pgvector, exposed on host port5433redis: queue, rate limiting, idempotency, pub/sub, and dead-letter storage
- A user logs in and initiates a call for a stakeholder on a deal.
- The backend validates org scope, applies Redis-backed throttling, persists a
CallSession, and invokes the Bolna adapter. - Bolna sends webhook updates, and the system also polls execution status as a fallback.
- Ingestion normalizes provider events, applies idempotency, appends
CallEventrows, and updates theCallSessionprojection. - Once a transcript is finalized, the worker runs extraction and stores an
ExtractionSnapshotplusEvidenceAnchorrows. - The risk engine computes stakeholder, deal, and risk snapshots, and updates current projections on the deal and stakeholder records.
- The recommendation pipeline generates action recommendations and follow-up drafts.
- The memory pipeline creates semantic documents and embeds them into pgvector for search and retrieval.
- Realtime hints are pushed over Redis pub/sub to WebSocket clients, while the frontend uses bounded polling as a resilience fallback.
- Postgres is the system of record.
- pgvector stores semantic embeddings inside the same database.
- Redis handles queueing, rate limiting, idempotency, dead-letter persistence, and realtime fan-out.
- Append-only artifacts are used where historical traceability matters:
CallEvent,ExtractionSnapshot,StakeholderSnapshot,DealSnapshot,RiskSnapshot,ActionRecommendation,FollowupDraft, andMemoryDocument. - Current read models are materialized on the main
Deal,Stakeholder, andCallSessionrecords for fast UI access.
This is the exact path to bring the full stack up locally with Docker and test it against Postgres plus pgvector.
- Docker Desktop with Compose
- A free local port set for
3000,8000,5433, and6379 - For live calls only: Bolna credentials and a public webhook URL
Copy the example file:
Copy-Item .env.example .envFor a local functional smoke test without real outbound calls, set this in
.env:
BOLNA_MOCK_MODE=trueFor real outbound call testing, set:
BOLNA_MOCK_MODE=false
BOLNA_API_KEY=your_bolna_api_key
BOLNA_AGENT_ID=your_bolna_agent_id
WEBHOOK_BASE_URL=https://your-public-url
BOLNA_SMOKE_TEST_NUMBER=your_phone_number
BOLNA_CAPTURE_REAL_PAYLOADS=trueIf you use a tunnel such as ngrok, WEBHOOK_BASE_URL should be the public URL
that reaches your local backend on port 8000.
docker compose up -d --build postgres redis api worker maintenance webThe app does not auto-run migrations on startup. Apply them explicitly:
docker compose run --rm api alembic upgrade headThis also creates the pgvector extension through the migration chain.
docker compose run --rm api python -m scripts.seedSeeded credentials:
- email:
admin@signallayer.dev - password:
changeme123
Seeded demo deal:
Acme Corp Enterprise License
Seeded demo stakeholders:
Jane Chenwith phoneMarcus Riverawith phonePriya Sharmawithout phone
Open:
- frontend:
http://localhost:3000 - API docs:
http://localhost:8000/docs - liveness:
http://localhost:8000/api/health/live - readiness:
http://localhost:8000/api/health/ready
Optional logs:
docker compose logs -f api worker maintenance web- Open
http://localhost:3000/login. - Sign in with the seeded admin credentials.
- Open the demo deal.
- Start a call for
Jane ChenorMarcus Rivera. - If you are in mock mode, the system should simulate the provider flow.
- If you are in live mode, answer the call on the destination phone and let it complete.
- Watch the call monitor page for status changes, transcript readiness, and post-call processing.
- Return to the deal page and verify:
- current risk score and risk level
- deal coverage status
- recommendations
- follow-up drafts
- Use the memory endpoints or later UI surfaces to verify semantic memory was generated.
For a direct provider smoke test outside the UI:
docker compose run --rm api python scripts/live_bolna_smoke.pyYou can also pass a specific phone number:
docker compose run --rm api python scripts/live_bolna_smoke.py --phone +15551234567When BOLNA_CAPTURE_REAL_PAYLOADS=true, the first real webhook and polling
payloads are captured into BOLNA_CAPTURE_FIXTURES_DIR.
Your Bolna webhook target should be:
{WEBHOOK_BASE_URL}/api/webhooks/bolna
If your tunnel URL changes, update .env, restart the affected services, and
update the webhook target in Bolna.
Stop the stack:
docker compose downStop the stack and remove volumes:
docker compose down -vRe-run only migrations:
docker compose run --rm api alembic upgrade headRe-run only seed:
docker compose run --rm api python -m scripts.seedBackend:
cd backend
uv sync
uv run pytest -q
uv run ruff check .
uv run mypy app
uv run uvicorn app.main:app --reloadFrontend:
cd frontend
npm install
npm run lint
npm run build
npm run devThe codebase is implemented through Phase 12 of the implementation plan. The main remaining work is operational validation and demo hardening:
- real outbound-call validation with your Bolna setup
- capture of real webhook and polling fixtures
- final end-to-end demo hardening and recording