redberry/synapse
Redberry Synapse is a Laravel package for structured state management. It provides a clean, expressive API for defining states and transitions, helping you keep complex application workflows predictable, maintainable, and easy to test.
Synapse is a Telescope-style dev dashboard for agents built with laravel/ai: it discovers your existing agent classes, lets you chat with them in a browser, and records every message, tool invocation, and token count as it happens. Nothing about your agents needs to change — it hooks into the SDK you already have, in its own synapse_* tables.
Minimal path from zero to a working dashboard:
composer require redberry/synapse --dev
php artisan synapse:install # publishes config, migrations, and a provider stub with the viewSynapse gate
php artisan migrate # migrations are publish-only — they will not run on their own
php artisan serve
Then open /synapse. If you get a 403 instead of the SPA shell, the gate is the reason — the install command publishes a SynapseServiceProvider stub containing the viewSynapse gate; define it there (the stub is meant to hold your real authorization rule, e.g. local env or an admin check), or the dashboard stays closed to you.
Look at these three things before anything else:
config/synapse.php — the whole surface is there: enabled, ui, discovery, playground, storage, retention, plus the attachments disk. Read it once, top to bottom; it answers most questions you'll have later.The first genuinely useful use case is debugging a bad answer: reproduce the prompt in Synapse, read the recorded tool calls and model steps, and see whether the agent called the wrong tool, passed the wrong arguments, or got bad sources — before you start rewriting the system prompt. That loop, not the chat window, is why the package earns its place.
Where it does not belong: production (set SYNAPSE_ENABLED=false and keep the route cached away), and CI. It is a human-driven browser tool. Browser-level verification of agents is a separate concern.
Reproduce → inspect → adjust → re-run. The core workflow. Chat with the agent, expand the recorded tool invocations to see exact arguments and results, check token usage per step, adjust the prompt or tool schema in code, then re-run the same conversation. Completion explanations and model-step inspection are what make this faster than adding Log::info() and tailing the log.
Human-in-the-loop approval testing. When your agent gates a tool behind an approval, the dashboard surfaces the pending approval so you can exercise both branches (approve/deny) without wiring a temporary UI. Use this to confirm the denied path actually returns something the model can consume rather than blowing up mid-stream.
Keep a scratch agent for experiments. A throwaway agent class registered only in local environments gives you a playground chat target that never ships. It's the cheapest way to iterate on tool definitions: change the schema, refresh discovery, chat, read the tool-call payload.
Separate storage for the dashboard. Since Synapse writes to its own tables, you can point it at a different connection for bigger projects:
SYNAPSE_DB_CONNECTION=sqlite_synapse
Same reasoning for attachments_disk: point it at local (not public) — attachments are served through authenticated routes, not public URLs.
Guard the side effects. Chatting in Synapse invokes real tools with real dependencies. If a tool writes to a DB, sends mail, or hits a third-party API, you are doing that for real from the UI. Either work against a seeded local database with fakes bound for outbound services, or keep destructive tools behind the approval gate so you get a deliberate click before the blast radius.
Retention as a habit, not a cleanup. Set retention low in the config (days) and let synapse:prune run on the package's schedule, or run it in your own scheduler. Recorded conversations include full prompts and tool payloads — treat them as you would any dev-only log, and don't let them accumulate indefinitely on a shared dev machine.
Companion commands. synapse:clear nukes recorded data when you want a clean slate before a debugging session; synapse:prune trims by retention. Both are dev-only tools — never wire them into a deployment script.
Pair it with SDK fakes, not instead of them. Synapse replaces the manual "echo the prompt and read the log" loop; it does not replace Agent::fake() in Pest tests. Keep the deterministic assertions in tests, use Synapse to explore behavior you haven't yet codified.
synapse:install copies them into your app; if you skip migrate (or a teammate does after pulling), the SPA loads and then fails on every API call. This is the single most common "it's broken" report.local/development only, or an explicit admin check. If you can reach /synapse from a shared staging host without a login, so can anyone else.enabled=false in production, and cache routes. Routes are registered conditionally. If you flip the flag in a deployed environment, remember php artisan route:clear / config:clear — a stale route cache can keep the dashboard reachable.composer update. The compiled frontend lives in the package's committed dist/ and is inlined into the Blade shell at request time. Consumers never run npm run build, but a view cache can serve an old shell after an update — php artisan view:clear if the interface looks wrong for the version you think you're on.synapse_* tables are entirely separate from the SDK's agent_conversations. Deleting a Synapse conversation does not delete SDK records, and SDK history won't appear in the dashboard. Don't try to join them; the package deliberately doesn't touch SDK tables.limit: 1000 when you meant 10" tells you everything.discovery config section and the diagnostics page before opening an issue. Constructors requiring runtime arguments are a frequent cause.--dev and keep it out of production installs; the package is MIT and actively developed (last release late 2026), so pin sensibly and read UPGRADE.md on minor bumps.How can I help you explore Laravel packages today?