Neuron AI V4.0: Workflow Refactor, Streaming Overhaul & Breaking Changes for PHP AI Agents

Neuron AI V4.0 introduces a major workflow refactor, breaking changes to Agent streaming and tool approval, removes WorkflowHandler, adds AG-UI events and streaming channels, and provides an AI-assisted upgrade guide for PHP developers building AI agents.

Open Source Tech Hub
Open Source Tech Hub
Open Source Tech Hub
Neuron AI V4.0: Workflow Refactor, Streaming Overhaul & Breaking Changes for PHP AI Agents

Upgrade Overview: From V3 to V4

Neuron AI V4.0 focuses on refactoring the core foundation — the Workflow system — while minimizing disruptive changes to the public API. The release addresses key issues from V3 (e.g., tool approval flow in Agents) and improves architectural design to reduce future breaking changes. Developers using Tool Approval, Interruption, or Streaming Adapters are strongly encouraged to use AI coding agents (Codex, Claude Code) with the official upgrade guide located at vendor/neuron-core/neuron-ai/upgrade.

Dependency Updates

Update the core dependency in composer.json:

{
  "require": {
    "neuron-core/neuron-ai": "^4.0"
  }
}

Removed Default Dependency

inspector-php

is no longer a default dependency. To connect Agents to Inspector monitoring and APM, manually require:

composer require inspector-apm/inspector-php

High-Impact Changes

1. New Agentic Skills for AI Coding Agents

Skills for AI coding agents have been completely rewritten to reflect V4 features. Delete old skill directories (e.g., .claude, .agent) and reconfigure using the official installation guide.

2. Agent Return Type & Streaming Refactor

Agent entities underwent major refactoring to align with Workflow usability:

Return type change : Agents now return AgentState instances (extends WorkflowState with helper methods for backward compatibility).

stream() method overhaul : Removed AgentHandler; stream() now directly returns a Generator.

Example usage:

foreach ($agent->stream(new UserMessage("Hello")) as $event) {
    if ($event instanceof TextChunk) {
        echo $event->content;
    }
}

Frontend streaming protocol adaptation : Register an adapter manually on the Agent instance:

$generator = MyAgent::make()
    ->setStreamAdapter(new AGUIAdapter('thread_id'))
    ->stream(new UserMessage("Hello"));
foreach ($generator as $event) {
    echo $event;
    ob_flush();
    flush();
}

Note: structured() and chat() invocation methods remain unchanged.

3. Tool Class Becomes Pure Abstract

Tool

is now abstract and cannot be instantiated directly; must be extended. Changes:

Removed abstract class constructor.

Tool name ( $name) and description ( $description) are defined as regular class properties; no need to call parent::__construct(). Only define a constructor when injecting external dependencies.

Example:

class MyTool extends Tool {
    protected string $name = 'my_tool';
    protected ?string $description = 'What the tool does.';

    public function __construct(protected string $apiKey) {}

    public function __invoke() {
        // tool business logic
    }
}

4. Complete Removal of WorkflowHandler

Workflow execution simplified: no longer need init() to get a WorkflowHandler. Call run() or events() directly on the workflow instance.

V3 (old):

$handler = MyWorkflow::make()->init();
// single run
$finalState = $handler->run();
// event stream
foreach ($handler->events() as $chunk) { /* ... */ }
$finalState = $handler->getResult();

V4 (new):

// single run
$finalState = MyWorkflow::make()->run();
// event stream
$generator = MyWorkflow::make()->events();
foreach ($generator as $chunk) { /* ... */ }
$finalState = $generator->getResult();

5. Workflow Interruption & Resumption Architecture Redesign

Redesigned interruption and resumption to enable durable, crash-proof production workflows.

▪ Removed WorkflowInterrupt Exception

Workflows no longer throw a special WorkflowException on interruption; they return a state object marked as interrupted. No try/catch needed:

$state = $workflow->run();
if ($state->isInterrupted()) {
    $request = $state->getInterruptRequest();
    $workflowId = $workflow->getWorkflowId();
}

▪ Resumption Payload Simplified to Plain Array

Interrupt requests from nodes are now signals. Resume by passing a plain array:

// Node triggers interruption
class InterruptableNode extends Node {
    public function __invoke(FirstEvent $event, WorkflowState $state): NextEvent {
        $payload = $this->interrupt(new ApprovalRequest('human input needed'));
        $state->set('received_feedback', $payload);
        return new NextEvent();
    }
}
// External resume: pass array directly
$payload = ['action_id' => 'approve'];
$finalState = $workflow->resume($payload);

6. Agent Instructions Strong Typing

Agent instructions must now be SystemMessage instances. Pass the prompt string to the constructor:

use NeuronAI\Chat\Messages\SystemMessage;
class YouTubeAgent extends Agent {
    protected function provider(): AIProviderInterface { /* ... */ }
    protected function instructions(): SystemMessage {
        return new SystemMessage(
            "You are an AI Agent specialized in writing YouTube video summaries"
        );
    }
}

7. Tool Approval Mechanism Fully Rewritten

Agent now manages the full tool approval flow; developers only handle frontend UI rendering (approve/reject buttons).

Pending approval tool state stored in the last ToolCallMessage of chat history.

Frontend renders chat history sequentially; when encountering a ToolCallMessage, check its approval status to show actions.

New requiresApproval() Dynamic Method

Tools can implement requiresApproval(array $inputs): bool to decide approval based on actual model-provided arguments:

class MyTool extends Tool {
    public function requiresApproval(array $inputs): bool {
        // e.g., only require approval when amount > 100
        return $inputs['amount'] > 100;
    }
}

Note: Requires ToolApproval middleware on the Agent. Middleware custom rules take precedence over the tool's own requiresApproval .

8. Workflow Persistence Database Schema Changes

Due to execution model refactor, persistence table structures changed. If persistence is enabled, run the official SQL migrations.

9. Removed Guzzle Hard Dependency, Switched to Native cURL

Before : Required guzzlehttp/guzzle as HTTP client.

Now : Built-in CurlHttpClient with zero external Composer dependencies; only needs PHP's ext-curl (enabled by default).

Note : If you explicitly pass a custom GuzzleHttpClient instance, manually run composer require guzzlehttp/guzzle.

10. Vector Store Native Filter Support

VectorStoreInterface

refactored to support native filtering; method names and signatures changed. Custom vector store implementations must update signatures.

11. Calculator Toolkit Refactor & Token Optimization

Previously, models poorly composed calls to add, subtract, multiply etc., wasting tokens. V4 consolidates into a single Evaluate tool: model outputs a full math expression, tool parses and returns result in one step, drastically reducing context and token usage.

12. Chat History & Storage Decoupling

Two goals: (1) separate message storage from session context window management; (2) simplify Neuron integration with business systems.

Removed ChatHistoryInterface, introduced MessageStoreInterface.

Archive only, never delete : Messages exceeding context window are marked archived (not physically deleted). LLM receives trimmed active context; database retains full history.

13. Middleware Method Signature Adjustment

Workflow engine supports transient Resources (tool sets, system instructions, chat history) not persisted during interruption. Middleware before and after now receive a $resources parameter:

interface WorkflowMiddleware {
    public function before(
        NodeInterface $node,
        Event $event,
        WorkflowState $state,
        WorkflowResources $resources // new
    ): void;
    public function after(
        NodeInterface $node,
        Event $result,
        WorkflowState $state,
        WorkflowResources $resources // new
    ): void;
}

14. ReaderInterface Contract Change

File reader interface replaced static getText() with instance method read() to support constructor dependency injection:

interface ReaderInterface {
    public function read(string $filePath): string;
}

Medium-Impact Changes

1. Monitoring & Event Dispatcher Migrating to PSR-14

Observability moving from native PHP \SplObserver to standard PSR-14 Event Dispatcher . Legacy observer interfaces and LogObserver retained but marked @deprecated, greatly improving integration with modern PHP frameworks.

2. AI Provider Unified ProviderResponse Return

Provider chat() and stream() now return ProviderResponse objects (not raw Message). Allows access to assistant message, raw HTTP response body ( body()), and headers ( headers()). Affects only code directly calling Providers outside Agent internals.

$response = $provider->chat(new UserMessage(...));
$response->message(); // assistant message
$response->body();    // raw response body
$response->headers(); // response headers

3. AIProviderInterface Tweaks

Removed redundant messageMapper() and toolPayloadMapper(); added getModel(). Custom Provider implementations must adapt.

New Features

1. AG-UI Custom Event Support

Native support for STEP_STARTED, STEP_FINISHED, ACTIVITY_SNAPSHOT, CUSTOM frontend events. Supports Vercel-spec transient data-* fragments so intermediate business info streams to frontend without polluting history context.

2. Streaming Channels (Breaking HTTP Limits)

Complex, long-running Agent chains often hit HTTP timeouts. V4 introduces Channels : stream Agent/Workflow output out of HTTP lifecycle directly to Pusher, WebSocket, Redis queues or other long-lived connection services, then push to frontend.

3. Automatic Event Fragmentation for Streaming

Real-time push services (Pusher, Laravel Reverb, Soketi) impose message size limits (e.g., 10KB–100KB). Neuron now auto-fragments large tool results or snapshots into sequential fragments. Companion front-end SDK: TypeScript NPM package @neuron-core/streaming handles out-of-order reassembly and stream restoration.

4. Cross-Session Semantic Long-Term Memory

Agents gain cross-session long-term memory via SemanticMemoryRetrieval component, automatically storing and retrieving user preferences, background info, and historical focus across multiple conversations.

5. Interruptible HTTP Client

When user clicks "Stop generating", the in-flight streaming transfer can be interrupted at network layer; already-generated text chunks are preserved and properly stored in chat history.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

AI AgentsWorkflowStreamingPHPBreaking ChangesVector StoreMigration GuideNeuron AITool ApprovalSemantic Memory
Open Source Tech Hub
Written by

Open Source Tech Hub

Sharing cutting-edge internet technologies and practical AI resources.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.