PHP code example of pocketarc / ai-workflow

1. Go to this page and download the library: Download pocketarc/ai-workflow library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

pocketarc / ai-workflow example snippets


use AiWorkflow\Facades\Prompt;

$prompt = Prompt::load('support', [
    'customer_name' => 'Jane',
    'product' => 'Pro',
    'is_vip' => true,
]);

$prompt = Prompt::load('my_prompt');

use AiWorkflow\AiService;
use AiWorkflow\Facades\Prompt;
use AiWorkflow\Messages\UserMessage;

$aiService = app(AiService::class);

$response = $aiService->sendMessages(
    collect([new UserMessage('What is the weather like?')]),
    Prompt::load('chat'),
);

echo $response->text;

use AiWorkflow\Messages\Attachment;
use AiWorkflow\Messages\AttachmentKind;
use AiWorkflow\Messages\UserMessage;

new UserMessage('What does this invoice say?', [
    Attachment::fromPath(AttachmentKind::Document, storage_path('invoice.pdf'), title: 'Invoice'),
    Attachment::fromUrl(AttachmentKind::Image, 'https://example.com/receipt.jpg'),
    Attachment::fromBase64(AttachmentKind::Audio, $base64, 'audio/mpeg'),
    Attachment::text('Extra context, placed before the message text.'),
]);

use AiWorkflow\Schema\ResponseSchema;

