도구 사용(함수 호출)의 사용 패턴

도구 사용(함수 호출)의 사용 패턴

병렬 도구 호출, 다단계 도구 사용 등 Cohere Chat 엔드포인트로 다양한 도구 사용 패턴을 구현하는 방법에 대한 가이드예요 (API v2).

출처: 문서

본문

Chat 엔드포인트의 도구 사용 기능은 개발자가 다양한 도구 사용 시나리오를 구현할 수 있게 해주는 일련의 능력과 함께 제공돼요. 이 섹션은 이러한 능력들이 지원하는 도구 사용 구현의 서로 다른 패턴을 설명합니다. 각 패턴은 단독으로 또는 다른 패턴과 조합해 구현할 수 있어요.

설정(Setup)

먼저 Cohere 라이브러리를 임포트하고 클라이언트를 만듭니다.

Cohere 플랫폼

PYTHON

# ! pip install -U cohere
import cohere

co = cohere.ClientV2(
    "COHERE_API_KEY"
)  # Get your free API key here: https://dashboard.cohere.com/api-keys

프라이빗 배포(Private deployment)

PYTHON

# ! pip install -U cohere
import cohere

co = cohere.ClientV2(
    api_key="",  # Leave this blank
    base_url="<YOUR_DEPLOYMENT_URL>",
)

이전 예시와 동일한 search_docs 도구를 사용할게요.

PYTHON

def search_docs(query, top_k=3):
    # Implement any retrieval logic here (vector DB, keyword search, etc.)
    return [
        {
            "title": "Tool use (function calling) overview",
            "url": "https://docs.cohere.com/v2/docs/tool-use-overview",
            "text": "Tool use connects models to external tools like search engines and APIs.",
        },
        {
            "title": "Structured outputs",
            "url": "https://docs.cohere.com/docs/structured-outputs",
            "text": "Use JSON schema to define structured inputs/outputs for tools and responses.",
        },
        {
            "title": "Chat API reference (v2)",
            "url": "https://docs.cohere.com/reference/chat",
            "text": "Use the Chat endpoint to generate responses and optionally call tools.",
        },
    ][:top_k]
    # Return a string or a list of objects. In Step 3, we'll wrap each object into a `document` content block.


functions_map = {"search_docs": search_docs}

tools = [
    {
        "type": "function",
        "function": {
            "name": "search_docs",
            "description": "Search documentation and return relevant snippets as documents.",
            "parameters": {
                "type": "object",
                "properties": {
                    "query": {
                        "type": "string",
                        "description": "The search query to look up in the docs.",
                    },
                    "top_k": {
                        "type": "integer",
                        "description": "How many documents to return.",
                    },
                },
                "required": ["query"],
            },
        },
    },
]

병렬 도구 호출(Parallel tool calling)

모델은 두 개 이상의 도구 호출이 필요하다고 판단할 수 있으며, 이때 여러 도구를 병렬로 호출해요. 이는 같은 도구를 여러 번 호출하거나, 얼마든지 많은 호출에 걸쳐 다른 도구들을 호출하는 것일 수 있어요.

아래 예시에서 사용자는 도구 사용과 구조화된 출력에 관한 문서를 요청해요. 이는 search_docs 도구를 주제당 한 번씩 두 번 호출해야 합니다. 이는 모델의 응답에 반영되어, 두 개의 병렬 도구 호출이 생성됩니다.

PYTHON

messages = [
    {
        "role": "user",
        "content": "Find docs about tool use and structured outputs.",
    }
]

response = co.chat(
    model="command-a-plus-05-2026", messages=messages, tools=tools
)

if response.message.tool_calls:
    messages.append(response.message)
    print(response.message.tool_plan, "\n")
    print(response.message.tool_calls)

cURL

curl --request POST \
  --url https://api.cohere.ai/v2/chat \
  --header 'accept: application/json' \
  --header 'content-type: application/json' \
  --header "Authorization: bearer ***" \
  --data '{
  "model": "command-a-plus-05-2026",
  "messages": [
    {
      "role": "user",
      "content": "Find docs about tool use and structured outputs."
    }
  ],
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "search_docs",
        "description": "Search documentation and return relevant snippets as documents.",
        "parameters": {
          "type": "object",
          "properties": {
            "query": {
              "type": "string",
              "description": "The search query to look up in the docs."
            },
            "top_k": {
              "type": "integer",
              "description": "How many documents to return."
            }
          },
          "required": ["query"]
        }
      }
    }
  ]
}'

