Single-step vs Multi-step

This guide outlines the difference in model behavior for single-step and multi-step tool use. This is a mode that can be toggled in the Chat API by providing tools and setting the force_single_step parameter.

Single Step Tool Use

Single step tool use is enabled by setting force_single_step=True and providing a list of tools through the Chat API. This forces the model to make just one set of tool calls, after which it will provide a final answer. In single-step tool use, the model cannot make a sequence of tool calls and reason over them.

Note that “single step” doesn’t mean “single tool.” In single-step tool use the model can still call multiple tools by calling them in parallel. Whet this happens, the model will output multiple tool calls in the tool_results part of the response.

When Should I Use Single-step Tool Use?

You should operate in single-step mode when you want the model to answer a question after one step. With a query like “Is there a reservation available at Johnny’s Pizza or Alfredo’s Pizza at 9PM,” for example, the model would query the APIs for Johny’s Pizza and Alfredo’s Pizza, in parallel.

Code example

For the sake of this illustration, we’ll assume a developer is building a chatbot to assist with sales-related questions. The chatbot has access to two tools to answer user questions: a daily sales report tool which holds data on sales volumes, and a product catalog which contains information about each product being sold.

Here is a walkthrough of what a relevant single-step tool use workflow would look like.

Step 1

The developer provides the sales database and the products database to the model using the tools parameter.

Observe that, for each tool, the developer describes the tool name, description, and inputs. Each input can have a type and can be marked as required.

PYTHON
1import cohere
2
3co = cohere.Client(api_key="<YOUR API KEY>")
4
5# tool descriptions that the model has access to
6tools = [
7 {
8 "name": "query_daily_sales_report",
9 "description": "Connects to a database to retrieve overall sales volumes and sales information for a given day.",
10 "parameter_definitions": {
11 "day": {
12 "description": "Retrieves sales data for this day, formatted as YYYY-MM-DD.",
13 "type": "str",
14 "required": True,
15 }
16 },
17 },
18 {
19 "name": "query_product_catalog",
20 "description": "Connects to a a product catalog with information about all the products being sold, including categories, prices, and stock levels.",
21 "parameter_definitions": {
22 "category": {
23 "description": "Retrieves product information data for all products in this category.",
24 "type": "str",
25 "required": True,
26 }
27 },
28 },
29]
30
31# preamble containing instructions about the task and the desired style for the output.
32preamble = """
33## Task & Context
34You help people answer their questions and other requests interactively. You will be asked a very wide array of requests on all kinds of topics. You will be equipped with a wide range of search engines or similar tools to help you, which you use to research your answer. You should focus on serving the user's needs as best you can, which will be wide-ranging.
35
36## Style Guide
37Unless the user asks for a different style of answer, you should answer in full sentences, using proper grammar and spelling.
38"""
39
40# user request
41message = "Can you provide a sales summary for 29th September 2023, and also give me some details about the products in the 'Electronics' category, for example their prices and stock levels?"
42
43response = co.chat(
44 message=message,
45 tools=tools,
46 force_single_step=True,
47 preamble=preamble,
48 model="command-a-03-2025",
49)

Step 2

The model’s response contains the list of appropriate tools to call in order to answer the user’s question, as well as the appropriate inputs for each tool call.

PYTHON
1print("The model recommends doing the following tool calls:")
2print("\n".join(str(tool_call) for tool_call in response.tool_calls))
3
4# An example output:
5# cohere.ToolCall {
6# name: query_daily_sales_report
7# parameters: {'day': '2023-09-29'}
8# generation_id: 4807c924-9003-4d6b-8069-eda03962c465
9# }
10# cohere.ToolCall {
11# name: query_product_catalog
12# parameters: {'category': 'Electronics'}
13# generation_id: 4807c924-9003-4d6b-8069-eda03962c465
14# }

Step 3

Now, the developer will query the appropriate tools and receive a tool result in return.

