> ## Documentation Index
> Fetch the complete documentation index at: https://www.edgee.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# TypeScript SDK - Tools (Function Calling)

> Complete guide to function calling with the TypeScript SDK.

The Edgee TypeScript SDK supports OpenAI-compatible function calling (tools), allowing models to request execution of functions you define. This enables models to interact with external APIs, databases, and your application logic.

## Overview

Function calling works in two steps:

1. **Request**: Send a request with tool definitions. The model may request to call one or more tools.
2. **Execute & Respond**: Execute the requested functions and send the results back to the model.

## Tool Definition

A tool is defined using the `Tool` interface:

```typescript theme={"dark"}
interface Tool {
  type: "function";
  function: FunctionDefinition;
}
```

### FunctionDefinition

| Property                                                                                                                      | Type                      | Description                                                                                               |
| ----------------------------------------------------------------------------------------------------------------------------- | ------------------------- | --------------------------------------------------------------------------------------------------------- |
| `name` <Tooltip headline="Required" tip="The field is required."><Icon icon="asterisk" size={15} color="#8924A6" /></Tooltip> | `string`                  | The name of the function (must be unique, a-z, A-Z, 0-9, \_, -)                                           |
| `description`                                                                                                                 | `string`                  | Description of what the function does. **Highly recommended** - helps the model understand when to use it |
| `parameters`                                                                                                                  | `Record<string, unknown>` | JSON Schema object describing the function parameters                                                     |

### Parameters Schema

The `parameters` field uses JSON Schema format:

```typescript theme={"dark"}
{
  type: "object",
  properties: {
    paramName: {
      type: "string" | "number" | "boolean" | "object" | "array",
      description: "Parameter description"
    }
  },
  required: ["paramName"]  // Array of required parameter names
}
```

**Example - Defining a Tool:**

```typescript theme={"dark"}
const response = await edgee.send({
  model: 'gpt-5.2',
  input: {
    messages: [
      { role: 'user', content: 'What is the weather in Paris?' }
    ],
    tools: [
      {
        type: 'function',
        function: {
          name: 'get_weather',
          description: 'Get the current weather for a location',
          parameters: {
            type: 'object',
            properties: {
              location: {
                type: 'string',
                description: 'The city and state, e.g. San Francisco, CA'
              },
              unit: {
                type: 'string',
                enum: ['celsius', 'fahrenheit'],
                description: 'Temperature unit'
              }
            },
            required: ['location']
          }
        }
      }
    ],
    tool_choice: 'auto'
  }
});
```

## Tool Choice

The `tool_choice` parameter controls when and which tools the model should call:

| Value                                                       | Type     | Description                                          |
| ----------------------------------------------------------- | -------- | ---------------------------------------------------- |
| `"auto"`                                                    | `string` | Let the model decide whether to call tools (default) |
| `"none"`                                                    | `string` | Don't call any tools, even if provided               |
| `{ type: "function", function: { name: "function_name" } }` | `object` | Force the model to call a specific function          |

### ToolChoice Type

```typescript theme={"dark"}
type ToolChoice =
  | "none"
  | "auto"
  | { type: "function"; function: { name: string } };
```

**Example - Force a Specific Tool:**

```typescript theme={"dark"}
const response = await edgee.send({
  model: 'gpt-5.2',
  input: {
    messages: [
      { role: 'user', content: 'What is the weather?' }
    ],
    tools: [
      {
        type: 'function',
        function: {
          name: 'get_weather',
          description: 'Get the current weather',
          parameters: { /* ... */ }
        }
      }
    ],
    tool_choice: {
      type: 'function',
      function: { name: 'get_weather' }
    }
  }
});
// Model will always call get_weather
```

**Example - Disable Tool Calls:**

```typescript theme={"dark"}
const response = await edgee.send({
  model: 'gpt-5.2',
  input: {
    messages: [
      { role: 'user', content: 'What is the weather?' }
    ],
    tools: [
      {
        type: 'function',
        function: {
          name: 'get_weather',
          description: 'Get the current weather',
          parameters: { /* ... */ }
        }
      }
    ],
    tool_choice: 'none'
  }
});
// Model will not call tools, even though they're available
```

