PHPackages                             raulast/macro-llm-php - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. raulast/macro-llm-php

ActiveLibrary[API Development](/categories/api)

raulast/macro-llm-php
=====================

Provider-agnostic AI client for Laravel, Slim 4, and standalone PHP. Extends Laravel's HTTP client via macros with support for OpenAI, Anthropic, Gemini, Groq, OpenRouter, Ollama, and llama.cpp. Includes tool calling, skills, agents, multi-agent orchestration, and MCP server/client.

00PHP

Since Jun 22Pushed todayCompare

[ Source](https://github.com/raulast/macro-llm-php)[ Packagist](https://packagist.org/packages/raulast/macro-llm-php)[ RSS](/packages/raulast-macro-llm-php/feed)WikiDiscussions master Synced today

READMEChangelogDependenciesVersions (1)Used By (0)

macro-llm-php
=============

[](#macro-llm-php)

Provider-agnostic AI client for Laravel, Slim 4, and standalone PHP.

[![PHP Version](https://camo.githubusercontent.com/1bf6755ff9e196d6f7a5b65c052f137b3bbe53acadadb347a680847ba27d7aad/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f7261756c6173742f6d6163726f2d6c6c6d2d706870)](https://packagist.org/packages/raulast/macro-llm-php)[![Laravel](https://camo.githubusercontent.com/e318ae4be28139e4db425542a2f219c31be670221baae920b3fb42e6784d7cc7/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c61726176656c2d31302e7825323025374325323031312e782d726564)](https://laravel.com)[![License](https://camo.githubusercontent.com/667a0124b26c4ee5d1260dda3265045d3eca77b9848ffef9627a7ad8f943d8e2/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f7261756c6173742f6d6163726f2d6c6c6d2d706870)](LICENSE)[![Packagist](https://camo.githubusercontent.com/58c436a2ff637ad8500d2e62772a6375870359368df058edb1edabd782de8078/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f7261756c6173742f6d6163726f2d6c6c6d2d706870)](https://packagist.org/packages/raulast/macro-llm-php)

Overview
--------

[](#overview)

MacroLLM extends Laravel's HTTP client (`PendingRequest`) through PHP macros, giving you a unified interface to interact with any AI provider. Call `Http::openai(...)`, `Http::anthropic(...)`, or `Http::gemini(...)` with the same request format — swap providers by changing a single string.

Internally, every request and response flows through a normalized format (`InternalRequest` / `InternalResponse`). Providers implement bidirectional normalization: your application code stays the same regardless of which provider is behind the call. This decouples business logic from vendor-specific APIs and makes provider migration a configuration change, not a rewrite.

On top of the provider layer, MacroLLM provides a full agentic stack: **Skills** (reusable system-prompt + tool bundles), **Agents** (automatic tool-call loops with configurable memory), and **Orchestration** (sequential or parallel multi-agent workflows). Combined with built-in MCP client/server support, you can build complex AI-powered systems while keeping each piece testable and swappable.

Features
--------

[](#features)

- 9 built-in providers: OpenAI, Anthropic, Gemini, Groq, OpenRouter, Ollama, llama.cpp, OpenCode Zen Go, OpenCode Zen Go (Anthropic)
- Unified `InternalRequest` / `InternalResponse` format with bidirectional normalization
- Automatic tool-call loop via `Agent`
- Reusable Skills (system prompt + tools + config — composable, subclassable, DB-hydratable via `fromArray`)
- Parametrizable conversation memory (`NullMemory` stateless default, `InMemoryMemory`, extensible)
- Multi-agent Orchestration (sequential and parallel via Guzzle concurrent requests)
- MCP Client — discover and use tools from any MCP server
- MCP Server — expose your tools as a PSR-15 middleware endpoint
- Laravel integration (ServiceProvider, Facade, auto-discovery, `vendor:publish`)
- Slim 4 integration (`MacroLLMSlimExtension`)
- Standalone PHP — no framework required
- PHP 8.1+ (enums, readonly classes, fibers)

Supported Providers
-------------------

[](#supported-providers)

ProviderTypeAuthDefault Base URLNotesopenaiOpenAI-compatibleBearer API key`api.openai.com/v1`Also supports Azure OpenAI via `base_url` overrideanthropicNativex-api-key header`api.anthropic.com/v1`Messages APIgeminiNativex-goog-api-key header`generativelanguage.googleapis.com/v1beta`generateContent APIgroqOpenAI-compatibleBearer API key`api.groq.com/openai/v1`openrouterOpenAI-compatibleBearer API key`openrouter.ai/api/v1`Model names prefixed: `openai/gpt-4o`ollamaOpenAI-compatibleOptional`localhost:11434/v1`Local inferencellamacppOpenAI-compatibleNone`localhost:8080/v1`Local inferenceopencode-zen-goOpenAI-compatibleBearer API key`opencode.ai`GLM, Kimi, DeepSeek, MiMo; API key from [opencode.ai](https://opencode.ai) Zen consoleopencode-zen-go-anthropicAnthropic-compatiblex-api-key header`opencode.ai`MiniMax, Qwen; same API key as opencode-zen-goRequirements
------------

[](#requirements)

- PHP ^8.1
- Laravel ^10 | ^11 (optional, for Laravel integration)

Installation
------------

[](#installation)

```
composer require raulast/macro-llm-php
```

Laravel auto-discovery registers the ServiceProvider automatically. Optionally publish the config:

```
php artisan vendor:publish --tag=macro-llm-config
```

Configuration
-------------

[](#configuration)

The config file (`config/macro-llm.php`) defines:

KeyDescriptionDefault`default_provider`Provider used when none is specified`ollama``timeout`Global request timeout in seconds`30``retries`Automatic retries on failure`0``max_tool_iterations`Max agent tool-call loop iterations`10``providers`Array of provider configurations—`mcp_servers`External MCP server connections—Each provider entry supports: `api_key`, `default_model`, `base_url`, `timeout`, `retries`, `extra_headers`.

API keys support environment variable patterns (`'${ENV_VAR}'`) resolved lazily at access time.

Example `.env` entries:

```
MACRO_LLM_DEFAULT_PROVIDER=openai
OPENAI_API_KEY=sk-...
ANTHROPIC_API_KEY=sk-ant-...
GEMINI_API_KEY=AIza...
GROQ_API_KEY=gsk_...
OPENROUTER_API_KEY=sk-or-...
OPENCODE_ZEN_API_KEY=ocz-...
```

Usage
-----

[](#usage)

### Standalone (no framework)

[](#standalone-no-framework)

```
use MacroLLM\MacroLLM;
use MacroLLM\Config\Config;
use MacroLLM\Message\InternalRequest;
use MacroLLM\Message\InternalMessage;

$llm = MacroLLM::standalone(Config::fromArray([
    'default_provider' => 'openai',
    'providers' => [
        'openai' => ['api_key' => '${OPENAI_API_KEY}', 'default_model' => 'gpt-4o'],
    ],
]));

$response = $llm->chat(new InternalRequest([
    InternalMessage::user('Hello, world!'),
]));

echo $response->content;
```

### Laravel (via Facade)

[](#laravel-via-facade)

```
use MacroLLM\Integration\Laravel\MacroLLMFacade as LLM;
use MacroLLM\Message\InternalRequest;
use MacroLLM\Message\InternalMessage;

$response = LLM::chat(new InternalRequest([
    InternalMessage::system('You are a helpful assistant.'),
    InternalMessage::user('What is Laravel?'),
]));
```

### Laravel (via HTTP macro)

[](#laravel-via-http-macro)

```
use MacroLLM\Message\InternalRequest;
use MacroLLM\Message\InternalMessage;

$response = Http::openai(new InternalRequest([
    InternalMessage::user('Explain macros in PHP.'),
]));
```

### Streaming

[](#streaming)

```
foreach ($llm->stream(new InternalRequest([InternalMessage::user('Tell me a story.')])) as $chunk) {
    if ($chunk->finished) {
        echo "\n\n[done — {$chunk->response->usage->totalTokens} tokens]\n";
        break;
    }
    echo $chunk->delta;
    flush();
}
```

### Listing Available Models

[](#listing-available-models)

```
// Fetches live model list from the provider's own API (may make HTTP request)
$models = $llm->models('openai');
// → ['gpt-4o', 'gpt-4o-mini', 'o1', 'o3', ...]

$models = $llm->models('anthropic');
// → ['claude-opus-4-5', 'claude-sonnet-4-5', ...]

// OpenCode Zen fetches from GET /zen/go/v1/models
$models = $llm->models('opencode-zen-go');
// → ['deepseek-v3-0324', 'glm-z1-flash', 'kimi-k2', ...]

// Ollama and llama.cpp reflect locally installed / loaded models
$models = $llm->models('ollama');
// → ['llama3.2:latest', 'codellama:7b', ...]

// Via the Facade (Laravel)
$models = \MacroLLM\Integration\Laravel\MacroLLMFacade::models('gemini');

// Via provider directly (no HTTP needed for provider object access)
$provider = $llm->providers()->get('groq');
$models = $provider->getModels();
```

### Tool Calling

[](#tool-calling)

```
use MacroLLM\Tool\ToolDefinition;

$llm->tools()->register(new ToolDefinition(
    name: 'get_weather',
    description: 'Get the current weather for a city.',
    parameters: [
        'type' => 'object',
        'properties' => [
            'city' => ['type' => 'string', 'description' => 'City name'],
        ],
        'required' => ['city'],
    ],
    callable: fn(array $args): string => "Sunny, 22°C in {$args['city']}",
));

$agent = $llm->agent(new \MacroLLM\Agent\AgentConfig(
    provider: 'openai',
    maxIterations: 5,
));

$response = $agent->run('What is the weather in Buenos Aires?');
echo $response->content;
```

### Skills

[](#skills)

```
use MacroLLM\Skill\Skill;

// Inline skill
$translatorSkill = Skill::create(
    name: 'translator',
    systemPrompt: 'You are a professional translator. Always respond in the target language.',
    tools: ['detect_language', 'translate_text'],
);

$llm->skills()->register($translatorSkill);

// From DB record
$skillData = $db->find('skills', 1);
$skill = Skill::fromArray($skillData);
$llm->skills()->register($skill);

// Dynamic skill via subclass
class SupportSkill extends Skill
{
    public function __construct(private string $product) {}
    public function getName(): string { return 'support'; }
    public function getSystemPrompt(): string {
        return "You are a support agent for {$this->product}. Be helpful and concise.";
    }
}
```

### Conversation Memory

[](#conversation-memory)

```
use MacroLLM\Agent\AgentConfig;
use MacroLLM\Agent\Memory\InMemoryMemory;

$agent = $llm->agent(new AgentConfig(
    provider: 'anthropic',
    memory: new InMemoryMemory(), // stateful — remembers across run() calls
));

$agent->run('My name is Ana.');
$response = $agent->run('What is my name?');
echo $response->content; // "Your name is Ana."
```

### Multi-Agent Orchestration

[](#multi-agent-orchestration)

```
use MacroLLM\Orchestration\Orchestrator;
use MacroLLM\Orchestration\RoutingStrategy;
use MacroLLM\Orchestration\ErrorStrategy;

$orchestrator = new Orchestrator(
    routing: RoutingStrategy::Parallel,
    errorStrategy: ErrorStrategy::Continue,
);

$orchestrator->addAgent('researcher', $llm->agent(new AgentConfig(
    provider: 'openai',
    systemPrompt: 'Research and summarize information.',
)));

$orchestrator->addAgent('writer', $llm->agent(new AgentConfig(
    provider: 'anthropic',
    systemPrompt: 'Write engaging content based on research.',
)));

$result = $orchestrator->dispatch('Write an article about PHP 8.1 fibers.');

foreach ($result->outcomes as $outcome) {
    echo "Agent {$outcome->agentName} ({$outcome->durationMs}ms):\n";
    echo $outcome->response?->content . "\n\n";
}
```

### MCP Client

[](#mcp-client)

```
use MacroLLM\Mcp\MCPClient;

$mcp = new MCPClient($llm->tools());
$mcp->connect('filesystem', 'http://localhost:3001', auth: 'my-token');
// Tools now available as "filesystem/read_file", "filesystem/write_file", etc.

$agent = $llm->agent(new AgentConfig(provider: 'openai'));
$response = $agent->run('Read the contents of /tmp/notes.txt');
```

### MCP Server (Laravel)

[](#mcp-server-laravel)

```
// In a Laravel route or controller:
use MacroLLM\Mcp\MCPServer;
use MacroLLM\Mcp\MCPServerMiddleware;

// Mount as PSR-15 middleware on /mcp
$app->middleware(MCPServerMiddleware::class);
// External MCP clients can now call tools/list and tools/call on /mcp
```

### Slim 4

[](#slim-4)

```
use MacroLLM\Integration\Slim\MacroLLMSlimExtension;

$extension = new MacroLLMSlimExtension($container, require 'config/macro-llm.php');
$extension->register();

$macroLLM = $container->get(\MacroLLM\MacroLLM::class);
```

Directory Structure
-------------------

[](#directory-structure)

```
src/
├── Agent/          # Agent loop, AgentConfig, Memory strategies
├── Config/         # Config and ProviderConfig value objects
├── Contract/       # Interfaces (Provider, Skill, Memory, Concurrency)
├── Exception/      # Domain-specific exceptions
├── Integration/    # Framework bindings (Laravel, Slim)
├── Mcp/            # MCP Client, Server, and PSR-15 middleware
├── Message/        # InternalRequest, InternalResponse, StreamChunk, Usage
├── Orchestration/  # Multi-agent orchestrator, strategies, results
├── Provider/       # Provider implementations and factory
├── Registry/       # Tool, Skill, and Provider registries
├── Skill/          # Base Skill class (composable, subclassable)
├── Tool/           # ToolDefinition, ToolCall, ToolResult
├── skill-macro-llm-php/  # AI agent skill document (SKILL.md for coding assistants)
└── MacroLLM.php    # Main entry point and macro registration

```

Architecture
------------

[](#architecture)

MacroLLM follows a hexagonal architecture. The core domain (`Message`, `Contract`, `Registry`) has no framework dependencies. The provider layer implements bidirectional normalization behind `ProviderInterface`, so adding a new provider means implementing a single class without touching application code. The agentic layer (`Agent`, `Skill`, `Orchestration`) composes on top of the provider layer, using the same normalized types. Framework integrations (`Laravel`, `Slim`) are thin adapters that wire the core into their respective DI containers and lifecycle hooks.

Exception Handling
------------------

[](#exception-handling)

ExceptionThrown when`UnregisteredProviderException`Macro called for unregistered provider`ProviderRequestException`HTTP 4xx/5xx from provider API`MissingApiKeyException`API key missing before request`ToolNotFoundException`Model requested an unregistered tool`MaxToolIterationsException`Agent loop exceeded max iterations`SkillToolConflictException`Two composed skills define same tool`SkillToolNotFoundException`Skill references a tool not in the registry`MCPConnectionException`MCP server unreachable`MCPToolCallException`MCP server returned error`StreamInterruptedException`SSE stream ended unexpectedlyLicense
-------

[](#license)

MIT — see [LICENSE](LICENSE) file.

Author
------

[](#author)

Raul Antonio Salazar Torres —

###  Health Score

20

—

LowBetter than 13% of packages

Maintenance65

Regular maintenance activity

Popularity0

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity11

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/42895495?v=4)[Raúl Salazar Torres](/maintainers/raulast)[@raulast](https://github.com/raulast)

---

Top Contributors

[![raulast](https://avatars.githubusercontent.com/u/42895495?v=4)](https://github.com/raulast "raulast (6 commits)")

### Embed Badge

![Health badge](/badges/raulast-macro-llm-php/health.svg)

```
[![Health](https://phpackages.com/badges/raulast-macro-llm-php/health.svg)](https://phpackages.com/packages/raulast-macro-llm-php)
```

###  Alternatives

[exsyst/swagger

A php library to manipulate Swagger specifications

35816.3M7](/packages/exsyst-swagger)[hubspot/api-client

Hubspot API client

24015.5M18](/packages/hubspot-api-client)[botman/driver-telegram

Telegram driver for BotMan

93452.6k6](/packages/botman-driver-telegram)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
