Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
b828639
feat: add dynamic office mode for agent families
Sep 5, 2026
8de6f4c
feat: label agents by work role
Sep 6, 2026
ac10f6c
feat: prepare Agent Flow Office for VPS hosting
Sep 7, 2026
aae1977
feat: allow isolated relay preview ports
Sep 7, 2026
140fe59
fix: strip Office prefix before Next proxy
Sep 7, 2026
fb578ff
fix: keep production web port separate from mantenimiento
Sep 7, 2026
a219c7f
feat: protect production office route
Sep 7, 2026
ca46cfc
fix: watch all VPS agent workspaces
Sep 7, 2026
3a1303a
feat: enrich office agent avatars and states
Sep 7, 2026
342cada
feat: add office filters and interaction controls
Sep 7, 2026
8001fa4
feat: add office waiting room and richer spaces
Sep 7, 2026
c3ef14b
fix: keep available agents in waiting room
Sep 8, 2026
de3f9a3
fix: remove duplicate waiting room banner
Sep 8, 2026
2c70d1d
feat: show agents from all sessions in office
Sep 8, 2026
79d4426
feat: aggregate local and VPS agent sessions
Sep 8, 2026
3a4c02a
feat: proxy hybrid ingest through hosted web
Sep 8, 2026
cb9553e
feat: bridge local sessions to hosted office
Sep 8, 2026
0d7616f
fix: keep hosted bridge file-only
Sep 8, 2026
5292872
fix: use temporary SSH host verification
Sep 8, 2026
d7f10e0
fix: launch hosted bridge from any folder
Sep 8, 2026
d189a2d
fix: avoid pnpm dependency in hosted launcher
Sep 8, 2026
aa9e401
feat: add one-click hosted office launcher
Sep 8, 2026
857208f
fix: return completed agents to waiting room
Sep 8, 2026
f1ad0bc
fix: route office agents by observed activity
Sep 8, 2026
da2552e
feat: improve office session observability
Sep 9, 2026
57671b2
fix: keep observed sessions in office roster
Sep 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@ dist
*.local
.next
*.vsix
.relay.env

# Auto-generated
extension/README.md
scripts/.dev-relay.js
scripts/.dev-relay.js.map
scripts/.remote-forwarder.js
scripts/.remote-forwarder.js.map
app/dist/
next-env.d.ts
*.tsbuildinfo
Expand Down
115 changes: 108 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,50 @@ Claude Code is powerful, but its execution is a black box — you see the final
- **Live agent visualization**: Watch agent execution as an interactive node graph with real-time tool calls, branching, and return flows
- **Claude Code + Codex**: Auto-detects sessions from both runtimes concurrently and shows them side-by-side, or restrict to one via the `agentVisualizer.runtime` setting
- **Claude Code hooks**: Lightweight HTTP hook server receives events directly from Claude Code for zero-latency streaming
- **Hosted hybrid bridge**: Optional ephemeral Windows bridge forwards filtered local Claude/Codex session metadata to the VPS Office without installing a local service
- **Codex rollout tailing**: Reads `~/.codex/sessions/**/rollout-*.jsonl` (respects `CODEX_HOME`) and surfaces tool calls, reasoning, and authoritative token counts from Codex's own event stream
- **Multi-session support**: Track multiple concurrent agent sessions with tabs
- **Interactive canvas**: Pan, zoom, click agents and tool calls to inspect details
- **Timeline & transcript panels**: Review the full execution timeline, file attention heatmap, and message transcript
- **JSONL log file support**: Point at any JSONL event log to replay or watch agent activity
- **Office mode (MVP)**: The visualizer opens in a privacy-scoped office view by default; the existing Graph view remains available as a reversible toggle
- **Office session roster**: Shows every known session, including sessions waiting for their first agent event, with live connection, runtime, origin, freshness, and session-scoped filters
- **Hybrid source fidelity**: Preserves bounded local/VPS and Claude/Codex metadata through the event bridge so background sessions remain identifiable without exposing prompts or transcripts

## Office mode (MVP)

Office is a read-only projection of the event stream already consumed by Agent
Flow. It places observed agents into evidence-backed work zones and shows
parent/child relationships only when a corresponding spawn or dispatch event
exists. It does not create a second source of truth or persist layout state.

