Ir al contenido
Nibiru docsv0.9.2

Plugin del agente

Una herramienta agente estilo ReAct. Extienda la herramienta para darle cualquier capacidad de PHP que pueda escribir.

Stable Reading time ~ 3 min Edit on GitHub

El complemento del Agente le permite darle a un LLM la capacidad de actuar — para llamar consultas SQL, golpear puntos finales HTTP, leer archivos o hacer cualquier otra cosa que pueda expresar como un método PHP. Ejecuta un bucle estilo ReAct: piensa → llamada a herramienta → observa → repite → responde.

use Nibiru\Module\Ai\Ai;
use Nibiru\Module\Ai\Plugin\Tools\PdoQuery;
$ai = new Ai();
echo $ai->agent()
->withTools([new PdoQuery()])
->run('How many active users do we have?');
// → "We have 1,247 active users." (after the agent ran SELECT count(*)…)
user task
LLM gets system prompt with tool definitions
LLM emits ```tool {"tool":"pdo_query","args":{"sql":"SELECT…"}}```
Agent runs the tool, captures result
LLM gets observation, decides: more tools or final answer?
"FINAL: 1,247 active users."

El protocolo utiliza un sentinela de JSON con marcas\“tool {…}```— que cualquier modelo puede producir. No se requiere una API nativa de llamada a herramientas, por lo que funciona en todos los modelos de Ollama sin necesidad de configuración adicional. (Los modelos que admiten llamadas a herramientas nativas pueden integrarse mediante una subclase que sobrescriba el métodoparseToolCall()`.)

Nibiru envía tres:

Herramienta¿Qué hace?
Tools\PdoQueryLectura única y de solo lectura SELECT contra la base de datos de la aplicación. Bloquea INSERT/UPDATE/DELETE/DROP/TRUNCATE/ALTER. Devuelve hasta 50 filas como JSON.
Tools\HttpGetObtiene una URL HTTP/HTTPS con encabezados opcionales. Devuelve el cuerpo, truncado a 8 KB.
Tools\FileReadLee un archivo del proyecto por ruta relativa. Bloquea la traversión ... Devuelve hasta 8 KB.
use Nibiru\Module\Ai\Plugin\Tools;
$agent = $ai->agent()->withTools([
new Tools\PdoQuery(),
new Tools\HttpGet(),
new Tools\FileRead(),
]);
// Multi-step task
echo $agent->run(
'Read application/controller/loginController.php and tell me '
. 'whether it implements rate limiting.'
);

El agente llamará a file_read con la ruta, observará el origen y responderá basándose en lo que realmente vio — no en lo que imaginó.

Extienda Tool:

namespace App\AiTools;
use Nibiru\Module\Ai\Plugin\Tool;
class StripeRefund extends Tool
{
public function name(): string { return 'stripe_refund'; }
public function description(): string {
return 'Issue a Stripe refund for a charge ID.';
}
public function schema(): array {
return [
'charge_id' => [
'type' => 'string',
'description' => 'A Stripe charge ID, e.g. ch_3K…',
'required' => true,
],
'amount_cents' => [
'type' => 'integer',
'description' => 'Amount to refund in cents. Omit for full refund.',
'required' => false,
],
];
}
public function execute(array $args): mixed {
$stripe = new \Stripe\StripeClient(getenv('STRIPE_SECRET_KEY'));
$refund = $stripe->refunds->create(array_filter([
'charge' => $args['charge_id'],
'amount' => $args['amount_cents'] ?? null,
]));
return json_encode([
'refund_id' => $refund->id,
'status' => $refund->status,
'amount' => $refund->amount,
]);
}
}

Luego conéctalo:

$ai->agent()
->withTools([new \App\AiTools\StripeRefund(), new Tools\PdoQuery()])
->run('Refund order #4421 — they were charged twice.');

El agente utilizará pdo_query para encontrar la carga, luego llamará a stripe_refund con ese ID de carga.

$agent = $ai->agent()->withTools([new Tools\PdoQuery()]);
$answer = $agent->run('How many products in the gold-plating category?');
foreach ($agent->trace() as $step) {
echo "Step {$step['step']}: action={$step['action']}\n obs={$step['observation']}\n";
}

Útil para la depuración, registros de auditoría o para construir una interfaz de usuario “muestra tu trabajo”.

  • PdoQuery bloquea escrituras. Si necesitas acceso de escritura, escribe una subclase más privilegiada con un registro de auditoría. No levantes la restricción de solo SELECT en la herramienta incorporada.
  • HttpGet permite cualquier URL por defecto. Bloquea mediante una lista blanca en [AI] http_allowed_hosts[] (planeado), o escribe una subclase RestrictedHttpGet que filtre las URLs.
  • FileRead bloquea ... Está confinido a la raíz de la aplicación.
  • Iteraciones máximas. agent.max_iterations = 6 en el INI previene bucles sin control. Aumenta con cuidado.
  • Tiempo de espera de herramienta. agent.tool_timeout = 30 (segundos). Una herramienta que se atasque no mantendrá la solicitud para siempre.
  • Olvidar withTools(). Sin herramientas, el agente es solo un Chat regular.
  • Permitir que el agente vea secretos. Nunca pongas claves API, contraseñas en bruto o datos personales identificables (PII) en la respuesta de una herramienta — el modelo recibe la cadena completa.
  • Salidas largas de herramientas. Cada observación se anexa a la conversación. Una herramienta que vuelca 50 KB agotará rápidamente el contexto. Las herramientas integradas tienen un límite de 8 KB; haz lo mismo en tus herramientas personalizadas.
  • No hay llamada a herramienta en la respuesta = respuesta final. Si el modelo produce una respuesta final que parece una llamada a herramienta pero no se valida, el agente la trata como final. Sé explícito en el aviso: “Salida una llamada a herramienta O una respuesta final, nunca ambas.”