桌面墨水屏接入本地 Agent:结构化协议、刷新预算与断连自愈

发布时间:2026/9/18 20:18:23
桌面墨水屏接入本地 Agent:结构化协议、刷新预算与断连自愈 1. 为什么把「显示什么」这件事交出去而不是继续写定时脚本桌上多一块屏这件事我从三年前就开始折腾了。先是拿旧平板当副屏后来换成手机常亮显示日历再后来是各种小尺寸 LCD 模块。这些方案全都活不过两周——要么亮得晃眼要么一整天在充电要么显示的内容三天不更新我自己都懒得瞟一眼。最后真正留下来的是块 7.5 寸的桌面墨水屏不发光、断电留存、一天刷几次就够。但留下来之后新的问题来了给桌面墨水屏喂什么内容。我一开始走的是最常规的路子写个脚本定时拉天气、拉日程、拉待办拼成一张图推过去。跑了几个月屏幕上的东西基本没变过我自己都产生了视觉盲区。后来我把这块屏接给了一个本地跑的桌面端 Agent让它自己决定现在这一刻屏幕上该出现什么顺便把手上的内测机 MIMO X 也拉进来做了一轮对照测试。这篇文章讲的就是这一整套链路Agent 怎么变成屏幕的内容生产者、墨水屏这端的物理约束是什么、以及内测设备在真实桌面环境里暴露了哪些问题。先说清楚适合谁看。如果你手上有一块闲置的墨水屏、或者正在考虑给桌面加一块低干扰信息屏并且对 Agent 有点兴趣但不知道能拿它干点具体什么活这篇的路径可以直接抄。如果你只是想找个屏挂时钟那这套方案属于杀鸡用牛刀用现成的固件更省事。整条链路里唯一聪明的部分只有一处——决定显示什么其余全是笨功夫而这些笨功夫恰恰是能不能稳定跑一周的分水岭。1.1 定时脚本真正的崩溃点在哪很多人以为定时脚本的问题是不够灵活其实不是。它的崩溃点是内容生命周期和刷新周期错配。拿周报日历举例日程是每天变的但我的脚本每 30 分钟刷一次意味着一天里有 47 次刷新在展示完全一样的内容。墨水屏的每一次刷新都是有物理代价的虽然不至于刷几次就坏但这种无意义刷新累积下来既浪费电又加速残影堆积。反过来如果设成一天刷一次那突发事件临时改的会议、刚收到的包裹提醒就完全捕捉不到。第二个崩溃点是布局写死。我最早那版是把天气放在左上、日程放右上、待办占下半屏位置是硬编码的。结果有一次待办有 12 条文字直接溢出屏幕底部被裁掉另一次日程为空屏幕中间空了一大块丑得我第二天就把脚本改了。修法是加了折行和截断但那是头痛医头。真正让我下决心换掉的是第三个问题数据源换了要改代码。我从一个日历服务换到另一个字段名全变了改完解析逻辑又要调布局。这些都是我在干活不是工具在干活。1.2 Agent 接管的是决策不是像素这里有个很关键的分工绕开它整套东西就会变成一团乱麻Agent 只负责决定展示哪些信息、以什么优先级、用什么类型的卡片绝不负责决定像素画在哪。我试过让模型直接吐 Markdown然后拿现成的渲染库转图。翻车翻得很彻底模型有时吐三级标题、有时吐表格、有时吐一段带缩进的代码块同样的信息量占用的高度能差三倍。有一次它认为某个待办特别重要加了满屏的星号装饰直接导致下半屏的天气卡片被挤没。让语言模型去控制排版等于把布局的稳定性交给一个概率分布。正确的切法是两层模型输出结构化数据下面第 2 节细讲协议渲染层拿数据做确定性的布局计算。渲染层永远只认那几个字段字段超长就截断卡片放不下就按优先级丢逻辑完全可控。这样一来模型再怎么发挥也不会把屏幕搞崩。1.3 墨水屏的物理特性反过来约束了 Agent 的设计墨水屏这几个特性必须提前想清楚它们会一路反向影响 Agent 的提示词和调度策略刷新慢。全屏刷新通常要两秒往上快刷模式能压到一秒内但代价是残影。这意味着屏幕上不能出现每秒变一次的东西进度条、倒计时秒数全部出局。只能显示静态帧。没有局部动画的余地任何动态信息都得转成快照 时间戳的形式。断电留存。这是最大的优势意味着设备离线、Agent 挂掉、电脑关机屏幕上的内容还在。所以设计的重点不是实时而是最后一帧足够有用。无背光。白天靠环境光晚上不开灯就是一块黑。如果你的桌面晚上主要靠台灯得考虑侧向补光否则内容等于不存在。这四条合起来其实给 Agent 划了一个非常清晰的活动范围低频、离散、快照式、以可读性为最高优先级。后面所有的坑基本都是因为某一次我忘了这个范围。2. 从模型输出到屏幕像素我给 Agent 定制的输出协议整套系统里我改动最多、也最值钱的部分就是这个协议。它不长但每一个字段都是被坑出来的。2.1 卡片式 JSON字段设计背后的取舍最后稳定下来的结构大致是这样用一个带版本号的顶层对象包住一组卡片{ version: 1, generated_at: 2026-01-14T09:12:0008:00, ttl_seconds: 3600, priority: 2, cards: [ { type: schedule, title: 今天, items: [ {time: 10:00, text: 项目对齐会, flag: important}, {time: 14:30, text: 供应商电话} ] }, { type: note, title: 提醒, text: 牛奶没了回家路上买 } ] }几个字段值得单独说version看着多余但没有它我改一次渲染层就得同时改模型侧的输出格式两边不同步的时候设备上出现的是乱码级别的画面。加了版本号之后渲染层可以拒绝不认识的高版本输出直接保留上一帧。ttl_seconds卡片自己的保质期。日程卡片我一般给 3600 秒一句提醒给 6 小时。过期之后调度器会主动请求新内容而不是等下一个固定时间点。这一条把刷新周期从固定值变成了数据驱动的值。priority用来和设备的刷新预算做仲裁。高优先级的卡片可以打断静默时段低优先级的只能在反正要刷一次的时候搭车。type渲染层为每种 type 写一个固定的布局函数。常见的就那么几种——日程、清单、一句话提醒、图像、状态条。type 的数量一定要克制我有段时间加了七八种结果每种都要单独调中文字号和折行维护成本爆炸。2.2 渲染层放在电脑侧而不是设备侧这个决定我几乎没有犹豫理由是算力、字库和迭代速度方案优势代价设备端渲染ESP32 上排版、取字模传输量小只传文本中文字库占用大只能内嵌极少数常用字排版逻辑改一次就得重新烧录字号选择极其有限电脑侧渲染转 1-bit 位图后推流字体随便用排版随便改改的是电脑上的 Python 脚本不是固件传输量上升一屏 800×480 的 1-bit 图约 48KB我选后者。原因是迭代成本调中文字号、调行距、调卡片间距如果每次都要重新烧录固件我大概第三天就放弃了。而一屏 48KB 这个量级在局域网里推一次几十毫秒就完事一天刷几十次也完全不是问题。压缩之后更小——墨水屏图像是大片纯色RLE 或者 zlib 之后经常能压到原来的十分之一不到。真正的收益是字体自由。我可以在标题上用一套比较粗的黑体、正文用另一套笔画清晰的黑体这两个选择直接决定了小字号下能不能看清。2.3 折行、截断与字号搜索中文排版的三个硬骨头在 1-bit 屏幕上排中文比在手机屏幕上难一个量级。我踩的三块硬骨头**第一块是宽度计算。**中文是等宽的但混合数字和英文之后就不是了。我一开始用字符数 × 字号估算宽度结果会议 14:30这种混合文本算出来总是偏窄右边被裁掉一点。后来改成老老实实用图像库的字形度量接口逐个字符测量宽度再累加速度慢一点但结果准确。这一步没有捷径。**第二块是折行规则。**中文可以在任意字符之间断行但不能在标点前面断也不能把数字和时间从中间劈开。我简单加了个规则表遇到逗号、句号、右括号这类字符时不允许作为行首遇到冒号和连字符时不允许作为行尾。规则不多但效果立竿见影。**第三块是字号搜索。**卡片的文字长度完全不可预测固定字号一定会有溢出或者大片留白。我的做法是从期望字号开始往下降每次降一档就重新折行测量直到总高度装得进卡片为止如果降到最小可读字号还装不下就按行截断并加省略号。这个循环最多跑五六次耗时可以忽略但它彻底消灭了文字溢出被裁这个问题。注意一个反直觉的点字号搜索的下限不能设太低。如果允许它一直降到 8px遇到超长文本它真的会降下去最后页面上会出现一屏完全看不清的小字反而不如截断加省略号。2.4 抖动、二值化和压缩哪些图该抖哪些绝对不能抖灰度处理这块我走了弯路。墨水屏能显示 4 级甚至 16 级灰度但需要多次刷新叠加。对于文字我强烈建议直接二值化——只有纯黑和纯白边缘最锐利。文字如果用误差扩散抖动笔画边缘会出现一圈噪点小字号下直接糊成一团。对于图片比如我偶尔会推一张二维码或者天气图标抖动就有必要了否则大面积灰色会变成一道道的黑条纹。我用的是有序抖动比误差扩散速度快很多而且在墨水屏上观感更稳定。压缩这块没什么特别的整张位图先做一次行程编码把大片连续的同色像素压掉再叠一层通用压缩。实测一屏文字为主的画面压完通常只有几 KB设备端解压的开销也很小。3. ESP32 这一端局刷残影、中文字形和刷新寿命屏幕背后的驱动板是 ESP32 方案的这套东西网上资料很多但真正用起来麻烦全在细节里。这一节讲的是设备端那几个绕不过去的物理约束。3.1 局部刷新不是免费的残影累积与全刷补偿局部刷新快、闪得少用起来很爽。但它有个代价残影会累积。同一块区域的像素反复在黑白之间切换几次之后就会留下淡淡的前一帧痕迹。我最早为了追求响应快所有更新都走局刷结果一周之后屏幕右下角的时长区域出现了明显的重影两三个数字叠在一起特别难看。解决办法是做全刷补偿维护一个计数器每 N 次局刷强制做一次全屏刷新把整屏电荷状态重置一遍。N 的取值需要试——太小了闪得烦太大了残影压不住。我这块屏最后定在 8 到 12 之间。这个数字和屏幕型号、刷新内容都有关系没有通用值只能自己试。还有一个容易忽略的点局刷的区域要和卡片布局对齐。我有次让局刷区域跟着内容高度动态变化结果区域边界正好落在文字中间那一行文字被切成了两半上半清晰下半发灰。后来我把所有卡片高度都吸附到 8 像素的网格上问题就消失了。3.2 中文字号的下限是算出来的小字号中文在 1-bit 屏幕上到底多小还能认这个我没靠感觉而是打印了一张测试图贴到屏幕旁边在不同距离下看。结论是这样的在正常桌面视距大约 60 到 70 厘米下中文正文小于 16 像素高笔画开始粘连尤其是警囊这类笔画密集的字基本靠上下文猜。标题 24 像素以上就比较舒服了。如果是给站在一米外的人看正文至少要 20 像素。所以我在渲染层里定死了三个字号档标题 28、正文 18、次要信息 15不允许字号搜索突破 15 这个下限。字体选择上笔画粗细均匀的黑体明显优于带衬线的字体衬线在 1-bit 下那些细笔画直接消失。3.3 刷新耗时、温度和供电三件容易被忽视的事刷新耗时。全屏刷新在两秒到四秒之间取决于屏幕尺寸和固件。这意味着你的调度器必须知道一次刷新还没结束不能在刷新过程中再推一张图进来。我的做法是设备端刷完之后回一条确认电脑侧收到确认才发下一帧中间加超时重传。温度。低温下墨水屏刷新会明显变慢北方冬天桌面靠窗的话早上第一次刷新可能要五六秒。如果这时候程序认为超时了并重发就会出现刷到一半被打断的花屏。我的经验是把超时阈值在冬天调大一倍宁可等。供电。这是最容易被忽略、后果最严重的一条绝对不要在刷新过程中断电或者复位。墨水屏在刷新的瞬间会有一段电荷状态不确定的窗口这时候掉电轻则留下半屏残影要做几次全刷才能清掉重则整块屏呈现一片灰。所以我的固件里加了一个刷新中标志位只有刷新彻底完成后才允许响应复位指令电源端也加了电容做缓冲。3.4 几种刷新模式的适用场景对照把这几年的经验整理成一张表选型的时候直接对照刷新模式典型耗时残影表现适合的内容不建议的场景全屏刷新2–4 秒几乎无残影会闪黑换页、每天第一次更新、残影补偿需要频繁更新的局部区域局部刷新0.3–0.8 秒有轻微残影累积单张卡片内容变化、时钟分钟位连续快速更新同一区域快速刷新0.2–0.5 秒残影较重交互反馈、临时提示静态内容长时间停留局刷 定期全刷—残影可控日常主用模式无我自己日常就是最后一种绝大多数更新走局刷每十次左右插一次全刷。这个组合在看得清和不闪眼之间是个不错的平衡点。4. 内测中的 MIMO X我实际测了哪些项哪里翻车了先说清楚立场以下所有观察都来自我手里这一台内测机、内测固件量产版本大概率会有变化不要拿我这台的结论去下判断。我把它接进来本来只是想知道外接式桌面墨水屏和自组 ESP32 方案这两条路各自的边界在哪。4.1 拿到机器之后我先做的一件事跑通最小闭环很多人拿到新设备第一件事是测参数、跑分我反着来先用最简单的静态图跑通电脑生成图 → 推给屏 → 屏上显示这个闭环跑通了再谈别的。理由很实在。新设备的坑大多不在参数上而在链路里那些没写在文档里的细节设备是被识别成显示器还是识别成串口设备、分辨率上报的是多少、系统缩放有没有插一脚、刷新指令走的是哪条通道。这些细节决定了后面所有代码的写法。我如果先花两小时测灰度表现最后发现分辨率上报和实际面板差 40 像素那两个小时就白花了。实测下来我这台在电脑侧的识别和常规显示设备差不多这意味着可以复用一部分现成的截图/合成思路但也带来一个新问题——见 4.4。4.2 静态显示质量与灰度表现静态画面是墨水屏的主场这部分整体是满意的。文字边缘干净1-bit 渲染下没有发虚整块屏幕的均匀度不错没有明显的暗角。灰度方面我这台在多级灰阶下的过渡比较自然没有出现明显的色带断层。但和前面说的一样灰度只对图片有意义。我试过把文字做成 4 级灰度观感反而比纯二值差笔画边缘多了一圈浅灰远看像发虚。所以最后我的渲染管线里文字一律走纯二值只有图像素材才开灰度。还有一个细节值得提刷新时的整体闪动比我想象中要轻。切黑那一下的持续时间短看久了不会像早期墨水屏那样刺眼。对一块放在显示器旁边的屏来说这个体验很关键——它决定了你会不会想把它关掉。4.3 连续刷新与长时间点亮的表现墨水屏不怕长时间显示静态内容怕的是连续刷新。我做了两组测试一组是每 10 秒刷一次连续跑两小时另一组是每 5 分钟刷一次跑满一整天。高频那组整体没有明显故障但残影在这两小时里肉眼可见地累积尤其是在数字区域。跑完之后需要连做两三次全刷才能清干净。这说明它同样需要全刷补偿机制不能无脑高频局刷。低频那组一整天下来状态很稳没有任何异常。这符合预期也再次印证了前面那个判断——墨水屏就该按低频快照的方式用。长时间点亮实际上是长时间保持同一帧完全没有问题这本来就是墨水屏的强项。功耗方面我没做精密测量但接在 USB 口上整机对我桌面的供电压力可以忽略。4.4 我在桌面端适配时撞到的两个坑**第一个坑是多屏坐标漂移。**我这台在系统里表现为一个额外的显示输出系统缩放是 150%。第一次推送的时候图被放大了一倍多只能看到左上角一小块。查了半天才确认是缩放层级的问题。解决办法是绕开系统缩放直接在生成位图的时候就按设备真实分辨率输出推送通道不走系统的显示合成而是走设备自己的数据通道。另一个变数是多屏顺序我插拔过一次显示器之后系统给的坐标原点变了推送的位置整体偏了。所以千万不要把系统里的屏幕坐标写死进代码每次启动都重新查一遍。**第二个坑是休眠唤醒后的重连。**电脑休眠再唤醒之后设备侧有时不会自动恢复接收状态表现为推过去的图完全没反应但设备也没报错。加了一个每次推送前先发一次心跳、收到回应再推的检查之后这个问题就再没出现过。代价是每次多一个来回几十毫秒完全可以接受。4.5 它和自组 ESP32 方案的分工边界折腾完这一轮我对两条路线的定位清楚了不少维度自组 ESP32 墨水屏桌面式墨水屏设备上手门槛需要接线、烧录、自己写固件接上就能用重点在软件侧可控程度完全可控刷新模式、时序随便调受固件能力限制能调的参数少稳定性取决于自己写的代码断电重连要自己处理正常使用下比较稳异常恢复也基本自动适合的场景想折腾、有特殊时序需求、追求极低成本只想把内容显示出来不想碰硬件细节我的结论是如果你只是想给桌面加一块信息屏桌面式设备省下的时间远超它贵出来的钱。如果你需要精细控制刷新时序、或者想把屏幕塞进某个定制的壳子里那自组方案才有意义。两者我都留着自组那块主要用来做实验桌面这台负责每天真正要看的内容。5. 无人值守跑一周刷新预算、容错与内容边界前面讲的都是能不能显示出来这一节讲的是能不能一直显示下去。我这套东西的目标是连续跑一周不用管实测下来最关键的四个机制是刷新预算、内容去重、失败回退和隐私边界。5.1 给屏幕排一个优先级队列**不是每一次 Agent 的输出都值得刷一次屏。**这句话是整个调度设计的起点。我的做法是在渲染层前面加一个队列队列元素是待渲染的卡片组带优先级和过期时间。调度器的工作规则是高优先级内容比如一个明确的提醒可以立即触发刷新甚至可以打断当前的静默时段。中低优先级内容进入队列等待只有当反正要进行一次刷新的时候才合并进去一起显示。队列里同一位置的内容被后来的覆盖避免堆积一堆过期的旧内容。队列超过一定长度时按优先级丢弃防止内存里攒一堆永远刷不出去的东西。这套规则带来的最大好处是刷新次数从按时间变成了按内容。以前是一天固定刷 48 次现在的内容密度下大概是一天 15 到 25 次少了一半而屏幕上有用信息的比例反而更高。5.2 内容哈希去重和静默时段这两个机制朴素但效果特别明显。内容哈希去重每次渲染完位图之后算一个哈希如果和当前屏幕上的哈希一致直接跳过这次刷新什么也不做。听起来像废话但实测中这个判断拦掉了大约三成的刷新——因为很多情况下重新生成的内容和屏幕上已有的内容其实是一样的只是生成时间和来源不同而已。省下的每一次刷新都是实打实的。静默时段晚上十一点到早上七点之间除了最高优先级内容一律不刷新。理由有两个一是这个时间段我的桌面没开灯墨水屏根本看不见刷了也白刷二是如果不加这个约束Agent 有时会在半夜因为某些外部事件被唤醒然后在凌晨三点刷一屏东西第二天早上我看到的时候已经过期了。小声提醒静默时段的作用不只是省刷新次数更重要的是它给 Agent 划了一条明确的时间边界让它不至于变成一个全天候乱推送的东西。5.3 护栏、编排和harness这层到底在干什么这套系统里最容易混淆的概念是Agent和包在它外面的那层调度编排。我的理解是这样Agent 负责判断和生成外面那层负责约束、重试、仲裁和投递。很多讨论里提到的 harness 或者编排层其实说的就是后面这层东西——它不产生内容但它决定内容以什么节奏、什么优先级、在什么条件下真正到达输出设备。这一点在接入屏幕的场景里特别直观。如果把模型直接接到屏幕上会怎样它可能在你刚刷完的 30 秒后又来一版措辞略有不同的内容触发一次毫无必要的刷新也可能在某次网络抖动时吐出一段缺字段的 JSON让渲染层直接崩掉。这些都不是模型能力的问题是缺少约束层的问题。我在这层里加的护栏说白了就四条格式校验。JSON 解析失败、缺必需字段、版本号不认识一律拒绝这一帧直接保留上一帧不做任何变化。超时与重试。请求模型超过设定时间没回直接放弃这一轮等下一个触发点。绝不排队重试因为墨水屏上的内容时效性强晚到的内容往往已经没意义了。字段白名单。渲染层只读协议里定义过的字段。模型偶尔会自己加一些花哨的字段全部忽略不用管这样就不会出现模型今天心情好加了个新类型导致渲染器找不到对应布局函数的情况。输出长度上限。单个卡片的文本长度在协议层面就设上限超了直接截断。这比在渲染层做各种兜底要干净得多。另外模型侧的输出能力我是拆成几组技能来管的日程类一个、提醒类一个、图像类一个。每类技能有自己固定的输出模板和示例这样模型不至于在每次调用时自由发挥输出结构。把能力拆开、每个能力约束得死一点比指望一个好的通用提示词要靠谱。5.4 断连自愈让屏幕在没人管的时候也能活断连是必然会发生的不是异常情况是常态。我的处理思路是让每一层都能独立存活设备侧保留最后一帧不动。设备掉线时屏幕上是最后一帧内容看着仍然是完整的、有时效提示的我在页脚固定显示生成时间不会变成一块白屏或者花屏。电脑侧加一个心跳检查。每次推送之前先发心跳收到回应才推图连续三次收不到就把设备标记为下线暂停刷新队列避免无意义的重试把日志刷爆。每隔几分钟尝试重新握手一次。Agent 侧加超时和降级。模型这一轮返回失败不是什么都不做而是回退到一个纯本地的模板比如只显示当前时间和一句固定的内容更新中至少保证屏幕不是停在几个小时前的内容上。这样三层各管一段一周下来我的体验是偶尔会出现内容有点旧的情况但从来没出现过屏幕白屏或者显示成乱码这种情况。这个取舍我认为是对的——宁可显示旧内容也不要显示坏内容。5.5 常亮屏的隐私边界最后说一个容易被忽略但我觉得挺重要的点这是一块常亮的屏位置还在桌面上能被人看到。所以我在这套链路上设了几条硬边界不把完整邮件正文、聊天记录原文推上屏只推摘要或数量提示。涉及账号、金额、身份信息的字段在渲染前做脱敏处理而且是在送到渲染层之前就处理不让它进入图像管道。输出的内容来源限定在几个我明确配置过的数据源模型不能自己联想出额外的信息来展示。这几条看着有点小题大做但考虑到屏幕是常亮的、内容可能是敏感时段敏感的提前设边界成本几乎为零。6. 折腾完这一轮我留下的和砍掉的6.1 保留下来的四条设计跑完这一轮有四条设计我是不会再动的**第一结构化协议先行。**在写任何渲染代码之前先把 JSON 的字段和约束定清楚包括版本号、过期时间、优先级。它看起来像过早设计但实测下来这是最省时间的一步。后面所有的地方——渲染、调度、去重、容错——都是围绕这份协议展开的。**第二电脑侧渲染、推位图。**虽然传输量大了一点但换来的是字体、布局、字号搜索这几块完全自由。中文字体这种需要反复微调的东西改起来不用烧录固件这一点完全值回票价。**第三优先级队列加内容哈希去重。**它把刷新这件事从时间驱动改成了内容驱动一天少刷一半屏幕上的信息密度反而更高。**第四三层容错宁可显示旧内容也不显示坏内容。**这条不只适用于墨水屏任何输出直接面向人的设备都适用。出错的时候保持原状比显示一个错误的、可能被误读的内容要好得多。6.2 被砍掉的三个想法**第一个被砍掉的是实时刷新。**我一开始想让屏幕做到任务状态一变就刷实测发现局刷高频跑两个小时残影就已经很明显了而且信息本身的价值也撑不起这个刷新频率。改成低频快照之后一切都舒服了。**第二个被砍掉的是让模型控制排版。**这个前面说过模型在排版上是不可控的。现在我的协议里连字体大小这种字段都没有模型能选的只有卡片类型剩下全归渲染层。**第三个被砍掉的是设备端的离线推理。**我一度想让设备在不联网的时候也能自己生成点内容试了之后发现算力和内存都不现实而且能生成的内容质量很低。换成保留最后一帧 页脚时间戳之后用户也就是我对它的信任度反而更高——因为我知道屏幕上显示的是什么时候的东西。6.3 如果你也想试我的起步路径如果你是第一次做这类项目我的建议是别一上来就折腾 Agent按这个顺序走**先让屏幕能显示一张静态图。**这一步的目的是把驱动、分辨率、传输通道这些基础问题解决掉。**加一个最简单的定时刷新。**一个 Python 脚本二十分钟生成一张图推过去验证自动刷新这条链路是通的。**引入去重逻辑。**把内容一致就不刷加上去。这一步只需要十几行代码但你会立刻感受到整个系统的聪明程度提升了一个档次。**最后再引入 Agent。**这时候你已经有稳定的渲染层和调度层了Agent 只需要输出协议格式的数据就行。反过来做的话你会同时面对硬件问题、链路问题和模型输出不稳定三件事很容易在第二步就放弃。至于那块 MIMO X我会继续用一段时间。它解决了我不想碰硬件细节的需求让我的注意力能集中在内容本身。而自组那块 ESP32 屏我也不会扔它更适合做实验——想调一点刷新时序或者试个新的渲染方式还是自己接的板子更顺手。两套东西并排放在桌上各自负责自己擅长的部分这大概是我折腾这几年之后最满意的一种状态。