Synaptic Monitor

View Source

The 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_000

That is enough to start the monitor runtime automatically when :synaptic boots, because Synaptic starts monitor children from Synaptic.Application.

If the monitor is disabled:

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: 4050

Mount 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
end

Then start your app as usual:

mix phx.server

Open:

  • http://localhost:4000/dev/synaptic

Notes:

  • Synaptic.Monitor.Web.Live is 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: 4050

Then 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:

  1. Enable Synaptic.Monitor in dev.
  2. Decide whether you want embedded or standalone mode.
  3. If embedded, mount Synaptic.Monitor.Web.Live in your Phoenix router.
  4. If standalone, enable Synaptic.Monitor.Web or start it manually.
  5. Start the app and run a workflow.
  6. 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
end

Then:

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: true is 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.Cowboy when 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:

Web APIs: