Every component, in the order it has to start, with the commands — and a checklist at the end that tells you whether the installation is actually working.
For
Whoever is setting the platform up: a developer or a systems administrator.
Takes
45 minutes for the two required components; about 90 with knowledge and databases.
You end up with
A running Control Panel, a running Studio you can sign in to, and whichever of the Collection Server and SQL Connection Manager you need — all verified.
Before you start
Node.js 20.11 or later. Check with node -v. Read the warning about Node 24 below before you settle on a version.
The four project folders, side by side in one directory.
Docker Desktop, only if you will run agents as container images. Agents run perfectly well as folders without it.
A terminal, and the ability to leave two or three windows running.
Five things. The first two are required; the rest are installed when you need what they do.
Component
Folder
Default port
Needed?
Symphonix Control Panel the board every agent reports to
LGStudioMonitor
5180
Required. Start it first.
Symphonix Studio where flows are written and deployed
LGStudio
5174
Required for building agents.
Symphonix Core the engine, compiler and runtime
LGFlow
none — it is a library and a command
Required. Not a server.
Collection Server indexes documents and answers from them
LGFlow/collection
7300
Only for agents that answer from documents.
SQL Connection Manager holds database connections and schemas
LGFlow/database
7500
Only for agents that query a database.
Why the folders are named differently from the products
The folders, packages and import names are lgflow, lgstudio and lgstudio-monitor; the products are Symphonix Core, Symphonix Studio and the Symphonix Control Panel. That is deliberate and will not change: every generated project vendors the engine under its package name and pins it, so renaming the package would break every project already on disk until it was reinstalled. Commands name folders; screens name products.
Node.js, and the one version question that matters#
Node 20.11 or later is the floor, declared by the packages themselves. Use Node 24 if any agent here will stop and wait for a person — a form, an ask node, or an approval.
On an older Node, a waiting agent forgets what it was waiting for
From Core 0.26.6 the waiting state is kept in node:sqlite, which arrived well after 20.11. On an older Node the agent still runs, and says Waiting: in memory when it starts — which means a restart loses whatever somebody had half-filled in. It is not an error and nothing fails; you simply lose the thing you were least expecting to lose. Read that line on startup.
Put the four project folders side by side in one directory. Several defaults depend on it: the Studio serves flows from ../LGFlow with no flag when the two are siblings, and the test and sweep scripts in each project reach into ../LGFlow/scripts.
C:\Dev\Apps\
LGFlow\ Symphonix Core — the engine, and the collection/ and database/ servers
LGStudio\ Symphonix Studio
LGStudioMonitor\ Symphonix Control Panel
Any directory works; these paths are used throughout this page as an example.
on the machine Open a terminal in each of the three folders in turn and run npm install. The platform has almost no dependency tree — Core has five packages, the Studio one and the Control Panel one — so this is quick.
on the machine If you will use the SQL Connection Manager, also run npm install in LGFlow/database. It has its own package.json and its own three drivers, deliberately kept out of everything else.
on the machine The Collection Server lives in LGFlow/collection and needs no separate install — it runs on Core's own dependencies.
Check before going on
node -v prints 20.11 or later, and npm install finished without errors in each folder. There is no build step in any of these projects — nothing is compiled, so there is nothing else to run.
The order matters, and this is the reason: the Studio asks the Control Panel whether people must sign in. Start them the other way round and you get a Studio with no door.
on the machine Open a terminal in LGStudioMonitor and start it:
cd C:\Dev\Apps\LGStudioMonitor
node index.js --port 5180
It stays in the foreground. Ctrl+C stops it. npm start does the same thing on the default port.
on the machine Watch the console for Runner registered. Starting the board also starts a runner for this machine, which is what later lets the board stop and start agents on it.
in the Control Panel Open http://127.0.0.1:5180 in a browser. You should get the Control Panel.
Binding wider than loopback, and the token that goes with it
By default the board listens on 127.0.0.1 only. If an agent will run inside a container it cannot reach that — inside a container 127.0.0.1 is the container's own loopback — so the board has to be bound wider with --host 0.0.0.0. It refuses to do that without a token, and says so:
Listening beyond 127.0.0.1 without a token would let anyone who can reach the port terminate your agents. Set MONITOR_TOKEN.
Put MONITOR_TOKEN in that folder's .env so the command line carries no secret, and give each agent the same value. If nothing is containerised, leave the flag off — loopback is the safer default and needs no token.
on the machine Open a second terminal in LGStudio and start it:
cd C:\Dev\Apps\LGStudio
npm start
on the machine Read the one line on the console that is worth reading every time:
sign in: when-known, through http://127.0.0.1:5180
That line, and not the screen, says which mode the Studio came up in.
in the Studio Open http://127.0.0.1:5174.
Three steps, not two: start the board → refresh the page → sign in
The Studio asks the board whether a sign-in is required at all. The setting is STUDIO_SIGN_IN and its default is when-known, meaning ask while a board is reachable and has people in it. If the board is not answering when the page loads, the Studio opens with no door at all — and a tab that was already open before the board came up keeps showing whatever it was showing.
On any machine more than one person can reach, set STUDIO_SIGN_IN=required in the Studio's .env. That makes an unreachable board mean nobody gets in rather than everybody does.
Check before going on
The Studio's page loads at 127.0.0.1:5174, and the console line above names your board's address. If the Studio loads but shows no sign-in and you expected one, the board was not reachable when the page loaded: confirm the board is up, then refresh the page — restarting the Studio is not what fixes it.
3 · The Collection Server, if agents will answer from documents#
on the machine Start it on its own port:
cd C:\Dev\Apps\LGFlow
node collection/collection-server.mjs --http 7300
on the machine Its settings come from LGFlow/collection/.env. The names it reads are COLLECTION_PORT, COLLECTION_DB, COLLECTION_BOARD_MAY_STOP, MONITOR_URL and MONITOR_TOKEN. There is an .env.example beside it listing them.
on the machineDocuments live on this machine. A collection reads files from a folder on the Collection Server's own disk — not from your laptop, and not through a browser upload. Decide now which machine that is.
Why it reads COLLECTION_PORT and not PORT
Because the board's runner hands its own environment to anything it starts and takes PORT out on the way. A stray PORT on a machine would otherwise override every agent's own, which is a hard fault to find. The same reasoning gives the SQL Connection Manager DATABASE_PORT.
4 · The SQL Connection Manager, if agents will query a database#
on the machine Start it from its own folder:
cd C:\Dev\Apps\LGFlow\database
npm start
That script is node database-server.mjs --http 7500.
on the machine Its settings are DATABASE_PORT, DATABASE_DB, MONITOR_URL and MONITOR_TOKEN, from LGFlow/database/.env.
Why this is a separate package at all
It owns the database drivers — pg, oracledb and mssql — so that the engine does not, and so that no generated agent carries them. Three drivers in one component that needs them, rather than in every agent that does not. It supports Postgres, Oracle and SQL Server. Released
Nothing requires them to share one. Each is reached by an address, and the addresses are configured rather than assumed.
What needs to reach what
How it is told
The Studio → the Control Panel
The Studio's own environment. The console line at startup prints the address it will use.
An agent → the Control Panel
MONITOR_URL in the agent's .env, plus MONITOR_TOKEN when the board is bound beyond loopback.
An agent → the Collection Server
The server's entry in the Control Panel's MCP catalogue, which holds its address.
The Collection Server → its documents
A folder path on the Collection Server's own machine.
Inside a container, 127.0.0.1 means the container
Anything on the host machine is host.docker.internal, and that name also resolves on Windows itself — so one value works in both places. It affects MONITOR_URL (ws://host.docker.internal:5180/agent) and PGHOST or anything else pointing at a local service. The service also has to accept the connection: Postgres needs listen_addresses set beyond loopback and a pg_hba.conf entry for the address Docker's NAT presents.
Each component reads its own .env from its own folder. These are the names; the values are yours.
Never put a secret anywhere but a .env file
Not on a command line, not in a flow, not in a deployment setting. The platform is built around this: a flow names an MCP server and never its credential, agents sweep secrets out of anything they report, and a generated project's Dockerfile does not copy .env — .dockerignore excludes it, and a test holds both. A folder's .env sits on one machine; an image is pushed to a registry and its layers can be read back.
Where
Name
What it decides
Control Panel
MONITOR_TOKEN
Required before the board may bind beyond loopback. Agents send the same value.
ENTRA_*, LDAP_*
Sign-in through Microsoft Entra or an LDAP directory. ENTRA_TENANT_ID, ENTRA_CLIENT_ID, ENTRA_CLIENT_SECRET, ENTRA_REDIRECT_URI; LDAP_URL, LDAP_BASE_DN, LDAP_BIND_DN, LDAP_BIND_PASSWORD, LDAP_ATTRIBUTE, LDAP_INSECURE. There is an .env.example in that folder listing them all.
Studio
STUDIO_SIGN_IN
when-known by default. Set to required on any shared machine.
Collection Server
COLLECTION_PORT
The port. Not PORT — see the note above.
COLLECTION_DB
Where its index is kept.
COLLECTION_BOARD_MAY_STOP
Whether the board is allowed to stop it.
SQL Connection Manager
DATABASE_PORT, DATABASE_DB
Its port and its store.
Each deployed agent
PORT
The port it serves its chat page on. With nothing set it asks the operating system for a free one and prints the address it got — so it is different on every start.
MONITOR_URL, MONITOR_TOKEN
Which board to report to, and the token if the board requires one.
BIND, TRIGGER_BIND
What the chat door and the webhook endpoint listen on. Both loopback by default, and neither implies the other. An agent bound wider than loopback says so on stdout.
KNOWLEDGE_<NAME>_FOLDER
Where the documents for a named collection are. There is nowhere in a flow to put this, which is deliberate.
The webhook endpoint has no Host check
The chat door checks Host and that check is not configurable. The trigger endpoint does not — whatever reaches it starts the flow. That is why TRIGGER_BIND is a separate decision from BIND rather than inheriting it, and why widening it is something to do deliberately and behind something.
The Control Panel holds people, roles and privileges, and somebody has to be the first one.
in the Control Panel Open the Control Panel at http://127.0.0.1:5180. On a board with no people in it, STUDIO_SIGN_IN=when-known means the Studio will not ask for a sign-in — which is convenient on a single-machine setup and is exactly what you are about to change.
in the Control Panel Open Settings and add the first user and the role that may manage the estate. The privileges this page refers to elsewhere — agents.manage for the MCP catalogue, access.manage for an agent's tool subscriptions — are granted here.
on the machine Once there is a person on the board, set STUDIO_SIGN_IN=required in the Studio's .env and restart the Studio.
The exact screens for adding a user and building a role are not captured here yet
This page describes where that work happens and which privileges matter; the field-by-field walkthrough of Settings → users and roles has not been written against a running Control Panel, so it is not written here as though it had. The product repository's own material covers the thirty privileges and what each grants. Planned
docker stop <name> — a graceful stop, which removes its lock. docker rm -f kills it and leaves the lock behind, and the next start waits 20 seconds for the heartbeat to go quiet before taking the folder.
The installation is working when all of these are true. Each one is something you can see, not something you can assume.
node -v prints 20.11 or later — and 24 or later if any agent will wait for a person.
The Control Panel answers at its address, and its console said Runner registered.
The Studio answers at its address, and its startup line names your board.
You can sign in to the Studio — or you have deliberately decided that this machine does not require it.
If you installed it: the Collection Server is running, and you know which machine its documents folder is on.
If you installed it: the SQL Connection Manager is running.
If agents will be containers: docker version shows a Server section, not only a Client, and MONITOR_TOKEN is set on both the board and the agents.
No secret is anywhere except a .env file.
The one test that exercises all of it
Follow Build your first agent. It ends with an agent you deployed, started, talked to, and found on the board — which is every component above, proved by use rather than by inspection.
Confirm the board is up, then refresh the Studio page. Restarting the Studio is not what fixes it. To make this impossible, set STUDIO_SIGN_IN=required.
The board refuses to start with a message about a token
--host 0.0.0.0 without MONITOR_TOKEN.
Set the token in the board's .env, or drop the flag if nothing is containerised.
An agent starts but never appears on the board
It could not reach MONITOR_URL when it started.
From a container, the address is host.docker.internal, not 127.0.0.1. Check the agent's log for the Monitor: registered line.
An agent says Waiting: in memory
Node older than 24.
Upgrade Node if that agent waits for people. Otherwise it is only a note.
A collection says never built after a build
The folder path is not readable on the Collection Server's machine.
Check the path on that machine, not the one you typed it from.
An agent stands down immediately
Two copies of one flow — usually the Studio's Play and a container at once.
Stop one. Nothing undoes a stand-down when the other copy goes away; see Deploy and monitor.
A port is already in use
Something else has it, often a previous run.
Every component takes a port on the command line or from its own named variable. Nothing here insists on a particular number.
When something looks wrong, three questions in this order
Is the board up? Almost everything confusing downstream — a Studio with no sign-in, an agent that answers nobody — is this.
Did the agent register? Look for the Monitor: registered line in its log.
Is there a second copy? Check for a container and for Play in the Studio at the same time.
Which build this describes
Core 0.61.0 · Studio 0.41.0 · Control Panel 0.53.0 · DSL 0.33 · protocol 0.19. Ports, commands and variable names on this page were read out of the repositories at build time or verified against them by hand; see the verification report that ships with this site for which is which.