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

@northbound-run/chat-adapter-matrix-agent

v0.7.0

Published

Matrix adapter for the Vercel Chat SDK. Works with any Chat SDK host (Mastra, bare Chat SDK, etc.) via a single createMatrixAgentAdapter().

Readme

@northbound-run/chat-adapter-matrix-agent

Matrix adapter for the Vercel Chat SDK. Sibling to @chat-adapter/slack, @chat-adapter/discord, @chat-adapter/telegram — drop it into any Chat SDK host (Mastra, bare Chat SDK, or custom bot framework) and it covers every platform AgentChannels' Matrix substrate bridges: Slack, Telegram, Discord, Signal, WhatsApp, iMessage, plain Matrix.

Overview

Implements the chat@^4.24 Adapter<TThreadId, TRawMessage> interface. One platform-agnostic createMatrixAgentAdapter() reads Matrix sync events and dispatches them to the Chat SDK's ChatInstance.processMessage; outbound operations delegate to @northbound-run/matrix-agent-sdk.

Because AgentChannels' Matrix substrate normalizes every bridged platform into m.room.message events, a single adapter instance handles everything the official @chat-adapter/* packages cover — plus Signal, WhatsApp, and iMessage, which Vercel Chat SDK does not ship adapters for.

Quick Start

With bare Chat SDK

import { Chat } from "chat";
import { AgentChannelsMatrixClient } from "@northbound-run/matrix-agent-sdk";
import { createMatrixAgentAdapter } from "@northbound-run/chat-adapter-matrix-agent";

const matrix = new AgentChannelsMatrixClient({
  accessToken: process.env.MATRIX_ACCESS_TOKEN!,
  userId: process.env.MATRIX_USER_ID!,
  homeserverUrl: "https://matrix.agentchannels.dev",
});
await matrix.start();

const bot = new Chat({
  userName: "support-bot",
  adapters: {
    matrix: createMatrixAgentAdapter({ client: matrix }),
  },
});

bot.onNewMention(async (thread, message) => {
  await thread.post(`You said: ${message.text}`);
});

With Mastra

import { Agent } from "@mastra/core/agent";
import { Mastra } from "@mastra/core";
import { AgentChannelsMatrixClient } from "@northbound-run/matrix-agent-sdk";
import { createMatrixAgentAdapter } from "@northbound-run/chat-adapter-matrix-agent";

const matrix = new AgentChannelsMatrixClient({
  accessToken: process.env.MATRIX_ACCESS_TOKEN!,
  userId: process.env.MATRIX_USER_ID!,
  homeserverUrl: "https://matrix.agentchannels.dev",
});
await matrix.start();

export const supportAgent = new Agent({
  id: "support-agent",
  name: "Support Agent",
  instructions: "You are a helpful support assistant.",
  model: "openai/gpt-4.1-mini",
  channels: {
    adapters: {
      matrix: createMatrixAgentAdapter({ client: matrix }),
    },
  },
});

export const mastra = new Mastra({ agents: { supportAgent } });

Invite the bot to a Matrix room bridged to your target platform. Every @bot-mention surfaces on the Chat SDK's event handlers (onNewMention / onSubscribedMessage); replies are posted back through the bridge.

See examples/mastra-basic.ts for a full runnable Mastra fixture.

Installation

bun add @northbound-run/chat-adapter-matrix-agent
# or
npm install @northbound-run/chat-adapter-matrix-agent

Peers required:

  • chat ^4.24 — the Vercel Chat SDK.
  • @mastra/core ^1.22optional. Only needed when consumed from Mastra; skip it for bare Chat SDK apps.

Workspace runtime dep (managed):

  • @northbound-run/matrix-agent-sdk — provides the AgentChannelsMatrixClient.

Configuration

The adapter accepts a single MatrixAgentAdapterOptions record:

| Field | Type | Default | Description | |---|---|---|---| | client | AgentChannelsMatrixClient | — | BYO Matrix client (already .start()-ed). If omitted, the adapter constructs one from credentials / env vars / FileStore. | | credentials | StoredCredentials | — | Explicit {accessToken, userId, deviceId?, homeserverUrl}. Ignored when client is set. | | homeserverUrl | string | https://matrix.agentchannels.dev | Override the SDK default. | | storePath | string | ~/.matrix-agent | Override the SDK's FileStore location. | | userName | string | MXID localpart | Bot username surfaced to the Chat SDK. | | bridgeBotFilter | string[] \| (userId: string) => boolean | SDK's isBridgeBotMxid | Override the echo filter. A string array filters by exact MXID; a function is called per sender. | | inlineMediaMimePatterns | string[] | [] | MIME patterns to resolve inline (planned for richer attachment handling). | | lockScope | "thread" \| "channel" | "thread" | Mapped 1:1 to the Chat SDK Adapter.lockScope. Use "channel" for WhatsApp/Telegram-style serialization. | | approvalTimeoutMs | number | 300_000 (5 min) | How long a requireApproval: true tool gate waits before auto-denying. | | logger | chat.Logger | undefined | Chat SDK logger. Receives warn/error strings for reconnect and rate-limit events. |

API Reference

createMatrixAgentAdapter(options)

Factory returning a MatrixAgentAdapter — assignable to Adapter<MatrixThreadData, MatrixRawMessage>.

MatrixAgentAdapter

Implements the Vercel Chat SDK Adapter contract. See Not Implemented in V1 for the methods deliberately absent.

Thread-ID codec

import {
  encodeThreadId,
  decodeThreadId,
  channelIdFromThreadId,
  threadDataFromMessage,
  TOP_LEVEL_ROOT,
} from "@northbound-run/chat-adapter-matrix-agent";

Thread IDs are matrix:<base64url(roomId)>:<rootEventId | "top">. The codec splits on the first two colons only, so Matrix event IDs (shape $hash:server, which contain colons) round-trip intact.

Format translation

import { renderFormatted, htmlToMdast } from "@northbound-run/chat-adapter-matrix-agent";

renderFormatted(mdast);      // { html, plain }
htmlToMdast(matrixHtml);     // mdast Root

Matrix HTML whitelist: <b>/<strong>, <i>/<em>, <code>, <pre><code>, <a href>, <ul>/<ol>/<li>, <blockquote>, <br>. Unknown tags and entities outside the five canonical ones are dropped.

Channel / DM classification

import { ChannelVisibilityResolver, classifyRoom } from "@northbound-run/chat-adapter-matrix-agent";

Slack rooms go through the Beeper m.bridge state event. Everything else falls back to a 2-member-joined-room heuristic. Signal / WhatsApp / Telegram / iMessage / Discord bridges that adopt the Beeper convention automatically participate via the SDK's SUPPORTED_BRIDGE_PROTOCOLS set.

Approval state machine

import { ApprovalRegistry, APPROVE_PATTERNS, DENY_PATTERNS } from "@northbound-run/chat-adapter-matrix-agent";

Tools marked requireApproval: true post a plain-text prompt like 🔐 Approval needed for <toolName>: <preview>. Reply "approve" / "yes" / 👍 or "deny" / "no" / 👎 within 5 minutes.. Replies are matched FIFO per thread. Non-matching replies pass through to the agent as a normal turn.

Error Handling

Outbound operations emit every error type @northbound-run/matrix-agent-sdk defines: AuthError, TokenExpiredError, RateLimitError, NetworkError, RoomNotFoundError, InsufficientPowerLevelError, etc. See matrix-agent-sdk's README for the full taxonomy.

The adapter auto-retries RateLimitError once when retryAfterMs <= 30000; longer waits rethrow so the Chat SDK's concurrency / onLockConflict hooks can decide what to do.

Runtime

  • Bun (primary) and Node 22+.
  • The package emits pure ESM ("type": "module"); CJS consumers need a wrapper.
  • Requires a long-running host. Sync-loop mode holds a persistent Matrix connection; Vercel Functions / Netlify Functions / Cloudflare Workers are not supported in V1.

Not Implemented in V1

The following optional Chat SDK Adapter methods are deliberately absent. The Chat SDK handles missing optional methods gracefully — see the Chat SDK docs for the fallback each triggers.

| Method | Why absent | V2 plan | |---|---|---| | scheduleMessage | Matrix has no native scheduled-send primitive. | Client-side timer + postMessage at the scheduled time. | | postObject / editObject | Plans / Polls render to platform-native Block Kit / inline keyboards; Matrix has no equivalent. | Render to Matrix HTML with reaction-based voting. | | rehydrateAttachment | Only relevant for concurrency: "queue" / "debounce" workloads where attachments are serialized. | Lift the fetch-closure out of parseMessage so rehydration works via roomId + mxc. | | native stream | Slack-specific streaming API. | m.in_reply_to edit-based streaming with update throttling. | | openModal | Matrix has no Block Kit modal equivalent. | Reaction-based approval cards (👍/👎 on a proposal message). | | postEphemeral | Matrix has no ephemeral-visibility primitive. | Silent DM fallback via openDM + postMessage. |

V1 Known Limitations

  • End-to-end encrypted rooms — the adapter early-returns on m.room.encrypted events with a warn log; sends into encrypted rooms will fail. Invite the bot only to unencrypted rooms until matrix-agent-sdk gains E2EE support.
  • Serverless hosts — the sync-loop model requires a long-running process.
  • Legacy m.in_reply_to — Matrix replies outside the modern threading model route into the main timeline (no thread ID derived). Reply context is preserved on Message.raw.normalized.replyTo for advanced consumers.

Tier

Community adapter. The @chat-adapter/* npm scope is reserved for Vercel's official adapters. This package publishes under our own @northbound-run/* scope.

License

MIT