$schema = new ResponseSchema('analysis', [
    'type' => 'object',
    'properties' => [
        'summary' => ['type' => 'string', 'description' => 'A brief summary'],
        'priority' => ['type' => 'number', 'description' => 'Priority from 1-5'],
    ],
    '

use AiWorkflow\Attributes\Description;
use Spatie\LaravelData\Data;

class SentimentAnalysis extends Data
{
    public function __construct(
        #[Description('The detected sentiment: positive, negative, or neutral')]
        public readonly string $sentiment,
        #[Description('Confidence score from 0.0 to 1.0')]
        public readonly float $confidence,
    ) {}
}

$result = $aiService->sendStructuredData(
    collect([new UserMessage('Analyze the sentiment of: "I love this product!"')]),
    Prompt::load('sentiment'),
    SentimentAnalysis::class,
);

// $result->data is a validated SentimentAnalysis instance
echo $result->data->sentiment;   // "positive"
echo $result->data->confidence;  // 0.95

$result->response;  // the structured response from the attempt that passed
$result->usage;     // token usage summed across every attempt

$stream = $aiService->streamMessages(
    collect([new UserMessage('Tell me a story')]),
    Prompt::load('chat'),
);

foreach ($stream as $event) {
    if ($event instanceof \AiWorkflow\Streaming\TextDelta) {
        echo $event->delta;
    }
}

$response = $aiService->sendMessages(
    $messages,
    Prompt::load('respond_to_customer'),
    extraContext: Prompt::load('shared_context'),
);

// In your AppServiceProvider::boot()
use AiWorkflow\AiService;
use AiWorkflow\Tools\Tool;

$aiService = app(AiService::class);

$aiService->resolveToolsUsing(fn (array $context) => [
    new Tool(
        'get_weather',
        'Get current weather conditions.',
        [
            'type' => 'object',
            'properties' => ['city' => ['type' => 'string', 'description' => 'The city name']],
            '

$aiService->setContext(['customer' => $customer]);
$response = $aiService->sendMessages($messages, $prompt);

$aiService->setTags(['billing', 'priority']);

use AiWorkflow\Models\AiWorkflowRequest;

AiWorkflowRequest::query()->withTag('classification')->get();
AiWorkflowRequest::query()->withAnyTag(['classification', 'intent'])->get();
AiWorkflowRequest::query()->byModel('claude-4')->successful()->get();
AiWorkflowRequest::query()->errors()->get();

Schedule::command('ai-workflow:prune')->daily();

'pruning' => [
    'requests_days' => 90,
    'chunk_size' => 1000,
],

$aiService->startExecution('work_ticket', ['ticket_id' => $ticket->id]);

$aiService->sendMessages($messages, Prompt::load('decide_action'));
$aiService->sendMessages($messages, Prompt::load('generate_response'));
$aiService->sendStructuredMessages($messages, Prompt::load('judge_response'), $schema);

$execution = $aiService->endExecution();
// All three calls are linked to this execution.

use AiWorkflow\Models\AiWorkflowExecution;

$execution = AiWorkflowExecution::query()->byName('work_ticket')->recent()->first();
$execution->totalInputTokens();
$execution->totalOutputTokens();
$execution->totalTokens();
$execution->totalDurationMs();
$execution->requestCount();

use AiWorkflow\Events\AiWorkflowRequestCompleted;
use AiWorkflow\Events\AiWorkflowRequestFailed;
use AiWorkflow\Listeners\SentryBreadcrumbListener;

protected $listen = [
    AiWorkflowRequestCompleted::class => [SentryBreadcrumbListener::class . '@handleCompleted'],
    AiWorkflowRequestFailed::class => [SentryBreadcrumbListener::class . '@handleFailed'],
];

// config/ai-workflow.php
'middleware' => [
    App\Middleware\LogRequestMetrics::class,
],

$aiService->addMiddleware(new App\Middleware\LogRequestMetrics());

use AiWorkflow\Middleware\AiWorkflowContext;
use AiWorkflow\Middleware\AiWorkflowMiddleware;

class LogRequestMetrics implements AiWorkflowMiddleware
{
    public function handle(AiWorkflowContext $context, Closure $next): AiWorkflowContext
    {
        // Before the AI request
        $start = microtime(true);

        $context = $next($context);

        // After the AI request
        logger()->info('AI request took ' . (microtime(true) - $start) . 's');

        return $context;
    }
}

use AiWorkflow\Middleware\InputGuardrail;
use AiWorkflow\Middleware\AiWorkflowContext;

class PiiDetectionGuardrail extends InputGuardrail
{
    protected function validate(AiWorkflowContext $context): void
    {
        // Throw GuardrailViolationException if PII is detected in messages
    }
}

use AiWorkflow\AiWorkflowReplayer;

$replayer = app(AiWorkflowReplayer::class);

// Replay exactly as recorded
$result = $replayer->replay($request);

// Replay with a different model
$result = $replayer->replay($request, model: 'anthropic:claude-4');

// Replay with the latest prompt from disk (uses the stored prompt_id to load)
$result = $replayer->replay($request, useCurrentPrompts: true);

// Both: latest prompt + different model
$result = $replayer->replay($request, useCurrentPrompts: true, model: 'anthropic:claude-4');

// Compare one request across multiple models
$results = $replayer->replayAcrossModels($request, [
    'openrouter:google/gemini-3-pro',
    'anthropic:claude-4',
    'openrouter:openai/gpt-5.2',
]);
// Returns array keyed by model name.

// Replay an entire execution — each request loads its own prompt via prompt_id
$results = $replayer->replayExecution($execution, useCurrentPrompts: true);

// In your action, group AI calls under an execution:
$aiService->startExecution('decide_action #42', ['ticket_id' => 42]);
$response = $aiService->sendStructuredMessages($messages, $prompt, $schema);
$execution = $aiService->endExecution();
// $execution->id is the UUID you'll reference

use AiWorkflow\Eval\AiWorkflowEvalJudge;
use AiWorkflow\Eval\AiWorkflowEvalResult;
use AiWorkflow\Models\AiWorkflowRequest;
use AiWorkflow\Responses\StructuredResponse;
use AiWorkflow\Responses\TextResponse;

class MyJudge implements AiWorkflowEvalJudge
{
    public function judge(AiWorkflowRequest $originalRequest, TextResponse|StructuredResponse $response): AiWorkflowEvalResult
    {
        // Compare the new response against the original recorded response
        // Return a score from 0.0 to 1.0
        return new AiWorkflowEvalResult(score: 0.9, details: ['reasoning' => '...']);
    }
}

use AiWorkflow\Eval\AiWorkflowEvalRunner;
use AiWorkflow\Models\AiWorkflowEvalDataset;

$runner = app(AiWorkflowEvalRunner::class);
$dataset = AiWorkflowEvalDataset::query()->where('name', 'decide-actions')->firstOrFail();

$evalRun = $runner->run(
    name: 'Decision eval',
    requests: $dataset->requests(),
    models: ['openrouter:anthropic/claude-4', 'openrouter:google/gemini-3-pro'],
    judge: app(MyJudge::class),
);

$evalRun->averageScore();                                    // overall
$evalRun->averageScoreForModel('openrouter:anthropic/claude-4'); // per model

use AiWorkflow\Testing\OpenRouterFake;

OpenRouterFake::respondWith(
    OpenRouterFake::toolCalls([['name' => 'get_weather', 'arguments' => ['city' => 'Lisbon']]]),
    OpenRouterFake::completion('It is sunny in Lisbon.', usage: OpenRouterFake::tokens(120, 30)),
);

// Your code that calls AiService receives these responses in order.

OpenRouterFake::sentBodies(); // the JSON bodies sent to OpenRouter, oldest first
bash
php artisan vendor:publish --tag=ai-workflow-config
bash
php artisan vendor:publish --tag=integrations-migrations
php artisan migrate
php artisan integrations:install openrouter --credential=api_key=YOUR_OPENROUTER_KEY
bash
php artisan vendor:publish --tag=ai-workflow-migrations
php artisan migrate