From 34ba2cdf38a0b4efd41621312c1d33fd927cf1b7 Mon Sep 17 00:00:00 2001 From: Battleplus <121445871+Battleplus@users.noreply.github.com> Date: Mon, 24 Aug 2026 09:15:00 +0800 Subject: [PATCH] fix(docs): update middleware guide to current AgentMiddleware API (#4968) --- backend/CONTRIBUTING.md | 30 +++++++++---------- .../src/content/en/harness/customization.mdx | 18 ++++++----- .../src/content/en/harness/middlewares.mdx | 14 ++++----- .../src/content/zh/harness/customization.mdx | 18 ++++++----- .../src/content/zh/harness/middlewares.mdx | 17 ++++++----- 5 files changed, 51 insertions(+), 46 deletions(-) diff --git a/backend/CONTRIBUTING.md b/backend/CONTRIBUTING.md index 9110dcd94..701f9b8ee 100644 --- a/backend/CONTRIBUTING.md +++ b/backend/CONTRIBUTING.md @@ -276,28 +276,28 @@ tools: ```python # packages/harness/deerflow/agents/middlewares/my_middleware.py -from langchain.agents.middleware import BaseMiddleware -from langchain_core.runnables import RunnableConfig +from langchain.agents import AgentState +from langchain.agents.middleware import AgentMiddleware +from langgraph.runtime import Runtime -class MyMiddleware(BaseMiddleware): +class MyMiddleware(AgentMiddleware[AgentState]): """Middleware description.""" - def transform_state(self, state: dict, config: RunnableConfig) -> dict: - """Transform the state before agent execution.""" - # Modify state as needed - return state + def before_model(self, state: AgentState, runtime: Runtime) -> dict | None: + """Runs before each model call. Return a dict of state updates, or None.""" + return None + + def after_model(self, state: AgentState, runtime: Runtime) -> dict | None: + """Runs after each model call. Inspect or modify the result.""" + return None ``` -2. Register in `packages/harness/deerflow/agents/lead_agent/agent.py`: +2. Register via `custom_middlewares` when building the agent: ```python -middlewares = [ - ThreadDataMiddleware(), - SandboxMiddleware(), - MyMiddleware(), # Add your middleware - TitleMiddleware(), - ClarificationMiddleware(), -] +middlewares = build_middlewares( + config, model_name, custom_middlewares=[MyMiddleware()], ... +) ``` ### Adding New API Endpoints diff --git a/frontend/src/content/en/harness/customization.mdx b/frontend/src/content/en/harness/customization.mdx index 7117972af..7a460ca37 100644 --- a/frontend/src/content/en/harness/customization.mdx +++ b/frontend/src/content/en/harness/customization.mdx @@ -25,19 +25,21 @@ To add a custom middleware: 2. Pass your middleware to the `custom_middlewares` parameter when building the agent. ```python +from langchain.agents import AgentState from langchain.agents.middleware import AgentMiddleware -from deerflow.agents.thread_state import ThreadState +from langgraph.runtime import Runtime -class AuditMiddleware(AgentMiddleware): - async def on_start(self, state: ThreadState, config): - # Runs before each model call + +class AuditMiddleware(AgentMiddleware[AgentState]): + def before_model(self, state: AgentState, runtime: Runtime) -> dict | None: + """Runs before each model call.""" print(f"[audit] turn starts: {len(state.messages)} messages in context") - return state, config + return None - async def on_end(self, state: ThreadState, config): - # Runs after each model call + def after_model(self, state: AgentState, runtime: Runtime) -> dict | None: + """Runs after each model call.""" print(f"[audit] turn ends: last message type = {state.messages[-1].type}") - return state, config + return None ``` Custom middlewares are injected into the chain immediately before `ClarificationMiddleware`, which always runs last. diff --git a/frontend/src/content/en/harness/middlewares.mdx b/frontend/src/content/en/harness/middlewares.mdx index 78befa5b3..402d92ea1 100644 --- a/frontend/src/content/en/harness/middlewares.mdx +++ b/frontend/src/content/en/harness/middlewares.mdx @@ -235,15 +235,13 @@ The basic structure is: from langchain.agents.middleware import AgentMiddleware class MyMiddleware(AgentMiddleware): - async def on_start(self, state, config): - # Runs before the model call - # Modify state or config here - return state, config + def before_model(self, state, runtime) -> dict | None: + """Runs before each model call.""" + return None - async def on_end(self, state, config): - # Runs after the model call - # Inspect or modify the result - return state, config + def after_model(self, state, runtime) -> dict | None: + """Runs after each model call.""" + return None ``` Custom middlewares are passed to `make_lead_agent` via the `custom_middlewares` parameter in `build_middlewares`. They are injected immediately before `ClarificationMiddleware` at the end of the chain. diff --git a/frontend/src/content/zh/harness/customization.mdx b/frontend/src/content/zh/harness/customization.mdx index da9c9ee44..c8de856c3 100644 --- a/frontend/src/content/zh/harness/customization.mdx +++ b/frontend/src/content/zh/harness/customization.mdx @@ -25,19 +25,21 @@ DeerFlow 的可插拔架构意味着系统的大多数部分都可以在不 fork 2. 在构建 Agent 时通过 `custom_middlewares` 参数传入你的中间件。 ```python +from langchain.agents import AgentState from langchain.agents.middleware import AgentMiddleware -from deerflow.agents.thread_state import ThreadState +from langgraph.runtime import Runtime -class AuditMiddleware(AgentMiddleware): - async def on_start(self, state: ThreadState, config): - # 在每次模型调用前运行 + +class AuditMiddleware(AgentMiddleware[AgentState]): + def before_model(self, state: AgentState, runtime: Runtime) -> dict | None: + """在每次模型调用前运行。""" print(f"[审计] 轮次开始:上下文中有 {len(state.messages)} 条消息") - return state, config + return None - async def on_end(self, state: ThreadState, config): - # 在每次模型调用后运行 + def after_model(self, state: AgentState, runtime: Runtime) -> dict | None: + """在每次模型调用后运行。""" print(f"[审计] 轮次结束:最后一条消息类型 = {state.messages[-1].type}") - return state, config + return None ``` 自定义中间件在链末尾 `ClarificationMiddleware` 之前注入,后者始终最后运行。 diff --git a/frontend/src/content/zh/harness/middlewares.mdx b/frontend/src/content/zh/harness/middlewares.mdx index 0814fe135..da103ea5b 100644 --- a/frontend/src/content/zh/harness/middlewares.mdx +++ b/frontend/src/content/zh/harness/middlewares.mdx @@ -216,16 +216,19 @@ summarization: 自定义中间件可以注入到链中用于专业用途。中间件必须实现 `langchain.agents.middleware` 中的 `AgentMiddleware` 接口: ```python +from langchain.agents import AgentState from langchain.agents.middleware import AgentMiddleware +from langgraph.runtime import Runtime -class MyMiddleware(AgentMiddleware): - async def on_start(self, state, config): - # 在模型调用前运行 - return state, config - async def on_end(self, state, config): - # 在模型调用后运行 - return state, config +class MyMiddleware(AgentMiddleware[AgentState]): + def before_model(self, state: AgentState, runtime: Runtime) -> dict | None: + """在模型调用前运行。""" + return None + + def after_model(self, state: AgentState, runtime: Runtime) -> dict | None: + """在模型调用后运行。""" + return None ``` 自定义中间件在链末尾 `ClarificationMiddleware` 之前注入。