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

@hanzo/teams

v1.0.0

Published

Hanzo AI for Microsoft Teams — a Bot Framework app with chat, message extensions, and Adaptive Card actions, built on @hanzo/ai, @hanzo/iam, and @hanzo/cards.

Downloads

93

Readme

Hanzo AI for Microsoft Teams

A Bot Framework app that brings Hanzo AI into Microsoft Teams — the comms standard for enterprises and regulated, non-technical orgs. DM Hanzo or @mention it in a channel, run quick actions on any message ("Ask Hanzo"), or compose an AI draft — all answered by Hanzo AI and rendered as native Adaptive Cards.

It reuses the same backend and design as every other Hanzo surface: model calls go through api.hanzo.ai / /v1 via the headless @hanzo/ai client (never an /api/ path), identity is Hanzo IAM via @hanzo/iam, and every card is built from the shared canonical panel spec in @hanzo/cards — one PanelSpectoAdaptiveCard. No new API surface, no hand-written Adaptive Card JSON.

What it does

  • Chat — a DM or @Hanzo <prompt> in a channel runs a completion and replies with the Hanzo assistant panel (model picker, quick actions, prompt).
  • Quick actions — Draft reply, Summarize, Explain, Extract action items — as Adaptive Card buttons and as the "Ask Hanzo" message-action command on any message.
  • Compose — the "Compose with Hanzo" command generates an AI draft to insert while writing a message.
  • Adaptive Card actions — model picker (Input.ChoiceSet), quick-action buttons, and a prompt Input.Text + submit, all from @hanzo/cards.

Architecture

Teams  ──POST /api/messages──▶  server.ts (restify + CloudAdapter)
                                      │
                                      ▼
                                   bot.ts  (TeamsActivityHandler)
             ┌────────────────────────┼─────────────────────────┐
             ▼                        ▼                          ▼
        context.ts               dispatch.ts                 panels.ts
    (message/thread text)   (data.action → intent)   (PanelSpec → Adaptive Card
             │                        │                    via @hanzo/cards)
             └───────────┬────────────┘
                         ▼
                     hanzo.ts  ──▶  @hanzo/ai  ──▶  api.hanzo.ai /v1

Everything except server.ts (opens the socket) and bot.ts (wires botbuilder) is a pure module — dispatch, panels, context, hanzo, identity, config — so the routing, card assembly, and text extraction are unit-tested in isolation.

The Action.Submit dispatch flow

Every button and input in a Hanzo card comes from @hanzo/cards, which stamps a stable id onto each Action.Submit as data.action, and keys the inputs by ActionId.ModelSelect (hanzo_model_select) and PROMPT_INPUT_ID (hanzo_prompt). Teams returns that merged payload on submit, and dispatch(data) turns it into one typed CardIntent:

| data.action | Also carries | → CardIntent | | ----------------------------------- | ------------------------------------ | -------------------------------------- | | hanzo_sign_in | — | { kind: 'sign_in' } | | hanzo_model_select | hanzo_model_select = model id | { kind: 'model_select', model } | | hanzo_prompt_submit | hanzo_prompt, hanzo_model_select | { kind: 'prompt', prompt, model? } | | hanzo_quick_action:<chip> | chip, hanzo_prompt, model | { kind: 'quick_action', chip, … } | | anything else | — | { kind: 'unknown', action? } |

bot.ts receives the submit two ways and routes both through the same dispatch: a classic Action.Submit arrives as a message activity with activity.value set (handled in onMessage), and an Action.Execute arrives via onAdaptiveCardInvoke (invokeValue.action.data). One routing table, two entry points.

Requirements

  • Node 18+ and pnpm.
  • An Azure Bot registration (app id + secret) — see below.
  • A Hanzo API key (hk-…) with model access on api.hanzo.ai.

Configuration

All secrets come from the environment — nothing is committed. loadConfig (src/config.ts) reads and validates them at startup:

