NANOAGENT

NanoAgent: Your First AI Agent in PHP

PHP developers get a lot of AI examples — but almost all of them start in Python. If your app is already in PHP (and it usually is), the "add an agent" path looks like bolting on a sidecar or learning a framework. It doesn't have to.

This is the smallest working agent in NanoAgent: one agent, one custom tool, one task.

The four pieces

An agent in NanoAgent is just four objects:

  • Agent — talks to the LLM.
  • FunctionTool — a PHP callable the model can choose to invoke.
  • Task — bundles a goal with background context.
  • A config — provider, model, API key.
  • Let's build it piece by piece. First, the boilerplate: pull in the autoloader and the three classes you need.

    php
    require_once __DIR__ . '/../NanoAgent/autoloader.php';
    
    use NanoAgent\Agent;
    use NanoAgent\Task;
    use NanoAgent\Tools\FunctionTool;

    1. Config — where the LLM connection details live

    Rather than hard-code a provider and API key, read them from a config.php file if one exists, and fall back to sane defaults (Groq's free tier) if it doesn't. This means the same script runs out of the box for a first-time reader, and switches provider for anyone with their own config.

    php
    $configFile = __DIR__ . '/../NanoAgent/config.php';
    $config = file_exists($configFile) ? require $configFile : [];
    
    $llmConfig = [
        'provider' => $config['provider'] ?? 'groq',
        'model'    => $config['model']    ?? 'llama-3.3-70b-versatile',
        'api_key'  => $config['api_key']  ?? ''
    ];

    2. The tool — a PHP function the model can call

    A FunctionTool wraps three things: a name the model refers to, a description it reads to decide when to use the tool, and a JSON Schema describing the arguments. The callable is just a normal PHP closure — here it fabricates a "secret token" from the input string.

    php
    $secretTool = new FunctionTool(
        name: 'generate_secret_token',
        description: 'Generates a secure token based on input string.',
        parameters: [
            'type' => 'object',
            'properties' => [
                'input' => ['type' => 'string', 'description' => 'The string to obfuscate']
            ],
            'required' => ['input']
        ],
        callable: fn(array $args) => "TOKEN_" . strtoupper(strrev($args['input'])) . "_SECURE"
    );

    3. The agent — the brain that decides when to use the tool

    The Agent ties the LLM config to a system prompt and the list of tools it's allowed to use. Nothing runs yet — this just assembles the pieces.

    php
    $agent = new Agent(
        llm: $llmConfig,
        systemPrompt: "You are a helpful PHP technical assistant.",
        tools: [$secretTool]
    );

    4. The task — the actual goal, plus context

    A Task bundles a goal with any background context you want the model to have (here, just the project name). Calling execute() is what actually sends the prompt, lets the model call the tool if it wants to, and returns the final answer.

    php
    $task = new Task($agent);
    $task->addContext("Project", "NanoAgent Library");
    
    $response = $task->execute(
        "Generate a secret token for 'NanoAgent' and explain how it was created."
    );
    
    echo $response;

    Why the tool matters

    The FunctionTool is the whole idea. You describe a PHP function with a JSON Schema, and the model decides when to call it and what to pass. Task::execute() formats the goal + context into a prompt, and handles the tool round-trip for you — when the model asks to call generatesecrettoken, the agent runs your callable, feeds the result back, and continues. You never wire that loop by hand.

    What this unlocks

    That's the floor. Once you have an agent that can call tools, everything else is adding more tools or more agents:

  • Stateful chat that survives requests
  • Persistent memory that survives restarts
  • Structured output from unstructured text
  • MCP: remote tool servers in 4 lines
  • Ready to ship an agent?

    $ composer require hammrouni/nanoagent

    MIT, zero dependencies. Explore the full series - each article teaches one pattern.

    Get each new article by email - one per publish day + the 12-part cheatsheet when it drops.