The projection discovers new Claude Code and Codex agents as events arrive.
Agent identities are deterministic and session-scoped, so equal names in
different sessions remain distinct and nested agents can be represented. Terra
and Luna receive their named avatar families; other and future model IDs are
kept as reported without a hard-coded model catalogue.

Agents also receive a short work-based label (for example, `Seguridad · Terra`
or `Validador · Luna`). Labels come from a closed vocabulary inferred from
bounded work hints; prompts and task text are not copied into the UI. The
opaque agent ID remains available for exact identification.

Office intentionally exposes only bounded names, model IDs, states, zones, and
relationship evidence. Prompts, transcript text, file paths, and tool
arguments are not passed to the Office view. The implementation is local and
read-only: it does not write to `.codex`.

The Office roster also distinguishes an observed session from a decorative
standby character. A session card can exist before its first agent event; no
agent is fabricated for that state. Selecting a session filters the room view
and synchronizes the Graph session, while the global view keeps all observed
sessions available. Duplicate relay events with sequence numbers are ignored,
and unchanged background projections are cached so long-running offices do not
replay every session on each update.

For the local/demo workflow, use the commands below and open the displayed
localhost URL. Office is the initial view; select **Graph** to return to the
original canvas, and **Office** to switch back.

## Getting Started

Expand Down Expand Up @@ -53,6 +92,48 @@ pnpm run dev # start the web app + event relay

Open http://localhost:3000 and start a Claude Code session in another terminal — events will stream to the browser in real-time.

The relay binds to localhost for the local workflow. It reads the existing
Claude Code and Codex event sources; it does not require a hosted service.

### Hosted VPS Office

For an internal office that remains available when a workstation is retired,
run the agents, relay, and Next.js server on the same VPS. The browser then
opens the launcher path (for example `/agent-flow/`) and receives the relay
over the same HTTPS origin; no local server or local transcript copy is
needed.

The hosted build uses these public-build variables:

```bash
NEXT_PUBLIC_BASE_PATH=/agent-flow
NEXT_PUBLIC_RELAY_URL=/agent-flow/events
NEXT_PUBLIC_DEMO=0
```

To make the currently running local Claude/Codex sessions visible in that
hosted Office, run the ephemeral bridge from this repository (it does not
install a Windows service or local web server):

```powershell
powershell -ExecutionPolicy Bypass -File .\scripts\connect-hosted.ps1
```

Stop it with `Ctrl+C` when local sessions no longer need to be shown.

For a one-click launch, double-click `open-agent-flow-office.cmd` in the
repository root. It opens the hosted PWA and starts the temporary bridge; use
`stop-agent-flow-office.ps1` to disconnect it.

The production units, reverse-proxy locations, PWA manifest, and network-only
service worker are in [`deploy/agent-flow/`](deploy/agent-flow/). Keep the
private web and relay listeners behind the launcher's existing authentication;
never publish the relay port directly or cache authenticated agent data.

For a hybrid office that also receives bounded events from an existing local
Claude/Codex channel, see [`docs/hosted-hybrid-sessions.md`](docs/hosted-hybrid-sessions.md).
This uses the VPS as the aggregator and does not require a new Windows service.

### VS Code Extension

