Back to portfolio
Intelligence · PRJ-004

The Commission

Turning field conversations into a structured competitive-intelligence graph — at the effort of a text message.

<3s
Message to fully structured CRM records
~95%
Cost cut vs commercial sales-intel platforms
~$12/mo
All-in infrastructure (free-tier AI)
The Problem

A client in enterprise cybersecurity channel sales had a problem common to high-velocity B2B teams: critical competitive intelligence was being lost between conversations. Reps interact constantly with channel partners (VARs and MSSPs), OEM vendor reps, and enterprise security leaders, and those interactions produce valuable signals — vendor contract expirations, executive movements, competitive displacements, partner shifts — that rarely made it into the CRM.

The intelligence has a short half-life: it is most valuable in the hours and days after it is gathered. But traditional CRMs require navigating to the right account, finding or creating the right contact, picking fields, and typing structured notes — a workflow incompatible with the pace of field sales. So the team’s collective knowledge and what the system reflected steadily drifted apart: pipeline reviews ran on memory, competitive positioning was reactive, and relationship maps lived only in individual reps’ heads.

The client needed to reduce the capture barrier to the effort of sending a text message, automatically extract structured entities and relationships from unstructured input, maintain a relational graph connecting people, organizations, technologies, and signals, and give both individual and team-wide visibility into accumulated intelligence.

The Architecture

The Commission is a conversational sales-intelligence platform fronted by a Telegram bot. Each incoming message does double duty: the model returns a natural conversational acknowledgment to the rep and, simultaneously, silently extracts structured intelligence — organizations, contacts with titles, technology references, and confidence-scored competitive signals — which is inserted into a PostgreSQL relational graph with automatic foreign-key associations.

01

Capture surface — Telegram

Reps message the bot from their phones exactly as they would a colleague, voice notes included — zero install, native notifications, and a UX they already use dozens of times a day. Telegraf handles command routing, middleware authentication, text and voice handling, and typing indicators. The bottleneck being solved is capture friction, not interface sophistication, so the fastest path from “intel in the rep’s head” to “record in the database” wins.

02

Dual-function AI extraction

A single Gemini call operates in two modes defined by the system prompt: it writes a conversational reply and, only when new intelligence is present, emits a tagged JSON extraction block that the application detects by regex and parses. Doing both in one call halves per-message cost and removes a round-trip versus a separate classify-then-extract pipeline.

03

The intelligence graph

A PostgreSQL schema of seven tables (organizations, contacts, signals, deals, current_vehicle, relationship_edges, arbitrage_alerts) stores the extracted entities with automatic foreign-key associations. Multi-value attributes — tech stacks, partner lists, tags — use native TEXT[] arrays with GIN indexes, so “find all organizations using CrowdStrike” is a single indexed containment check rather than a junction-table join.

04

Relationships as first-class edges

Interpersonal and inter-organizational relationships are modeled explicitly in a dedicated table with typed relationships, strength scores, and uniqueness constraints — not inferred from co-occurrence. Knowing that a contact at a partner used to work with a decision-maker at a prospect, and can make a warm introduction, is exactly the relationship-based intelligence that drives deal outcomes.

05

Intelligence / pipeline firewall

A dedicated current_vehicle table separates employer-specific pipeline data (onboarding, MRR, contract dates) from team-wide market intelligence, with fuzzy search via pg_trgm and UUID primary keys via uuid-ossp throughout. The separation keeps the intelligence graph valuable independent of any single employer relationship and prevents internal pipeline data leaking into market-intelligence queries.

06

Deployment & access

The system runs on a single Hetzner VPS (Node.js 22, PostgreSQL 16, headless Chromium for future enrichment) under tmux for process persistence, with Ed25519 key-only SSH and an authorized-user allowlist enforced as bot middleware — unauthorized users get no response at all. Five BEFORE UPDATE triggers keep timestamps consistent regardless of which module writes a record.

Key Decisions & Tradeoffs

The reasoning behind the build — and what each choice cost.

Messaging (Telegram) as the interface, not a native or web app

Why

The bottleneck is capture friction, not interface polish. A native app means app-store cycles and an install; a PWA still needs a bookmark and navigation. Telegram gives zero-install deployment, voice notes, native notifications, and a paradigm reps already use dozens of times a day.

Tradeoff

Less control over the UX and a dependency on a third-party platform — accepted because the fastest path from intel-in-head to record-in-database is the messaging app reps already live in.

Single-call AI extraction, not separate classify + extract

Why

One prompt defines two modes and emits a tagged JSON block only when new intel is present, detected by regex in the app layer — halving per-message cost and removing a round-trip.

Tradeoff

More prompt complexity and reliance on the model distinguishing new intel from follow-up chatter; mitigated with explicit per-mode example messages and graceful malformed-JSON handling.

Postgres native arrays + GIN, not junction tables

Why

Sales-intel queries are dominated by membership filters (tech stack, partners, tags). TEXT[] columns with GIN indexes turn “find all orgs using CrowdStrike” into one containment check instead of a three-table join, and the tag vocabulary is inherently fluid.

Tradeoff

Loses referential integrity on array values and some normalization — accepted because enforcing a controlled vocabulary would be maintenance burden without proportional benefit.

Relationships as explicit first-class edges, not inferred

Why

The client’s competitive advantage is relationship-based access; a dedicated typed, strength-scored edge table captures the nature of a relationship that co-occurrence inference would miss.

Tradeoff

Extra schema complexity and the need for explicit relationship creation.

Tagged JSON in the response, not function calling

Why

Keeping extraction as tagged JSON in the response text lets the schema evolve without touching function definitions and keeps the whole interaction in a single stream.

Tradeoff

No API-level schema validation, so the application parses defensively with try-catch and error logging.

Hetzner VPS + Gemini free tier over managed cloud + paid LLM

Why

The workload needs a plain Node + Postgres + headless-browser box, not Lambda/RDS; Hetzner delivers 4 vCPU / 16GB for ~$10/month (about a quarter of comparable AWS/GCP), and Gemini 2.5 Flash’s free tier covers a 5–10-rep team’s volume with headroom.

Tradeoff

European-datacenter latency (~100–150ms, imperceptible in a messaging UX) and free-tier deprecation risk — mitigated by isolating the AI client behind a single swappable chat function.

Outcome & Performance

The Commission went from bare infrastructure to live production in a single ~3-hour engagement — VPS provisioning, OS config, schema design and deployment, AI integration, bot development, and live field testing. In the first live test, one natural-language message describing a competitive displacement produced 4 classified organization records, 2 confidence-scored competitive signals with technology tags, and 1 contact auto-associated by foreign key — fully structured in under three seconds.

The economics are the headline. All-in infrastructure runs about $12/month with zero incremental AI cost: a 10-rep team at ~25 messages/day projects to roughly 7,500 requests/month, well inside the Gemini free tier. That is about a 95% cost reduction versus commercial sales-intelligence platforms at $50–150 per user per month — while giving the client full data ownership and no vendor lock-in. The access-control layer is verified: authorized users get full functionality, unauthorized users get no acknowledgment the system even exists.

Operationally, the team has folded it into their daily field workflow, and pipeline reviews have shifted from memory-based recounting to data-driven discussion grounded in time-stamped, attributed, confidence-scored intelligence. The schema was built to grow: four planned modules — automated web enrichment, a signal-density scoring engine, a real-time alert pipeline, and a Next.js team dashboard — all share the existing database.

Capabilities
Node.js 22Telegraf (Telegram)Google Gemini 2.5 FlashPostgreSQL 16pg_trgm · GIN · arraysRelationship-graph schemaPlaywright (enrichment)Hetzner VPS · tmuxnode-postgres pooluuid-ossp