Overview
Installing and configuring the VaaniEval Node.js SDK — options, defaults, automatic fetch instrumentation and the upload API.
@vaanieal/observer is a zero-dependency, pure-ESM package that records
voice-agent calls to a local session package and uploads them after the call.
VaaniEval is in closed beta
The repositories below are private while the product is in closed beta, so the links will 404 unless your GitHub account has been granted access. Neither SDK is published to a public package registry yet — both install from Git.
To get access, email shubham@vaanieval.com or book a call — a short conversation about your use case tells us whether VaaniEval fits, and gets you onboarded with the setup that matches your stack.
Install
npm install github:shubhamofbce/vaanieval-observer-nodejs-sdkRequires Node.js 20 or newer. The package is ESM-only and uses only Node
built-ins — node:async_hooks, node:fs/promises, node:crypto,
node:perf_hooks. Nothing else enters your dependency tree.
{
"type": "module"
}Pin a commit or tag in production
(github:shubhamofbce/vaanieval-observer-nodejs-sdk#v0.1.0). Installing from a
moving branch means a redeploy can change your instrumentation without a
version bump.
Constructing the observer
import { VaaniObserver } from '@vaanieal/observer';
const vaani = new VaaniObserver({
endpoint: 'http://localhost:8000',
apiKey: 'local-dev',
spoolDirectory: './.vaani-spool',
capture: { audio: true, httpBodies: false },
instrumentations: { fetch: true, websocket: true },
endpoints: [
{ id: 'stt', type: 'stt', url: 'wss://api.deepgram.com/v1/listen' },
{ id: 'llm', type: 'llm', url: 'https://api.openai.com/v1' },
{ id: 'tts', type: 'tts', url: 'https://api.elevenlabs.io' },
],
upload: { retries: 3 },
strict: false,
});Prop
Type
Constructing the observer patches global fetch immediately. It performs no
network I/O. Construct it once at process start.
Because fetch is a global, constructing more than one observer in a process
stacks patches. Create exactly one and share it.
Lifecycle
Start a session per call
const session = vaani.startSession({ agentId: 'support-bot', metadata: { env: 'prod' } });End the session
const finalized = await session.end({ outcome: 'completed' });
console.log(finalized.directory, finalized.sessionId);Closes open spans, composes stereo audio, writes manifest.json last.
Upload
await vaani.uploadPackage(finalized);Requires endpoint and apiKey — it throws if either is missing. If you skip
this, the package simply stays on disk.
Flush at shutdown
process.on('SIGTERM', async () => {
await vaani.flush();
process.exit(0);
});Finalizes every open session. Finalization errors reject, matching
Promise.all semantics — a package that could not be written is visible, not
swallowed.
Observer API
| Method | Purpose |
|---|---|
startSession(input) | Open a session (sessionId, agentId, metadata) |
flush() | Finalize all open sessions |
run(session, fn) | Install ambient context |
runWithEndpoint(session, endpointId, fn, turnId) | Force an endpoint rule |
runWithTurn(session, turnId, fn) | Tag ambient work with a turn |
currentContext() | Read the ambient context |
classifyUrl(url) | Which endpoint rule a URL matches |
observeWebSocket(socket, options) | Observe a socket; returns { detach } |
uploadPackage(finalized) | Upload a written package |
Automatic fetch instrumentation
A patched fetch is recorded only when there is an ambient session and the
URL matches one of your endpoint rules:
await session.run(async () => {
await fetch('https://api.openai.com/v1/chat/completions', { method: 'POST', body });
});Everything else passes through untouched — your database, your feature flag service, your own APIs.
Streaming response bodies are never drained to capture them. Reading a
stream to inspect it would hold back the first token, which is exactly the
latency this SDK exists to measure. httpBodies: true captures non-streaming
bodies only.
Failure behaviour
With strict: false (the default), instrumentation errors are swallowed.
Recording problems surface as capture_status counters in the manifest and as
the unverifiable class in the dashboard. Set strict: true in staging so those
failures throw.
Spool directories are not removed after a successful upload. Add a cleanup
sweep of .vaani-spool to your deployment, or audio will accumulate on your
agent hosts indefinitely.