<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ayoola Solomon</title>
    <description>The latest articles on DEV Community by Ayoola Solomon (@ayoolasolomon).</description>
    <link>https://dev.to/ayoolasolomon</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F58080%2Fcb137a0e-7d34-4dcd-8b38-2822fb2d4143.jpeg</url>
      <title>DEV Community: Ayoola Solomon</title>
      <link>https://dev.to/ayoolasolomon</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ayoolasolomon"/>
    <language>en</language>
    <item>
      <title>Your resume can be faked in an afternoon. Your work can't.</title>
      <dc:creator>Ayoola Solomon</dc:creator>
      <pubDate>Fri, 25 Sep 2026 10:19:45 +0000</pubDate>
      <link>https://dev.to/ayoolasolomon/your-resume-can-be-faked-in-an-afternoon-your-work-cant-3nbl</link>
      <guid>https://dev.to/ayoolasolomon/your-resume-can-be-faked-in-an-afternoon-your-work-cant-3nbl</guid>
      <description>&lt;p&gt;Anyone can now ask an AI to write a polished, backdated account of their career in an afternoon. A glowing summary of projects you led, skills you mastered, impact you drove: generated in minutes, nearly indistinguishable from the real thing, and almost impossible to verify after the fact.&lt;/p&gt;

&lt;p&gt;That should worry anyone who relies on resumes, LinkedIn profiles, or portfolios to signal what they've actually done. Every one of them is a self-reported claim. They always have been. We just used to treat the effort of writing them as a weak proxy for truth. AI removed that proxy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Polishing the claim doesn't fix the problem
&lt;/h2&gt;

&lt;p&gt;Most advice for standing out right now is about being more visible: post more, network more, build a personal brand. That isn't bad advice. It just solves discoverability, not credibility. It makes claims louder, not truer.&lt;/p&gt;

&lt;p&gt;In a world where anyone can generate a convincing story about their past, louder claims just mean better-produced fiction competes with honest work on equal footing.&lt;/p&gt;

&lt;h2&gt;
  
  
  What if your work wrote itself down as it happened?
&lt;/h2&gt;

&lt;p&gt;I've been designing, and am now building (for myself first) a different answer: a work journal that doesn't rely on you remembering to write anything down, and can't be quietly rewritten later.&lt;/p&gt;

&lt;p&gt;The core idea is simple. Instead of a document you write once and polish forever, it's a log that captures itself passively from things you're already doing: commits, calendar events, the real trail of a working life. Periodically, weekly or monthly, you review what it captured, approve it, and it becomes part of a permanent, dated record.&lt;/p&gt;

&lt;p&gt;The part that matters most: once an entry is approved, it's immutable. Not "hard to edit." Actually append-only, enforced at the core of how the tool works, with optional cryptographic timestamping so the record's integrity can be verified by anyone, even years later, even if I disappear as the person maintaining it. That's what turns it from another journal into something closer to proof of existence at a point in time.&lt;/p&gt;

&lt;h2&gt;
  
  
  The shape of it
&lt;/h2&gt;

&lt;p&gt;A few design decisions I think matter:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Local-first.&lt;/strong&gt; Your data lives on your machine by default. Nothing is required to leave it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Passive, not another app to open.&lt;/strong&gt; It runs quietly in the background and nudges you, rather than waiting for you to remember it exists.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open source.&lt;/strong&gt; The whole point is trust, so there's nothing about how it works that isn't inspectable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Immutable by design.&lt;/strong&gt; Entries can be corrected by appending, never edited or deleted.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optional, not mandatory sharing.&lt;/strong&gt; The log is yours. What you choose to show a future employer, or no one at all, is up to you.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Where this stands
&lt;/h2&gt;

&lt;p&gt;I'm building a personal version first, pulling from my own GitHub and calendar into a monthly rollup, and I'm going to actually live with it for six months before deciding whether it's worth being more than that. No grand claims yet. I just think the underlying problem is real and getting worse, and I'd rather find out if this is a genuine answer to it than assume it is.&lt;/p&gt;

&lt;p&gt;If this resonates, or if you think it's solving the wrong problem, I'd like to hear it.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>career</category>
      <category>productivity</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Resumes are becoming obsolete. Here's what I think replaces them</title>
      <dc:creator>Ayoola Solomon</dc:creator>
      <pubDate>Fri, 18 Sep 2026 09:49:14 +0000</pubDate>
      <link>https://dev.to/ayoolasolomon/resumes-are-becoming-obsolete-heres-what-i-think-replaces-them-3njd</link>
      <guid>https://dev.to/ayoolasolomon/resumes-are-becoming-obsolete-heres-what-i-think-replaces-them-3njd</guid>
      <description>&lt;p&gt;I've been in tech for over 10 years, across five companies: fintech, SaaS, and my own startups. Every time I update my resume, promo case, or LinkedIn, I hit the same wall: I genuinely can't remember what I did.&lt;/p&gt;

&lt;p&gt;Not because it wasn't meaningful. Because nobody wrote it down as it happened. Ask me what I shipped in Q2 last year and I've got nothing, until I sit with it and slowly reconstruct. That's career amnesia, not a personal failing.&lt;/p&gt;

&lt;p&gt;And even when I do remember, the resume format kills the part that mattered. "Managed cross-functional team to deploy new architecture" tells you nothing about the problem, the constraints, what broke, or what I learned fixing it. A resume doesn't just compress your career. It strips the context, and the context was the point.&lt;/p&gt;

&lt;p&gt;Now add AI: a polished, keyword-optimized resume takes 30 seconds, whether you did the work or not. The format that already threw away the substance is now trivially fakeable too.&lt;/p&gt;

&lt;p&gt;So what's left? Not what you say you did, but a dated, ongoing record of what you actually did, with the context intact.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's already out there
&lt;/h2&gt;

&lt;p&gt;A few tools circle this problem. Each solves a slice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dayflow&lt;/strong&gt;: open-source, local on your Mac, turns screen activity into a daily timeline and standup summary. Great for "what did I do today?" Days and weeks, not a career.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;bragdoc.ai&lt;/strong&gt; and similar: pull GitHub commits and PRs into an AI brag doc for review season. Developer-only, and built for one moment a year.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ActivityWatch&lt;/strong&gt;: long-running open-source activity tracker. Strong on raw data, no narrative.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trajecta&lt;/strong&gt;: closest in spirit, a permanent record of professional impact. Still manual entry. You're the one writing it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each nails a piece: local-first privacy, developer activity, raw tracking, long-term framing. None puts it together: passive where possible, guided where it can't be, non-technical roles included, built for years instead of days.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'm building
&lt;/h2&gt;

