You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

延迟ToolMessage注入Chat模型后返回空内容的技术解决方案问询

问题

我有一个调度器,能在原始用户-模型对话之外触发工具函数。到达定时时间时,会向Chat模型发送ToolMessage,但模型返回空内容的AIMessage(content=""),而非正常响应。

消息流

[HumanMessage] → [AIMessage(发起调度)] → 
    [ToolMessage(已调度函数)] → 
    [AIMessage(确认调度)] → ... → 
    [ToolMessage(来自定时函数)]

最后一条ToolMessage由定时回调触发生成,此时模型返回空字符串。

定时回调代码

def _task_reminder_callback(thread_id: str, task_description: str):
    print(f"\n\n === AGENT: TASK REMINDER! (for thread: {thread_id}) === ")
    print(f" TASK: {task_description} ")
    print(" ======================================================= \n\n")

    config = {"configurable": {"thread_id": thread_id, "user_id": "user_123"}}
    workflow_instance = app_state.get("WORKFLOW")

    state = workflow_instance.get_state(config)

    # Find the most recent tool call for schedule_reminder
    tool_call_id = None
    if state and state.values and "messages" in state.values:
        for msg in reversed(state.values["messages"]):
            if hasattr(msg, 'tool_calls') and msg.tool_calls:
                for tool_call in msg.tool_calls:
                    if tool_call.get('name') == 'schedule_reminder':
                        tool_call_id = tool_call.get('id')
                        break
            if tool_call_id:
                break

    print(f'[DEBUG] tool_call_id: {tool_call_id}')

    if workflow_instance:
        try:
            reminder_message = ToolMessage(
                content=(
                    f"REMINDER: generate a natural sounding message to remind user "
                    f"that it's time to do this task:\n\n {task_description}.\n\n"
                ),
                tool_call_id=tool_call_id
            )

            result = workflow_instance.invoke({"messages": reminder_message}, config=config)

            print(f" === Successfully invoked workflow for reminder in thread {thread_id} === \n\n {result} === \n\n")
        except Exception as e:
            print(f"ERROR in _task_reminder_callback for thread {thread_id}: {e} !!! \n\n")
    else:
        print(f"ERROR: WORKFLOW not initialized. Cannot run reminder for thread {thread_id}")

问题现象

定时函数运行并调用workflow_instance.invoke()传入ToolMessage时,Chat模型返回空内容的AIMessage,无法像对话流程中直接接收ToolMessage那样正常响应。

输出示例

HumanMessage(content='ok', additional_kwargs={}, response_metadata={}, id='40ff741d-f298-4fe5-ad54-4e5539aa483c'), AIMessage(content='', additional_kwargs={'function_call': {'name': 'schedule_reminder', 'arguments': '{"time_str": "2025-10-26 13:06:00", "task_description": "drink water"}'}}, response_metadata={'prompt_feedback': {'block_reason': 0, 'safety_ratings': []}, 'finish_reason': 'STOP', 'model_name': 'gemini-2.0-flash', 'safety_ratings': []}, id='lc_run--464ab3c1-8fb3-4c4c-9876-2424c96ac78c-0', tool_calls=[{'name': 'schedule_reminder', 'args': {'time_str': '2025-10-26 13:06:00', 'task_description': 'drink water'}, 'id': 'a1e09652-4b50-4b5c-b2b9-29a280f1b1f6', 'type': 'tool_call'}], usage_metadata={'input_tokens': 1851, 'output_tokens': 30, 'total_tokens': 1881, 'input_token_details': {'cache_read': 0}}), ToolMessage(content="Error: 1 validation error for ScheduleReminderSchema\ntime_str\n  Value error, Time must be in the future. Current time is 2025-10-26 13:06:01.077565 [type=value_error, input_value='2025-10-26 13:06:00', input_type=str]\n Please fix your mistakes.", name='schedule_reminder', id='831e3acd-915c-4063-af40-6bdbd7b221ac', tool_call_id='a1e09652-4b50-4b5c-b2b9-29a280f1b1f6', status='error'), AIMessage(content='I am sorry. I made a mistake. The time must be in the future. Let me try again.', additional_kwargs={'function_call': {'name': 'schedule_reminder', 'arguments': '{"time_str": "2025-10-26 13:10:00", "task_description": "drink water"}'}}, response_metadata={'prompt_feedback': {'block_reason': 0, 'safety_ratings': []}, 'finish_reason': 'STOP', 'model_name': 'gemini-2.0-flash', 'safety_ratings': []}, id='lc_run--4d55aeef-5b66-4a52-81d4-8f0265bc1b9e-0', tool_calls=[{'name': 'schedule_reminder', 'args': {'time_str': '2025-10-26 13:10:00', 'task_description': 'drink water'}, 'id': '5484ca4f-bdbb-4f64-9f75-66bec5bfbb00', 'type': 'tool_call'}], usage_metadata={'input_tokens': 2010, 'output_tokens': 53, 'total_tokens': 2063, 'input_token_details': {'cache_read': 0}}), ToolMessage(content="Successfully scheduled reminder: 'drink water' at 2025-10-26 13:10:00.", name='schedule_reminder', id='15469566-c614-455e-a311-590cc4cbdac8', tool_call_id='5484ca4f-bdbb-4f64-9f75-66bec5bfbb00'), AIMessage(content='I have scheduled a reminder for you to drink water at 2025-10-26 13:10:00.', additional_kwargs={}, response_metadata={'prompt_feedback': {'block_reason': 0, 'safety_ratings': []}, 'finish_reason': 'STOP', 'model_name': 'gemini-2.0-flash', 'safety_ratings': []}, id='lc_run--ff375360-aa24-4a47-9687-204b669c7c47-0', usage_metadata={'input_tokens': 2074, 'output_tokens': 33, 'total_tokens': 2107, 'input_token_details': {'cache_read': 0}}), ToolMessage(content="REMINDER: generate a natural sounding message to remind user that it's time to do this task:\n\n drink water.\n\n", id='b88ab321-c855-4fb0-b8b0-fe0d1836513d', tool_call_id='3d82238b-5b14-4e4c-a56b-a11545184409'), AIMessage(content='', additional_kwargs={}, response_metadata={'prompt_feedback': {'block_reason': 0, 'safety_ratings': []}, 'finish_reason': 'STOP', 'model_name': 'gemini-2.0-flash', 'safety_ratings': []}, id='lc_run--c1aaa8f5-261e-4b68-a163-61b47e493480-0', usage_metadata={'input_tokens': 2106, 'output_tokens': 0, 'total_tokens': 2106, 'input_token_details': {'cache_read': 0}})]}  

