A focus group
you can call.
You have an idea for something. You can probably come up with a few reasons someone would want it. It’s harder to work out why they’d ignore it, or what you’d have to change before they’d care.
I built Tunnel with Dev, Suneru, and Haresh, and we won 2 awards at Hack the North. We made a world of AI personas you can pitch an idea to, then talk to the ones whose responses you want to understand.
The whole thing lives on a globe. Each point is a generated person with a job, interests, a location, and their own response to your idea. Click one and you can read what they thought. If their answer leaves you with more questions, you can call them.
Find an audience
We start with the idea you type in. Tunnel identifies its niche, then looks for personas whose backgrounds have something to do with it. A tool for developers should reach people who write code. A consumer product might need a very different group.
Each profile has structured fields for occupation, industry, interests, demographics, and traits like price sensitivity. We turn those fields into a short text document and send the documents to Cohere’s rerank API, with the niche and original idea as the query.
We use Cohere’s rerank-english-v3.0 model and request the top results, capped at the number of available profiles. It returns document indices and relevance scores. We map those indices back to the original profiles and keep their persona IDs through the rest of the pipeline, from opinion generation to the points on the globe.
That score answers a fairly narrow question: how relevant is this profile to the idea? It doesn’t tell us whether the person will like it. We ask that separately.
product + audiencePersona profiles
work + interests + traits
A smaller group to start with
Give each person
a response
Once we have a group, we make a separate Cohere Command R request for each persona. The prompt includes that person’s background and the product idea. We ask for their level of attention, sentiment, a reason, and a comment with any suggestions. Each call has a 700 token output limit, which keeps the response short enough to read and parse.
The response comes back as JSON. We validate that attention is one of three values and that sentiment is a number between zero and one. Keeping those fields separate lets the interface show a quick overview while still giving you the actual explanation.
The API starts the requests together using Promise.all. Each request catches its own errors, so one failed response won’t reject the entire group. The endpoint waits for the group before returning the results. That saves us from waiting for every persona in sequence, though it also means a slow request can hold up the batch.
Once the responses arrive, the interface reveals five every 600 milliseconds and updates the globe and counts together. Those are completed responses being displayed gradually. Each one carries its persona ID so the point, written feedback, and eventual call all refer to the same profile.
One response per persona
- personaId
- Keep the same identity
- attention
- full / partial / ignore
- sentiment
- 0 to 1
- reason
- Why they reacted this way
- comment
- What they would change
Okay, but why?
A written response can leave you with more questions. We added a way to call that persona and ask them directly.
We used Vapi for the voice conversation. Before the call starts, we build a system prompt from the selected persona, the idea you pitched, and the reaction they already gave. If they were skeptical about the price, the call should start with that concern.
The prompt asks the agent to hold onto its initial opinion unless you address the specific objection. Otherwise it’s too easy to get a completely different answer just by opening a new conversation.
The standalone call view reads a context object from sessionStorage containing the persona, reaction, and product idea. It uses that object to build the system prompt before starting the Vapi session. The browser listens for call, speech, and transcript events from Vapi. Those events update the call controls and the transcript while you talk. The voice session gets the same persona context as the written response, so you can go straight to a follow up question.

Try it again
You can save the responses you want to work on, then ask Tunnel to revise the idea using that feedback. We send the original pitch and the selected comments back to Cohere and put the revised version into the input.
From there, we run it through the existing focus group again. Keeping the group gives you a way to compare responses without also changing everyone you’re asking. When you’re ready, the global view sends the idea to all the loaded personas.
We used Auth0’s Management API to create the synthetic identities and store their profile fields as metadata. MongoDB holds the analysis sessions, including the prompt, selected people, opinions, and interface state. Each session has user and project IDs, with a compound index on that pair for workspace lookups. Autosave waits two seconds after a change before saving, resetting the timer if another change comes in. That lets you return to the same experiment without saving on every edit.
Back to the same group ↵
What I’d want to test next
I’d want to put these responses next to interviews with real people. The profiles and opinions are generated, so a positive result tells us how the model reacted to a description. It doesn’t establish that someone would buy the product.
The hackathon version also substitutes a fallback response if an individual model call fails. I’d make those failures visible and exclude them from the results before using the scores to compare ideas.