A ToolResult answers a ToolCall. Its IsError
flag is one of skyl's genuinely lossy fields — it reaches the model faithfully
on exactly one adapter.
Reference#
type ToolResult struct {
CallID string
Content string
IsError bool
}
Parameters
CallID— must match theToolCall.IDthis result answers. Required.Content— the tool's output, rendered as text.IsError— reports that the tool failed.
Caveats
ValidaterequiresCallID.- Every provider rejects a result that does not follow the call it answers. Append the assistant's turn first.
IsErrorarrives intact only on Anthropic, as a realis_errorboolean.- The OpenAI-format adapters are lossy: they prefix
"error: "to the content, and drop the flag entirely when the content is empty. - Gemini drops it completely — the signal never reaches the wire.
- Never return an empty
Contentfor a failure; it erases the signal on two adapters at once.
Usage#
The portable way to report a failure
// The prose is the signal that works everywhere. IsError is a bonus where
// it survives.
skyl.ToolErrorMessage(call.ID,
fmt.Sprintf("ERROR: %s failed: %v. Do not retry; tell the user the data "+
"is unavailable.", call.Name, err))// The prose is the signal that works everywhere. IsError is a bonus where
// it survives.
skyl.ToolErrorMessage(call.ID,
fmt.Sprintf("ERROR: %s failed: %v. Do not retry; tell the user the data "+
"is unavailable.", call.Name, err))Three things that text does which the boolean cannot: it names the tool, it says what to do next, and it works on all four adapters.
A successful result
skyl.ToolResultMessage(call.ID, "22C and sunny in Kampala")skyl.ToolResultMessage(call.ID, "22C and sunny in Kampala")Constructing one directly
skyl.Message{
Role: skyl.RoleTool,
Parts: []skyl.Part{skyl.ToolResult{
CallID: call.ID,
Content: "22C and sunny",
IsError: false,
}},
}skyl.Message{
Role: skyl.RoleTool,
Parts: []skyl.Part{skyl.ToolResult{
CallID: call.ID,
Content: "22C and sunny",
IsError: false,
}},
}Troubleshooting#
The model kept calling a tool that had failed
On Gemini and, when content is empty, on the OpenAI family, the model was never told it failed. Put the failure in the text and say explicitly not to retry.
A 400 after appending my tool result
Almost always ordering: the assistant turn containing the call must be appended before the result. Every provider enforces this.
A call I skipped caused the whole turn to be rejected
Every call must get a result. If a tool panicked, send an error message rather than nothing.