1. Install the extension
Expand Down Expand Up @@ -143,14 +224,23 @@ Created by [Simon Patole](https://github.com/patoles), for [CraftMyGame](https:/

## Privacy & Telemetry

Agent Flow ships **opt-out** anonymous usage telemetry, enabled by default only
in the published `npx agent-flow-app` binary. `pnpm run dev` and the VS Code
extension emit nothing. Only aggregate events are sent — session count,
duration, event count, OS/arch, Agent Flow version, distinct model IDs
observed, which runtimes were watched, and error class names. Prompts, file
paths, tool calls, user info, and environment variables are never sent.
Telemetry is disabled by default for the Office MVP/local demo and creates no
install ID or telemetry directory. To opt in explicitly, set:

```bash
AGENT_FLOW_TELEMETRY=true pnpm run dev
```

In PowerShell, use `$env:AGENT_FLOW_TELEMETRY="true"` before starting the
command. Only the explicit value `true` (case-insensitive) opts in;
`DO_NOT_TRACK=1` always disables telemetry, even when opt-in is set.
The same variables can be exported before using another local entry point.
When telemetry is enabled by a published entry point, only aggregate events
are sent; prompts, file paths, tool calls, user info, and environment variables
are not sent. Office itself has no telemetry path and does not write `.codex`.

- **Turn off:** `export AGENT_FLOW_TELEMETRY=false` or `export DO_NOT_TRACK=1`
- **Turn off:** unset `AGENT_FLOW_TELEMETRY` (the default) or use
`export DO_NOT_TRACK=1`
(disabled installs write zero state to disk — no `~/.agent-flow/` directory)
- **Inspect the payload:** `cat ~/.agent-flow/telemetry/events.jsonl`
- **Full schema + exact fields:** see the v0.8.1 entry in
Expand All @@ -159,6 +249,17 @@ paths, tool calls, user info, and environment variables are never sent.
- **Reset your anonymous identity:** delete `~/.agent-flow/installation-id` —
a fresh random UUIDv4 will be generated on next run

## MVP limitations and rollback

Office states are derived only from events observed by the relay/parser. An
unseen event, an interrupted session, or an unfamiliar event type can leave an
agent as `unknown`, `stale`, or otherwise incomplete; the view does not infer
intent or claim a complete execution history.

Rollback is reversible: close the local Office/Agent Flow process and reopen
the visualizer, then select **Graph**. No deployment or canary is implied by
this MVP documentation.


## License

Expand Down
4 changes: 4 additions & 0 deletions app/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ export async function startServer(options: ServerOptions) {
return relay.handleSSE(req, res)
}

if (req.url === '/ingest' && req.method === 'POST') {
return relay.handleIngest(req, res)
}

// Static files (UI)
if (req.method === 'GET') {
return serveStatic(req, res)
Expand Down
109 changes: 109 additions & 0 deletions deploy/agent-flow/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# Agent Flow Office on the VPS

This is the production shape for the internal launcher/PWA. The Windows
checkout is only a development/review source; the runtime lives on the VPS.

## Runtime contract

- App root: `/home/discanary/apps/agent-flow-office`
- Watch root: `/home/discanary` so new Claude/Codex sessions and their subagents
under the VPS user's workspaces are incorporated automatically.
- Private web listener: `172.17.0.1:8612` (kept separate from the existing Mantenimiento service on `8610`)
- Private SSE relay: `172.17.0.1:3001`
- Public path: `/agent-flow/` on the already authenticated launcher host
- Browser SSE path: `/agent-flow/events`
- Workspace observed by the relay: `/home/discanary/apps/agent-flow-office`
- Claude and Codex session data remain on the VPS under the `discanary` account
- A future local source can submit bounded, authenticated lifecycle events to
`/agent-flow/ingest`; this is an optional hook/bridge channel, not a new
Windows service. The relay rejects the route until a token is configured.

The relay must run on the same host as the agents. It is not a GitHub Actions
job and it is not a Windows process.

For a pre-production preview, keep the same code and use a separate checkout,
path, and ports (for example `/agent-flow-preview/`, `8611`, and `3002`) with
`AGENT_FLOW_RELAY_PORT=3002`. Never point the preview proxy at the production
ports.

## New agent onboarding contract

The Office is event-driven, so adding a subagent to a supported Claude or Codex
session does not require a new page or another deployment. The runtime emits
the existing lifecycle events (`agent_spawn`, `model_detected`,
`subagent_dispatch`, and the normal tool or completion events). A future runtime
adapter can use the same contract. The projection keeps an opaque
session-scoped identity, derives a bounded work label, and gives an
unrecognised future model a stable generated avatar. Task text is not copied
into the Office view. This keeps new Terra, Luna, Codex, Claude, or future
model IDs visible without exposing their prompts or requiring a catalogue edit.

## Build an approved release on the VPS

Run only after the corresponding GitHub PR has been reviewed and the release
identity has been recorded:

```bash
cd /home/discanary/apps/agent-flow-office
pnpm install --frozen-lockfile
node scripts/build-relay.js
NEXT_PUBLIC_BASE_PATH=/agent-flow \
NEXT_PUBLIC_RELAY_URL=/agent-flow/events \
NEXT_PUBLIC_DEMO=0 \
pnpm --dir web build
```

The web build embeds the public path and SSE route. Do not use the development
server in production.

## Services

Install the two unit files in this directory, then perform a controlled
`daemon-reload`, enable, and start. The release operator must verify the
effective unit files before starting them; a merge alone is not deployment
evidence.

```bash
sudo install -m 0644 deploy/agent-flow/agent-flow-relay.service /etc/systemd/system/
sudo install -m 0644 deploy/agent-flow/agent-flow-web.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now agent-flow-relay.service agent-flow-web.service
```

The relay needs write access to `/home/discanary/.claude/agent-flow` for Claude
hook discovery. If that directory cannot be created, stop the release and fix
the VPS ownership/permissions; do not silently publish an office that cannot
observe the configured runtime.

To enable the optional ingress, create an environment file owned by `discanary`
at `/home/discanary/apps/agent-flow-office/.relay.env` with mode `0600` and one
line:

```text
AGENT_FLOW_INGEST_TOKEN=<long-random-token>
```

Keep that value out of GitHub and out of the URL. The local runtime channel,
when available, sends `Authorization: Bearer <token>` to the public ingest
location documented below.

## Nginx Proxy Manager route

Create the route on the existing authenticated launcher host. Keep the private
ports inaccessible from the Internet and reuse the launcher's existing access
policy. The custom locations are documented in
`nginx-proxy-manager-locations.md`.

After the proxy change, verify all of the following from an authenticated
browser session:

1. `https://<launcher-host>/agent-flow/` returns the Office UI.
2. `https://<launcher-host>/agent-flow/healthz` returns the web service JSON.
3. The private relay `http://172.17.0.1:3001/healthz` returns the relay service JSON.
4. `/agent-flow/manifest.webmanifest` and `/agent-flow/sw.js` are reachable.
5. `/agent-flow/events` remains an open SSE stream (proxy buffering disabled).
6. A real VPS agent session appears with its role label and lifecycle events.
7. Reopening the page from another device still shows the remote office.

Do not cache the authenticated HTML, SSE stream, transcripts, tool output, or
operational results in the PWA service worker.
28 changes: 28 additions & 0 deletions deploy/agent-flow/agent-flow-relay.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
[Unit]
Description=Agent Flow Office event relay
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=discanary
Group=discanary
WorkingDirectory=/home/discanary/apps/agent-flow-office
Environment=HOME=/home/discanary
Environment=NODE_ENV=production
Environment=AGENT_FLOW_RUNTIME=auto
Environment=AGENT_FLOW_SOURCE=vps
Environment=AGENT_FLOW_HOST_ID=vps
EnvironmentFile=-/home/discanary/apps/agent-flow-office/.relay.env
Environment=AGENT_FLOW_RELAY_HOST=172.17.0.1
ExecStart=/usr/bin/node /home/discanary/apps/agent-flow-office/scripts/.dev-relay.js /home/discanary
Restart=always
RestartSec=5
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=full
ProtectHome=read-only
ReadWritePaths=/home/discanary/apps/agent-flow-office /home/discanary/.claude /home/discanary/.codex

[Install]
WantedBy=multi-user.target
22 changes: 22 additions & 0 deletions deploy/agent-flow/agent-flow-web.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[Unit]
Description=Agent Flow Office web UI
After=network-online.target agent-flow-relay.service
Wants=network-online.target

[Service]
Type=simple
User=discanary
Group=discanary
WorkingDirectory=/home/discanary/apps/agent-flow-office/web
Environment=NODE_ENV=production
ExecStart=/usr/bin/node /home/discanary/apps/agent-flow-office/web/node_modules/next/dist/bin/next start -H 172.17.0.1 -p 8612
Restart=always
RestartSec=5
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=full
ProtectHome=read-only
ReadWritePaths=/home/discanary/apps/agent-flow-office/.next

[Install]
WantedBy=multi-user.target
Loading