> ## Documentation Index
> Fetch the complete documentation index at: https://docs.veadk.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# VeADK Frontend

VeADK ships a production-grade React frontend — an enterprise agent-application workbench that talks to agents over the Google ADK API server: create, debug, manage, and use agents from the UI. `veadk frontend` is a self-contained launcher: in the default mode it serves this React UI and the agent API from a single process on the same origin, so there is no separate backend to deploy and no cross-origin setup.

## What it can do

* **Create agents**: use a conversational, custom, or template flow to produce a runnable VeADK project (`agent.py`, `requirements.txt`, and so on) that you can preview, edit, and download. The workflow entry is marked as coming soon and cannot be selected.
* **Chat and debug**: multi-turn conversations showing thinking, tool calls, token usage and timing; conversations also render the [A2UI](/productions/veadk/archives/1.0.1/en/components/frontend/a2ui) rich-UI cards an agent returns.
* **Agent picker**: switch agents from the top-left; hover an agent to see its model and mounted tools.
* **Skill center**: browse and discover reusable skills to use when creating agents.
* **Session history**: auto-saved, time-sorted, reopen or delete.
* **Smart search**: the *Session* source full-text-searches the current agent's history; the *Web* source calls the agent's mounted web-search tool live, using credentials from the server's environment variables.
* **Add an AgentKit agent**: paste a URL and API key to connect a remote agent over the ADK protocol; it then appears in the picker.
* **Tracing**: view the call flame graph for the current session.
* **Login**: SSO or a local username.

## Run

Build the UI once, then serve the UI and the agent API together from a single process.

<Steps>
  <Step title="Build the UI">
    ```bash lines theme={null}
    cd frontend && npm install && npm run build
    ```

    The build output is served as the UI by `veadk frontend`. When VeADK is installed via pip, a built UI is already bundled in the package, so you can run it directly.
  </Step>

  <Step title="Launch">
    ```bash lines theme={null}
    veadk frontend --agents-dir examples
    # open http://127.0.0.1:8000
    ```
  </Step>
</Steps>

### Dev mode (hot reload)

In dev mode `veadk frontend` serves only the agent API and allows CORS from the Vite dev server (`http://localhost:5173`); the UI runs separately under Vite with hot reload.

```bash lines theme={null}
veadk frontend --dev --agents-dir examples   # API only, CORS for Vite
cd frontend && npm run dev                    # http://localhost:5173, proxies API
```

## The `veadk frontend` command

| Option | Default | Description |
| :- | :- | :- |
| `--agents-dir` | `.` | Directory of agent apps; each subdirectory exposes a `root_agent`. |
| `--frontend-dir` | packaged build, falling back to `./frontend/dist` | Override the built React UI directory. Priority: the explicitly passed directory, then the packaged UI, then `./frontend/dist` relative to the current directory. |
| `--host` | `127.0.0.1` | Address to bind. |
| `--port` | `8000` | Port to bind. |
| `--dev` | off | Dev mode: serve the API only and allow CORS from the Vite dev server (`http://localhost:5173`). |
| `--oauth2-user-pool` | — | VeIdentity User Pool name. Enables SSO when set together with the client. |
| `--oauth2-user-pool-client` | — | VeIdentity User Pool client name. |
| `--oauth2-user-pool-uid` | env `OAUTH2_USER_POOL_ID` | Specify the pool by UID instead of name. |
| `--oauth2-user-pool-client-uid` | env `OAUTH2_USER_POOL_CLIENT_ID` | Specify the client by UID instead of name. |
| `--oauth2-redirect-uri` | `http://{host}:{port}/oauth2/callback` | OAuth2 callback URL (env `OAUTH2_REDIRECT_URI`). Set this when deploying behind a public host or runtime. |
| `--oauth2-provider` | `veidentity` when a user pool is configured | SSO provider id (env `OAUTH2_PROVIDER`). One of `veidentity`, `github`, `google`, or a custom name. |
| `--oauth2-provider-label` | provider's built-in label | Display label for the login button (env `OAUTH2_PROVIDER_LABEL`). |
| `--auth-mode` | `frontend` | Authentication mode: `frontend` or `gateway`; can also be set with `VEADK_FRONTEND_AUTH_MODE`. |

<Note>
  Outside dev mode, if the built UI directory is not found, the command fails and asks you to run `npm run build` first (or use `--dev` with the Vite dev server).
</Note>

## Authentication

Sessions and memory are scoped by the ADK `user_id`, which comes from the signed-in user. On startup the command loads a `.env` file from the current directory or its parents, so the environment variables below can be placed in `.env`.

**Gateway authentication** — use `gateway` mode when the service runs behind an AgentKit Runtime gateway that has already authenticated the user:

```bash lines theme={null}
veadk frontend --agents-dir examples --auth-mode gateway
```

This mode does not run the frontend's built-in OAuth2 login. It obtains the user identity from the `Authorization: Bearer <JWT>` header forwarded by the upstream gateway.

<Warning>
  `gateway` mode trusts that the upstream gateway has already validated the JWT and does not verify its signature again. Use it only when every request must pass through a trusted authentication gateway and clients cannot reach VeADK Frontend directly.
</Warning>

