定制 builtbyberry/laravel-swarm 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

builtbyberry/laravel-swarm

Composer 安装命令:

composer require builtbyberry/laravel-swarm

包简介

Multi-agent swarm orchestration for Laravel, built on Laravel AI.

README 文档

README

Laravel Swarm

Latest Version on Packagist Total Downloads Tests Nightly (Laravel dev-main) License PHP Version Require Documentation

📚 Full documentation: swarm.builtbyberry.com

Laravel Swarm brings reusable multi-agent orchestration to Laravel on top of the official Laravel AI package.

Define a swarm once, return the Laravel AI agents that participate in it, and run the workflow synchronously, on a queue, as a stream, or as a checkpointed durable run.

Contents

Quick Start

composer require builtbyberry/laravel-swarm
php artisan swarm:install
php artisan make:swarm:swarm ContentPipeline
use App\Ai\Swarms\ContentPipeline;

$response = ContentPipeline::make()->prompt('Draft a launch post about Laravel queues.');

echo $response->output;

For background execution, streaming, and durable workflows, see Choosing an Execution Mode.

Requirements

  • PHP ^8.5
  • Laravel 13 (illuminate/* ^13.0)
  • laravel/ai ^0.9

The PHP ^8.5 floor is a deliberate requirement — the package builds on 8.5 language features. As of v0.20.0 the laravel/ai floor is ^0.9; support for 0.8 was dropped (0.6 / 0.7 were dropped earlier, in v0.13.0). Consumers pinned below laravel/ai 0.9 must upgrade. See the changelog for what the 0.9 adoption changes.

This package declares "minimum-stability": "dev" with "prefer-stable": true because laravel/ai is still pre-1.0 and ships dev-tagged releases. Composer will not resolve a pre-stable transitive dependency from a stable consuming project, so your application's composer.json must also set:

{
    "minimum-stability": "dev",
    "prefer-stable": true
}

prefer-stable keeps Composer biased toward tagged releases — only dependencies without a stable release (today, laravel/ai) resolve to a dev- constraint. This requirement will be dropped when laravel/ai reaches 1.0; the package will then move to "minimum-stability": "stable" and consuming applications will be free to do the same.

Laravel Swarm orchestrates the same Laravel AI agents, providers, and streams as your application. Treat Composer updates to Laravel or laravel/ai as integration-test events: run your test suite and any queued, streamed, or durable swarm smoke paths after dependency changes. This package's changelog covers Swarm-owned changes; it does not replace verification against upstream Laravel or Laravel AI releases.

Installation

Require the package with Composer, then run the interactive installer:

composer require builtbyberry/laravel-swarm
php artisan swarm:install

Tagged releases are available on Packagist. Pin a tagged release for production applications.

swarm:install walks you through the full setup in one shot — it publishes config/swarm.php, seeds the canonical Swarm .env keys with safe defaults, runs the package migrations (or scaffolds LaravelSwarm::ignoreMigrations() for a cache-only deployment), warns when QUEUE_CONNECTION=sync, and offers to dispatch the targeted sub-installers in the same pass:

  • swarm:install:durable — scheduler entries (swarm:relay, swarm:recover, swarm:prune), persistence/queue checks, copy-paste worker snippets.
  • swarm:install:audit — bind a SwarmAuditSink (and optional SwarmAuditSigner / ActorResolver / CapturePolicy) inside AppServiceProvider.
  • swarm:install:memory — verify the memory tables (offering to run migrations if they are missing), then print the effective persistence driver and replay mode for the Swarm Memory subsystem.
  • swarm:install:examples — copy the runnable starter example pack into app/Ai/.

Pulse observability (recorders + dashboard cards) lives in a separate companion package as of v0.17.1 — see Pulse for the builtbyberry/laravel-swarm-pulse install steps.

For CI and scripted setups, every prompt has a flag override:

php artisan swarm:install \
    --no-interaction \
    --persistence=database \
    --with-durable --with-audit --with-memory --with-examples

Pass --without-<name> to skip a sub-installer in non-interactive mode, --persistence=cache for cache-only deployments, --skip-migrate to defer migrations, or --force to overwrite an existing config/swarm.php.

After the install, confirm everything wired up cleanly:

php artisan swarm:health
php artisan swarm:health --durable

--durable also verifies the database tables required by dispatchDurable() and coordinated multi-worker hierarchical queueing.

Read Getting Started for the full new-user walkthrough — installer flow, post-install verification, and running your first starter swarm in under five minutes.

Advanced setup (manual)

Prefer to wire things by hand? Every step swarm:install performs has a stable manual equivalent. See Advanced Setup for the full manual flow — config publish, migrations vs. ignoreMigrations(), scheduler entries, audit sink binding, and copying the starter examples by hand.

Your First Swarm

Generate a swarm class:

php artisan make:swarm:swarm ContentPipeline

Or scaffold a complete, runnable swarm from a curated blueprint — the swarm, its agents, and a console command, renamed as your own:

php artisan make:swarm:blueprint SupportTriage --template=triage

See Generators for the full generator surface, including make:swarm:blueprint and its catalog, make:swarm:agent, and the --topology flag.

Swarms live in App\Ai\Swarms, implement BuiltByBerry\LaravelSwarm\Contracts\Swarm, use the Runnable trait, and return their participating Laravel AI agents from agents():

<?php

namespace App\Ai\Swarms;

use App\Ai\Agents\ArticleEditor;
use App\Ai\Agents\ArticlePlanner;
use App\Ai\Agents\ArticleWriter;
use BuiltByBerry\LaravelSwarm\Attributes\Topology;
use BuiltByBerry\LaravelSwarm\Concerns\Runnable;
use BuiltByBerry\LaravelSwarm\Contracts\Swarm;
use BuiltByBerry\LaravelSwarm\Enums\Topology as TopologyEnum;

#[Topology(TopologyEnum::Sequential)]
class ContentPipeline implements Swarm
{
    use Runnable;

    public function agents(): array
    {
        return [
            new ArticlePlanner,
            new ArticleWriter,
            new ArticleEditor,
        ];
    }
}

In a sequential swarm, the first agent receives the original task. Each later agent receives the previous agent's output.

Running a Swarm

Use prompt() when the caller can wait for the full workflow result:

use App\Ai\Swarms\ContentPipeline;

$response = ContentPipeline::make()->prompt('Draft a launch post about Laravel queues.');

$response->output;
$response->steps;
$response->usage;
$response->artifacts;
$response->metadata;

Structured task input is supported:

$response = ContentPipeline::make()->prompt([
    'topic' => 'Laravel queues',
    'audience' => 'intermediate developers',
    'goal' => 'launch post',
]);

run() remains available as a compatibility alias for prompt().

SwarmResponse casts to a string for simple use cases and implements toArray() / JsonSerializable for JSON responses:

return response()->json($response);

toArray() intentionally omits the live RunContext so an API response does not accidentally re-emit prompt or input data. Read $response->context directly when your application needs the in-process context.

Choosing an Execution Mode

Method Returns Use when
prompt() SwarmResponse The request can wait for the full result.
run() SwarmResponse Existing code still calls the compatibility alias.
queue() QueuedSwarmResponse One background job can own the workflow.
stream() StreamableSwarmResponse A sequential workflow should emit live progress or token events.
broadcast() / broadcastNow() StreamableSwarmResponse A sequential workflow should stream and broadcast typed events immediately.
broadcastOnQueue() QueuedSwarmResponse A worker should stream and broadcast typed events.
dispatchDurable() DurableSwarmResponse The workflow needs checkpointing, recovery, operator controls, or branch jobs.

Guardrails (input, per-step, final output policy checks) run across these modes at fixed orchestration boundaries; see docs/guardrails.md.

queue() and dispatchDurable() return dispatch handles with a runId. Listen for lifecycle events or inspect persisted history for eventual results.

stream() and the broadcast helpers support sequential swarms only. Use lifecycle events and application-owned broadcasts for queued, durable, parallel, or hierarchical operations feeds.

Queueing a Swarm

Use queue() when the workflow should run in the background:

use App\Ai\Swarms\ContentPipeline;

$response = ContentPipeline::make()
    ->queue([
        'topic' => 'Laravel queues',
        'audience' => 'intermediate developers',
    ])
    ->onConnection('redis')
    ->onQueue('ai');

$response->runId;

Queued swarms are re-resolved from Laravel's container on the worker. Keep swarm definitions stateless across the queue boundary, and pass per-run data in the task payload:

// Do this.
ContentPipeline::make()->queue(['draft_id' => $draft->id]);

// Do not rely on runtime constructor state crossing the queue boundary.
(new ContentPipeline($draft->id))->queue('Review the draft');

Queued and durable task payloads should use plain data: strings, integers, floats, booleans, null, and arrays containing only those values. Do not pass models, closures, resources, or runtime service objects.

With the shipped conservative defaults, queued and durable swarms require active context capture:

SWARM_CAPTURE_ACTIVE_CONTEXT=true

You may still leave input, output, and artifact capture disabled for redacted history.

Streaming a Swarm

Use stream() when a browser, CLI, or custom consumer needs live typed events from a sequential swarm:

foreach (ContentPipeline::make()->stream(['topic' => 'Laravel queues']) as $event) {
    if ($event->type() === 'swarm_text_delta') {
        // $event->delta
    }
}

Return the response directly from a route for Laravel AI-style SSE output:

return ContentPipeline::make()->stream([
    'topic' => 'Laravel queues',
]);

Broadcast the same typed stream events through Laravel broadcasting:

use Illuminate\Broadcasting\PrivateChannel;

ContentPipeline::make()->broadcast(
    ['topic' => 'Laravel queues'],
    new PrivateChannel('swarm.content-pipeline'),
);

ContentPipeline::make()->broadcastNow(
    ['topic' => 'Laravel queues'],
    new PrivateChannel('swarm.content-pipeline'),
);

ContentPipeline::make()
    ->broadcastOnQueue(
        ['topic' => 'Laravel queues'],
        new PrivateChannel('swarm.content-pipeline'),
    )
    ->onQueue('ai-streams');

Persisted stream replay is opt in:

$stream = ContentPipeline::make()
    ->stream(['topic' => 'Laravel queues'])
    ->storeForReplay();

Replay later with SwarmHistory::replay($runId). See Streaming for event schemas, replay behavior, capture, limits, and failure handling.

Crash-replay resume (v0.12.0)

A streamed run that is abandoned mid-stream — a worker crash, a dropped connection, an early break — can be resumed by re-running the same swarm with the same run id:

$runId = (string) Str::uuid();

ArticlePipeline::make()->stream(RunContext::from($task, $runId)); // abandoned mid-stream

// Resume on a fresh worker: same run id picks up where it left off.
return ArticlePipeline::make()->stream(RunContext::from($task, $runId));

On resume, already-completed non-final steps are skipped (their providers are not re-invoked and tool side effects do not re-fire — their output is rehydrated from a per-step checkpoint), and the terminal streamed step replays byte-identically from its frozen memory snapshot. Governed by the memory replay mode (frozen_view default; fresh_execution opts out) and the database persistence driver. See Streaming — Crash-Replay Durability.

Tool calls (including MCP tools) (v0.13.0)

Swarm carries laravel/ai ToolCall / ToolResult objects through the stream and the durable snapshot as opaque passthrough, so the MCP client/server tools added in laravel/ai 0.8 flow through with no MCP-specific configuration — including structured (non-scalar) MCP results, preserved intact. A tool value JSON cannot represent degrades to a typed placeholder at the tool boundary rather than crashing the run. See Streaming — Tool calls (including MCP tools).

Streaming dynamic swarms & the causal-log substrate (v0.15.0)

stream() now streams dynamic Hierarchical swarms — the coordinator runs synchronously, then its workers stream as the plan is walked. Underneath, the streamed event log is an append-only causal log: nothing is mutated or deleted in place, course-corrections are typed void-edges, and any shape a reader wants (clean vs. forensic, causal vs. presentation order) is a read-time fold via CausalLogView. A background compactor graduates sealed history to a cold tier so the hot log stays bounded, and authors can bound their own context with 'type' => 'rollup' plan nodes and a declarative #[ContextGrowthPolicy].

  • Authors: Streaming Substrate Author Guide — dynamic streaming, the causal-log fold, rollup nodes, the context-growth policy.
  • Operators: Streaming Substrate Operator Runbook — hot/cold tiering, scheduling swarm:compact, retention, recovery and quarantine.
  • Driver authors (v0.17.1): CausalLogStore and ColdArchiveDriver are now public contracts for a custom persistence backend's read/query seam. See the Streaming Substrate Driver Guide for exactly what's pluggable today (hot/cold read stitching, causal-log resolution) and what isn't yet (compaction, #[DurableStreaming] per-node streaming).

Durable Execution

Use dispatchDurable() when the workflow is too important or too long-lived for one queue job:

$response = ContentPipeline::make()
    ->dispatchDurable([
        'topic' => 'Laravel queues',
        'audience' => 'intermediate developers',
    ])
    ->onQueue('swarm-durable');

$response->runId;

Durable execution requires database-backed swarm persistence and advances the workflow through checkpointed jobs. Sequential durable swarms run one agent per job. Parallel durable swarms and hierarchical parallel groups use independent branch jobs and join before continuing.

Durable responses also expose operator helpers:

$response->inspect();
$response->pause();
$response->resume();
$response->cancel();
$response->signal('approval_received', ['approved' => true], idempotencyKey: 'approval-123');

Schedule the relay, recovery, and pruning for durable execution:

use Illuminate\Support\Facades\Schedule;

Schedule::command('swarm:relay')->everyMinute();   // required: drains the outbox after each checkpoint
Schedule::command('swarm:recover')->everyMinute(); // safety net: redispatches stranded runs
Schedule::command('swarm:prune')->daily();         // retention: removes expired persistence rows

Start with Durable Execution, then use the topic guides for waits and signals, retries and progress, child swarms, and webhooks.

Durable per-node streaming (v0.15.0)

A durable run can stream each node's events into the causal log as it executes, instead of producing one blocking prompt() response per node — so operators get a live, replay-safe signal from a durable run. Opt a swarm in with the #[DurableStreaming] attribute (off by default); the decision is pinned onto the run row at start, so a redeploy never changes an in-flight run.

use BuiltByBerry\LaravelSwarm\Attributes\DurableStreaming;
use BuiltByBerry\LaravelSwarm\Concerns\Runnable;
use BuiltByBerry\LaravelSwarm\Contracts\Swarm;

#[DurableStreaming]
final class ClaimsReview implements Swarm
{
    use Runnable;

    // agents() …
}

It streams on every durable topology — sequential, hierarchical, static_hierarchical, and parallel (including fan-out branches) — with each node's attempt voided-and-retried cleanly on crash-resume (the same append-only causal-log fold the live substrate uses). The hierarchical coordinator streams structural events; token-streaming the coordinator is a follow-up. Declaring the attribute on a topology not yet wired for streaming fails loud at dispatch. An operator kill-switch (SWARM_DURABLE_STREAMING_ENABLED=false) pauses emission fleet-wide without a redeploy, safely mid-run. See Durable Execution — per-node streaming.

Operator control contract (v0.16.0)

Pause, resume, cancel, signal, and recover durable runs through the stable public SwarmOperator contract — resolve it from the container to drive runs from an operator console, HTTP controller, or approval workflow, without reaching into package internals:

use BuiltByBerry\LaravelSwarm\Contracts\SwarmOperator;

$operator = app(SwarmOperator::class);

$result = $operator->pause($runId);
$result->status;         // DurableLifecycleStatus::Paused | ::PauseScheduled
$result->isImmediate();  // false when a mid-step run pauses at its next checkpoint

The control verbs return rich result objects (DurablePauseResult / DurableResumeResult / DurableCancelResult, backed by the DurableLifecycleStatus enum) that report the effective transition — whether the run paused/cancelled immediately or is scheduled to at its next step boundary. The contract is control-only (operational reads stay on SwarmHistory / RunHistoryStore), authorization-agnostic (gate the call in your own app), and fails loud on an unknown run. The $response->pause() / resume() / cancel() handle methods shown above delegate to it. See Durable Execution — operator control contract.

Read-only inspection contracts (v0.19.0)

The read-only counterpart to SwarmOperator, for companion packages and external readers (a Filament panel, an MCP server, a dashboard) that need to display run data. Resolve the contract instead of reaching into the @internal cipher or manager:

use BuiltByBerry\LaravelSwarm\Contracts\InspectsDurableRuns;

app(InspectsDurableRuns::class)->inspect($runId); // display-decrypted DurableRunDetail

Three seams ship: InspectsDurableRuns (durable run, branches, child runs, hierarchical node outputs), ReadableRunHistoryStore (run + step detail and the runs list), and ReadableAuditOutbox (non-mutating outbox-health reads). Every sealed field is display-decrypted per row — it honors swarm.persistence.decrypt_failure_policy and degrades an undecryptable field to null with an *_available: false flag rather than throwing or leaking ciphertext, so one bad row never 500s a page. The operational reads (RunHistoryStore::find, AuditOutbox::drain, durable resume) are untouched and still fail loud. See Public Surface — read-only inspection contracts.

Memory (v0.9.0+)

Swarm Memory is a first-class, scoped, snapshot-replayable memory subsystem. It gives agents and application code a place to read and write structured values that persist across steps, survive queue boundaries, and can be replayed deterministically from a frozen snapshot on a crash-resume.

use BuiltByBerry\LaravelSwarm\Contracts\SwarmMemory;
use BuiltByBerry\LaravelSwarm\Enums\MemoryScope;

$memory = app(SwarmMemory::class);
$memory->put(MemoryScope::Run, $runId, 'draft_approved', true);
$approved = $memory->get(MemoryScope::Run, $runId, 'draft_approved');

RunContext writes through to MemoryScope::Run automatically via its ArrayAccess interface — $context['key'] = $value mirrors to memory without any code change.

Propagation, redaction, and an operator surface (v0.10.0+). Memory now ships the controls a regulated workload needs:

  • MemoryPropagationPolicy decides which memory entries a worker agent sees at invocation (default: the Run-scoped view, byte-identical to v0.9).
  • MemoryCapturePolicy redacts or drops entries at the write boundary, so PII never reaches a snapshot (default: a no-op).
  • Operator CLIswarm:memory:inspect (view a run's frozen snapshots), swarm:memory:dump (export the full memory + snapshot trail for an audit packet / DSAR), and swarm:memory:purge (enforce per-scope retention windows).

See Swarm Memory for the full reference: scope hierarchy, store drivers, lifecycle events, propagation and capture policies, snapshot inspection, replay semantics (frozen_view vs fresh_execution), and the #[MemoryReplay] / #[PropagationPolicy] attributes; and Compliance & Audit for the regulated-workload runbook (redaction, retention, audit-packet export). Vector-backed recall ships as the laravel-swarm-memory-vector companion package.

Agent memory tools (v0.11.0+). Agents can now read and write memory mid-prompt as ordinary laravel/ai tools — drop the shipped Recall and Remember tools into any agent's tools() array (or expose them via the HasSwarmMemoryTools trait). Scope ids resolve from the active run, never the model; reads honour the propagation policy and writes honour the capture policy, so the tools can never surface or persist anything the policies forbid. They are disabled by default (swarm.memory.tools.enabled) — granting an LLM access to shared memory is an explicit decision. Scaffold custom variants with php artisan make:memory-tool. See the memory recipes for worked patterns: per-user and tenant-scoped recall, policy-enforced custom tools, recall + redact, and sub-agent memory continuity.

Topologies

Laravel Swarm supports four topologies.

Sequential

Agents run in order. Each agent receives the previous agent's output.

#[Topology(TopologyEnum::Sequential)]
class ContentPipeline implements Swarm
{
    use Runnable;

    public function agents(): array
    {
        return [new Planner, new Writer, new Editor];
    }
}

Parallel

Agents run concurrently and each receives the original task.

Parallel agents must be stateless and container-resolvable by class because Laravel concurrency resolves them inside worker processes.

#[Topology(TopologyEnum::Parallel)]
class ResearchSwarm implements Swarm
{
    use Runnable;

    public function agents(): array
    {
        return [new MarketResearcher, new CompetitorResearcher, new SeoResearcher];
    }
}

Hierarchical

The first agent is the coordinator. It returns a Laravel AI structured output route plan. Laravel Swarm validates the plan as a DAG and executes selected worker, parallel, and finish nodes.

#[Topology(TopologyEnum::Hierarchical)]
class SupportRoutingSwarm implements Swarm
{
    use Runnable;

    public function agents(): array
    {
        return [
            new SupportCoordinator,
            new PolicyAgent,
            new DraftAgent,
        ];
    }
}

Read Hierarchical Routing for the route plan schema, validation rules, queue behavior, and durable branch coordination.

Static Hierarchical

The route plan is defined in PHP — no coordinator LLM call runs at runtime. Use it when the graph of agents is always the same and only the content changes.

#[Topology(TopologyEnum::StaticHierarchical)]
class ContentSwarm implements HasRoutePlan, Swarm
{
    use Runnable;

    public function agents(): array
    {
        return [new Researcher, new Writer, new Editor];
    }

    public function plan(): array
    {
        return [
            'start_at' => 'finish',
            'nodes' => [
                'finish' => ['type' => 'finish', 'output' => ''],
            ],
        ];
    }
}

Read Static Hierarchical Topology for the plan schema, streaming modes, step budgets, and execution mode support.

Testing

Use fake() to intercept swarm execution in application tests:

use App\Ai\Swarms\ContentPipeline;

ContentPipeline::fake(['first response']);

expect((string) ContentPipeline::make()->prompt('Draft an intro'))->toBe('first response');

ContentPipeline::assertPrompted('Draft an intro');
ContentPipeline::assertNeverQueued();

Fakes cover prompt, queue, stream, broadcast, and durable dispatch intent:

ContentPipeline::assertQueued(['draft_id' => 42]);
ContentPipeline::assertStreamed('Draft an intro');
ContentPipeline::assertDispatchedDurably(['document_id' => 100]);

Use database-backed feature tests when you need to prove durable leases, checkpoints, retries, branch joins, wait release, recovery, or webhook idempotency. SwarmFake records intent; it does not execute the durable runtime.

To assert that swarm lifecycle events (started, step, completed, failed, …) fired during a real run, add the InteractsWithSwarmEvents trait to your test case and call assertEventFired() (v0.15.1+):

use BuiltByBerry\LaravelSwarm\Testing\InteractsWithSwarmEvents;

class ContentPipelineTest extends TestCase
{
    use InteractsWithSwarmEvents;
}

ContentPipeline::make()->run('Draft an intro');
ContentPipeline::assertEventFired(SwarmCompleted::class);

See Testing and Testing Swarms.

Configuration

Laravel Swarm stores defaults in config/swarm.php.

Settings are grouped by concern:

  • Coreswarm.topology, swarm.timeout, swarm.max_agent_steps
  • Persistence & historyswarm.persistence.*, swarm.capture.*, swarm.retention.*, swarm.history.*
  • Execution modesswarm.queue.*, swarm.durable.*, swarm.streaming.*
  • Memory & contextswarm.memory.*, swarm.context.*, swarm.context_growth.*, swarm.compaction.*
  • Topology plansswarm.hierarchical.*, swarm.static_hierarchical.*
  • Governance & observabilityswarm.guardrails.*, swarm.audit.*, swarm.observability.*, swarm.artifacts.*, swarm.limits.*

Capture defaults are conservative. Prompts, outputs, automatic step artifacts, and rich active-context snapshots are not persisted unless you opt in. When the global persistence driver or a per-store override uses database, swarm.persistence.encrypt_at_rest defaults to true and seals designated sensitive string columns with Laravel's encrypter.

Use Persistence And History, Maintenance, Observability: Logging And Tracing, and Audit Evidence Contract before enabling production capture, audit, or retention policies.

Production Checklist

  • Choose prompt(), queue(), stream(), or dispatchDurable() intentionally.
  • Use database persistence for durable execution, long-lived history, active-run pruning protection, or operational dashboards.
  • Set SWARM_CAPTURE_ACTIVE_CONTEXT=true for queued and durable swarms.
  • Size queue worker timeouts and queue retry_after above the longest expected provider call.
  • Schedule swarm:relay every minute for durable execution AND for the v0.5 audit outbox. The relay drains the durable outbox after each checkpoint and replays failed audit records through the bound sink — a single schedule covers both lanes. Without it, durable runs stall after the first step and queued audit failures accumulate without retry. Use swarm:relay --type=audit to drain only the audit lane during focused recovery. See Durable Execution and Audit Evidence Contract for the full relay reference.
  • Run php artisan migrate on database persistence to create swarm_audit_outbox — required for the v0.5 default SWARM_AUDIT_FAILURE_POLICY=queue (sink failures persist for retry instead of being silently dropped). Cache persistence detects the missing outbox and falls back to log-and-swallow automatically.
  • Schedule swarm:recover every five minutes for durable execution and coordinated multi-worker hierarchical queueing. Recovery redispatches runs whose workers died between checkpoint and dispatch. See Maintenance.
  • Schedule swarm:prune daily for database retention cleanup, or set SWARM_PREVENT_PRUNE=true when retention is managed outside the package.
  • Streaming crash-replay (v0.12.0): php artisan migrate creates swarm_stream_step_checkpoints, which records each completed non-final streamed step's raw output + usage so an abandoned stream() run resumes idempotently (no provider re-invoke, no side-effect re-fire). It is operational resume state, encrypted at rest by default under the database driver (swarm.persistence.encrypt_at_rest), and pruned with the run — early-pruned alongside snapshots by swarm:memory:purge (--keep-snapshots retains both) and cascade-deleted via the swarm_run_histories foreign key as the swarm:prune backstop. See Streaming — Crash-Replay Durability.
  • Rotate APP_KEY carefully (v0.12.1): when encrypt_at_rest is on, durable operational resume state is sealed with the active APP_KEY. Rotating the key without re-keying the stored rows now makes durable resume fail loud with a clear SwarmException ("…verify APP_KEY…") instead of silently resuming from a wrong/empty prompt — re-point APP_KEY to the key that sealed the rows and re-dispatch the affected runs. See Upgrading to v0.12.1.
  • Treat operational swarm tables as TTL-based runtime storage, not immutable compliance archives.
  • Bind SwarmAuditSink for regulated evidence export.
  • Bind SwarmTelemetrySink for logs, metrics, or tracing correlation.
  • Avoid secrets in metadata. Capture redaction does not sanitize arbitrary developer-supplied metadata. Set SWARM_MAX_METADATA_BYTES to enforce a hard size cap.
  • Build run inspection around run_id, lifecycle events, SwarmHistory, and durable runtime state.
  • Bookmark the Operator Runbook: Audit Outbox Triage before going live. It is the 3 a.m. decision tree for dead-letter rows, stale pending rows, and sink outages — and it assumes the reader has not just re-read the reference docs.
  • Use php artisan swarm:trace <run_id> (v0.7+) to reconstruct a single run's audit chain across run history, the audit outbox, and the bound sink. Read-only, on-demand, with --json for monitoring and --include-payloads for full envelopes. See Audit Evidence Contract, including the Security and retention subsection covering how the command unseals encrypted-at-rest data on output.

Audit Extension Points

Regulated deployments can replace four audit contracts in the container:

  • ActorResolver — resolves the human or system actor recorded on each evidence envelope.
  • CapturePolicy — decides which run fields are captured, redacted, or omitted before evidence is emitted.
  • SinkFailureHandler — handles SwarmAuditSink write failures (log, retry, halt, or escalate).
  • SwarmAuditSigner — produces the cryptographic signature attached to each envelope for tamper-evident export.

One optional extension contract (v0.7+):

  • ReadableSwarmAuditSink — extends SwarmAuditSink with forRun(string $runId): iterable<array> so the sink can participate in swarm:trace. Opt-in; the shipped NoOpSwarmAuditSink does not implement it and existing custom sinks remain valid.

Two environment knobs control strict-mode behavior:

  • SWARM_AUDIT_ACTOR_REQUIRED=true — fail closed when no actor can be resolved for a run.
  • SWARM_AUDIT_FAILURE_POLICY=halt — halt run progression when the audit sink rejects an envelope.

The full SWARM_AUDIT_FAILURE_POLICY matrix (since v0.5): swallow (drop silently — v0.4 default), log (log and continue), queue (persist to swarm_audit_outbox for retry — v0.5 default), dead_letter (persist directly to dead-letter status, no retry), halt (fail the run). The audit outbox is monitored by default via swarm:health (or swarm:health --audit for focused investigation).

Audit-path exception messages are redacted to [redacted] by default since v0.14.0 (SWARM_AUDIT_REDACT_EXCEPTION_MESSAGES=true) unless capture already permits failure free-text; the exception class/type is always logged, so failures stay diagnosable.

See Audit Evidence Contract for the full reference. When responding to an audit-outbox page, see the Operator Runbook: Audit Outbox Triage.

Documentation

The full documentation site is at swarm.builtbyberry.com — searchable, versioned, and the recommended starting point.

The same content is mirrored in this repository; the in-repo documentation index is the complete, categorized map when working offline. A few common entry points:

For the full set — topologies, guardrails, the durable subsystems, observability, operator runbooks, and examples — see the documentation index.

Companion Packages

Laravel Swarm is a small core with a growing family of companion packages — additive, MIT, and installed only when you need them. Each reads and extends the core through its public contracts and events, never by patching internals. The full ecosystem map, with setup for each, lives on swarm.builtbyberry.com.

The Filament panel and the MCP server are two read-only renderings of the same public display seams — a panel for your team, an MCP surface for an AI client — neither able to mutate a run.

Local Development

From the package root:

composer install
composer lint
composer analyse
composer test

If you run PHPStan directly, use:

vendor/bin/phpstan analyse --memory-limit=2G --no-progress

composer format rewrites files with Pint. Use composer lint when you need a non-mutating formatting check.

License

MIT

builtbyberry/laravel-swarm 适用场景与选型建议

builtbyberry/laravel-swarm 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 1.69k 次下载、GitHub Stars 达 28, 最近一次更新时间为 2026 年 04 月 25 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「laravel」 「agents」 「ai」 「orchestration」 「swarm」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 builtbyberry/laravel-swarm 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 builtbyberry/laravel-swarm 我们能提供哪些服务?
定制开发 / 二次开发

基于 builtbyberry/laravel-swarm 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 1.69k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 28
  • 点击次数: 34
  • 依赖项目数: 3
  • 推荐数: 0

GitHub 信息

  • Stars: 28
  • Watchers: 0
  • Forks: 1
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-04-25