예제 응답:

I will search the docs for tool use and structured outputs.

[
    ToolCallV2(
        id="search_docs_9b0nr4kg58a8",
        type="function",
        function=ToolCallV2Function(
            name="search_docs", arguments='{"query":"tool use","top_k":3}'
        ),
    ),
    ToolCallV2(
        id="search_docs_0qq0mz9gwnqr",
        type="function",
        function=ToolCallV2Function(
            name="search_docs", arguments='{"query":"structured outputs","top_k":3}'
        ),
    ),
]

상태 관리(State management)

도구가 병렬로 호출될 때는 모든 도구 호출을 담은 단일 assistant 메시지 하나와 각 도구 호출에 대한 tool 메시지 하나를 messages 목록에 추가합니다.

PYTHON

import json

if response.message.tool_calls:
    for tc in response.message.tool_calls:
        tool_result = functions_map[tc.function.name](
            **json.loads(tc.function.arguments)
        )
        tool_content = []
        for data in tool_result:
            # Optional: the "document" object can take an "id" field for use in citations, otherwise auto-generated
            tool_content.append(
                {
                    "type": "document",
                    "document": {"data": json.dumps(data)},
                }
            )
        messages.append(
            {
                "role": "tool",
                "tool_call_id": tc.id,
                "content": tool_content,
            }
        )

메시지의 순서는 아래 다이어그램에 표현되어 있습니다.

%%{init: {'htmlLabels': true}}%%
flowchart TD
    classDef defaultStyle fill:#fff,stroke:#000,color:#000;

    A["<div><b>USER</b><br />Query</div>"]
    B["<div><b>ASSISTANT</b><br />Tool calls</div>"]
    C["<div><b>TOOL</b><br />Tool result #1</div>"]
    D["<div><b>TOOL</b><br />Tool result #2</div>"]
    E["<div><b>TOOL</b><br />Tool result #N</div>"]
    F["<div><b>ASSISTANT</b><br />Response</div>"]

    A -.-> B
    B -.-> C
    C -.-> D
    D -.-> E
    E -.-> F

    class A,B,C,D,E,F defaultStyle;

직접 응답(Directly answering)

도구 사용 시스템의 핵심 속성은 작업에 적합한 도구를 선택하는 모델의 능력이에요. 여기에는 도구를 전혀 사용하지 않기로 결정하고, 대신 사용자 메시지에 직접 응답하는 모델의 능력도 포함됩니다.

아래 예시에서 사용자는 간단한 산술 질문을 해요. 모델은 사용 가능한 도구(이 경우엔 search_docs 단 하나) 중 어떤 것도 사용할 필요가 없다고 판단하고, 대신 사용자에게 직접 답합니다.

PYTHON

messages = [{"role": "user", "content": "What's 2+2?"}]

response = co.chat(
    model="command-a-plus-05-2026", messages=messages, tools=tools
)

if response.message.tool_calls:
    print(response.message.tool_plan, "\n")
    print(response.message.tool_calls)

else:
    print(response.message.content[0].text)

cURL

curl --request POST \
  --url https://api.cohere.ai/v2/chat \
  --header 'accept: application/json' \
  --header 'content-type: application/json' \
  --header "Authorization: bearer ***" \
  --data '{
  "model": "command-a-plus-05-2026",
  "messages": [
    {
      "role": "user",
      "content": "What'\''s 2+2?"
    }
  ],
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "search_docs",
        "description": "Search documentation and return relevant snippets as documents.",
        "parameters": {
          "type": "object",
          "properties": {
            "query": {
              "type": "string",
              "description": "The search query to look up in the docs."
            },
            "top_k": {
              "type": "integer",
              "description": "How many documents to return."
            }
          },
          "required": ["query"]
        }
      }
    }
  ]
}'

예제 응답:

The answer to 2+2 is 4.

상태 관리(State management)

