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

@agentshieldhq/langchain

v1.0.0

Published

AgentShield LangChain integration — callback handler for AI agent policy governance

Readme

@agentshieldhq/langchain

npm version license TypeScript

LangChain callback handler for AI agent policy governance. Automatically intercepts tool calls and evaluates them through AgentShield's policy engine.

Installation

npm install @agentshieldhq/langchain

Peer dependency: langchain >= 0.1.0 (optional — the handler works with any callback system that calls handleToolStart / handleToolEnd).

Quick Start

Embedded Mode (No Server Needed)

import { AgentShieldCallbackHandler } from '@agentshieldhq/langchain';
import { AgentExecutor } from 'langchain/agents';

const handler = new AgentShieldCallbackHandler({
  mode: 'embedded',
  policies: [
    {
      policyId: 'POL-001',
      name: 'Block SQL DROP',
      agentRole: 'DataAgent',
      resource: 'PostgreSQL',
      action: 'DROP',
      permissionLevel: 'BLOCK',
      priority: 20,
      enabled: true,
    },
    {
      policyId: 'POL-002',
      name: 'Require approval for writes',
      agentRole: 'DataAgent',
      resource: 'PostgreSQL',
      action: 'WRITE',
      permissionLevel: 'REQUIRE_APPROVAL',
      priority: 10,
      enabled: true,
    },
  ],
  defaultAgentRole: 'DataAgent',
  toolNameMap: { 'sql_db_query': 'PostgreSQL' },
});

// Attach to an AgentExecutor
const executor = AgentExecutor.fromAgentAndTools({
  agent,
  tools,
  callbacks: [handler],
});

Hosted Mode (Connects to Server)

import { AgentShieldCallbackHandler } from '@agentshieldhq/langchain';

const handler = new AgentShieldCallbackHandler({
  serverUrl: 'https://agentshield.example.com',
  mode: 'hosted',
  apiKey: 'sk-...',
  defaultAgentRole: 'CodeAgent',
  onBlock: 'return',
  onRequireApproval: 'allow',
});

const executor = AgentExecutor.fromAgentAndTools({
  agent,
  tools,
  callbacks: [handler],
});

With LangGraph

const handler = new AgentShieldCallbackHandler({
  mode: 'embedded',
  policies: [/* ... */],
  defaultAgentRole: 'ResearchAgent',
});

const result = await graph.invoke(
  { messages: [/* ... */] },
  { callbacks: [handler] }
);

Configuration

AgentShieldLangChainConfig

Extends the base AgentShieldConfig with LangChain-specific options:

interface AgentShieldLangChainConfig extends AgentShieldConfig {
  /** What to do when a tool call is blocked.
   *  - 'throw' — throw AgentShieldBlockError (default)
   *  - 'return' — replace tool output with block message
   */
  onBlock?: 'throw' | 'return';

  /** What to do when a tool call requires approval.
   *  - 'throw' — throw AgentShieldApprovalError (default)
   *  - 'return' — replace tool output with approval message
   *  - 'allow' — let the tool call through (async approval workflow)
   */
  onRequireApproval?: 'throw' | 'return' | 'allow';

  /** Custom block message template.
   *  Variables: {toolName}, {reason}, {agentRole}
   *  @default 'Tool call blocked by AgentShield: {toolName} - {reason}'
   */
  blockMessage?: string;

  /** Custom approval message template.
   *  Variables: {toolName}, {reason}, {approvalRequestId}, {agentRole}
   *  @default 'Tool call requires approval: {toolName} - {reason} (Request: {approvalRequestId})'
   */
  approvalMessage?: string;

  /** Map LangChain tool names to AgentShield resource names.
   *  e.g., { 'sql_db_query': 'PostgreSQL', 'requests_get': 'HTTPClient' }
   */
  toolNameMap?: Record<string, string>;

  /** Map LangChain agent names to AgentShield agent roles.
   *  e.g., { 'sql-agent': 'DataAgent' }
   *  Checked against metadata/tags passed in handleToolStart.
   */
  agentRoleMap?: Record<string, string>;

  /** Default agent role if none can be inferred.
   *  @default 'DefaultAgent'
   */
  defaultAgentRole?: string;

  /** Callback invoked after every evaluation.
   *  Useful for logging, metrics, or custom side effects.
   */
  onEvaluate?: (event: AgentShieldEvent) => void;
}

Base Config (from AgentShield)

These fields are also available since AgentShieldLangChainConfig extends AgentShieldConfig:

| Field | Type | Description | |---|---|---| | mode | 'hosted' \| 'embedded' | Operating mode (auto-detected if omitted) | | serverUrl | string | Server URL for hosted mode | | apiKey | string | API key for hosted mode | | policies | Policy[] | Initial policies for embedded mode | | zeroTrust | boolean | Default deny when no policy matches (default: true) | | fetch | typeof fetch | Custom fetch function (edge runtime, etc.) |

Tool Name Mapping

Map LangChain tool names to the resource names used in your policies:

