langchain-middleware

tarafından langchain-ai

İnsan döngüde onayı, özel ara katman yazılımı ve LangChain ajanları için yapılandırılmış çıktı desenleri. HumanInTheLoopMiddleware, tehlikeli araç çağrılarından önce yürütmeyi duraklatarak insanların onaylamasına, argümanları düzenlemesine veya geri bildirimle reddetmesine olanak tanır. Araç başına kesinti politikaları, risk seviyesine göre farklı onay kuralları yapılandırmanızı sağlar; durum kalıcılığı için bir checkpointer ve thread_id gerektirir. Komut devam deseni, insan kararlarından sonra yürütmeyi sürdürür ve araç argümanlarını düzenleme desteği sunar...

npx skills add https://github.com/langchain-ai/langchain-skills --skill langchain-middleware
Middleware patterns for production LangChain agents:
  • 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

Set up an agent with HITL middleware that pauses before sending emails for approval.
from langchain.agents import create_agent
from langchain.agents.middleware import HumanInTheLoopMiddleware
from langgraph.checkpoint.memory import MemorySaver
from langchain.tools import tool

@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"]},
            }
        )
    ],
)
Set up an agent with HITL that pauses before sending emails for human approval.
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"] } },
    }),
  ],
});
Run the agent, detect an interrupt, then resume execution after human approval.
from langgraph.types import Command

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
)
Run the agent, detect an interrupt, then resume execution after human approval.
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
);
Edit the tool arguments before approving when the original values need correction.
# Human edits the arguments — edited_action must include name + args
result2 = agent.invoke(
    Command(resume={
        "decisions": [{
            "type": "edit",
            "edited_action": {
                "name": "send_email",
                "args": {
                    "to": "alice@company.com",  # Fixed email
                    "subject": "Project Meeting - Updated",
                    "body": "...",
                },
            },
        }]
    }),
    config=config
)
Edit the tool arguments before approving when the original values need correction.
// Human edits the arguments — editedAction must include name + args
const result2 = await agent.invoke(
  new Command({
    resume: {
      decisions: [{
        type: "edit",
        editedAction: {
          name: "send_email",
          args: {
            to: "alice@company.com",  // Fixed email
            subject: "Project Meeting - Updated",
            body: "...",
          },
        },
      }]
    }
  }),
  config
);
Reject a tool call and provide feedback explaining why it was rejected.
# Human rejects
result2 = agent.invoke(
    Command(resume={
        "decisions": [{
            "type": "reject",
            "feedback": "Cannot delete customer data without manager approval",
        }]
    }),
    config=config
)
Configure different HITL policies for each tool based on risk level.
agent = create_agent(
    model="gpt-4.1",
    tools=[send_email, read_email, delete_email],
    checkpointer=MemorySaver(),
    middleware=[
        HumanInTheLoopMiddleware(
            interrupt_on={
                "send_email": {"allowed_decisions": ["approve", "edit", "reject"]},
                "delete_email": {"allowed_decisions": ["approve", "reject"]},  # No edit
                "read_email": False,  # No HITL for reading
            }
        )
    ],
)
### What You CAN Configure
  • 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)

Custom Middleware Hooks

Six decorator hooks are available. Two patterns:

  • Wrap hooks (wrap_tool_call, wrap_model_call): (request, handler) — call handler(request) to proceed, or return early to short-circuit.
  • Before/after hooks (before_model, after_model, before_agent, after_agent): (state, runtime) — inspect or modify state. Return None or a dict of state updates.
`@wrap_tool_call` intercepts tool execution. **Do NOT use `yield`** — it creates a generator and causes `NotImplementedError`.
from langchain.agents.middleware import wrap_tool_call

@wrap_tool_call
def retry_middleware(request, handler):
    for attempt in range(3):
        try:
            return handler(request)
        except Exception:
            if attempt == 2:
                raise

@wrap_tool_call
def guard_middleware(request, handler):
    if request.tool_call["name"] == "dangerous_tool":
        return "This tool is disabled"  # short-circuit
    return handler(request)
`createMiddleware({ wrapToolCall })` intercepts tool execution.
import { createMiddleware } from "langchain";

const retryMiddleware = createMiddleware({
  wrapToolCall: async (request, handler) => {
    for (let attempt = 0; attempt < 3; attempt++) {
      try { return await handler(request); }
      catch (e) { if (attempt === 2) throw e; }
    }
  },
});
`before_model` / `after_model` / `before_agent` / `after_agent` all share `(state, runtime)` signature.
from langchain.agents.middleware import before_model, after_model

@before_model
def log_calls(state, runtime):
    print(f"Calling model with {len(state['messages'])} messages")

@after_model
def check_output(state, runtime):
    print(f"Model responded")
All before/after hooks share the same `(state, runtime)` signature via `createMiddleware`.
import { createMiddleware } from "langchain";

const loggingMiddleware = createMiddleware({
  beforeModel: (state, runtime) => {
    console.log(`Calling model with ${state.messages.length} messages`);
  },
  afterModel: (state, runtime) => {
    console.log("Model responded");
  },
});
### What You CANNOT Configure
  • Interrupt after tool execution (must be before)
  • Skip checkpointer requirement for HITL
