Skip to main content

Overview

nextneural_coach runs practice calls. A trainee talks to a simulated customer — a persona placed in a scenario — and the resulting conversation is scored against a rubric.

It can also run entirely without a human: an LLM plays the rep against the simulated customer, which is how a prompt change is regression-tested before it reaches a real caller.

How the pieces fit​

Persona  +  Scenario  ──►  Run  ──►  Score
│ │ │
│ │ ├─ text: LLM plays the rep
│ │ └─ voice: spoken through the flow's own socket
│ │
│ └─ situation, objective, stop conditions, rubric
└─ who the customer is: profile, objections, hidden state, speech habits
  1. Personas are the simulated customer
  2. Scenarios put that persona in a situation with an objective
  3. Documents ground what the customer knows
  4. Runs are one practice call, scored
  5. Live practice is a human doing it in real time

Response shapes​

nextneural_coach differs from the other three binaries in two ways that matter to a client.

List endpoints wrap rows in results, and an empty collection may come back as null rather than []:

{ "results": null }

Treat null and [] as equivalent. Single-resource endpoints return the object directly, with no envelope.

Authentication responses are flat. Where the other binaries return {token, user: {…}}, nextneural_coach returns the account fields alongside the token:

{
"token": "eyJhbGciOiJIUzI1NiIs...",
"email": "[email protected]",
"role": "admin",
"superadmin": true,
"organization_name": "Pragati AI",
"organization_uuid": "ff791b46-9eea-4dc0-b33e-efcb976eca28",
"waitlist_status": "approved"
}

GET /api/nn-coach/auth/me returns the same fields plus auth_method (session or api_key), and omits the token. An account with no organization yet has no organization_* fields.

Do not reuse a response parser across binaries.

Base paths​

SurfaceBase
API/api/nn-coach
Auth/api/nn-coach/auth
Superadmin/api/nn-coach/auth/superadmin
Live practice/api/nn-coach/live
Health/health

nextneural_coach listens on :8010 by default (NN_COACH_ADDR), not 8080.

One surface, two credentials​

Unlike the other binaries, nextneural_coach does not split a console API from a developer API. Every route under /api/nn-coach accepts either a session token or an API key, with the same handlers and the same org scoping — so a capability never exists on one surface and is quietly missing from the other.

Role-gated routes (creating personas, scenarios, documents; deleting runs) refuse API keys outright. Those are manager or admin actions.

Runs are always against a real agent​

There is no built-in stand-in to practise against. A run names the deployed flow whose agent is under test:

{ "scenario_uuid": "…", "target_kind": "flow", "target_uuid": "…", "mode": "text" }

The mode changes the transport, not what is being tested:

ModeWhat happens
textLLM-to-LLM. Fast and cheap, exercises the prompt and the logic
voiceThe customer is spoken through TTS into the flow's real WebSocket, so STT, VAD, barge-in, and TTS are all exercised too

Voice mode can only target a flow, because the audio transport is the flow's own browser-test socket.

Scoring​

A finished run is judged against a rubric and carries a verdict: pass, fail, or partial.

Judging can be delegated to nextneural_intel through JUDGE_API_BASE_URL and JUDGE_API_TOKEN, so a practice call is scored by the same extraction a real call receives — which is what makes a trainee's score comparable to live performance rather than a separate ladder.

Requirements​

ForRequires
Any runOPENROUTER_API_KEY, and a database
Knowledge groundingpgvector — required, the migration has no fallback
Voice runsSARVAM_API_KEY, VOICE_API_BASE_URL, VOICE_API_TOKEN
nextneural_intel judgingJUDGE_API_BASE_URL, JUDGE_API_TOKEN

NN_COACH_DB_AUTO_CREATE defaults to true, so the binary creates its own database at boot if the role has CREATEDB.

Running it

make run APP=nn_coach fails — the generic target looks for ./cmd/server and this binary's is cmd/nn_coach. Use make run APP=nn_coach BIN=nn_coach, or apps/nn_coach/dev.sh, which also starts the front end on :5174.