const handler = new AgentShieldCallbackHandler({
  mode: 'embedded',
  policies: [
    {
      policyId: 'POL-001',
      name: 'Block SQL DROP',
      agentRole: 'DataAgent',
      resource: 'PostgreSQL',  // <-- policies reference this name
      action: 'DROP',
      permissionLevel: 'BLOCK',
      priority: 20,
      enabled: true,
    },
  ],
  toolNameMap: {
    'sql_db_query': 'PostgreSQL',       // LangChain tool -> AgentShield resource
    'sql_db_schema': 'PostgreSQL',
    'requests_get': 'HTTPClient',
  },
});

Agent Role Mapping

Map LangChain agent names to AgentShield roles using metadata or tags:

const handler = new AgentShieldCallbackHandler({
  mode: 'embedded',
  policies: [/* ... */],
  agentRoleMap: {
    'sql-agent': 'DataAgent',
    'code-agent': 'CodeAgent',
    'research-agent': 'ResearchAgent',
  },
  defaultAgentRole: 'DefaultAgent',
});

Evaluation Callback

Hook into every evaluation for logging, metrics, or side effects:

const handler = new AgentShieldCallbackHandler({
  mode: 'embedded',
  policies: [/* ... */],
  onEvaluate: (event) => {
    console.log(`[${event.result.decision}] ${event.agentRole} -> ${event.toolName}`);
    // Send to your observability platform
    metrics.increment(`agentshield.${event.result.decision.toLowerCase()}`);
  },
});

The AgentShieldEvent object contains:

| Field | Type | Description | |---|---|---| | result | EvaluateResult | The evaluation result from AgentShield | | toolName | string | The LangChain tool name | | shieldResource | string | The AgentShield resource name (after mapping) | | agentRole | string | The resolved agent role | | args | Record<string, unknown> | The arguments passed to the tool | | timestamp | Date | When the evaluation occurred |

Error Classes

AgentShieldBlockError

Thrown when a tool call is blocked and onBlock is 'throw' (default).

import { AgentShieldBlockError } from '@agentshieldhq/langchain';

try {
  // ... agent execution
} catch (error) {
  if (error instanceof AgentShieldBlockError) {
    console.log(error.toolName);     // 'sql_db_query'
    console.log(error.agentRole);    // 'DataAgent'
    console.log(error.result);       // EvaluateResult object
    console.log(error.result.reason); // 'Blocked by policy: Block SQL DROP'
  }
}

Properties:

| Property | Type | Description | |---|---|---| | result | EvaluateResult | The evaluation result that caused the block | | toolName | string | The tool name that was blocked | | agentRole | string | The agent role that was blocked |

AgentShieldApprovalError

Thrown when a tool call requires approval and onRequireApproval is 'throw' (default).

import { AgentShieldApprovalError } from '@agentshieldhq/langchain';

try {
  // ... agent execution
} catch (error) {
  if (error instanceof AgentShieldApprovalError) {
    console.log(error.toolName);                   // 'sql_db_query'
    console.log(error.agentRole);                  // 'DataAgent'
    console.log(error.result.approvalRequestId);   // 'APR-abc123'
  }
}

Properties:

| Property | Type | Description | |---|---|---| | result | EvaluateResult | The evaluation result that triggered the approval | | toolName | string | The tool name that requires approval | | agentRole | string | The agent role that requires approval |

Utility Methods

toCallbacks()

Get the handler as a plain callback object for LangChain compatibility:

const handler = new AgentShieldCallbackHandler({ /* ... */ });

// Use as a plain object instead of class instance
const callbacks = handler.toCallbacks();

getShield()

Access the underlying AgentShield instance for direct operations:

const handler = new AgentShieldCallbackHandler({
  mode: 'embedded',
  policies: [/* ... */],
});

// Add policies at runtime
handler.getShield().addPolicy({
  policyId: 'POL-DYN',
  name: 'Runtime policy',
  agentRole: 'DataAgent',
  resource: 'PostgreSQL',
  action: 'DROP',
  permissionLevel: 'BLOCK',
  priority: 50,
  enabled: true,
});

// Check health
const healthy = await handler.getShield().isHealthy();

API Reference

AgentShieldCallbackHandler

LangChain-compatible callback handler that intercepts tool calls and evaluates them through AgentShield.

Constructor

new AgentShieldCallbackHandler(config?: AgentShieldLangChainConfig)

If mode is not specified, it defaults to 'embedded' unless serverUrl is provided.

Callback Methods (LangChain Interface)

| Method | Description | |---|---| | handleToolStart(tool, input, runId?, parentRunId?, tags?, metadata?, kwargs?) | Evaluates the tool call before execution | | handleToolEnd(output, runId?, parentRunId?, tags?) | Replaces output if the call was intercepted | | handleToolError(error, runId?, parentRunId?, tags?) | Cleans up interception state on error |

Utility Methods

| Method | Returns | Description | |---|---|---| | toCallbacks() | Record<string, unknown> | Get handler as a plain callback object | | getShield() | AgentShield | Access the underlying AgentShield instance |

Re-exported Types

All core types are re-exported for convenience:

import type {
  Decision,
  Policy,
  PolicyDefinition,
  EvaluateRequest,
  EvaluateResult,
  MatchedPolicy,
  ConditionRule,
  Trace,
} from '@agentshieldhq/langchain';

Related Packages

License

MIT