DisPatch:一款用于本地AI代理的自托管聊天应用

发布日期
2026年7月11日
更新日期
2026年10月9日
作者
Jacob Lloyd —— 项目完成后,在 AI 协助下撰写
阅读时长
约 17 分钟阅读

简单来说: DisPatch是一款聊天应用,它运行在您自己的电脑上,并且可以在家中的任何手机或笔记本电脑上使用。您可以通过它与同样运行在该电脑上的AI助手进行对话,还能将文件发送到电脑上供这些助手处理。一个PIN码机制确保了那些功能强大的AI助手不会被随意调用;因此,在这台供全家共用的设备上,用户只能使用那些经过安全授权的功能子集。

DisPatch是我自己开发的应用程序,目的是不再需要运行包含30个容器的 Rocket.Chat 环境来与我自己的AI代理进行交流。它仅由一个Python进程和一个SQLite数据库文件构成。家中的任何设备都能访问它;这些AI代理会像人类一样在各自的对话线程中回复信息。只要我把文件从手机上传到DisPatch,它们就会立刻出现在那些AI代理运行的机器上。2.0.0版本于2026年10月9日发布:下载包为3 MB的ZIP文件,其内置的测试套件能顺利通过1,915项测试。本页面介绍了该应用的功能、回复信息如何精准地发送到您的手机上,以及PIN码锁定机制如何防止家庭中的平板电脑被那些能够执行实际操作的AI代理所利用。

简而言之:

  • 这是什么:一个专为本地AI代理设计的自托管式网页聊天工具(可作为 OpenClaw 网关使用,也可对接其他模型API);同时具备文件拖放功能,任何能访问主机的设备均可使用。
  • 费用:免费。无需购买SaaS服务或注册账号。
  • 所需条件:安装了Python 3.12及以上版本与 uv 工具的Linux系统,或者Docker环境即可。若需要能调用外部工具的AI代理,则需安装OpenClaw。
  • 功能亮点:为每个AI代理设立独立对话线程;支持带有“停止”按钮的实时回复流、内容重新生成与编辑功能;具备文件拖放能力;可嵌入各类工具与应用;提供十种主题样式;设有受PIN码保护的服务器级安全模式;还配有适用于定时任务的推送API。
  • 下载方式:可获取2.0.0版本安装包,该版本与公开代码库中的 v2.0.0 标签对应。采用MIT许可协议。

功能介绍

这些截图均来自一个使用模拟数据运行的沙盒环境。前四张截图来自 2.0 版本;“安全模式”与“文件服务器”相关的截图则来自 7 月份的测试版,不过它们在 2.0 版本中的运作方式完全相同。

在默认的 Glacier 主题下运行的 DisPatch 2.0:画面左侧为三个机器人头像栏;右侧是按日期分组的对话列表,其中某条回复以项目列表及可排序的对比表格的形式呈现了一日游计划。
桌面端界面,1440像素分辨率,Glacier主题:包含机器人头像栏、对话列表以及聊天面板。计划内容与表格均通过 Markdown 渲染生成,且表格支持按列排序。
在 Forest 主题下显示的回复内容:一个包含四项家务事项的清单表格,每行均配有复选框以及可排序的“任务”、“执行者”与“时间”列。
2.0版本新增的清单表格功能:由机器人发布后,任何用户均可勾选完成状态,这些标记会同步至所有设备上。
分辨率为390像素的 DisPatch 移动端界面:单面板式对话界面,包含以 Markdown 格式呈现的编号列表与购物清单;每条消息旁均有“复制”按钮及菜单选项;底部设有 Bots、Chats 与 Messages 三个标签页。
同样的应用在390像素分辨率下的显示效果。机器人头像栏会收缩为底部的标签页。每条消息均配有“复制”按钮以及 ⋯ 菜单,后者包含重新生成、编辑、引用等功能选项。
设置界面中的主题选项卡:显示六个核心主题的实时预览效果,另有一个“更多主题”区域可供选择另外四个主题。
设置 → 主题:提供十个主题供选择,每个主题均有实时预览功能,且可针对不同设备单独配置。
设置 PIN 码后进入的安全模式界面:机器人头像栏仅显示三个被标记为“安全”的机器人;底部有一个琥珀色锁形按钮用于解锁其余机器人。
设置了 PIN 码后的安全模式:仅列出被标记为“安全”的机器人。服务器不会向客户端发送其他机器人的相关信息。
  • 跨设备同步对话记录:即便在手机上中途加入对话,显示的也是带有完整历史记录的同一对话流。用户可对对话进行置顶、归档、重命名及搜索操作。
  • 流式 Markdown 回复功能:支持语法高亮的代码块与复制按钮;图片与视频则可通过弹窗预览;此外还提供可安装的 PWA 应用。
  • 实时运行状态面板与停止按钮:状态栏会显示当前任务进展(如模型加载、内容生成或工具调用)。点击输入提示符即可查看智能体的思考过程及工具调用情况;按下“停止”按钮则可中断当前任务。
  • 常规聊天应用控制功能:“重新生成”可保留之前的回复内容;用户可编辑任意消息并重新发送;还可引用回复、进行点赞/点踩操作或将其从对话上下文中移除。每个对话均可单独指定所使用的模型及推理深度级别,同时有一个进度条显示当前上下文的使用情况。
  • 草稿与离线发送功能:未发送的消息会保留在对应对话中;即便在网络中断时发送消息,系统也会待网络恢复后自动发送。
  • 工具与应用集成功能:点击“工具”按钮即可调用应用内的各类项目:静态文件夹、网页内容或自带后端与智能体的可信应用包。“任务面板”即为首个预置应用。
  • 两种 AI 交互方式:用户可在设置面板中将某个机器人直接绑定至模型 API(如 LM Studio、Ollama、OpenAI、Anthropic 或任何兼容 OpenAI 的接口);也可通过 OpenClaw 网关连接那些需要调用工具并在本地执行操作的智能体。
  • 推送式 API 功能:POST /api/inject 接口允许定时任务或其他智能体向指定对话中插入消息。正因如此,每日晨间简报能在无需我手动操作的情况下自动推送到手机上。
  • 双层安全锁机制:PIN 码将具备完整权限的智能体与仅具备受限功能的“安全型”智能体区分开来。更多细节将在下文说明。
  • 主机控制面板:可查看系统健康状态、存储空间使用率、数据库完整性及备份情况;同时还会列出所有配置不当的项目。
  • 多语言与主题支持:提供八种界面语言,包括从右向左书写的阿拉伯语;另有十个主题可供选择。
  • 本地文件预览功能:点击消息中的文件路径即可在应用内直接打开相应文件,即便是在手机端也是如此。只有在用户指定文件夹后系统才会启用此功能,且绝不会泄露任何敏感信息或系统路径。

智能体还可向对话中插入图片。只需在回复中加入 [[pic:prompt|caption]] 标记,即刻会显示占位符;待图片渲染完成后便会自动呈现实际图像。这些图片均由网络中的 GPU 服务器生成。若该服务器出现故障,则占位符会提示相关情况而非静默失败。

文件服务器

这是我最常用的功能。在任何设备上打开 DisPatch,将文件拖放到其中,文件便会上传至服务器;它们会按日期分组显示,图片和视频还会显示缩略图。

DisPatch文件服务器界面:顶部为上传区域,下方是按日期分组的文件列表,包含图片缩略图及文件类型标识。
文件服务器界面:顶部为上传区,下方是按日期分组的文件。在手机上,这就是完整的操作流程。

其价值在于文件的存储位置:它们就保存在运行代理程序的同一台机器上。比如我从手机上传的照片,几秒钟后就能被代理程序读取到;这样我就可以对照片进行描述、归档或发布到网站上,完全无需云盘或数据线。

代码中还设置了多种保护措施以防止常见故障发生:

  • 在 FastAPI 缓冲上传内容之前,会先检查文件大小是否符合限制,从而避免手机端上传过大文件导致主机内存耗尽。
  • 默认情况下总存储空间上限为20 GB(由 DISPATCH_FILES_TOTAL_MAX 参数控制;设为0即关闭此限制)。
  • 每个上传的文件都会先写入临时文件,同步完成后才重命名为正式文件名,这样即便连接中断也不会留下不完整文件。
  • 被锁定的设备只能进行单向上传操作:它们可以向服务器发送文件,但无法浏览或下载服务器上的任何内容。

为何我选择自己构建,而非使用现有的 UI?

Rocket.Chat 确实能用,但为了实现“发送文本、接收回复并同步到各处”这一简单功能,却需要维护数据库以及大量容器,这实在是一种资源浪费。

对于“自托管式 AI 聊天应用”的需求,通常的解决方案是 Open WebUI 或 LibreChat,它们在与模型交互方面表现不错。不过我的需求有所不同:我希望有智能代理能参与到全屋共享的对话中;希望服务器能对儿童使用的设备施加访问限制;需要一个 HTTP 端点供脚本发送数据;还需要让文件能直接被那些智能代理读取。DisPatch 正是为了满足这些需求而诞生的。如果你只是想要一个漂亮的模型前端界面,那选择上述两者中的任何一个即可。

此外,DisPatch 无需任何构建步骤。其前端仅由纯 JS 模块以及普通的 CSS/HTML 构成,既不需要打包工具,也无需执行 npm run build。最初设定这一要求时,我的目标是“便于日后由 AI 代理进行修改”:只需编辑文件后刷新页面即可完成更改。如今我依然会做出同样的选择。

下载包中包含的内容

该压缩包名为 dispatch-2026-10.zip,即 DisPatch 2.0.0 版本。其内容与 公开代码库中的 v2.0.0 标签完全一致。我针对此版本做了如下检测:

项目详情
下载大小2,992,647 字节(2.9 MB);共319个文件;解压后大小为7.9 MB
SHA-256e9824d3c13bb3acd2d2eebcf2b162b14ae26eb86f56ca0e4ac8aa20f686a2398
后端需要 Python 3.12+;使用 FastAPI 与 uvicorn;包含一个 SQLite 数据库文件,由 uv 进行管理。backend/app/ 目录下共有36,501行代码(其中 main.py 有12,331行),此外捆绑的“任务板”应用还包含5,497行代码
测试共有30,726行 Python 测试代码;pytest 显示 1,915项测试全部通过;另有473项前端测试可通过 node --test 运行
前端未经过构建的原生 JavaScript代码:除第三方库与测试代码外,还有约21,000行代码;另外还有约9,300行 CSS与 HTML代码
第三方库marked、highlight.js、DOMPurify。未调用任何 CDN服务
数据文件默认情况下位于 ~/.local/share/local-chat/(该项目的旧名称)目录下:包含数据库、config.yaml、security.yaml、多媒体文件以及定期备份的数据库文件
许可证MIT

自8月份的1.0.0版本压缩包发布后,有哪些变化呢?

  • 回复处理效率提升且不会丢失。 现在消息会通过已建立的 WebSocket连接发送至代理网关,而无需为每条消息单独启动一个新的 openclaw 进程。经实测,每次回复所需时间减少了约1秒(固定开销从2.26秒降至1.12秒)。模型生成文本后会实时流式传输至客户端。系统会持续跟踪每一条成功接收的回复直至其完全送达,因此即便连接中断或服务器重启,回复也能顺利发送。
  • 许可证变更。 1.0.0版本采用 AGPL-3.0 许可证;2026年8月30日起项目改以 MIT 许可证发布,2.0.0版本亦遵循此许可证。此前的7月和8月发布的压缩包仍保留原地址,且各自附带了对应的 LICENSE 文件。
  • 编程终端功能已移除。 1.0.0版本曾提供可选的浏览器内终端功能(服务器端通过 PTY将输出流传输至 xterm.js)。由于我后来不再使用相关的编程代理工具,故2.0版本移除了该功能及其依赖的第三方库。当安装了 dsh 后,DeepSeek Harness 面板可承担原终端的功能:支持启动、监控及终止实时会话。
  • 新增功能: 对话控制、草稿与待发送消息管理、工具与应用集成、清单表格、本地内容预览器、图片标记功能;此外还新增了10种主题以取代原有的明暗模式切换选项,同时优化了消息行的视觉表现。完整更新列表可查阅代码库中的 CHANGELOG.md 文件。

设置方法

以下内容摘自压缩包中的 README.md 以及 docs/ 目录。这只是一个普通的 uv 项目:

unzip dispatch-2026-10.zip
cd DisPatch-2.0.0/backend
uv sync --frozen
uv run pytest -q          # 1,915 passed on my machine
uv run uvicorn app.main:app --host 0.0.0.0 --port 8765

或者跳过 Python 步骤:在解压后的目录顶层执行 cp .env.example .env && docker compose up -d。deploy/systemd/ 目录下包含了用于实现常驻运行模式的服务单元文件;而 docs/deploy-bare-metal.md 则说明了一个常被忽略的步骤:loginctl enable-linger。否则,当你关闭 SSH 会话后用户服务就会停止运行。

  • 首先设置 PIN 码(点击齿轮图标,然后选择“安全”选项)。上述两个命令均监听 0.0.0.0,因此在设置 PIN 码之前,网络上的任何人都能完全访问该服务。在初步测试时,可使用 --host 127.0.0.1(或在 Docker 环境下使用 BIND_ADDR=127.0.0.1),并且切勿将该端口转发到互联网上。
  • 编辑数据目录下的 config.yaml 文件,确保其中配置的机器人 id 与你的 OpenClaw 代理端 ID 相匹配。该文件发生变动时会自动重新加载。
  • 所有配置参数均通过以 DISPATCH_ 为前缀的环境变量来设定,具体选项可在 .env.example 中查看:HOST、PORT、DATA_DIR、AGENT_TIMEOUT(默认值为 900 秒)、MAX_CONCURRENCY(默认值为 3)以及 GATEWAY_WS。
  • DISPATCH_MAX_CONCURRENCY 用于限制同时运行的代理数量。默认值设为 3,这样可保护运行本地模型的机器。若有第四个请求出现,它会排队等待而非被丢弃。

DisPatch 本身并不包含 OpenClaw。对于代理端而言,它要求同一主机上必须有 OpenClaw 网关才行。即便没有该网关,程序依然能启动并输出相应警告信息。此时线程管理、注入 API、文件服务器、PIN 码锁定机制、各类工具以及模型调用接口均仍可正常使用。我正是采用这种方式来测试压缩包:直接解压后执行 uv sync,选用一个空闲端口,且无需配置网关。

回复是如何送达您的

我们花费大量精力处理各种异常情况:比如回复发送过程中连接中断、服务器重启时任务仍在进行中,或者某个子代理延迟十分钟才给出回复。传输方式由 DISPATCH_GATEWAY_WS 决定。若该参数未设置,则每条消息都会触发一个 openclaw agent,该进程在运行结束后将回复返回。而 shadow则会模拟连接过程并记录本应发送的内容,但实际并不真正发送。当设为 1 时,消息会通过网关套接字发送,回复也会通过该套接字流式传输回来。我目前使用的就是 1 设置。压缩包中该选项默认处于关闭状态,因此在您手动开启之前,回复的送达方式不会发生任何变化。

开启套接字后,网关所接收的所有任务都会被记录到“进行中任务表”中,随后通过网关自身的“等待指定任务完成”机制完成处理。即便实时传输链路中断,任务结束后回复依然能顺利送达;服务器宕机时那些处于处理状态的任务也能在重启后被恢复。只有网关完全未接收过的任务才会被重新发送,从而确保不会出现重复发送的情况。

关于后备机制有一点需要注意:转录文件扫描功能需要读取 OpenClaw 生成的会话文件;不过较新版本的 OpenClaw 已将会话信息存储至数据库中。在此类环境下,DisPatch 会在启动时提示基于文件的后备机制无法运行,此时套接字便成为唯一的回复传输途径。这也是建议开启套接字功能的另一个重要原因。

无论通过哪种途径送达,所有候选回复都会经过同一个去重流程检查:若某回复已被发送过,即便多次出现也只会显示一次。即便 CLI 端发生错误,扫描机制仍会在放弃前执行,因为模型往往在进程崩溃前便已将回复内容写入转录文件了。

双层锁定机制:普通模式与安全模式

未锁定的模式可不是儿戏。在该模式下,系统允许相关程序编辑代码、将更改推送至我的在线网站、运行各种工具并管理所在的服务器。而锁定模式则仅支持常规聊天功能;虽然仍能用于提问或寻求帮助,但无法执行上述操作。由于家庭电话并非始终由成年人使用,因此服务器会强制启用锁定机制。以下是请求的处理流程:

除非在安全设置中手动开启,否则‘记住设备’功能默认处于关闭状态;开启后,可信设备的有效期为30天。点击已标记为可信设备的‘锁定’按钮可使其不再被信任;更改PIN码则会使所有已标记的可信设备均失去信任资格。服务器最多仅能记录10台可信设备。若存储可信设备信息的文件损坏,则所有设备均被视为不可信,不过PIN码验证功能依然可用。

倘若因操作失误导致自己无法登录,可通过两种方式恢复访问权限:使用恢复代码文件,或直接编辑security.yaml配置文件。若security.yaml文件本身已损坏,系统则会保持锁定状态,而不会向局域网内的任何用户开放服务。此设计是出于安全考量而特意如此设定的。

注意事项/易错点

  • 注入 API 的字段名为 content。 POST /api/inject 要求的请求体格式为 {"bot_id": "...", "content": "..."}。发送纯 text 是最常见的集成错误,我也犯过这个错。
  • 切勿将长消息作为 CLI 参数传递(即使在回退路径下这也很重要)。Linux 对单个参数的长度限制为 128 KB(MAX_ARG_STRLEN),过长的消息会导致进程启动失败并出现 E2BIG 错误。正确的做法是将消息写入临时文件,然后传递 --message-file 参数。千万别为了“简化”操作而又把消息当作参数使用。
  • 会话密钥需小写,但机器人 ID 则不必。 OpenClaw 会将会话密钥转换为小写形式,不过你的机器人 ID 可以包含大小写混合字符(如 Alpha、My_Bot)。如果采用区分大小写的匹配方式,虽然其他功能仍能正常运行,但面板显示及延迟回复功能会失效。正确的修复方式是先执行精确匹配,再尝试小写形式作为后备方案。
  • CLI 仅返回最终生成的内容块。 由于没有使用套接字通信,智能体在多次工具调用之间输出的内容只会保存在其转录记录中。正因如此才有了转录记录清理机制;即便启用了套接字通信,该机制仍会作为后备措施继续运行。
  • 处理 WebSocket 请求时需校验 Origin 字段。 HTTP 中间件不会对 WebSocket 路由生效。DisPatch 会在握手阶段进行身份验证:若 Origin 中的主机名与 Host 不匹配,请求就会被拒绝,这样能有效防止跨站点的 WebSocket 劫持行为。非浏览器客户端不会发送 Origin 字段,因此可顺利通过验证。
  • 绝不可将上传的 SVG 文件当作图片来展示。 直接打开 SVG 文件可能会在其所在源站点中执行恶意脚本,从而形成存储型 XSS 漏洞。DisPatch 会拒绝将 SVG 视为媒体文件,且发送给客户端的所有媒体内容均会附带沙箱化 CSP 策略与 nosniff 指令。
  • Service Worker 更新会导致旧标签页仍运行旧版 JS。 这种现象看起来就像程序出现了回退。解决办法就是在触发 controllerchange 事件时自动刷新页面。

实现思路解析

即便您从未运行过我提供的压缩包,整个架构其实由四个可替换的组件构成:

  • 聊天后端:负责管理对话历史记录。它由一个小型 Web 服务器构成(此处使用的是 FastAPI 以及以 WAL 模式运行的 SQLite 数据库),还包含一个用于实时更新的 WebSocket 接口,以及一个用于接收消息的普通 HTTP 端点。这个组件取代了传统数据库及众多容器的作用。
  • 代理网关:后端程序通过它与其他服务通信。此处使用的是 OpenClaw,但实际上任何能够接收会话 ID、消息内容并返回文本的服务均可胜任此角色。由于它是独立运行的进程,即便发生崩溃或需要升级,也不会影响聊天应用的正常运行。
  • 模型服务器:位于网关之后,包括 LM Studio、vLLM 以及 Ollama。这些服务器的管理属于网关的职责范围,与聊天应用并无直接关联。
  • 可选的媒体服务:比如运行在另一台机器上的图像生成器,可供各类代理作为工具调用。后端仅需存储其返回的结果即可。

无论您采用何种技术栈,以下原则都同样适用:

  • 务必在服务器端强制启用锁定模式,切勿仅依赖 CSS 来实现。
  • 将“消息必须仅被发送给用户一次”视为需要解决的传输问题,并为此设计去重机制。
  • 如果后续由 AI 代理负责维护前端界面,那么尽量保持前端无需编译即可运行的状态。

相关链接:基于 OpenClaw 的本地 AI 代理堆栈 · DeepSeek Harness 初探 · 利用本地 AI 代理管理个人网站 · 如何搭建自己的 LLM 助手

下载

仅限个人使用免费。如果它替你省下了一下午的时间,欢迎点旁边的咖啡按钮支持一下。


← 更多AI 与本地 LLM