HITL middleware requires a checkpointer to persist state.
# WRONG
agent = create_agent(model="gpt-4.1", tools=[send_email], middleware=[HumanInTheLoopMiddleware({...})])

# CORRECT
agent = create_agent(
    model="gpt-4.1", tools=[send_email],
    checkpointer=MemorySaver(),  # Required
    middleware=[HumanInTheLoopMiddleware({...})]
)
HITL requires a checkpointer to persist state.
// 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 } })],
});
Always provide thread_id when using HITL to track conversation state.
# WRONG
agent.invoke(input)  # No config!

# CORRECT
agent.invoke(input, config={"configurable": {"thread_id": "user-123"}})
Use Command class to resume execution after an interrupt.
# WRONG
agent.invoke({"resume": {"decisions": [...]}})

# CORRECT
from langgraph.types import Command
agent.invoke(Command(resume={"decisions": [{"type": "approve"}]}), config=config)
Use Command class to resume execution after an interrupt.
// WRONG
await agent.invoke({ resume: { decisions: [...] } });

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

langchain-ai tarafından daha fazla skill

langgraph-docs
langchain-ai
LangGraph dokümantasyonuna erişerek durum bilgisi olan ajanlar ve çoklu ajan iş akışları oluşturun. Resmi LangGraph Python dokümanlarını getirir; durum makineleri, grafik tabanlı ajan tasarımı ve insan-döngüde desenlerini kapsar. Sorgu türüne göre ilgili dokümantasyonu önceliklendirir: nasıl yapılır soruları için uygulama kılavuzları, teori için kavram sayfaları, uçtan uca örnekler için eğitimler ve teknik detaylar için API referansları. En alakalı 2–4 dokümantasyon URL'sini otomatik olarak seçer ve yanıtlamak için içeriklerini alır...
official
langgraph-human-in-the-loop
langchain-ai
Graf yürütmesini insan incelemesi, onayı veya doğrulaması için duraklatır, ardından girdileriyle devam eder. Üç bileşen gerektirir: bir checkpointer (InMemorySaver veya PostgresSaver), config içinde bir thread ID ve JSON-serializable interrupt payload'ları. interrupt(value) duraklatır ve verileri yüzeye çıkarır; Command(resume=value) devam ettirir ve bu değeri duraklatılan düğüme döndürür. interrupt() öncesindeki tüm kod devamda yeniden çalıştırılır, bu nedenle yan etkiler idempotent olmalıdır (insert değil upsert kullanın). Onay iş akışlarını destekler,...
official
web-research
langchain-ai
Web araştırması ile ilgili talepler için bu beceriyi kullanın; kapsamlı web araştırması yapmak için yapılandırılmış bir yaklaşım sunar.
official
langchain-oss-primer
langchain-ai
Herhangi bir LangChain, Deep Agents veya LangGraph ajan oluşturma projesine BAŞLANGIÇ NOKTASI. Diğer becerileri seçmeden veya herhangi bir şey yazmadan önce gerekli başlangıç noktası.
official
skill-creator
langchain-ai
Etkili beceriler oluşturmak için rehber; bu beceriler, uzmanlaşmış bilgi, iş akışları veya araç entegrasyonları ile ajan yeteneklerini genişletir. Kullanıcı…
official
social-media
langchain-ai
Platformaya özel sosyal medya gönderilerini, araştırma destekli içerik ve oluşturulan eşlik eden görsellerle hazırlar. LinkedIn gönderilerini (profesyonel tonla 1.300 karakter) ve Twitter/X thread'lerini (tweet başına 280 karakter, 1/🧵 formatı) destekler. Yazmadan önce araştırmayı bir alt ajana devretmeyi, ardından doğruluk ve alaka düzeyini sağlamak için bulguları okumayı gerektirir. generate_social_image aracıyla, küçük... için optimize edilmiş cesur, yüksek kontrastlı kompozisyonlarla otomatik olarak dikkat çekici sosyal görseller oluşturur.
official
deep-agents-memory
langchain-ai
Deep Agents için geçici, kalıcı ve hibrit yönlendirme seçeneklerine sahip takılabilir bellek ve dosya arka uçları. Dört arka uç türü: StateBackend (iş parçacığı kapsamlı, geçici), StoreBackend (oturumlar arası kalıcı), FilesystemBackend (yerel geliştirme için gerçek disk erişimi) ve CompositeBackend (farklı yolları farklı arka uçlara yönlendirir). FilesystemMiddleware altı dosya işleme aracı sağlar: ls, read_file, write_file, edit_file, glob, grep. CompositeBackend en uzun önek eşlemesini kullanarak yönlendirme yapar...
official
deep-agents-orchestration
langchain-ai
Alt ajanları yönetir, çok adımlı görevleri planlar ve hassas işlemler için insan onayı gerektirir. Görev aracı aracılığıyla uzmanlaşmış alt ajanlara iş dağıtır; özel alt ajanlar izole araç setlerini ve sistem yönlendirmelerini desteklerken, varsayılan "genel amaçlı" alt ajan ana ajan yapılandırmasını devralır. write_todos ile karmaşık iş akışlarını planlayıp takip eder, görevleri beklemede, devam eden ve tamamlanmış durumlar arasında düzenler; kalıcılık için bir thread_id gerektirir. Uygular...
official