builtbyberry/laravel-swarm
Composer 安装命令:
composer require builtbyberry/laravel-swarm
包简介
Multi-agent swarm orchestration for Laravel, built on Laravel AI.
README 文档
README
Laravel Swarm
📚 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.
- Documentation: swarm.builtbyberry.com
- Packagist:
builtbyberry/laravel-swarm - Namespace:
BuiltByBerry\LaravelSwarm - Repository: https://github.com/builtbyberry/laravel-swarm
- In-repo docs: docs/README.md
- Examples: examples/README.md
- Upgrading: UPGRADING.md
- Contributing: CONTRIBUTING.md
Contents
- Getting started — Quick Start · Requirements · Installation · Your First Swarm · Running a Swarm
- Execution modes — Choosing an Execution Mode · Queueing · Streaming · Durable Execution
- Capabilities — Memory · Topologies
- Production & reference — Testing · Configuration · Production Checklist · Documentation · Companion Packages · Local Development
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 aSwarmAuditSink(and optionalSwarmAuditSigner/ActorResolver/CapturePolicy) insideAppServiceProvider.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 intoapp/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):
CausalLogStoreandColdArchiveDriverare 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:
MemoryPropagationPolicydecides which memory entries a worker agent sees at invocation (default: the Run-scoped view, byte-identical to v0.9).MemoryCapturePolicyredacts or drops entries at the write boundary, so PII never reaches a snapshot (default: a no-op).- Operator CLI —
swarm:memory:inspect(view a run's frozen snapshots),swarm:memory:dump(export the full memory + snapshot trail for an audit packet / DSAR), andswarm: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:
- Core —
swarm.topology,swarm.timeout,swarm.max_agent_steps - Persistence & history —
swarm.persistence.*,swarm.capture.*,swarm.retention.*,swarm.history.* - Execution modes —
swarm.queue.*,swarm.durable.*,swarm.streaming.* - Memory & context —
swarm.memory.*,swarm.context.*,swarm.context_growth.*,swarm.compaction.* - Topology plans —
swarm.hierarchical.*,swarm.static_hierarchical.* - Governance & observability —
swarm.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(), ordispatchDurable()intentionally. - Use database persistence for durable execution, long-lived history, active-run pruning protection, or operational dashboards.
- Set
SWARM_CAPTURE_ACTIVE_CONTEXT=truefor queued and durable swarms. - Size queue worker timeouts and queue
retry_afterabove the longest expected provider call. - Schedule
swarm:relayevery 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. Useswarm:relay --type=auditto drain only the audit lane during focused recovery. See Durable Execution and Audit Evidence Contract for the full relay reference. - Run
php artisan migrateon database persistence to createswarm_audit_outbox— required for the v0.5 defaultSWARM_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:recoverevery 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:prunedaily for database retention cleanup, or setSWARM_PREVENT_PRUNE=truewhen retention is managed outside the package. - Streaming crash-replay (v0.12.0):
php artisan migratecreatesswarm_stream_step_checkpoints, which records each completed non-final streamed step's raw output + usage so an abandonedstream()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 byswarm:memory:purge(--keep-snapshotsretains both) and cascade-deleted via theswarm_run_historiesforeign key as theswarm:prunebackstop. See Streaming — Crash-Replay Durability. - Rotate
APP_KEYcarefully (v0.12.1): whenencrypt_at_restis on, durable operational resume state is sealed with the activeAPP_KEY. Rotating the key without re-keying the stored rows now makes durable resume fail loud with a clearSwarmException("…verify APP_KEY…") instead of silently resuming from a wrong/empty prompt — re-pointAPP_KEYto 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
SwarmAuditSinkfor regulated evidence export. - Bind
SwarmTelemetrySinkfor logs, metrics, or tracing correlation. - Avoid secrets in metadata. Capture redaction does not sanitize arbitrary developer-supplied metadata. Set
SWARM_MAX_METADATA_BYTESto 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--jsonfor monitoring and--include-payloadsfor 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— handlesSwarmAuditSinkwrite 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— extendsSwarmAuditSinkwithforRun(string $runId): iterable<array>so the sink can participate inswarm:trace. Opt-in; the shippedNoOpSwarmAuditSinkdoes 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:
- Choosing an Execution Mode — prompt, queue, stream, or durable
- Durable Execution — checkpointing, recovery, and operator controls
- Swarm Memory — scoped, snapshot-replayable memory
- Configuration — every config key
- Public Surface — the supported API, events, and read seams
- Audit Evidence Contract — compliance and auditability
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.
laravel-swarm-filament— a read-only Filament panel that turns every run into a topology-aware flow graph, with click-through to per-step inputs, outputs, tokens, timing, and memory.laravel-swarm-mcp— a read-only Model Context Protocol server that exposes run history, durable-run state, and audit-outbox health as MCP resources, so any MCP client (Claude, Cursor, …) can observe your swarms.laravel-swarm-pulse— Laravel Pulse recorders and dashboard cards for swarm runs, steps, memory, and audit-outbox health (see Pulse).laravel-swarm-memory-vector— vector-backed semantic memory recall on top of core Swarm Memory.
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 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 builtbyberry/laravel-swarm 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
DX-first workflow / saga / compensation engine for Laravel with native dry-run, reverse-order compensation, business impact tracking, opt-in persistence, and audit events.
Interactive CLI that generates customized Claude Code markdown files (CLAUDE.md, commands, agents) for PHP projects with Symfony, Laravel, Rector, PHPStan, PHP-CS-Fixer, GrumPHP and more.
PHP microservice orchestration pattern library.
Alfabank REST API integration
Symfony bundle and framework-agnostic core to integrate managed applications with Application Manager (orchestration, consumption, operational state).
Framework-neutral PHP client and worker SDK for the Durable Workflow server
统计信息
- 总下载量: 1.69k
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 28
- 点击次数: 34
- 依赖项目数: 3
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-04-25