> ## Documentation Index
> Fetch the complete documentation index at: https://docs.vizra.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Macros & Mixins

> Extend Vizra ADK with custom methods using Laravel's powerful macros and mixins pattern

## What are Macros?

Macros allow you to add custom methods to classes at runtime. This is a powerful extensibility pattern borrowed from Laravel that lets you extend Vizra ADK's functionality without modifying the core code.

<CardGroup cols={2}>
  <Card title="Custom Tracking" icon="chart-line">
    Add analytics and tracking to your agents
  </Card>

  <Card title="Third-party Integrations" icon="plug">
    Integrate with external services seamlessly
  </Card>

  <Card title="Domain Logic" icon="building">
    Add business-specific functionality
  </Card>

  <Card title="Reusable Patterns" icon="recycle">
    Create patterns you can use across your app
  </Card>
</CardGroup>

## Supported Classes

The following Vizra ADK classes support macros:

| Class             | Access            | Description                          |
| ----------------- | ----------------- | ------------------------------------ |
| `AgentManager`    | `Agent` facade    | Central agent management             |
| `AgentBuilder`    | Fluent builder    | Agent configuration and registration |
| `WorkflowManager` | `Workflow` facade | Workflow orchestration               |

## Basic Usage

### Registering a Macro

Register macros in your `AppServiceProvider::boot()` method:

```php app/Providers/AppServiceProvider.php theme={null}
<?php

namespace App\Providers;

use Vizra\VizraADK\Services\AgentBuilder;
use Vizra\VizraADK\Facades\Agent;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        // Add a tracking macro for analytics
        AgentBuilder::macro('track', function (Model $model) {
            $this->trackedModel = $model;
            return $this; // Return $this for method chaining
        });
    }
}
```

### Using Your Macro

```php theme={null}
use App\Models\Unit;
use Vizra\VizraADK\Facades\Agent;

// Step 1: Use the macro when registering the agent
Agent::build(CustomerSupportAgent::class)
    ->track(Unit::find(12))
    ->register();

// Step 2: Run the agent using the executor API
$response = CustomerSupportAgent::run('User input')
    ->forUser($user)
    ->go();
```

<Tip>
  **Always return `$this`** from your macros to maintain the fluent interface and enable method chaining.
</Tip>

## Real-World Examples

### Analytics Tracking

Track which models are using AI features:

```php theme={null}
use Vizra\VizraADK\Services\AgentBuilder;
use Illuminate\Database\Eloquent\Model;

AgentBuilder::macro('track', function (Model $model) {
    $this->trackedModel = $model;
    $this->trackedModelType = get_class($model);
    $this->trackedModelId = $model->getKey();
    return $this;
});

// Usage
Agent::build(MyAgent::class)
    ->track(Unit::find(12))
    ->register();

// Then run the agent
MyAgent::run('User input')
    ->forUser($user)
    ->go();
```

### Conditional Execution

Add conditional logic to your builder:

```php theme={null}
AgentBuilder::macro('whenCondition', function ($condition, callable $callback) {
    if ($condition) {
        $callback($this);
    }
    return $this;
});

// Usage
$agentName = Agent::define('conditional-agent')
    ->whenCondition($user->isPremium(), function ($builder) {
        $builder->model('gpt-4o');
    })
    ->whenCondition(!$user->isPremium(), function ($builder) {
        $builder->model('gpt-4o-mini');
    })
    ->register();

// Run the defined agent
Agent::named($agentName)->run('User input')->go();
```

### Metadata Tagging

Add metadata for logging or debugging:

```php theme={null}
AgentBuilder::macro('withTags', function (array $tags) {
    $this->tags = $tags;
    return $this;
});

AgentBuilder::macro('withPriority', function (string $priority) {
    $this->priority = $priority;
    return $this;
});

// Usage
$agentName = Agent::define('support-agent')
    ->withTags(['customer-facing', 'urgent'])
    ->withPriority('high')
    ->register();

// Run the agent
Agent::named($agentName)->run('User input')->go();
```

### Cost Tracking

Track estimated costs for budget monitoring:

```php theme={null}
AgentBuilder::macro('trackCost', function (string $costCenter) {
    $this->costCenter = $costCenter;
    $this->trackTokenUsage = true;
    return $this;
});

// Usage
Agent::build(AnalyticsAgent::class)
    ->trackCost('DEPT-001')
    ->register();

// Run the agent
AnalyticsAgent::run('User input')->go();
```

## Using Mixins

Mixins allow you to add multiple macros at once by grouping related functionality in a class:

```php app/Mixins/AnalyticsMixin.php theme={null}
<?php

namespace App\Mixins;

use Illuminate\Database\Eloquent\Model;

class AnalyticsMixin
{
    public function track()
    {
        return function (Model $model) {
            $this->trackedModel = $model;
            return $this;
        };
    }

    public function recordActivity()
    {
        return function ($activity) {
            $this->activityLog[] = $activity;
            return $this;
        };
    }

    public function getActivityLog()
    {
        return function () {
            return $this->activityLog ?? [];
        };
    }
}
```

Register the mixin in your service provider:

```php app/Providers/AppServiceProvider.php theme={null}
use Vizra\VizraADK\Services\AgentBuilder;
use App\Mixins\AnalyticsMixin;

public function boot(): void
{
    AgentBuilder::mixin(new AnalyticsMixin());
}
```

Now use all the mixed-in methods:

```php theme={null}
$agentName = Agent::define('analytics-agent')
    ->track($unit)
    ->recordActivity('agent_created')
    ->recordActivity('agent_configured')
    ->register();

// Run the agent
Agent::named($agentName)->run('User input')->go();
```

<Info>
  Mixins are ideal when you have a group of related macros that logically belong together, such as analytics, auditing, or domain-specific operations.
</Info>

## Advanced Patterns

### Integration with Events

Combine macros with Laravel events for powerful side effects:

```php theme={null}
use App\Events\AgentTracked;

AgentBuilder::macro('trackWithEvent', function (Model $model) {
    $this->trackedModel = $model;

    // Fire an event when the agent is used
    event(new AgentTracked($model, $this));

    return $this;
});
```

### Dynamic Configuration

Load configuration dynamically from your models:

```php theme={null}
AgentBuilder::macro('configureFor', function (Model $model) {
    // Load model-specific configuration
    $config = $model->agentConfiguration ?? [];

    if (isset($config['model'])) {
        $this->model($config['model']);
    }

    if (isset($config['instructions'])) {
        $this->instructions($config['instructions']);
    }

    return $this;
});

// Usage
Agent::build(MyAgent::class)
    ->configureFor($tenant)
    ->register();

// Run the agent
MyAgent::run('User input')->go();
```

### Workflow Macros

Add custom workflow types using the `WorkflowManager`:

```php theme={null}
use Vizra\VizraADK\Facades\Workflow;
use Vizra\VizraADK\Services\WorkflowManager;

WorkflowManager::macro('retryable', function (string $agentClass, int $maxRetries = 3) {
    $retries = $maxRetries;
    return Workflow::loop($agentClass)
        ->until(function ($result) use (&$retries) {
            return $result->success || $retries-- <= 0;
        });
});

// Usage
$result = Workflow::retryable(UnreliableAgent::class, 5)->go();
```

## Best Practices

<CardGroup cols={2}>
  <Card title="Return $this" icon="link">
    Always return `$this` to maintain the fluent interface
  </Card>

  <Card title="Register Early" icon="clock">
    Register macros in `AppServiceProvider::boot()`
  </Card>

  <Card title="Descriptive Names" icon="tag">
    Use clear, descriptive names for your macros
  </Card>

  <Card title="Document Well" icon="book">
    Document macros for other developers on your team
  </Card>
</CardGroup>

Additional tips:

* **Consider scope** - Macros are global, so namespace them if needed to avoid conflicts
* **Test your macros** - Write tests to ensure macros work as expected
* **Group related macros** - Use mixins to organize related functionality

## Testing Macros

Test your macros using Pest or PHPUnit:

```php tests/Feature/MacroTest.php theme={null}
use Vizra\VizraADK\Services\AgentBuilder;
use Vizra\VizraADK\Facades\Agent;
use App\Models\Unit;

it('can track models with macro', function () {
    AgentBuilder::macro('track', function (Model $model) {
        $this->trackedModel = $model;
        return $this;
    });

    $model = Unit::factory()->create();
    $builder = Agent::define('test-agent')->track($model);

    expect($builder->trackedModel)->toBe($model);
});
```

<Tip>
  The full test suite for macro support is available at `tests/Feature/MacroSupportTest.php` with 10 comprehensive tests covering all major use cases.
</Tip>

## Learn More

<CardGroup cols={2}>
  <Card title="Laravel Macros Docs" icon="laravel" href="https://laravel.com/docs/11.x/helpers#method-macro">
    Official Laravel documentation on macros
  </Card>

  <Card title="Agent Builder API" icon="book" href="/api-reference/agent-class">
    Complete AgentBuilder reference
  </Card>
</CardGroup>