모델이 사용자에게 직접 응답하기로 선택하면 위의 항목 2와 3(도구 호출 및 도구 응답 메시지)은 없어요. 대신 최종 assistant 메시지가 사용자에 대한 모델의 직접 응답을 담습니다.

%%{init: {'htmlLabels': true}}%%
flowchart TD
    classDef defaultStyle fill:#fff,stroke:#000,color:#000;

    A["<div><b>USER</b><br />Query</div>"]
    B["<div><b>ASSISTANT</b><br />Response</div>"]

    A -.-> B

    class A,B defaultStyle;

참고: tool_choice 파라미터를 사용해 여기에 설명된 대로 매번 모델이 직접 응답하도록 강제할 수 있어요.

다단계 도구 사용(Multi-step tool use)

Chat 엔드포인트는 모델이 순차적 추론을 수행할 수 있게 해주는 다단계 도구 사용을 지원해요. 이는 작업을 완료하기 위해 여러 단계가 필요한 에이전트형 워크플로에서 특히 유용합니다.

예를 들어, 어떤 도구 사용 애플리케이션이 웹 검색 도구에 접근할 수 있다고 가정해 보세요. "2023년 미국에서 가장 가치 있는 회사의 수익은 얼마였나요?"라는 질문이 주어지면 특정 순서로 일련의 단계를 수행해야 합니다:

  • 2023년 미국에서 가장 가치 있는 회사 식별
  • 그런 다음 회사가 식별된 상태에서 수익 수치만 얻기

이를 설명하기 위해 search_docs 도구를 사용하고, 보통 여러 번의 검색(처음에는 도구 사용 기초, 그다음에는 tool_choice)이 필요한 질문을 할게요.

다음은 도구의 함수 정의입니다:

PYTHON

def search_docs(query, top_k=3):
    # Implement any retrieval logic here (vector DB, keyword search, etc.)
    return [
        {
            "title": "Tool use (function calling) overview",
            "url": "https://docs.cohere.com/v2/docs/tool-use-overview",
            "text": "Tool use connects models to external tools like search engines and APIs.",
        },
        {
            "title": "Usage patterns for tool use",
            "url": "https://docs.cohere.com/v2/docs/tool-use-usage-patterns",
            "text": "Common patterns include parallel tool calling, multi-step tool use, and more.",
        },
        {
            "title": "Structured outputs",
            "url": "https://docs.cohere.com/docs/structured-outputs",
            "text": "Use JSON schema to define structured inputs/outputs for tools and responses.",
        },
    ][:top_k]


functions_map = {"search_docs": search_docs}

그리고 해당 도구 스키마는 다음과 같습니다:

PYTHON

tools = [
    {
        "type": "function",
        "function": {
            "name": "search_docs",
            "description": "Search documentation and return relevant snippets as documents.",
            "parameters": {
                "type": "object",
                "properties": {
                    "query": {
                        "type": "string",
                        "description": "The search query to look up in the docs.",
                    },
                    "top_k": {
                        "type": "integer",
                        "description": "How many documents to return.",
                    },
                },
                "required": ["query"],
            },
        },
    },
]

다음으로, 이전 페이지에서 설명한 네 단계 도구 사용 워크플로를 구현합니다.

여기서 핵심 차이는 두 번째(도구 호출)와 세 번째(도구 실행) 단계가 while 루프에 들어간다는 점이에요. 즉 이 쌍의 시퀀스가 여러 번 일어날 수 있다는 뜻입니다. 이는 모델이 도구 호출 단계에서 더 이상 도구 호출이 필요 없다고 결정할 때 멈추며, 그때 네 번째 단계(응답 생성)가 촉발됩니다.

이 예시에서 사용자는 도구 사용에 대한 설명과 도구 사용을 강제하는 방법을 인용과 함께 요청합니다.

PYTHON

import json

# Step 1: Get the user message
messages = [
    {
        "role": "user",
        "content": "Explain how tool use works and how to force tool usage. Please cite your sources.",
    }
]

# Step 2: Generate tool calls (if any)
model = "command-a-plus-05-2026"
response = co.chat(
    model=model, messages=messages, tools=tools, temperature=0.3
)

