The demo application
demo/in the repository root. A page that does not describe the three ways of embedding — it runs all three of them at once. AGNT2-241.
Embedding worked before this folder existed, but showing it meant assembling a page by hand every time. This is that page, assembled once and kept.
Running it
cp demo/.env.example demo/.env # then fill in three lines
make dev # api + app + admin + the demo on :3002or on its own, without the other three applications:
node demo/server.mjs # :3002, or DEMO_PORT=3999 node demo/server.mjsThere is nothing to install. The demo has no dependencies, no build and no lockfile — node demo/server.mjs runs from a clean clone. That is a decision: a fourth package manifest beside api, app and admin would mean a fourth install in make dev and one more place where the installed tree can drift from what is declared.
Inside a Superset workspace
make dev binds the shared ports 3000/3001/3333 and kills whoever holds them, so it must not be run there. ./.superset/run.sh raises the demo instead, on API_PORT + 3 from the workspace's own port block.
Configuration, and nothing in the code
Everything lives in demo/.env. No file under demo/ needs editing for any of it, and the repository contains no real identifier, ticket or key — only demo/.env.example, which is names and shapes.
| variable | what it is |
|---|---|
AGENTFY_AGENT_ID | which agent the widget talks to |
AGENTFY_HUB_URL | the hub address the visitor's browser reaches — not the api's port |
AGENTFY_EMBED_KEY | the team key. Set it, and the demo mints its own tickets — see below |
AGENTFY_API_URL | the api the demo's own server calls with that key |
AGENTFY_EMBED_TOKEN | a page ticket pasted by hand. Used only when there is no key |
AGENTFY_TOKEN_URL | where the widget inside these docs asks for a ticket — the demo's /token |
AGENTFY_SDK_URL | where the widget bundle comes from; empty means the stock address |
AGENTFY_DOCS_URL | where these docs are running, for the links back to this section |
DEMO_PORT | the demo's port; 3002 by default |
The key never leaves the demo's own process. It is in no response the browser sees, and it is not read by the documentation build — see below.
What the page shows
| way | on the page |
|---|---|
| script tag, floating bubble | live — the bubble in the bottom-right corner |
| a package in your build | live — a window inside the page, from the same init({ mode: 'inline', mount }); only the npm i line is described rather than executed, because the demo deliberately has no build |
| your own interface over the client | live — a chat drawn entirely by the page's own markup over BridleClient |
Each of the three blocks is a separate visitor: the page ticket is exchanged for a per-visitor one three times, so the three blocks hold three independent conversations rather than sharing one.
The fifteen-minute problem, and two answers to it
An embed ticket lives 15 minutes by default and 24 hours at most — see why it cannot live longer. A demo with a ticket written into a file is therefore guaranteed to stop answering one day, and the person looking at a silent widget will conclude that embedding is broken.
So the demo has two modes, and it says on the page which one it is in.
key — nothing to expire
With AGENTFY_EMBED_KEY set, the demo's own server is the website's backend: it asks the api for a ticket naming one customer, at the moment the page connects. No ticket is in the file at all, so nothing in it can go stale. This is what a real site does, and it is the mode to use.
It also shows the part of the key that matters. The three blocks arrive as three named people rather than three anonymous strangers, and they show up in the team's lead list with names and emails.
token — the case that cannot avoid it
With no key and a pasted AGENTFY_EMBED_TOKEN, the demo behaves like a static site: it reads its own ticket before handing it to the widget, shows how long is left, and when the time runs out says exactly that — when it expired, why the life is so short, where to mint a new one, and that the server does not need restarting, because .env is re-read on every configuration request. If it expires while the page is open, a countdown walks it to the same explanation without a reload, and the widgets come down rather than sitting there pretending.
The widget in these very pages
The section you are reading carries the same floating bubble, on /embed/* in all three languages, and it comes down when you leave the section.
It is configured from the same demo/.env, and it is the case the section argues about: a documentation build is a static site with no backend of its own. So it takes AGENTFY_TOKEN_URL — the demo's /token — when there is one, and a pasted AGENTFY_EMBED_TOKEN when there is not.
The team key is never read by the documentation build. It would end up in a published bundle, and a published key mints tokens naming anyone in the team. With none of it configured the pages build exactly as before, with no widget and no warning.
The port
3002, added in three places: make dev raises it, make kill-ports frees it before the start, and make down frees it after. The existing three — 3000, 3001, 3333 — are untouched.
A port added to dev and forgotten in kill-ports fails in a way worth naming: the demo survives one Ctrl-C, keeps the port, and the next make dev dies on an address already in use with nothing to point at.