跳转到内容

输入关键词开始搜索文档。

在 AWS 上部署智能体

最后更新 查看 Markdown 源文件

Flue 的 Node 目标是一个长期运行的 HTTP 服务器,而非函数。它在进程中持有智能体会话,并通过长连接提供流式响应,因此在 AWS 上你需要将它作为持续运行的容器服务来运行 — Flue 负责服务器,AWS 负责周围的平台。

这里的每个选项都运行来自使用 Docker 部署智能体的相同镜像。构建它,推送到 Amazon ECR 中的私有仓库,然后将下面的某个计算选项指向该镜像:

aws ecr create-repository --repository-name flue-agents
docker build -t flue-agents .
docker tag flue-agents:latest <account>.dkr.ecr.<region>.amazonaws.com/flue-agents:latest
aws ecr get-login-password --region <region> \
  | docker login --username AWS --password-stdin <account>.dkr.ecr.<region>.amazonaws.com
docker push <account>.dkr.ecr.<region>.amazonaws.com/flue-agents:latest

镜像绑定 PORT(Docker 指南设置为 8080);无论你选择什么,平台的端口和健康检查必须与之匹配。构建后的服务器只读取启动时提供的环境变量 — 它不会加载 .env — 因此 provider key(ANTHROPIC_API_KEY / OPENAI_API_KEY,可选的 MODEL_SPECIFIER)和 DATABASE_URL 来自平台的密钥存储,而不是镜像。

下面是三种计算选项,按照 AWS 为你管理的程度排序。

Amazon ECS Express Mode 是托管路径:一次 API 调用接受一个容器镜像和两个 IAM 角色,并在你的账户中配置完整的栈 — Fargate 上的 ECS 服务、带健康检查的应用负载均衡器、基于 CPU 的自动扩缩容、安全组和服务 URL。没有额外费用;你只需为底层资源付费。

aws ecs create-express-gateway-service \
  --service-name flue-agents \
  --execution-role-arn arn:aws:iam::<account>:role/ecsTaskExecutionRole \
  --infrastructure-role-arn arn:aws:iam::<account>:role/ecsInfrastructureRoleForExpressServices \
  --primary-container '{
    "image": "<account>.dkr.ecr.<region>.amazonaws.com/flue-agents:latest",
    "containerPort": 8080,
    "environment": [{ "name": "MODEL_SPECIFIER", "value": "anthropic/claude-sonnet-4-6" }]
  }' \
  --health-check-path /health \
  --scaling-target '{"minTaskCount":1,"maxTaskCount":4}' \
  --monitor-resources
关注点Express Mode
镜像--primary-container image 指向 ECR 仓库;execution role 拉取它。
环境变量和密钥明文变量放在 environment 中。通过任务 secrets 引用注入密钥,由 execution role 从 Secrets Manager 或 SSM Parameter Store 解析 — 将 provider key 和 DATABASE_URL 保持在镜像之外。
健康检查--health-check-path 是 ALB 目标组的路径。Flue 不会自动生成 — 在 app.ts 中定义 /health。
扩缩容--scaling-target 设置 minTaskCount / maxTaskCount;扩缩容跟踪 CPU。保持 minTaskCount ≥ 1 以便始终有一个进程持有会话。

ALB 位于长期对话 GET 读取(长轮询/SSE)的前端。提升目标组的空闲超时,并保留准入的 streamUrl 和 offset,以便客户端可以重新连接并恢复对话流。多个任务需要共享 Postgres 来实现持久化状态,但每个智能体实例仍必须路由到一个活动任务;不要对同一实例进行轮询。参见流式协议。

EC2(最简单,完全控制)

单个实例是最直接的”你自己的机器”,也是你承担最多运维工作的方式。使用 Docker 运行镜像:

docker run -d --restart unless-stopped -p 80:8080 \
  -e ANTHROPIC_API_KEY=sk-... \
  -e MODEL_SPECIFIER=anthropic/claude-sonnet-4-6 \
  <account>.dkr.ecr.<region>.amazonaws.com/flue-agents:latest

或者跳过容器,直接在 systemd 下运行 Node 构建 — 使用 npx vite build(vite.config.ts 中的 flue() 插件)构建到 dist/server.mjs,然后用 node dist/server.mjs 启动:

