Skip to content

Commit cea5611

Browse files
committed
subagent历史带工具调用信息
1 parent 6a6d030 commit cea5611

3 files changed

Lines changed: 29 additions & 21 deletions

File tree

astrbot/core/astr_agent_tool_exec.py

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,7 @@ async def _execute_handoff(
373373
except Exception:
374374
pass
375375

376-
llm_resp = await ctx.tool_loop_agent(
376+
llm_resp, runner_messages = await ctx.tool_loop_agent(
377377
event=event,
378378
chat_provider_id=prov_id,
379379
prompt=input_,
@@ -384,25 +384,16 @@ async def _execute_handoff(
384384
max_steps=agent_max_step,
385385
tool_call_timeout=run_context.tool_call_timeout,
386386
stream=stream,
387+
return_runner_messages=True
387388
)
388389

389390
# 保存历史上下文
390-
if agent_name:
391+
if agent_name and runner_messages:
391392
try:
392393
from astrbot.core.dynamic_subagent_manager import DynamicSubAgentManager
393-
394-
# 构建当前对话的历史消息
395-
current_messages = []
396-
# 添加本轮用户输入
397-
current_messages.append({"role": "user", "content": input_})
398-
# 添加助手回复
399-
current_messages.append(
400-
{"role": "assistant", "content": llm_resp.completion_text}
394+
DynamicSubAgentManager.update_subagent_history(
395+
umo, agent_name, runner_messages
401396
)
402-
if current_messages:
403-
DynamicSubAgentManager.save_subagent_history(
404-
umo, agent_name, current_messages
405-
)
406397
except Exception:
407398
pass # 不影响主流程
408399

astrbot/core/dynamic_subagent_manager.py

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@ class DynamicSubAgentManager:
7070
_max_subagent_count: int = 3
7171
_auto_cleanup_per_turn: bool = True
7272
_shared_context_enabled: bool = False
73-
_shared_context_maxlen: int = 200
74-
73+
_shared_context_maxlen: int = 200 # 公共上下文保留的历史消息条数
74+
_max_subagent_history: int = 500 # 每个subagent最多保留的历史消息条数
7575
_tools_blacklist: set[str] = {
7676
"send_shared_context_for_main_agentcreate_dynamic_subagent",
7777
"protect_subagent",
@@ -251,20 +251,32 @@ def protect_subagent(cls, session_id: str, agent_name: str) -> None:
251251
)
252252

253253
@classmethod
254-
def save_subagent_history(
254+
def update_subagent_history(
255255
cls, session_id: str, agent_name: str, current_messages: list
256256
) -> None:
257-
"""Save conversation history for a subagent"""
257+
"""Update conversation history for a subagent"""
258258
session = cls.get_session(session_id)
259259
if not session or agent_name not in session.protected_agents:
260260
return
261261

262262
if agent_name not in session.subagent_histories:
263263
session.subagent_histories[agent_name] = []
264264

265-
# 追加新消息
266265
if isinstance(current_messages, list):
267-
session.subagent_histories[agent_name].extend(current_messages)
266+
_MAX_TOOL_RESULT_LEN = 2000
267+
for msg in current_messages:
268+
if isinstance(msg, dict) and msg.get("role") == "system": # 移除system消息
269+
current_messages.remove(msg)
270+
# 对过长的 tool 结果做截断,避免单条消息占用过多空间
271+
if (isinstance(msg, dict) and msg.get("role") == "tool" and isinstance(msg.get("content"), str) and len(msg["content"]) > _MAX_TOOL_RESULT_LEN
272+
):
273+
msg["content"] = (
274+
msg["content"][:_MAX_TOOL_RESULT_LEN] + "\n...[truncated]"
275+
)
276+
277+
session.subagent_histories[agent_name].extend(current_messages)
278+
if cls._max_subagent_history < len(session.subagent_histories[agent_name]):
279+
session.subagent_histories[agent_name] = session.subagent_histories[agent_name][-cls._max_subagent_history:]
268280

269281
logger.debug(
270282
"[EnhancedSubAgent:History] Saved messages for %s, current len=%d",

astrbot/core/star/context.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ async def tool_loop_agent(
159159
max_steps: int = 30,
160160
tool_call_timeout: int = 120,
161161
**kwargs: Any,
162-
) -> LLMResponse:
162+
) -> LLMResponse | tuple[LLMResponse, list[Any]]:
163163
"""Run an agent loop that allows the LLM to call tools iteratively until a final answer is produced.
164164
If you do not pass the agent_context parameter, the method will recreate a new agent context.
165165
@@ -250,6 +250,11 @@ async def tool_loop_agent(
250250
llm_resp = agent_runner.get_final_llm_resp()
251251
if not llm_resp:
252252
raise Exception("Agent did not produce a final LLM response")
253+
if kwargs.get("return_runner_messages", False):
254+
runner_messages = []
255+
for msg in agent_runner.run_context.messages:
256+
runner_messages.append(msg.model_dump())
257+
return llm_resp, runner_messages
253258
return llm_resp
254259

255260
async def get_current_chat_provider_id(self, umo: str) -> str:

0 commit comments

Comments
 (0)