builtbyberry / laravel-swarm-memory-vector
Vector-backed memory driver for Laravel Swarm — semantic recall via pgvector and Laravel AI embeddings. Implements the MemoryStore contract from laravel-swarm.
Package info
github.com/builtbyberry/laravel-swarm-memory-vector
pkg:composer/builtbyberry/laravel-swarm-memory-vector
Requires
- php: ^8.5
- builtbyberry/laravel-swarm: ^0.23
- illuminate/console: ^13.0
- illuminate/contracts: ^13.0
- illuminate/database: ^13.0
- illuminate/support: ^13.0
- laravel/ai: ^0.9
- spatie/laravel-package-tools: ^1.16
Requires (Dev)
- larastan/larastan: ^3.10
- laravel/pint: ^1.29
- orchestra/testbench: ^11.1
- pestphp/pest: ^4.7
- pestphp/pest-plugin-laravel: ^4.1
This package is auto-updated.
Last update: 2026-07-21 05:12:13 UTC
README
Vector-backed semantic recall for Laravel Swarm memory. This companion package implements the core MemoryStore contract, transparently embedding every memory write and letting agents recall memory by meaning — "what did we learn about the rocket?" — instead of by exact key. Semantic search runs natively on PostgreSQL with pgvector, with a portable fallback that works on any database.
Semantic search is a ranking layer, never a leak. The vector reader only ever ranks the exact set of entries the active swarm's propagation policy already permits an agent to see. A vector hit can never surface memory that the standard
recalltool would withhold.
Requirements
- PHP 8.5+
builtbyberry/laravel-swarm^0.23laravel/ai^0.9 (for embeddings)- For the native
pgvectordriver: a PostgreSQL connection with thevectorextension available
Installation
composer require builtbyberry/laravel-swarm-memory-vector
Publish the config and run the migration:
php artisan vendor:publish --tag=swarm-memory-vector-config php artisan migrate
The migration creates a swarm_memory_vectors table. On PostgreSQL it enables the vector extension and creates a native vector(N) column with an HNSW cosine index; on any other database it stores embeddings as JSON for the portable scan driver.
Configure an embedding provider
Embeddings are generated through Laravel AI. Point it at your embedding provider of choice — for example Voyage AI:
VOYAGEAI_API_KEY=your-key SWARM_MEMORY_VECTOR_PROVIDER=voyageai SWARM_MEMORY_VECTOR_DIMENSIONS=1024
SWARM_MEMORY_VECTOR_DIMENSIONS must match the vector width your provider/model returns — it fixes the width of the vector(N) column. Voyage's voyage-4 returns 1024; OpenAI's text-embedding-3-small returns 1536. A mismatch fails loudly rather than corrupting the index.
How it works
Once installed, the package rebinds the Swarm MemoryStore to a decorator around the core database store:
- Writes still land in
swarm_memoriesexactly as before — same rows, timestamps, lifecycle events, andrun_idcascade. Alongside each string-valued write, the decorator generates an embedding and upserts it intoswarm_memory_vectors. The memory row and its embedding commit in a single transaction; the embedding provider call happens before the transaction opens, so a slow network round-trip never holds a database transaction open. - Redaction stays outermost. The core
RedactingMemoryStorewraps this store, so the text that gets embedded is the same capture-policy-redacted text that gets persisted — never a pre-redaction value. - Reads are unchanged. Exact-key recall, propagation, and replay all behave identically; the embedding is purely additive.
Non-string values (arrays, numbers, booleans) are persisted normally but not embedded — they remain fully available through the exact-key recall tool.
Semantic recall in an agent
Scaffold a vector-aware memory tool with the core generator (it detects this companion via Composer):
php artisan make:memory-tool SemanticRecall --vector
Wire the generated tool's semanticRecall() to this package's reader:
use BuiltByBerry\LaravelSwarmMemoryVector\Contracts\VectorMemoryReader; use Illuminate\Container\Container; protected function semanticRecall(string $query, MemoryScope $scope): string { return Container::getInstance() ->make(VectorMemoryReader::class) ->search($scope, $query, limit: 5); }
Drop the tool into any laravel/ai agent's tools() array. When the model calls it with a free-text query, it gets back the most semantically similar memory entries, formatted exactly like the core recall tool (key: value, one per line). The scope id is resolved from the active run — never accepted from the model.
Configuration
All keys live in config/swarm-memory-vector.php:
| Key | Env | Default | Purpose |
|---|---|---|---|
enabled |
SWARM_MEMORY_VECTOR_ENABLED |
true |
Rebind the memory store to the vector-backed decorator. |
connection |
SWARM_MEMORY_VECTOR_CONNECTION |
default | Connection holding the vector table (must match the memory connection). |
driver |
SWARM_MEMORY_VECTOR_DRIVER |
auto | pgvector, scan, or null to auto-detect (pgvector on pgsql). |
table |
SWARM_MEMORY_VECTOR_TABLE |
swarm_memory_vectors |
The embedding table. |
embedding.provider |
SWARM_MEMORY_VECTOR_PROVIDER |
Laravel AI default | Embedding provider. |
embedding.model |
SWARM_MEMORY_VECTOR_MODEL |
provider default | Embedding model. |
embedding.dimensions |
SWARM_MEMORY_VECTOR_DIMENSIONS |
1024 |
Vector width; must match the provider/model. |
search.default_limit |
SWARM_MEMORY_VECTOR_LIMIT |
5 |
Results returned when the caller omits a limit. |
search.min_similarity |
SWARM_MEMORY_VECTOR_MIN_SIMILARITY |
null | Drop hits below this cosine score. |
on_embedding_failure |
SWARM_MEMORY_VECTOR_ON_EMBEDDING_FAILURE |
store_without_vector |
store_without_vector keeps memory durable when embedding fails; throw aborts the write. |
Drivers
pgvector— nativevector(N)column ranked with PostgreSQL's<=>cosine-distance operator over an HNSW index. The headline path; scales to large memory.scan— stores embeddings as JSON and ranks with an in-PHP cosine similarity. Works on sqlite and mysql. Because ranking is always scoped to the small, already-authorized candidate set, the scan stays cheap.
Testing
composer test # Pest composer analyse # PHPStan (level 8) composer lint # Pint
The suite runs against sqlite (scan driver) locally and additionally against a real pgvector-enabled PostgreSQL in CI.