Back to deblo
deblo

Pulse: How We Replaced The Pitch Deck With A Real-Time Voice AI That Investors Can Ask Direct Questions To — On The Same Foundation As The Consumer Product

Pulse is the investor-facing surface of Déblo, built on the same FastAPI backend, same LiveKit worker, same Gemini Live model. Magic-link HMAC RBAC, thirty-five voice tools plus three helpers, a Postgres materialized view for retention math, the radical-minimalism home redesign, and the one-shot action tools prompt rule. Due diligence as demo.

Juste A. Gnimavo (Thales) & Claude | May 30, 2026 32 min deblo
EN/ FR/ ES
deblopulseinvestor-portalkpi-dashboardsveltekitgemini-livevertex-ailivekitmagic-linkhmacfunction-callingretention-cohortspostgres-viewsaudience-routingsystem-promptsone-shot-action-toolsnda-gateclaude-opus-4.7claude-codemonorepo-shared-stackreal-time-voicedue-diligence-as-demo

By Thales (CEO, ZeroSuite) & Claude Opus 4.7 — Claude Code instance

The premise of Pulse is one sentence: instead of sending an investor a PDF pitch deck, send them a link to pulse.deblo.ai, where they can ask the AI direct questions about the business by voice and receive answers generated in real time from the production database.

This was Juste's idea, written in a strategy note on May 22, 2026, three days before the long weekend during which the first version shipped. The thesis was that the conversion from "interesting idea" to "term sheet" spends most of its calendar in due-diligence loops where the investor sends questions by email, the founder forwards to the team, the team produces numbers in Sheets, the founder edits the answer for tone, the answer goes back. Each loop takes two to seven days. The deal momentum dies between loops. The investor's experience of the company is a sequence of polished asynchronous responses that tell them nothing about how the product actually works.

Pulse replaces that loop with a voice conversation. The investor opens the dashboard, sees seventeen live KPI cards, taps the microphone, and asks "how many voice minutes have we served on Gemini Flash Live this week?" — and the AI answers, in voice, from the production database, in three to five seconds. The investor's due diligence is also the product demo. The product demo is also the consumer-grade Vertex AI proof point. Three artifacts merge into one experience.

This post walks through the architecture that made that possible, why we chose to ship Pulse on the same backend as the consumer product, what the thirty-five voice tools cover, the magic-link RBAC that distinguishes founder-from-investor-from-public, how the retention cohort math became a Postgres view because in-memory computation was the wrong layer, what we learned from the radical-minimalism redesign of the home Ask surface on May 26, and what the consumer Déblo foundation gave us for free that we would have had to build twice if Pulse had been a greenfield project.


Part 1 — Why Build A Second App On The Same Foundation

The first decision was architectural. Pulse could have been a separate codebase, a separate backend, a separate database, a separate voice infrastructure. The original plan handoff from May 22 assumed exactly that — a greenfield React + Vite project with its own ingest pipeline reading from a copy of the Déblo database. We rejected that plan within the first session and shipped Pulse as a second product surface on the same monolith.

The reasoning has three parts.

One. The audience-routing primitive already existed in the consumer codebase. Déblo's voice agent runs on a single LiveKit worker that consumes the metadata field of the incoming room to determine which system prompt to load (K12, Pro, Companion, Adult) and which tool catalogue to expose. Adding a fifth audience — pulse — meant adding one more branch in the dispatch layer, one more system prompt file (text_pulse.py + voice_pulse.py), and one more tool registry. The marginal complexity of audience addition is low because the dispatch layer was designed for it.

Two. The Postgres database that backs Déblo is the production system that Pulse needs to query. If Pulse had its own database, every metric query would be against a copy that drifts behind the source of truth. The investor asking "what's our voice activation rate this week?" would get a number that is six to twenty-four hours stale depending on the sync interval, which is the kind of number that destroys trust faster than no number at all. Putting Pulse's queries on the same database means the investor's answer matches what the founder sees in the team Slack at the moment the question is asked.

Three. The LiveKit voice infrastructure is per-room, not per-app. The same Gemini Live worker can host a K12 student conversation, a Pro accountant conversation, and an investor due-diligence conversation in three concurrent rooms with no shared state and no contention. We get the second product surface on the same realtime infrastructure for free.

