> ## 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 自带一个生产级 React 前端——一个面向企业的智能体应用工作台，通过 Google ADK API Server 与智能体通信：在界面中创建、调试、管理智能体，并将其接入使用。`veadk frontend` 是一个自包含的启动器：在默认模式下，它以单个进程同时提供这套 React 界面与智能体 API，两者同源，因此无需单独部署后端，也无需处理跨域配置。

## 功能一览

* **创建智能体**：当前可通过自定义配置创建智能体，产出可运行的 VeADK 项目（`agent.py`、`requirements.txt` 等），并可在线预览、编辑与下载。智能模式、模板和工作流入口显示为「敬请期待」，暂不可用。
* **多模态消息**：上传图片、TXT、Markdown、PDF 和视频；用户附件与模型返回的媒体均可预览并随历史会话重新加载。
* **对话与调试**：与智能体多轮对话，展示思考过程、工具调用、Token 与用时；对话中还会渲染智能体返回的 [A2UI](/productions/veadk/archives/1.0.5/zh/components/frontend/a2ui) 富界面卡片。
* **智能体选择器**：左上角切换智能体；悬停可查看该智能体的模型与挂载的工具。
* **技能与子智能体**：输入 `/` 选择当前智能体挂载的技能，输入 `@` 把本轮任务交给可选的子智能体。
* **技能中心**：从 Skill Hub、本地上传或 AgentKit SkillSpace 选择技能，供创建智能体时使用。
* **历史会话**：自动保存、按时间排序，可重新打开或删除。
* **智能搜索**：「会话」源在当前智能体的历史消息中做全文检索；「网页」源调用该智能体挂载的联网搜索工具实时检索，使用服务端环境变量里的凭据。
* **添加 AgentKit 智能体**：填入访问地址与 API Key，按 ADK 协议接入远程智能体，接入后出现在选择器中。
* **Studio 部署**：在同一工作台中检查生成代码，配置地域、消息渠道、网络与环境变量，然后部署到 AgentKit 并查看任务状态。
* **Tracing 观测**：查看本次会话的调用火焰图。
* **登录**：支持 SSO 或本地用户名。

## 完成工具 OAuth 授权

当 MCP 或其他工具需要 OAuth 凭证时，Frontend 会在对话中显示授权卡片。选择授权后，浏览器会打开身份提供方页面；授权回调返回 Frontend 后，当前工具调用会自动继续，无需重新发送消息。若回调无法由当前页面自动读取，界面会要求粘贴完整的回调 URL。

身份提供方中登记的回调 URL 必须与工具配置一致，并指向当前 Frontend 可访问的地址。浏览器阻止授权窗口时，应允许本站打开弹窗后重试。

## 运行

先构建前端，再用一条命令在单个进程中同时提供界面与智能体 API。

<Steps>
  <Step title="构建前端">
    ```bash lines theme={null}
    cd frontend && npm install && npm run build
    ```

    构建产物会作为界面被 `veadk frontend` 提供。使用 pip 安装 VeADK 时，包内已内置一份构建产物，可直接运行。
  </Step>

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

### 开发模式（热更新）

开发模式下 `veadk frontend` 只提供智能体 API，并为 Vite 开发服务器（`http://localhost:5173`）放行 CORS；界面则由 Vite 单独以热更新方式运行。

```bash lines theme={null}
veadk frontend --dev --vite --agents-dir examples   # 仅 API，为 Vite 放行 CORS
cd frontend && npm run dev                    # http://localhost:5173，代理 API
```

## `veadk frontend` 命令

| 选项 | 默认值 | 说明 |
| :- | :- | :- |
| `--agents-dir` | `.` | 智能体应用目录，每个子目录暴露一个 `root_agent`。 |
| `--frontend-dir` | 包内置构建产物，回退至 `./frontend/dist` | 覆盖已构建 React 界面所在目录。优先使用显式传入的目录，其次为包内置界面，最后回退至相对当前目录的 `./frontend/dist`。 |
| `--host` | `127.0.0.1` | 监听地址。 |
| `--port` | `8000` | 监听端口。 |
| `--dev` | 关闭 | 在智能体选择器中加载本地智能体，而不是云端 AgentKit Runtime。 |
| `--vite` | 关闭 | 仅提供 API，并允许 Vite 开发服务器跨域访问；用于开发 React 前端。 |
| `--oauth2-user-pool` | — | VeIdentity 用户池名称。与客户端同时设置后启用 SSO。 |
| `--oauth2-user-pool-client` | — | VeIdentity 用户池客户端名称。 |
| `--oauth2-user-pool-uid` | 环境变量 `OAUTH2_USER_POOL_ID` | 用 UID 代替名称指定用户池。 |
| `--oauth2-user-pool-client-uid` | 环境变量 `OAUTH2_USER_POOL_CLIENT_ID` | 用 UID 代替名称指定客户端。 |
| `--oauth2-redirect-uri` | `http://{host}:{port}/oauth2/callback` | OAuth2 回调地址，环境变量 `OAUTH2_REDIRECT_URI`。部署到公网或 runtime 时需设置。 |
| `--oauth2-provider` | `veidentity`（配置了用户池时） | SSO provider 标识，环境变量 `OAUTH2_PROVIDER`。可取 `veidentity`、`github`、`google` 或自定义名称。 |
| `--oauth2-provider-label` | provider 内置文案 | 登录按钮的显示文案，环境变量 `OAUTH2_PROVIDER_LABEL`。 |
| `--auth-mode` | `frontend` | `frontend` 由本服务处理 OAuth2；`gateway` 信任上游网关验证并转发的 JWT。 |
| `--generated-agent-test-run-ttl` | `1800` | Studio 生成智能体的临时调试进程保留秒数。 |
| `--open / --no-open` | `--no-open` | 服务启动后是否打开系统浏览器；`--vite` 模式下忽略。 |

