系统架构
理解 Clouisle 的技术栈、请求链路、扩展性与安全边界
Clouisle 采用前端、后端与基础设施分层的架构:Next.js 前端负责界面与 SSR,FastAPI 后端承载 Agent/工作流/知识库业务,Celery 处理异步任务,PostgreSQL、Redis 与 Qdrant 分别承担业务数据、缓存队列与向量检索。
技术栈
| 层 | 组件 | 说明 |
|---|---|---|
| 前端 | Next.js 16(App Router)、TypeScript、Tailwind CSS 4 + shadcn/ui、Bun | 容器运行 Next.js standalone(node server.js),不含 Nginx;deploy/nginx/default.conf 仅是可选的外部反向代理示例 |
| 后端 | FastAPI(Python 3.13)、Tortoise ORM + asyncpg、Celery + Redis | LangChain 适配器(对话/嵌入/文本切分);自研 WorkflowOrchestrator 执行工作流;LangGraph 已声明但运行时未使用;MarkItDown 做文档转换 |
| 基础设施 | PostgreSQL 17(pg_search 全文检索)、Redis 7(缓存/Celery broker/SSE 事件缓冲/限速与锁定计数)、Qdrant(向量) | 向量按嵌入维度存入独立集合({prefix}_{dimension}),维度由所选嵌入模型决定 |
请求链路与执行模型
1. 基础请求链路
浏览器 → (可选外部反代/Ingress)→ Next.js SSR (node server.js) → FastAPI API → PostgreSQL → 响应2. 对话请求流与持久化 AgentRun 生命周期
Clouisle 为 Agent 会话提供了持久化、解耦的 AgentRun 异步执行架构:
用户消息 ──► FastAPI (POST /api/v1/agents/{agent_id}/chat/runs) ──► Redis 队列 (Celery agent)
│ (202 Accepted, run_id) │
▼ ▼
SSE 流式通道 Celery Worker (run_agent_task)
(GET /api/v1/agents/{agent_id}/chat/runs/{id}/stream) │
▲ 获取会话排他锁 (Conversation Lock)
│ │
Redis 事件缓冲区 ◄────────────────────────────── AgentLoop ReAct 思考循环
(SSE Event Pub/Sub) │
┌──────────┴──────────┐
▼ ▼
工具调用 / RAG 检索 三层上下文压缩
│ (微压缩与宏总结)
▼ │
[ask_user 交互挂起] ▼
(状态: WAITING) 带水印摘要消息- 持久化 AgentRun:发起运行提交 Celery 任务并立即返回
202 Accepted与run_id。任务路由到agent队列,由主 Worker 消费;如果部署时把 Worker 的-Q改写掉了agent,运行会永远停在queued且不报错,用户只会看到「排队中」(队列映射见部署架构)。客户端通过 SSE(/chat/runs/{run_id}/stream)监听事件流,支持断线后基于from_sequence无缝重连,后台工具执行不受影响。agent队列任务不配置自动重试——模型调用与工具执行有副作用,重试会重复执行;Worker 崩溃导致的中断运行由 Beat 每 2 分钟投递的sweep-lost-agent-runs回收并标记为interrupted(不会重放)。 - AgentLoop ReAct 引擎:管理多轮迭代推理与工具调用(最大轮次
max_iterations、单轮超时与凭据安全注入)。 - 三层上下文压缩机制:
- 微压缩(Micro Compaction):自动截断或摘要过长的工具输出和原始 base64 数据,保护 token 预算。
- 宏总结(Macro Compaction):当会话 token 超过触发预算时,在完整轮次边界启动 LLM 总结历史消息,插入带水印的
context_summary消息,保留最近轮次的原始对话。 - 预检与恢复保护:预留 token 缓冲空间,遇到模型提供商上下文长度超限时自动重试与兜底。
- 人机协同(
ask_user)挂起与恢复:当模型调用ask_user时,AgentRun转入WAITING状态挂起。用户提交答案(POST /chat/runs/{run_id}/answers)后,后端使用 ORM 行锁校验并无缝恢复同一运行。
3. 工作流引擎执行流
触发事件 / 用户输入 ──► FastAPI (POST /workflows/{id}/runs) ──► Celery 队列 (workflow)
│
▼
WorkflowOrchestrator
│
解析 DAG 图拓扑规划
(ExecutionPlan,过滤注释节点)
│
执行节点流水线
(LLM, Code, Condition,
Iteration, Pause...)
│
┌───────────────────────┴───────────────────────┐
▼ ▼
常规节点并发执行 人工审批挂起
(ExecutionContext 上下文) (状态: WAITING)
│ │
▼ ▼
完成最终输出 提交反馈后恢复执行- 拓扑规划器(
ExecutionPlan):校验 DAG 依赖,规划可并行批次,自动过滤画布注释等非执行节点(NON_EXECUTABLE_NODE_TYPES = {"comment"})。 - 模块化节点执行器:提供
llm、condition、code(沙箱)、iteration/loop、template、variable_aggregator、knowledge_retrieval、tool、agent与sub_workflow执行器。 - 暂停与恢复机制:需要人工确认的
pause节点持久化WorkflowPauseRequest并将状态设为WAITING,待用户提交反馈后恢复执行。
扩展性
前端与 API 无状态,可多副本水平扩展。主 Worker(python main.py worker -c 4 -Q default,agent,knowledge,workflow)一次消费 default、agent、knowledge、workflow 四个队列;按队列独立扩容时,额外启动只订阅单一队列的 Worker(例如 -Q agent)即可,但任何时刻都必须有 Worker 消费 default 和 agent,否则通知、清理任务与 Agent 对话会静默堆积在队列里。代码沙箱是独立的第五个队列 sandbox,由专用 sandbox-worker 消费,扩容它不影响知识库与工作流。Celery Beat 必须且只能运行一个副本——它是裸调度器、无数据库锁,多副本会重复投递定时任务。完整队列映射、Beat 周期任务与扩缩容命令见部署架构。
安全与多租户
- 认证:密码(bcrypt)、SSO(OAuth2/OIDC/SAML/CAS)、API Key(
clou_+Authorization: Bearer)。 - 授权:JWT 校验 + 权限检查(
resource:action/admin:resource:action),超级管理员绕过。 - 数据隔离:资源按团队归属,查询按团队成员自动过滤;普通用户只能看到自己的会话(详见 团队与安全)。
- 审计:记录操作者、操作与变更前后快照,支持保留天数与归档。
性能与缓存
用户会话默认 30 天(站点设置 session_timeout_days 控制),JWT 兜底令牌 8 天;站点设置不缓存、每次直读数据库。
平台没有统一的全局限速中间件,各保护机制按场景独立实现,边界也各不相同:
| 机制 | 限制 | 落地位置 |
|---|---|---|
| 登录失败锁定 | 同一账户连续失败 max_login_attempts(默认 5)次后锁定 lockout_duration_minutes(默认 15)分钟 | 账户字段 + 站点设置 |
| TOTP 校验 | 300 秒窗口内失败 5 次即锁定 900 秒 | Redis 计数 |
| 管理员批量邮件 | 每个发送者 100 封/小时 | Redis 计数(TTL 3600 秒) |
| 单收件人邮件 | 每个邮箱 5 封/天 | Redis 计数(TTL 86400 秒) |
| API Key 每分钟请求数 | rate_limit 字段默认 1000/分钟,0 表示不限——仅存储,当前不执行 | 元数据字段 |
不要把 API Key 的 rate_limit 当成生效的防滥用措施,也不要指望单靠验证码兜住暴力破解:真正拦截登录失败的是账户级锁定与 TOTP 锁定(详见 团队与安全)。
健康检查
/api/v1/health— 公开基础健康检查(容器 HEALTHCHECK 使用)。/api/v1/admin/observability/system/health— 管理端观测健康(CPU/内存/磁盘/数据库/Redis/Worker),需admin:dashboard:access。
参见:
这篇文章对你有帮助吗?