## Tool Call Object Structure

When the model requests a tool call, you receive a `ToolCall` object:

| Property             | Type     | Description                                   |
| -------------------- | -------- | --------------------------------------------- |
| `id`                 | `string` | Unique identifier for this tool call          |
| `type`               | `string` | Type of tool call (typically `"function"`)    |
| `function`           | `object` | Function call details                         |
| `function.name`      | `string` | Name of the function to call                  |
| `function.arguments` | `string` | JSON string containing the function arguments |

### Parsing Arguments

```typescript theme={"dark"}
const toolCall = response.toolCalls[0];
const args = JSON.parse(toolCall.function.arguments);
// args is now a JavaScript object
console.log(args.location);  // e.g., "Paris"
```

## Complete Example

Here's a complete end-to-end example with error handling:

```typescript theme={"dark"}
import Edgee from 'edgee';

const edgee = new Edgee('your-api-key');

// Define the weather function
async function getWeather(location: string, unit: string = 'celsius') {
  // Simulate API call
  return {
    location,
    temperature: 15,
    unit,
    condition: 'sunny'
  };
}

// Step 1: Initial request with tools
const response1 = await edgee.send({
  model: 'gpt-5.2',
  input: {
    messages: [
      { role: 'user', content: 'What is the weather in Paris and Tokyo?' }
    ],
    tools: [
      {
        type: 'function',
        function: {
          name: 'get_weather',
          description: 'Get the current weather for a location',
          parameters: {
            type: 'object',
            properties: {
              location: {
                type: 'string',
                description: 'The city name'
              },
              unit: {
                type: 'string',
                enum: ['celsius', 'fahrenheit'],
                description: 'Temperature unit'
              }
            },
            required: ['location']
          }
        }
      }
    ],
    tool_choice: 'auto'
  }
});

// Step 2: Execute all tool calls
const messages = [
  { role: 'user', content: 'What is the weather in Paris and Tokyo?' },
  response1.message! // Include assistant's message
];

if (response1.toolCalls) {
  for (const toolCall of response1.toolCalls) {
    const args = JSON.parse(toolCall.function.arguments);
    const result = await getWeather(args.location, args.unit);
    
    messages.push({
      role: 'tool',
      tool_call_id: toolCall.id,
      content: JSON.stringify(result)
    });
  }
}

// Step 3: Send results back
const response2 = await edgee.send({
  model: 'gpt-5.2',
  input: {
    messages,
    tools: [
      // Keep tools available for follow-up
      {
        type: 'function',
        function: {
          name: 'get_weather',
          description: 'Get the current weather for a location',
          parameters: {
            type: 'object',
            properties: {
              location: { type: 'string', description: 'The city name' },
              unit: { type: 'string', enum: ['celsius', 'fahrenheit'] }
            },
            required: ['location']
          }
        }
      }
    ]
  }
});

console.log(response2.text);
```

**Example - Multiple Tools:**

You can provide multiple tools and let the model choose which ones to call:

You can provide multiple tools and let the model choose:

```typescript theme={"dark"}
const response = await edgee.send({
  model: 'gpt-5.2',
  input: {
    messages: [
      { role: 'user', content: 'Get the weather in Paris and send an email about it' }
    ],
    tools: [
      {
        type: 'function',
        function: {
          name: 'get_weather',
          description: 'Get the current weather for a location',
          parameters: {
            type: 'object',
            properties: {
              location: { type: 'string', description: 'City name' }
            },
            required: ['location']
          }
        }
      },
      {
        type: 'function',
        function: {
          name: 'send_email',
          description: 'Send an email to a recipient',
          parameters: {
            type: 'object',
            properties: {
              to: { type: 'string', description: 'Recipient email address' },
              subject: { type: 'string', description: 'Email subject' },
              body: { type: 'string', description: 'Email body' }
            },
            required: ['to', 'subject', 'body']
          }
        }
      }
    ],
    tool_choice: 'auto'
  }
});
```

