# I am gonna use langchain builtin middleware in custom state graph

**URL:** <https://forum.langchain.com/t/i-am-gonna-use-langchain-builtin-middleware-in-custom-state-graph/2414>\
**Category:** LangGraph\
**Tags:** intro-to-langgraph, python-help\
**Created:** [December 4, 2025, 9:12am UTC](https://forum.langchain.com/t/i-am-gonna-use-langchain-builtin-middleware-in-custom-state-graph/2414 "2025-12-04T09:12:46Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Dev](https://avatars.discourse-cdn.com/v4/letter/d/e8c25b/32.png) [@Dev](https://forum.langchain.com/u/Dev)\
**Post date:** [December 4, 2025, 9:12am UTC](https://forum.langchain.com/t/i-am-gonna-use-langchain-builtin-middleware-in-custom-state-graph/2414/1 "2025-12-04T09:12:46Z")

</div>

is it possible to directly use the langchain builtin middleware like ModelCallLimitMiddleware in my custom stateGraph.

Much appreciate if you help me

---

<div class="post-metadata">

**Author:** ![pawel-twardziak](https://yyz1.discourse-cdn.com/flex007/user_avatar/forum.langchain.com/pawel-twardziak/32/960_2.png) [@pawel-twardziak](https://forum.langchain.com/u/pawel-twardziak)\
**Post date:** [December 4, 2025, 7:42pm UTC](https://forum.langchain.com/t/i-am-gonna-use-langchain-builtin-middleware-in-custom-state-graph/2414/2 "2025-12-04T19:42:57Z")

</div>

hi @Dev

what do you mean by `my custom stateGraph`?

Afaik LangChain’s built‑in agent middleware (e.g., `ModelCallLimitMiddleware`) is wired into the agent graph that `create_agent` builds. In a hand-built `StateGraph`, there is no generic `graph.add_middleware(...)` and the built-ins assume the standard agent loop nodes (`model`, `tools`, `end`) and jump semantics.

I reckon you can instantiate `ModelCallLimitMiddleware` and call its hooks around your model node:

- Call `before_model(state, runtime)` (or `abefore_model`) before the model; if it returns `{"jump_to": "end", "messages": [...]}`, route to your END node; if `exit_behavior="error"`, handle `ModelCallLimitExceededError`
- Call `after_model(state, runtime)` (or `aafter_model`) after the model to increment counters
- Ensure your state carries thread\_model\_call\_count and run\_model\_call\_count; if you use a checkpointer, treat run count as non-persistent (untracked) yourself

Maybe sth like this:

```py
from langchain.agents.middleware.model_call_limit import ModelCallLimitMiddleware, ModelCallLimitExceededError

limit = ModelCallLimitMiddleware(thread_limit=10, run_limit=5, exit_behavior="end")

def before_model_node(state, runtime):
    updates = limit.before_model(state, runtime) or {}
    # If updates includes {"jump_to": "end"}, add your conditional edge to END.
    return updates

def model_node(state):
    # ... call your model ...
    return {"messages": [...]} # your AIMessage(s)

def after_model_node(state, runtime):
    return limit.after_model(state, runtime) or {}

```

Key caveats:

- The middleware’s `hook_config(can_jump_to=["end"])` metadata isn’t wired automatically in a plain `StateGraph`; you must add conditional edges based on the returned `jump_to`

- The built-in uses `UntrackedValue` for the run counter; replicate that by not checkpointing `run_model_call_count` (or resetting it per run)

---

<div class="post-metadata">

**Author:** ![Dev](https://avatars.discourse-cdn.com/v4/letter/d/e8c25b/32.png) [@Dev](https://forum.langchain.com/u/Dev)\
**Post date:** [December 9, 2025, 6:43am UTC](https://forum.langchain.com/t/i-am-gonna-use-langchain-builtin-middleware-in-custom-state-graph/2414/3 "2025-12-09T06:43:03Z")

</div>

Hello Pawel

I succeed to implement the langchain builtin middleware in the stateGraph

Thank

---

<div class="post-metadata">

**Author:** ![KDKHD](https://yyz1.discourse-cdn.com/flex007/user_avatar/forum.langchain.com/kdkhd/32/1861_2.png) [@KDKHD](https://forum.langchain.com/u/KDKHD)\
**Post date:** [December 12, 2025, 10:42am UTC](https://forum.langchain.com/t/i-am-gonna-use-langchain-builtin-middleware-in-custom-state-graph/2414/4 "2025-12-12T10:42:51Z")

</div>

@Dev Do you mind giving an example of how you are making this work?

---

<div class="post-metadata">

**Author:** ![Dev](https://avatars.discourse-cdn.com/v4/letter/d/e8c25b/32.png) [@Dev](https://forum.langchain.com/u/Dev)\
**Post date:** [December 12, 2025, 11:55am UTC](https://forum.langchain.com/t/i-am-gonna-use-langchain-builtin-middleware-in-custom-state-graph/2414/5 "2025-12-12T11:55:36Z")

</div>

```auto
limit = ToolCallLimitMiddleware(
    thread_limit=None,
    run_limit=DEFAULT_TOOL_LIMIT,
    exit_behavior=DEFAULT_EXIT_BEHAVIOR,
)
def limit_check_node(state: GraphState, runtime):
        """
        MUST be placed after tool execution.
        This is the only correct place where tool call count is updated.
        """
        updates = limit.after_model(state, runtime) or {}

        if updates.get("jump_to") == "end":
            return {" __end__": True}

        return updates

```

---

<div class="post-metadata">

**Author:** ![Dev](https://avatars.discourse-cdn.com/v4/letter/d/e8c25b/32.png) [@Dev](https://forum.langchain.com/u/Dev)\
**Post date:** [December 12, 2025, 12:03pm UTC](https://forum.langchain.com/t/i-am-gonna-use-langchain-builtin-middleware-in-custom-state-graph/2414/6 "2025-12-12T12:03:00Z")

</div>

Hello @pawel-twardziak  
I have another significant challenge to implement the ToolCallLimitMiddleware  
I set the tool call limit to **5**. When I ask the LLM to create **6 images** , the assistant returns:

```auto
tool_calls = [call1, call2, call3, call4, call5, call6]

```

What I want is to **execute only the first 5 tool calls** , **ignore the 6th** , and then **return control to the LLM**.

However, with my current implementation using `ToolCallLimitMiddleware`, all **6 tool calls are executed sequentially** , and the middleware only triggers **after** the 6th call, which defeats the purpose of the limit.

How can I modify the implementation so that **only the first 5 tool calls are executed** and the 6th is skipped?

---

<div class="post-metadata">

**Author:** ![pawel-twardziak](https://yyz1.discourse-cdn.com/flex007/user_avatar/forum.langchain.com/pawel-twardziak/32/960_2.png) [@pawel-twardziak](https://forum.langchain.com/u/pawel-twardziak)\
**Post date:** [December 12, 2025, 1:10pm UTC](https://forum.langchain.com/t/i-am-gonna-use-langchain-builtin-middleware-in-custom-state-graph/2414/7 "2025-12-12T13:10:17Z")

</div>

Hi @Dev  
Hmm that is an interesting issue 🤨  
Could you create another post since this one is related to original issue and already resolved?  
Just to keep things clear and well structured here on the forum. Appreciate 😉  
You can tag me there and I will answer today later on.

---

<div class="post-metadata">

**Author:** ![Dev](https://avatars.discourse-cdn.com/v4/letter/d/e8c25b/32.png) [@Dev](https://forum.langchain.com/u/Dev)\
**Post date:** [December 12, 2025, 1:13pm UTC](https://forum.langchain.com/t/i-am-gonna-use-langchain-builtin-middleware-in-custom-state-graph/2414/8 "2025-12-12T13:13:15Z")

</div>

Thank you, I just did it.

---

<div class="post-metadata">

**Author:** ![pawel-twardziak](https://yyz1.discourse-cdn.com/flex007/user_avatar/forum.langchain.com/pawel-twardziak/32/960_2.png) [@pawel-twardziak](https://forum.langchain.com/u/pawel-twardziak)\
**Post date:** [December 12, 2025, 3:20pm UTC](https://forum.langchain.com/t/i-am-gonna-use-langchain-builtin-middleware-in-custom-state-graph/2414/9 "2025-12-12T15:20:33Z")

</div>

I’m attaching the link here as the follow up

> [@Implement ToolLimitationNode in stateGraph](https://forum.langchain.com/t/implement-toollimitationnode-in-stategraph/2502):
>
> I have one significant challenge to implement the ToolCallLimitMiddleware I set the tool call limit to 5. When I ask the LLM to create 6 images, the assistant returns: tool\_calls = [call1, call2, call3, call4, call5, call6] What I want is to execute only the first 5 tool calls, ignore the 6th, and then return control to the LLM. However, with my current implementation using ToolCallLimitMiddleware, all 6 tool calls are executed sequentially, and the middleware only triggers after the 6th c…