while response.message.tool_calls:
    print("TOOL PLAN:")
    print(response.message.tool_plan, "\n")
    print("TOOL CALLS:")
    for tc in response.message.tool_calls:
        print(
            f"Tool name: {tc.function.name} | Parameters: {tc.function.arguments}"
        )
    print("=" * 50)

    messages.append(response.message)

    # Step 3: Get tool results
    print("TOOL RESULT:")
    for tc in response.message.tool_calls:
        tool_result = functions_map[tc.function.name](
            **json.loads(tc.function.arguments)
        )
        tool_content = []
        print(tool_result)
        for data in tool_result:
            # Optional: the "document" object can take an "id" field for use in citations, otherwise auto-generated
            tool_content.append(
                {
                    "type": "document",
                    "document": {"data": json.dumps(data)},
                }
            )
        messages.append(
            {
                "role": "tool",
                "tool_call_id": tc.id,
                "content": tool_content,
            }
        )

    # Step 4: Generate response and citations
    response = co.chat(
        model=model,
        messages=messages,
        tools=tools,
        temperature=0.1,
    )

messages.append(
    {
        "role": "assistant",
        "content": response.message.content[0].text,
    }
)

# Print final response
print("RESPONSE:")
print(response.message.content[0].text)
print("=" * 50)

# Print citations (if any)
verbose_source = (
    True  # Change to True to display the contents of a source
)
if response.message.citations:
    print("CITATIONS:\n")
    for citation in response.message.citations:
        print(
            f"Start: {citation.start}| End:{citation.end}| Text:'{citation.text}' "
        )
        print("Sources:")
        for idx, source in enumerate(citation.sources):
            print(f"{idx+1}. {source.id}")
            if verbose_source:
                print(f"{source.tool_output}")
        print("\n")

모델은 먼저 도구 사용에 관한 문서를 찾아봐야 한다고 결정한 다음, tool_choice를 통해 도구 사용 강제에 대한 세부 사항을 두 번째 검색할 수 있어요.

이것은 모델 응답에 반영되며, 여기서 여러 도구 호출-결과 쌍이 시퀀스로 생성될 수 있습니다.

예제 응답:

TOOL PLAN:
First, I will search the docs for how tool use works. Then, I will search for how to force tool usage (tool_choice).

TOOL CALLS:
Tool name: search_docs | Parameters: {"query":"tool use","top_k":3}
==================================================
TOOL RESULT:
[{'title': 'Tool use (function calling) overview', 'url': 'https://docs.cohere.com/v2/docs/tool-use-overview', 'text': 'Tool use connects models to external tools like search engines and APIs.'}]
TOOL PLAN:
Now I'll search for how to force tool usage via the tool_choice parameter.

TOOL CALLS:
Tool name: search_docs | Parameters: {"query":"tool_choice REQUIRED NONE","top_k":3}
==================================================
TOOL RESULT:
[{'title': 'Usage patterns for tool use', 'url': 'https://docs.cohere.com/v2/docs/tool-use-usage-patterns', 'text': 'Common patterns include parallel tool calling, multi-step tool use, and more.'}]
RESPONSE:
Tool use lets models call external tools (like doc search) and then answer using tool results with citations. You can force tool usage with tool_choice="REQUIRED" or force a direct response with tool_choice="NONE".
==================================================
CITATIONS:

Start: 126| End:135| Text:'tool_choice'
Sources:
1. search_docs_p0dage9q1nv4:0
{'title': 'Usage patterns for tool use', 'url': 'https://docs.cohere.com/v2/docs/tool-use-usage-patterns', 'text': 'Common patterns include parallel tool calling, multi-step tool use, and more.'}

상태 관리(State management)

다단계 도구 사용 시나리오에서는 assistant-tool 메시지가 한 번만 발생하는 대신, 관련된 여러 단계의 도구 호출을 반영해 assistant-tool 메시지의 시퀀스가 있게 됩니다.

