npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@mnemix-ai/bland-kit

v0.1.0

Published

Mnemix integration kit for Bland.ai voice pathways — pre-call enrichment + post-call memory write-back.

Downloads

35

Readme

@mnemix-ai/bland-kit

Mnemix integration kit for Bland.ai voice pathways. Pre-call enrichment + post-call memory write-back.

Why this exists

Bland builds production voice pathways. Mnemix is the memory and identity layer behind those pathways: every inbound call can resolve the caller through Twilio Lookup, Trestle, and Baylio before the first audio packet, then return variables your pathway can template into the first turn.

After the call, the kit writes a structured summary back to Mnemix so the next call starts with useful context. The kit is intentionally thin: it verifies Bland webhooks when configured, calls the three supported Mnemix v1 endpoints, builds pathway variables, and degrades to safe defaults when external data is unavailable.

Install

npm install @mnemix-ai/bland-kit @mnemix-ai/client

Quickstart: Cloudflare Worker

import { Mnemix } from "@mnemix-ai/client";
import {
  handleBlandPostCall,
  handleBlandPreCall,
  type BlandPostCallPayload,
  type BlandPreCallPayload,
} from "@mnemix-ai/bland-kit";

interface Env {
  MNEMIX_KEY: string;
  BLAND_WEBHOOK_SECRET?: string;
  MNEMIX_TENANT?: string;
}

export default {
  async fetch(req: Request, env: Env): Promise<Response> {
    if (req.method !== "POST") {
      return new Response("Method not allowed", { status: 405 });
    }

    const url = new URL(req.url);
    const rawBody = await req.text();
    const signature = req.headers.get("x-bland-signature") ?? undefined;
    const mnemix = new Mnemix({ apiKey: env.MNEMIX_KEY });
    const opts = {
      mnemix,
      blandWebhookSecret: env.BLAND_WEBHOOK_SECRET,
      tenantId: env.MNEMIX_TENANT,
    };

    if (url.pathname === "/bland/pre-call") {
      const payload = JSON.parse(rawBody) as BlandPreCallPayload;
      const ctx = await handleBlandPreCall(opts, payload, {
        signature,
        rawBody,
        tone: "warm",
        agentName: "the assistant",
      });
      return Response.json({ variables: ctx.variables, system_prompt: ctx.system_prompt });
    }

    if (url.pathname === "/bland/post-call") {
      const payload = JSON.parse(rawBody) as BlandPostCallPayload;
      return Response.json(await handleBlandPostCall(opts, payload));
    }

    return new Response("Not found", { status: 404 });
  },
};

Quickstart: Node Express

import express from "express";
import { Mnemix } from "@mnemix-ai/client";
import { handleBlandPostCall, handleBlandPreCall } from "@mnemix-ai/bland-kit";

const app = express();
app.use(express.text({ type: "application/json" }));

const mnemix = new Mnemix({ apiKey: process.env.MNEMIX_KEY! });

app.post("/bland/pre-call", async (req, res) => {
  const rawBody = req.body as string;
  const ctx = await handleBlandPreCall(
    {
      mnemix,
      blandWebhookSecret: process.env.BLAND_WEBHOOK_SECRET,
      tenantId: process.env.MNEMIX_TENANT,
    },
    JSON.parse(rawBody),
    {
      signature: req.header("x-bland-signature") ?? undefined,
      rawBody,
      tone: "warm",
    },
  );
  res.json({ variables: ctx.variables, system_prompt: ctx.system_prompt });
});

app.post("/bland/post-call", async (req, res) => {
  const result = await handleBlandPostCall({ mnemix }, JSON.parse(req.body as string));
  res.json(result);
});

app.listen(process.env.PORT ?? 8787);

Quickstart: Next.js App Router

// app/api/bland/[hook]/route.ts
import { Mnemix } from "@mnemix-ai/client";
import { handleBlandPostCall, handleBlandPreCall } from "@mnemix-ai/bland-kit";

const mnemix = new Mnemix({ apiKey: process.env.MNEMIX_KEY! });

