# Function Calling

{% content-ref url="/pages/tMRAxvFbmCHMdkBxiTVa" %}
[Installing the SDK](/introduction/installing-the-sdk.md)
{% endcontent-ref %}

Automatic Tool Calling

{% tabs %}
{% tab title="Typescript" %}
Here we define the tool function in json

```javascript
import { RunnableToolFunction } from 'propulsionai/lib/RunnableFunction';

const tools: RunnableToolFunction<any>[] = [
  {
    type: 'function',
    function: {
      name: 'list',
      description: 'list queries books by genre, and returns a list of names of books',
      parameters: {
        type: 'object',
        properties: {
          genre: { type: 'string', enum: ['mystery', 'nonfiction', 'memoir', 'romance', 'historical'] },
        },
      },
      function: list,
      parse: JSON.parse,
    },
  } as RunnableToolFunction<{ genre: string }>,
  {
    type: 'function',
    function: {
      name: 'search',
      description: 'search queries books by their name and returns a list of book names and their ids',
      parameters: {
        type: 'object',
        properties: {
          name: { type: 'string' },
        },
      },
      function: search,
      parse: JSON.parse,
    },
  } as RunnableToolFunction<{ name: string }>,
  {
    type: 'function',
    function: {
      name: 'get',
      description:
        "get returns a book's detailed information based on the id of the book. Note that this does not accept names, and only IDs, which you can get by using search.",
      parameters: {
        type: 'object',
        properties: {
          id: { type: 'string' },
        },
      },
      function: get,
      parse: JSON.parse,
    },
  } as RunnableToolFunction<{ id: string }>,
];

async function list({ genre }: { genre: string }) {
  console.log('calling list: ', genre);
  return db.filter((item) => item.genre === genre).map((item) => ({ name: item.name, id: item.id }));
}

async function search({ name }: { name: string }) {
  console.log('calling search: ', name);
  return db.filter((item) => item.name.includes(name)).map((item) => ({ name: item.name, id: item.id }));
}

async function get({ id }: { id: string }) {
  console.log('calling get: ', id);
  return db.find((item) => item.id === id);
}
```

Using `run_tools` for automatic function calling **with or without streaming**.

```javascript
async function main() {
  const runner = await client.chat.completions
    .runTools({
      deployment: '<deployment_id>',
      stream: true, // can be false
      tools, // as defined earlier
      messages: [
        {
          role: 'system',
          content:
            'Please use our book database, which you can access using functions to answer the following questions.',
        },
        {
          role: 'user',
          content:
            'I really enjoyed reading Where the Crawdads Sing, could you recommend me a book that is similar and tell me why?',
        },
      ],
    })
    .on('message', (msg) => console.log('msg', msg))
    .on('functionCallResult', (functionCallResult) => console.log('functionCallResult', functionCallResult))
    .on('content', (diff) => process.stdout.write(diff))
    .on('totalUsage', (totalUsage) => console.log('totalUsage', totalUsage))
    .on('task_id', (task_id) => console.log('task_id', task_id));

  const result = await runner.finalChatCompletion();
  console.log();
  console.log('messages');
  console.log(JSON.stringify(runner.messages));

  console.log();
  console.log('final chat completion');
  console.dir(result, { depth: null });
}

main()
```

{% endtab %}

{% tab title="Python" %}
Here we define the tool function, its parameters and examples (optional)

```python
def get_current_weather(location: str, format: str) -> str:
    """
    Retrieves the current weather for a specified location.

    This function fetches the current weather data for the given location
    and returns it in the specified format.

    Parameters:
    -----------
    location : str
        The name of the location (city, country, etc.) to get weather for.
    format : str
        The desired output format. Accepted values are 'celsius', 'fahrenheit',
        or 'kelvin' for temperature units.

    Examples:
    ---------
    >>> get_current_weather("New York", "celsius")
    'Current weather in New York: 22°C, Partly Cloudy'

    >>> get_current_weather("London", "fahrenheit")
    'Current weather in London: 59°F, Rainy'
    """
    # print(f"Function Log: Getting weather for {location} in {format} format...")
    return f'{{"temperature": 22, "description": "Partly Cloudy", "location": "{location}", "units": "{format}"}}'
```

Using `run_tools` for automatic function calling without streaming.

```python
def sync_main() -> None:
    response = client.chat.completions.run_tools(
        deployment="<deployment_id>",
        messages=[
            {
                "role": "system",
                "content": "You are a helpful assistant.",
            },
            {
                "role": "user",
                "content": "What is the weather in SF and NY?",
            },
        ],
        tools=[get_current_weather],
        stream=False,
        tool_debug=False,
    )
    print(response.to_json())
sync_main()
```

Using `run_tools` for automatic function calling while **streaming**.

```python
def sync_main() -> None:
    response = client.chat.completions.run_tools(
        deployment="<deployment_id>",
        messages=[
            {
                "role": "system",
                "content": "You are a helpful assistant.",
            },
            {
                "role": "user",
                "content": "What is the weather in SF and NY?",
            },
        ],
        tools=[get_current_weather],
        stream=True,
        tool_debug=False,
    )
    for data in response:
      if data:
          chunk = data.to_json()
          chunk_json = json.loads(chunk)
          
          if chunk_json["choices"] and chunk_json["choices"][0]["delta"] is not None:
              delta = chunk_json["choices"][0]["delta"]
              
              # Check if 'content' exists in delta and is not None
              if "content" in delta and delta["content"] is not None:
                  sys.stdout.write(delta["content"])
                  sys.stdout.flush()  # Ensure content is displayed immediately
              
              # Check for tool calls
              # if "tool_calls" in delta:
                  # print("Tool call detected:", delta["tool_calls"])
              
              # Check for finish reason
              # if "finish_reason" in chunk_json["choices"][0] and chunk_json["choices"][0]["finish_reason"] == "stop":
              #     print("\nGeneration complete.")
sync_main()
```

{% endtab %}
{% endtabs %}

Manualy manage function calling

{% tabs %}
{% tab title="Typescript" %}

```
// TODO
```

{% endtab %}

{% tab title="Python" %}

```
// TODO
```

{% endtab %}
{% endtabs %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.propulsionhq.com/quick-start/function-calling.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
