Wednesday 9 / 09 / 2026タイラー

Striker

Most "AI SDR" tools stop at the door. Find leads, run a sequence, book a meeting, hand it to a human. That is the easy half.

The hard half starts after the meeting: follow-up, quotes, objections, and the seller who swore he would call back on Tuesday. Striker is built for that half. Prospecting is a door, not the product.

The layer

Take the funnel a sales manager already knows, prospecting through close, and put one layer on top of it:

  • who acts at each stage, agent or human
  • what happens when the human does not execute
  • meeting agreements, meeting quality, executive evaluation, sentiment

Remove that layer and you have a CRM. The layer is the product.

Three planes, one rule

Edenin-processwritesdashboardVite SPAserverBun · ElysiaagentsMastradbPostgrescorepure rules
The dashboard calls the server directly. No BFF in between.

server — Bun + Elysia + Better Auth. Multi-tenant HTTP, webhooks, orchestration, sends, jobs. It is the only thing that touches the database.

agents — Mastra. Drafts only: conversation, first touch, persona. No auth, no DB, no send. Imported in-process by default, with the option to run as its own process when a deployment needs it.

core — pure engines. Scoring, send gates, playbooks, pricing. No IO, so it is the part that is actually testable.

The rule is that only the server writes. It sounds trivial until an inference framework asks for a repo, and you say no, and the blast radius of a bad prompt stays at "a draft nobody sent".

Rest of the stack: Bun workspaces with Moon, not Turborepo or Nx. Postgres as truth, Redis for cache and queues, Drizzle for schema and repos, Zod contracts shared across the wire. The dashboard is a Vite SPA speaking Eden Treaty straight to the server. No BFF, so there is no second backend to keep in sync with the first.

The accent

The agent sells in Chile, so it speaks Chilean Spanish. The voice was fine until someone interrupted it. After an interruption it came back neutral, which mid-call reads as a different person picking up the phone.

The fix was not a better prompt. The accent had been living in three places at once: the product repo, the platform repo, and the runtime. So we gave it one home. A Profile now pins what the voice speaks and what the transcriber expects, and every surface that renders that voice reads the same contract. Interruptions stopped changing who was talking.

Most of the interesting bugs here look like that. Not "the model is wrong", but "two components each believe they own the same fact".

Silence is a step

A campaign that keeps sending while the prospect is halfway through a reply is worse than one that never sends at all.

So waiting is not a gap between steps. It is an authored step with its own state. An inbound email stops the clock. A human task blocks the next move until someone closes it. The runtime keeps a ledger of turns rather than a list of phrases to fire.

Tools work the same way: the agent binds named packs instead of seven loose flags, capped at twelve, with one bit that unbinds them all.

What I would keep

Contracts before prompts. Every "the model is behaving weirdly" bug so far has turned out to be a fact with two owners.

One writer to the database. Everything else drafts.

Domain rules stay pure and far away from anything that talks to an LLM.

It is live at striker.tyrell.so