&lt;p&gt;That's the gap I'm building into with &lt;strong&gt;EchoWork&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Where it can, it pulls from where the work already lives: commits, tickets, calendar. Where it can't (enterprise, IP-locked environments), it doesn't scrape or spy. It notices you had a three-hour block on "system migration" Friday and asks what you decided and shipped. Either way, it becomes a real monthly rollup: not a bullet point, but the actual story, dated and preserved.&lt;/p&gt;

&lt;p&gt;It runs local-first, with your choice of LLM, so none of it has to leave your machine.&lt;/p&gt;

&lt;p&gt;It's not built to replace LinkedIn or hand your data to recruiters. It's for you first, so when review season, a promo case, or a job search comes around, you're not starting from zero. Sharing a slice with an application is optional, not the point.&lt;/p&gt;

&lt;p&gt;I'm building the first version for myself right now, testing whether I'd actually use it daily before deciding what it becomes. I think the resume's days are numbered. What replaces it is proof, with the context still attached.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>career</category>
      <category>productivity</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Material vs locked: the rule that lets 2048 and Sudoku share a board</title>
      <dc:creator>Ayoola Solomon</dc:creator>
      <pubDate>Sun, 13 Sep 2026 13:31:16 +0000</pubDate>
      <link>https://dev.to/ayoolasolomon/material-vs-locked-the-rule-that-lets-2048-and-sudoku-share-a-board-172d</link>
      <guid>https://dev.to/ayoolasolomon/material-vs-locked-the-rule-that-lets-2048-and-sudoku-share-a-board-172d</guid>
      <description>&lt;p&gt;I've always loved Sudoku and 2048. They're the puzzles I open instead of scrolling. For a long time I wanted a mashup that felt like both, not a gimmick with two logos stuck on one grid.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ayoolasolomon.com/play/number-merge-sudoku" rel="noopener noreferrer"&gt;Play Number Merge Sudoku&lt;/a&gt; (Daily or Endless). What follows is the design decision that made it playable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why mashups usually fail
&lt;/h2&gt;

&lt;p&gt;Sudoku says: every digit appears once per row, column, and box.&lt;/p&gt;

&lt;p&gt;2048 says: equal neighbors merge into the next value, and duplicates are the whole point of the economy.&lt;/p&gt;

&lt;p&gt;If every tile on the board counts as a Sudoku digit the moment it appears, merges die. You can't keep two 2s in the same row long enough to make a 4. If you ignore uniqueness until the end, you don't have Sudoku; you have a merge game with a checkbox at the finish line.&lt;/p&gt;

&lt;p&gt;The interesting problem isn't "can I render a grid in React." It's: &lt;strong&gt;when does a number start counting?&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The contract: material vs locked
&lt;/h2&gt;

&lt;p&gt;Every occupied cell holds a tile in one of two states:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Material&lt;/strong&gt;: may share its value with other material tiles in the same row, column, or box. Material tiles can merge. They do &lt;strong&gt;not&lt;/strong&gt; count toward Sudoku uniqueness.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Locked&lt;/strong&gt;: counts as a Sudoku digit. Locked tiles cannot merge. A value may appear at most once as locked in each row, column, and box.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You only ever spawn &lt;strong&gt;1&lt;/strong&gt;s, and they always spawn as material. Merge two equal material neighbors and you get the next value, still material, on the survivor cell. No auto-chains. No Sudoku check on merge.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Seal&lt;/strong&gt; is the verb that turns material into locked, in place. Seal is illegal if that value is already locked in the same row, column, or box. Until you seal, the board is allowed to look "illegal" by Sudoku standards. That's intentional. Duplicates are fuel.&lt;/p&gt;

&lt;p&gt;Win condition: every cell is occupied by a &lt;strong&gt;locked&lt;/strong&gt; tile, and every row, column, and box contains each digit of the board's alphabet exactly once. Easy is 4×4 (digits 1–4). Medium and Hard are 6×6 (digits 1–6).&lt;/p&gt;

&lt;p&gt;One sentence version: &lt;strong&gt;Sudoku uniqueness applies only to locked digits.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That single sentence is the whole product.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three moves, three jobs
&lt;/h2&gt;

&lt;p&gt;The run is empty at the start. No seeded givens. You build the puzzle by playing it.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Spawn&lt;/strong&gt;: put a material 1 on any empty cell. Always legal. No uniqueness check.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Merge&lt;/strong&gt;: two orthogonally adjacent material tiles of equal value become one material tile of the next value on the survivor; the other cell clears. Max digit is terminal (4 on Easy, 6 on Medium/Hard). Locked tiles never merge.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Seal&lt;/strong&gt;: convert one material tile to locked, if uniqueness still holds for locked digits.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;UI-wise it's two-tap merge and tap-empty to spawn. The mental model is what matters: merge builds value; seal commits it to the Sudoku layer.&lt;/p&gt;

&lt;p&gt;Color follows the same contract. Each digit has a fixed hue. Material uses a softer treatment; locked uses a denser one. Color never encodes "legal move" or hints. Digits stay readable. Hue is state, not advice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Soft-locks aren't bugs
&lt;/h2&gt;

&lt;p&gt;You can fill yourself into a corner where no spawn, merge, or seal remains, even with empty cells left. That's a &lt;strong&gt;Loss&lt;/strong&gt;: a soft-lock.&lt;/p&gt;

&lt;p&gt;I almost treated that as a failure of the ruleset. It isn't. It's the tax of a merge economy living under a uniqueness ceiling. If soft-locks couldn't happen, the puzzle would be too forgiving to feel like either parent game.&lt;/p&gt;

