Hey!
I have a scheduler that triggers a tool function later (outside the original user–model exchange).
When the scheduled time comes, it sends a ToolMessage back into the chat model — but the model returns an empty message (content="") instead of responding.
This is the flow of messages:
[HumanMessage] → [AIMessage] → [ToolMessage] → [AIMessage] → … → [ToolMessage (from scheduled function)]
The final ToolMessage is the one created when the scheduled callback fires.
That’s where the issue happens — the model simply returns an empty string.
The Scheduled Callback:
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} !!!")
Problem
When this scheduled function runs and I call workflow_instance.invoke() with a ToolMessage,
the chat model returns an empty content message AIMessage(content="") — it doesn’t “react” like it normally would when the tool message comes directly during conversation flow.
Expected behavior:
The model should interpret the tool message and respond naturally (e.g., “Hey, it’s time to do your scheduled task!”).
My Question:
How can I correctly re-inject a delayed ToolMessage into the workflow so that the model responds like it does during normal tool use?
Is there something special about how the tool_call_id or message history needs to be linked so the model knows what to do?
Or do I need to send a different type of message (like SystemMessage or AssistantMessage) when reactivating the model after a delay?