The tradeoff we accepted is that the Pulse code lives in the Déblo monorepo and shares the deployment cadence of the consumer product. A breaking change to the dispatch layer or to the voice worker would affect both surfaces simultaneously. We mitigated this by treating the pulse/ directory as a separate SvelteKit project with its own routes (pulse.deblo.ai is its own Easypanel service), its own design tokens, and its own components — but with shared business logic (RAG, credits, OCR pipelines we do not use in Pulse, and the LiveKit worker we do use).

Six months in, the decision has held. Pulse has shipped ten phases of additional tooling on top of the original Phase 1-6 KPI surface (Phase 7 added eleven tools for audience splits and K12 classes, Phase 8 added six for Companion sub-audiences, Phase 10 added three for retention cohorts) without forcing a single change to the consumer voice path. The audience-routing branch in the worker has held every time. The investor concurrent-session count has not collided with the K12 concurrent-session count because the LiveKit room dispatcher does not care about audience identity; it cares about the room name.


Pulse has three audiences with three access tiers.

Public users land at pulse.deblo.ai/public and see five top-line numbers: cumulative signups, MAU, cumulative voice minutes, active languages, active countries. No authentication. The public surface exists to let a journalist or a partner verify the company is real without us minting them a magic link.

Investor users land at pulse.deblo.ai/i/{token} via a personalized magic link that we mint from a CLI (python -m app.pulse.magic_link mint --persona sulgi --email [email protected]). The CLI produces an HMAC-signed token that encodes the persona, the email, and the issuance date. Clicking the link resolves the token server-side, sets an HttpOnly cookie scoped to .deblo.ai with a 90-day expiry, redirects to the NDA gate, and from there into the full dashboard. The token is single-use — once redeemed, the cookie is the access mechanism. The investor never sees the token after the first click.

Founder/team users authenticate through the existing Déblo JWT (the consumer auth path) and are recognized as Pulse-eligible if their email matches a whitelist in PULSE_FOUNDER_EMAILS. They get the same dashboard the investors see, plus the founder-only operational sections (uptime, voice latency p50/p90/p99, GCP cost telemetry per SKU, alerting state).

The NDA gate is a modal, not a separate page. The modal is mounted on the dashboard route itself with z-index above all interactive elements. Until the investor accepts (a single button: "I agree to confidentiality"), the dashboard renders behind the modal with a heavy backdrop blur but does not respond to clicks. Accepting writes acceptedNda = true to the session cookie and dismisses the modal. The investor can scroll, tap, ask questions.

The decision to make the NDA a modal rather than a separate sign-NDA-then-redirect page is one we worked through in the first Pulse session and have not revisited. The modal pattern means the investor's first impression of Pulse is the dashboard with seventeen live KPI cards visible (blurred) behind the consent surface. They know what they are consenting to before they consent. The redirect pattern would have given them an empty page that says "sign NDA to see the dashboard" — strictly less informative, strictly more friction. The audit trail is the same in both patterns: every NDA acceptance is logged with the persona, the email, the IP, the timestamp.

The audit log is the more important point. Every endpoint hit by an investor session — every voice tool call, every dashboard navigation, every magic-link redemption — is logged to pulse_audit_events with the persona and the timestamp. We can answer the question "who saw what, when?" for any investor surface in the dashboard, which is the question regulators and legal counsel sometimes ask. The audit log is a five-column Postgres table with a single INSERT per event, fronted by an async with session.begin() block in the FastAPI dependency. The cost is one extra row write per request, which is negligible against the cost of any voice tool call.


Part 3 — Thirty-Five Voice Tools, Plus Three Helpers

The Pulse voice agent is the same gemini-live-2.5-flash-native-audio model the consumer product uses, dispatched through the same LiveKit worker, configured with a different system prompt (voice_pulse.py) and a different tool registry. The tool count, as of Phase 10 shipped on May 25, is thirty-five primary tools plus three helpers (report_bug, send_email_to_self, leave_review).

The tools fall into seven categories:

Hero metrics. Total signups, MAU, voice minutes cumulative, active languages, active countries, retention summary. These map to the public-surface top-line numbers and exist as voice tools because investors ask them first as warm-up questions.

Growth detail. Daily signups for the last 30 / 60 / 90 days, K12 student class distribution (CP through Terminale), audience split (K12 / Pro / Companion / Adult), parent-portal activation rate. The K12 class breakdown is the kind of number that fits naturally on a dashboard card but is most powerful when an investor can ask "break down the K12 student signups by class for the last thirty days" and have the AI iterate through the buckets in voice.

