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.
Source installs and hosted beta
The repositories are public and support anonymous Git access. These guides install the SDKs from public Git. Anonymous registry checks on 20 September 2026 returned HTTP 404 for npm @vaanieal/observer and PyPI vaanieval-observer; no release was found under those names. Source availability does not mean the hosted service is ready for public launch: new public workspaces remain closed.
The quickstarts pin published Python 0.5.7b1 and Node 0.1.1-beta.1 source previews. Both installed previews have uploaded synthetic calls to the isolated hosted development environment. Git/build tooling and explicit revision upgrades are required; this is not registry publication or production-readiness certification.
For setup help, email shubham@vaanieval.com or book a call — a short conversation about your use case tells us whether Vaanieval fits, and helps identify 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.
Next
LiveKit Agents
Capture available LiveKit Agents spans, milestones and enabled audio using a mixin and recorder, with coverage and shutdown limitations.
Recording a call
The full Node.js recording surface — turns, operations, milestones, samples, audio attribution, websockets and AsyncLocalStorage context.