PYTHON
1tool_results = []
2# Iterate over the tool calls generated by the model
3for tool_call in response.tool_calls:
4 # here is where you would call the tool recommended by the model, using the parameters recommended by the model
5 output = functions_map[tool_call.name](**tool_call.parameters)
6 # store the output in a list
7 outputs = [output]
8 # store your tool results in this format
9 tool_results.append({"call": tool_call, "outputs": outputs})
10
11
12print("Tool results that will be fed back to the model in step 4:")
13print(json.dumps(tool_results, indent=4))
14# Tool results that will be fed back to the model in step 4:
15# [
16# {
17# "call": {
18# "name": "query_daily_sales_report",
19# "parameters": {
20# "day": "2023-09-29"
21# },
22# "generation_id": "4807c924-9003-4d6b-8069-eda03962c465"
23# },
24# "outputs": [
25# {
26# "date": "2023-09-29",
27# "summary": "Total Sales Amount: 10000, Total Units Sold: 250"
28# }
29# ]
30# },
31# {
32# "call": {
33# "name": "query_product_catalog",
34# "parameters": {
35# "category": "Electronics"
36# },
37# "generation_id": "4807c924-9003-4d6b-8069-eda03962c465"
38# },
39# "outputs": [
40# {
41# "category": "Electronics",
42# "products": [
43# {
44# "product_id": "E1001",
45# "name": "Smartphone",
46# "price": 500,
47# "stock_level": 20
48# },
49# {
50# "product_id": "E1002",
51# "name": "Laptop",
52# "price": 1000,
53# "stock_level": 15
54# },
55# {
56# "product_id": "E1003",
57# "name": "Tablet",
58# "price": 300,
59# "stock_level": 25
60# }
61# ]
62# }
63# ]
64# }
65# ]

Step 4

Call the chat endpoint again with the tool results to get the final model answer. Note that this is done through the tool_results parameter, with the other parameters operating as expected.

PYTHON
1response = co.chat(
2 message=message,
3 tools=tools,
4 tool_results=tool_results,
5 preamble=preamble,
6 model="command-a-03-2025",
7 temperature=0.3,
8)
9
10
11print("Final answer:")
12print(response.text)
13
14
15# Final answer:
16# On the 29th of September 2023, there were 250 units sold, with a total sales amount of 10,000.
17
18
19# The Electronics category contains three products:
20# - Smartphone: 500 (price), 20 (stock level)
21# - Laptop: 1000 (price), 15 (stock level)
22# - Tablet: 300 (price), 25 (stock level)

In this step, the model cites which tool results were used to generate the final model answer! These citations make it easy to check where the model’s generated response claims are coming from.

When Should I Use Multi-step Tool Use?

For more complex queries, such as those that require multiple steps, it’s probably better to operate in multi-step mode. You can do this by setting enable_multistep=True and providing a list of tools through the Chat API. In multi-step mode, the model can reason across steps and select multiple tools to answer a question completely.

To illustrate, imagine you give the Chat API a query like “What was the weather where I was yesterday,” along with a location tool (to return the user’s location given a timestamp) and a weather tool (to return the weather at a given location). Here’s what happens:

  • First, the model will make a plan, which consists in first calling the location tool (step 1), and then calling the weather tool (step 2) based on the output of the location tool.
  • Then, the model receives the results of these tool calls and the underlying model’s reasoning.
  • In a subsequent call, the model will determine that it still doesn’t have all the information required to answer, and select another tool.
  • Etc.

In the next section, there’s a code snippet demonstrating how to do this programmatically.

Multi-step Code Examples

Here, we’ll walk through a couple of different ways of using multi-step tool use in order to answer questions about the weather.

$curl --location 'https://api.cohere.ai/v1/chat' \
>--header 'Content-Type: application/json' \
>--header 'Accept: application/json' \
>--header 'Authorization: Bearer <YOUR_API_KEY>' \
>--data '{
> "model": "command-a-03-2025",
> "enable_multi_step": true,
> "message": "What was the weather where I was yesterday?",
> "tools": [
> {
> "name": "get_weather",
> "description": "Gets the weather for a given location",
> "parameter_definitions": {
> "location": {
> "description": "The city and state, e.g. San Francisco, CA",
> "type": "str",
> "required": true
> }
> }
> },
> {
> "name": "get_location",
> "description": "Gets the users current location",
> "parameter_definitions": {
> "time": {
> "description": "The date in format YYYY/MM/DD",
> "type": "str"
> }
> }
> }
> ]
>}'

In the response below, the model selects a tool and returns a message containing its reasoning.

${
> "response_id": "6d6978b1-fdf7-4802-9b5d-953336466d8b",
> "text": "I will find the user's location and then use that to find the weather there yesterday.",
> "generation_id": "5c38b246-4f58-4ccf-b85d-09b25ad506fa",
> "chat_history": [
> {
> "role": "USER",
> "message": "What was the weather where I was yesterday?"
> },
> {
> "role": "CHATBOT",
> "message": "I will find the user's location and then use that to find the weather there yesterday.",
> "tool_calls": [
> {
> "name": "get_location",
> "parameters": {
> "time": "2024/05/09"
> }
> }
> ]
> }
> ],
> "finish_reason": "COMPLETE",
> "meta": {
> "api_version": {
> "version": "1"
> },
> "billed_units": {
> "input_tokens": 52,
> "output_tokens": 35
> },
> "tokens": {
> "input_tokens": 980,
> "output_tokens": 35
> }
> },
> "tool_calls": [
> {
> "name": "get_location",
> "parameters": {
> "time": "2024/05/09"
> }
> }
> ]
>}

