Custom Drivers & Extension

v1.0.0

Extend Obelaw SystemOne with custom decision drivers for local LLMs, OpenAI, Anthropic, or on-premise inference engines.

Custom Drivers & Extension

Obelaw SystemOne is engineered from the ground up to be driver-agnostic. While obelaw/systemone-clef provides turnkey edge inference via Cloudflare Workers AI, you can easily integrate any AI provider, local inference runtime (e.g. Ollama, vLLM), or custom rule engine.


The Driver Contract

Every SystemOne driver implements Obelaw\SystemOne\Contracts\DriverInterface:

flowchart TD
    App["Laravel Application Code"] --> Facade["SystemOne Facade"]
    Facade --> Manager["SystemOneManager"]

    Manager -->|"driver('clef')"| Clef["ClefDriver (Official)<br/>Cloudflare Workers AI"]
    Manager -->|"driver('ollama')"| Ollama["OllamaDriver (Custom)<br/>Local Daemon :11434"]
    Manager -->|"driver('vllm')"| VLLM["vLLM / Custom Driver<br/>On-Premise GPU Cluster"]

    subgraph DriverContract["DriverInterface Contract"]
        direction TB
        M1["decide(DecisionRequest): DecisionResponseInterface"]
        M2["run(DecisionRequest): DecisionResponseInterface"]
    end

    Clef -.-> DriverContract
    Ollama -.-> DriverContract
    VLLM -.-> DriverContract
namespace Obelaw\SystemOne\Contracts;

use Obelaw\SystemOne\DecisionRequest;

interface DriverInterface
{
    /**
     * Execute the decision request and return a response.
     */
    public function decide(DecisionRequest $request): DecisionResponseInterface;

    /**
     * Alias for decide().
     */
    public function run(DecisionRequest $request): DecisionResponseInterface;
}

Registering Custom Drivers

You can register custom drivers using two convenient approaches:

Approach A: Using SystemOne::extend()

Ideal for registering custom drivers in your AppServiceProvider or dedicated package service provider:

namespace App\Providers;

use App\Services\SystemOne\OllamaDriver;
use Illuminate\Support\ServiceProvider;
use Obelaw\SystemOne\Facades\SystemOne;
use Obelaw\SystemOne\SystemOneManager;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        $this->app->resolving('systemone', function (SystemOneManager $manager, $app) {
            $manager->extend('ollama', function ($app) {
                return new OllamaDriver(
                    baseUrl: config('services.ollama.url', 'http://127.0.0.1:11434'),
                    model: config('services.ollama.model', 'llama3')
                );
            });
        });
    }
}

Approach B: Service Container Binding

The SystemOneManager will automatically look for container bindings with the prefix systemone.driver.{name}:

$this->app->singleton('systemone.driver.ollama', function ($app) {
    return new OllamaDriver();
});

Step-by-Step: Building an Ollama Driver

Here is a complete, working example of an on-premise driver connecting SystemOne to a local Ollama daemon:

flowchart LR
    Req["DecisionRequest<br/>(State + Primitives)"] --> Payload["Extract payload &amp; targetModel<br/>Enforce strict JSON schema in prompt"]
    Payload --> HTTP["HTTP POST /api/generate<br/>format: 'json', stream: false"]
    HTTP --> Daemon["Ollama Local Daemon<br/>(e.g. llama3.2:3b)"]
    Daemon --> Res["Raw Response JSON<br/>answers: { ... }"]
    Res --> Resp["new DecisionResponse(answers, raw)"]
namespace App\Services\SystemOne;

use Illuminate\Support\Facades\Http;
use InvalidArgumentException;
use Obelaw\SystemOne\Contracts\DecisionResponseInterface;
use Obelaw\SystemOne\Contracts\DriverInterface;
use Obelaw\SystemOne\DecisionRequest;
use Obelaw\SystemOne\DecisionResponse;

class OllamaDriver implements DriverInterface
{
    public function __construct(
        protected string $baseUrl = 'http://127.0.0.1:11434',
        protected string $model = 'llama3.2:3b'
    ) {
    }

    public function decide(DecisionRequest $request): DecisionResponseInterface
    {
        $payload = $request->toPayload();
        $targetModel = $request->getModel() ?? $this->model;

        // Build prompt enforcing strict JSON output
        $systemPrompt = "You are a deterministic decision engine. "
            . "Evaluate the given state and answer each registered question strictly matching the requested primitive type. "
            . "Output JSON with key 'answers' mapping each question key to: "
            . "{ value: <float|string|number>, confidence: <float 0-1>, probabilities?: <object> }.";

        $httpResponse = Http::timeout(60)
            ->post("{$this->baseUrl}/api/generate", [
                'model' => $targetModel,
                'system' => $systemPrompt,
                'prompt' => json_encode($payload, JSON_PRETTY_PRINT),
                'stream' => false,
                'format' => 'json',
            ]);

        if ($httpResponse->failed()) {
            throw new InvalidArgumentException("Ollama request failed: " . $httpResponse->body());
        }

        $decoded = json_decode($httpResponse->json('response', '{}'), true);
        $answers = $decoded['answers'] ?? [];

        return new DecisionResponse($answers, $httpResponse->json());
    }

    public function run(DecisionRequest $request): DecisionResponseInterface
    {
        return $this->decide($request);
    }
}

Using Your Custom Driver

Once registered, you can invoke your driver by name:

use Obelaw\SystemOne\Facades\SystemOne;
use Obelaw\SystemOne\Primitives\Noul;

$response = SystemOne::state('Disk space utilization is 96% on primary database node.')
    ->driver('ollama')
    ->ask('escalate', Noul::make('Should an on-call engineer be paged immediately?'))
    ->run();

if ($response->isPositive('escalate')) {
    PagerDuty::triggerIncident();
}

Or pass a direct driver instance directly into run():

$driverInstance = new OllamaDriver(baseUrl: 'http://internal-ai.lan:11434');

$response = SystemOne::state($serverState)
    ->ask('is_healthy', Noul::make('Is database operational?'))
    ->run($driverInstance);

Next Steps

Our Premium Sponsors

Obelaw is proudly open-source. Continued development, bug fixes, and community support are made possible by the generosity of our sponsors.

Sponsor Obelaw