%%{init: {'htmlLabels': true}}%%
flowchart TD
    classDef defaultStyle fill:#fff,stroke:#000,color:#000;

    A["<div style='color:black;'><b>USER</b><br />Query</div>"]
    B1["<div style='color:black;'><b>ASSISTANT</b><br />Tool call step #1</div>"]
    C1["<div style='color:black;'><b>TOOL</b><br />Tool result step #1</div>"]
    B2["<div style='color:black;'><b>ASSISTANT</b><br />Tool call step #2</div>"]
    C2["<div style='color:black;'><b>TOOL</b><br />Tool result step #2</div>"]
    BN["<div style='color:black;'><b>ASSISTANT</b><br />Tool call step #N</div>"]
    CN["<div style='color:black;'><b>TOOL</b><br />Tool result step #N</div>"]
    D["<div style='color:black;'><b>ASSISTANT</b><br />Response</div>"]

    A -.-> B1
    B1 -.-> C1
    C1 -.-> B2
    B2 -.-> C2
    C2 -.-> BN
    BN -.-> CN
    CN -.-> D

    class A,B1,C1,B2,C2,BN,CN,D defaultStyle;

도구 사용 강제(Forcing tool usage)

참고(Note)

이 기능은 Command R7B 및 이후 모델과만 호환됩니다.

이전 예시들에서 볼 수 있듯이, 도구 호출 단계에서 모델은 다음 중 하나를 결정할 수 있어요:

  • 도구 호출을 만들거나
  • 또는 사용자 메시지에 직접 응답.

하지만 이 옵션 중 하나를 선택하도록 모델을 강제할 수 있어요. 이는 tool_choice 파라미터를 통해 이루어집니다.

  • tool_choice 파라미터를 REQUIRED로 설정하면 모델이 도구 호출을 만들도록 강제할 수 있어요, 즉 직접 응답하지 않게 하는 것입니다.
  • 또는 tool_choice 파라미터를 NONE으로 설정하면 모델이 직접 응답하도록 강제할 수 있어요, 즉 도구 호출을 만들지 않게 하는 것입니다.

기본적으로 tool_choice 파라미터를 지정하지 않으면, 도구 호출을 할지 직접 응답할지는 모델이 결정합니다.

PYTHON

response = co.chat(
    model="command-a-plus-05-2026",
    messages=messages,
    tools=tools,
    tool_choice="REQUIRED" # optional, to force tool calls
    # tool_choice="NONE" # optional, to force a direct response
)

상태 관리(State management)

tool_choice가 REQUIRED로 설정되었을 때의 메시지 순서는 다음과 같습니다.

%%{init: {'htmlLabels': true}}%%
flowchart TD
    classDef defaultStyle fill:#fff,stroke:#000,color:#000;

    A["<div><b>USER</b><br />Query</div>"]
    B["<div><b>ASSISTANT</b><br />Tool call</div>"]
    C["<div><b>TOOL</b><br />Tool result</div>"]
    D["<div><b>ASSISTANT</b><br />Response</div>"]

    A -.-> B
    B -.-> C
    C -.-> D

    class A,B,C,D defaultStyle;

tool_choice가 NONE으로 설정되었을 때의 메시지 순서는 다음과 같습니다.

%%{init: {'htmlLabels': true}}%%
flowchart TD
    classDef defaultStyle fill:#fff,stroke:#000,color:#000;

    A["<div><b>USER</b><br />Query</div>"]
    B["<div><b>ASSISTANT</b><br />Response</div>"]

    A -.-> B

    class A,B defaultStyle;

챗봇(다중 턴, Chatbots)

챗봇을 구축하려면 여러 턴에 걸친 대화의 메모리 또는 상태를 유지해야 해요. 이를 위해 대화의 각 턴을 계속 messages 목록에 추가하면 됩니다.

예를 들어, 다음은 대화 첫 번째 턴의 messages 목록입니다.

PYTHON

from cohere import ToolCallV2, ToolCallV2Function

messages = [
    {
        "role": "user",
        "content": "How does tool use work in Cohere? Please cite your sources.",
    },
    {
        "role": "assistant",
        "tool_plan": "I will search the docs for how tool use works in Cohere.",
        "tool_calls": [
            ToolCallV2(
                id="search_docs_1byjy32y4hvq",
                type="function",
                function=ToolCallV2Function(
                    name="search_docs",
                    arguments='{"query":"tool use Cohere","top_k":3}',
                ),
            )
        ],
    },
    {
        "role": "tool",
        "tool_call_id": "search_docs_1byjy32y4hvq",
        "content": [
            {
                "type": "document",
                "document": {
                    "data": '{"title":"Tool use (function calling) overview","url":"https://docs.cohere.com/v2/docs/tool-use-overview","text":"Tool use connects models to external tools like search engines and APIs."}'
                },
            }
        ],
    },
    {
        "role": "assistant",
        "content": "Tool use lets models call external tools (like doc search) and then answer using tool results with citations.",
    },
]

