Executing Workflows
Executing Workflows in PHP
The Workflow Engine in tokomono/ai-suite executes step-by-step AI and PHP pipelines defined as a directed graph of nodes (steps) and edges (connections). Workflows can be built visually in the Workflows UI and are synchronized with PHP classes in app/Ai/Workflows.
Live Example Workflows on this Server: You can open, inspect, edit, and run these live workflows directly in the interactive editor:
- Claim Handler (
ClaimHandlerWorkflow) — Full end-to-end workflow combiningstart,php_code,if_else,statement,agent,human_in_the_loop, andresponse.- Enum Tester (
EnumTesterWorkflow) — Demonstrates structured routing withenum,enum_value, andresponsenodes usingJev.- LLM as a Judge (
LLMAsAJudgeWorkflow) — Chains multipleWorkerAgentnodes intoJudgeAgent, followed byenumrouting andphp_codefallback.
To run a workflow (such as ClaimHandlerWorkflow) from your application code (e.g., a Controller, Service, or Queue Job), use Tokomono\AiSuite\Workflows\Core\WorkflowEngine together with Tokomono\AiSuite\Workflows\Data\WorkflowContextDto.
1. Running Directly from the PHP Class
Fetch the workflow definition via getDefinition() on the workflow class and pass your initial variables into WorkflowContextDto:
use App\Ai\Workflows\ClaimHandlerWorkflow;
use Tokomono\AiSuite\Workflows\Core\WorkflowEngine;
use Tokomono\AiSuite\Workflows\Data\WorkflowContextDto;
// 1. Initialize the context with input variables
// Note: StartModule reads $context->globalVariables['question'] as the initial output by default
$context = new WorkflowContextDto(
globalVariables: [
'question' => 'My package arrived damaged.',
'order_id' => 12345,
],
clearConversation: false,
);
// 2. Resolve the workflow definition and run the engine
$workflow = app(ClaimHandlerWorkflow::class);
$engine = app(WorkflowEngine::class);
$engine->run($workflow->getDefinition(), $context);
// 3. Check for errors and read the output from the context
if ($context->error !== null) {
logger()->error('Workflow failed: ' . $context->error);
}
// Final output of the last executed step (as a string)
$finalAnswer = $context->getPreviousStepOutput()?->content;
// Structured array data of the last executed step (if any)
$finalData = $context->getPreviousStepOutput()?->data;
// Retrieve the output of a specific node by its node ID
$agentOutput = $context->getHistory('node_agent')?->content;
2. Running with Database Logging (WorkflowRun) and Published DB Version
If you want to execute the latest published version from the Workflow Editor and log the execution in the workflow_runs table:
use App\Ai\Workflows\ClaimHandlerWorkflow;
use Tokomono\AiSuite\Models\Workflow;
use Tokomono\AiSuite\Models\WorkflowRun;
use Tokomono\AiSuite\Workflows\Core\WorkflowEngine;
use Tokomono\AiSuite\Workflows\Data\WorkflowContextDto;
$workflowModel = Workflow::where('class_name', ClaimHandlerWorkflow::class)->firstOrFail();
// Use the published database definition, falling back to the PHP class definition
$definition = $workflowModel->activeVersion?->definition
?? app(ClaimHandlerWorkflow::class)->getDefinition();
$inputData = ['question' => 'My package arrived damaged.'];
$context = new WorkflowContextDto(
workflowRecord: $workflowModel,
globalVariables: $inputData,
clearConversation: false,
);
$run = WorkflowRun::create([
'workflow_id' => $workflowModel->id,
'is_test' => false,
'input_data' => $inputData,
'status' => 'running',
'started_at' => now(),
]);
try {
app(WorkflowEngine::class)->run($definition, $context);
$run->update([
'status' => $context->error ? 'failed' : 'completed',
'error_message' => $context->error,
'execution_log' => $context->steps,
'completed_at' => now(),
]);
} catch (\Throwable $e) {
$run->update([
'status' => 'failed',
'error_message' => $e->getMessage(),
'execution_log' => $context->steps,
'completed_at' => now(),
]);
}
Note for Queue Jobs / CLI: If your workflow includes an
AgentModuleand runs in a background job or CLI command where no user is authenticated, authenticate the target user first (auth()->login($user)) if the agent tracks conversation history per user.