# %pip install cohere
import cohere

co = cohere.ClientV2(
    api_key="AZURE_API_KEY_CHAT",
    base_url="AZURE_ENDPOINT_CHAT",  # example: "https://cohere-command-r-plus-08-2024-xyz.eastus.models.ai.azure.com/"
)
```

## Create tools

The pre-requisite, before we can run a tool use workflow, is to set up the tools. Let's create three tools:

* `search_faqs`: A tool for searching the FAQs of a company. For simplicity, we'll not implement any retrieval logic, but we'll simply pass a list of three predefined documents. In practice, we would set up a retrieval system as we did in Chapters 4, 5, and 6.
* `search_emails`: A tool for searching the emails. Same as above, we'll simply pass a list of predefined emails.
* `create_calendar_event`: A tool for creating new calendar events. Again, for simplicity, we'll only return mock successful event creations without actual implementation. In practice, we can connect to a calendar service API and implement all the necessary logic here.

Here, we are defining a Python function for each tool, but more broadly, the tool can be any function or service that can receive and send objects.

```python PYTHON
def search_faqs(query):
    faqs = [
        {
            "text": "Submitting Travel Expenses:\nSubmit your expenses through our user-friendly finance tool."
        },
        {
            "text": "Side Projects Policy:\nWe encourage you to explore your passions! Just ensure there's no conflict of interest with our business."
        },
        {
            "text": "Wellness Benefits:\nTo promote a healthy lifestyle, we provide gym memberships, on-site yoga classes, and health insurance."
        },
    ]
    return faqs


def search_emails(query):
    emails = [
        {
            "from": "hr@co1t.com",
            "to": "david@co1t.com",
            "date": "2024-06-24",
            "subject": "A Warm Welcome to Co1t, David!",
            "text": "We are delighted to have you on board. Please find attached your first week's agenda.",
        },
        {
            "from": "it@co1t.com",
            "to": "david@co1t.com",
            "date": "2024-06-24",
            "subject": "Instructions for IT Setup",
            "text": "Welcome, David! To get you started, please follow the attached guide to set up your work accounts.",
        },
        {
            "from": "john@co1t.com",
            "to": "david@co1t.com",
            "date": "2024-06-24",
            "subject": "First Week Check-In",
            "text": "Hi David, let's chat briefly tomorrow to discuss your first week. Also, come join us for lunch this Thursday at noon to meet everyone!",
        },
    ]
    return emails


def create_calendar_event(date: str, time: str, duration: int):
    # You can implement any logic here
    return {
        "is_success": True,
        "message": f"Created a {duration} hour long event at {time} on {date}",
    }


