> For the complete documentation index, see [llms.txt](https://docs.neuron-ai.dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.neuron-ai.dev/neuron-v3-es/agente/tools.md).

# Herramientas y kits de herramientas

El ciclo principal del agente consiste en llamar a un modelo, dejar que elija las herramientas a ejecutar y, después, terminar cuando ya no se necesiten más herramientas para proporcionar una respuesta:

<figure><img src="/files/80b3f4811690b2b6247cf77450e1422de2fa4cb6" alt=""><figcaption></figcaption></figure>

### Qué es una herramienta

Las herramientas permiten a los agentes ir más allá de generar texto al facilitar la interacción con los servicios de tu aplicación o con APIs externas.

Piensa en las herramientas como funciones especiales que tu agente de IA puede usar cuando necesita realizar tareas específicas. Te permiten ampliar las capacidades de tu agente dándole acceso a funciones concretas que puede llamar dentro de tu código.

{% embed url="<https://www.youtube.com/watch?v=lI8xE-uIek8>" %}

En el [YouTubeAgent](/neuron-v3-es/agente/agent.md) ejemplo podemos definir una herramienta para hacer que el agente pueda recuperar la transcripción del video de YouTube, de modo que pueda crear un resumen breve:

```php
namespace App\Neuron;

use NeuronAI\Agent\Agent;
use NeuronAI\Agent\SystemPrompt;
use NeuronAI\Providers\AIProviderInterface;
use NeuronAI\Providers\Anthropic\Anthropic;
use NeuronAI\Tools\PropertyType;
use NeuronAI\Tools\Tool;
use NeuronAI\Tools\ToolProperty;

class YouTubeAgent extends Agent
{
    protected function provider(): AIProviderInterface
    {
        // devuelve una instancia de proveedor de IA (Anthropic, OpenAI, Ollama, Gemini, etc.)
        return new Anthropic(
            key: 'ANTHROPIC_API_KEY',
            model: 'ANTHROPIC_MODEL',
        );
    }
    
    protected function instructions(): string 
    {
        return (string) new SystemPrompt(
            background: ["Eres un agente de IA especializado en escribir resúmenes de vídeos de YouTube."],
            steps: [
                "Obtén la URL de un vídeo de YouTube, o pide al usuario que proporcione una.",
                "Usa las herramientas disponibles para recuperar la transcripción del vídeo.",
                "Escribe el resumen.",
            ],
            output: [
                "Escribe un resumen en un párrafo sin usar listas. Usa solo texto fluido.",
                "Después del resumen, añade una lista de tres frases como las tres conclusiones más importantes del vídeo.",
            ]
        );
    }
    
    protected function tools(): array
    {
        return [
            Tool::make(
                'get_transcription',
                'Recuperar la transcripción de un video de YouTube.',
            )->addProperty(
                new ToolProperty(
                    name: 'video_url',
                    type: PropertyType::STRING,
                    description: 'La URL del video de YouTube.',
                    required: true
                )
            )->setCallable(function (string $video_url) {
                return "Transcripción del video...";
            })
        ];
    }
}

```

Desglosemos el código.

Hemos introducido el nuevo método `tools()` en la clase Agent. Este método espera devolver un array de objetos Tool que la IA podrá usar si lo necesita.

En este ejemplo devolvemos un array con solo una herramienta, llamada `get_transcription`.

Observa que el `ToolProperty` que definamos debe coincidir con la firma de la función que uses como callable. El callable recibe los argumentos `$video_url` y el nombre de la propiedad es exactamente "video\_url".

Lo más importante son el nombre y la descripción que le das a la herramienta y a sus propiedades. Toda esta información se enviará al LLM en lenguaje natural. Cuanto más explícito y claro seas, más probable será que el LLM entienda cuándo, si y por qué conviene usar la herramienta.

Una vez que el agente decide usar una herramienta, se ejecuta la función callable. Aquí podemos implementar la lógica para recuperar la transcripción del video y devolver la información al LLM.

Neuron te ofrece estas APIs claras y sencillas y automatiza todas las interacciones subyacentes con el LLM. Una vez que entiendes el concepto, se abre de inmediato la posibilidad de conectar prácticamente todo lo que quieras al agente. Poder ejecutar funciones locales te permite invocar cualquier API externa o componente de la aplicación.

### Herramientas personalizadas

Gracias a la arquitectura modular de Neuron, las herramientas son componentes que implementan `ToolInterface` . Eres libre de crear clases de herramientas preempaquetadas para que el agente pueda realizar acciones específicas, y publicarlas como paquetes externos de Composer o enviar un PR a nuestro repositorio para que se integren en el framework principal.

Para crear una nueva herramienta ejecuta el siguiente comando de consola:

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

```bash
vendor/bin/neuron make:tool App\\Neuron\\GetTranscriptionTool
```

{% endtab %}

{% tab title="Windows" %}

```powershell
.\vendor\bin\neuron make:tool App\Neuron\GetTranscriptionTool
```

{% endtab %}
{% endtabs %}

Puedes personalizar el esqueleto de la herramienta con el siguiente código:

```php
<?php

namespace App\Neuron\Tools;

use GuzzleHttp\Client;
use NeuronAI\Tools\PropertyType;
use NeuronAI\Tools\Tool;
use NeuronAI\Tools\ToolProperty;

class GetTranscriptionTool extends Tool
{
    protected Client $client;
    
    public function __construct(protected string $key)
    {
        // Definir el nombre y la descripción de la herramienta
        parent::__construct(
            'get_transcription',
            'Recuperar la transcripción de un video de YouTube.',
        );
    }
    
    /**
     * Devuelve la lista de propiedades.
     */
    protected function properties(): array
    {
        return [
            new ToolProperty(
                name: 'video_url',
                type: PropertyType::STRING,
                description: 'La URL del video de YouTube.',
                required: true
            )
        ];
    }
    
    /**
     * Implementación de la lógica de la herramienta
     */
    public function __invoke(string $video_url): string
    {
        $response = $this->getClient()
            ->get('transcript?url=' . $video_url.'&text=true')
            ->getBody()
            ->getContents();

        $response = json_decode($response, true);

        return $response['content'];
    }
    
    protected function getClient(): Client
    {
        return $this->client ??= new Client([
            'base_uri' => 'https://api.supadata.ai/v1/youtube/',
            'headers' => [
                'x-api-key' => $this->key,
            ]
        ]);
    }
}
```

**Nombre y descripción de la herramienta**: Define el nombre y la descripción de la herramienta en el constructor de la herramienta. Invierte en ingeniería de prompts para ayudar al modelo a tomar mejores decisiones.

**El método properties**: Implementa este método para devolver la lista de propiedades que espera la herramienta.

**El `__invoke` método**: Aquí necesitas implementar la lógica de la herramienta y devolver un resultado que se le devolverá al modelo. El método mágico de PHP `__invoke` se usa de forma predeterminada.

Fíjate en cómo el `__invoke()` método acepta los mismos argumentos definidos por `ToolProperty` . En este ejemplo estoy usando un servicio externo para recuperar la transcripción del video de YouTube llamado [Supadata.ai](https://supadata.ai/).

Puedes adjuntar la herramienta en la clase del agente como de costumbre:

```php
<?php

namespace App\Neuron;

use NeuronAI\Agent;
use NeuronAI\Providers\AIProviderInterface;
use App\Neuron\Tools\GetTranscriptionTool;

class YouTubeAgent extends Agent
{
    protected function provider(): AIProviderInterface
    {...}
    
    protected function instructions(): string
    {...}
    
    protected function tools(): array
    {
        return [
            GetTranscriptionTool::make('API_KEY'),
        ];
    }
}
```

GetTranscriptions es solo un ejemplo. Eventualmente puedes implementar otras herramientas para hacer que el agente pueda recuperar otros metadatos del video y mejorar sus capacidades de análisis de video.

Finalmente puedes hablar con el agente pidiéndole el resumen de un video de YouTube.

```php
use NeuronAI\Chat\Messages\UserMessage;

$message = YouTubeAgent::make($user)->chat(
    new UserMessage('¿Qué te parece este video: https://www.youtube.com/watch?v=WmVLcj-XKnM')
)->getMessage();
    
echo $message->getContent();

/**

Basándome en la transcripción, proporcionaré un resumen de este poderoso mensaje ambiental de 
"Madre Naturaleza":
Este video presenta ...

Tres conclusiones más importantes:

1. La naturaleza ha existido ...

2. El bienestar de la humanidad es ...

3. Cómo los humanos eligen actuar hacia la Naturaleza determina ...

*/
```

### Máximo de ejecuciones

Los agentes tienen un mecanismo de seguridad que registra el número de veces que se invoca una herramienta durante una sesión de ejecución. Si el agente supera este límite, la ejecución se interrumpe y se lanza la `ToolRunsExceededException` . De forma predeterminada, el límite es de 10 llamadas, y se cuenta para cada herramienta de manera individual.

Puedes personalizar este valor con el método `toolMaxRuns()` a nivel del agente, o usar `setMaxRuns()` a nivel de la herramienta. **Establecer el máximo de intentos en una sola herramienta tiene prioridad sobre la configuración global**.

```php
try {

    $response = YouTubeAgent::make()
        ->toolMaxRuns(5) // Número máximo de llamadas para cada herramienta
        ->addTool(
            // La configuración a nivel de herramienta tiene prioridad sobre la configuración global
            CustomTool::make()->setMaxRuns(2)
        )
        ->chat(...)
        ->getMessage();
        
} catch (ToolMaxTriesException $exception) {
    // hacer algo
}
```

### Visibilidad

Puedes condicionar la disponibilidad de las herramientas según reglas personalizadas. La clase Tool te proporciona el `visible` método para determinar si el agente debería siquiera saber que esta herramienta existe:

```php
class YouTubeAgent extends Agent
{
    ...
    
    protected function tools(): array
    {
        return [
            GetTranscriptionTool::make('API_KEY')->visible(
                auth()->user()->can(...)
            ),
        ];
    }
}
```

Si el `visible` método devuelve `false`, la herramienta no estará disponible durante la ejecución del agente.

### Aprobación de herramientas

Neuron te ofrece soporte completo para el patrón human in the loop, incluida la aprobación de herramientas. Es diferente de la visibilidad porque la "aprobación" es un guardián en tiempo de ejecución. El framework intercepta la llamada a la herramienta y se detiene esperando la decisión final del usuario.

Puedes conectar esta función a tu agente con nuestro [ToolApproval](#tool-properties) middleware integrado.

```php
new ToolApproval(
    tools: [
        BuyTicketTool::class => function (array $args): bool {
            return $args['amount'] > 100;
        }
    ]
)
```

{% content-ref url="/pages/b17ff1200828767959e6ec06f777645020907a3a" %}
[Middleware](/neuron-v3-es/agente/middleware.md)
{% endcontent-ref %}

### Búsqueda dinámica de herramientas

De forma predeterminada, cada vez que se invoca el proveedor, se cargan todas las herramientas y se transmiten al LLM de backend. Un agente complejo en producción conectado a correo, calendario, drive, CRM y múltiples servidores MCP puede alcanzar fácilmente cientos de herramientas, cada una con su nombre, descripción, esquema de parámetros y sugerencias de uso.

La búsqueda de herramientas replantea el catálogo de herramientas como algo que el agente consulta bajo demanda en lugar de algo que lleva en cada solicitud.

Puedes usar el middleware global `ToolSearchMiddleware` para activar la selección dinámica de herramientas en tu agente:

```php
new ToolSearchMiddleware([
    MyCustomTool::make(),
    ...CalculatorToolkit::make()->tools()
    ...MCPConnector::make([...])->tools()
])
```

{% content-ref url="/pages/b17ff1200828767959e6ec06f777645020907a3a" %}
[Middleware](/neuron-v3-es/agente/middleware.md)
{% endcontent-ref %}

### Monitorización y depuración

Neuron gestiona automáticamente por ti el bucle de herramientas, según lo que el LLM decidió llamar.

Para observar este flujo de trabajo debes conectar tu agente al [panel de monitoreo Inspector](https://inspector.dev/) para ver en tiempo real el flujo de ejecución de las llamadas a herramientas.

{% embed url="<https://docs.inspector.dev/guides/neuron-ai>" %}

<figure><img src="/files/fecfc6cc715c2ea83cdccc166cfcb66efbfa1a45" alt=""><figcaption></figcaption></figure>

En la imagen de abajo puedes ver todos los detalles sobre la ejecución de la herramienta para recuperar la transcripción del video:

<figure><img src="/files/4b1ecc55f0db36d4af931e49722d87c275ae17d7" alt=""><figcaption></figcaption></figure>

## Propiedades de la herramienta

Neuron te permite definir el formato de los datos que quieres recibir en la función de la herramienta. Puedes anidar estos objetos entre sí para definir estructuras de datos complejas.

### ToolProperty

Esta clase representa un valor escalar simple como string, int o boolean.

```php
namespace App\Neuron\Tools;

use NeuronAI\Tools\PropertyType;
use NeuronAI\Tools\Tool;
use NeuronAI\Tools\ToolProperty;

class MyTool extends Tool
{
    public function __construct(){...}
	
    protected function properties(): array
    {
        return [
            new ToolProperty(
                name: 'arg',
                type: PropertyType::STRING,
                description: 'Describe el valor que esperas',
                required: true,
                nullable: false
            )
        ];
    }
    
    public function __invoke(string $arg){...}
}
```

### ArrayProperty

El `ArrayProperty` te permite requerir una lista de elementos con características específicas.

Usa el argumento `items` para especificar el tipo de datos de los elementos del array. En el ejemplo siguiente pedimos un array de strings.

```php
namespace App\Neuron\Tools;

use NeuronAI\Tools\PropertyType;
use NeuronAI\Tools\Tool;
use NeuronAI\Tools\ArrayProperty;
use NeuronAI\Tools\ToolProperty;

class MyTool extends Tool
{
    public function __construct(){...}
	
    protected function properties(): array
    {
        return [
            new ArrayProperty(
                name: 'prop_array',
                description: 'Describe el valor que esperas',
                required: true,
                items: new ToolProperty(
                    name: 'prop',
                    type: PropertyType::STRING,
                    description: 'Describe el valor que esperas',
                    required: true
                )
            )
        ];
    }
    
    public function __invoke(string $arg){...}
}
```

#### Límites máximos y mínimos

ArrayProperty también te permite definir limitaciones sobre el tamaño del array esperado usando los argumentos `minItems` y `maxItems` .

```php
$property = new ArrayProperty(
    name: "tags",
    description: "Lista de etiquetas asociadas con el elemento",
    required: true,
    items: new ToolProperty(
        name: "tag",
        type: PropertyType::STRING,
        description: "Una sola etiqueta",
        required: true
    ),
    minItems: 1,
    maxItems: 10
);
```

### ObjectProperty

De forma similar al ejemplo anterior del array, puedes definir una estructura de datos de objeto:

```php
namespace App\Neuron\Tools;

use NeuronAI\Tools\PropertyType;
use NeuronAI\Tools\Tool;
use NeuronAI\Tools\ObjectProperty;
use NeuronAI\Tools\ToolProperty;

class MyTool extends Tool
{
    public function __construct(){...}
	
    protected function properties(): array
    {
        return [
            new ObjectProperty(
                name: 'colors',
                description: 'Color RGB',
                required: true,
                properties: [
                    new ToolProperty(
                        name: 'r',
                        type: PropertyType::NUMBER,
                        description: 'La parte roja del RGB',
                        required: true
                    ),
                    new ToolProperty(
                        name: 'g',
                        type: PropertyType::NUMBER,
                        description: 'La parte verde del RGB',
                        required: true
                    ),
                    new ToolProperty(
                        name: 'b',
                        type: PropertyType::NUMBER,
                        description: 'La parte azul del RGB',
                        required: true
                    )
                ]
            )
        ];
    }
    
    public function __invoke(string $arg){...}
}
```

### Entrada estructurada de la herramienta

Si el objeto que quieres tiene muchas propiedades, puedes pasar una clase PHP estructurada a `ObjectProperty` en lugar de definir el esquema manualmente. Neuron te proporcionará una instancia de esta clase como argumento de entrada de la función de la herramienta:

```php
namespace App\Neuron\Tools;

use App\Neuron\Dto\Color;
use NeuronAI\Tools\PropertyType;
use NeuronAI\Tools\Tool;
use NeuronAI\Tools\ToolProperty;

class MyTool extends Tool
{
    public function __construct(){...}
	
    protected function properties(): array
    {
        return [
            new ObjectProperty(
                name: 'color',
                description: 'Combinación de colores',
                required: true,
                class: Color::class
            )
        ];
    }
    
    public function __invoke(Color $color){...}
}
```

Así es como luce la clase Colors:

```php
<?php

namespace App\Neuron\Dto;

use NeuronAI\StructuredOutput\SchemaProperty;

class Color
{
    #[SchemaProperty(description: "La parte ROJA del RGB", required: true)]
    public float $r;
    
    #[SchemaProperty(description: "La parte VERDE del RGB", required: true)]
    public float $g;
    
    #[SchemaProperty(description: "La parte AZUL del RGB", required: true)]
    public float $b;
}
```

## Herramientas del proveedor

Algunos proveedores ofrecen la posibilidad de usar sus herramientas integradas como web\_search, file\_search y otras, en lugar de depender de servicios externos. Aunque ofrecen este servicio, introducen muchas restricciones al usar estas herramientas. La forma más flexible y fiable de añadir capacidades a tus agentes sigue siendo los sistemas de Tools y Toolkits.

Puedes añadir una herramienta del proveedor como de costumbre en el array de herramientas de tu agente:

```php
use NeuronAI\Tools\ProviderTool;

class MyAgent extends Agent
{
    protected function provider(): AIProviderInterface
    {
        return new OpenAIResponses(
            key: 'OPENAI_API_KEY',
            model: 'OPENAI_MODEL',
        );
    }

    protected function tools(): array
    {
        return [
            ProviderTool:make(
                type: 'web_search'
            )->setOptions([...]),
        ];
    }
}
```

Actualmente solo [OpenAIResponses](/neuron-v3-es/proveedores/ai-provider.md#openairesponses), [Gemini](/neuron-v3-es/proveedores/ai-provider.md#gemini), y [Anthropic](/neuron-v3-es/proveedores/ai-provider.md#anthropic) soportan estas herramientas.

## Toolkits

La filosofía detrás del sistema de toolkits de Neuron surgió de una observación fundamental durante el desarrollo de agentes de IA: mientras que las herramientas individuales proporcionan capacidades específicas, los agentes de IA del mundo real suelen requerir conjuntos coordinados de funcionalidades relacionadas.

En lugar de obligar a los desarrolladores a ensamblar manualmente colecciones de herramientas para casos de uso comunes, Neuron introduce los toolkits como una capa de abstracción que transforma la forma en que pensamos sobre la composición de capacidades del agente. Aquí tienes un ejemplo de cómo puedes añadir un toolkit a un agente:

```php
<?php

namespace App\Neuron;

use NeuronAI\Agent;
use NeuronAI\Tools\Calculator\CalculatorToolkit;

class MyAgent extends Agent
{
    ...
	
    protected function tools(): array
    {
        return [
            CalculatorToolkit::make(),
        ];
    }
}
```

El enfoque tradicional requiere instanciar cada herramienta individualmente. Imagina que quieres construir agentes que necesiten razonamiento matemático: las herramientas de suma, resta, multiplicación, división y exponenciación deben declararse todas por separado en la configuración de herramientas del agente. Este enfoque granular se vuelve rápidamente difícil de manejar cuando los agentes requieren conjuntos de funcionalidades completos.

Los toolkits representan la solución de Neuron a esta complejidad, empaquetando las herramientas creadas en torno al mismo ámbito en una interfaz única y coherente que puede adjuntarse a cualquier agente con una sola línea de código.

Aquí tienes un ejemplo del `CalculatorToolkit`:

```php
namespace NeuronAI\Tools\Toolkits\Calculator;

use NeuronAI\Tools\Toolkits\AbstractToolkit;

class CalculatorToolkit extends AbstractToolkit
{
    public function guidelines(): ?string
    {
        return "Este toolkit te permite realizar operaciones matemáticas. También puedes usar estas funciones para resolver
        expresiones matemáticas ejecutando operaciones más pequeñas paso a paso para calcular el resultado final.";
    }

    public function provide(): array
    {
        return [
            SumTool::make(),
            SubtractTool::make(),
            MultiplyTool::make(),
            DivideTool::make(),
            ExponentiateTool::make(),
        ];
    }
}
```

El `AbstractToolkit` la clase base establece una interfaz coherente que heredan todos los toolkits, garantizando un comportamiento predecible en todo el framework.

**Directrices**

El `guidelines()` el método cumple una función especialmente importante en el desarrollo de agentes: proporciona información contextual que ayuda al modelo de lenguaje subyacente a entender no solo qué herramientas están disponibles, sino cómo deben usarse juntas. En el caso del `CalculatorToolkit`, las directrices sugieren explícitamente que las expresiones matemáticas complejas pueden resolverse mediante operaciones paso a paso, guiando al agente hacia estrategias eficaces de resolución de problemas.

**Proporcionar**

El `provide()` el método devuelve el array de herramientas incluidas de forma predeterminada en el toolkit. Cuando un toolkit se adjunta a un agente, las herramientas individuales pasan a estar disponibles exactamente como si se hubieran añadido por separado, pero sin la carga cognitiva de gestionar múltiples declaraciones de herramientas.

### Filtros

Durante el desarrollo de agentes complejos, a menudo me he encontrado con escenarios en los que un toolkit ofrece la funcionalidad adecuada en general, pero incluye herramientas que podrían provocar un comportamiento no deseado en contextos específicos, o simplemente necesitan restringirse y configurarse individualmente.

#### Excluir

El `exclude()` el método aborda este desafío de manera elegante, permitiendo a los desarrolladores adjuntar toolkits completos mientras mantienen un control granular sobre las capacidades disponibles. Esto resulta especialmente útil cuando se trabaja con agentes especializados que necesitan capacidades concretas, pero quieres reducir la probabilidad de errores del agente y el consumo de tokens.

```php
class MyAgent extends Agent
{
    ...
	
    protected function tools(): array
    {
    	return [
            CalculatorToolkit::make()->exclude([
                DivideTool::class,
                ExponentiateTool::class,
                MultiplyTool::class,
            ]),
        ];
    }
}
```

El mecanismo de exclusión funciona a nivel de clase, usando nombres de clase completamente calificados para identificar las herramientas que se van a eliminar.

#### Solo

De la misma manera también puedes usar el método `only()` para solicitar un subconjunto de las herramientas disponibles en el toolkit.

```php
class MyAgent extends Agent
{
    ...
	
    protected function tools(): array
    {
    	return [
            CalculatorToolkit::make()->only([
                StandardDeviationTool::class,
                MedianTool::class,
            ]),
        ];
    }
}
```

#### Con

Siguiendo el mismo patrón, puede que necesites obtener una instancia de una herramienta específica del toolkit para cambiar su configuración. Puedes hacerlo usando el método `with()` . Puedes pasar el nombre de clase completamente calificado para declarar qué herramienta quieres recuperar, y la instancia de la herramienta se inyectará en la callback para que puedas cambiar su configuración y devolverla.

```php
class MyAgent extends Agent
{
    ...
	
    protected function tools(): array
    {
    	return [
            MySQLToolkit::make()
                ->with(
                    MySQLSchemaTool::class, 
                    fn (ToolInterface $tool) => $tool->setMaxTries(1)
                ),
        ];
    }
}
```

Desde una perspectiva de extensibilidad, el sistema de toolkits abre oportunidades notables para la contribución de la comunidad y el crecimiento del ecosistema. La interfaz coherente significa que desarrolladores de terceros pueden crear toolkits específicos de dominio que se integren perfectamente con la arquitectura de Neuron. Un desarrollador que construya agentes para aplicaciones financieras podría crear un FinancialToolkit que incluya herramientas para conversión de divisas, cálculo de intereses y evaluación de riesgos. Del mismo modo, un WebScrapingToolkit podría empaquetar herramientas de solicitud HTTP, capacidades de análisis de HTML y utilidades de extracción de datos en un componente único y reutilizable.

## Toolkits disponibles

Neuron incluye varias herramientas y toolkits integrados que te permiten equipar rápidamente a tus agentes con muchas habilidades. Puedes usar estas herramientas de forma individual o adjuntar toolkits completos con una sola línea de código.

### Calculadora

CalculatorToolkit proporciona un conjunto completo de herramientas de cálculo diseñadas para que tus agentes de IA realicen cálculos precisos. Puede integrarse sin problemas con toolkits complementarios que proporcionan acceso a datos, como conectores de bases de datos, procesadores CSV, clientes de API o lectores de hojas de cálculo, permitiendo a los agentes de IA realizar cálculos estadísticos sofisticados y ofrecer insights completos en respuesta a consultas empresariales complejas.

```php
<?php

namespace App\Neuron;

use NeuronAI\Agent;
use NeuronAI\Tools\Toolkits\Calculator\CalculatorToolkit;

class MyAgent extends Agent
{
    ...
    
    protected function tools(): array
    {
        return [
            CalculatorToolkit::make(),
        ];
    }
}
```

<table data-header-hidden><thead><tr><th width="253"></th><th></th></tr></thead><tbody><tr><td>sumar</td><td>NeuronAI\Tools\Toolkits\Calculator\SumTool</td></tr><tr><td>restar</td><td>NeuronAI\Tools\Toolkits\Calculator\SubtractTool</td></tr><tr><td>multiplicar</td><td>NeuronAI\Tools\Toolkits\Calculator\MultiplyTool</td></tr><tr><td>dividir</td><td>NeuronAI\Tools\Toolkits\Calculator\DivideTool</td></tr><tr><td>exponencial</td><td>NeuronAI\Tools\Toolkits\Calculator\ExponentialTool</td></tr><tr><td>raíz cuadrada</td><td>NeuronAI\Tools\Toolkits\Calculator\SquareRootTool</td></tr><tr><td>raíz n-ésima</td><td>NeuronAI\Tools\Toolkits\Calculator\NthRootTool</td></tr><tr><td>media</td><td>NeuronAI\Tools\Toolkits\Calculator\MeanTool</td></tr><tr><td>mediana</td><td>NeuronAI\Tools\Toolkits\Calculator\MedianTool</td></tr><tr><td>moda</td><td>NeuronAI\Tools\Toolkits\Calculator\ModeTool</td></tr><tr><td>desviación estándar</td><td>NeuronAI\Tools\Toolkits\Calculator\StandardDeviationTool</td></tr><tr><td>varianza</td><td>NeuronAI\Tools\Toolkits\Calculator\VarianceTool</td></tr></tbody></table>

### Calendario

Este toolkit proporciona operaciones completas de fecha y hora. Usa estas herramientas para que tu agente pueda trabajar con fechas, horas, formateo, cálculos y conversiones de zona horaria.

```php
<?php

namespace App\Neuron;

use NeuronAI\Agent;
use NeuronAI\Tools\Toolkits\CalendarToolkit\CalendarToolkit;

class MyAgent extends Agent
{
    ...
    
    protected function tools(): array
    {
        return [
            CalendarToolkit::make(),
        ];
    }
}
```

<table data-header-hidden><thead><tr><th width="205"></th><th></th></tr></thead><tbody><tr><td>current_datetime</td><td>NeuronAI\Tools\Toolkits\Calendar\CurrentDateTimeTool</td></tr><tr><td>get_timestamp</td><td>NeuronAI\Tools\Toolkits\Calendar\GetTimestampTool</td></tr><tr><td>format_date</td><td>NeuronAI\Tools\Toolkits\Calendar\FormatDateTool</td></tr><tr><td>date_difference</td><td>NeuronAI\Tools\Toolkits\Calendar\DateDifferenceTool</td></tr><tr><td>add_time</td><td>NeuronAI\Tools\Toolkits\Calendar\AddTimeTool</td></tr><tr><td>subtract_time</td><td>NeuronAI\Tools\Toolkits\Calendar\SubtractTimeTool</td></tr><tr><td>calculate_age</td><td>NeuronAI\Tools\Toolkits\Calendar\CalculateAgeTool</td></tr><tr><td>convert_timezone</td><td>NeuronAI\Tools\Toolkits\Calendar\ConvertTimezoneTool</td></tr><tr><td>get_timezone_info</td><td>NeuronAI\Tools\Toolkits\Calendar\GetTimezoneInfoTool</td></tr><tr><td>get_weekday</td><td>NeuronAI\Tools\Toolkits\Calendar\GetWeekdayTool</td></tr><tr><td>is_weekend</td><td>NeuronAI\Tools\Toolkits\Calendar\IsWeekendTool</td></tr><tr><td>is_leap_year</td><td>NeuronAI\Tools\Toolkits\Calendar\IsLeapYearTool</td></tr><tr><td>get_days_in_month</td><td>NeuronAI\Tools\Toolkits\Calendar\GetDaysInMonthTool</td></tr><tr><td>start_of_period</td><td>NeuronAI\Tools\Toolkits\Calendar\StartOfPeriodTool</td></tr><tr><td>end_of_period</td><td>NeuronAI\Tools\Toolkits\Calendar\EndOfPeriodTool</td></tr><tr><td>get_week_number</td><td>NeuronAI\Tools\Toolkits\Calendar\GetWeekNumberTool</td></tr><tr><td>compare_dates</td><td>NeuronAI\Tools\Toolkits\Calendar\CompareDatesTool</td></tr><tr><td>is_date_in_range</td><td>NeuronAI\Tools\Toolkits\Calendar\IsDateInRangeTool</td></tr></tbody></table>

### MySQL y PostgreSQL

Estos toolkits permiten que tu agente interactúe con tu base de datos. Si preguntas "¿Cuántos votos obtuvieron los autores en los últimos 14 días?", el agente no adivina ni alucina una respuesta. En su lugar, reconoce que esta pregunta requiere acceso a la base de datos, identifica las tablas apropiadas involucradas y recupera datos reales de tu sistema.

<figure><img src="/files/e1cf0bda4b97f87f4921b50572ac78c5c45cee0d" alt=""><figcaption></figcaption></figure>

Todas las herramientas de los toolkits de MySQL y PostgreSQL requieren una [PDO](https://www.php.net/manual/en/class.pdo.php) como argumento del constructor. Si estás en un entorno de framework o ya estás usando un ORM en general, puedes obtener la instancia PDO subyacente del ORM y pasarla a las herramientas. Puedes aprender más sobre esta estrategia de implementación en este artículo detallado: <https://inspector.dev/mysql-ai-toolkit-bringing-intelligence-to-your-database-layer-in-php/>

La instancia PDO es básicamente una conexión a una base de datos específica, así que también podrías pensar en crear credenciales dedicadas para tu agente. Puede ser útil para controlar el nivel de acceso que tu agente tiene a la base de datos.

En cualquier caso, tienes herramientas separadas para leer y escribir en la base de datos. Si no confías en el comportamiento de tu agente, puedes no proporcionar la herramienta de escritura.

```php
<?php

namespace App\Neuron;

use NeuronAI\Agent;
use NeuronAI\Tools\Toolkits\MySQL\MySQLToolkit;
use NeuronAI\Tools\Toolkits\MySQL\PGSQLToolkit;

class MyAgent extends Agent
{
    ...
    
    protected function tools(): array
    {
        return [
            // Conecta a una base de datos MySQL
            MySQLToolkit::make(
                new \PDO("mysql:host=localhost;dbname=DB_NAME;charset=utf8mb4", "DB_USER", "DB_PASS"),
            ),
            
            // o base de datos Postgre
            PGSQLToolkit::make(
                new \PDO("pgsql:host=localhost;dbname=DB_NAME;charset=utf8mb4", "DB_USER", "DB_PASS"),
            ),
        ];
    }
}
```

{% hint style="warning" %}
Estos ejemplos se refieren a `MySQLToolkit` pero es exactamente igual usando `PGSQLToolkit`.
{% endhint %}

#### MySQLSchemaTool / PGSQLSchemaTool

Esta herramienta permite que los agentes comprendan la estructura de tu base de datos, lo que les permite construir consultas inteligentes sin que tengas que codificar de forma rígida las estructuras de las tablas o las relaciones en los prompts. En esencia, esta herramienta le da a tu agente el equivalente a la comprensión de un administrador de bases de datos sobre tu esquema, permitiéndole crear consultas que respeten tu modelo de datos y aprovechen los índices y relaciones existentes.

```php
namespace App\Neuron;

use NeuronAI\Agent;
use NeuronAI\Tools\Toolkits\MySQL\MySQLSchemaTool;

class MyAgent extends Agent
{
    ...
    
    protected function tools(): array
    {
        return [
            MySQLSchemaTool::make(new \PDO(...)),
            
            // PGSQLSchemaTool::make(new \PDO(...)),
        ];
    }
}
```

Esta herramienta también acepta un segundo argumento `$tables`. Básicamente puedes pasar una lista de tablas que quieras incluir en la información del esquema pasada al LLM. En esencia, esta es una forma de limitar el alcance de las consultas que el agente ejecutará más adelante en la base de datos.

```php
namespace App\Neuron;

use NeuronAI\Agent;
use NeuronAI\Tools\Toolkits\MySQL\MySQLSchemaTool;

class MyAgent extends Agent
{
    ...
    
    protected function tools(): array
    {
        return [
            MySQLSchemaTool::make(
                new \PDO(...),
                ['users', 'categories', 'articles', 'tags']
            ),
        ];
    }
}
```

Al limitar el alcance del esquema, puedes crear agentes especializados que se centren en áreas específicas de tu aplicación. Un agente de gestión de contenidos podría necesitar solo acceso a las tablas de artículos, categorías y etiquetas, mientras que un agente de administración de usuarios requiere visibilidad sobre las tablas de usuarios, roles y permisos. Este enfoque no solo mejora el rendimiento, sino que también reduce la carga cognitiva del modelo de lenguaje, lo que conduce a respuestas más precisas y enfocadas.

#### MySQLSelectTool / PGSQLSelectTool

Usa esta herramienta para permitir que tu agente ejecute consultas SELECT en la base de datos.

```php
namespace App\Neuron;

use NeuronAI\Agent;
use NeuronAI\Tools\Toolkits\MySQL\MySQLSchemaTool;
use NeuronAI\Tools\Toolkits\MySQL\MySQLSelectTool;

class MyAgent extends Agent
{
    ...
    
    protected function tools(): array
    {
        return [
            MySQLSchemaTool::make(new \PDO(...)),
            MySQLSelectTool::make(new \PDO(...)),
        ];
    }
}
```

#### MySQLWriteTool / PGSQLWriteTool

Usa esta herramienta para permitir que tu agente realice operaciones de escritura en la base de datos (INSERT, UPDATE, DELETE).

```php
namespace App\Neuron;

use NeuronAI\Agent;
use NeuronAI\Tools\Toolkits\MySQL\MySQLSchemaTool;
use NeuronAI\Tools\Toolkits\MySQL\MySQLWriteTool;

class MyAgent extends Agent
{
    ...
    
    protected function tools(): array
    {
        return [
            MySQLSchemaTool::make(new \PDO(...)),
            MySQLWriteTool::make(new \PDO(...)),
        ];
    }
}
```

### Sistema de archivos

Este toolkit permite que el agente interactúe con el sistema de archivos local.

```php
namespace App\Neuron;

use NeuronAI\Agent;
use NeuronAI\Tools\Toolkits\FileSystem\FileSystemToolkit;

class MyAgent extends Agent
{
    ...
    
    protected function tools(): array
    {
        return [
            FileSystemToolkit::make(),
        ];
    }
}
```

<table data-header-hidden><thead><tr><th width="256"></th><th></th></tr></thead><tbody><tr><td>describe_directory_content</td><td>NeuronAI\Tools\Toolkits\FileSystem\DescribeDirectoryContentTool</td></tr><tr><td>read_file</td><td>NeuronAI\Tools\Toolkits\FileSystem\ReadFileTool</td></tr><tr><td>grep_file_content</td><td>NeuronAI\Tools\Toolkits\FileSystem\GrepFileContentTool</td></tr><tr><td>glob_path</td><td>NeuronAI\Tools\Toolkits\FileSystem\GlobPathTool</td></tr><tr><td>preview_file</td><td>NeuronAI\Tools\Toolkits\FileSystem\PreviewFileTool</td></tr><tr><td>parse_file</td><td>NeuronAI\Tools\Toolkits\FileSystem\ParseFileTool</td></tr></tbody></table>

### Tavily

Este toolkit permite que tu agente realice búsquedas web, extracción de contenido de páginas y rastreo.

```php
namespace App\Neuron;

use NeuronAI\Agent;
use NeuronAI\Tools\Toolkits\Tavily\TavilyToolkit;

class MyAgent extends Agent
{
    ...
    
    protected function tools(): array
    {
        return [
            TavilyToolkit::make(
                key: 'TAVILY_API_KEY'
            ),
        ];
    }
}
```

#### Búsqueda web de Tavily

Permite que tu agente busque en la web. Requiere acceso a [las API de Tavily](https://tavily.com/).

```php
namespace App\Neuron;

use NeuronAI\Agent;
use NeuronAI\Tools\Toolkits\Tavily\TavilySearchTool;

class MyAgent extends Agent
{
    ...
    
    protected function tools(): array
    {
        return [
            TavilySearchTool::make(
                key: 'TAVILY_API_KEY'
            ),
        ];
    }
}
```

Puedes personalizar las opciones predeterminadas para recuperar resultados de búsqueda pasando tu preferencia en `withOptions` método:

```php
TavilySearchTool::make(
    key: 'TAVILY_API_KEY'
 )->withOptions([
    'days' => 30,
    'max_results' => 10,
]),
```

#### Extracción de Tavily

Extrae el contenido de una página web desde una URL. Requiere acceso a [las API de Tavily](https://tavily.com/).

```php
namespace App\Neuron;

use NeuronAI\Agent;
use NeuronAI\Tools\Toolkits\Tavily\TavilyExtractTool;

class MyAgent extends Agent
{
    ...
    
    protected function tools(): array
    {
        return [
            TavilyExtractTool::make(
                key: 'TAVILY_API_KEY'
            ),
        ];
    }
}
```

#### Rastreo de Tavily

Tavily Crawl es una herramienta de recorrido de sitios web basada en grafos que puede explorar cientos de rutas en paralelo con extracción integrada y descubrimiento inteligente.

```php
namespace App\Neuron;

use NeuronAI\Agent;
use NeuronAI\Tools\Toolkits\Tavily\TavilyCrawlTool;

class MyAgent extends Agent
{
    ...
    
    protected function tools(): array
    {
        return [
            TavilyCrawlTool::make(
                key: 'TAVILY_API_KEY'
            ),
        ];
    }
}
```

### Jina

Este toolkit permite que tu agente realice búsquedas web y lea el contenido de una URL específica.

```php
namespace App\Neuron;

use NeuronAI\Agent;
use NeuronAI\Tools\Toolkits\Jina\JinaToolkit;

class MyAgent extends Agent
{
    ...
    
    protected function tools(): array
    {
        return [
            JinaToolkit::make(
                key: 'JINA_API_KEY'
            ),
        ];
    }
}
```

#### Búsqueda web de Jina

Permite que tu agente busque en la web. Requiere acceso a [API de Jina](https://jina.ai/).

```php
namespace App\Neuron;

use NeuronAI\Agent;
use NeuronAI\Tools\Toolkits\Jina\JinaWebSearch;

class MyAgent extends Agent
{
    ...
    
    protected function tools(): array
    {
        return [
            JinaWebSearch::make(
                key: 'JINA_API_KEY'
            ),
        ];
    }
}
```

#### Lector de URL de Jina

Extrae el contenido de una página web desde una URL. Requiere acceso a [API de Jina](https://jina.ai/).

```php
namespace App\Neuron;

use NeuronAI\Agent;
use NeuronAI\Tools\Toolkits\Jina\JinaUrlReader;

class MyAgent extends Agent
{
    ...
    
    protected function tools(): array
    {
        return [
            JinaUrlReader::make(
                key: 'JINA_API_KEY'
            ),
        ];
    }
}
```

### Memoria de Zep

Este toolkit conecta un agente de NeuronAI con [Zep](https://www.getzep.com/) grafo de conocimiento de Zep. Este tipo de sistema permite al agente almacenar hechos relevantes que pueden surgir durante las interacciones con el agente a lo largo del tiempo. Es una memoria a largo plazo en el sentido de que no está limitada a la conversación actual como lo [ChatHistory](/neuron-v3-es/agente/chat-history-and-memory.md) hace el componente. Es un almacenamiento externo y persistente que el agente utilizará para almacenar y recuperar piezas individuales de información que pueden permitir respuestas más personalizadas.

Para saber más sobre las capacidades de este tipo de sistema, puedes visitar el sitio web de Zep: <https://www.getzep.com/>

```php
namespace App\Neuron;

use NeuronAI\Agent;
use NeuronAI\Tools\Toolkits\Zep\ZepLongTermMemoryToolkit;

class MyAgent extends Agent
{
    ...
    
    protected function tools(): array
    {
        return [
            ZepLongTermMemoryToolkit::make(
                key: 'ZEP_API_KEY',
                user_id: 'ID'
            ),
        ];
    }
}
```

El `user_id` Este argumento te permite separar la memoria a largo plazo en diferentes silos si quieres atender a varios usuarios. Según tu caso de uso, puedes usar este parámetro como una "clave" para separar la memoria de las distintas entidades con las que interactúa el agente (usuarios, empresas, etc.).

### AWS SES

#### Servicio simple de correo electrónico (SES)

Esta herramienta permite al agente enviar un mensaje de correo electrónico a uno o más destinatarios, enviar notificaciones, confirmaciones, informes o cualquier otra comunicación basada en correo electrónico. La herramienta gestiona automáticamente la entrega correcta del correo electrónico y el manejo básico de errores.

Para usar esta herramienta, el SDK de AWS para PHP debe estar instalado.

```
composer require aws/aws-sdk-php
```

La herramienta obtiene una instancia de la `SesClient` clase del SDK de AWS para PHP.

```php
namespace App\Neuron;

use Aws\Ses\SesClient;
use NeuronAI\Agent;
use NeuronAI\Tools\Toolkits\AWS\SESTool;

class MyAgent extends Agent
{
    ...
    
    protected function tools(): array
    {
        return [
            SESTool::make(
                sesClient: new SesCleint(...),
                fromEmail: 'my-address@email.com'
            ),
        ];
    }
}
```

### Supadata YouTube

Este toolkit proporciona acceso a transcripciones de videos de YouTube, metadatos, información del canal y datos de listas de reproducción a través de Supadata.ai con fines de análisis de contenido e investigación.

```php
namespace App\Neuron;

use NeuronAI\Agent;
use NeuronAI\Tools\Toolkits\Supadata\SupadataYouTubeToolkit;

class MyAgent extends Agent
{
    ...
    
    protected function tools(): array
    {
        return [
            SupadataYouTubeToolkit::make(
                key: 'SUPADATA_API_KEY',
            ),
        ];
    }
}
```

#### Transcripción de video

Permite al agente recuperar la transcripción de un video de YouTube.

```php
namespace App\Neuron;

use NeuronAI\Agent;
use NeuronAI\Tools\Toolkits\Supadata\SupadataVideoTranscriptTool;

class MyAgent extends Agent
{
    ...
    
    protected function tools(): array
    {
        return [
            SupadataVideoTranscriptTool::make(
                key: 'SUPADATA_API_KEY',
            ),
        ];
    }
}
```

#### Metadatos de video

Permite al agente recuperar los metadatos de un video de YouTube.

```php
namespace App\Neuron;

use NeuronAI\Agent;
use NeuronAI\Tools\Toolkits\Supadata\SupadataVideoMetadataTool;

class MyAgent extends Agent
{
    ...
    
    protected function tools(): array
    {
        return [
            SupadataVideoMetadataTool::make(
                key: 'SUPADATA_API_KEY',
            ),
        ];
    }
}
```

#### Metadatos del canal

Permite al agente recuperar metadatos de un canal de YouTube, incluido el nombre, la descripción, el número de suscriptores y más.

```php
namespace App\Neuron;

use NeuronAI\Agent;
use NeuronAI\Tools\Toolkits\Supadata\SupadataYoutubeChannelTool;

class MyAgent extends Agent
{
    ...
    
    protected function tools(): array
    {
        return [
            SupadataYoutubeChannelTool::make(
                key: 'SUPADATA_API_KEY',
            ),
        ];
    }
}
```

#### Metadatos de la lista de reproducción

Permite al agente recuperar metadatos de una lista de reproducción de YouTube, incluido el título, la descripción, el número de videos y más.

```php
namespace App\Neuron;

use NeuronAI\Agent;
use NeuronAI\Tools\Toolkits\Supadata\SupadataYoutubePlaylistTool;

class MyAgent extends Agent
{
    ...
    
    protected function tools(): array
    {
        return [
            SupadataYoutubePlaylistTool::make(
                key: 'SUPADATA_API_KEY',
            ),
        ];
    }
}
```

## Llamadas paralelas a herramientas

Si tus agentes usan mucho las herramientas, puedes habilitar la ejecución paralela si el modelo solicita múltiples llamadas a herramientas en una sola petición.

#### Ejecución secuencial (estándar)

El agente llama a las herramientas **una a la vez**, esperando a que cada una termine antes de iniciar la siguiente:

```
1. Llamar a la herramienta A → esperar el resultado
2. Llamar a la herramienta B → esperar el resultado  
3. Llamar a la herramienta C → esperar el resultado

Tiempo total: Tiempo(A) + Tiempo(B) + Tiempo(C)
```

#### Ejecución paralela (con `pcntl`)

El agente llama a **múltiples herramientas simultáneamente**, permitiéndoles ejecutarse al mismo tiempo:

```
1. Llamar a las herramientas A, B y C todas a la vez
2. Esperar a que todas terminen

Tiempo total: Máx(Tiempo(A), Tiempo(B), Tiempo(C))
```

### Requisitos

Para usar esta función necesitas instalar el `spatie/fork` paquete. Para más información consulta el repositorio de GitHub: <https://github.com/spatie/fork>

```shellscript
composer require spatie/fork
```

{% hint style="warning" %}

### Limitaciones

Esta implementación requiere la `pcntl` extensión pcntl, que está instalada por defecto en muchos sistemas Unix y Mac.

**pcntl solo funciona en procesos CLI, no en un contexto web.**

Si el `pcntl` Si la extensión no está presente en el sistema que ejecuta el agente (por ejemplo, máquinas Windows), el trait recurre automáticamente a la ejecución estándar de llamadas a herramientas. Esto puede ser útil si tienes una discrepancia entre tu entorno local de desarrollo y el entorno de producción. Puedes desarrollar localmente con `pcntl` desactivado, luego desplegar a entornos de producción donde puede estar habilitado—**sin modificar una sola línea de código**. El agente se adapta automáticamente al entorno de ejecución en el que se encuentre.
{% endhint %}

### Habilitar ejecución paralela

Establece `parallelToolCalls(true)` en tu Agent o RAG. El framework inyectará el nodo dedicado `ParallelToolNode` en lugar del `ToolNode` estándar en el flujo de trabajo.

```php
class DemoAgent extends Agent
{
    public function __construct()
    {
        parent::__construct();
        $this->parallelToolCalls(true);
    }
    
    protected function provider(): AIProviderInterface
    {
        ...
    }

    protected function tools(): array
    {
        return [
            CalculatorToolkit::make(),
        ];
    }
}
```

## Manejador de errores

Ahora la cuestión es cómo manejar los errores de las herramientas. Hay un par de opciones para adaptarse a diferentes escenarios y necesidades.

El `ToolNode` acepta un `$errorHandler` argumento [(código)](https://github.com/neuron-core/neuron-ai/blob/3.x/src/Agent/Nodes/ToolNode.php#L37). Es una devolución de llamada que recibe la excepción lanzada por la herramienta y la instancia de la herramienta que falla.

Te permite implementar una lógica personalizada en caso de error de la herramienta (excepciones generales de herramientas, o `ToolRunsExceededException`). **Si devuelves un valor, se devolverá al modelo como resultado de la herramienta.** Por defecto, ToolNode relanza los errores de ejecución.

**Definición fluida:**

```php
$agent = Agent::make()
    ->toolErrorHandler(
        fn(Throwable $e, ToolInterface $tool): string => "Error: {$e->getMessage()}"
    );
```

**Extender el agente**

También puedes implementar `resolveToolErrorHandler()` directamente para definir la devolución de llamada que se ejecutará.

```php
class MyAgent extends Agent
{
    ...

    protected function resolveToolErrorHandler(): ?callable
    {
        return fn(Throwable $e, ToolInterface $tool): string => "Error: {$e->getMessage()}";
    }
}
```
