Skip to content

Extending Orbit ​

Orbit is designed to be extended. Use contracts, service bindings, and custom implementations to tailor the dashboard to your needs.

Contracts ​

Orbit defines contracts (interfaces) for core services:

AgentRegistryContract ​

php
use Ashrafic\AiOrbit\Contracts\AgentRegistryContract;

interface AgentRegistryContract
{
    public function all(): Collection;
    public function find(string $class): ?array;
    public function refresh(): void;
}

Bind your custom implementation:

php
// In AppServiceProvider
use Ashrafic\AiOrbit\Contracts\AgentRegistryContract;
use App\Services\CustomAgentRegistry;

public function register(): void
{
    $this->app->singleton(AgentRegistryContract::class, CustomAgentRegistry::class);
}

Custom Agent Registry Example ​

php
namespace App\Services;

use Ashrafic\AiOrbit\Contracts\AgentRegistryContract;
use Illuminate\Support\Collection;

class CustomAgentRegistry implements AgentRegistryContract
{
    public function all(): Collection
    {
        // Load agents from your own source (database, API, etc.)
        return collect([
            'App\AI\Agents\SupportAgent',
            'App\AI\Agents\SalesAgent',
        ]);
    }

    public function find(string $class): ?array
    {
        // Return custom metadata
        return [
            'class' => $class,
            'instructions' => 'Custom instructions',
            'tools' => [],
            'has_schema' => false,
        ];
    }

    public function refresh(): void
    {
        // Clear any caches
    }
}

Extending Services ​

Custom Cost Calculator ​

php
use Ashrafic\AiOrbit\Services\CostCalculator;

class CustomCostCalculator extends CostCalculator
{
    public function calculate(string $model, int $inputTokens, int $outputTokens): array
    {
        // Add your own pricing logic
        if ($model === 'custom-model') {
            return [
                'input_cost' => 0,
                'output_cost' => 0,
                'total' => 0,
                'currency' => 'USD',
            ];
        }

        return parent::calculate($model, $inputTokens, $outputTokens);
    }
}

Bind it:

php
app()->singleton(CostCalculator::class, CustomCostCalculator::class);

Custom Export Service ​

php
use Ashrafic\AiOrbit\Services\ExportService;

class CustomExportService extends ExportService
{
    public function toPest(string $conversationId): string
    {
        $content = parent::toPest($conversationId);
        
        // Add custom assertions or setup
        $content .= "\n    // Custom assertion\n";
        $content .= "    expect(true)->toBeTrue();\n";
        
        return $content;
    }
    
    public function toXml(string $conversationId): string
    {
        // Add a completely new export format
        $conversation = $this->repository->find($conversationId);
        // ... XML generation logic
    }
}

Custom Livewire Components ​

Create entirely new Livewire components that integrate with Orbit:

php
namespace App\Http\Livewire;

use Ashrafic\AiOrbit\Services\ConversationRepository;
use Livewire\Component;

class CustomAnalytics extends Component
{
    public function render()
    {
        $repository = app(ConversationRepository::class);
        
        // Your custom analytics logic
        $stats = $this->calculateCustomStats();
        
        return view('livewire.custom-analytics', [
            'stats' => $stats,
        ]);
    }
}

Register it:

php
use Livewire\Livewire;
use App\Http\Livewire\CustomAnalytics;

Livewire::component('custom-analytics', CustomAnalytics::class);

Use it in a published view:

blade
<livewire:custom-analytics />

Custom Middleware ​

Add custom middleware to Orbit routes by extending the middleware stack:

php
// config/ai-orbit.php
'middleware' => ['web', 'auth', 'custom-middleware'],

Custom Notifications ​

Extend Orbit's notifications:

php
use Ashrafic\AiOrbit\Notifications\BudgetExceeded;

class SlackBudgetExceeded extends BudgetExceeded
{
    public function via(object $notifiable): array
    {
        return ['mail', 'slack'];
    }
    
    public function toSlack(object $notifiable): SlackMessage
    {
        return (new SlackMessage)
            ->content("Budget alert: {$this->alert->period} threshold exceeded!");
    }
}

Events ​

Orbit dispatches events that you can listen to:

Override Events ​

Listen for Livewire events in your components:

php
// In your custom component
#[On('tool-call-counts-updated')]
public function handleToolCallCounts(array $counts): void
{
    // React to tool call updates
}

Best Practices ​

  1. Extend, don't replace — Where possible, extend existing services rather than replacing them entirely
  2. Use contracts — Program against interfaces (AgentRegistryContract) rather than concrete classes
  3. Test extensions — Write tests for your custom implementations
  4. Document changes — Keep a record of what you've extended for future maintainers
  5. Watch for updates — Major Orbit updates may change service signatures; test after updating