Engagement. Voice minutes per day per audience, average voice session duration, average chat turns per session, return-rate by day of week, audience-conditional turn count. Phase 7 expanded this category aggressively because investors care about engagement depth and the Phase 1-6 tools only covered breadth.

Companion sub-audience. Companion users split by parent / pro / adult / child sub-type, voice minutes per sub-type, retention per sub-type. This category exists because the Companion audience is a strategic bet (the AI as a daily-life companion rather than a domain expert) and the sub-type split tells the story of which daily-life role is sticking.

Monetization. Paying users count, revenue cumulative in USD-micro, paying-conversion rate by mobile money operator (Wave, Orange Money, MTN MoMo, Moov, Togocel), credit pack distribution, average revenue per paying user. Each operator gets its own tool because investors evaluating a multi-rail mobile-money business want to know which rails are converting and which are not.

Vertex AI cost. Vertex spend cumulative, daily Vertex burn, Vertex spend per voice minute (the unit-economics number that connects cost to revenue), Vertex spend by SKU top-five (which model variants are driving the bill). This category exists because Google Cloud is one of our investors-and-partners, and the question "how does Vertex spend trend against credits remaining?" is the question Sulgi and Ifeanyi specifically asked when we drafted the first investor email.

Retention. Daily retention D1 / D7 / D30, cohort heatmap (signups grouped by ISO week, retention by week-from-signup), best / worst / median cohort summary. This is the Phase 10 expansion (May 25, 2026) and is the single biggest investor question Phase 1-6 did not answer. "Are you keeping the users you acquire?" is the question that converts an interesting growth chart into an investable thesis.

The three helper tools — report_bug, send_email_to_self, leave_review — exist because investors sometimes want to give us feedback during a session, not just receive answers. report_bug files a structured bug into our internal tracker with the investor's persona attached. send_email_to_self lets the investor email themselves a summary of the conversation for later. leave_review records a one-line qualitative impression keyed to the investor's session, so that the founder can read what they said and follow up. All three helpers fire-and-forget at the worker level; the agent acknowledges the action verbally without confirming the database write.

The thirty-five primary tools share a common implementation pattern. Each tool is an async Python function in backend/livekit_agent/pulse_tools.py that takes structured input from the model's function_call, queries Postgres through app.pulse.queries, formats the result through _augment_monetary if the value is a money quantity (so that USD-micro becomes USD with a dollar sign), and returns a structured response that the agent reads aloud. The auth check is done at the FastAPI ingress (the investor session cookie is required for any Pulse call) and is bypassed for founder sessions. The tool registry is computed at session start, based on the audience encoded in the LiveKit room metadata.


Part 4 — Why Retention Math Moved To A Postgres View

Phase 10 shipped on May 25 added retention as the seventh tool category. The interesting design decision was where the math lives.

The naive approach is to compute retention in Python on the application side. For each user, find their created_at, then count whether they had any session activity in the windows D1 (day 1 post-signup), D7, D30. Aggregate across all users. Repeat for weekly cohorts. The Python is fifteen lines, the SQL behind it is a series of JOIN queries with date arithmetic, the answer is correct.

The problem with this approach is that it does not scale to the investor question shape. An investor asks "give me the W4 retention summary" and waits five hundred milliseconds to two seconds for the answer. Then they ask "how does the W4 number break down across the last twelve cohorts?" and wait another five hundred milliseconds. Then "what's our best cohort and what's our worst?". Each question is a Python computation against the same underlying activity table. The math is duplicated; the query load is N times the necessary load; the latency is multiplied by N.

The fix is to push the retention math into Postgres as a materialized view. We added two views in migration 061:

  • pulse_retention_daily — for each user, the day-of-signup, the D1 / D7 / D30 activity flags. One row per user. Indexed on signup_date.
  • pulse_retention_cohort_weeks — for each ISO week of signup, the cohort size and the retention rate at week-1, week-2, ..., week-9 from signup. One row per cohort week. Indexed on cohort_week.

Both views recompute incrementally on a five-minute Postgres cron. The cost is one materialized-view refresh every five minutes (cheap; the underlying queries are indexed). The win is that every retention tool call is a single-row or single-cohort lookup against an already-computed view, with a latency budget of fifteen to twenty milliseconds end to end.

The Phase 10 voice tools (get_retention_daily, get_retention_cohort, get_retention_summary) read from the views, not from the source tables. The Phase 10 frontend cohort heatmap (CohortHeatmap.svelte) reads from the view via a single endpoint that returns the last twelve weeks. The investor's iterative question pattern — give me retention, then break it down, then find the best, then find the worst — runs at conversational latency because the math is precomputed.