&lt;p&gt;So Difficulty isn't "how many givens." There are no givens. Difficulty chooses board size, alphabet, &lt;strong&gt;undo budget&lt;/strong&gt;, and &lt;strong&gt;hint budget&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Difficulty&lt;/th&gt;
&lt;th&gt;Board&lt;/th&gt;
&lt;th&gt;Digits&lt;/th&gt;
&lt;th&gt;Undos&lt;/th&gt;
&lt;th&gt;Hints&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Easy&lt;/td&gt;
&lt;td&gt;4×4&lt;/td&gt;
&lt;td&gt;1–4&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;6×6&lt;/td&gt;
&lt;td&gt;1–6&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hard&lt;/td&gt;
&lt;td&gt;6×6&lt;/td&gt;
&lt;td&gt;1–6&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Undo reverts the last successful spawn, merge, or seal. It stays available through a soft-lock so you can dig out. After a &lt;strong&gt;Win&lt;/strong&gt;, the run auto-finalizes; undo and hint close.&lt;/p&gt;

&lt;p&gt;Hint is a legality nudge, not a solver. It reveals one currently legal move and leaves you to play it. Prefer merges that don't crowd the survivor's house with the result digit, then spawns that set up merges, then seals of unique material values. It does &lt;strong&gt;not&lt;/strong&gt; claim a path to win. Spending a hint locks Difficulty for the run the same way the first real move does.&lt;/p&gt;

&lt;h2&gt;
  
  
  Daily as the habit loop
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Daily&lt;/strong&gt;: one run per UTC day. Leave mid-board and it resumes. Pick Difficulty until the first successful spawn, merge, seal, or hint; then it's fixed for that day. Elapsed time starts on the first real move (not on staring at an empty board, not on hint alone), pauses when the tab is hidden, and freezes on win.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Endless&lt;/strong&gt;: same rules, as many runs as you want. No Daily share.&lt;/p&gt;

&lt;p&gt;On Daily win, you get a board snapshot (digit hues intact) plus a caption: game name, UTC date, difficulty, win, undos used, hints used, elapsed time, and a clean link back to the play page. Share is opt-in after finalize. Losses aren't share artifacts. Soft-locks are for learning, not for the timeline.&lt;/p&gt;

&lt;p&gt;I built the thing I'd open with coffee. The Daily is how that intention shows up in the product.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I deliberately didn't do
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No seeded puzzle of the day.&lt;/strong&gt; The day is a label and a lock, not an RNG board. You and I start from the same empty grid; the run diverges with play.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No solver-as-hint.&lt;/strong&gt; Hint answers "what is legal right now," not "what would a SAT solver do."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No React tutorial.&lt;/strong&gt; The shell is Remix, TypeScript, and a small domain core with tests. The novel work was the state machine for material vs locked, not the component tree.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No "place any digit" mode.&lt;/strong&gt; If you can drop a 6 wherever you like, you're back to Sudoku with extra steps. The merge ladder is the constraint that makes the board feel like 2048.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;If you have a few minutes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open &lt;a href="https://ayoolasolomon.com/play/number-merge-sudoku" rel="noopener noreferrer"&gt;Number Merge Sudoku&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Start on Easy if you want the rule to click fast; Medium if you want the real Daily shape.&lt;/li&gt;
&lt;li&gt;Spawn 1s, merge equals, seal only when uniqueness allows.&lt;/li&gt;
&lt;li&gt;Soft-lock once on purpose. Undo. Notice what you learned.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When you win a Daily, share the board if you want. I'd rather see your soft-lock stories in the comments than a stack screenshot.&lt;/p&gt;

&lt;p&gt;The mashup only works because uniqueness waits. Everything else is choreography around that one contract.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Play:&lt;/strong&gt; &lt;a href="https://ayoolasolomon.com/play/number-merge-sudoku" rel="noopener noreferrer"&gt;ayoolasolomon.com/play/number-merge-sudoku&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Project notes:&lt;/strong&gt; &lt;a href="https://ayoolasolomon.com/projects/number-merge-sudoku" rel="noopener noreferrer"&gt;ayoolasolomon.com/projects/number-merge-sudoku&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If this was useful, the follow-ups worth writing are soft-locks as a feature, and a hint engine that reveals without playing. Tell me which one you want next.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>typescript</category>
      <category>gamedev</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Try our evaluation playground — no API key, no signup</title>
      <dc:creator>Ayoola Solomon</dc:creator>
      <pubDate>Fri, 05 Jun 2026 19:06:57 +0000</pubDate>
      <link>https://dev.to/ayoolasolomon/try-our-evaluation-playground-no-api-key-no-signup-2dk8</link>
      <guid>https://dev.to/ayoolasolomon/try-our-evaluation-playground-no-api-key-no-signup-2dk8</guid>
      <description>&lt;p&gt;We shipped a public playground for &lt;a href="https://getechostack.com" rel="noopener noreferrer"&gt;echostack&lt;/a&gt; — paste business signal text, get a structured decision back.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try it:&lt;/strong&gt; &lt;a href="https://getechostack.com/playground" rel="noopener noreferrer"&gt;https://getechostack.com/playground&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;No account required.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does
&lt;/h2&gt;

&lt;p&gt;Most tools give you a score. This returns an operational decision:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Status&lt;/strong&gt; — e.g. &lt;code&gt;QUALIFIED&lt;/code&gt;, &lt;code&gt;PARTIAL&lt;/code&gt;, &lt;code&gt;ESCALATE.&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extracted fields&lt;/strong&gt; — budget, authority, severity, timeline, etc.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recommended next action&lt;/strong&gt; — e.g. &lt;code&gt;BOOK_MEETING&lt;/code&gt;, &lt;code&gt;ESCALATE_NOW&lt;/code&gt;, &lt;code&gt;GATHER_INFO&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Scenarios built in
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Sales call&lt;/strong&gt; — inbound qualification (BANT-style)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Web form&lt;/strong&gt; — demo request / inbound lead&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Support ticket&lt;/strong&gt; — P0 outage triage&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trial usage&lt;/strong&gt; — PLG expansion signals&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each scenario loads sample text you can edit, or paste your own (up to 1,000 chars).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr0fhuyb4fsoikjaq2g14.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr0fhuyb4fsoikjaq2g14.png" alt=" " width="800" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why we built it
&lt;/h2&gt;

&lt;p&gt;We kept hearing: "I don't want another lead score — I want to know what to &lt;em&gt;do&lt;/em&gt; with this inbound signal."&lt;/p&gt;