| Variable | Required | Default | Meaning | | ------------------------- | -------- | -------------------- | ---------------------------------------------------- | | MICROSOFT_APP_ID | yes | — | Azure Bot app id (botId). | | MICROSOFT_APP_PASSWORD | yes | — | Azure Bot client secret. | | HANZO_API_KEY | yes | — | Hanzo API key (bearer to api.hanzo.ai). | | MICROSOFT_APP_TYPE | no | MultiTenant | MultiTenant / SingleTenant / UserAssignedMSI. | | MICROSOFT_APP_TENANT_ID | no | "" | AAD tenant id (required for SingleTenant). | | HANZO_BASE_URL | no | https://api.hanzo.ai | Override the AI base URL (local dev). | | HANZO_MODELS | no | zen-eco-3b,zen-mini-8b,zen-4b | Comma-separated picker models. | | HANZO_DEFAULT_MODEL | no | first of HANZO_MODELS | Default model id. | | PORT | no | 3978 | HTTP port for the messaging endpoint. |

Develop

pnpm install          # from the monorepo root (workspace), or standalone here
pnpm typecheck        # tsc --noEmit
pnpm test             # vitest — pure logic (dispatch, panels, context, config, …)
pnpm build            # tsup → dist/ (library + runnable server)
pnpm start            # node dist/server.js  (needs the env above)

Run locally against Teams with a tunnel (e.g. devtunnel or ngrok) pointing at http://localhost:3978/api/messages.

Azure Bot registration

  1. In the Azure portalCreate a resourceAzure Bot. Choose a name and, for Type of App, Multi Tenant (or Single Tenant / MSI).
  2. Under Configuration, set the Messaging endpoint to your public URL: https://<your-host>/api/messages.
  3. Under Configuration → Microsoft App ID, copy the App IDMICROSOFT_APP_ID. Click ManageCertificates & secretsNew client secret → copy the value → MICROSOFT_APP_PASSWORD.
  4. Under Channels, add the Microsoft Teams channel.

Build & sideload the Teams app package

The Teams app package is a zip of manifest.json + color.png + outline.png. The build step substitutes ${{…}} placeholders from the environment and zips:

MICROSOFT_APP_ID=<your-bot-app-id> \
TEAMS_APP_ID=<a-guid-for-the-app> \   # optional; defaults to MICROSOFT_APP_ID
  pnpm package                        # → dist/hanzo-teams.zip

Then upload it one of two ways:

  • Developer Portal / Teams client — Teams → AppsManage your appsUpload an appUpload a custom app → pick dist/hanzo-teams.zip.
  • Teams Admin Center (org-wide) — Teams apps → Manage apps → Upload new app, then set the org/app permission policy so users can install it.

Manifest highlights (manifest/manifest.json)

  • Schema v1.16.
  • bots — scopes personal, team, groupChat (1:1, channel, group chat).
  • composeExtensionsaskHanzo (action, contexts message/compose/ commandBox, with the four quick actions as a choiceset) and composeHanzo (query, inserts an AI draft).
  • permissionsidentity, messageTeamMembers.
  • validDomainsapi.hanzo.ai, token.botframework.com.

Identity

Two supported models, both in src/identity.ts:

  1. Per-tenant key (default, complete out of the box) — the tenant is provisioned one HANZO_API_KEY; every Teams user acts as that Hanzo principal. The enterprise/regulated-org pattern.
  2. Per-user link — a Teams user presents a Hanzo IAM JWT (via Teams SSO); resolveFromToken validates it with @hanzo/iam and derives the Hanzo org from the sub (org/username) claim.

Deploy

Build the image in CI (ghcr.io/hanzoai/teams, --platform linux/amd64) and run it behind the platform ingress; set the Azure Bot Messaging endpoint to https://<host>/api/messages. Secrets (MICROSOFT_APP_*, HANZO_API_KEY) come from KMS, never from the image or the repo. GET /healthz is the readiness probe.