functions_map = {
    "search_faqs": search_faqs,
    "search_emails": search_emails,
    "create_calendar_event": create_calendar_event,
}
```

## Define tool schemas

The next step is to define the tool schemas in a format that can be accepted by the Chat endpoint. The schema must contain the following fields: `name`, `description`, and `parameter_definitions`.

This schema informs the LLM about what the tool does, and the LLM decides whether to use a particular tool based on it. Therefore, the more descriptive and specific the schema, the more likely the LLM will make the right tool call decisions.

```python PYTHON
tools = [
    {
        "type": "function",
        "function": {
            "name": "search_faqs",
            "description": "Given a user query, searches a company's frequently asked questions (FAQs) list and returns the most relevant matches to the query.",
            "parameters": {
                "type": "object",
                "properties": {
                    "query": {
                        "type": "string",
                        "description": "The query from the user",
                    }
                },
                "required": ["query"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "search_emails",
            "description": "Given a user query, searches a person's emails and returns the most relevant matches to the query.",
            "parameters": {
                "type": "object",
                "properties": {
                    "query": {
                        "type": "string",
                        "description": "The query from the user",
                    }
                },
                "required": ["query"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "create_calendar_event",
            "description": "Creates a new calendar event of the specified duration at the specified time and date. A new event cannot be created on the same time as an existing event.",
            "parameters": {
                "type": "object",
                "properties": {
                    "date": {
                        "type": "string",
                        "description": "the date on which the event starts, formatted as mm/dd/yy",
                    },
                    "time": {
                        "type": "string",
                        "description": "the time of the event, formatted using 24h military time formatting",
                    },
                    "duration": {
                        "type": "number",
                        "description": "the number of hours the event lasts for",
                    },
                },
                "required": ["date", "time", "duration"],
            },
        },
    },
]
```

## Run agent

Now, let's set up the agent using Cohere's tool use feature. We can think of a tool use system as consisting of four components:

* The user
* The application
* The LLM
* The tools

At its most basic, these four components interact in a workflow through four steps:

* Step 1: Get user message. The LLM gets the user message (via the application).
* Step 2: Generate tool calls. The LLM makes a decision on the tools to call (if any) and generates the tool calls.
* Step 3: Get tool results. The application executes the tools and sends the tool results to the LLM.
* Step 4: Generate response and citations. The LLM generates the response and citations and sends them back to the user.

Let's create a function called `run_assistant` to implement these steps and print out the key events and messages along the way. This function also optionally accepts the chat history as an argument to keep the state in a multi-turn conversation.

```python PYTHON
import json

system_message = """## Task and Context
You are an assistant who assists new employees of Co1t with their first week. You respond to their questions and assist them with their needs. Today is Monday, June 24, 2024"""


def run_assistant(query, messages=None):
    if messages is None:
        messages = []

    if "system" not in {m.get("role") for m in messages}:
        messages.append({"role": "system", "content": system_message})

    # Step 1: get user message
    print(f"Question:\n{query}")
    print("=" * 50)

    messages.append({"role": "user", "content": query})

    # Step 2: Generate tool calls (if any)
    response = co.chat(
        model="model",  # Pass a dummy string
        messages=messages,
        tools=tools,
    )

    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
        for idx, tc in enumerate(response.message.tool_calls):
            tool_result = functions_map[tc.function.name](
                **json.loads(tc.function.arguments)
            )
            tool_content = []
            for data in tool_result:
                tool_content.append(
                    {
                        "type": "document",
                        "document": {"data": json.dumps(data)},
                    }
                )
                # Optional: add an "id" field in the "document" object, otherwise IDs are auto-generated
            messages.append(
                {
                    "role": "tool",
                    "tool_call_id": tc.id,
                    "content": tool_content,
                }
            )

        # Step 4: Generate response and citations
        response = co.chat(
            model="model",  # Pass a dummy string
            messages=messages,
            tools=tools,
        )

    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)
    if response.message.citations:
        print("\nCITATIONS:")
        for citation in response.message.citations:
            print(citation, "\n")

    return messages
```

Let’s now run the agent. We'll use an example of a new hire asking about IT access and the travel expense process.

Given three tools to choose from, the model is able to pick the right tools (in this case, `search_faqs` and `search_emails`) based on what the user is asking for.

Also, notice that the model first generates a plan about what it should do ("I will ...") before actually generating the tool call(s).

Additionally, the model also generates fine-grained citations in tool use mode based on the tool results it receives, the same way we saw with RAG.

```python PYTHON
messages = run_assistant(
    "Any doc on how do I submit travel expenses? Also, any emails about setting up IT access?"
)
```

```mdx
Question:
Any doc on how do I submit travel expenses? Also, any emails about setting up IT access?
==================================================
Tool plan:
I will search for a document on how to submit travel expenses, and also search for emails about setting up IT access. 

Tool calls:
Tool name: search_faqs | Parameters: {"query":"how to submit travel expenses"}
Tool name: search_emails | Parameters: {"query":"setting up IT access"}
==================================================
Response:
You can submit your travel expenses through the user-friendly finance tool.

You should have received an email from it@co1t.com with instructions for setting up your IT access.
==================================================

CITATIONS:
start=48 end=75 text='user-friendly finance tool.' sources=[ToolSource(type='tool', id='search_faqs_wkfggn2680c4:0', tool_output={'text': 'Submitting Travel Expenses:\nSubmit your expenses through our user-friendly finance tool.'})] type='TEXT_CONTENT' 

start=105 end=176 text='email from it@co1t.com with instructions for setting up your IT access.' sources=[ToolSource(type='tool', id='search_emails_8n0cvsh5xknt:1', tool_output={'date': '2024-06-24', 'from': 'it@co1t.com', 'subject': 'Instructions for IT Setup', 'text': 'Welcome, David! To get you started, please follow the attached guide to set up your work accounts.', 'to': 'david@co1t.com'})] type='TEXT_CONTENT' 
```

## Conclusion

In this tutorial, we learned about:

* How to set up tools with parameter definitions for the Cohere chat API
* How to define tools for building agentic applications
* How to set up the agent
* How to run a tool use workflow involving the user, the application, the LLM, and the tools