Skip to content

Instantly share code, notes, and snippets.

@badlogic
Last active December 10, 2025 19:11
Show Gist options
  • Select an option

  • Save badlogic/aa8c12f55b2e2f93b9f1d5d31885d981 to your computer and use it in GitHub Desktop.

Select an option

Save badlogic/aa8c12f55b2e2f93b9f1d5d31885d981 to your computer and use it in GitHub Desktop.
Mistral API limitation: user message after tool message not allowed
import { Mistral } from "@mistralai/mistralai";
import { describe, expect, it } from "vitest";
describe.skipIf(!process.env.MISTRAL_API_KEY)("Mistral SDK Direct", () => {
const client = new Mistral({ apiKey: process.env.MISTRAL_API_KEY });
it("tool call + result + user follow-up", async () => {
const response = await client.chat.complete({
model: "devstral-medium-latest",
messages: [
{ role: "user", content: "Check the weather" },
{
role: "assistant",
content: "",
toolCalls: [
{
id: "T7TcP5RVB",
type: "function",
function: {
name: "get_weather",
arguments: JSON.stringify({ location: "Tokyo" }),
},
},
],
},
{
role: "tool",
name: "get_weather",
content: "Weather in Tokyo: 18Β°C",
toolCallId: "T7TcP5RVB",
},
{ role: "user", content: "What was the temperature?" },
],
tools: [
{
type: "function",
function: {
name: "get_weather",
description: "Get weather for a location",
parameters: {
type: "object",
properties: {
location: { type: "string" },
},
},
},
},
],
});
console.log("Response:", JSON.stringify(response, null, 2));
expect(response.choices?.[0]?.finishReason).not.toBe("error");
});
it("emoji in tool result (no user follow-up)", async () => {
const response = await client.chat.complete({
model: "devstral-medium-latest",
messages: [
{ role: "user", content: "Use the test tool" },
{
role: "assistant",
content: "",
toolCalls: [
{
id: "T7TcP5RVB",
type: "function",
function: {
name: "test_tool",
arguments: "{}",
},
},
],
},
{
role: "tool",
name: "test_tool",
content: `Test with emoji πŸ™ˆ and other characters:
- Monkey emoji: πŸ™ˆ
- Thumbs up: πŸ‘
- Heart: ❀️
- Thinking face: πŸ€”
- Rocket: πŸš€
- Mixed text: Mario Zechner wann? Wo? Bin grad Γ€ußersr eventuninformiert πŸ™ˆ
- Japanese: こんにけは
- Chinese: δ½ ε₯½
- Mathematical symbols: βˆ‘βˆ«βˆ‚βˆš
- Special quotes: "curly" 'quotes'`,
toolCallId: "T7TcP5RVB",
},
],
tools: [
{
type: "function",
function: {
name: "test_tool",
description: "A test tool",
parameters: {
type: "object",
properties: {},
},
},
},
],
});
console.log("Response:", JSON.stringify(response, null, 2));
// Model might make another tool call or stop - either is fine, we're testing emoji handling
expect(response.choices?.[0]?.finishReason).toMatch(/stop|tool_calls/);
});
it("emoji in tool result WITH user follow-up (should fail)", async () => {
const response = await client.chat.complete({
model: "devstral-medium-latest",
messages: [
{ role: "user", content: "Use the test tool" },
{
role: "assistant",
content: "",
toolCalls: [
{
id: "T7TcP5RVB",
type: "function",
function: {
name: "test_tool",
arguments: "{}",
},
},
],
},
{
role: "tool",
name: "test_tool",
content: "Result with emoji: πŸ™ˆπŸ‘β€οΈ",
toolCallId: "T7TcP5RVB",
},
{ role: "user", content: "Summarize the tool result" },
],
tools: [
{
type: "function",
function: {
name: "test_tool",
description: "A test tool",
parameters: {
type: "object",
properties: {},
},
},
},
],
});
console.log("Response:", JSON.stringify(response, null, 2));
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment