🛡️ Portarus: the gateway for AI agents Discover more →
Engineering

How to Filter LangChain Agent Input Before the LLM

Don't pay tokens to reject tokens.

Orlando Quijada · · 4 min read
Raw webhook traffic with duplicates, bursts and junk passing through a pre-LLM filter layer, so only one clean message reaches a LangChain agent and the model
  • The chain tokenizes whatever lands — duplicates, bursts and junk included.
  • LLM-classifying input inside the chain means paying tokens to reject tokens.
  • Filtering in front invokes the chain once per real event.

The problem

  • A LangChain agent runs the model on whatever lands in its input.
  • Duplicates, bursts and bot junk all get tokenized — and you pay for all of it.
  • Guard inside the chain with an LLM and you pay tokens to reject tokens.

The solution

Filter before the request reaches your handler.

Two places to act, and they cost very differently:

  1. Inside the chain: a guard node saves the model call — but the handler already ran, and a burst still invokes it per fragment.
  2. In front of the endpoint: the chain never invokes, so nothing tokenizes.

Drop duplicate retries, merge bursts into one invocation, reject junk and oversized payloads.

Result: the chain runs once per real event and your tokens track actual conversations.

See the full fix
A closer look

Your LangChain agent runs the model on whatever lands in its input. A duplicate retry, a user who splits one thought across five messages, a bot probing your endpoint — the chain tokenizes all of it and you pay for all of it. The cheapest tokens are the ones the model never sees. Here is how to filter LangChain agent input before it reaches the LLM.

Why the chain is the wrong place to filter

Three patterns inflate the bill before any logic of yours runs: duplicates (senders retry on timeout, each a full chain invocation), bursts (a user types four messages — four invocations for one intent), and junk and abuse (bots, scanners, and oversized payloads the model tokenizes before you notice). None of it shows as an error, only as a token graph running ahead of your real conversations.

The manual fix (Option 1)

Guard inside the chain. Add a RunnableBranch or a plain validation function at the top of your chain: reject empty input, drop payloads over a size cap, and short-circuit before the expensive ChatModel call.

On a gateway, duplicates, bursts and junk are dropped before your endpoint is hit at all.

The catch: the handler ran before your guard

A pure-code guard saves the model call, but the request still ran your handler, a burst still invokes it per fragment, and you repeat the guard in every chain you expose. To stop the invocation itself, the filter has to live in front of the endpoint.

Place a gateway layer (Option 2) — faster

A message gateway sits between the sender and your webhook URL. You point senders at the gateway, and it drops duplicate retries, merges a burst into one message, and rejects junk before forwarding. Your FastAPI (or LangServe) endpoint receives one clean payload per real event, so the chain invokes once and your tokens track actual conversations.

Option 1 (in-chain) vs Option 2 (in front)

 Guard inside the chainFilter in front (gateway)
Duplicate retry ~Handler still runs ✓Chain never invoked
Burst of fragments ~One invocation each ✓Merged into one
Bot / oversized junk ✕Tokenized if LLM-classified ✓Rejected at the edge
Token-flood payload ~Truncate after arrival ✓Capped before forwarding
Every chain / endpoint ~Repeat the guard each time ✓One layer, all of them
Control of internals ✓Full ~Abstracted away

A single oversized message is its own problem — see token floods and your agent’s budget. Usually duplicates and bursts waste the most; deduplicating and merging fragments cut the count with no change to your chain. It’s one piece of message quality for AI agents.

If option 2 sounds more like you, here’s the short version of how to set it up: keep junk out of your chain invocations →.

Either way — go make your chain run only on real input.

Thanks for reading. 👋

Orlando. -

Found this helpful? Share it with someone who needs it

OQ

Orlando Quijada

Technologist with 15+ years of experience. Developer, SaaS tester, and AI collaboration & optimization specialist. Currently contributing at portarus.com.

Written on

What to read next