@reallyartificial/approval-protocol-langchain
v0.1.1
Published
LangChain integration for Approval Protocol — wrap any tool with human-in-the-loop approval.
Downloads
227
Maintainers
Readme
@reallyartificial/approval-protocol-langchain
LangChain integration for Approval Protocol — wrap any tool with human-in-the-loop approval.
One function call. Full lifecycle. Drop-in replacement.
Install
npm install @reallyartificial/approval-protocol-langchain @reallyartificial/approval-protocol-coreQuickstart
import { DynamicStructuredTool } from "@langchain/core/tools";
import { ApprovalClient } from "@reallyartificial/approval-protocol-core";
import { approvalTool } from "@reallyartificial/approval-protocol-langchain";
import { z } from "zod";
// Your existing LangChain tool
const sendEmail = new DynamicStructuredTool({
name: "send_email",
description: "Send an email to a customer",
schema: z.object({
to: z.string(),
body: z.string(),
}),
func: async ({ to, body }) => {
// actual send logic
return `Email sent to ${to}`;
},
});
// Wrap it with Approval Protocol
const client = new ApprovalClient("http://localhost:4000");
const safeSendEmail = approvalTool(sendEmail, {
client,
agent: "support-agent",
risk: { reversible: false, blast_radius: "external" },
undo: { type: "manual", description: "Contact recipient to disregard" },
});
// Use safeSendEmail anywhere you'd use the original tool.
// It's a drop-in replacement — same name, description, and schema.What It Does
approvalTool wraps a LangChain StructuredTool with the full Approval Protocol lifecycle:
invoke(input)
-> ap/request (ask for approval)
-> waitForDecision (poll until human decides)
-> tool.invoke() (run the original tool)
-> ap/confirm (report result + undo info)
-> return resultThe wrapped tool is a standard DynamicStructuredTool — it works in any LangChain agent (ReAct, OpenAI Functions, custom chains, etc.) with no changes to your agent code.
API
approvalTool(tool, config)
Returns a new DynamicStructuredTool with the same name, description, and schema.
Parameters:
| Param | Type | Description |
|-------|------|-------------|
| tool | StructuredToolInterface | The LangChain tool to wrap |
| config | ApprovalToolConfig | Configuration (see below) |
ApprovalToolConfig:
| Field | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| client | ApprovalClient | Yes | — | AP client pointed at your server |
| agent | string | Yes | — | Agent identifier for AP requests |
| risk | ApRiskMetadata | No | — | Risk metadata attached to every request |
| undo | ApUndoMetadata | No | — | Undo instructions sent on confirm |
| timeout | number | No | 300 | Seconds to wait for human decision |
| pollInterval | number | No | 1000 | Milliseconds between status polls |
Error Classes
ApprovalDeniedError — Thrown when the human denies the request (or it's auto-denied by policy).
import { ApprovalDeniedError } from "@reallyartificial/approval-protocol-langchain";
try {
await safeSendEmail.invoke({ to: "[email protected]", body: "Hello" });
} catch (err) {
if (err instanceof ApprovalDeniedError) {
console.log(`Denied: ${err.reason}`); // "Too risky"
console.log(err.requestId); // "req_abc123"
}
}ApprovalDryRunResult — Thrown when the policy specifies dry_run execution mode. The tool is not executed.
import { ApprovalDryRunResult } from "@reallyartificial/approval-protocol-langchain";
try {
await wrappedTool.invoke(input);
} catch (err) {
if (err instanceof ApprovalDryRunResult) {
console.log(`Dry run for ${err.toolName}, request ${err.requestId}`);
}
}Behavior by Status
| AP Response | What Happens |
|-------------|-------------|
| auto_approved | Tool executes immediately, result confirmed |
| pending → approved | Waits for human, then executes and confirms |
| pending → denied | Throws ApprovalDeniedError |
| pending → expired | Throws Error (timeout) |
| auto_denied | Throws ApprovalDeniedError |
| dry_run mode | Confirms without executing, throws ApprovalDryRunResult |
| Tool throws | Confirms failure to AP, then re-throws original error |
Peer Dependencies
| Package | Version |
|---------|---------|
| @langchain/core | >= 0.3.0 |
| @reallyartificial/approval-protocol-core | >= 0.1.0 |
Related
- @reallyartificial/approval-protocol-core — The core protocol: server, client, policies, channels.
- PROTOCOL.md — Full protocol specification.
License
MIT