疑问

  • 如何正确将延迟的ToolMessage重新注入工作流,使模型像正常使用工具时一样响应?
  • 是否需要对tool_call_id或消息历史进行特殊关联,让模型明确处理逻辑?
  • 或者重新激活模型时需要发送SystemMessage或AssistantMessage这类不同类型的消息?
解决方案

1. 修正ToolMessage的关联逻辑

当前获取的tool_call_id是历史调度工具调用的ID,但定时触发的提醒并非该工具调用的直接返回结果,属于独立的外部触发事件。模型会认为这个ToolMessage是对应之前工具调用的响应,但之前的调用已经完成并得到确认,因此返回空内容。

解决方法:

  • 不需要设置tool_call_id,将其设为None,明确这是新的独立外部触发消息;
  • 若需关联历史任务,可在ToolMessage的content中明确说明这是之前调度的任务到期,而非依赖tool_call_id关联。

修改后的ToolMessage创建代码:

reminder_message = ToolMessage(
    content=(
        f"REMINDER: It's time to complete the task you scheduled earlier:\n\n {task_description}.\n\n"
        f"Please send a friendly reminder message to the user."
    ),
    tool_call_id=None  # 去掉无效的关联ID
)

2. 调整工作流调用方式

直接传入单个ToolMessage可能不符合工作流的预期输入格式,部分LangChain工作流期望接收消息列表,或需要明确触发模型思考流程。

可尝试两种方式:

  • 将ToolMessage包装成列表传入:
result = workflow_instance.invoke({"messages": [reminder_message]}, config=config)
  • 先更新工作流状态添加这条ToolMessage,再触发模型下一步处理:
# 更新状态中的消息历史
state.values["messages"].append(reminder_message)
workflow_instance.set_state(state, config)
# 触发工作流继续执行
result = workflow_instance.invoke({}, config=config)

3. 改用SystemMessage或模拟用户消息触发

若ToolMessage方式不生效,可换用SystemMessage传递提醒指令,或模拟一条标注为系统触发的用户消息:

示例(使用SystemMessage):

from langchain_core.messages import SystemMessage

reminder_message = SystemMessage(
    content=f"SYSTEM REMINDER: The scheduled task '{task_description}' is now due. "
            f"Please generate a natural reminder message for the user."
)
result = workflow_instance.invoke({"messages": [reminder_message]}, config=config)

4. 检查模型的工具调用配置

部分模型(如Gemini)处理工具响应时,会根据之前的工具调用状态判断是否生成响应。如果之前对话已处于"结束"状态(模型最后返回普通文本而非工具调用),模型可能不会对新的ToolMessage做出响应。此时需确保工作流状态处于"等待工具响应"或"可继续对话"状态,或在调用时明确告知模型需要继续处理。


内容的提问来源于stack exchange,提问作者Md Vicky

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 03:45:55