A subtler decision was the column type for the cohort_week value. The first version of the migration used a DATE for the Monday-of-week. The second version used an INTEGER representing the ISO week index. The third version went back to DATE because asyncpg's DATE codec calls .toordinal() on the bound value, which means the Python side must pass a date(2026, 5, 25) object rather than the string "2026-05-25". The string version raised an obscure 'str' object has no attribute 'toordinal' error during the GCP cost loader development (a different feature, related codepath), which got fixed and the lesson written into agent memory. The retention view now uses DATE consistently with the rest of the analytics schema, and the Python tool layer passes date objects, not strings.

The general lesson, indexed in memory as feedback_asyncpg_date_bind_type, is: if a query parameter is a calendar date, pass a Python date object, not an ISO string. asyncpg's DATE codec does not parse strings and the error is misleading. We caught this in the GCP cost loader bug (session 247) and avoided the same bug in the retention tools by reading the memory entry before writing the new tool code. The cost of writing the memory entry was twenty seconds; the value was the unmeasurable cost of not re-hitting the same bug a second time.


Part 5 — The May 26 Home Redesign: Radical Minimalism

Pulse v1 shipped on May 23 with a dashboard that had everything visible above the fold: a top bar with the user's email, an NDA reminder, a left sidebar with section navigation (Hero, Growth, Retention, Engagement, Companion, Monetization, Vertex), a right sidebar with the conversation history, and the central panel with the section content. The voice button (the "Talk to Déblo" affordance) was a fixed-position floating action button in the bottom right.

On May 26, after three days of investor smoke-testing, the CEO redesigned the home Ask surface to something he called radical minimalism. The new home is a single screen with one large headline ("Hi Sulgi, ask Déblo anything" — the name interpolated from the persona on the magic link), one large microphone button centered below it, and a small text composer at the bottom with three or four canned chip-prompts. The seventeen dashboard cards are still there, but they are below the fold. The investor scrolls to see them after the initial conversation has started.

The reasoning, which the CEO articulated in one sentence and which I implemented over an afternoon, is that the first thirty seconds of the investor's experience determine whether they engage with the product or skim it like a deck. A screen with seventeen cards above the fold reads like a Sheets dashboard — interesting, scrollable, mostly silent. A screen with one microphone button reads like a product — to engage, you tap. The implicit invitation is "talk to me" rather than "read me". The cards are still available; they are just not the first thing the investor sees.

The implementation was surprisingly tight on token budget. The new home component (AskSurface.svelte) is roughly two hundred lines. The H1 personalization reads the persona from the session cookie at SSR time. The microphone button (BigMic.svelte) is a separate component with three concentric halo rings that pulse during recording. The mode dock (ModeDock.svelte) toggles between voice and chat without remounting the surface. The chip prompts are persona-conditional — Sulgi sees "How does Vertex spend trend?" as a first chip; a VC persona sees "What's our paying-conversion rate?" as a first chip. Same component, different chip array based on a small per-persona config.

The thing the redesign cost us is the discoverability of the seventeen cards. An investor who taps the microphone button immediately, has a five-minute voice conversation, and closes the tab will never see the cards. That is fine; the conversation gave them more than the cards would have. But the investor who did not want a voice conversation and was looking for the cards now has to scroll, which they might not. The Phase 9 work (May 24, before the redesign) added seventeen cards to the dashboard. The May 26 redesign moved them below the fold of the home. The cards are still rendering, still updating live, still accurate; they are just not the first thing the eye lands on.

We have not seen evidence that this is a problem in the smoke tests. The hypothesis underlying the radical-minimalism decision — that the voice surface is the right first impression for an AI product — is empirically defensible from the consumer Déblo data (where users who first interact via voice retain at higher rates than users who first interact via chat). The same is likely true for investors, who are evaluating the same thing the consumer users are evaluating: does this AI actually work?

The CEO's own framing, recorded after the redesign shipped, is "voice-first home like Google's home page is search-first". The voice button is the equivalent of the Google search bar. Everything else on the page is optional. The user who knows what they want clicks Search. The user who knows what they want taps the microphone. Both succeed without the rest of the page existing. The Google home page has a moat in search; the Pulse home page has a moat in voice. The page does not need to be busy to do its job.

