Real people should never be the testing ground
CallCraft is a simulated practice space for crisis-support conversations, built so that trainees get their reps before anyone in crisis is depending on them.
By Prosocial Coding LLC (Ryan Thomas)
You can teach someone the words for a crisis-support call. Teaching them to use those words while a real person is coming apart on the other end of the line is a different thing, and the only way across that gap is practice. Practice is the thing most crisis-support training is short on. Good role-play takes a trained facilitator, a willing partner, and time, and even then the scenarios are uneven and the feedback depends on who happens to be in the room that day. Trainees often reach their first real calls having rehearsed far less than the stakes deserve.
I spent years in direct services in the domestic violence field, and that work set the bar I built CallCraft to meet. CallCraft is an independent Prosocial Coding LLC project, separate from my day job. The rule I built it around is one sentence: real people should never be the testing ground. A trainee should be able to stumble, pause, try again, and get feedback in a room where the only person on the line is simulated.
That rule is also why the safety work is not a part of this project. It is the project. Everything else is downstream of one question, asked before any feature gets built: could this harm someone? If the honest answer is unclear, the feature does not ship until it is clear.
What it does
CallCraft is a practice space for crisis-support conversations. A participant picks a scenario, chooses a difficulty level, and enters a live voice session with an AI caller. The voice side runs on Google Gemini Live, with browser microphone input, voice activity detection through an AudioWorklet, audio streamed over WebSocket, and Web Audio playback. There is a text-based mode too, along with live coaching tips, full transcripts, saved history, and post-session analysis. The stack is React, Vite, Express, Firebase, and Firestore, with Zod for validation and Playwright and Vitest for tests.
The backend does real work before anything reaches the model. It authenticates the user, resolves the scenario, builds the Gemini session configuration on the server, issues a short-lived session token, enforces the legal acceptance step, checks usage limits, and keeps the scenario prompt and the scoring materials out of the browser entirely. The scoring engine compares a transcript against the scenario's objectives, a set of canonical skill dimensions, and server-side reference answers the client never sees. Keeping that logic on the server is a safety decision as much as a product one. A trainee should not be able to read the rubric they are being measured against, and a scenario prompt is not something to hand to the client and hope it stays put.
Who it is for
This is built for the people who run training, not for a consumer looking for advice in a hard moment: hotline supervisors, training leads, program managers, and institutional teams that need crisis-support practice they can repeat and rely on. The market work names plausible users like domestic violence service providers with hotline programs, state coalitions, national hotline networks, university crisis and advocacy programs, and grant-funded training programs. Those are written down in the repo as hypotheses, not as customers I already have.
The core problem is repetition, and the things that make repetition scarce. Good practice costs facilitator time and emotional energy. Every trainee should face the same baseline scenario, and in practice they rarely do. Consistent feedback after each attempt is harder still. CallCraft makes practice more available without moving judgment away from the people who should hold it. The app supplies the reps and the structure. Human trainers keep the call on what matters.
The safety work
Here is what that looks like in the code.
The app is built so organizations do not bump into each other. Firebase Auth, organization scoping, role checks, fresh-claims checks, and tenant-aware limits keep users and their data on separate paths by design rather than by luck. Every request crosses validation at the API and storage boundaries through strict Zod schemas, with transcript limits and request checks before any work proceeds, and a layer of standard web hardening around all of it: CSRF protection, strict security headers and content-security policy, CORS allowlists, payload caps, and rate limits tuned separately for general traffic, expensive AI calls, tenant usage, pilot access, and webhooks.
Live sessions are leased. A session lease lives in Firestore, scoped to a user or organization, with a time limit, heartbeat renewal, release when the page closes, and fail-closed behavior when the lease or rate-limit store cannot be trusted. If the system cannot confirm a session is allowed, it does not grant one. Transcripts are scrubbed of personal information before they are saved, covering emails, phone numbers, Social Security numbers, addresses, IP addresses, card-like strings, handles, and contextual name patterns, and analysis text is scrubbed again before it returns to the browser. Pilot sessions carry a retention limit, and users have endpoints to export or delete their data.
The output safety layer is the one I am most attached to. Before any AI caller audio reaches the trainee, it is checked for blocked harmful phrases and for persona-break patterns. If something unsafe comes through, the system stops it: it clears the audio buffer, prevents playback, and shows a safety interruption instead of letting the moment play. The scoring path fails closed the same way. If the analysis comes back malformed or unsafe, the system retries once in a structured form and then returns an explicit analysis_unavailable result rather than inventing a score to paper over the failure. A wrong score in a training tool teaches the wrong lesson with confidence, and that is not a small thing.
A few smaller choices come from the same place. High-risk safety flags can be marked for trainer review rather than resolved automatically. Transcript indices survive truncation, so a piece of feedback can point back to the moment it refers to. Scoring accounts for network latency instead of charging a bad connection against the trainee. When a voice session fails, the system saves the partial transcript and marks the analysis unavailable rather than guessing. None of these is dramatic. Small decisions are where a training tool either respects the stakes or quietly avoids them.
What it does not prove
CallCraft is not a clinical tool, and the repo says so plainly. The caller, the scoring, and the feedback are all AI-generated, which means they can be wrong and they can miss nuance. It is built for supervised training and practice, not for certification, diagnosis, or standing in for a human supervisor. There is also a privacy boundary worth stating directly: live audio is not scrubbed in real time before it reaches Gemini. That is precisely why CallCraft is a simulated practice space and nothing else. Real survivor data does not belong in a practice session, and the design assumes it never enters one.
I tested the safety claims as code, not just as intent. As of June 20, 2026, the repo records 1,788 passing tests across client, server, contract, security, and end-to-end paths, including focused regression tests for the output-safety layer: blocked phrases, persona-break patterns, and live blocking through the voice simulator. That matters, and it is not the same as clinical validation. Infrastructure tests prove the gates work. They do not prove the pedagogy is sound, and those are two different claims.
Where it is going
CallCraft works today, and it is well tested. The honest gaps are few and named. It has not had an independent clinical review. The real-time audio boundary is a deliberate constraint rather than a solved problem. And the deeper institutional deployment work, the kind large training organizations expect, is scoped but not built. None of it is buried in the codebase, and the system was designed so that finishing it is addition, not demolition.
The next priorities are an independent clinical review, tighter scenario-authoring controls, stronger adversarial testing, SSO or SCIM for institutional deployment, LMS integration, and a headless practice API for teams that already run a training platform.
What I want from CallCraft is plain. I want a trainee to hear a hard moment twice before they meet it once. I want a supervisor to see where someone needs help without relying on memory or on how confident the trainee sounded. And I want the AI in it to stay in its lane: simulated repetition, structured feedback, and a clean handoff to human judgment. It is built, it is tested, and it is ready for the programs that will put it to work.
Start with harm, then decide whether the feature has earned the right to exist. That is the method, and CallCraft is what it produced.
Related articles
An AI answer can sound right and still be dangerous
EchoCheck is a workbench for judging AI responses in survivor-serving contexts, built for reviewers who need more than a 'looks good' to go on.
ProductsProtective order software should fail closed
Protectly is a Texas protective order drafter built so that safety beats speed and privacy beats convenience, every time the two are in tension.
ProductsPolicy Work Needs a Better Operating Surface
Texas Legislature Tracker pulls bills, districts, legislators, committees, and advocacy drafting into one place, so a small team can get from information to action without stitching five systems together by hand.