The order middleware runs in
With several middleware, before hooks run in list order and after hooks in reverse. Get it wrong and a hook sees the state before the change you expected.
A class gives middleware a name and room for more than one hook. Tag prints its label from both model hooks, so two of them show the order.
from langchain.agents.middleware import AgentMiddleware
class Tag(AgentMiddleware):
def __init__(self, label):
super().__init__()
self.label = label
@property
def name(self):
return self.label
def before_model(self, state, runtime):
print("before", self.label)
def after_model(self, state, runtime):
print("after ", self.label)The name property matters here: LangChain names each middleware after its class unless told otherwise, and refuses two with the same name.
from langchain.agents import create_agent
from shop_model import ShopModel
from tag import Tag
agent = create_agent(ShopModel(), tools=[], middleware=[Tag("first"), Tag("second")])
agent.invoke({"messages": [{"role": "user", "content": "Hello"}]})Before hooks ran first to last, in the order of the list. After hooks ran last to first. Picture the list as layers around the model: the first entry is the outermost, the first in and the last out. Lesson 19 shows what this means for two middleware that handle the same error.
Pick one to watch it run, step by step.
The argument has to be called runtime
from langchain.agents import create_agent
from langchain.agents.middleware import AgentMiddleware
from shop_model import ShopModel
class Short(AgentMiddleware):
def before_model(self, state, rt):
print(len(state["messages"]))
agent = create_agent(ShopModel(), tools=[], middleware=[Short()])
agent.invoke({"messages": [{"role": "user", "content": "Hello"}]})LangChain passes the runtime to a hook by the name runtime, so a hook that calls it rt fails the first time it runs. The documentation does not mention this; rename the argument and it works.
- Pass
Tag("first")twice and read the error. - Add a third
Tagin the middle of the list and predict the six lines before you run it. - Add a
before_agentmethod toTagand see where it prints.
You understood something today that you didn't yesterday.