export async function POST(
  req: Request,
  { params }: { params: { hook: string } },
) {
  const rawBody = await req.text();
  const opts = {
    mnemix,
    blandWebhookSecret: process.env.BLAND_WEBHOOK_SECRET,
    tenantId: process.env.MNEMIX_TENANT,
  };

  if (params.hook === "pre-call") {
    const ctx = await handleBlandPreCall(opts, JSON.parse(rawBody), {
      signature: req.headers.get("x-bland-signature") ?? undefined,
      rawBody,
      tone: "professional",
    });
    return Response.json({ variables: ctx.variables, system_prompt: ctx.system_prompt });
  }

  if (params.hook === "post-call") {
    return Response.json(await handleBlandPostCall(opts, JSON.parse(rawBody)));
  }

  return Response.json({ error: "unknown hook" }, { status: 404 });
}

What You Get Back

handleBlandPreCall() returns a BlandPreCallContext:

interface BlandPreCallContext {
  variables: {
    caller_name: string;
    is_returning: boolean;
    last_intent: string | null;
    last_call_summary: string | null;
    carrier: string | null;
    line_type: string | null;
    company: string | null;
    role: string | null;
    industry: string | null;
    suggested_intent: string | null;
  };
  system_prompt: string;
  mnemix: {
    trace_id: string;
    known: boolean;
    caller_id: string;
    memory_age_ms: number;
    timing_ms: { total: number; memory_ms: number; enrichment_ms: number };
  };
}

variables is the safe subset Bland should template into prompts and branch conditions. system_prompt is a ready-to-use prompt assembled from those variables. mnemix carries trace and timing data for logs, support, and debugging.

System Prompt Customization

import { buildSystemPrompt } from "@mnemix-ai/bland-kit";

const systemPrompt = buildSystemPrompt(ctx.variables, {
  tone: "warm", // "warm" | "professional" | "casual"
  agentName: "Avery",
  brandName: "Northstar Support",
  fallbackGreeting: "Hi there",
});

The builder does not invent missing history. If Mnemix returns no memory, the prompt tells the agent to ask rather than assume.

Webhook Signature Verification

Set BLAND_WEBHOOK_SECRET in your deployment and pass blandWebhookSecret to the kit. For pre-call webhooks, also pass the raw request body and the X-Bland-Signature header to handleBlandPreCall().

The kit verifies HMAC-SHA256 signatures through verifyBlandSignature(). If signature verification fails, the pre-call path returns a safe default context instead of exposing enriched caller data.

Graceful Degradation

Voice pathways should not block on enrichment. If Mnemix times out, returns a 5xx, receives a malformed phone number, or returns partial enrichment, the kit returns defaults such as caller_name: "there" and is_returning: false. Bland can continue the call while Mnemix logs the failure path.

Partial enrichment is still useful. For example, Twilio Lookup can supply carrier data while Trestle is unavailable, or Baylio can suggest a likely intent without a full profile.

Errors

BlandKitError is the base typed error for kit-level failures.

BlandKitSignatureError represents invalid Bland webhook signatures. The pre-call handler is designed to degrade safely; direct users of verifyBlandSignature() can throw or map this error according to their own policy.

Mnemix client errors are not wrapped unless the kit needs to add Bland-specific context.

Configuration

| Option | Required | Description | | --- | --- | --- | | mnemix | Yes | A Mnemix client constructed with your API key. | | blandWebhookSecret | No, recommended | Shared secret used to verify Bland webhook signatures. | | tenantId | No | Optional tenant override when one API key serves multiple tenants. | | recallTimeoutMs | No | Maximum time to wait before falling back to default pre-call context. | | logger | No | Logger with info, warn, and error; defaults to console. |

The 3 v1 Endpoints This Kit Calls

  • POST /v1/recall_and_enrich for pre-call memory and enrichment.
  • POST /v1/calls/end for post-call memory write-back.
  • GET /v1/caller/{phone_number} for optional out-of-band caller lookup.

The default API base URL is https://mnemix-api.sayeed965.workers.dev.

Privacy & Compliance

Phone numbers are normalized to E.164 before use. Audit logging stores a phone hash produced with HMAC-SHA256 over the tenant secret and normalized phone number. The kit sends caller context to Mnemix only; it does not send PII to OpenAI or Anthropic. If your agent sends transcripts to a model provider, redact or filter those transcripts in your application before write-back.

Mnemix supports GDPR-compliant access, deletion, and audit workflows. Keep your Bland retention settings, transcript storage, and recording URLs aligned with your own data processing agreements.

License

MIT