Synaptic Monitor
View SourceThe Synaptic monitor is a dev-only browser UI for watching workflows, services, instances, router calls, step activity, and recent events in one place.
It supports two modes:
- embedded inside an existing Phoenix app
- standalone on its own port, in the same BEAM node as the Synaptic runtime
The current MVP is:
- single-node only
- in-memory only
- read-only
- intended for development, demos, and workflow debugging
What It Shows
The monitor currently helps you inspect:
- active and recent runs
- current step and step history
- router / agent call relationships
- service, instance, task reference, and workflow topology
- recent activity log with timestamps
- input and output payloads for steps and router calls
- waiting states, retries, and errors
- LLM and MCP summary events when telemetry is present
Core Setup
Enable the monitor core in your host application config:
config :synaptic, Synaptic.Monitor,
enabled: config_env() == :dev,
history_limit: 500,
retention_ms: 300_000That is enough to start the monitor runtime automatically when :synaptic
boots, because Synaptic starts monitor children from
Synaptic.Application.
If the monitor is disabled:
Synaptic.Monitor.snapshot/0returns an empty snapshotSynaptic.Monitor.recent_events/1returns[]Synaptic.Monitor.capture/1becomes inert
Embedded Phoenix Setup
Use this when your project already has a Phoenix app and you want the monitor
available under a dev route such as /dev/synaptic.
Keep the standalone viewer disabled:
config :synaptic, Synaptic.Monitor.Web,
enabled: false,
port: 4050Mount the embeddable LiveView in your router:
if Application.compile_env(:my_app, :dev_routes) do
import Phoenix.LiveView.Router
scope "/dev" do
pipe_through :browser
live "/synaptic", Synaptic.Monitor.Web.Live
end
endThen start your app as usual:
mix phx.server
Open:
http://localhost:4000/dev/synaptic
Notes:
Synaptic.Monitor.Web.Liveis only compiled when Phoenix LiveView is available.- The monitor page subscribes to the Synaptic monitor bus and updates live.
Standalone Setup
Use this when your app is headless or when you want the monitor on a dedicated port.
Enable the standalone viewer:
config :synaptic, Synaptic.Monitor.Web,
enabled: config_env() == :dev,
port: 4050Then start your app normally. Synaptic will boot the monitor endpoint automatically.
Open:
http://localhost:4050
The standalone viewer runs in the same BEAM node as your application and reads monitor state directly.
Manual Start In IEx
If you prefer not to auto-start the standalone viewer, leave
Synaptic.Monitor.Web disabled and start it manually:
{:ok, _viewer} = Synaptic.Monitor.Web.start_link(port: 4050)This is useful when:
- you only want the monitor sometimes
- you are validating a Phoenix app like
tmp/voice_lab - you are experimenting in
iex
Existing Project Checklist
For an existing project using Synaptic:
- Enable
Synaptic.Monitorindev. - Decide whether you want embedded or standalone mode.
- If embedded, mount
Synaptic.Monitor.Web.Livein your Phoenix router. - If standalone, enable
Synaptic.Monitor.Webor start it manually. - Start the app and run a workflow.
- Open the monitor and select the active run from the sidebar.
Example: Existing Phoenix App
# config/dev.exs
config :synaptic, Synaptic.Monitor,
enabled: true,
history_limit: 500,
retention_ms: 300_000
config :synaptic, Synaptic.Monitor.Web,
enabled: false# lib/my_app_web/router.ex
if Application.compile_env(:my_app, :dev_routes) do
import Phoenix.LiveView.Router
scope "/dev" do
pipe_through :browser
live "/synaptic", Synaptic.Monitor.Web.Live
end
endThen:
mix phx.server
Open http://localhost:4000/dev/synaptic.
Example: Voice Lab
The internal example app at tmp/voice_lab already includes monitor config:
tmp/voice_lab/config/config.exs
Run it:
cd tmp/voice_lab
iex -S mix phx.server
Then either:
- open the app and start using it, if standalone monitor is enabled in config
- or start the standalone monitor manually in IEx:
{:ok, _viewer} = Synaptic.Monitor.Web.start_link(port: 4050)Open:
- app:
http://localhost:4000 - monitor:
http://localhost:4050
Payload Inspection
The monitor includes Input and Output buttons on:
- activity log events
- step history entries
Clicking either opens a modal with the captured payload.
Current payload coverage is best for:
- workflow step execution
- routed agent / service calls
- wait / resume / failure transitions
LLM and MCP events currently emphasize summaries and metrics more than raw provider payloads.
Troubleshooting
The monitor page is empty
Check that:
config :synaptic, Synaptic.Monitor, enabled: trueis set for the current env- the app was restarted after enabling it
- a workflow has actually been started
For long-running Phoenix sessions, changing config and running recompile is
not enough if the Synaptic application already booted without monitor children.
Restart the app.
Standalone monitor does not start
The standalone endpoint needs Phoenix plus an HTTP adapter. Synaptic will use:
Plug.Cowboywhen available- otherwise
Bandit.PhoenixAdapter
If neither is available, Synaptic.Monitor.Web.start_link/1 will raise with a
clear message.
The monitor crashes on errors or exception structs
This should now be handled safely. Exception values are normalized for browser rendering and JSON snapshots so failed runs remain visible instead of taking down the page.
Voice workflows show runs, not a rich agent mesh
That is expected when the app runs direct workflows rather than routing through
Synaptic services with AgentRouter. In that case the most useful views are:
- run focus
- step history
- activity log
- payload inspection
Public APIs
Core APIs:
Synaptic.Monitor.snapshot/0Synaptic.Monitor.entity/2Synaptic.Monitor.recent_events/1Synaptic.Monitor.subscribe/0Synaptic.Monitor.unsubscribe/0
Web APIs: