langchain-middleware

langchain-ai/langchain-skills · updated Apr 8, 2026

$npx skills add https://github.com/langchain-ai/langchain-skills --skill langchain-middleware
0 commentsdiscussion
summary

Human-in-the-loop approval, custom middleware, and structured output patterns for LangChain agents.

  • HumanInTheLoopMiddleware pauses execution before dangerous tool calls, allowing humans to approve, edit arguments, or reject with feedback
  • Per-tool interrupt policies let you configure different approval rules based on risk level; requires a checkpointer and thread_id for state persistence
  • Command resume pattern continues execution after human decisions, with support for editing tool a
skill.md
  • HumanInTheLoopMiddleware / humanInTheLoopMiddleware: Pause before dangerous tool calls for human approval
  • Custom middleware: Intercept tool calls for error handling, logging, retry logic
  • Command resume: Continue execution after human decisions (approve, edit, reject)

Requirements: Checkpointer + thread_id config for all HITL workflows.


Human-in-the-Loop

@tool def send_email(to: str, subject: str, body: str) -> str: """Send an email.""" return f"Email sent to {to}"

agent = create_agent( model="gpt-4.1", tools=[send_email], checkpointer=MemorySaver(), # Required for HITL middleware=[ HumanInTheLoopMiddleware( interrupt_on={ "send_email": {"allowed_decisions": ["approve", "edit", "reject"]}, } ) ], )

</python>
<typescript>
Set up an agent with HITL that pauses before sending emails for human approval.
```typescript
import { createAgent, humanInTheLoopMiddleware } from "langchain";
import { MemorySaver } from "@langchain/langgraph";
import { tool } from "@langchain/core/tools";
import { z } from "zod";

const sendEmail = tool(
  async ({ to, subject, body }) => `Email sent to ${to}`,
  {
    name: "send_email",
    description: "Send an email",
    schema: z.object({ to: z.string(), subject: z.string(), body: z.string() }),
  }
);

const agent = createAgent({
  model: "anthropic:claude-sonnet-4-5",
  tools: [sendEmail],
  checkpointer: new MemorySaver(),
  middleware: [
    humanInTheLoopMiddleware({
      interruptOn: { send_email: { allowedDecisions: ["approve", "edit", "reject"] } },
    }),
  ],
});

config = {"configurable": {"thread_id": "session-1"}}

Step 1: Agent runs until it needs to call tool

result1 = agent.invoke({ "messages": [{"role": "user", "content": "Send email to john@example.com"}] }, config=config)

Check for interrupt

if "interrupt" in result1: print(f"Waiting for approval: {result1['interrupt']}")

Step 2: Human approves

result2 = agent.invoke( Command(resume={"decisions": [{"type": "approve"}]}), config=config )

</python>
<typescript>
Run the agent, detect an interrupt, then resume execution after human approval.
```typescript
import { Command } from "@langchain/langgraph";

const config = { configurable: { thread_id: "session-1" } };

// Step 1: Agent runs until it needs to call tool
const result1 = await agent.invoke({
  messages: [{ role: "user", content: "Send email to john@example.com" }]
}, config);

// Check for interrupt
if (result1.__interrupt__) {
  console.log(`Waiting for approval: ${result1.__interrupt__}`);
}

// Step 2: Human approves
const result2 = await agent.invoke(
  new Command({ resume: { decisions: [{ type: "approve" }] } }),
  config
);
  • Which tools require approval (per-tool policies)
  • Allowed decisions per tool (approve, edit, reject)
  • Custom middleware hooks: before_model, after_model, wrap_tool_call, before_agent, after_agent
  • Tool-specific middleware (apply only to certain tools)

What You CANNOT Configure

  • Interrupt after tool execution (must be before)
  • Skip checkpointer requirement for HITL

CORRECT

agent = create_agent( model="gpt-4.1", tools=[send_email], checkpointer=MemorySaver(), # Required middleware=[HumanInTheLoopMiddleware({...})] )

</python>
<typescript>
HITL requires a checkpointer to persist state.
```typescript
// WRONG: No checkpointer
const agent = createAgent({
  model: "anthropic:claude-sonnet-4-5", tools: [sendEmail],
  middleware: [humanInTheLoopMiddleware({ interruptOn: { send_email: true } })],
});

// CORRECT: Add checkpointer
const agent = createAgent({
  model: "anthropic:claude-sonnet-4-5", tools: [sendEmail],
  checkpointer: new MemorySaver(),
  middleware: [humanInTheLoopMiddleware({ interruptOn: { send_email: true } })],
});

CORRECT

agent.invoke(input, config={"configurable": {"thread_id": "user-123"}})

</python>
</fix-no-thread-id>

<fix-wrong-resume-syntax>
<python>
Use Command class to resume execution after an interrupt.
```python
# WRONG
agent.invoke({"resume": {"decisions": [...]}})

# CORRECT
from langgraph.types import Command
agent.invoke(Command(resume={"decisions": [{"type": "approve"}]}), config=config)

// CORRECT import { Command } from "@langchain/langgraph"; await agent.invoke(new Command({ resume: { decisions: [{ type: "approve" }] } }), config);

</typescript>
</fix-wrong-resume-syntax>

Discussion

Product Hunt–style comments (not star reviews)
  • No comments yet — start the thread.
general reviews

Ratings

4.462 reviews
  • Chen Thomas· Dec 28, 2024

    Solid pick for teams standardizing on skills: langchain-middleware is focused, and the summary matches what you get after install.

  • Dhruvi Jain· Dec 24, 2024

    We added langchain-middleware from the explainx registry; install was straightforward and the SKILL.md answered most questions upfront.

  • Dev Okafor· Dec 20, 2024

    I recommend langchain-middleware for anyone iterating fast on agent tooling; clear intent and a small, reviewable surface area.

  • Noah Bansal· Dec 16, 2024

    langchain-middleware reduced setup friction for our internal harness; good balance of opinion and flexibility.

  • Olivia Rahman· Dec 8, 2024

    langchain-middleware fits our agent workflows well — practical, well scoped, and easy to wire into existing repos.

  • Diego Wang· Dec 4, 2024

    Registry listing for langchain-middleware matched our evaluation — installs cleanly and behaves as described in the markdown.

  • Noah Torres· Dec 4, 2024

    Useful defaults in langchain-middleware — fewer surprises than typical one-off scripts, and it plays nicely with `npx skills` flows.

  • Diya Johnson· Dec 4, 2024

    langchain-middleware is among the better-maintained entries we tried; worth keeping pinned for repeat workflows.

  • Harper Verma· Nov 23, 2024

    langchain-middleware reduced setup friction for our internal harness; good balance of opinion and flexibility.

  • Fatima Liu· Nov 23, 2024

    We added langchain-middleware from the explainx registry; install was straightforward and the SKILL.md answered most questions upfront.

showing 1-10 of 62

1 / 7