&lt;p&gt;The playground runs the same evaluation path as our production API. Sign up only if you want API keys and to wire it into your stack.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd love feedback on
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Is the output format actually useful for your workflow?&lt;/li&gt;
&lt;li&gt;What scenario should we add next? (support triage, fraud, compliance, etc.)&lt;/li&gt;
&lt;li&gt;Would you use this via API, webhook, or no-code?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Drop a comment — especially if something breaks or the result feels wrong for your input.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>api</category>
      <category>saas</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Stop writing prompts to classify text: make evaluation declarative</title>
      <dc:creator>Ayoola Solomon</dc:creator>
      <pubDate>Tue, 02 Jun 2026 20:02:27 +0000</pubDate>
      <link>https://dev.to/ayoolasolomon/stop-writing-prompts-to-classify-text-make-evaluation-declarative-5555</link>
      <guid>https://dev.to/ayoolasolomon/stop-writing-prompts-to-classify-text-make-evaluation-declarative-5555</guid>
      <description>&lt;p&gt;I've built the same thing more than once: a step that reads an inbound&lt;br&gt;
message — a lead form, a support ticket, a DM — and decides what to do with&lt;br&gt;
it. Qualify it, escalate it, route it, drop it.&lt;/p&gt;

&lt;p&gt;Every time, the implementation had the same shape: hand-write a prompt that&lt;br&gt;
asks an LLM to return JSON, parse the JSON, branch on it. And every time it&lt;br&gt;
rotted the same way:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The prompt was untestable. "Looks right" was the only QA.&lt;/li&gt;
&lt;li&gt;It drifted. A model upgrade or a one-word prompt tweak silently changed the
output and nobody noticed until something got misrouted.&lt;/li&gt;
&lt;li&gt;The JSON lied. The model would confidently return a category that wasn't in
my allowed set, or a number outside the range I expected, and my downstream
&lt;code&gt;switch&lt;/code&gt; would happily act on garbage.&lt;/li&gt;
&lt;li&gt;"Confidence" was theater. &lt;code&gt;if confidence &amp;gt; 0.7&lt;/code&gt; is a magic number that means
nothing across different inputs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Eventually I stopped writing prompts. This is what I built instead and what I&lt;br&gt;
learned.&lt;/p&gt;

&lt;h2&gt;
  
  
  The core idea: declare what to detect, not how to ask
&lt;/h2&gt;

&lt;p&gt;Instead of a prompt, you declare typed &lt;strong&gt;detectors&lt;/strong&gt;. Two kinds:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;presence&lt;/strong&gt; — "is this signal in the text?" → returns &lt;code&gt;found&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;classification&lt;/strong&gt; — "put this into exactly one of a fixed set of
categories" → returns the category, enum-validated
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Partnership routing"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"template"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"custom"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"custom_detectors"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"competitor_mentioned"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"presence"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"examples"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"we're currently using Acme"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"switching off a competitor"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"non_examples"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"love your product"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"partnership_inquiry"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"classification"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"categories"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"reseller"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"affiliate"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"strategic"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"none"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"examples"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"interested in your reseller program"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"want to co-sell with you"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"just a support question"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You never see the prompt — it's compiled from the declaration. That part isn't&lt;br&gt;
the interesting bit; anyone can template a prompt. The interesting bit is&lt;br&gt;
everything that becomes possible &lt;em&gt;because&lt;/em&gt; a detector is a typed object instead&lt;br&gt;
of a string.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Detectors are tested at create-time, not in prod
&lt;/h2&gt;

