---
title: "Tools"
description: "Let a Workers AI model call your PHP tools. Pick a model that calls them, and force a call when needed."
---

> Documentation Index
> Fetch the complete documentation index at: https://laravel-cf-workersai-docs.mdick85.workers.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Tools

Tools use the standard Laravel AI interfaces. The package maps each tool to an OpenAI-style function definition.

## Define a tool and an agent

```php
use Illuminate\Contracts\JsonSchema\JsonSchema;
use Laravel\Ai\Contracts\Agent;
use Laravel\Ai\Contracts\HasTools;
use Laravel\Ai\Contracts\Tool;
use Laravel\Ai\Promptable;
use Laravel\Ai\Tools\Request;

class GetWeather implements Tool
{
    public function description(): string
    {
        return 'Look up the current weather.';
    }

    public function handle(Request $request): string
    {
        return "Sunny in {$request['city']}.";
    }

    public function schema(JsonSchema $schema): array
    {
        return ['city' => $schema->string()->required()];
    }
}

class WeatherAgent implements Agent, HasTools
{
    use Promptable;

    public function instructions(): string
    {
        return 'Use the tool to answer weather questions.';
    }

    public function tools(): iterable
    {
        return [new GetWeather];
    }
}

(new WeatherAgent)->prompt('Weather in Tokyo?', provider: 'workers-ai');
```

## What the package does

- It sends `tool_choice: auto` when the agent has tools.
- A tool with no parameters works. The package sends an empty `properties` object, because Workers AI rejects an empty array.
- It keeps reasoning text from a tool-call turn and sends it back on the next turn.
- It supports sub-agents and MCP tools. It uses the name from the tool's `name()` method when one exists, so two instances of one class do not collide.
- It encodes array tool results with unescaped slashes and unicode.

## Choose a model for tools

Not every model calls tools. Measured on 2026-06-11 on the direct API, on one account:

| Model | Tool calls |
| --- | --- |
| `@cf/meta/llama-3.3-70b-instruct-fp8-fast` (default) | Answers in prose. Does not call tools on the `/v1` endpoint. |
| `@cf/meta/llama-4-scout-17b-16e-instruct` | Calls tools. |
| `@cf/openai/gpt-oss-120b` | Calls tools. |

If your agent uses tools, set the model on the agent or the call. Do not rely on the default model.

## Force a tool call

Under `tool_choice: auto`, open-weight models call a tool only some of the time. To force a call, return `tool_choice` from `providerOptions()`:

```php
use Laravel\Ai\Enums\Lab;

// Inside your agent class:
public function providerOptions(Lab|string $provider): array
{
    return $provider === 'workers-ai' ? ['tool_choice' => 'required'] : [];
}
```

On the turn after the tool result, the package changes a forced `tool_choice` to `auto`. Without this, the model would call the tool again until the step limit and return no text. The package keeps the value `none`.

## Provider tools are not supported

Laravel AI provider tools, such as `WebSearch`, run inside a provider's own API, and Workers AI has none. On `laravel/ai` 1.1 and later, Laravel AI removes them before the call, so the model answers without them and you get no error. On 0.9 to 1.0, the package throws `RuntimeException` with the message `Workers AI does not support [ToolName] provider tools.`

For web search, use [`CloudflareWebSearch`](/docs/guides/web-search/). For anything else, write a normal tool that calls the service.

## Limit the steps

Laravel AI runs the tool loop. Set `#[MaxSteps]` on the agent to cap the number of steps.

Source: https://laravel-cf-workersai-docs.mdick85.workers.dev/docs/guides/tools/index.mdx