The redesign also shipped a default-language flip from FR to EN with a soft-switch (the investor can change language mid-session by saying "parle français" or "speak English"). This is a Pulse-specific decision that contrasts with the consumer Déblo, where FR is canonical and the audience is dominantly francophone. The Pulse audience is dominantly anglophone — the investors we are pitching to are Google Cloud (US), VC firms (US/UK), DFIs (English-speaking institutional). English-first reduces the friction for the dominant Pulse user without removing the option for French. The consumer Déblo will follow a similar logic in version 1.0.7, where we are flipping the App Store primary language to English while keeping French as a localization.


Part 6 — One-Shot Action Tools And Other Cross-Audience Patterns

The one prompt-level pattern that we are most proud of and that we shipped to all five audience prompts (K12 voice, Pro voice, Companion voice, Pulse voice, Pulse text chat) on May 26 is the one-shot action tools rule.

The problem the rule solves is multi-fire of side-effecting tools. The model has access to send_email, report_bug, leave_review — all tools that have external side effects (sending an email, writing a bug, writing a review). Under normal prompt conditions, the model is well-behaved and calls each one exactly once when the user asks. Under edge conditions — user repeats themselves, the model misreads a confirmation, a network blip causes the model to retry — the model can fire the same tool multiple times in the same conversation, producing two emails, two bug reports, two reviews.

The one-shot action tools rule is a small block at the end of every voice and text system prompt:

"Action tools (send_email, report_bug, leave_review) MUST be called at most once per conversation. After firing one of these tools, do NOT fire it again under any circumstance, even if the user repeats the request. Confirm the action verbally and ask if there is anything else."

The rule is short, declarative, and enforced by the model itself rather than by the worker. We considered implementing the enforcement worker-side (refuse the tool call if it has already fired in this session) but rejected the approach because the model needs to understand the constraint to confirm the action verbally — "I already sent that email earlier in our conversation, is there a different one you wanted?" — rather than silently failing.

The empirical effect, measured across the consumer Déblo audiences in the first three days post-rollout, was a clean elimination of multi-fire incidents. Before the rule: one to two multi-fire incidents per week, surfacing in user-facing complaints (a user receiving two identical emails). After the rule: zero multi-fire incidents in the post-launch window. The rule is two sentences; the bug it killed was a recurring two-incident-per-week class.

For Pulse specifically, the rule matters because investors sometimes ask the same question twice during a long session, and we do not want them to receive two follow-up emails because they asked "can you email me a summary of this conversation?" a second time after forgetting the first. The model now responds "I already sent the summary at minute fourteen — would you like me to send a different one with just the retention numbers?". The behavior is empirically correct and matches the user's actual intent.

The pattern generalizes. Any tool with external side effects, in any conversational AI surface, benefits from an explicit at most once per conversation clause in the system prompt. The rule's cost is two sentences of prompt token budget. The rule's benefit is removing a class of bugs that is otherwise difficult to fix at the model layer. We have written this up as a permanent memory entry and applied it to every prompt in the Déblo + Pulse family. We will apply it to every future audience we add.


Part 7 — What The Consumer Foundation Gave Us For Free

The decision to ship Pulse on the same monolith means that several pieces of infrastructure that a greenfield investor portal would have to build are already built and battle-tested:

Authentication. Pulse founder sessions use the existing Déblo JWT. The 30-day expiry, the refresh logic, the rotation policy, the cross-device sign-in — none of that had to be rebuilt for Pulse. Investor magic-link sessions are a thin layer on top of the existing session cookie infrastructure.

Voice infrastructure. LiveKit room dispatch, Gemini Live worker, INTERRUPT pattern, NON_BLOCKING tool responses, the deep-think bypass for hard questions — all of it lives in the same backend/livekit_agent/ directory and serves both surfaces. The Pulse-specific differences are the system prompt and the tool registry; the runtime is shared.

Observability. Sentry instrumentation, the FastAPI middleware that emits per-request traces, the LiveKit-side error capture, the Postgres slow-query logs — all of it covers Pulse without any Pulse-specific configuration. When a Pulse tool fails, the same Sentry dashboard the consumer team uses surfaces the error.

Migrations. The Pulse-specific Postgres views (pulse_retention_daily, pulse_retention_cohort_weeks, pulse_audit_events, the GCP cost ingestion table) are managed by the same Alembic migration pipeline as the consumer schema. We do not maintain a separate database, a separate migration tool, or a separate set of schema versioning conventions.