그런 다음 두 번째 턴에서, 다소 모호한 후속 사용자 메시지가 주어지면 모델은 맥락이 여전히 도구 사용에 관한 것임을 올바르게 추론하고, tool_choice에 대한 정보를 검색합니다.

PYTHON

messages.append(
    {"role": "user", "content": "How do I force tool usage?"}
)

response = co.chat(
    model="command-a-plus-05-2026", messages=messages, tools=tools
)

if response.message.tool_calls:
    messages.append(response.message)
    print(response.message.tool_plan, "\n")
    print(response.message.tool_calls)

cURL

curl --request POST   --url https://api.cohere.ai/v2/chat   --header 'accept: application/json'   --header 'content-type: application/json'   --header "Authorization: bearer ***"   --data '{
  "model": "command-a-plus-05-2026",
  "messages": [
    {
      "role": "user",
      "content": "How does tool use work in Cohere? Please cite your sources."
    },
    {
      "role": "assistant",
      "tool_plan": "I will search the docs for how tool use works in Cohere.",
      "tool_calls": [
        {
          "id": "search_docs_1byjy32y4hvq",
          "type": "function",
          "function": {
            "name": "search_docs",
            "arguments": "{\"query\":\"tool use Cohere\",\"top_k\":3}"
          }
        }
      ]
    },
    {
      "role": "tool",
      "tool_call_id": "search_docs_1byjy32y4hvq",
      "content": [
        {
          "type": "document",
          "document": {
            "data": "{\"title\":\"Tool use (function calling) overview\",\"url\":\"https://docs.cohere.com/v2/docs/tool-use-overview\",\"text\":\"Tool use connects models to external tools like search engines and APIs.\"}"
          }
        }
      ]
    },
    {
      "role": "assistant",
      "content": "Tool use lets models call external tools (like doc search) and then answer using tool results with citations."
    },
    {
      "role": "user",
      "content": "How do I force tool usage?"
    }
  ],
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "search_docs",
        "description": "Search documentation and return relevant snippets as documents.",
        "parameters": {
          "type": "object",
          "properties": {
            "query": {
              "type": "string",
              "description": "The search query to look up in the docs."
            },
            "top_k": {
              "type": "integer",
              "description": "How many documents to return."
            }
          },
          "required": ["query"]
        }
      }
    }
  ]
}'

예제 응답:

I will search the docs for how to force tool usage using tool_choice.

[ToolCallV2(id='search_docs_8hwpm7d4wr14', type='function', function=ToolCallV2Function(name='search_docs', arguments='{"query":"tool_choice REQUIRED NONE","top_k":3}'))]

상태 관리(State management)

메시지의 순서는 아래 다이어그램에 표현되어 있습니다.

%%{init: {'htmlLabels': true}}%%
flowchart TD
    classDef defaultStyle fill:#fff,stroke:#000,color:#000;

    A["<div><b>USER</b><br />Query - turn #1</div>"]
    B["<div><b>ASSISTANT</b><br />Tool call - turn #1</div>"]
    C["<div><b>TOOL</b><br />Tool result - turn #1</div>"]
    D["<div><b>ASSISTANT</b><br />Response - turn #1</div>"]
    E["<div><b>USER</b><br />Query - turn #2</div>"]
    F["<div><b>ASSISTANT</b><br />Tool call - turn #2</div>"]
    G["<div><b>TOOL</b><br />Tool result - turn #2</div>"]
    H["<div><b>ASSISTANT</b><br />Response - turn #2</div>"]
    I["<div><b>USER</b><br />...</div>"]

    A -.-> B
    B -.-> C
    C -.-> D
    D -.-> E
    E -.-> F
    F -.-> G
    G -.-> H
    H -.-> I

    class A,B,C,D,E,F,G,H,I defaultStyle;

더 알아보기 (Learn more)