docs: document dashboard + refresh local dev setup (#1376)

* docs: document dashboard + refresh local dev setup in INSTALLATION

- add the web dashboard (ui/) and its FastAPI backend API to the setup flow
- document dashboard-login OAuth (GITHUB_APP_CLIENT_ID/SECRET, second callback
  URL) as distinct from the LangSmith-brokered agent-runtime OAuth
- add new env vars: DASHBOARD_API_BASE_URL/BASE_URL/JWT_SECRET/ALLOWED_ORIGINS,
  CONFIGURED_ADMINS, X_SERVICE_AUTH_JWT_SECRET, LANGGRAPH_URL, SANDBOX_TYPE,
  REVIEWER_OUTCOMES_DATASET, PUBLIC_REPO_ORG_GATE, SLACK_CLIENT_ID/SECRET/TEAM_ID,
  SLACK_REPO_OWNER/NAME
- add "Sign in with Slack" OIDC account-linking setup
- rewrite local dev: make dev serves 3 graphs + FastAPI on :2024; new step for
  running the UI (bun) on :3000, incl. the required DASHBOARD_ALLOWED_ORIGINS
  CORS setting and cookie wiring
- correct production langgraph.json to three graphs; document Vercel UI deploy
- add dashboard verify + troubleshooting sections
- README: dashboard feature bullet + updated install blurb

* docs: clarify dashboard API setup

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>

---------

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
This commit is contained in:
Johannes du Plessis 2026-06-02 15:55:35 -07:00 • committed by GitHub
parent 5dda8acb7a
commit 0a7fae60cd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 145 additions and 20 deletions

View file

@ -1,7 +1,12 @@
# Installation Guide
This guide walks you through setting up Open SWE end-to-end: local development, GitHub App creation, LangSmith configuration, webhooks, and production deployment.
This guide walks you through setting up Open SWE end-to-end: local development, GitHub App creation, LangSmith configuration, webhooks, the web dashboard, and production deployment.
Open SWE has two runnable pieces:
- **The backend** — a LangGraph app (three graphs: `agent`, `reviewer`, `analyzer`) plus a FastAPI app (`agent.webapp:app`) that owns the webhooks and the dashboard API. Both are served together by `langgraph dev`.
- **The dashboard** — a TanStack Start + Vite web app in `ui/` (package name `open-swe-dashboard`). It's a thin client over the FastAPI dashboard API (`/dashboard/api/*`): GitHub-login, per-user model/profile settings, team defaults, enabled-repo and review-style management, user mappings, and the Agents chat UI. It's optional for pure webhook-driven use, but recommended.
> **The steps are ordered to avoid forward references.** Each step only depends on things you've already completed.
@ -11,6 +16,7 @@ This guide walks you through setting up Open SWE end-to-end: local development,
- [uv](https://docs.astral.sh/uv/) package manager
- [LangGraph CLI](https://langchain-ai.github.io/langgraph/cloud/reference/cli/)
- [ngrok](https://ngrok.com/) (for local development — exposes webhook endpoints to the internet)
- [Bun](https://bun.sh/) (only if you want to run the dashboard UI locally — see step 8). Node 20+ also works, but `ui/bun.lock` is the canonical lockfile.
## 1. Clone and install
@ -56,7 +62,9 @@ Write this down. You'll use it in the callback URL below and again in step 4 whe
2. Fill in:
- **App name**: `open-swe` (or your preferred name)
- **Homepage URL**: This can be any valid URL — it's only shown on the GitHub Marketplace page (which you won't be using). Use something like `https://github.com/langchain-ai/open-swe`
- **Callback URL**: `https://smith.langchain.com/host-oauth-callback/<your-provider-id>` — replace `<your-provider-id>` with the ID you chose in step 3a (e.g. `https://smith.langchain.com/host-oauth-callback/your-org-github-oauth`)
- **Callback URL**: GitHub Apps allow multiple callback URLs (one per line). Add **both**:
1. `https://smith.langchain.com/host-oauth-callback/<your-provider-id>` — replace `<your-provider-id>` with the ID you chose in step 3a (e.g. `https://smith.langchain.com/host-oauth-callback/your-org-github-oauth`). This is the **agent-runtime** OAuth callback, brokered by LangSmith (step 4b).
2. `http://localhost:2024/dashboard/api/auth/callback` — the **dashboard-login** OAuth callback (step 8). For production, also add `https://<your-dashboard-api-url>/dashboard/api/auth/callback`. This is a separate, direct GitHub OAuth flow (not via LangSmith), so it needs its own callback URL.
- **Request user authorization (OAuth) during installation**: ✅ Enable this
- **Webhook URL**: `https://<your-ngrok-url>/webhooks/github` — use the ngrok URL from step 2
- **Webhook secret**: generate one and save it — you'll need it later as `GITHUB_WEBHOOK_SECRET`:
@ -83,6 +91,10 @@ After creating the app:
1. **App ID** — shown at the top of the app's settings page. Save this as `GITHUB_APP_ID`.
2. **Private key** — scroll down to **Private keys** → click **Generate a private key**. A `.pem` file will download. Save its contents as `GITHUB_APP_PRIVATE_KEY`.
3. **Client ID** — shown near the top of the app's settings page (starts with `Iv...`). Save this as `GITHUB_APP_CLIENT_ID`.
4. **Client secret** — under **Client secrets** → **Generate a new client secret**. Save it as `GITHUB_APP_CLIENT_SECRET`.
> `GITHUB_APP_CLIENT_ID` / `GITHUB_APP_CLIENT_SECRET` power the **dashboard login** flow (the direct GitHub OAuth in 3b's second callback URL). They are independent of the LangSmith OAuth provider in step 4b — the dashboard talks to GitHub directly, while the agent runtime resolves per-user tokens through LangSmith.
### 3d. Install the app on your repositories
@ -118,7 +130,7 @@ Open SWE uses [LangSmith](https://smith.langchain.com/) for:
### 4b. Configure GitHub OAuth (optional but recommended)
This lets each user authenticate with their own GitHub account. Without it, all operations use the GitHub App's installation token (a shared bot identity).
This is the **agent-runtime** OAuth provider: it lets each agent run authenticate with the triggering user's own GitHub account, brokered by LangSmith. (It is separate from the dashboard-login OAuth, which uses `GITHUB_APP_CLIENT_ID`/`GITHUB_APP_CLIENT_SECRET` directly — see step 3c.) Without it, all agent operations use the GitHub App's installation token (a shared bot identity).
**What this affects:**
- **With per-user OAuth**: PRs and commits show the triggering user's identity; each user's GitHub permissions are respected
@ -299,7 +311,8 @@ Users can also override the team/project mapping per-comment by including `repo:
},
"oauth_config": {
"redirect_urls": [
"https://smith.langchain.com/host-oauth-callback/<your-provider-id>"
"https://smith.langchain.com/host-oauth-callback/<your-provider-id>",
"http://localhost:2024/dashboard/api/slack/callback"
],
"scopes": {
"bot": [
@ -350,7 +363,17 @@ Users can also override the team/project mapping per-comment by including `repo:
**Default repo:**
Slack messages are routed to the default repo (`DEFAULT_REPO_OWNER`/`DEFAULT_REPO_NAME` — see step 6) unless the user specifies one with `repo:owner/name` in their message.
Slack messages are routed to the Slack default repo (`SLACK_REPO_OWNER`/`SLACK_REPO_NAME`, falling back to `DEFAULT_REPO_OWNER`/`DEFAULT_REPO_NAME` — see step 6) unless the user specifies one with `repo:owner/name` in their message.
**"Sign in with Slack" account linking (optional):**
The dashboard can let a user link their Slack identity to their GitHub login via Slack OIDC ("Sign in with Slack"). This is what lets a Slack-triggered run resolve to the right GitHub user. To enable it:
1. The manifest above already registers the OIDC redirect (`.../dashboard/api/slack/callback`). Under **OpenID Connect** (or **Sign in with Slack**) make sure the `openid`, `email`, and `profile` user scopes are available.
2. From **Basic Information → App Credentials**, save the app's **Client ID** as `SLACK_CLIENT_ID` and **Client Secret** as `SLACK_CLIENT_SECRET`.
3. (Optional) Set `SLACK_TEAM_ID` (your workspace ID, `T...`) to restrict linking to a single workspace.
If `SLACK_CLIENT_ID`/`SLACK_CLIENT_SECRET` are unset, the "Sign in with Slack" link is simply disabled; the rest of Slack triggering still works.
## 6. Environment variables
@ -381,10 +404,18 @@ GITHUB_APP_INSTALLATION_ID="" # From step 3d
# === GitHub Webhook (required) ===
GITHUB_WEBHOOK_SECRET="" # The secret you generated in step 3b
# === GitHub OAuth via LangSmith (optional) ===
# Without these, all operations use the GitHub App's bot token.
# With these, each user authenticates with their own GitHub account.
# === Dashboard GitHub OAuth (required for the dashboard) ===
# Direct GitHub OAuth used by the dashboard login flow (not via LangSmith).
GITHUB_APP_CLIENT_ID="" # From step 3c
GITHUB_APP_CLIENT_SECRET="" # From step 3c
# === Agent-runtime GitHub OAuth via LangSmith (optional) ===
# Without these, all agent operations use the GitHub App's bot token.
# With these, each agent run authenticates as the triggering user.
GITHUB_OAUTH_PROVIDER_ID="" # The provider ID from steps 3a / 4b
# Secret used to mint short-lived service JWTs that ask LangSmith to resolve a
# specific user's GitHub token. Needed for per-user token resolution in deployed mode.
X_SERVICE_AUTH_JWT_SECRET=""
# === Repo Allowlist (optional) ===
# Comma-separated list of GitHub orgs the agent is allowed to operate on.
@ -403,6 +434,28 @@ ALLOWED_GITHUB_REPOS="" # e.g. "some-user/their-repo,another-org/
DEFAULT_REPO_OWNER="" # Default GitHub org (e.g. "my-org")
DEFAULT_REPO_NAME="" # Default GitHub repo (e.g. "my-repo")
# === Dashboard (required to run the web dashboard) ===
# Public URL that browsers use for /dashboard/api/* and OAuth callbacks.
# Use the FastAPI backend URL for local/cross-origin direct API calls.
# Use the dashboard frontend URL when a same-origin frontend rewrite proxies /dashboard/api/*.
# Its scheme drives cookie security: http:// => SameSite=Lax (local);
# https:// => Secure + SameSite=None (production).
DASHBOARD_API_BASE_URL="http://localhost:2024"
# Public base URL of the dashboard frontend (the ui/ app). Default post-login redirect.
DASHBOARD_BASE_URL="http://localhost:3000"
# HMAC secret for all dashboard JWTs (session cookie, OAuth state, account-link tokens).
DASHBOARD_JWT_SECRET="" # Generate with: openssl rand -hex 32
# Comma-separated origins allowed for credentialed CORS and post-login redirects.
# Required whenever the frontend and API are on different origins — including local
# dev (UI :3000 -> API :2024 is cross-origin). CORS is only enabled when this is set.
DASHBOARD_ALLOWED_ORIGINS="http://localhost:3000" # prod: your frontend origin(s)
# Comma-separated email allowlist for admin dashboard endpoints (matched against the
# logged-in user's GitHub email). Empty => nobody is an admin.
CONFIGURED_ADMINS="" # e.g. "alice@my-org.com,bob@my-org.com"
# URL of the LangGraph server the FastAPI side calls to trigger/stream runs.
# Defaults to http://localhost:2024 locally; set to your deployment URL in prod.
LANGGRAPH_URL="http://localhost:2024"
# === Linear (if using Linear trigger) ===
LINEAR_API_KEY="" # From step 5
LINEAR_WEBHOOK_SECRET="" # From step 5
@ -412,11 +465,28 @@ SLACK_BOT_TOKEN="" # From step 5
SLACK_BOT_USER_ID=""
SLACK_BOT_USERNAME=""
SLACK_SIGNING_SECRET=""
# Optional: Slack-specific default repo (falls back to DEFAULT_REPO_OWNER/NAME).
SLACK_REPO_OWNER=""
SLACK_REPO_NAME=""
# Optional: "Sign in with Slack" account linking (GitHub <-> Slack). See step 5.
SLACK_CLIENT_ID=""
SLACK_CLIENT_SECRET=""
SLACK_TEAM_ID="" # Optional; restrict linking to one workspace (T...)
# === Exa (optional — enables web search tool) ===
EXA_API_KEY="" # From https://dashboard.exa.ai
# === Reviewer / Analyzer (optional) ===
# LangSmith dataset where reviewer finding outcomes are recorded and read back by
# the analyzer. Defaults to "openswe-reviewer-outcomes" if unset.
REVIEWER_OUTCOMES_DATASET=""
# Single GitHub org whose members may trigger the agent on *public* repos.
# Empty => no public-repo gate (back-compat). Distinct from ALLOWED_GITHUB_ORGS.
PUBLIC_REPO_ORG_GATE=""
# === Sandbox (optional) ===
# Provider: langsmith (default), modal, daytona, runloop, or local. See CUSTOMIZATION.md.
SANDBOX_TYPE="langsmith"
DEFAULT_SANDBOX_SNAPSHOT_ID="" # Required when SANDBOX_TYPE=langsmith (see step 4c)
DEFAULT_SANDBOX_SNAPSHOT_FS_CAPACITY_BYTES="" # Root FS size in bytes (default: 32 GiB)
DEFAULT_SANDBOX_VCPUS="" # vCPUs per sandbox (default: 4)
@ -452,15 +522,16 @@ invalidating already-stored GitHub tokens:
and the user will be re-prompted to authenticate — same UX as if the thread
had never authed.
## 7. Start the server
## 7. Start the backend
Make sure ngrok is still running from step 2, then start the LangGraph server in a second terminal:
Make sure ngrok is still running from step 2, then start the backend in a second terminal:
```bash
uv run langgraph dev --no-browser
make dev # uv run langgraph dev
# or: uv run langgraph dev --no-browser
```
The server runs on `http://localhost:2024` with these endpoints:
`langgraph dev` serves **all three graphs** (`agent`, `reviewer`, `analyzer`) *and* the FastAPI app (`agent.webapp:app`) together on `http://localhost:2024`. The FastAPI app owns both the webhooks and the dashboard API:
| Endpoint | Purpose |
|---|---|
@ -469,9 +540,35 @@ The server runs on `http://localhost:2024` with these endpoints:
| `GET /webhooks/linear` | Linear webhook verification |
| `POST /webhooks/slack` | Slack event webhooks |
| `GET /webhooks/slack` | Slack webhook verification |
| `GET /dashboard/api/auth/login` | Dashboard GitHub OAuth login |
| `GET /dashboard/api/auth/callback` | Dashboard GitHub OAuth callback (registered on the App in step 3b) |
| `GET /dashboard/api/*` | Dashboard API (profiles, team settings, repos, review styles, threads, …) |
| `GET /health` | Health check |
## 8. Verify it works
> `make run` (`uvicorn agent.webapp:app --port 8000`) serves the FastAPI app **without** the LangGraph runtime, on port 8000. The dashboard's Agents chat features call LangGraph, so for full local dev use `make dev` on `:2024`, not `make run`.
## 8. Run the dashboard (optional)
The dashboard is the web app in `ui/`. It's a static TanStack Start client that calls the FastAPI dashboard API from step 7. Run it in a third terminal:
```bash
cd ui
bun install
cat > .env <<'EOF'
VITE_DASHBOARD_API_BASE_URL="http://localhost:2024"
EOF
bun run dev # vite dev --port 3000 -> http://localhost:3000
```
The dashboard needs `VITE_DASHBOARD_API_BASE_URL` in `ui/.env` pointing at the backend for local dev. The file is intentionally untracked because `.env*` files are gitignored.
The client calls `${VITE_DASHBOARD_API_BASE_URL}/dashboard/api/*` with `credentials: "include"`, so the backend's `osw_session` cookie rides along. Because the UI (`:3000`) and API (`:2024`) are different origins, the backend needs **CORS** enabled for the UI origin — set `DASHBOARD_ALLOWED_ORIGINS="http://localhost:3000"` (CORS is off unless this is set). Keep `DASHBOARD_API_BASE_URL` on an `http://` URL locally so the cookie uses `SameSite=Lax` rather than `Secure`.
For the dashboard login to succeed, you need (from steps 3c / 6): `GITHUB_APP_CLIENT_ID`, `GITHUB_APP_CLIENT_SECRET`, `DASHBOARD_JWT_SECRET`, `DASHBOARD_API_BASE_URL`, `DASHBOARD_BASE_URL`, and `DASHBOARD_ALLOWED_ORIGINS`. To reach the admin pages (user mappings, etc.), add your GitHub email to `CONFIGURED_ADMINS`.
Other UI scripts: `bun run build`, `bun run typecheck`, `bun run lint`, `bun run test`.
## 9. Verify it works
### GitHub
@ -497,21 +594,31 @@ The server runs on `http://localhost:2024` with these endpoints:
2. Mention the bot: `@open-swe what's in the repo?`
3. You should see a reply in the thread with the agent's response.
## 9. Production deployment
### Dashboard
For production, deploy the agent on [LangGraph Cloud](https://langchain-ai.github.io/langgraph/cloud/) instead of running locally:
1. With the backend (step 7) and UI (step 8) both running, open `http://localhost:3000`
2. Click **Sign in with GitHub** — you'll be sent through the GitHub OAuth flow and back to the dashboard
3. You should land logged-in and be able to see your profile/settings. If your email is in `CONFIGURED_ADMINS`, the **Admin** pages (e.g. User mappings) are available.
## 10. Production deployment
Production runs the backend and dashboard separately.
**Backend** — deploy on [LangGraph Cloud / Platform](https://langchain-ai.github.io/langgraph/cloud/):
1. Push your code to a GitHub repository
2. Connect the repo to LangGraph Cloud
3. Set all environment variables from step 6 in the deployment config
4. Update your webhook URLs (Linear, Slack, GitHub App) to point to your production URL (replace the ngrok URL)
3. Set all environment variables from step 6 in the deployment config. Set `DASHBOARD_BASE_URL` and `LANGGRAPH_URL` to your production URLs (all `https://`). Set `DASHBOARD_API_BASE_URL` to the URL browsers use for dashboard API requests and OAuth callbacks: either the backend URL for direct cross-origin calls, or the dashboard/Vercel URL when a same-origin rewrite proxies `/dashboard/api/*`.
4. Update your webhook URLs (Linear, Slack, GitHub App) and the GitHub App / Slack OAuth callback URLs to your production URLs (replace the ngrok / localhost values). The dashboard GitHub App callback must be `<DASHBOARD_API_BASE_URL>/dashboard/api/auth/callback`.
The `langgraph.json` at the project root already defines the graph entry point and HTTP app:
The `langgraph.json` at the project root defines the three graphs and the HTTP app:
```json
{
"graphs": {
"agent": "agent.server:get_agent"
"agent": "agent.server:get_agent",
"reviewer": "agent.reviewer:get_reviewer_agent",
"analyzer": "agent.analyzer:get_analyzer"
},
"http": {
"app": "agent.webapp:app"
@ -519,6 +626,10 @@ The `langgraph.json` at the project root already defines the graph entry point a
}
```
**Dashboard** — the `ui/` app deploys to [Vercel](https://vercel.com/). The recommended production setup uses **same-origin** requests to `/dashboard/api/*` (leave `VITE_DASHBOARD_API_BASE_URL` empty), and `ui/vercel.json` rewrites those to the hosted LangGraph deployment. In this mode, set both `DASHBOARD_API_BASE_URL` and the GitHub App dashboard callback URL to the Vercel/dashboard origin (for example, `https://your-dashboard.vercel.app/dashboard/api/auth/callback`). The OAuth callback response then sets the `osw_session` cookie on the dashboard host, and later same-origin `/dashboard/api/*` requests include it. Update the rewrite `destination` in `ui/vercel.json` to your own LangGraph deployment URL.
Alternatively, you can run the dashboard as a direct cross-origin client: set `VITE_DASHBOARD_API_BASE_URL` to the hosted backend origin, set `DASHBOARD_API_BASE_URL` to that same backend origin, and include the dashboard origin in `DASHBOARD_ALLOWED_ORIGINS`.
## Troubleshooting
### Webhook not receiving events
@ -534,6 +645,19 @@ The `langgraph.json` at the project root already defines the graph entry point a
- Ensure the GitHub App is installed on the target repositories
- Check that the private key includes the full `-----BEGIN RSA PRIVATE KEY-----` and `-----END RSA PRIVATE KEY-----` lines
### Dashboard login fails or won't stay logged in
- `500 GITHUB_APP_CLIENT_ID not configured` (or client secret): set `GITHUB_APP_CLIENT_ID` / `GITHUB_APP_CLIENT_SECRET` (step 3c) and `DASHBOARD_JWT_SECRET`.
- OAuth `redirect_uri` mismatch: the GitHub App must list `<DASHBOARD_API_BASE_URL>/dashboard/api/auth/callback` as a callback URL (step 3b). Locally that's `http://localhost:2024/dashboard/api/auth/callback`.
- Login redirects but the session doesn't stick: this is almost always a cookie problem. Locally, keep `DASHBOARD_API_BASE_URL` on `http://` (so cookies are `SameSite=Lax`); in prod use `https://` for both API and frontend and add the frontend origin to `DASHBOARD_ALLOWED_ORIGINS`.
- Login rejected with an org error: `ALLOWED_GITHUB_ORGS` gates dashboard login (and requires the App's Organization → Members: Read-only permission). See step 5.
- Admin pages 403: add your GitHub email to `CONFIGURED_ADMINS`.
### Dashboard UI can't reach the backend
- Confirm the backend is running via `make dev` on `:2024` (not `make run` on `:8000`).
- Confirm `ui/.env` has `VITE_DASHBOARD_API_BASE_URL=http://localhost:2024`. If it's empty, the UI falls back to relative `/dashboard/api/*`, which only works behind the Vercel rewrite, not in local dev.
### Sandbox creation failures
- Verify `LANGSMITH_API_KEY_PROD` is set and valid

View file

@ -134,12 +134,13 @@ This is an area where you can extend Open SWE for your org: add deterministic CI
- **GitHub OAuth built-in** — authenticates with your GitHub account automatically
- **Opens PRs automatically** — commits changes and opens a draft PR when done, linked back to your ticket
- **Subagent support** — the agent can spawn child agents for parallel subtasks
- **Web dashboard** — a companion app (in `ui/`) for GitHub login, per-user model/profile settings, team defaults, enabled-repo and review-style management, user mappings, and an Agents chat UI
---
## Getting Started
- **[Installation Guide](INSTALLATION.md)** — GitHub App creation, LangSmith, Linear/Slack/GitHub triggers, and production deployment
- **[Installation Guide](INSTALLATION.md)** — local dev (backend + dashboard), GitHub App creation, LangSmith, Linear/Slack/GitHub triggers, and production deployment
- **[Customization Guide](CUSTOMIZATION.md)** — swap the sandbox, model, tools, triggers, system prompt, and middleware for your org
## License