PHPackages                             cainydev/laragraph - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. cainydev/laragraph

ActiveLibrary

cainydev/laragraph
==================

Build stateful, multi-agent LLM workflows in Laravel. Adapts LangGraph’s cyclic graphs for PHP’s stateless architecture with built-in persistence.

v0.1.1(yesterday)00MITPHPPHP ^8.4CI passing

Since Mar 22Pushed todayCompare

[ Source](https://github.com/cainydev/laragraph)[ Packagist](https://packagist.org/packages/cainydev/laragraph)[ Docs](https://github.com/cainydev/laragraph)[ GitHub Sponsors](https://github.com/cainy)[ RSS](/packages/cainydev-laragraph/feed)WikiDiscussions main Synced today

READMEChangelogDependencies (16)Versions (3)Used By (0)

 [![LaraGraph](resources/images/laragraph_logo.svg)](resources/images/laragraph_logo.svg)LaraGraph
=========

[](#laragraph)

[![Latest Version on Packagist](https://camo.githubusercontent.com/5b00768b269594ef3afad7c73092818541a621a04b7ef3c3ca5e2b8f36c3d271/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6361696e796465762f6c61726167726170682e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/cainydev/laragraph)[![GitHub Tests Action Status](https://camo.githubusercontent.com/1c8484dd28b4f9dcc69d62e21b4fa0ea0ecd5385aefadf722fdb14e0d6f9bc03/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f6361696e796465762f6c61726167726170682f72756e2d74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/cainydev/laragraph/actions?query=workflow%3Arun-tests+branch%3Amain)[![Total Downloads](https://camo.githubusercontent.com/2b5eb8abc0dca59e2ff7d459b33ec16d11dad9907c8d543f23ff545ec729f806/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6361696e796465762f6c61726167726170682e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/cainydev/laragraph)

Stateful, graph-based workflow engine for Laravel.
Build multi-step agent pipelines, human-in-the-loop processes, and parallel fan-out/fan-in tasks — all backed by your database and queue.

Inspired by [LangGraph](https://github.com/langchain-ai/langgraph)

Table of Contents
-----------------

[](#table-of-contents)

- [Installation](#installation)
- [Core Concepts](#core-concepts)
- [Building a Workflow](#building-a-workflow)
    - [Nodes](#nodes)
    - [Transitions](#transitions)
    - [Conditional Edges](#conditional-edges)
    - [Branch Edges](#branch-edges)
    - [Fan-out / Fan-in](#fan-out--fan-in)
- [Running a Workflow](#running-a-workflow)
    - [Registering Workflows](#registering-workflows)
    - [Starting a Run](#starting-a-run)
    - [Starting from a Blueprint](#starting-from-a-blueprint)
- [State](#state)
    - [Reducers](#reducers)
    - [Custom Reducer](#custom-reducer)
- [Human-in-the-Loop](#human-in-the-loop)
    - [interrupt\_before](#interrupt_before)
    - [interrupt\_after](#interrupt_after)
    - [Resuming](#resuming)
    - [Dynamic Pause from a Node](#dynamic-pause-from-a-node)
- [Node Contracts](#node-contracts)
    - [HasName](#hasname)
    - [HasTags](#hastags)
    - [HasTimeout](#hastimeout)
    - [HasRetryPolicy](#hasretrypolicy)
- [Built-in Node Types](#built-in-node-types)
    - [FormatNode](#formatnode)
    - [HumanInterruptNode](#humaninterruptnode)
- [Prism Integration](#prism-integration)
    - [PrismNode](#prismnode)
    - [ToolNode](#toolnode)
    - [Automatic Tool Loops](#automatic-tool-loops)
    - [Manual Tool Routing](#manual-tool-routing)
- [Laravel AI Integration](#laravel-ai-integration)
    - [AsGraphNode Trait](#asgraphnode-trait)
    - [Structured Output](#structured-output)
    - [Tool-Using Agents](#tool-using-agents)
- [Sub-graph Workflows](#sub-graph-workflows)
- [Events](#events)
- [Configuration](#configuration)
- [Testing](#testing)

---

Installation
------------

[](#installation)

```
composer require cainy/laragraph
```

Publish and run the migration:

```
php artisan vendor:publish --tag="laragraph-migrations"
php artisan migrate
```

Publish the config file:

```
php artisan vendor:publish --tag="laragraph-config"
```

---

Core Concepts
-------------

[](#core-concepts)

LaraGraph models a workflow as a **directed graph** of nodes connected by edges. Each run of that graph is a `WorkflowRun` — a database record that tracks the current state, status, and active node pointers.

TermMeaning**Node**A unit of work. Receives the current state, returns a mutation.**Edge**A directed connection between two nodes, optionally conditional.**State**A plain PHP array that accumulates mutations as nodes execute.**Pointer**Tracks which nodes are currently in-flight for a run.**WorkflowRun**The persisted record for a single execution of a workflow.Execution is fully queue-driven. Each node runs as an independent `ExecuteNode` job, so parallel branches execute concurrently across your worker pool.

---

Building a Workflow
-------------------

[](#building-a-workflow)

### Nodes

[](#nodes)

A node is any class implementing `Cainy\Laragraph\Contracts\Node`:

```
use Cainy\Laragraph\Contracts\Node;
use Cainy\Laragraph\Engine\NodeExecutionContext;

class SummarizeNode implements Node
{
    public function handle(NodeExecutionContext $context, array $state): array
    {
        $text = implode("\n", $state['paragraphs'] ?? []);

        return ['summary' => substr($text, 0, 200)];
    }
}
```

`handle()` receives a typed `NodeExecutionContext` and the current full state. It returns an array of **mutations** — only the keys you want to change.

#### NodeExecutionContext

[](#nodeexecutioncontext)

The context object carries everything the node needs to know about its execution environment:

```
$context->runId          // int   — ID of the WorkflowRun
$context->workflowKey    // string — registered name or key of the workflow
$context->nodeName       // string — name of this node in the graph
$context->attempt        // int   — current queue attempt (1-based)
$context->maxAttempts    // int   — maximum attempts configured
$context->createdAt      // DateTimeImmutable
$context->isolatedPayload // ?array — payload from a Send fan-out (see below)
```

### Transitions

[](#transitions)

Build a workflow with the fluent `Workflow` builder:

```
use Cainy\Laragraph\Builder\Workflow;

$workflow = Workflow::create()
    ->addNode('fetch',     FetchNode::class)
    ->addNode('transform', TransformNode::class)
    ->addNode('store',     StoreNode::class)
    ->transition(Workflow::START, 'fetch')
    ->transition('fetch',     'transform')
    ->transition('transform', 'store')
    ->transition('store',     Workflow::END);
```

`Workflow::START` and `Workflow::END` are the reserved entry and exit pseudo-nodes.

Nodes can be registered as class strings (resolved via the container) or as pre-built instances.

### Conditional Edges

[](#conditional-edges)

Pass a condition as the third argument to `->transition()`. It can be a **Closure** or a **Symfony Expression Language string**:

```
// Closure
->transition('classify', 'approve', fn(array $state) => $state['score'] > 50)
->transition('classify', 'reject',  fn(array $state) => $state['score'] transition('classify', 'approve', "state['score'] > 50")
->transition('classify', 'reject',  "state['score']
