M
Mastra3w ago
liger

Sending tool messages back

Hi, As far as I understand, we should send back the assistant messages with tool-call and the tool message with tool-result back to the model also on subsequent messages, not just for the last message. Which may look like; role: user with prompt role: assistant with tool-call request role: tool with tool-result role: assistant with reply to user prompt considering tool result a while later, again.. user assistant with tool-call tool with tool-result assistant And if there were multiple tool calls, it could look like user assistant with first tool-call tool with first tool-result assistant with second tool-call tool with second tool-result assistant with third tool-call tool with third tool-result assistant Given that I should send back the older messages with tool-call and tool-result, I have a few questions around this: - I couldn't find a clean way (besides an heuristic) to pick just the right tool-call/tool-result messages from the final stream chunk to save on my db for user conversation history so that I can return those as part of messages: []. What is the suggestion, is there a helper function or am I missing something here? - I understand Mastra and/or AI SDK transforms/normalizes the shape of the message item, some properties like tool_call_id becomes toolCallId and maps message item to a different data structure.. I would like to ideally store the tool-call and tool-request messages on my db as expected by the model API. But when I send back the messages:[] list in shape of what model API would expect, Mastra discards the messages from assistant with tool_calls list and messages from tool with tool_call_id etc. I guess I am doing something wrong here or not utilizing a helper function that might be around? Correction: AI SDK discards tool_calls: [] and drops the tool message altogether. Appreciate your time and support!
11 Replies
Mastra Triager
📝 Created GitHub issue: https://github.com/mastra-ai/mastra/issues/10386 🔍 If you're experiencing an error, please provide a minimal reproducible example whenever possible to help us resolve it quickly. 🙏 Thank you for helping us improve Mastra!
liger
ligerOP3w ago
Correction to original post: AI SDK discards tool_calls: [] and converts the tool message to assistant message while dropping the tool_call_id. I'm not sure if this is expected, when I observe the requests going from Mastra Studio, the integrity of the tool call and tool result message are maintained.
logger.info({ messages }, 'before conversion');
const convertedMessages = convertMessages(messages).to('AIV5.Model');
logger.info({ convertedMessages }, 'after conversion');
logger.info({ messages }, 'before conversion');
const convertedMessages = convertMessages(messages).to('AIV5.Model');
logger.info({ convertedMessages }, 'after conversion');
[2025-11-21 12:52:09:119] INFO: before conversion
{
"messages": [
{
"role": "user",
"content": [
{
"text": "Tell me about xyz",
"type": "text"
}
]
},
{
"role": "assistant",
"content": "",
"tool_calls": [
{
"id": "call_ZgjQ5HRiLUttzf4NFeTWYJd5",
"type": "function",
"function": {
"arguments": "{\"query\":\"xyz\"}",
"name": "wikiSearchTool"
}
}
]
},
{
"role": "tool",
"content": "[{\"content\":\"No content was found\",\"page\":{\"title\":\"\",\"url\":\"https://example.com\"},\"space\":{\"name\":\"John Doe\",\"url\":\"https://example.com\"}}]",
"tool_call_id": "call_ZgjQ5HRiLUttzf4NFeTWYJd5"
}
]
}

[2025-11-21 12:52:09:119] INFO: after conversion
{
"convertedMessages": [
{
"role": "user",
"content": [
{
"type": "text",
"text": "Tell me about xyz"
}
]
},
{
"role": "assistant",
"content": [
{
"type": "text",
"text": ""
}
]
},
{
"role": "assistant",
"content": [
{
"type": "text",
"text": "[{\"content\":\"No content was found\",\"page\":{\"title\":\"\",\"url\":\"https://example.com\"},\"space\":{\"name\":\"John Doe\",\"url\":\"https://example.com\"}}]"
}
]
}
]
}
[2025-11-21 12:52:09:119] INFO: before conversion
{
"messages": [
{
"role": "user",
"content": [
{
"text": "Tell me about xyz",
"type": "text"
}
]
},
{
"role": "assistant",
"content": "",
"tool_calls": [
{
"id": "call_ZgjQ5HRiLUttzf4NFeTWYJd5",
"type": "function",
"function": {
"arguments": "{\"query\":\"xyz\"}",
"name": "wikiSearchTool"
}
}
]
},
{
"role": "tool",
"content": "[{\"content\":\"No content was found\",\"page\":{\"title\":\"\",\"url\":\"https://example.com\"},\"space\":{\"name\":\"John Doe\",\"url\":\"https://example.com\"}}]",
"tool_call_id": "call_ZgjQ5HRiLUttzf4NFeTWYJd5"
}
]
}

[2025-11-21 12:52:09:119] INFO: after conversion
{
"convertedMessages": [
{
"role": "user",
"content": [
{
"type": "text",
"text": "Tell me about xyz"
}
]
},
{
"role": "assistant",
"content": [
{
"type": "text",
"text": ""
}
]
},
{
"role": "assistant",
"content": [
{
"type": "text",
"text": "[{\"content\":\"No content was found\",\"page\":{\"title\":\"\",\"url\":\"https://example.com\"},\"space\":{\"name\":\"John Doe\",\"url\":\"https://example.com\"}}]"
}
]
}
]
}
Grayson
Grayson3w ago
Hey @liger can you share more about what you are trying to do. Are you trying to store with a custom memory solution? I believe Mastras built-in Memory solves the issues you are asking
liger
ligerOP7d ago
Hi @Grayson Thank you for the follow-up. I'm trying to save and send back the tool-call and tool-result messages as separate message as expected by OpenAI. I do not wish you use built-in Memory, I'm integrating into an existing application and there is already a db with thousands of messages. (I'm also hesitant to say using Memory would solve this, because the message converters appear to be either stripping out tool messages or transforming them partially.) Is there anybody from the team willing understand/discuss the issue?
Grayson
Grayson7d ago
Hey @liger sorry I was out of office last week! Yea I can ping some others Will dig in to this a bit today
liger
ligerOP7d ago
Hey @Grayson Thanks! Feel free to ask any question, I'm happy to answer/provide anything I can. I understand it can be a bit hard to align on each others assumptions, expectations and the current behavior to even start reasoning about my query 🙂 Appreciate your time!
Grayson
Grayson7d ago
Okay, after chatting with @Abhi Aiyer think this is a bug. will take a look at the convertMessages function Hey @liger I published a snapshot to npm with potential fix. Can you try this version (update your mastra deps in package json to this version) and let me know if it resolves? 0.0.0-fix-10386-preserve-tool-calls-in-convert-aisdk-20251201210222 Draft PR is here: https://github.com/mastra-ai/mastra/pull/10736 I think just update mastra/core with that version (may have an npm publish issue on that snapshot, so if you hit errors, let me know)
liger
ligerOP6d ago
Hi, thank you for the update! I’ll try it out and get back to you as soon as I can 🙌
Ward
Ward6d ago
To understand this myself @liger are these client side tools or openai internal tools, like search?
liger
ligerOP5d ago
Hi @Ward Sure. In practice the tools are on my backend and created using Mastra's createTool(). Eventually they get sent to the model as described here https://platform.openai.com/docs/guides/function-calling so in that sense, I'd say they are neither client side tool nor openai internal tools. But I'd be happy to hear if you feel something's off or if you have a different suggestion/view.
_roamin_
_roamin_4d ago
Hey @liger ! Did the fix Grayson shared with you helped with the issue you're having?

Did you find this page helpful?