**SSO** — enable by passing the pool and client. The UI shows a login page and redirects through the identity provider, then uses the user identifier returned by the userinfo endpoint as the `user_id`. The pool and client can be given either by name or by UID.

```bash lines theme={null}
veadk frontend --agents-dir examples \
--oauth2-user-pool "your-user-pool-name" --oauth2-user-pool-client "your-user-pool-client-name"
# or by UID (env OAUTH2_USER_POOL_ID / OAUTH2_USER_POOL_CLIENT_ID)
# --oauth2-user-pool-uid <id> --oauth2-user-pool-client-uid <id>
```

Enabling VeIdentity SSO requires the process to have access to Volcengine credentials. The middleware protects the API while exempting the UI shell, `/web/auth-config`, `/favicon.ico`, `/assets`, and `/skillhub`, so the app loads and shows its own login page instead of being bounced to the identity provider. The login button's label and icon are config-driven.

**Third-party / custom OAuth2 (env vars)** — without a VeIdentity user pool, set `OAUTH2_CLIENT_ID` (and the secret) to enable GitHub, Google, or any OIDC login. Endpoints are resolved in this order: a built-in preset (`OAUTH2_PROVIDER=github` or `google`), then OIDC discovery (set `OAUTH2_ISSUER`), then explicit endpoints (`OAUTH2_AUTHORIZE_URL`, etc.).

| Env var | Description |
| :- | :- |
| `OAUTH2_PROVIDER` | Provider id: `github`, `google`, or a custom name. Drives the login button label and the preset. |
| `OAUTH2_CLIENT_ID` / `OAUTH2_CLIENT_SECRET` | OAuth2 client credentials. Setting `OAUTH2_CLIENT_ID` enables the generic provider. |
| `OAUTH2_ISSUER` | OIDC issuer base URL; endpoints are auto-discovered, e.g. `https://accounts.google.com`. |
| `OAUTH2_AUTHORIZE_URL` / `OAUTH2_TOKEN_URL` / `OAUTH2_USERINFO_URL` | Explicit endpoints for a non-OIDC provider. |
| `OAUTH2_SCOPE` | Override the requested scopes. |
| `OAUTH2_PROVIDER_LABEL` | Override the login button text. |
| `OAUTH2_REDIRECT_URI` | Callback URL. Set this when deploying behind a public host or runtime, and register the same value in your OAuth app; defaults to `http://{host}:{port}/oauth2/callback` locally. |

The GitHub preset only needs the client credentials:

```bash lines theme={null}
export OAUTH2_PROVIDER=github
export OAUTH2_CLIENT_ID="your-github-oauth-client-id"
export OAUTH2_CLIENT_SECRET="your-github-oauth-client-secret"
export OAUTH2_REDIRECT_URI=http://127.0.0.1:8000/oauth2/callback
veadk frontend --agents-dir examples
```

Google is the same with `OAUTH2_PROVIDER=google`; for any OIDC provider (Keycloak, Auth0, Okta, and so on) set `OAUTH2_ISSUER` plus the client credentials. A full example lives at `examples/front_with_sso/`.

<Warning>
  When deploying to a runtime or public host, the OAuth callback must point at an externally reachable URL: set `OAUTH2_REDIRECT_URI` to the public callback URL and register the same value in your OAuth app. The cookie `Secure` flag is enabled automatically when that URL is HTTPS.
</Warning>

**No SSO (local username)** — without those flags, the login page asks for a username (letters and digits, up to 16 characters), stored locally and used as the `user_id`. In this case the server always reports an unauthenticated state and an empty provider list, and the app renders its local username login.

<Note>
  Login state is cached: SSO via the `veadk_session` cookie, local mode via `localStorage`. The session itself is created lazily on the first message, not on page load. Logout is a local logout — it clears the session and returns to the login page.
</Note>

## Rendering flow

The frontend talks to the Google ADK API server: it lists available agents, creates a session, and receives the agent's output as a live stream. When the agent returns an A2UI message, the frontend parses its UI instructions, creates and incrementally updates the corresponding surface, then renders the matching React components by type. A registry maps each component type to a renderer, so adding a new component type only requires registering a renderer for it.

## Adding a custom (enterprise) component

A custom component has two halves that share one catalog id. For the backend half, see [A2UI](/productions/veadk/archives/1.0.1/en/components/frontend/a2ui#custom-components); the frontend half is below.

**Frontend half** — drop in a new directory; it auto-registers, with no central edit:

```text lines theme={null}
src/a2ui/components/RevenueChart/
├── RevenueChart.tsx
└── index.ts
```

```ts title="src/a2ui/components/RevenueChart/index.ts" lines theme={null}
import { register } from "../../registry";
import { RevenueChart } from "./RevenueChart";
register("RevenueChart", RevenueChart);
```

```tsx title="src/a2ui/components/RevenueChart/RevenueChart.tsx" lines theme={null}
import type { ComponentRendererProps } from "../../registry";

export function RevenueChart({ node, ctx }: ComponentRendererProps) {
  const series = ctx.resolve(node.series as any);
  return <div className="corp-chart">{/* render series */}</div>;
}
```

A newly added component directory is discovered and registered automatically, with no central configuration file to edit.

<Note>
  Unknown components with no registered renderer fall back to a collapsible JSON view, so a catalog/renderer mismatch never crashes the UI.
</Note>
