Skip to main content
Laravel applications use the Superwire\Laravel\Workflow fluent API to send workflows to the executor.

Install package

composer require superwire/superwire-laravel

Run a workflow from a file

use Superwire\Laravel\Workflow;

$result = Workflow::fromFile(resource_path('workflows/reply.wire'))
    ->inputs([
        'message' => 'Write a short welcome message.',
    ])
    ->secrets([
        'api_key' => config('services.openai.key'),
    ])
    ->run();

$output = $result->output;

Run a workflow from source

use Superwire\Laravel\Workflow;

$source = <<<'WIRE'
input {
    message: string
}

secrets {
    api_key: string
}

provider llm from openai {
    endpoint: "https://api.openai.com/v1"
    api_key: secrets.api_key
}

model fast from llm {
    id: "gpt-4.1-mini"
}

agent reply {
    model: model.fast
    instruction: "Reply to {{ input.message }}"

    output {
        message: string
    }
}

output {
    message: agent.reply.message
}
WIRE;

$result = Workflow::fromSource($source)
    ->inputs(['message' => 'Hello'])
    ->secrets(['api_key' => config('services.openai.key')])
    ->run();

Cache key

Use cacheKey() to opt into executor caching for a specific client-controlled scope. Reuse the same key to reuse matching cached agent outputs, or change the key to start a fresh cache scope.
$result = Workflow::fromFile(resource_path('workflows/reply.wire'))
    ->inputs(['message' => 'Hello'])
    ->secrets(['api_key' => config('services.openai.key')])
    ->cacheKey("tenant:{$tenantId}:conversation:{$conversationId}")
    ->run();

Stream workflow events

stream() yields ExecutorEvent instances.
use Superwire\Laravel\Workflow;

foreach (
    Workflow::fromFile(resource_path('workflows/reply.wire'))
        ->inputs(['message' => 'Hello'])
        ->secrets(['api_key' => config('services.openai.key')])
        ->stream() as $event
) {
    if ($event->output() !== null) {
        $partialOrFinalOutput = $event->output();
    }

    if ($event->isTerminal()) {
        break;
    }
}
streamToResult() consumes the stream and returns the final WorkflowResult.
$result = Workflow::fromFile(resource_path('workflows/reply.wire'))
    ->inputs(['message' => 'Hello'])
    ->secrets(['api_key' => config('services.openai.key')])
    ->streamToResult();

Event helpers

An ExecutorEvent exposes:
$event->kind;
$event->agentName;
$event->event;
$event->isTerminal();
$event->output();
$event->toArray();
Known event kinds include workflow started, workflow planned, agent started, agent completed, tool call started, tool call completed, tool call failed, MCP call started, MCP call completed, MCP call failed, workflow completed, and workflow failed.

Validate and format

$validation = Workflow::fromFile(resource_path('workflows/reply.wire'))
    ->secrets(['api_key' => config('services.openai.key')])
    ->validate();

$formatted = Workflow::fromFile(resource_path('workflows/reply.wire'))
    ->format();

Map output into a class

mapInto() maps the final output into a PHP class. If the class has a static from() method, it is used. Otherwise, array output is passed as named constructor arguments.
final readonly class ReplyOutput
{
    public function __construct(
        public string $message,
    ) {}
}

$result = Workflow::fromFile(resource_path('workflows/reply.wire'))
    ->inputs(['message' => 'Hello'])
    ->secrets(['api_key' => config('services.openai.key')])
    ->mapInto(ReplyOutput::class)
    ->run();

$output = $result->output;

Testing with fakes

use Superwire\Laravel\Workflow;

Workflow::fake([
    'message' => 'Fake workflow output.',
]);

$result = Workflow::fromFile(resource_path('workflows/reply.wire'))
    ->inputs(['message' => 'Hello'])
    ->secrets(['api_key' => 'test-key'])
    ->run();

Workflow::restoreFake();

Testing patterns

Validate workflow contracts in tests:
use Superwire\Laravel\Workflow;

$validation = Workflow::fromFile(resource_path('workflows/reply.wire'))
    ->secrets([
        'api_key' => config('services.openai.key'),
    ])
    ->validate();
Use fake execution for deterministic application tests:
use Superwire\Laravel\Workflow;

Workflow::fake([
    'message' => 'Hello from a fake workflow.',
]);

$result = Workflow::fromFile(resource_path('workflows/reply.wire'))
    ->inputs(['message' => 'Hello'])
    ->secrets(['api_key' => 'test-key'])
    ->run();

expect($result->output)->toBe([
    'message' => 'Hello from a fake workflow.',
]);

Workflow::restoreFake();
Test data guidance:
  • Keep test workflows small.
  • Use deterministic inputs.
  • Avoid live provider calls in unit tests.
  • Reserve end-to-end tests for the executor boundary.

API summary

Workflow::fromFile($path);
Workflow::fromSource($source);

$workflow->inputs([...]);
$workflow->secrets([...]);
$workflow->mapInto(SomeOutput::class);

$workflow->run();
$workflow->stream();
$workflow->streamToResult();
$workflow->validate();
$workflow->format();

Workflow::fake([...]);
Workflow::restoreFake();