日期:2026-05-19 入口:endpoint_test.py → agui.py
langgraph.errors.GraphRecursionError: Recursion limit of 25 reached without hitting a stop condition.
尽管 endpoint.py 中���配置 "recursion_limit": 1000,运行时仍以默认值 25 触发限制。
| # | 位置 | 说明 |
|---|---|---|
| 1 | endpoint.py:36 | Agent config 设置 recursion_limit: 1000 |
| 2 | agui.py:225 (retry) | super().run(input) 进入 ag_ui_langgraph |
| 3 | ag_ui_langgraph/agent.py:142 | ensure_config(self.config.copy()) → config 含 recursion_limit=1000 |
| 4 | ag_ui_langgraph/agent.py:311 | regenerate 路径:prepare_regenerate_stream 被触发 |
| 5 | ag_ui_langgraph/agent.py:392 | fork = await self.graph.aupdate_state(...) 返回仅含 configurable 的 config |
| 6 | ag_ui_langgraph/agent.py:401 | get_stream_kwargs(config=fork) — fork 中无 recursion_limit |
| 7 | langchain_core/.../event_stream.py:1027 | ensure_config(fork) 填充默认值 → recursion_limit=25 |
| 8 | langgraph/pregel/main.py:2804 | ensure_config(self.config, config) — 后者(25)覆盖前者(1000) |
aupdate_state 返回的 fork config 仅包含 checkpoint 元数据(thread_id, checkpoint_id),不含 recursion_limit。langchain_core.ensure_config 后被填充为默认值 25。随后在 Pregel.astream 中,langgraph 的 ensure_config 按顺序赋值(无 "skip if default" 保护),最终 25 覆盖了 graph 自身的 1000。
# langgraph ensure_config — 简单赋值,后者覆盖前者
for config in configs:
for k, v in config.items():
if _is_not_empty(v) and k in CONFIG_KEYS:
empty[k] = v # ← 25 覆盖 1000
# langgraph merge_configs — 有保护逻辑
elif key == "recursion_limit":
if config["recursion_limit"] != DEFAULT_RECURSION_LIMIT:
base["recursion_limit"] = config["recursion_limit"] # ← 25 == default,跳过
agent_state.messages > client_messages)recursion_limit首次调用和 retry 均可能触发(retry 更容易,因为首次失败后 state 中已有新消息)。
BaseLangGraphAGUIAgent.get_stream_kwargs 中,将 config 传入 kwargs 前,确保 recursion_limit 始终从 self.config 继承:
# agui.py — get_stream_kwargs
if config:
if self.config and "recursion_limit" in self.config and "recursion_limit" not in config:
config = {**config, "recursion_limit": self.config["recursion_limit"]}
kwargs['config'] = config
此修复覆盖所有代码路径(normal / regenerate / resume),不修改原始 config 对象。
| 文件 | 角色 |
|---|---|
| src/agents/copilot/agui.py | 修复位置 — get_stream_kwargs |
| src/agents/copilot/endpoint.py | Agent 配置入口 |
| ag_ui_langgraph/agent.py | prepare_regenerate_stream(问题源头) |
| langgraph/_internal/_config.py | ensure_config 覆盖行为 |
| langchain_core/runnables/config.py | DEFAULT_RECURSION_LIMIT = 25 |