- 入门指南
- Studio Web 中的 UiPath 智能体
- UiPath 编码智能体

智能体用户指南
匿名访问设置
概述
匿名访问权限使您可以为没有 UiPath 帐户的用户嵌入对话智能体。这适用于面向客户的应用程序、公共门户或您希望用户无需 UiPath 身份验证即可与智能体交互的任何场景。
匿名访问权限需要:
- 在 UiPath 管理门户中配置的机密外部应用程序
- 由您的组织托管的用于处理身份验证的令牌端点
- 配置了身份验证参数的嵌入式智能体 URL
应用程序作用域内的机密外部应用程序允许在未经用户身份验证的情况下进行匿名访问。请仔细配置权限,以防止数据遭到意外访问。我们强烈建议将匿名智能体隔离在您自己的门户或登录名后面,以减少滥用。
目标用户:需要访问对话智能体但没有 Automation Cloud 帐户的用户。
先决条件
开始之前,确保您拥有:
- Orchestrator 中已发布的对话智能体。
- 组织管理员对 UiPath 管理门户的访问权限。
- 用于托管无服务器功能或 API 端点(例如 AWS Lambda、Azure Functions、Google Cloud Functions)的基础设施。
第 1 步:创建外部应用程序
- 在 UiPath 主页中,导航到“管理员”。
- 选择“外部应用程序”。
- 选择“添加应用程序”。
- 填写应用程序详细信息:
- 应用程序名称:为应用程序提供描述性名称。
- 应用程序类型:选择“机密应用程序”。
- 将以下作用域添加为应用程序作用域:
| API | 范围 |
|---|---|
| Orchestrator API 访问权限 | OR.Jobs |
| Orchestrator API 访问权限 | OR.Execution |
| Orchestrator API 访问权限 | OR.Users |
| Orchestrator API 访问权限 | OR.Folders |
| 追踪 API 访问权限 | Traces.Api |
| 对话智能体 | ConversationalAgents |
- 单击“添加”(此客户端不需要重定向 URL)。
- 弹出窗口显示应用程序 ID 和应用程序密钥。
复制应用程序密钥并安全存储。关闭此窗口后,您将无法再次查看,创建令牌端点时需要使用这些信息。
若将任何作用域添加为用户作用域,而非应用程序作用域,会导致聊天应用程序请求用户登录,从而无法实现匿名访问的目的。
第 2 步:配置外部应用程序权限
创建外部应用程序后,配置其权限,以控制匿名智能体可以访问的资源。
分配租户级访问权限
- 导航到 Orchestrator。
- 选择左上角的“租户”。
- 在工具栏中选择“管理访问权限”。
- 选择“外部应用程序”。
- 选择“分配外部应用程序”。
- 搜索并选择您创建的外部应用程序。
- 在“其他角色”下,选择所需的角色:
- 最低要求:Automation User。
- 仅根据您的用例需求添加其他角色。
- 选择“分配”。
分配文件夹级访问权限
- 导航到 Orchestrator 中的“文件夹”。
- 对于智能体需要访问的每个文件夹:
- 选择文件夹。
- 选择“分配帐户/组/外部应用程序”。
- 从下拉菜单中选择您的外部应用程序。
- 分配所需的角色。
- 选择“分配”。
外部应用程序被禁止访问其无明确权限的任何资源。确保应用程序拥有访问对话智能体所需的所有上下文、工具和资源的权限。
第 3 步:创建令牌端点
由于嵌入式对话智能体无法安全存储客户端密钥,因此需要令牌端点。您的令牌端点使用客户端凭据向 UiPath 进行身份验证,并将访问令牌返回给嵌入式智能体。
建议架构
我们建议为令牌端点采用无服务器架构:
- 低成本:例如,每月 3,000,000 次响应的 AWS Lambda 定价约为 0.40 美元。
- 维护量最小:无需管理服务器。
- 轻松扩展:自动处理峰值流量。
安全注意事项
客户端密钥是高度敏感信息。如果无意中暴露密钥,请立即删除,并在“外部应用程序”设置中生成新密钥。
确保您的令牌端点实施:
- 安全地存储客户端密钥(环境变量、密钥管理器)
- 验证请求来源,以防止未经授权的访问
- 对所有通信使用 HTTPS
实施示例
以下 JavaScript 代码适用于您的无服务器平台。响应正文必须返回 {access_token: <token>}:
// Whitelist: Configure allowed origins for your deployment
const ALLOWED_ORIGINS = [
'https://cloud.uipath.com/*',
// Add your application domains here
];
function matchesOriginPattern(origin, pattern) {
try {
const originUrl = new URL(origin);
const originBase = `${originUrl.protocol}//${originUrl.host}`;
if (pattern.includes('*')) {
const regexPattern = pattern
.replace(/[.+?^${}()|[\]\\]/g, '\\$&')
.replace(/\*/g, '.*');
const regex = new RegExp(`^${regexPattern}$`);
return regex.test(originBase);
} else {
return originBase.startsWith(pattern);
}
} catch (e) {
return false;
}
}
function checkOrigin(req) {
const origin = req.headers.origin || req.headers.referer;
if (!origin) {
const host = req.headers.host;
if (host && (host.includes('localhost') || host.includes('127.0.0.1'))) {
return true;
}
return false;
}
return ALLOWED_ORIGINS.some(pattern => matchesOriginPattern(origin, pattern));
}
async function getClientAccessToken() {
const clientId = process.env.CLIENT_ID;
const clientSecret = process.env.CLIENT_SECRET;
const scope = 'OR.Default ConversationalAgents Traces.Api';
const params = new URLSearchParams({
grant_type: 'client_credentials',
client_id: clientId,
client_secret: clientSecret,
scope: scope
});
const response = await fetch('https://cloud.uipath.com/identity_/connect/token', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: params.toString()
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`Token request failed: ${response.status} ${errorText}`);
}
const data = await response.json();
return data.access_token;
}
export async function token(context, req) {
if (!checkOrigin(req)) {
context.res = {
status: 403,
headers: { 'Content-Type': 'application/json' },
body: { error: 'Origin not allowed' }
};
return;
}
try {
const accessToken = await getClientAccessToken();
context.res = {
status: 200,
headers: { 'Content-Type': 'application/json' },
body: { access_token: accessToken }
};
} catch (error) {
console.error('Error fetching access token:', error);
context.res = {
status: 500,
headers: { 'Content-Type': 'application/json' },
body: { error: 'Failed to fetch access token' }
};
}
}
// Whitelist: Configure allowed origins for your deployment
const ALLOWED_ORIGINS = [
'https://cloud.uipath.com/*',
// Add your application domains here
];
function matchesOriginPattern(origin, pattern) {
try {
const originUrl = new URL(origin);
const originBase = `${originUrl.protocol}//${originUrl.host}`;
if (pattern.includes('*')) {
const regexPattern = pattern
.replace(/[.+?^${}()|[\]\\]/g, '\\$&')
.replace(/\*/g, '.*');
const regex = new RegExp(`^${regexPattern}$`);
return regex.test(originBase);
} else {
return originBase.startsWith(pattern);
}
} catch (e) {
return false;
}
}
function checkOrigin(req) {
const origin = req.headers.origin || req.headers.referer;
if (!origin) {
const host = req.headers.host;
if (host && (host.includes('localhost') || host.includes('127.0.0.1'))) {
return true;
}
return false;
}
return ALLOWED_ORIGINS.some(pattern => matchesOriginPattern(origin, pattern));
}
async function getClientAccessToken() {
const clientId = process.env.CLIENT_ID;
const clientSecret = process.env.CLIENT_SECRET;
const scope = 'OR.Default ConversationalAgents Traces.Api';
const params = new URLSearchParams({
grant_type: 'client_credentials',
client_id: clientId,
client_secret: clientSecret,
scope: scope
});
const response = await fetch('https://cloud.uipath.com/identity_/connect/token', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: params.toString()
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`Token request failed: ${response.status} ${errorText}`);
}
const data = await response.json();
return data.access_token;
}
export async function token(context, req) {
if (!checkOrigin(req)) {
context.res = {
status: 403,
headers: { 'Content-Type': 'application/json' },
body: { error: 'Origin not allowed' }
};
return;
}
try {
const accessToken = await getClientAccessToken();
context.res = {
status: 200,
headers: { 'Content-Type': 'application/json' },
body: { access_token: accessToken }
};
} catch (error) {
console.error('Error fetching access token:', error);
context.res = {
status: 500,
headers: { 'Content-Type': 'application/json' },
body: { error: 'Failed to fetch access token' }
};
}
}
环境变量
在您的无服务器平台中配置以下环境变量:
| 变量 | 描述 |
|---|---|
CLIENT_ID | 第 1 步中的应用程序 ID |
CLIENT_SECRET | 第 1 步中的应用程序密钥 |
设置环境变量的具体方法取决于您的托管平台。
配置允许的来源
ALLOWED_ORIGINS 矩阵会拒绝来自未授权来源的令牌请求,从而提供了安全性。在此列表中配置:
https://cloud.uipath.com/*(嵌入式智能体的必填项)https://staging.uipath.com(如果您需要允许来自临时环境的请求)- 您的应用程序域名(如果在本地测试或在其他环境中测试)
第 4 步:嵌入具有匿名访问权限的智能体
配置令牌端点后,使用以下 URL 格式嵌入对话智能体:
https://<cloud_env>.uipath.com/<organization>/<tenant>/autopilotforeveryone_/conversational-agents/?agentId=<agent_id>&externalAuth=true&authEndpoint=<token_endpoint_url>&externalUserId=<user_id>
https://<cloud_env>.uipath.com/<organization>/<tenant>/autopilotforeveryone_/conversational-agents/?agentId=<agent_id>&externalAuth=true&authEndpoint=<token_endpoint_url>&externalUserId=<user_id>
匿名访问 URL 参数
| 参数 | 必填 | 描述 |
|---|---|---|
agentId | 是 | 已发布智能体的发行版 ID |
externalAuth | 是 | 设置为 true,以启用匿名访问权限 |
authEndpoint | 是 | 令牌端点的 URL |
externalUserId | 是 | 用户的唯一标识符(请参阅下面的说明) |
externalUserId 是您定义和维护的值。它会分离并检索用户聊天历史记录。如需保留聊天历史记录,请使用有意义的用户 ID;如果不需要保留聊天历史记录,则可以使用随机 GUID。
嵌入 URL 示例
https://<cloud_env>.uipath.com/myorg/mytenant/autopilotforeveryone_/conversational-agents/?agentId=12345&externalAuth=true&authEndpoint=https://my-api.example.com/token&externalUserId=user-abc-123
https://<cloud_env>.uipath.com/myorg/mytenant/autopilotforeveryone_/conversational-agents/?agentId=12345&externalAuth=true&authEndpoint=https://my-api.example.com/token&externalUserId=user-abc-123
HTML 示例
<iframe
src="https://<cloud_env>.uipath.com/myorg/mytenant/autopilotforeveryone_/conversational-agents/?agentId=12345&externalAuth=true&authEndpoint=https://my-api.example.com/token&externalUserId=user-abc-123"
width="400"
height="600"
frameborder="0"
allow="clipboard-write"
></iframe>
<iframe
src="https://<cloud_env>.uipath.com/myorg/mytenant/autopilotforeveryone_/conversational-agents/?agentId=12345&externalAuth=true&authEndpoint=https://my-api.example.com/token&externalUserId=user-abc-123"
width="400"
height="600"
frameborder="0"
allow="clipboard-write"
></iframe>
如果缺少 externalAuth=true 参数,嵌入式智能体将使用标准登录重定向流,而非匿名访问。
故障排除
令牌端点返回 403
- 验证您的
ALLOWED_ORIGINS列表是否包含正确的域名。 - 检查请求来源标头是否正确发送。
- 直接测试端点以隔离问题。
令牌请求失败,并显示身份验证错误
- 验证
CLIENT_ID和CLIENT_SECRET环境变量是否正确设置。 - 确认外部应用程序在 UiPath 管理门户中仍处于活跃状态。
- 检查代码中的令牌端点 URL 是否指向正确的 UiPath 环境。
智能体无法访问资源
- 在 Orchestrator 中查看为外部应用程序分配的角色。
- 验证是否已为所有必要文件夹配置了文件夹级权限。
- 检查添加到外部应用程序的作用域是否与所需的 API 访问权限相匹配。
聊天历史记录未保留
- 确保您对同一用户使用了一致的
externalUserId。 - 验证用户 ID 是否在嵌入 URL 中正确传递。
后续步骤
- iFrame 和 Apps 嵌入:完整的嵌入文档
- 许可:了解匿名用户的消耗情况