Console + public site
Two separate Flask apps with very different audiences. Knowing which one you want before you ask saves a round trip.

The Console (internal)
The Console is a members-only web app where Agent A drops internal tools. Think of it as your team's private dashboard surface.
- URL pattern:
/applications/<slug>/for tool apps,/reports/<slug>/for report pages. - Reachable only to workspace members. Anonymous visitors get a login wall.
- The app reads identity from auth headers, so every page knows who is viewing it (owner, admin, member, viewer).
- Database access: full read/write to
console_dbandconsole_site_db. Cannot reachsite_db.
Build a Console page when: - The output is for your team only. - It needs to query internal data, call connectors, or surface controls. - Customers should never see it.
The public site (external)
The public site is a separate Flask app, on a separate port, running as a separate OS user, with a separate database role. It exists to serve content to people outside your workspace.
- URL pattern:
/<route>for everything. Conventional patterns:/u/<token>for one-off shared reports,/r2s/<token>for reviewed runs,/docs/<slug>for these docs. - Visibility is controlled by a workspace-level toggle (see Modes below).
- Database access: read/write
site_db(it owns it). Read/writeconsole_site_db. Cannot reachconsole_db.
Build a public site page when: - A customer, prospect, or anonymous visitor needs to see something. - You want a shareable URL outside of email or Slack. - The data has already been generated (in Console or by a job) and you are just serving it.
Three modes for the public site
The public site has three states, toggled by an owner or admin from the workspace UI. The agent itself cannot flip these.
- off — nginx returns 403 to everyone. The Flask process is still running; no traffic reaches it.
- authorized — workspace members and explicitly invited guests can view it. Good for review before a launch.
- open — anyone with the URL can view it. Treat every visitor as untrusted.
When mode is open, the agent applies extra defaults: Pydantic validation on every visitor input, no per-visitor connector calls (cache to site_db instead), separate connector approvals for the site surface, and visible output is sanitized before persistence.
Cross-surface communication
The Console and public site live in different processes. They can still cooperate, but only through one explicit channel: the console_site_db database.
- Console writes data (a report, a brief, an artifact) into a table.
- Public site reads that table and renders it at a token-gated URL.
- Site can write back interaction signals (e.g. "the visitor clicked through") that the Console reads.
The agent does NOT try to proxy a Console query through a public route. The REVOKE is at the database layer; it would fail anyway, and it would also be the wrong design.