In this next request, we’ll send the model the tool result and the reasoning message through the chat_history parameter to get the next tool step. If you’re going to use this approach, make sure to include the reasoning message, as it helps the model select the right tool.

$curl --location 'https://api.cohere.ai/v1/chat' \
>--header 'Content-Type: application/json' \
>--header 'Accept: application/json' \
>--header 'Authorization: Bearer <YOUR_API_KEY>' \
>--data '{
> "model": "command-a-03-2025",
> "enable_multi_step": true,
> "chat_history": [
> {
> "role": "USER",
> "message": "What was the weather where I was yesterday?"
> },
> {
> "role": "CHATBOT",
> "message": "I will find the user'\''s location and then use that to find the weather there yesterday.",
> "tool_calls": [
> {
> "name": "get_location",
> "parameters": {
> "time": "2024/04/30"
> }
> }
> ]
> }
> ],
> "tool_results": [{
> "call": {
> "name": "get_location",
> "parameters": {
> "time": "2024/04/25"
> }
> },
> "outputs": [
> {
> "location": "Toronto, Ontario"
> }
> ]
> }],
> "tools": [
> {
> "name": "get_weather",
> "description": "Gets the weather for a given location",
> "parameter_definitions": {
> "location": {
> "description": "The city and state, e.g. San Francisco, CA",
> "type": "str",
> "required": true
> }
> }
> },
> {
> "name": "get_location",
> "description": "Gets the users current location",
> "parameter_definitions": {
> "time": {
> "description": "The date in format YYYY/MM/DD",
> "type": "str"
> }
> }
> }
> ]
>}'

And here’s the response. As you can see, the model outputs another reasoning step and another tool call request. Again, make sure to include the model reasoning step in the next request via the chat_history.

${
> "response_id": "58897e19-5a63-4781-b9a6-1039e9b76ab4",
> "text": "The user was in Toronto, Ontario yesterday. Now I will find the weather there yesterday.",
> "generation_id": "ca6c183f-43d6-4194-a309-6d61a5ced7be",
> "chat_history": [
> {
> "role": "USER",
> "message": "What was the weather where I was yesterday?"
> },
> {
> "role": "CHATBOT",
> "message": "I will find the user's location and then use that to find the weather there yesterday.",
> "tool_calls": [
> {
> "name": "get_location",
> "parameters": {
> "time": "2024/04/30"
> }
> }
> ]
> },
> {
> "role": "TOOL",
> "tool_results": [
> {
> "call": {
> "name": "get_location",
> "parameters": {
> "time": "2024/04/25"
> }
> },
> "outputs": [
> {
> "location": "Toronto, Ontario"
> }
> ]
> }
> ]
> },
> {
> "role": "CHATBOT",
> "message": "The user was in Toronto, Ontario yesterday. Now I will find the weather there yesterday.",
> "tool_calls": [
> {
> "name": "get_weather",
> "parameters": {
> "location": "Toronto, Ontario"
> }
> }
> ]
> }
> ],
> "finish_reason": "COMPLETE",
> "meta": {
> "api_version": {
> "version": "1"
> },
> "billed_units": {
> "input_tokens": 83,
> "output_tokens": 28
> },
> "tokens": {
> "input_tokens": 1083,
> "output_tokens": 28
> }
> },
> "tool_calls": [
> {
> "name": "get_weather",
> "parameters": {
> "location": "Toronto, Ontario"
> }
> }
> ]
>}

In this final request, the tool results for get_weather are passed to the model along with the text containing the model’s reasoning text, so that the final text can be generated.

$curl --location 'https://api.cohere.ai/v1/chat' \
>--header 'Content-Type: application/json' \
>--header 'Accept: application/json' \
>--header 'Authorization: Bearer <YOUR_API_KEY>' \
>--data '{
> "model": "command-a-03-2025",
> "enable_multi_step": true,
> "chat_history": [
> {
> "role": "USER",
> "message": "What was the weather where I was yesterday?"
> },
> {
> "role": "CHATBOT",
> "message": "I will find the user'\''s location and then use that to find the weather there yesterday",
> "tool_calls": [
> {
> "name": "get_location",
> "parameters": {
> "time": "2024/04/30"
> }
> }
> ]
> },
> {
> "role": "TOOL",
> "tool_results": [
> {
> "call": {
> "name": "get_location",
> "parameters": {
> "time": "2024/04/25"
> }
> },
> "outputs": [
> {
> "location": "Toronto, Ontario"
> }
> ]
> }
> ]
> },
> {
> "role": "CHATBOT",
> "message": "The user was in Toronto, Ontario yesterday. Now I will find the weather there yesterday.",
> "tool_calls": [
> {
> "name": "get_weather",
> "parameters": {
> "location": "Toronto, Ontario"
> }
> }
> ]
> }
> ],
> "tool_results": [{
> "call": {
> "name": "get_weather",
> "parameters": {
> "time": "Toronto, Ontario"
> }
> },
> "outputs": [
> {
> "temperature": "18 celsius", "weather": "cloudy"
> }
> ]
> }],
> "tools": [
> {
> "name": "get_weather",
> "description": "Gets the weather for a given location",
> "parameter_definitions": {
> "location": {
> "description": "The city and state, e.g. San Francisco, CA",
> "type": "str",
> "required": true
> }
> }
> },
> {
> "name": "get_location",
> "description": "Gets the users current location",
> "parameter_definitions": {
> "time": {
> "description": "The date in format YYYY/MM/DD",
> "type": "str"
> }
> }
> }
> ]
>}'

And in the final response, the model completes a sequence of tool calls and outputs the final message.

${
> "response_id": "8ea52e5f-f376-4d06-b308-3318296ecebb",
> "text": "Yesterday, in Toronto, Ontario, the weather was cloudy and the temperature was 18°C.",
> "generation_id": "67190a18-3cee-490a-95fc-ddd22b611672",
> "chat_history": [
> {
> "role": "USER",
> "message": "What was the weather where I was yesterday?"
> },
> {
> "role": "CHATBOT",
> "message": "I will find the user's location and then use that to find the weather there yesterday",
> "tool_calls": [
> {
> "name": "get_location",
> "parameters": {
> "time": "2024/04/30"
> }
> }
> ]
> },
> {
> "role": "TOOL",
> "tool_results": [
> {
> "call": {
> "name": "get_location",
> "parameters": {
> "time": "2024/04/25"
> }
> },
> "outputs": [
> {
> "location": "Toronto, Ontario"
> }
> ]
> }
> ]
> },
> {
> "role": "CHATBOT",
> "message": "The user was in Toronto, Ontario yesterday. Now I will find the weather there yesterday.",
> "tool_calls": [
> {
> "name": "get_weather",
> "parameters": {
> "location": "Toronto, Ontario"
> }
> }
> ]
> },
> {
> "role": "TOOL",
> "tool_results": [
> {
> "call": {
> "name": "get_weather",
> "parameters": {
> "time": "Toronto, Ontario"
> }
> },
> "outputs": [
> {
> "temperature": "18 celsius",
> "weather": "cloudy"
> }
> ]
> }
> ]
> },
> {
> "role": "CHATBOT",
> "message": "Yesterday, in Toronto, Ontario, the weather was cloudy and the temperature was 18°C."
> }
> ],
> "finish_reason": "COMPLETE",
> "meta": {
> "api_version": {
> "version": "1"
> },
> "billed_units": {
> "input_tokens": 120,
> "output_tokens": 21
> },
> "tokens": {
> "input_tokens": 1184,
> "output_tokens": 21
> }
> },
> "citations": [
> {
> "start": 14,
> "end": 30,
> "text": "Toronto, Ontario",
> "document_ids": [
> "get_location:0:2:0"
> ]
> },
> {
> "start": 48,
> "end": 54,
> "text": "cloudy",
> "document_ids": [
> "get_weather:0:4:0"
> ]
> },
> {
> "start": 79,
> "end": 83,
> "text": "18°C",
> "document_ids": [
> "get_weather:0:4:0"
> ]
> }
> ],
> "documents": [
> {
> "id": "get_location:0:2:0",
> "location": "Toronto, Ontario",
> "tool_name": "get_location"
> },
> {
> "id": "get_weather:0:4:0",
> "temperature": "18 celsius",
> "tool_name": "get_weather",
> "weather": "cloudy"
> }
> ]
>}

Best practices

Use single step when you want to force the model to answer the user query using a single tool. Otherwise, the model may take more steps than necessary to provide an answer.

Summary of Key Differences

Single step tool useMulti step tool use
Model outputs reasoningNoYes
Max number of tool call steps before final answer is produced115