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

zehrava-gate-langchain

v0.1.0

Published

Wrap LangChain/LangGraph tools with Zehrava Gate governance — deterministic policy enforcement before any tool executes

Downloads

105

Readme

@zehrava/langchain-gate

Wrap LangChain tools and LangGraph graphs with Zehrava Gate — deterministic policy enforcement before any tool executes.

Every tool call becomes a governed intent. Gate evaluates it against your YAML policy (field checks, rate limits, environment thresholds) before the tool runs. No LLM in the policy path.

What Gate does here

  • Approved → the underlying tool executes normally
  • BlockedGateBlockedError is thrown (or your onBlocked handler runs)
  • Pending approval → polls until a human approves, rejects, or your timeoutMs expires

Gate does not rewrite the LangChain API, add latency on auto-approved calls (< 5ms), or require changes to your tool logic.

Install

npm install @zehrava/langchain-gate zehrava-gate
npm install @langchain/core          # peer dep
npm install @langchain/langgraph     # only if using graph hooks

Run Gate locally:

npx zehrava-gate start --api-key gate_sk_...

Wrap a single tool

const { Gate } = require('zehrava-gate');
const { GateTool, GateBlockedError } = require('@zehrava/langchain-gate');

const gate = new Gate({ apiUrl: 'http://localhost:3001', apiKey: 'gate_sk_...' });

const governed = new GateTool({
  tool: emailTool,          // your existing LangChain Tool
  gate,
  policy: 'outbound-email', // YAML policy ID in Gate
  destination: 'sendgrid.send',
});

try {
  const result = await governed._call(JSON.stringify({ to: '[email protected]', subject: '...' }));
} catch (err) {
  if (err instanceof GateBlockedError) {
    console.error('Blocked:', err.intentId, err.blockReason);
  }
}

Wrap multiple tools (GateToolkit)

const { GateToolkit } = require('@zehrava/langchain-gate');

const toolkit = new GateToolkit({
  tools: [emailTool, crmTool, slackTool],
  gate,
  policies: {
    'send-email':  'outbound-email',
    'crm-update':  'crm-low-risk',
    '__default__': 'crm-low-risk',   // fallback for unmapped tools
  },
  destinations: {
    'send-email':  'sendgrid.send',
    'crm-update':  'salesforce.api',
    '__default__': 'generic.http',
  },
});

const governedTools = toolkit.getTools(); // drop-in for your agent's tools list

LangGraph integration

Gate provides two primitives for StateGraph:

gateNode — submit intent as a graph node

const { StateGraph, END } = require('@langchain/langgraph');
const { gateNode, gateRouteAfter } = require('@zehrava/langchain-gate');

const graph = new StateGraph({ channels: { ... } });

graph.addNode('submit_to_gate', gateNode({
  gate,
  buildIntent: (state) => ({
    payload: JSON.stringify(state.payload),
    destination: 'salesforce.api',
    policy: 'crm-low-risk',
    recordCount: state.records.length,
  }),
}));

// gateNode writes: state.gateIntentId, state.gateStatus, state.gateBlockReason

gateRouteAfter — conditional edge based on Gate's decision

graph.addConditionalEdges('submit_to_gate', gateRouteAfter('gateStatus'), {
  execute:  'run_crm_tool',      // status === 'approved'
  blocked:  'handle_blocked',    // status === 'blocked' | 'duplicate_blocked'
  pending:  'notify_human',      // status === 'pending_approval'
  __end__:  END,
});

Full working example: examples/langgraph-crm-agent.js

Options

GateTool options

| Option | Type | Default | Description | |---|---|---|---| | tool | Tool | required | LangChain Tool to wrap | | gate | Gate | required | Gate SDK client | | policy | string | required | Policy ID | | destination | string | required | Destination string | | toolOptions.idempotencyKeyFn | (input) => string | none | Derive idempotency key from input | | toolOptions.onBlocked | (id, reason) => any | throws | Override default throw on block | | toolOptions.onPending | (id, status, count) => void | none | Called each poll cycle | | toolOptions.autoExecute | boolean | false | Report execution result back to Gate | | toolOptions.pollIntervalMs | number | 5000 | Polling interval (ms) | | toolOptions.timeoutMs | number | 300000 | Max wait for approval (ms) |

Error classes

const { GateBlockedError, GatePendingError, GateTimeoutError } = require('@zehrava/langchain-gate');

try {
  await governed._call(input);
} catch (err) {
  if (err instanceof GateBlockedError) {
    // err.intentId, err.blockReason
  }
  if (err instanceof GateTimeoutError) {
    // err.intentId, err.timeoutMs — human didn't approve in time
  }
  if (err instanceof GatePendingError) {
    // err.intentId — thrown if you poll manually and it's still pending
  }
}

What Gate does not do

Gate is a deterministic policy engine, not an LLM-based moderator.

  • It does not understand natural language in payloads
  • It does not catch every possible bad action — write explicit policies for what matters
  • It protects against mistakes and unauthorized actions, not against a model that modifies the policy files it governs
  • Self-hosted only — your credentials never leave your infrastructure

Links