## Streaming with Tools

The `stream()` method also supports tools. For details about streaming, see the [Stream Method documentation](/sdk/typescript/stream).

```typescript theme={"dark"}
for await (const chunk of edgee.stream('gpt-5.2', {
  messages: [
    { role: 'user', content: 'What is the weather in Paris?' }
  ],
  tools: [
    {
      type: 'function',
      function: {
        name: 'get_weather',
        description: 'Get the current weather for a location',
        parameters: {
          type: 'object',
          properties: {
            location: { type: 'string', description: 'City name' }
          },
          required: ['location']
        }
      }
    }
  ],
  tool_choice: 'auto'
})) {
  if (chunk.text) {
    process.stdout.write(chunk.text);
  }
  
  // Check for tool calls in the delta
  const toolCalls = chunk.choices[0]?.delta?.tool_calls;
  if (toolCalls) {
    console.log('\nTool calls detected:', toolCalls);
  }
  
  if (chunk.finishReason === 'tool_calls') {
    console.log('\nModel requested tool calls');
  }
}
```

## Best Practices

### 1. Always Provide Descriptions

Descriptions help the model understand when to use each function:

```typescript theme={"dark"}
// ✅ Good
{
  name: 'get_weather',
  description: 'Get the current weather conditions for a specific location',
  parameters: { /* ... */ }
}

// ❌ Bad
{
  name: 'get_weather',
  // Missing description
  parameters: { /* ... */ }
}
```

### 2. Use Clear Parameter Names

```typescript theme={"dark"}
// ✅ Good
properties: {
  location: { type: 'string', description: 'The city name' }
}

// ❌ Bad
properties: {
  loc: { type: 'string' }  // Unclear name, no description
}
```

### 3. Mark Required Parameters

```typescript theme={"dark"}
parameters: {
  type: 'object',
  properties: {
    location: { type: 'string', description: 'City name' },
    unit: { type: 'string', description: 'Temperature unit' }
  },
  required: ['location']  // location is required, unit is optional
}
```

### 4. Handle Multiple Tool Calls

Models can request multiple tool calls in a single response. Use `Promise.all()` to execute them in parallel:

```typescript theme={"dark"}
if (response.toolCalls && response.toolCalls.length > 0) {
  const results = await Promise.all(
    response.toolCalls.map(async (toolCall) => {
      const args = JSON.parse(toolCall.function.arguments);
      const result = await executeFunction(toolCall.function.name, args);
      return {
        tool_call_id: toolCall.id,
        result
      };
    })
  );
  
  // Add all tool results to messages
  const toolMessages = results.map(({ tool_call_id, result }) => ({
    role: 'tool' as const,
    tool_call_id,
    content: JSON.stringify(result)
  }));
  
  messages.push(...toolMessages);
}
```

### 5. Error Handling in Tool Execution

```typescript theme={"dark"}
if (response.toolCalls) {
  for (const toolCall of response.toolCalls) {
    try {
      const args = JSON.parse(toolCall.function.arguments);
      const result = await executeFunction(toolCall.function.name, args);
      
      messages.push({
        role: 'tool',
        tool_call_id: toolCall.id,
        content: JSON.stringify(result)
      });
    } catch (error) {
      // Send error back to model
      messages.push({
        role: 'tool',
        tool_call_id: toolCall.id,
        content: JSON.stringify({ error: error.message })
      });
    }
  }
}
```

### 6. Keep Tools Available

Include tools in follow-up requests so the model can call them again if needed:

```typescript theme={"dark"}
const response2 = await edgee.send({
  model: 'gpt-5.2',
  input: {
    messages: [...messagesWithToolResults],
    tools: [
      // Keep the same tools available
      { type: 'function', function: { /* ... */ } }
    ]
  }
});
```
