Static chat widget example

This walkthrough provisions a static-site support chat using ArcFlow Relay and published workflows. The browser bundle calls runPublished() only; agents, memory, and knowledge live in the dashboard or admin API.

Primary example: Static chat widget walkthrough. Index: Static chat widget walkthrough.

What this example demonstrates

Production static sites never embed LLM keys or workflow definitions in client JavaScript. The operator uploads knowledge, publishes a chat workflow, and the frontend developer wires two env vars plus a thin UI. Relay validates Origin and proxies runs to arcflow-server.

Prerequisites

ItemRequired
Server + Relay stackdocker compose -f docker/docker-compose.server.yml up -d
Site provisionedDashboard or scripts/static-provision-site.sh
Node.js18+ for Vite dev server
Allowed originsInclude http://localhost:5173 and production domain
Tutorial trackTrack F

Step 1: Operator setup (dashboard or scripts)

From repository root:

bash
docker compose -f docker/docker-compose.server.yml up -d
bash scripts/static-provision-site.sh
export SITE_ID=... # from script output
export TEXT_FILE=examples/static/chat-rag/kb.txt
bash scripts/static-ingest-knowledge.sh
bash scripts/static-publish-chat.sh

Copy relay URL and site token for frontend env vars.

Step 2: Configure frontend env

In examples/static/chat-rag/:

bash
VITE_ARCFLOW_RELAY_URL=http://localhost:8090/v1/sites/s_dev
VITE_ARCFLOW_SITE_TOKEN=st_live_devtoken

Use values from your site record, not placeholders, in real deployments.

Step 3: Run the chat UI locally

bash
cd examples/static/chat-rag
npm install
npm run dev

Open http://localhost:5173 and send a message. Traffic goes to Relay with Bearer site token and Origin header.

Production client pattern from src/main.ts:

typescript
import { ArcFlowClient } from "@arcflow/static";

const client = new ArcFlowClient({
 baseUrl: import.meta.env.VITE_ARCFLOW_RELAY_URL,
 apiKey: import.meta.env.VITE_ARCFLOW_SITE_TOKEN,
 mode: "relay",
});

await client.runPublished("chat", "^1.0.0", userMessage);

Step 4: Verify origin enforcement

Request from a disallowed origin should fail at Relay (403 or CORS rejection). Add your test origin in Sites allowed origins, retry, and confirm success.

Optional automated check:

bash
pytest examples/static/chat-rag/test_static.py -q

Expected output

Browser chat returns assistant replies grounded on ingested knowledge (stub or real provider depending on server config). Network tab shows POST to Relay /v1/sites/{id}/runs with 201 response and subsequent poll or stream per client settings.

Pass criteria:

CheckExpected
Chat message succeeds from allowed origin201 from Relay
Disallowed origin blockedError before server execution
No secrets in bundleOnly site token env at build time

Trace events you should see

Fetch trace via Relay or server (operator tools):

Event kindWhen
WorkflowStartedPublished chat workflow run
MemoryRetrievedWhen knowledge base matches query
StepCompletedChat agent step
WorkflowCompletedSuccessful reply

Traces are metadata only (trace data policy). End users do not receive raw trace JSON in the widget unless you add operator tooling.

Troubleshooting

SymptomLikely causeFix
CORS or 403 from RelayOrigin not allowlistedAdd exact scheme + host in site settings
Empty answersKnowledge not ingestedRe-run ingest script or dashboard upload
401 on RelayWrong site tokenRegenerate token; update env
Agents defined in browserWrong integration pathRemove inline Agent code; use publish flow only

Internal dev only: src/main-dev-direct.ts bypasses Relay for engine debugging. Do not ship to production.

ResourceLink
Relay BYOrelay-byo-deployment.md
Multi-turn intake botonline-application-chatbot
Tutorial trackTrack F