# How the Two agents, one page demo works

This demo shows several agents on one page, each with its own session. Watch the strip above the hotel page and the status light on each desk. Each light moves only on its own desk's events, and the strip lights once both desks have run.

The Atlas is a fictional boutique hotel above Alfama in Lisbon, and its home page has two desks side by side: a concierge and a spa. They are two different Mindset agents, `atlas-concierge` and `atlas-spa`, on one page. The demo proves three things at once: one served bundle can run any number of agents, each agent gets its own session, and a scripted agent and an unscripted one behave differently on the same page without any page code telling them apart.

## One bundle, two agents

The page loads `mindset-agent.js` once. That one script tag registers the one custom element. The page then creates two `<mindset-agent>` elements and calls `configure()` on each with a different `agent` handle. Nothing in the bundle knows about either agent: every difference between the desks arrives through the element's own configuration and the session it is given. The label on each desk names the handle it embeds, so you can see which agent you are talking to.

## A session per desk

Each element's `getSession` asks the site's session endpoint for a session bound to its own agent: `GET /api/demo-session?agent=atlas-concierge` for one desk and `?agent=atlas-spa` for the other. So each desk is its own session and its own conversation. The concierge cannot read the spa's chat and the spa cannot read the concierge's. That also means one visit to this page opens two sessions, and two conversations if you use both desks, which is worth knowing when you plan what several agents on one page will cost.

## The spa speaks first

The spa agent is bound to a one-phase script, `atlas-spa-welcome`. Its phase's `onEnter` runs before the agent's first token: an `$emit` step greets the guest, and a `$suggestReplies` step offers Restoring and Help me sleep. So the spa's greeting is in its chat before you type anything, while the concierge, which has no script, waits for you. The phase lists `atlas-spa-treatments` in `resources.functions`, because the phase where the guest's answer arrives is the one that needs the tool. It is `terminal` with `onComplete: "freeform"`, so after that first answer the chat runs free.

## Functions over sample data

Each desk has one function whose first step is literal sample data. `function__atlas-concierge-find-dining` returns restaurants near the hotel with their fado nights, tonight's start time and the walk in minutes, keeping only places with fado tonight when the guest asks for it. `function__atlas-spa-treatments` reads the guest's words as restoring or sleep and returns the matching treatments with length, price and tonight's times.

## The page only listens

Neither agent has page tools. The page listens to each element's `mindset:runtime-event` stream separately. Each desk's status light moves only on its own desk's events, and the "Your evening" card fills from each function's own `tool_end` output, so what the card shows is exactly what the function returned. The Under the hood tab shows each desk's calls on their own.
