agentsclimarketplace

Jambonz recipes

Skill jambonz/skills/skills/jambonz-recipes

Implementation recipes for jambonz voice app features. Use when writing code to build conversational voice AI agents (s2s, agent verb, vendor shortcuts, tool calling), collect input via IVR menus and gather, bridge or transfer calls (dial, SIP, queue, conference, recording, SIPREC), or configure applications via env_vars. Contains @jambonz/sdk JavaScript/TypeScript patterns (preferred) and raw-JSON examples for Python. Pair with the jambonz skill (decision-making) and the jambonz MCP server (schema lookups).From its SKILL.md

Install
npx -y skills add jambonz/skills --skill jambonz-recipes

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 4 stars4 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its file declares

Copied from the file, not written here

The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

6.3 KB, as published. Nobody here has run it

jambonz Implementation Recipes

This skill holds the runnable patterns for building jambonz voice apps. Use the parent jambonz skill to decide what to build and which transport to pick. Use this skill once you're writing code for a specific feature.

When to Load Each Reference

The four reference files below are loaded on-demand. Read only the ones relevant to the task.

  • references/voice-ai.md — Load when building s2s or cascaded agent-verb voice AI apps. Covers vendor shortcuts (OpenAI, Google, Deepgram, Ultravox, ElevenLabs), s2s vs agent trade-offs, tool/function calling, eventHook patterns, TTS token streaming.
  • references/ivr.md — Load when building IVR menus or gather-based input collection. Covers speech/DTMF/mixed input, multi-level menus, timeout and retry, default recognizer/synthesizer.
  • references/call-control.md — Load when building apps with dial, transfer, queuing, conference, recording, or mid-call control. Covers dial targets, SIP operations (sip-decline / sip-refer / sip-request), enqueue/dequeue, conference, REST API control, inject commands, SIPREC recording.
  • references/env-vars.md — Load when the app needs configurable parameters. Covers the two-step declare+read pattern, schema property types, the "only on initial call" gotcha, session.locals state.

Building the Application

With @jambonz/sdk (JavaScript or TypeScript — preferred)

Default to TypeScript when generating new code. Only emit JavaScript if the user explicitly asks for it. Both work with the same @jambonz/sdk package and the same imports — only file extensions and type annotations differ.

Install: npm install @jambonz/sdk (plus express for webhook apps).

Webhook pattern:

import express from 'express';
import { WebhookResponse } from '@jambonz/sdk/webhook';

const app = express();
app.use(express.json());

app.post('/incoming', (req, res) => {
  const jambonz = new WebhookResponse();
  jambonz.say({ text: 'Hello!' }).hangup();
  res.json(jambonz);
});

// Required: call status handler
app.post('/call-status', (req, res) => {
  console.log(`Call ${req.body.call_sid} status: ${req.body.call_status}`);
  res.sendStatus(200);
});

app.listen(3000);

WebSocket pattern:

import http from 'http';
import { createEndpoint } from '@jambonz/sdk/websocket';

const server = http.createServer();
const makeService = createEndpoint({ server, port: 3000 });
const svc = makeService({ path: '/' });

svc.on('session:new', (session) => {
  // Bind actionHook handlers BEFORE send()
  session.on('/gather-result', (evt) => {
    session.say({ text: `You said: ${evt.speech?.alternatives?.[0]?.transcript}` })
      .reply();  // reply() for all subsequent responses
  });

  session
    .gather({ input: ['speech'], actionHook: '/gather-result', timeout: 10,
      say: { text: 'Say something.' } })
    .send();  // send() — initial response only, exactly once
});

Critical SDK rules:

  • .send() — use ONCE for the initial verb array (response to session:new)
  • .reply() — use for ALL subsequent responses (actionHook events)
  • Bind actionHook handlers BEFORE calling .send()
  • Use session.locals for call-scoped state that persists across hooks
  • Use session.data.env_vars (WS) or req.body.env_vars (webhook) for configurable values — never process.env

Without the SDK (Python)

jambonz verbs are plain JSON. Python apps build jambonz apps by serving HTTP for webhooks (via Flask, FastAPI, etc.) or connecting via WebSocket for streaming. The verb JSON format is identical to what the TypeScript SDK produces.

Webhook: HTTP server receives POST with call data, returns JSON array of verbs:

[
  { "verb": "say", "text": "Hello!" },
  { "verb": "gather", "input": ["speech"], "actionHook": "/result", "timeout": 10,
    "say": { "text": "Say something." } }
]

WebSocket: Connect to jambonz WS endpoint, receive JSON messages, send JSON verb arrays back. See the WebSocket Protocol section of AGENTS.md (via the MCP jambonz_developer_toolkit tool) for the message format.

Use get_jambonz_schema from the jambonz MCP server to look up the exact JSON structure for any verb.

Both modes

  • Webhook apps must include a call-status POST handler (logs lifecycle events, returns 200).
  • Use jambonz application environment variables for configurable values — see references/env-vars.md.

Picking the Right Recipe

TaskReferenceMCP follow-up
Voice AI agent with one vendor (e.g. OpenAI Realtime)voice-ai.mdget_jambonz_schema("verb:openai_s2s")
Voice AI agent with runtime vendor selectionvoice-ai.mdget_jambonz_schema("verb:s2s")
LLM tool/function callingvoice-ai.mdget_sdk_example("agent")
Cascaded agent (STT + LLM + TTS as separate components)voice-ai.mdget_jambonz_schema("verb:agent")
Single-level IVRivr.mdget_jambonz_schema("verb:gather")
Multi-level menuivr.mdget_sdk_example("ivr-menu")
Bridge to phone number or SIP endpointcall-control.mdget_jambonz_schema("verb:dial")
Blind SIP transfercall-control.mdget_jambonz_schema("verb:sip-refer")
Call queueing with hold musiccall-control.mdget_sdk_example("queue-with-hold")
Conferencecall-control.mdget_jambonz_schema("verb:conference")
Recording (SIPREC)call-control.mdget_jambonz_schema("verb:siprec")
Mid-call control from RESTcall-control.mdget_jambonz_schema("component:command")
Runtime configuration via env_varsenv-vars.md(no schema needed — declare in app settings)

Keep looking

Skills are one crate of 627,801. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.