Documentation Index
Fetch the complete documentation index at: https://docs.instructorphp.com/llms.txt
Use this file to discover all available pages before exploring further.
Tool calling enables the model to request specific actions from your application. Instead of generating a text response, the model returns structured function calls with arguments, which your code can execute and optionally feed back into the conversation. This is the foundation for building agents, assistants, and any application that needs to interact with external systems.
Tools are defined as arrays following the OpenAI function calling format. Each tool describes a function’s name, purpose, and expected parameters:
<?php
$weatherTool = [
'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 country (e.g., "Paris, France")',
],
'unit' => [
'type' => 'string',
'enum' => ['celsius', 'fahrenheit'],
'description' => 'The temperature unit to use',
],
],
'required' => ['location'],
],
],
];
// @doctest id="e9e3"
Pass your tool definitions via the tools parameter and control how the model selects tools with toolChoice:
<?php
use Cognesy\Messages\Messages;
use Cognesy\Polyglot\Inference\Data\ToolChoice;
use Cognesy\Polyglot\Inference\Data\ToolDefinitions;
use Cognesy\Polyglot\Inference\Inference;
$response = Inference::using('openai')
->with(
messages: Messages::fromString('What is the weather like in Paris?'),
tools: ToolDefinitions::fromArray([$weatherTool]),
toolChoice: ToolChoice::auto(),
)
->response();
// @doctest id="ed3f"
The response object provides methods for inspecting whether the model made tool calls and extracting their details:
<?php
if ($response->hasToolCalls()) {
$toolCalls = $response->toolCalls();
foreach ($toolCalls->all() as $call) {
$name = $call->name(); // e.g. 'get_weather'
$args = $call->args(); // e.g. ['location' => 'Paris, France']
$id = $call->idString(); // unique call ID string for multi-turn conversations
// Execute the function and use the result...
}
} else {
// The model responded with text instead
echo $response->content();
}
// @doctest id="4cd4"
Convenience Accessors
For simple cases where you just need the tool call arguments as data, Polyglot provides shortcut methods:
<?php
use Cognesy\Messages\Messages;
use Cognesy\Polyglot\Inference\Data\ToolChoice;
use Cognesy\Polyglot\Inference\Data\ToolDefinitions;
use Cognesy\Polyglot\Inference\Inference;
// Get tool call arguments as a JSON string
$json = Inference::using('openai')
->with(
messages: Messages::fromString('Get the weather for Paris.'),
tools: ToolDefinitions::fromArray([$weatherTool]),
toolChoice: ToolChoice::auto(),
)
->asToolCallJson();
// Or as a decoded PHP array
$data = Inference::using('openai')
->with(
messages: Messages::fromString('Get the weather for Paris.'),
tools: ToolDefinitions::fromArray([$weatherTool]),
toolChoice: ToolChoice::auto(),
)
->asToolCallJsonData();
// @doctest id="5bf4"
When the model returns a single tool call, asToolCallJsonData() returns that call’s arguments as an array. When multiple tool calls are returned, it returns an array of all calls.
The toolChoice parameter controls how the model decides whether to use tools:
<?php
use Cognesy\Messages\Messages;
use Cognesy\Polyglot\Inference\Data\ToolChoice;
use Cognesy\Polyglot\Inference\Data\ToolDefinitions;
use Cognesy\Polyglot\Inference\Inference;
$toolDefs = ToolDefinitions::fromArray($tools);
// Let the model decide whether to call a tool or respond with text
$response = Inference::using('openai')
->with(
messages: Messages::fromString('What is the weather like in Paris?'),
tools: $toolDefs,
toolChoice: ToolChoice::auto(),
)
->response();
// Force the model to call a specific tool
$response = Inference::using('openai')
->with(
messages: Messages::fromString('What is the weather like in Paris?'),
tools: $toolDefs,
toolChoice: ToolChoice::specific('get_weather'),
)
->response();
// Prevent tool usage entirely (model responds with text)
$response = Inference::using('openai')
->with(
messages: Messages::fromString('What is the weather like in Paris?'),
tools: $toolDefs,
toolChoice: ToolChoice::none(),
)
->response();
// @doctest id="8ee7"
You can provide multiple tool definitions in a single request. The model will select the most appropriate one based on the user’s message:
<?php
use Cognesy\Messages\Messages;
use Cognesy\Polyglot\Inference\Data\ToolChoice;
use Cognesy\Polyglot\Inference\Data\ToolDefinitions;
use Cognesy\Polyglot\Inference\Inference;
$tools = [
[
'type' => 'function',
'function' => [
'name' => 'get_weather',
'description' => 'Get the current weather for a location',
'parameters' => [
'type' => 'object',
'properties' => [
'location' => ['type' => 'string'],
],
'required' => ['location'],
],
],
],
[
'type' => 'function',
'function' => [
'name' => 'get_flight_info',
'description' => 'Get information about a flight',
'parameters' => [
'type' => 'object',
'properties' => [
'flight_number' => ['type' => 'string'],
'date' => ['type' => 'string'],
],
'required' => ['flight_number'],
],
],
],
];
$response = Inference::using('openai')
->with(
messages: Messages::fromString('What is the status of flight AA123?'),
tools: ToolDefinitions::fromArray($tools),
toolChoice: ToolChoice::auto(),
)
->response();
// @doctest id="c547"
Using the Fluent API
The fluent builder methods withTools() and withToolChoice() offer an alternative to passing everything through with():
<?php
use Cognesy\Messages\Messages;
use Cognesy\Polyglot\Inference\Data\ToolChoice;
use Cognesy\Polyglot\Inference\Data\ToolDefinitions;
use Cognesy\Polyglot\Inference\Inference;
$response = Inference::using('openai')
->withMessages(Messages::fromString('Get the weather for Paris.'))
->withTools(ToolDefinitions::fromArray([$weatherTool]))
->withToolChoice(ToolChoice::auto())
->response();
// @doctest id="2286"
Provider Support
Tool calling support varies across providers:
| Provider | Tool Calling | Tool Choice |
|---|
| OpenAI | Yes | Yes (auto, none, specific function) |
| Anthropic | Yes | Yes |
| Groq | Yes | Yes |
| Gemini | Yes | Varies by model |
| Other providers | Varies | Varies |
You can query tool support programmatically through DriverCapabilities::supportsToolCalling() and DriverCapabilities::supportsToolChoice().
Tool calling is ideal for:
- Building agents that interact with external APIs and services
- Creating assistants that retrieve real-time information
- Implementing multi-step workflows where the model orchestrates actions
- Extracting structured data using function schemas (an alternative to JSON Schema mode)
- Giving the model access to specific capabilities like calculations, database queries, or file operations