# /etc/systemd/system/flue.service
[Service]
WorkingDirectory=/opt/flue-agents
ExecStart=/usr/bin/node dist/server.mjs
Environment=PORT=8080
EnvironmentFile=/etc/flue-agents.env
Restart=always

[Install]
WantedBy=multi-user.target
关注点EC2
环境变量和密钥systemd EnvironmentFile(权限 600)或 docker run -e。在启动时从 SSM Parameter Store 获取 provider key 和 DATABASE_URL,而不是提交到实例中。
健康检查没有进程为你检查。如果你在前面放了 ALB 或运行了监控器,将其指向 /health(在 app.ts 中定义路由)。
端口和 TLS实例的安全组必须打开监听端口。在机器上的反向代理(nginx / Caddy)或 ALB 后面终止 TLS;Node 服务器使用纯 HTTP。

没有第二个实例可以故障转移,也没有自动扩缩容 — 一个进程持有所有会话。长期对话流直接工作;如果前面有 ALB,提升其空闲超时。当进程重启时,内存中的状态会丢失;在扩展到一台机器之前添加共享 Postgres。

ECS on Fargate(编排)

当你需要明确控制网络和扩缩容时,自己定义任务和服务,而不是让 Express Mode 为你生成。任务定义引用 ECR 镜像并注入配置;ECS 服务在你的 VPC 中的 ALB 后面的 Fargate 上运行它。

在容器定义中,environment 携带明文变量,secrets(每个 { "name", "valueFrom" })通过任务 execution role 解析 Secrets Manager ARN 或 SSM 参数 — 这就是 provider key 和 DATABASE_URL 应该存放的地方。服务的 loadBalancers 块将容器端口映射到 ALB 目标组;因为 Fargate 使用 awsvpc 网络,目标组必须使用 IP 目标类型,其健康检查路径应该是 /health(在 app.ts 中定义)。打开任务安全组允许 ALB 访问容器端口,并设置 healthCheckGracePeriodSeconds 长于服务器启动时间,以免慢启动被中途终止。

Application Auto Scaling 调整期望的任务数量;为流式对话提升 ALB 空闲超时,使用共享 Postgres 实现持久化状态,并将每个智能体实例路由到一个活动任务。这与 Express Mode 自动构建的 Fargate-plus-ALB 栈相同 — 当你需要自己掌控各部分时使用它。

持久化

没有 db.ts 适配器时,Flue 将规范对话、附件和已接受的提交保存在进程本地内存中 — 在重启或重新部署时丢失,且对替换任务不可用。为了实现持久化状态,使用 Amazon RDS for PostgreSQL 从服务的 VPC 可达。共享存储支持替换恢复;它不会启用单个智能体实例的多活所有权。

添加适配器和一个包装你配置的 pg 连接池并读取 DATABASE_URL 的 db.ts — 参见 Postgres 了解完整的自带驱动运行器:

src/db.ts(节选)
import { postgres } from '@flue/postgres';
import { Pool } from 'pg';

// 使用 DATABASE_URL 连接字符串创建连接池
const pool = new Pool({ connectionString: process.env.DATABASE_URL });

export default postgres({
  query: async (text, params) => (await pool.query(text, params)).rows,
  transaction: async (fn) => {
    /* 每个事务一个检出的客户端;参见 Postgres 指南 */
  },
  close: () => pool.end(),
});

将 RDS 连接字符串存储在 Secrets Manager 中,并作为 DATABASE_URL 注入 — 在 Express Mode 和 Fargate 上作为任务 secrets 引用,在 EC2 上从 SSM 获取。Flue 在构建时发现 db.ts 并将其连接到生成的服务器中;适配器处理模式创建、规范对话流、不可变附件和持久化提交状态。

不支持 AWS Lambda

Flue 不以 Lambda 为目标。Node 服务器是长期运行且有状态的 — 它持有智能体会话和进程内协调器,并通过长期对话 GET 连接提供流式响应。Lambda 的无状态、短期调用模型不适合这些:没有持久化进程在调用之间持有会话,执行窗口也不适合开放流。在那里运行 Flue 需要一个将所有协调外部化的适配器,这超出了范围 — 与 Vercel 和 Netlify 等函数平台被排除在外的原因相同。使用上面的某个容器服务。

参考资料