Custom harness quickstart
You will need Node.js 22 or later, an OpenAI API key (or any OpenAI-compatible endpoint), an Agent Studio account connected to jambonz with speech-to-text and text-to-speech credentials, and ngrok or another tunnel so jambonz can reach your laptop.
1. Create the project
Put your key in .env:
The project is TypeScript on @jambonz/sdk/harness. Your logic is in
src/agent.ts; src/index.ts only starts the server. The generator’s source is
jambonz/create-agent-harness.
2. Run it
It listens on port 8080 and restarts when you edit src/. npm test runs it against a fake jambonz, without a model
key.
3. Let jambonz reach it
In a second terminal:
ngrok prints an https://….ngrok.app address. Your harness URL is the same address with wss://:
wss://….ngrok.app.
4. Create the agent in Agent Studio
- New agent, choose Custom harness, give it a name and create it.
- In the Custom harness section, enter the Harness URL.
- Check Hear & speak: the speech recognition and voice jambonz uses on the call.
5. Call it
In the Test panel, choose This browser and Start test call. You hear “Thanks for calling Acme. How can I help?”, and your terminal logs the call. Try:
- “When are you open?”: the model calls the harness’s own
get_business_hourstool. - “Can I talk to a person?”: transferred without a model call, to
OPERATOR_NUMBERin.env, or without it to the destination in the agent’s Transfer & hangup section.
6. Make it yours
Open src/agent.ts. Each part is optional:
instructionsandgreeting: the prompt and the first thing saidbeforeModel: runs before each model call; route, retrieve, or answer directly with{ reply }tools: tools of the harness’s own; the agent’s tools from Studio are offered to the model toocheckSentence: inspects each sentence before it is spokenonEvent: reacts todtmf,silence,transferand other events
See the SDK reference for every option.
7. Add a secret
To make sure only jambonz can connect, set a secret in .env and restart:
Then in the agent’s Custom harness section, enter the same value as the Secret and press Save. It is stored
in your jambonz account and sent as Authorization: Bearer <secret> when each call connects; a connection without it
gets HTTP 401.
8. Deploy
Run it behind TLS (a load balancer, or nginx or Caddy passing WebSocket upgrades) so the URL is wss://. GET /health
answers {"ok":true,"calls":N} for health checks. Put the production URL in the agent and publish: the URL is
part of the agent, so calls use the new one once you publish.