&lt;p&gt;Every detector requires at least one positive &lt;code&gt;example&lt;/code&gt;. When you create the&lt;br&gt;
evaluation, those examples run as a smoke test: each positive must actually&lt;br&gt;
match, and a &lt;code&gt;classification&lt;/code&gt; example must land inside its declared&lt;br&gt;
&lt;code&gt;categories&lt;/code&gt;. If it doesn't, &lt;strong&gt;creation fails&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This is the part I wish I'd had years ago. A prompt can be syntactically fine&lt;br&gt;
and semantically broken, and you find out in production. Here, a broken detector&lt;br&gt;
can't ship — the assertion runs before it's ever live. (&lt;code&gt;non_examples&lt;/code&gt; are&lt;br&gt;
presence-only, because a classification detector always lands &lt;em&gt;somewhere&lt;/em&gt;, so&lt;br&gt;
there's no "not found" state to assert.)&lt;/p&gt;

&lt;h2&gt;
  
  
  2. The output is validated deterministically, not trusted
&lt;/h2&gt;

&lt;p&gt;The LLM proposes; deterministic code disposes. The validators are boring on&lt;br&gt;
purpose: &lt;code&gt;present&lt;/code&gt;, &lt;code&gt;range:0-100&lt;/code&gt;, &lt;code&gt;enum:yes,no&lt;/code&gt;. An out-of-set classification&lt;br&gt;
doesn't get to pass — it's coerced to not-found and surfaced in an&lt;br&gt;
&lt;code&gt;invalid_fields&lt;/code&gt; list so you can see the model misbehaved instead of silently&lt;br&gt;
acting on it.&lt;/p&gt;

&lt;p&gt;This is the line I'd defend hardest: structured outputs / function calling get&lt;br&gt;
you a valid &lt;em&gt;shape&lt;/em&gt;. They don't get you a &lt;em&gt;checked value&lt;/em&gt;. A schema says "this&lt;br&gt;
is a string from a set"; it doesn't run your range check or tell you the model&lt;br&gt;
went off-menu.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Escalation is rules, not a confidence threshold
&lt;/h2&gt;

&lt;p&gt;Escalation is separate from the model's self-reported confidence. You write&lt;br&gt;
triggers on extracted values:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a classification trigger fires when the value is in a declared set&lt;/li&gt;
&lt;li&gt;a presence trigger fires when the detector is found&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;required: true&lt;/code&gt; triggers are ANDed; &lt;code&gt;required: false&lt;/code&gt; are ORed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So "escalate if it's a strategic partnership AND a competitor is mentioned" is&lt;br&gt;
expressible and deterministic. No magic 0.7.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. One call, structured decision out
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;POST /v1/evaluate → { status, extracted_signals, next_action }
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;status&lt;/code&gt; is one of &lt;code&gt;QUALIFIED / PARTIAL / FAILED / ESCALATE&lt;/code&gt;. That's the whole&lt;br&gt;
point: the thing my &lt;code&gt;switch&lt;/code&gt; branches on is a small closed enum, not free text I&lt;br&gt;
have to parse and pray over. It drops straight into n8n/Zapier/Make. You can&lt;br&gt;
also POST real outcomes back later (converted? deal value? days to close?) so&lt;br&gt;
the rubric can be measured against reality instead of vibes.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I got wrong / what's still ugly
&lt;/h2&gt;

&lt;p&gt;Being honest, because these are real:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Everything hits the LLM today.&lt;/strong&gt; Even an obvious keyword goes through a
model call. The plan is a pre-LLM pattern extractor so deterministic signals
never pay for inference — not built yet. So cost/latency is "one batched LLM
call per eval": fine for inbound webhooks, not for high-QPS streams.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It's synchronous.&lt;/strong&gt; Long transcripts are slow; I prepend a structured
header (severity/tier) instead of dumping a 5k-token thread.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Batching detectors into one prompt&lt;/strong&gt; keeps cost down but lets one
detector's phrasing bleed into another's extraction. Isolating them costs N
calls. I chose cost; not sure it's right.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-turn is naive.&lt;/strong&gt; Re-evaluating a growing conversation re-sends the
whole thing. Delta prompts are on the list.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The question I actually have
&lt;/h2&gt;

&lt;p&gt;Is "declare + validate + smoke-test" the right altitude? Or do people doing this&lt;br&gt;
seriously want prompt-level control and would find the abstraction a cage the&lt;br&gt;
first time they hit an edge case?&lt;/p&gt;

&lt;p&gt;My bet: for the 80% case — lead qual, ticket triage, intent on inbound — nobody&lt;br&gt;
should be hand-maintaining a classification prompt, the same way nobody&lt;br&gt;
hand-writes a query planner. But I've been wrong about abstractions before.&lt;br&gt;
Curious where this breaks for you.&lt;/p&gt;




&lt;p&gt;I packaged this up as the evaluation API behind &lt;a href="https://getechostack.com#demo" rel="noopener noreferrer"&gt;EchoStack&lt;/a&gt;&lt;br&gt;
— you can &lt;a href="https://getechostack.com#demo" rel="noopener noreferrer"&gt;run an evaluation on your own text in the demo&lt;/a&gt;&lt;br&gt;
(no signup) or skim the &lt;a href="https://docs.getechostack.com/guides/eval-quickstart/" rel="noopener noreferrer"&gt;API quickstart&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>typescript</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>How I Designed a Modular, Event-Driven Architecture for Real-Time Voice AI</title>
      <dc:creator>Ayoola Solomon</dc:creator>
      <pubDate>Wed, 19 Nov 2025 09:49:54 +0000</pubDate>
      <link>https://dev.to/ayoolasolomon/how-i-designed-a-modular-event-driven-architecture-for-real-time-voice-ai-3d6g</link>
      <guid>https://dev.to/ayoolasolomon/how-i-designed-a-modular-event-driven-architecture-for-real-time-voice-ai-3d6g</guid>
      <description>&lt;p&gt;&lt;strong&gt;Most voice AI systems today are built as a fixed chain:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;STT → LLM → TTS → Audio Output.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This works for demos, but falls apart the moment you need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Custom business logic&lt;/li&gt;
&lt;li&gt;CRM integrations&lt;/li&gt;
&lt;li&gt;Multi-agent routing&lt;/li&gt;
&lt;li&gt;Knowledge lookups&lt;/li&gt;
&lt;li&gt;Scheduling flows&lt;/li&gt;
&lt;li&gt;Post-call actions&lt;/li&gt;
&lt;li&gt;Pipeline branching&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Swappable providers (Claude vs GPT, Deepgram vs Whisper, etc.)&lt;/p&gt;

&lt;p&gt;So for &lt;strong&gt;EchoStack&lt;/strong&gt;, I scrapped the idea of a “voice bot pipeline” entirely and built a &lt;strong&gt;voice automation platform&lt;/strong&gt; powered by an &lt;strong&gt;event-driven orchestration layer&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here’s how the architecture works — and why it has completely changed what’s possible with real-time AI.&lt;/p&gt;

&lt;h2&gt;
  
  
  LiveKit Only Handles Ingress &amp;amp; Egress
&lt;/h2&gt;

&lt;p&gt;Not STT.&lt;br&gt;
Not LLM.&lt;br&gt;
Not TTS.&lt;/p&gt;

&lt;p&gt;Just pure audio transport:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User Mic → LiveKit → EchoStack  
EchoStack → LiveKit → User Speaker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside EchoStack, every audio frame becomes an event:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;processing.livekit.audio_frame
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes the audio layer fully modular and independent of AI logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Everything Inside EchoStack Is a Connector
&lt;/h2&gt;

&lt;p&gt;A connector can be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deepgram STT&lt;/li&gt;
&lt;li&gt;WhisperX&lt;/li&gt;
&lt;li&gt;AssemblyAI&lt;/li&gt;
&lt;li&gt;Claude&lt;/li&gt;
&lt;li&gt;GPT-4o&lt;/li&gt;
&lt;li&gt;Llama 3&lt;/li&gt;
&lt;li&gt;ElevenLabs&lt;/li&gt;
&lt;li&gt;Azure Neural TTS&lt;/li&gt;
&lt;li&gt;HubSpot&lt;/li&gt;
&lt;li&gt;Salesforce&lt;/li&gt;
&lt;li&gt;Zendesk&lt;/li&gt;
&lt;li&gt;Calendly&lt;/li&gt;
&lt;li&gt;A custom HTTP API&lt;/li&gt;
&lt;li&gt;A knowledge search&lt;/li&gt;
&lt;li&gt;A database entry&lt;/li&gt;
&lt;li&gt;Or even another AI agent
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"consumes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"processing.deepgram.text"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"produces"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"processing.claude.agent_message"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;EchoStack&lt;/strong&gt; uses this to decide where events flow next.&lt;/p&gt;

&lt;p&gt;This creates a real-time version of Zapier or LangGraph.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pipelines Are Just Manifests
&lt;/h2&gt;

&lt;p&gt;Instead of hardcoded logic, pipelines are defined like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"pipeline"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"ingress.livekit.audio_frame → deepgram.stt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"deepgram.stt → claude.agent"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"claude.agent → elevenlabs.tts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"elevenlabs.tts → egress.livekit.audio_chunk"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No code.&lt;br&gt;
No wiring.&lt;br&gt;
Just declarative routing.&lt;/p&gt;

&lt;p&gt;Want to swap Deepgram for Whisper?&lt;br&gt;
Edit one line.&lt;/p&gt;

&lt;p&gt;Want to add sentiment analysis between STT and LLM?&lt;br&gt;
Add one rule.&lt;/p&gt;

&lt;p&gt;Want multi-agent routing?&lt;br&gt;
Add a router connector.&lt;/p&gt;
&lt;h2&gt;
  
  
  Multi-Playbook Orchestration (The Real Game-Changer)
&lt;/h2&gt;

&lt;p&gt;Traditional voice agents can only run one flow.&lt;/p&gt;

&lt;p&gt;EchoStack can run many — and switch between them in real time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LeadQualifier.json  
MeetingBooker.json  
FAQBot.json  
SupportAgent.json  
CRMLogger.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the user says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“I want to book a meeting.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Routing connector switches the playbook:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;processing.deepgram.text → intent.router → meeting_booker.playbook
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is impossible in a linear voice bot pipeline, but trivial in an event system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-Time Streaming (STT, LLM, TTS)
&lt;/h2&gt;

&lt;p&gt;Because everything is async events, the system supports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Streaming STT transcripts&lt;/li&gt;
&lt;li&gt;Streaming LLM tokens (Claude / GPT-4o)&lt;/li&gt;
&lt;li&gt;Streaming TTS audio chunks&lt;/li&gt;
&lt;li&gt;Barge-in and interruption&lt;/li&gt;
&lt;li&gt;Live agent escalation&lt;/li&gt;
&lt;li&gt;Parallel processing&lt;/li&gt;
&lt;li&gt;Multi-agent collaboration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example LLM output stream event:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;processing.claude.agent_message.partial
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example TTS stream:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;processing.elevenlabs.audio_chunk.stream
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The user hears responses as they are generated — not after the full LLM response.&lt;/p&gt;

&lt;h2&gt;
  
  
  Full Pipeline Simulation (No LiveKit Needed)
&lt;/h2&gt;

&lt;p&gt;This is my favorite feature.&lt;/p&gt;

&lt;p&gt;EchoStack can simulate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Audio → STT&lt;/li&gt;
&lt;li&gt;STT → LLM&lt;/li&gt;
&lt;li&gt;LLM → TTS&lt;/li&gt;
&lt;li&gt;TTS → Egress&lt;/li&gt;
&lt;li&gt;All connector interactions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without touching real providers.&lt;/p&gt;

&lt;p&gt;It utilizes a mock runtime registry to generate realistic, fake outputs.&lt;/p&gt;

&lt;p&gt;This allows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Visual debugging&lt;/li&gt;
&lt;li&gt;Step-by-step replay&lt;/li&gt;
&lt;li&gt;Education demos&lt;/li&gt;
&lt;li&gt;Test-driven development&lt;/li&gt;
&lt;li&gt;Predictable QA&lt;/li&gt;
&lt;li&gt;“Dry runs” before deployment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is something even Retell &amp;amp; Vapi don’t have today.&lt;/p&gt;

&lt;h2&gt;
  
  
  And It Scales Like a Distributed System
&lt;/h2&gt;

&lt;p&gt;Because everything is events:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each connector is a worker&lt;/li&gt;
&lt;li&gt;Workers scale horizontally&lt;/li&gt;
&lt;li&gt;Backpressure is manageable&lt;/li&gt;
&lt;li&gt;Failures can be contained&lt;/li&gt;
&lt;li&gt;Retries &amp;amp; fallbacks are simple&lt;/li&gt;
&lt;li&gt;Pipelines can fork or merge&lt;/li&gt;
&lt;li&gt;Multi-agent flows work naturally&lt;/li&gt;
&lt;li&gt;Audioless connectors (CRM, DB, API) blend seamlessly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It behaves like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Zapier&lt;/li&gt;
&lt;li&gt;AWS EventBridge&lt;/li&gt;
&lt;li&gt;LangGraph&lt;/li&gt;
&lt;li&gt;Airflow&lt;/li&gt;
&lt;li&gt;N8N&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;…but optimized for real-time audio.&lt;/p&gt;

&lt;h2&gt;
  
  
  What This Unlocks for Businesses
&lt;/h2&gt;

&lt;p&gt;This is where the architecture stops being “cool tech” and becomes actual value:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lead qualification&lt;/li&gt;
&lt;li&gt;After-hours support&lt;/li&gt;
&lt;li&gt;Customer triage&lt;/li&gt;
&lt;li&gt;Booking assistants&lt;/li&gt;
&lt;li&gt;Helpdesk automation&lt;/li&gt;
&lt;li&gt;Sales follow-ups&lt;/li&gt;
&lt;li&gt;Knowledge Q&amp;amp;A&lt;/li&gt;
&lt;li&gt;Order tracking&lt;/li&gt;
&lt;li&gt;Multi-agent escalation&lt;/li&gt;
&lt;li&gt;CRM syncing&lt;/li&gt;
&lt;li&gt;Custom playbooks per industry&lt;/li&gt;
&lt;li&gt;Complex routing between AI tools&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You don’t just deploy “a bot.”&lt;/p&gt;

&lt;p&gt;You deploy a &lt;strong&gt;network of intelligent voice automations&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing Thoughts
&lt;/h2&gt;

&lt;p&gt;Voice AI is moving fast, but most of what exists today is still:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;rigid&lt;/li&gt;
&lt;li&gt;non-composable&lt;/li&gt;
&lt;li&gt;difficult to integrate&lt;/li&gt;
&lt;li&gt;tied to single vendors&lt;/li&gt;
&lt;li&gt;non-debuggable&lt;/li&gt;
&lt;li&gt;non-portable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By making the entire system event-driven and connector-based, EchoStack becomes:&lt;/p&gt;

&lt;p&gt;A real-time automation platform where voice is the entry point — not the limitation.&lt;/p&gt;

&lt;p&gt;If you’re into real-time systems, LiveKit, STT/LLM/TTS pipelines, or voice automation, I’d love to exchange ideas.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>architecture</category>
      <category>startup</category>
      <category>automation</category>
    </item>
    <item>
      <title>Inside the Manifest: How We Make Voice-AI Playbooks Deployable</title>
      <dc:creator>Ayoola Solomon</dc:creator>
      <pubDate>Mon, 10 Nov 2025 21:51:59 +0000</pubDate>
      <link>https://dev.to/ayoolasolomon/inside-the-manifest-how-we-make-voice-ai-playbooks-deployable-5431</link>
      <guid>https://dev.to/ayoolasolomon/inside-the-manifest-how-we-make-voice-ai-playbooks-deployable-5431</guid>
      <description>&lt;p&gt;Most businesses don’t want another AI “demo.”&lt;br&gt;
They want &lt;strong&gt;deployable outcomes&lt;/strong&gt; — like qualifying a lead, booking a meeting, or handling an after-hours call automatically.&lt;/p&gt;

&lt;p&gt;At EchoStack, we wanted to make these outcomes &lt;strong&gt;as easy to launch as deploying code&lt;/strong&gt; — and that’s how the &lt;em&gt;manifest&lt;/em&gt; was born.&lt;/p&gt;


&lt;h3&gt;
  
  
  The Problem
&lt;/h3&gt;

&lt;p&gt;Voice-AI tools today can hold great conversations, but they often stop there.&lt;br&gt;
To &lt;em&gt;actually&lt;/em&gt; move data into CRMs, book meetings, or send follow-ups, you need engineers stitching APIs together.&lt;/p&gt;

&lt;p&gt;That doesn’t scale for non-technical teams.&lt;/p&gt;


&lt;h3&gt;
  
  
  Our Solution — The Manifest
&lt;/h3&gt;

&lt;p&gt;Each playbook in EchoStack (e.g., &lt;em&gt;Lead Qualifier&lt;/em&gt;, &lt;em&gt;After-Hours Support&lt;/em&gt;) is powered by a &lt;strong&gt;manifest&lt;/strong&gt; — a single file that describes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;what the playbook does&lt;/li&gt;
&lt;li&gt;which tools it connects to&lt;/li&gt;
&lt;li&gt;and what should happen when key events occur.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s like &lt;strong&gt;Terraform&lt;/strong&gt;, but for voice-driven business outcomes.&lt;/p&gt;


&lt;h3&gt;
  
  
  Example Manifest (Simplified)
&lt;/h3&gt;

&lt;p&gt;Here’s a simplified version of what a playbook looks like under the hood:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"lead-qualifier"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Voice Lead Qualifier"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Qualifies inbound leads via voice and syncs results to CRM."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"connectors"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"twilio"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"hubspot"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"calendly"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"events"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"call.started"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"start_conversation"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"lead.qualified"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"create_contact"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"meeting.booked"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"schedule_event"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This isn’t code — it’s a &lt;strong&gt;declarative contract&lt;/strong&gt; between the voice experience and the business stack.&lt;br&gt;
Our platform reads this file, provisions the right connectors, and handles orchestration automatically.&lt;/p&gt;




&lt;h3&gt;
  
  
  Why It Matters
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No-code deployment:&lt;/strong&gt; Business teams can launch playbooks instantly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Version control:&lt;/strong&gt; Every manifest can be tracked, forked, and redeployed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extensibility:&lt;/strong&gt; Developers can author new playbooks using familiar patterns (JSON, events, connectors).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It turns &lt;strong&gt;AI workflows into deployable building blocks&lt;/strong&gt; — reusable, composable, and measurable.&lt;/p&gt;




&lt;h3&gt;
  
  
  What’s Next
&lt;/h3&gt;

&lt;p&gt;We’re expanding the manifest system to support richer event schemas and multi-step orchestration.&lt;br&gt;
Soon, teams will be able to chain multiple playbooks together — stacking outcomes like Lego blocks.&lt;/p&gt;




&lt;h3&gt;
  
  
  Closing Thought
&lt;/h3&gt;

&lt;p&gt;If you’ve ever written Terraform for infrastructure or YAML for CI/CD, imagine doing that —&lt;br&gt;
but for &lt;em&gt;voice automation&lt;/em&gt;.&lt;br&gt;
That’s what EchoStack’s manifests make possible.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Curious to see a manifest in action?&lt;/strong&gt;&lt;br&gt;
We’re opening early access for developers building voice-AI workflows — you can join at &lt;a href="https://getechostack.com" rel="noopener noreferrer"&gt;getechostack.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>automation</category>
      <category>startup</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Designing Deployable Voice-AI Playbooks</title>
      <dc:creator>Ayoola Solomon</dc:creator>
      <pubDate>Tue, 28 Oct 2025 08:54:07 +0000</pubDate>
      <link>https://dev.to/ayoolasolomon/designing-deployable-voice-ai-playbooks-p95-300-ms-preflight-bluegreen-55eh</link>
      <guid>https://dev.to/ayoolasolomon/designing-deployable-voice-ai-playbooks-p95-300-ms-preflight-bluegreen-55eh</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This is a &lt;strong&gt;design/engineering write-up&lt;/strong&gt; for our EchoStack pivot. We’re packaging Voice-AI &lt;strong&gt;playbooks&lt;/strong&gt; (like &lt;em&gt;After-hours Answering&lt;/em&gt; and &lt;em&gt;Lead Qualifier → Auto-Book&lt;/em&gt;) into &lt;strong&gt;deployable solutions&lt;/strong&gt; with no-code setup, safe rollouts, and KPI tiles.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Status:&lt;/strong&gt; Early Access only — we’re validating integrations and rollout safety with a small group before opening signups.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Why playbooks (not tool soup)
&lt;/h2&gt;

&lt;p&gt;Teams don’t buy models; they buy &lt;strong&gt;outcomes&lt;/strong&gt;: fewer missed calls, more booked meetings, lower AHT. The hard parts are &lt;strong&gt;barge-in latency&lt;/strong&gt; and &lt;strong&gt;safe deployment&lt;/strong&gt;, not the LLM itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Latency budget we hold ourselves to (p95 targets)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;ASR partials: &lt;strong&gt;60–90 ms&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;LLM first token: &lt;strong&gt;80–120 ms&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;TTS first audio: &lt;strong&gt;50–80 ms&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Network buffers: &lt;strong&gt;40–60 ms&lt;/strong&gt;
→ Goal: &lt;strong&gt;&amp;lt; 300 ms p95&lt;/strong&gt; end-to-end (barge-in friendly).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Rollout safety (what we’re building)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;preflight → plan → apply (blue) → smoke test → switch (green) → rollback&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Preflight&lt;/strong&gt; checks scopes, latency probes, and config drift.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Plan&lt;/strong&gt; shows a human-readable diff.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Apply&lt;/strong&gt; deploys to an inactive slot (blue).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Switch&lt;/strong&gt; flips traffic; &lt;strong&gt;Rollback&lt;/strong&gt; is one click.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Integration surface (first adapters)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Telephony: Twilio/Plivo/SIP&lt;/li&gt;
&lt;li&gt;Voice agent: Retell (others later)&lt;/li&gt;
&lt;li&gt;Calendar: Calendly/Google&lt;/li&gt;
&lt;li&gt;CRM: HubSpot/Salesforce (Sheets fallback)&lt;/li&gt;
&lt;li&gt;Helpdesk: Zendesk (optional)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What exists today
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Data model + manifests for two playbooks&lt;/li&gt;
&lt;li&gt;No-code configuration flow (internal)&lt;/li&gt;
&lt;li&gt;Preflight → plan → apply skeleton&lt;/li&gt;
&lt;li&gt;KPI tiles (self-serve %, AHT, booked meetings) wired to session events&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What we’re validating next
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Region-aware routing under load&lt;/li&gt;
&lt;li&gt;Failure modes during blue/green switches&lt;/li&gt;
&lt;li&gt;Adapter ergonomics (CRM/calendar/telephony edge cases)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Looking for feedback
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Are these &lt;strong&gt;p95 targets&lt;/strong&gt; realistic for your use case?&lt;/li&gt;
&lt;li&gt;What &lt;strong&gt;minimum logs/SLAs&lt;/strong&gt; make you comfortable with rollout?&lt;/li&gt;
&lt;li&gt;Which &lt;strong&gt;adapter combo&lt;/strong&gt; should be prioritized?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;More context:&lt;/strong&gt; &lt;a href="https://getechostack.com/playbooks" rel="noopener noreferrer"&gt;https://getechostack.com/playbooks&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Early Access (no public demo yet):&lt;/strong&gt; &lt;a href="https://getechostack.com/contact?subject=Early%20Access" rel="noopener noreferrer"&gt;https://getechostack.com/contact?subject=Early%20Access&lt;/a&gt;&lt;/p&gt;

</description>
      <category>voiceai</category>
      <category>architecture</category>
      <category>nocode</category>
      <category>saas</category>
    </item>
    <item>
      <title>From building a voice AI widget to mapping the entire Voice AI ecosystem (Introducing echostack)</title>
      <dc:creator>Ayoola Solomon</dc:creator>
      <pubDate>Mon, 13 Oct 2025 19:04:15 +0000</pubDate>
      <link>https://dev.to/ayoolasolomon/from-building-a-voice-ai-widget-to-mapping-the-entire-voice-ai-ecosystem-introducing-echostack-ceo</link>
      <guid>https://dev.to/ayoolasolomon/from-building-a-voice-ai-widget-to-mapping-the-entire-voice-ai-ecosystem-introducing-echostack-ceo</guid>
      <description>&lt;p&gt;Hey everyone,&lt;/p&gt;

&lt;p&gt;I’m Solomon — the creator of &lt;a href="https://getechospace.com/" rel="noopener noreferrer"&gt;GetEchoSpace&lt;/a&gt;, a voice AI widget that lets any website host real-time audio conversations for support, live shopping, or community.&lt;/p&gt;

&lt;p&gt;While building it, I constantly had to combine tools for ASR, text-to-speech, and LLMs — juggling APIs from different vendors and testing pipelines just to get a working flow.&lt;/p&gt;

&lt;p&gt;At some point, it hit me:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Everyone building in voice AI is reinventing the same workflows from scratch.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;There are incredible voice AI tools out there — from OpenAI’s speech APIs to ElevenLabs, Whisper, Speechmatics, and more.&lt;br&gt;
But there’s no central place to discover, compare, and see how they connect in real-world setups.&lt;/p&gt;

&lt;p&gt;Builders like me spend hours figuring out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;which ASR integrates best with Twilio,&lt;/li&gt;
&lt;li&gt;how to pass data between TTS and LLMs,&lt;/li&gt;
&lt;li&gt;and how to deploy these flows in production.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Enter echostack
&lt;/h2&gt;

&lt;p&gt;So I started building &lt;a href="https://getechostack.com" rel="noopener noreferrer"&gt;echostack&lt;/a&gt; — a public directory of voice AI tools and ready-made “stacks.”&lt;/p&gt;

&lt;p&gt;Think of it as Zapier templates or Stack Overflow for voice AI workflows.&lt;br&gt;
Each stack shows how to combine tools (e.g., Retell + OpenAI + Twilio + GCP ASR) to achieve real outcomes — like multilingual dubbing, customer triage bots, or AI-powered voice assistants.&lt;/p&gt;

&lt;p&gt;The goal:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;help developers and AI builders spend less time wiring tools, and more time shipping value.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Tech Behind the MVP
&lt;/h3&gt;

&lt;p&gt;The MVP is built with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Next.js 15 (App Router)&lt;/li&gt;
&lt;li&gt;TypeScript + Tailwind&lt;/li&gt;
&lt;li&gt;Supabase (for data)&lt;/li&gt;
&lt;li&gt;Zapier &amp;amp; n8n export support planned for v0.2&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What’s Live Now
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Figkl65113pmirp4him11.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Figkl65113pmirp4him11.png" alt="stack detail page" width="800" height="932"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can explore:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Featured voice AI tools&lt;/li&gt;
&lt;li&gt;Early “stacks” (like multilingual dubbing or real-time triage bots)&lt;/li&gt;
&lt;li&gt;Newsletter signup for updates as new stacks drop&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://getechostack.com" rel="noopener noreferrer"&gt;https://getechostack.com&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  I’d love your feedback
&lt;/h3&gt;

&lt;p&gt;If you’re building with Voice-AI or integrating ASR/TTS/LLM tools, I’d love to hear:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What workflows or “stacks” you’d want to see next&lt;/li&gt;
&lt;li&gt;Which tools are must-haves for you&lt;/li&gt;
&lt;li&gt;Whether you prefer no-code or code-level examples&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What’s Next?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Expand to more tools and stacks&lt;/li&gt;
&lt;li&gt;Add semantic search and tagging&lt;/li&gt;
&lt;li&gt;Support Zapier/n8n exports&lt;/li&gt;
&lt;li&gt;Launch the curated Voice-AI Stacks Newsletter&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If that sounds interesting, you can check it out or share feedback directly on &lt;a href="https://getechostack.com" rel="noopener noreferrer"&gt;echostack&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>voiceai</category>
      <category>indiehackers</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