<Note>
  非开发模式下，若未找到已构建的界面目录，命令会报错并提示先执行 `npm run build`。开发 React 前端时使用 `--vite`，并可同时使用 `--dev` 加载本地智能体。
</Note>

## 多模态附件与存储

输入框支持 PNG、JPEG、WebP、GIF、TXT、Markdown、PDF、MP4、WebM 和 QuickTime，默认单文件上限为 20 MB。PDF 会在模型调用前渲染为逐页图片；相关依赖从 1.0.5 起默认安装。

附件正文与 ADK Session 分开保存，Session Event 仅记录稳定引用。默认写入本地临时目录；需要跨进程保留时可改用 TOS：

| 环境变量 | 默认值 | 说明 |
| - | - | - |
| `VEADK_MEDIA_STORAGE` | `local` | `local` 或 `tos`。 |
| `VEADK_MEDIA_LOCAL_DIR` | `/tmp/veadk-media` | 本地媒体根目录。 |
| `VEADK_MEDIA_MAX_FILE_BYTES` | `20971520` | 单文件与模型输出的字节上限。 |
| `VEADK_MEDIA_TOS_PREFIX` | `veadk-media` | TOS 对象 Key 前缀。 |
| `DATABASE_TOS_BUCKET` | — | TOS Bucket，使用 `tos` 时必填。 |
| `DATABASE_TOS_REGION` | 按云环境推导 | TOS 地域。 |

```bash lines theme={null}
export VEADK_MEDIA_STORAGE=tos
export DATABASE_TOS_BUCKET="your-bucket"
export DATABASE_TOS_REGION=cn-beijing
export VOLCENGINE_ACCESS_KEY="your-access-key"
export VOLCENGINE_SECRET_KEY="your-secret-key"
veadk frontend --agents-dir examples
```

<Warning>
  本地模式使用 `/tmp`，文件可能随进程或宿主机回收而丢失。需要长期保存附件时应使用 TOS，并按用户权限限制 Bucket 访问。
</Warning>

## 使用技能与子智能体

在输入框中输入 `/` 可搜索当前智能体挂载的技能，输入 `@` 可选择允许转移的子智能体。选中项以可移除的标签显示，不会作为普通文本发送。选择子智能体后，技能列表会切换为目标智能体自身挂载的技能。

## 使用 Studio 部署

`veadk studio` 启动专注于创建与管理智能体的界面。准备部署时，在项目预览中检查生成代码并配置地域、消息渠道、网络与环境变量，然后由 Studio 创建 AgentKit Runtime。

```bash lines theme={null}
veadk studio --host 127.0.0.1 --port 8000
```

`veadk studio deploy` 可把 Studio 本身部署到 VeFaaS。未指定 `--iam-role` 时，命令会创建或复用默认服务角色，并附加 Studio 查询模型、日志、追踪、知识库、记忆与身份资源所需的只读权限。传入自定义角色时，命令不会修改其策略。

## 认证

会话与记忆按 ADK 的 `user_id` 隔离，该 `user_id` 来自登录用户。命令启动时会先加载当前目录及其上层目录中的 `.env` 文件，因此下述环境变量可写入 `.env`。

