本教程介绍如何使用 Cloudflare AI Gateway 和 Zero Trust 为 AI 智能体创建一个功能完备且安全的网站包装器。Cloudflare Zero Trust 管理员可以使用 Cloudflare Access 保护对该包装器的访问。此外,您可以实施 Gateway 策略来控制用户与 AI 智能体的交互方式,包括使用 Browser Isolation 在隔离的浏览器中执行 AI 智能体、实施数据丢失防护 (DLP) 配置文件以防止用户共享敏感数据,以及扫描内容以避免 AI 智能体给出违反公司内部准则的回答。如果您有特定 AI 提供商的企业计划(例如 ChatGPT Enterprise),创建 AI 智能体包装器也是实施租户控制(tenant control)的有效方法。
本教程以 ChatGPT 作为 AI 智能体的示例。
确保您拥有:
- 一个 Cloudflare Zero Trust 组织。
- 您所需 AI 提供商的 API 密钥,例如适用于 ChatGPT 的 OpenAI API 密钥 ↗。
首先,创建一个 AI Gateway 来控制您的 AI 应用程序。
-
在 Cloudflare 仪表板 ↗中,转到 AI Gateway 页面。
Go to AI Gateway ↗ -
选择 Create Gateway(创建网关)。
-
为您的网关命名。
-
选择 Create(创建)。
-
为网关配置所需的选项。
-
连接您的 AI 提供商,使用您的 AI Gateway 将查询代理到您选择的 AI 智能体。 7.(可选)开启通过身份验证的网关 (Authenticated Gateway)。通过身份验证的网关功能通过强制使用请求标头
cf-aig-authorization形式的令牌,确保只能安全地调用您的 AI Gateway。- 转到 AI > AI Gateway。
- 选择您的 AI Gateway,然后转到 Settings(设置)。
- 开启 Authenticated Gateway(已验证网关),然后选择 Confirm(确认)。
- 选择 Create authentication token(创建身份验证令牌),然后选择 Create an AI Gateway authentication token(创建 AI Gateway 身份验证令牌)。
- 配置您的令牌并复制令牌值。在创建 Worker 时,您需要在调用 AI Gateway 时传递此令牌。
有关更多信息,请参阅 AI Gateway 快速入门。
Guardrails 是 AI Gateway 的内置安全功能,允许 Cloudflare 根据所选类别识别提示词(prompt)和响应中的不安全或不当内容。
-
在 Cloudflare 仪表板中,转到 AI Gateway 页面。
Go to AI Gateway ↗ -
选择您的 AI Gateway。
-
转到 Guardrails(护栏)。
-
开启 Guardrails。
-
选择 Change(更改) 以配置您想要针对提示词和响应进行过滤的类别。
为了构建 Worker,您需要选择是使用 Wrangler 在本地构建,还是使用仪表板 ↗在远程构建。
-
在终端中,登录您的 Cloudflare 账户:
wrangler login -
在本地初始化项目:
mkdir ai-agent-wrapper cd ai-agent-wrapper wrangler init -
创建 Wrangler 配置文件:
name = "ai-agent-wrapper" main = "src/index.js" compatibility_date = "2023-10-30" [vars] # Add any environment variables here -
将您的 AI 提供商的 API 密钥添加为机密 (secret):
wrangler secret put <OPENAI_API_KEY>
您现在可以使用 Wrangler 创建的 index.js 文件来构建 Worker。
-
在 Cloudflare 仪表板中,转到 Workers & Pages 页面。
Go to Workers & Pages ↗ -
选择 Create(创建)。
-
在 Workers 中,选择 Hello world 模板。
-
为您的 Worker 命名,然后选择 Deploy(部署)。
-
选择您的 Worker,然后转到 Settings(设置) 选项卡。
-
转到 Variables and Secrets(变量和密钥),然后选择 Add(添加)。
-
选择 Secret 作为类型,为您的机密命名(例如
OPENAI_API_KEY),并在 Value(值) 中输入您的 AI 提供商的 API 密钥的值。
您现在可以通过在 Worker 页面上选择 Edit code(编辑代码),使用在线代码编辑器来构建 Worker。
以下是一个示例入门 Worker,它提供了一个简单的前端,允许用户与 AI Gateway 后面的 AI 提供商进行交互。此示例使用 OpenAI 作为其 AI 提供商:
export default {
async fetch(request, env) {
if (request.url.endsWith("/api/chat")) {
if (request.method === "POST") {
try {
const { messages } = await request.json();
const response = await fetch(
"https://gateway.ai.cloudflare.com/v1/$ACCOUNT_ID/$GATEWAY_ID/openai/chat/completions",
{
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${env.OPENAI_API_KEY}`,
},
body: JSON.stringify({
model: "gpt-4o-mini",
messages: messages,
}),
},
);
if (!response.ok) {
throw new Error(`AI Gateway Error: ${response.status}`);
}
const result = await response.json();
return new Response(
JSON.stringify({
response: result.choices[0].message.content,
}),
{
headers: { "Content-Type": "application/json" },
},
);
} catch (error) {
return new Response(JSON.stringify({ error: error.message }), {
status: 500,
headers: { "Content-Type": "application/json" },
});
}
}
return new Response("Method not allowed", { status: 405 });
}
return new Response(HTML, {
headers: { "Content-Type": "text/html" },
});
},
};
const HTML = `<!DOCTYPE html>
<html lang="en" data-theme="dark">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ChatGPT Wrapper</title>
<style>
:root {
--background-color: #1a1a1a;
--chat-background: #2d2d2d;
--text-color: #ffffff;
--input-border: #404040;
--message-ai-background: #404040;
--message-ai-text: #ffffff;
}
body {
font-family: system-ui, sans-serif;
margin: 0;
padding: 20px;
background: var(--background-color);
display: flex;
flex-direction: column;
align-items: center;
gap: 20px;
color: var(--text-color);
}
.chat-container {
width: 100%;
max-width: 800px;
background: var(--chat-background);
border-radius: 10px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
height: 80vh;
display: flex;
flex-direction: column;
}
.chat-header {
padding: 15px 20px;
border-bottom: 1px solid var(--input-border);
background: var(--chat-background);
border-radius: 10px 10px 0 0;
text-align: center;
}
.chat-messages {
flex-grow: 1;
overflow-y: auto;
padding: 20px;
}
.message {
margin-bottom: 20px;
padding: 10px 15px;
border-radius: 10px;
max-width: 80%;
}
.user-message {
background: #007AFF;
color: white;
margin-left: auto;
}
.ai-message {
background: var(--message-ai-background);
color: var(--message-ai-text);
}
.input-container {
padding: 20px;
border-top: 1px solid var(--input-border);
display: flex;
gap: 10px;
}
input {
flex-grow: 1;
padding: 10px;
border: 1px solid var(--input-border);
border-radius: 5px;
font-size: 16px;
background: var(--chat-background);
color: var(--text-color);
}
button {
padding: 10px 20px;
background: #007AFF;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 16px;
}
button:disabled {
background: #ccc;
}
.error {
color: red;
padding: 10px;
text-align: center;
}
</style>
</head>
<body>
<div class="chat-container">
<div class="chat-header">
<h2>AI Assistant</h2>
</div>
<div class="chat-messages" id="messages"></div>
<div class="input-container">
<input type="text" id="userInput" placeholder="Type your message..." />
<button onclick="sendMessage()" id="sendButton">Send</button>
</div>
</div>
<script>
let messages = [];
const messagesDiv = document.getElementById('messages');
const userInput = document.getElementById('userInput');
const sendButton = document.getElementById('sendButton');
userInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') sendMessage();
});
async function sendMessage() {
const content = userInput.value.trim();
if (!content) return;
userInput.disabled = true;
sendButton.disabled = true;
messages.push({ role: 'user', content });
appendMessage('user', content);
userInput.value = '';
try {
const response = await fetch('/api/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
messages
})
});
if (!response.ok) {
throw new Error('API request failed');
}
const result = await response.json();
const aiMessage = result.response;
messages.push({ role: 'assistant', content: aiMessage });
appendMessage('ai', aiMessage);
} catch (error) {
appendMessage('ai', 'Sorry, there was an error processing your request.');
console.error('Error:', error);
}
userInput.disabled = false;
sendButton.disabled = false;
userInput.focus();
}
function appendMessage(role, content) {
const messageDiv = document.createElement('div');
messageDiv.className = 'message ' + role + '-message';
messageDiv.textContent = content;
messagesDiv.appendChild(messageDiv);
messagesDiv.scrollTop = messagesDiv.scrollHeight;
}
</script>
</body>
</html>`;请注意,AI Gateway 端点中的账户 ID 和网关 ID 需要替换。您可以在 Workers 中将这些添加为环境变量或机密 (secrets)。如果您在创建 AI Gateway 时选择使用 Authenticated Gateway,请确保同时将您的令牌添加为机密,并在 cf-aig-authorization 标头中将其值传递给 AI Gateway。
Worker 代码完成后,您需要使用受 Cloudflare Access controls(访问控制)保护的主机名使 Worker 可被寻址访问。
编辑 Wrangler 配置文件并添加以下信息,以确保只能使用自定义主机名访问 Worker:
name = "ai-agent-wrapper"
main = "src/index.js"
compatibility_date = "2023-10-30"
workers_dev = false
+# Replace with your custom domain
+routes = [
+ { pattern = "<YOUR_CUSTOM_DOMAIN>", custom_domain = true }
+]
[vars]
# Add any environment variables here要发布 Worker,请运行 wrangler deploy。
如果您是使用 Cloudflare 仪表板中提供的代码编辑器远程构建 Worker 的,可以通过选择 Deploy(部署) 进行部署。
为确保只能从自定义主机名访问 Worker:
-
在 Cloudflare 仪表板中,转到 Workers & Pages 页面。
Go to Workers & Pages ↗ -
选择您的 Worker。
-
转到 Settings(设置)。
-
在 Domains & Routes(域和路由) 中,选择 Add(添加)。
-
选择 Custom domain(自定义域)。
-
输入您想要的自定义域名。
-
选择 Add domain(添加域)。
Worker 现在位于可寻址的公共主机名后面。请确保关闭 workers.dev 和 Preview URLs(预览 URL),以便只能使用其自定义域访问 Worker。
为了保护 AI 智能体包装器以确保只有受信任的用户可以访问它:
- 在 Cloudflare 仪表板 ↗中,转到 Zero Trust > Access controls(访问控制) > Applications(应用程序)。
- 选择 Create new application(创建新应用程序)。
- 选择 Self-hosted and private(自托管和私有)。
- 选择 Add public hostname(添加公共主机名) 并输入您为 Worker 设置的自定义域。
- 为您的 Worker 配置 Access 应用程序。
- 添加 Access 策略以控制谁可以连接到您的应用程序。
现在,只有成功匹配您的 Access 策略的用户才能访问您的 AI 包装器。
您现在可以使用 Gateway HTTP 策略阻止对所有未经授权的公共 AI 智能体的访问。
-
在 Cloudflare 仪表板 ↗中,转到 Zero Trust > Traffic policies(流量策略) > Firewall policies(防火墙策略) > HTTP。
-
选择 Add a policy(添加策略)。
-
添加以下策略:
选择器 运算符 值 操作 Content Categories(内容类别) in Artificial Intelligence(人工智能) Block(阻止) -
选择 Create policy(创建策略)。
这可确保无法使用托管端点访问公共 AI 智能体。
或者,您可以通过显示自定义阻止消息、重定向或用户通知将用户引导至 AI 智能体包装器,从而阻止用户使用公共 AI 智能体。
现在您已完全控制对 AI 智能体包装器的访问,可以实施额外安全方法(例如数据丢失防护 (DLP) 和无客户端 Web 隔离)来保护和控制与 AI 智能体共享的数据。
您可以使用数据丢失防护 (DLP) 防止用户向 AI 智能体发送敏感数据。
-
在 Cloudflare 仪表板 ↗中,转到 Zero Trust > Data loss prevention(数据防泄露) > Profiles(配置文件)。
-
确保正确配置了您想要实施的 DLP 配置文件。
-
添加一条 HTTP 策略,为主机名应用该 DLP 配置文件以用于您的包装器。例如:
选择器 运算符 值 逻辑 操作 Host(主机) is ai-wrapper.example.comAnd(且) Block(阻止) DLP Profile(DLP 配置文件) in AI DLP profile -
选择 Create policy(创建策略)。
有关创建 DLP 策略的更多信息,请参阅扫描 HTTP 流量。
因为您已将包装器发布为自托管的 Access 应用程序,所以您可以通过创建 Access 策略并为您的应用程序进行配置,从而在隔离会话中为您的用户执行它。
- 在 Cloudflare One ↗中,前往 Browser isolation > Browser isolation settings。
- 开启 Allow users to open a remote browser without the device client。
- 转到 Access controls(访问控制) > Policies(策略)。
- 选择 Add a policy(添加策略)。
- 将 Action(操作) 设置为 Allow。
- 在 Add rules(添加规则) 中,添加身份规则以定义应该为谁隔离该应用程序。
- 在 Additional settings (optional)(其他设置(可选)) 中,开启 Isolate application(隔离应用程序)。
一旦创建了 Access 策略,您就可以将其附加到您的包装器上。
- 转到 Access controls(访问控制) > Applications(应用程序)。
- 选择您的包装器应用程序,然后选择 Configure(配置)。
- 在 Policies(策略) 中,选择 Select existing policies(选择现有策略)。
- 选择您之前创建的 Access 策略。
- 选择 Confirm(确认),然后选择 Save(保存)。
因为无客户端 Web 隔离流量会应用您的 Gateway HTTP 策略,所以您配置的 DLP 配置文件将应用于隔离会话。
有关隔离 Access 应用程序的更多信息,请参阅隔离自托管应用程序。
采用 Cloudflare 保护 AI 智能体访问的组织将受益于更高得可见性和可配置性。
Zero Trust 将记录所有 Access 事件和 DLP 检测。此外,AI Gateway 还提供对用户提示词、模型响应、令牌使用情况和成本的可见性。
日志可以使用 Logpush 导出到外部提供商。
您可以将包装器配置为使用不同的 AI 提供商,或者为您的用户提供在多个 AI 提供商之间进行选择的选项,包括使用 Workers AI 直接在 Cloudflare 的全球网络上运行的 AI 模型。
借此,您可以控制与 AI 使用相关的成本,或采用更新的模型,而不会影响您的用户或已实施的访问控制。