---
title: "The gate votes on what it sees, not what runs"
date: 2026-09-22
series: 24
summary: "LangChain is adding a classifier that can veto an agent's tool calls. The first bug filed against it teaches more about agent security than the launch does."
voice: builder
tags: [tool-risk-gating, model-router-middleware, fail-open-fail-closed-design, middleware-ordering-security, wrap-tool-call-gate]
image: "/notes/typesafe-tool-gate-ordering/image.png"
imageAlt: null
linkedin: "urn:li:share:7508028673900507136"
sources:
  - title: "langchain-typesafe 0.0.1a3 (ModelRouterMiddleware + AutoModeMiddleware, experimental) — PyPI"
    url: https://pypi.org/project/langchain-typesafe/
    date: 2026-09-20
  - title: "Full middleware PR incl. SkillsMiddleware, STILL OPEN, not merged — GitHub"
    url: https://github.com/langchain-ai/langchain/pull/40556
    date: 2026-09-17
  - title: "Ordering bug: Auto Mode never re-scores a call rewritten by an inner middleware — GitHub"
    url: https://github.com/langchain-ai/langchain/issues/40694
  - title: "TypeSafe Jev model docs"
    url: https://docs.typesafe.ai
dateApprox: false
---

LangChain is adding a classifier that can veto an agent's tool calls. The first bug filed against it teaches more about agent security than the launch does.

langchain-typesafe hit PyPI this week (0.0.1a3, September 20). Two experimental middlewares: ModelRouterMiddleware picks which model handles a run, AutoModeMiddleware scores each tool call against plain-language criteria and returns an error ToolMessage when risk crosses your threshold. No approval flow, it refuses outright.

The failure semantics are the real design work. Routing fails open: classifier outage means your default route, not a stopped agent. The tool gate fails closed: classifier down, call does not run. Right defaults on both counts.

Two checks before you trust it in production:

One, the classifier is a hosted API with TYPESAFE_API_KEY and retries on 408/429/5xx. No latency or cost numbers published yet. If you run air-gapped, this middleware does not exist for you.

Two, issue #40694, ordering. Put the gate outside a human-in-the-loop middleware and a reviewer-edited tool call executes without ever being classified. The repro shows a 0.9-risk call going through. Swap the order and it blocks.

The trap: a wrap_tool_call gate votes on the call as it exists at its own layer. Any inner middleware that rewrites the call rewrites it after your policy already said yes.

Order the risk gate innermost, after everything that can mutate a tool call, and pin that order with a test.
