由.NET 构建的画布Agents
Sol 完全开源:用节点画布串联图片、视频、文本与 AI Agent
最近,AIDotNet 开源了一个名为 Sol 的 AI 创作项目。
Sol 是一个运行在浏览器中的可视化 AI 工作台。它没有把交互限制在传统的聊天窗口里,而是以全屏节点画布为核心,让用户在同一张画布上创建、连接和管理文本、图片、视频、Agent、MCP 工具及 Skills。
项目包含完整的前端、后端、数据库迁移、Docker Compose、Agent 运行时和 Skill 沙箱代码,使用 MIT License 发布,可以自由学习、修改、私有部署和二次开发。
Sol 是什么?
简单来说,Sol 想解决的是“多个 AI 模型和创作流程分散在不同网站里”的问题。
在 Sol 中,画布就是应用本身。用户可以在画布上创建节点,配置提示词、模型和输入素材,然后完成文本生成、图片生成或者视频生成。生成结果会进入素材库,画布及其节点关系也会被持久化保存,方便以后继续编辑。
它目前提供了几个比较有代表性的能力:
- 可视化创建和保存节点式 AI 工作流;
- 统一配置多个 AI 服务商和模型;
- 支持文本、图片和视频生成;
- 视频采用后端异步任务,即使关闭页面也能继续执行;
- 支持 Agent 会话,并让 Agent 获取当前画布上下文;
- 支持连接 MCP Server 和调用 MCP 工具;
- 支持安装包含说明、资源或者脚本的 Skills;
- 脚本型 Skill 可在隔离沙箱中执行;
- 无需注册即可使用,也可以通过 GitHub 登录关联多个设备;
- 使用 SignalR 实时推送画布、Agent 和任务事件。
这意味着 Sol 不只是一个“套壳聊天页面”,而是在尝试构建一个兼顾 AI 内容生成、工作流编排和 Agent 扩展能力的创作平台。
多模型与多协议支持
Sol 的后端没有把业务代码直接绑定到某一家模型厂商,而是按照协议类型组织客户端。
当前源码中可以看到以下协议适配:
| 协议 | 文本 | 图片 | 视频 |
|---|---|---|---|
| OpenAI Chat Completions | 支持 | — | — |
| OpenAI Responses API | 支持 | — | — |
| Anthropic Messages | 支持 | — | — |
Gemini generateContent |
支持 | 支持 | — |
| OpenAI Images | — | 支持 | — |
| OpenAI Video | — | — | 支持 |
| xAI Video | — | — | 支持 |
| Seedance Video | — | — | 支持 |
最新代码还在继续增加视频模型及第三方 AI 渠道支持。
这里有一个不错的设计:浏览器不会直接把 API Key 发送给模型厂商。前端只向 Sol 后端提交模型、渠道和提示词,后端解密保存的 API Key,再调用上游模型服务并保存结果。
这样既避免了 API Key 暴露在浏览器中,也绕开了部分模型接口的 CORS 限制,还方便部署方统一控制出口网络。
后端整体架构
Sol 后端使用 Clean Architecture,拆分成四个 .NET 项目:
Sol.Domain
↓
Sol.Application
↓
Sol.Infrastructure
↓
Sol.Api
各层职责比较清晰:
Sol.Domain:领域实体、值对象和业务不变量,不依赖任何外部 NuGet 包;Sol.Application:用例、业务接口、DTO 和抽象端口;Sol.Infrastructure:PostgreSQL、Redis、RabbitMQ、模型客户端、MCP 和 Skill 的具体实现;Sol.Api:ASP.NET Core Minimal API、SignalR Hub、中间件和依赖注入入口。
从外部服务来看,整体结构大致如下:
浏览器 / Next.js
│
│ 同源代理 /api/*、/hubs/*
▼
ASP.NET Core Sol.Api
│
├── PostgreSQL:身份、账号、画布、模型配置、Agent、Skill、媒体内容
├── Redis:缓存、在线状态、分布式锁、SignalR Backplane
├── RabbitMQ:集成事件
├── SignalR:实时消息
├── AI Provider:文本、图片和视频生成
├── MCP Server:外部工具调用
└── OpenSandbox:隔离执行 Skill 脚本
Sol 的后端技术栈
Sol 后端的核心技术栈如下:
| 类别 | 技术 |
|---|---|
| 开发语言 | C#,启用 Preview 语言版本 |
| 运行时 | .NET 11 Preview |
| Web 框架 | ASP.NET Core Minimal API |
| 编译方式 | Native AOT、自包含原生二进制 |
| API 描述 | Microsoft ASP.NET Core OpenAPI |
| 数据库 | PostgreSQL 18 |
| 数据访问 | Npgsql 10、Dapper 2.1.79、Dapper.AOT |
| 数据迁移 | 内嵌版本化 SQL、事务、校验和、PostgreSQL Advisory Lock |
| 缓存与锁 | Redis 8、StackExchange.Redis |
| 实时通信 | ASP.NET Core SignalR,可选 Redis Backplane |
| 消息队列 | RabbitMQ 4、RabbitMQ.Client 7 |
| 参数校验 | FluentValidation |
| Agent 运行 | 后台 AgentRunHost、流式模型客户端、工具审批 |
| MCP | Streamable HTTP、Legacy SSE、SSRF 防护 |
| Skill 沙箱 | Alibaba OpenSandbox、独立短生命周期容器 |
| API Key 加密 | AES-256-GCM |
| OAuth 登录 | GitHub OAuth,可扩展的外部身份适配器 |
| 日志 | Serilog、Compact JSON |
| 可观测性 | OpenTelemetry、OTLP |
| 健康检查 | 独立的 liveness 和 readiness 端点 |
| 测试 | xUnit v3 |
| 部署 | Docker、Docker Compose、Alpine Native AOT 镜像 |
前端则采用:
- Next.js 16 App Router;
- React 19;
- TypeScript 5;
- Tailwind CSS 4;
- shadcn/ui;
- XYFlow React 节点画布;
- Zustand 状态管理;
- SignalR JavaScript 客户端;
- Vitest 和 Playwright。
Native AOT 是后端的一大特点
Sol 后端一个比较值得关注的地方,是它从设计阶段就按照 Native AOT 的要求开发,而不是等项目完成后再尝试发布成 AOT。
Native AOT 会把 .NET 应用直接编译成本地机器码。部署服务器不需要预装完整的 .NET Runtime,通常可以获得更快的启动速度和更低的运行时开销。不过,它也会限制运行时反射、动态代码生成和程序集扫描等常见用法。
Sol 为此做了不少针对性设计:
- HTTP 和 SignalR 的 JSON 元数据使用源生成;
- 所有 Dapper 查询集中在
Sol.Infrastructure; - 使用 Dapper.AOT 编译查询拦截器;
- 把可能回退到反射的 Dapper 告警升级成构建错误;
- 不使用依赖动态代理的强类型 SignalR Hub;
- FluentValidation 逐个显式注册,避免运行时扫描;
- 配置对象采用手动绑定,避免反射式配置绑定;
- 启动时主动解析关键服务,发现 AOT 注册缺失就立即失败;
- 数据库迁移使用原生 SQL,不依赖 EF Core 的运行时模型构建。
根据项目文档,macOS ARM64 下发布的自包含单文件原生后端约为 25 MB。不过,这个数字与平台、编译器版本和构建配置有关,应将其理解为项目当前的实测数据。
PostgreSQL、Redis 和 RabbitMQ 分别做什么?
Sol 对三个基础组件的分工比较明确。
PostgreSQL
PostgreSQL 是主要的持久化数据库,用来保存:
- 设备和游客身份;
- GitHub OAuth 账号与登录会话;
- AI 渠道和模型配置;
- 加密后的 API Key;
- 画布、节点图和素材分组;
- 图片、视频等二进制内容;
- 视频异步任务;
- Agent 会话、消息和运行事件;
- MCP Server 配置;
- Skills 元数据和文件。
Sol 没有使用 EF Core,而是使用 Npgsql、Dapper 和 Dapper.AOT。
数据库迁移也没有使用传统迁移框架,而是将版本化 SQL 文件直接嵌入后端二进制。执行迁移时会使用 PostgreSQL Advisory Lock 防止多个实例同时修改表结构,并校验已执行脚本的 SHA-256,避免部署环境中的迁移文件被静默修改。
Redis
Redis 主要承担:
- 通用缓存;
- 设备在线状态;
- 多标签页 SignalR 连接记录;
- 分布式锁;
- 多节点部署时可选的 SignalR Backplane。
单节点部署默认不启用 SignalR Redis Backplane,需要横向扩容时再通过配置打开。
RabbitMQ
RabbitMQ 用于集成事件通信。
项目配置了 Topic Exchange、持久化消息、发布确认和死信队列。消费失败时会重试一次,再次失败则进入 DLQ,避免一条无法处理的“毒消息”反复占用消费者。
图片、文本和视频任务
Sol 对不同类型的 AI 生成任务采用了不同的执行方式。
文本和图片通常可以在一次请求中完成,因此使用同步生成接口;视频生成耗时更长,则采用异步任务:
- 浏览器提交视频生成请求;
- 后端调用上游视频接口创建任务;
- 任务 ID 和状态写入 PostgreSQL;
- 后端的
VideoJobPoller定期查询上游进度; - 视频完成后,后端下载文件并保存为画布素材;
- 用户重新打开页面后仍然可以看到任务结果。
这比让浏览器持续轮询模型厂商更可靠,因为用户关闭页面之后,后端仍能继续推进任务。
不过,当前视频轮询器明确按照单 API 实例设计。如果部署多个后端副本,每个实例可能重复轮询同一批视频任务。项目文档也指出,横向扩容前需要增加数据库行锁、FOR UPDATE SKIP LOCKED 或选主机制。
Agent、MCP 与 Skills
Sol 的 Agent 能力和画布是连接在一起的。
Agent 可以获得当前画布的上下文,并通过工具修改或读取画布内容。Agent Run 在后端后台运行,因此不会完全依赖浏览器页面的生命周期。
在 MCP 方面,Sol 支持 Streamable HTTP 和兼容旧版 SSE 的 MCP Server。stdio 配置可以保存,但服务端不会直接启动任意本地进程。
出于安全考虑,MCP 工具调用需要用户审批。MCP 地址还会经过协议校验、DNS 解析和私有网络地址过滤,减少通过 MCP 请求访问内网服务的 SSRF 风险。
Skills 可以包含说明文档、资源和脚本。Agent 开始运行时只获取 Skill 的名称和描述,确实需要时再通过 load_skill 加载完整内容,这样可以减少一次性塞入模型上下文的 Token 数量。
脚本型 Skill 不会直接在 Sol.Api 进程中运行,而是交给 OpenSandbox 创建隔离容器。沙箱默认限制网络、进程数、CPU、内存、文件大小、输出大小和执行时间。即使沙箱暂时不可用,说明型和资源型 Skill 仍然可以正常加载,只是脚本执行能力会被隐藏。
游客优先的身份设计
Sol 默认不要求注册账号。
第一次访问时,后端通过设备握手创建一个确定性的 device_id,并通过第一方 Cookie 保存。所有画布、渠道配置和素材首先按照设备隔离。
用户也可以使用 GitHub OAuth 登录。登录成功后,当前设备会被明确关联到账号,账号关联的多个设备可以访问同一份云端数据。
值得注意的是,Sol 还实现了设备信号和概率性设备关联,但概率匹配只用于判断访问关系,不会直接作为敏感资源的所有权依据。真正的画布、API Key 和素材权限仍基于确定性的设备 ID 或已验证的账号会话。
这套设计降低了游客使用门槛,但设备指纹本身涉及隐私和合规问题。公开部署时,仍然需要根据 GDPR、ePrivacy、中国《个人信息保护法》等要求完善告知、同意、数据保留和删除流程。
安全方面做了哪些处理?
从当前源码来看,Sol 已经考虑了不少常见的 AI 应用安全问题:
- 模型 API Key 使用 AES-256-GCM 加密保存;
- API 返回渠道配置时只展示脱敏后的 Key;
- 加密密钥缺失或格式错误时,服务会在启动阶段直接失败;
- 所有业务资源通过设备或账号范围过滤;
- 不属于当前用户的资源统一返回 404,减少 ID 探测;
- 上传素材同时校验 MIME 类型和文件签名;
- 后端不会主动下载用户填写的外部参考图片,降低 SSRF 风险;
- MCP Server 地址会过滤环回地址、私网地址和保留地址;
- Skill ZIP 会检查路径穿越、符号链接、嵌套压缩包和异常压缩比;
- 可执行 Skill 在独立容器中运行;
- API 进程本身不会挂载 Docker Socket;
- 数据库迁移带锁、事务和校验和;
- 日志不会返回明文渠道密钥。
这些措施说明 Sol 并不是只关注界面和功能,也在认真划分模型调用、用户数据、外部工具与脚本执行之间的安全边界。
如何本地运行?
如果只是想快速体验,可以直接使用 Docker Compose:
git clone https://github.com/AIDotNet/Sol.git
cd Sol
docker compose up -d --build
docker compose ps
当前 Compose 文件包含:
- PostgreSQL;
- Redis;
- RabbitMQ;
- OpenSandbox;
- Sol.Api;
- Next.js Web。
启动完成后打开:
http://localhost:3000
然后进入设置页面,添加一个 AI 渠道和对应的 API Key,即可尝试文本、图片或视频生成功能。
如果需要分别调试前后端,可以只启动基础设施:
docker compose up -d postgres redis rabbitmq opensandbox
dotnet run --project src/Sol.Api
然后启动前端:
cd web
cp .env.example .env.local
npm install
npm run dev
需要注意,项目目前锁定的是特定版本的 .NET 11 Preview SDK,global.json 禁用了自动版本滚动。非 Docker 环境开发时,必须安装项目要求的精确 SDK 版本。
这个项目适合谁?
Sol 比较适合以下几类开发者:
- 想搭建可视化 AI 内容创作平台的人;
- 希望统一接入文本、图片和视频模型的人;
- 正在研究 AI Agent、MCP 和 Skills 的开发者;
- 想学习 .NET Clean Architecture 的开发者;
- 想研究 ASP.NET Core Native AOT 实战的人;
- 希望私有部署 AI 工作台的团队;
- 想寻找 Next.js、React Flow 与 .NET 后端完整案例的人。
尤其是后端部分,Sol 把 Native AOT、Dapper.AOT、SignalR、Redis、RabbitMQ、MCP 和沙箱执行放进了同一个真实项目中,具有不错的学习和参考价值。
目前需要注意的地方
Sol 仍处于积极开发阶段,还不适合不经评估就直接作为大型生产系统使用:
- 使用精确锁定的 .NET 11 Preview SDK;
- 视频任务轮询目前按照单 API 实例设计;
- SignalR Redis Backplane 虽经过项目方 AOT 实测,但相关包尚未得到微软完整的 AOT 兼容性背书;
- 图片、视频和 Skill 文件目前默认保存到 PostgreSQL,部署规模扩大后需要评估数据库容量、备份时间和对象存储方案;
- 设备指纹及跨设备关联需要额外的隐私合规设计;
- Docker Compose 中的密码和加密密钥是开发环境占位值,生产环境必须替换;
- GitHub OAuth 默认关闭,需要自行创建 OAuth App;
- 将 MCP、Skill 脚本和外部模型服务开放给真实用户前,仍需完成权限、限流、审计和安全测试。
把它看成一个完成度较高、架构思路鲜明的开源 AI 工作台和技术参考项目,会比把它直接定义为成熟商业产品更准确。

部署的在线站点 https://sol.routin.ai/
总结
Sol 将可视化节点画布、文本生成、图片生成、异步视频任务、Agent、MCP 和 Skills 放进了一个完整的全栈项目中。
它的前端强调画布式交互,后端则以 ASP.NET Core、Clean Architecture、PostgreSQL、Redis、RabbitMQ 和 Native AOT 为核心,并对 API Key、设备身份、MCP 网络访问及 Skill 脚本执行划分了较明确的安全边界。
如果你正在寻找一个完全开源、可以自行部署,又包含现代 .NET 后端和 Agent 扩展能力的 AI 项目,Sol 值得关注。
项目地址:
浙公网安备 33010602011771号