**SSO** —— 传入用户池与客户端后启用。前端会展示登录页并跳转到身份提供方，登录后用户信息接口返回的用户标识将作为 `user_id`。用户池与客户端既可用名称指定，也可用 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"
# 或用 UID，读环境变量 OAUTH2_USER_POOL_ID / OAUTH2_USER_POOL_CLIENT_ID
# --oauth2-user-pool-uid <id> --oauth2-user-pool-client-uid <id>
```

启用 VeIdentity SSO 需要进程能拿到火山引擎凭证。中间件保护 API，同时放行界面外壳、`/web/auth-config`、`/favicon.ico`、`/assets` 与 `/skillhub`，因此应用能加载并展示自己的登录页，而不是被直接重定向到身份提供方。登录按钮的文案与图标由配置驱动。

**第三方 / 自定义 OAuth2（环境变量）** —— 不依赖 VeIdentity 用户池时，只要设置 `OAUTH2_CLIENT_ID`（及密钥），即可接入 GitHub、Google 或任意 OIDC 登录。端点来源按以下顺序确定：内置预设（`OAUTH2_PROVIDER=github` 或 `google`）、OIDC 自动发现（设置 `OAUTH2_ISSUER`）、显式端点（`OAUTH2_AUTHORIZE_URL` 等）。

| 环境变量 | 说明 |
| :- | :- |
| `OAUTH2_PROVIDER` | provider 标识：`github`、`google` 或自定义名称。决定登录按钮文案与内置预设。 |
| `OAUTH2_CLIENT_ID` / `OAUTH2_CLIENT_SECRET` | OAuth2 客户端凭据。设置 `OAUTH2_CLIENT_ID` 即启用通用 provider。 |
| `OAUTH2_ISSUER` | OIDC issuer 基址，端点将自动发现，例如 `https://accounts.google.com`。 |
| `OAUTH2_AUTHORIZE_URL` / `OAUTH2_TOKEN_URL` / `OAUTH2_USERINFO_URL` | 显式端点，用于非 OIDC provider。 |
| `OAUTH2_SCOPE` | 覆盖请求的 scope。 |
| `OAUTH2_PROVIDER_LABEL` | 覆盖登录按钮文案。 |
| `OAUTH2_REDIRECT_URI` | 回调地址。部署到公网或 runtime 时设为公网回调，并在 OAuth 应用中登记同一地址；本地默认 `http://{host}:{port}/oauth2/callback`。 |

GitHub 预设仅需客户端凭据：

```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 同理，把 `OAUTH2_PROVIDER` 换成 `google`；Keycloak、Auth0、Okta 等任意 OIDC 则设置 `OAUTH2_ISSUER` 加客户端凭据即可。完整示例见仓库 `examples/front_with_sso/`。

连接使用 `custom_jwt` 鉴权的 AgentKit Runtime 时，服务端会转发当前会话已验证的 OAuth access token。Token 的 issuer 必须匹配 Runtime 的 discovery URL，客户端 ID 也必须包含在 Runtime 的 `allowed_clients` 中。

<Warning>
  部署到 runtime 或公网时，OAuth 回调必须指向外部可访问的地址：把 `OAUTH2_REDIRECT_URI` 设为公网回调 URL，并在 OAuth 应用里登记同一地址。Cookie 的 `Secure` 标志会根据该地址是否为 HTTPS 自动开启。
</Warning>

**无 SSO（本地用户名）** —— 不传上述参数时，登录页会让用户输入一个用户名（字母加数字，不超过 16 位），保存在本地并作为 `user_id`。此时服务始终返回未认证状态与空的 provider 列表，应用即展示本地用户名登录界面。

<Note>
  登录态会被缓存：SSO 走 `veadk_session` Cookie，本地模式走 `localStorage`。会话本身在发送第一条消息或上传第一个附件时创建，而非打开页面时。退出登录为本地登出，即清除会话并回到登录页。
</Note>

## 前端服务安全限制

VeADK Frontend 可能部署到公网，因此会限制用户可控制的地址和文件路径：

* 在线创建项目不直接执行浏览器提交的代码；部署前测试应在受控的本地环境中完成。
* 远程 AgentKit 代理要求提供 API Key，并只接受 HTTPS 的 `volceapi.com` 域名。
* AgentKit 部署文件必须位于本次项目目录内，绝对路径和跳出目录的相对路径会被拒绝。
* 静态文件只允许从已构建的界面目录读取，不能通过路径跳转读取主机上的其他文件。

这些限制不会代替身份认证。公网部署仍应启用 SSO 或受信任的上游网关，并按最小权限原则配置云资源凭证。只需要创建和管理能力时，可以使用[Studio 智能体工作台](/productions/veadk/archives/1.0.5/zh/components/frontend/studio)。

## 渲染流程

前端与 Google ADK API Server 通信：列出可用智能体、创建会话，并以流式方式实时接收智能体的输出。当智能体返回 A2UI 消息时，前端从中解析出界面指令，据此创建并增量更新对应的界面区域，再按每个组件的类型渲染出相应的 React 组件。组件类型到渲染器的映射由一张注册表维护，因此新增一种组件类型，只需为它注册对应的渲染器。

## 添加企业自定义组件

一个自定义组件由两个部分组成，它们共享同一个 catalog id。后端部分见 [A2UI](/productions/veadk/archives/1.0.5/zh/components/frontend/a2ui#自定义组件)；前端部分如下。

**前端部分** —— 新建一个目录即可自动注册，无需修改任何中心文件：

```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">{/* 渲染 series */}</div>;
}
```

新增的组件目录会被自动发现并注册，无需改动任何中心配置文件。

<Note>
  未注册渲染器的未知组件会回退到可折叠的 JSON 视图，因此目录与渲染器不匹配也不会导致界面崩溃。
</Note>
