If a tool is provided for side-effects, such as printing something to the console or updating a dashboard (think querychat), the model may not reply with any text after the tool is successfully called.
pkgload::load_all()
#> ℹ Loading ellmer
chat <- chat_anthropic()
#> Using model = "claude-sonnet-4-20250514".
provider_anthropic <- chat$get_provider()
show_word <- tool(
function(word) {
cat("The word is:", word, "\n")
"Success. Don't say anything else."
},
name = "show_word",
description = "Show the word to the user.",
arguments = list(
word = type_string()
)
)
chat$register_tool(show_word)
chat$chat("Think of a random word and show it to me.")
#> I'll think of a random word and show it to you.
#> ◯ [tool call] show_word(word = "butterfly")
#> The word is: butterfly
#> ● #> Success. Don't say anything else.
Continuing the conversation leads to an error due to a final, empty assistant message.
chat$chat("What does the word mean?")
#> Error in `req_perform_connection()` at ellmer/R/httr2.R:38:5:
#> ! HTTP 400 Bad Request.
#> ℹ messages.3: all messages must have non-empty content except for the optional
#> final assistant message [invalid_request_error]
chat$get_turns() |> as_json(provider_anthropic, x = _) |> str()
#> List of 4
#> $ :List of 2
#> ..$ role : chr "user"
#> ..$ content:List of 1
#> .. ..$ :List of 2
#> .. .. ..$ type: chr "text"
#> .. .. ..$ text: chr "Think of a random word and show it to me."
#> $ :List of 2
#> ..$ role : chr "assistant"
#> ..$ content:List of 2
#> .. ..$ :List of 2
#> .. .. ..$ type: chr "text"
#> .. .. ..$ text: chr "I'll think of a random word and show it to you."
#> .. ..$ :List of 4
#> .. .. ..$ type : chr "tool_use"
#> .. .. ..$ id : chr "toolu_01PBn2JcfUoQdcunFDwfHCJu"
#> .. .. ..$ name : chr "show_word"
#> .. .. ..$ input:List of 1
#> .. .. .. ..$ word: chr "butterfly"
#> $ :List of 2
#> ..$ role : chr "user"
#> ..$ content:List of 1
#> .. ..$ :List of 4
#> .. .. ..$ type : chr "tool_result"
#> .. .. ..$ tool_use_id: chr "toolu_01PBn2JcfUoQdcunFDwfHCJu"
#> .. .. ..$ content : chr "Success. Don't say anything else."
#> .. .. ..$ is_error : logi FALSE
#> $ :List of 2
#> ..$ role : chr "assistant"
#> ..$ content: list()
chat$get_turns() |> lapply(\(x) x@json) |> str()
#> List of 4
#> $ : list()
#> $ :List of 7
#> ..$ id : chr "msg_01JFo5et9G4aNQUepYR7EvbD"
#> ..$ type : chr "message"
#> ..$ role : chr "assistant"
#> ..$ model : chr "claude-sonnet-4-20250514"
#> ..$ content :List of 2
#> .. ..$ :List of 2
#> .. .. ..$ type: chr "text"
#> .. .. ..$ text: chr "I'll think of a random word and show it to you."
#> .. ..$ :List of 4
#> .. .. ..$ type : chr "tool_use"
#> .. .. ..$ id : chr "toolu_01PBn2JcfUoQdcunFDwfHCJu"
#> .. .. ..$ name : chr "show_word"
#> .. .. ..$ input: chr "{\"word\": \"butterfly\"}"
#> ..$ stop_reason: chr "tool_use"
#> ..$ usage :List of 5
#> .. ..$ input_tokens : int 400
#> .. ..$ cache_creation_input_tokens: int 0
#> .. ..$ cache_read_input_tokens : int 0
#> .. ..$ output_tokens : int 67
#> .. ..$ service_tier : chr "standard"
#> $ : list()
#> $ :List of 7
#> ..$ id : chr "msg_011UmL7GCuouMbGssgbZK1bY"
#> ..$ type : chr "message"
#> ..$ role : chr "assistant"
#> ..$ model : chr "claude-sonnet-4-20250514"
#> ..$ content : list()
#> ..$ stop_reason: chr "end_turn"
#> ..$ usage :List of 5
#> .. ..$ input_tokens : int 486
#> .. ..$ cache_creation_input_tokens: int 0
#> .. ..$ cache_read_input_tokens : int 0
#> .. ..$ output_tokens : int 2
#> .. ..$ service_tier : chr "standard"
If a tool is provided for side-effects, such as printing something to the console or updating a dashboard (think querychat), the model may not reply with any text after the tool is successfully called.
Continuing the conversation leads to an error due to a final, empty assistant message.