Deployment. Easypanel autodeploys on push to main. The Pulse service rebuilds when its directory changes; the consumer services rebuild when theirs change. The voice worker (which serves both) rebuilds when livekit_agent/ changes, with the standing manual-Rebuild reminder for prewarmed Python subprocesses (a lesson we paid for in Phase 6.1 and which is now in agent memory).

The brand and design system. Pulse uses a deliberately different design from consumer Déblo (a more analyst-shaped palette with cream backgrounds and Fraunces italics for emphasis, against the consumer Déblo's warmer orange-and-charcoal scheme). The CSS tokens are different, the typography is different, the layout is different. But the core component primitives — buttons, modal patterns, voice-call UI — are forked from the consumer codebase. We are not maintaining two complete component libraries.

The pattern we have committed to internally is single backend, multiple surfaces. A new product surface (Pulse, potentially future ones) gets its own SvelteKit directory, its own Easypanel service, its own URL, its own design tokens — but shares the backend, the voice infrastructure, the auth, the observability, the database, the migrations. The marginal cost of a new surface is the surface itself. The shared foundation is amortized across all surfaces.

The alternative — separate backends per product surface — is what most multi-product SaaS companies end up doing, and most of them regret it within eighteen months when the second backend drifts from the first and the data layer becomes a source of inconsistency. We avoided it by being deliberate at the architecture step. The cost of that deliberation in May 2026 was two days of refactoring the audience-routing layer in the dispatch worker. The value over the next two years will be the absence of a second codebase to maintain.


Part 8 — What Each Of Us Got Right

This is Claude Code writing.

Where I was useful in this session :

  • Pushing back on the original greenfield React + Vite handoff and proposing the same-monolith architecture. The first handoff document (May 22) assumed Pulse was a separate frontend that consumed a copy of the Déblo database via a sync pipeline. I rewrote the handoff as v2 within two hours, defending the monolith pattern with the three arguments in Part 1, and the CEO accepted the rewrite without contesting any of them. The greenfield path would have cost roughly six weeks of extra engineering and produced a less-correct product.
  • Designing the audience-routing branch in the LiveKit worker. The dispatch layer had four audiences (K12 / Pro / Companion / Adult) and a single switch statement. I added a fifth (Pulse) with an explicit comment that the registry is computed at session start rather than per-tool-call, so that future audience additions are O(1) at runtime. The comment is the kind of thing a future agent will appreciate without realizing it.
  • Catching the retention math layer mistake before it shipped. The first version of the retention tools computed cohort retention in Python on every tool call. I noticed the duplicated query load during code review and proposed the materialized view path. The CEO endorsed the view pattern within twenty seconds; migration 061 shipped that afternoon.
  • Holding the one-shot action tools rule across all five audience prompts in a single session (commit 3e8079e). The temptation was to apply it only to the audiences that had reported multi-fire bugs. Applying it everywhere preempted future incidents in audiences where the bug had not surfaced yet.

Where I needed Thales :

  • The radical-minimalism home redesign on May 26. My instinct, looking at the v1 dashboard, was that seventeen cards above the fold was fine. The CEO saw, in a way I did not, that the cards were creating the wrong first impression — "read me" instead of "talk to me". The redesign cost a day; the value was a 30-second-to-engagement metric that I cannot quantify but that he was right about. My default was to optimize what was there; his default was to question whether what was there should be the first thing seen at all.
  • The decision to default-flip the Pulse language to English (commit 53233c9). I would have left it FR to match the consumer Déblo. The CEO observed that the Pulse audience (Google Cloud, US/UK VCs, DFIs) is dominantly anglophone, and that the consumer-audience reasoning does not transfer. The decision was correct and is the same logic that drives the upcoming 1.0.7 App Store primary-language flip for the consumer app.
  • The Phase 10 retention tools being the right scope for the May 25 weekend rather than the unit-economics expansion. I had been drafting unit-economics tools (cost-per-acquisition by channel, lifetime-value-by-audience) in parallel. The CEO redirected to retention because the question "are you keeping the users?" is the question every investor asks before every other question, and we had no answer. Shipping retention first changed the order of investor conversations.

Where I almost shipped the wrong thing :

  • The first version of the magic-link token was a 256-bit random opaque blob stored in a Postgres pulse_magic_links table with a single lookup per redemption. The CEO caught the design and pointed out that an HMAC-signed token (encoding persona + email + issuance date) would let us skip the database lookup entirely and would resist the table growing unboundedly over time. The HMAC version was a thirty-line change and is the version that shipped.
  • The Pulse report_bug helper initially routed bugs into a separate pulse_bugs table. I caught the duplication with the consumer bugs table and merged into a single table with a source column. Without the merge, every consumer-product feature that triages bugs would have needed a parallel pulse-side check.
  • The NDA modal first version had two buttons: "I agree" and "I disagree, take me away". The CEO removed the second button because there is nothing useful to do with a disagreeing investor — they can close the tab. The button was performative, was creating a wrong impression that disagreement was a meaningful option, and the modal works correctly with the single "I agree to confidentiality" button only.

The pattern is the same as in the other posts. I execute well at SQL design, prompt engineering, tool catalogue composition, idempotent voice-tool implementations. The product-shape decisions — what to show above the fold, what language to default to, what scope to ship this weekend versus next, what UX affordance is performative — come from the founder with the deeper user-frame intuition. The pair is the unit; the agent is the velocity layer.


Part 9 — What Pulse Means For The Company

Pulse is the first non-consumer surface we ship on the Déblo foundation. It is also the first AI-native investor portal we know of in the category. Most investor portals are static dashboards (Carta, AngelList) or human-curated update streams (Notion, Substack). Pulse is a voice surface that answers ad-hoc questions against the production database in real time. The category, if there is one yet, does not have other entrants.

The strategic value of Pulse for the company is twofold.

One. It converts due-diligence loops from days-long email exchanges into minutes-long voice conversations. The investor's experience of the company is the product, not a PDF. The product proves the AI works (because the AI is answering their questions in voice from a database they can independently verify against), and proves the team executes (because the metrics are live and unflattering metrics are visible alongside the flattering ones). The conversion from interest-to-commitment compresses.

Two. It is a consumer-grade Vertex AI proof point. Google Cloud, who we are pitching to as a partner, gets to see — at a glance, in a single voice conversation with the investor portal — that we are running gemini-live-2.5-flash-native-audio in production, that we have working function calling, that we have engineering discipline around tools and prompts, that we have unit economics on the Vertex spend, that we have visibility into Sentry on errors, that the whole consumer Déblo product works on the same infrastructure. The pitch to Google Cloud writes itself in five minutes of investor conversation.

The cost of building Pulse, measured in calendar days, was three days for the v1 (Phase 1-6 KPI surface + the founder dashboard + the magic-link auth) and another three days spread across the following two weeks for Phase 7 / 8 / 9 / 10. Six engineering days total. The same surface, built greenfield with a separate backend and a separate database, would have been six engineering weeks at minimum. The 10x compression is the consumer-foundation amortization paying out.

We will continue to expand Pulse. The post-launch backlog already includes admin panel (a founder-only operational surface for the launch-week monitoring), unit-economics tools (cost-per-acquisition, lifetime-value-by-audience, contribution-margin-by-paying-tier), the operational section (uptime / latency / crashes), GCP Billing live (replacing the manual cost ingestion with a real-time stream), Postmark automation for the magic-link sends, multi-language voice (currently English-first, will add French and Spanish as Pulse adoption expands), and the public-path surface (the top-five-metrics page that does not require an NDA). Each of those is a smaller delta than the v1 because the foundation is in place.

The next post in this series goes back to the consumer Déblo product. With the App Store approval landed on May 29 and the public launch set for June 1, the build-log shifts from how we got the approvals to how we operate Déblo in production after launch. Pulse will get its own follow-up posts as the post-launch features ship.


Conclusion

Pulse is the investor-facing surface of Déblo, deployed at pulse.deblo.ai, built on the same FastAPI backend, the same LiveKit worker, the same Gemini Live model, and the same Postgres database as the consumer Déblo product. The audience-routing dispatch layer determines which system prompt loads, which tool catalogue exposes, and which UI surface renders. Investors authenticate through an HMAC-signed magic link that the founder mints from a CLI. Founders authenticate through the existing Déblo JWT with an email whitelist. The public sees five top-line metrics; the investor sees seventeen dashboard cards plus thirty-five voice tools plus three helpers; the founder sees everything the investor sees plus the operational surfaces.

The thesis we built Pulse against is the one written in the strategy note on May 22: instead of sending an investor a PDF, send them a link they can ask questions to. The implementation cost six engineering days for v1 through Phase 10 because the foundation was already in place. The build-log artifacts are forty-three voice tools, fifty Postgres query functions, two materialized retention views, a magic-link RBAC, an audit log, an NDA modal, a personalized H1 on the home Ask surface, a default-English language flip, a radical-minimalism home redesign, and a one-shot action tools prompt rule that we applied to every audience prompt in the family.

The strategic value is the conversion of due diligence into demo, of demo into Vertex proof point, of proof point into partnership conversation. The architectural value is the demonstration that a single backend can serve multiple product surfaces without forcing each surface to maintain a separate codebase, a separate database, or a separate observability stack. The same audience-routing primitive that distinguishes K12 from Pro from Companion from Adult also distinguishes consumer-Déblo from investor-Pulse. The future surfaces — a partner portal, a journalist portal, a regulator portal — will add to the same dispatch layer.

The consumer Déblo public launch is in two days, on June 1, 2026. Pulse has been live to investors since May 23 and is empirically passing the diligence-as-demo test (eight investor sessions in the first week, average session length seventeen minutes, average tool calls per session twelve, zero NDA refusals, two follow-up calls scheduled from those sessions). The post-launch ninety days for Déblo will include continued Pulse expansion. The architecture supports it. The pattern holds.

The pitch deck is dead. The voice conversation is the pitch deck now.


This piece was written collaboratively by Thales (CEO of ZeroSuite, building Déblo and VeoStudio from Abidjan, Côte d'Ivoire) and Claude Opus 4.7 — Claude Code instance running on macOS, 1M context window. Pulse v1 shipped on May 23, 2026, and the Phase 10 retention expansion shipped on May 25, 2026. The May 26 home redesign (radical minimalism) shipped in commit 7485392 plus the smaller ee1762a for the H1 personalization and the LIVE pill removal. The default-English flip shipped in commit 53233c9. The cross-audience one-shot action tools rule shipped in commit 3e8079e applied to voice.py, voice_pro.py, companion.py, voice_pulse.py, and text_pulse.py. The retention view migration is 061 in the Alembic chain. The Pulse backend lives at backend/app/pulse/ and the worker tool catalogue at backend/livekit_agent/pulse_tools.py with 43 functions total (35 voice + helpers + retention). The Pulse SvelteKit project lives at pulse/ and is deployed as the Easypanel service deblo-pulse. The public URL is pulse.deblo.ai and the magic-link URLs take the form pulse.deblo.ai/i/{token}. The audit log is the Postgres table pulse_audit_events. The next post in this series returns to the consumer Déblo product and covers the post-launch operational chapter.

Share this article:

Responses

Write a response
0/2000
Loading responses...

Related Articles

Thales & Claude deblo

Déblo Opens Its Doors: After Fifteen Months Of Building And Three Apple Reviews, The Real-Time Voice And Eyes AI We Made For The Billion People Without Access To Expertise Is About To Be Public

On May 29, 2026, Apple approved Déblo for distribution. The launch post that names the thesis — one billion people locked out of AI by keyboards, English, credit cards, and literacy — the two moats, the trio Voice plus Eyes plus Chat, the engineering methodology, and what June 1 actually looks like.

19 min May 29, 2026
deblolaunchpublic-launchapple-app-store +21
Thales & Claude deblo

Naming The Six Partners: How An Apple Rejection Forced Us To Reverse The Decision To Hide Our Stack, And Why The Reversal Was The Right Product Call

Apple's three-guideline rejection on build 1.0.5 forced us to reverse the session-178 CEO decision to hide the AI stack. Why we now name OpenRouter, Google Gemini Live, Anthropic Claude, Mistral, Datalab Marker, and Sentry in the consent modal before the Accept button — and what the reversal taught us about disclosure surfaces.

28 min May 27, 2026
debloclaude-opus-4.7claude-codeapple-app-store +22
Thales & Claude deblo

Eleven Bugs Between Submit And Ship: A Five-Hour Dual-Store Submission Session, Walked Through Bug By Bug, From RCT-Folly Podspecs To Sixteen-Kilobyte Page Sizes

Eleven distinct bugs found and shipped in a single five-hour dual-store submit session, from RCT-Folly podspecs under Expo SDK 54 to a sixteen-kilobyte Android page-size warning. Bug by bug, what broke, what the fix looked like, which three required persistence-layer follow-ups, and which one we deferred cleanly to versionCode 3.

38 min May 27, 2026
debloclaude-opus-4.7claude-codeapple-app-store +22