Blog

Blog

PHODAL

从可编程到表现力:构建更好的 Agent 运行时重塑用户体验

最近,我重新看了 remio 在 PPT DSL 上的尝试,也注意到 OpenAI 的 Artifact Tool(产物工具)正逐渐演进成一套完整的专业文档运行时。 这让我重新想到一个问题:

当 Agent 已经能够通过代码生成 PPT,我们真正缺少的还是更多 API 吗?

引子:PPT 已经可以被编程,为什么仍然不好用?

回头看最早的 PPT Agent,我觉得这里其实存在两个不同的问题:

  • Agent 如何理解并持续操作一份专业文档
  • 当底层能力已经足够丰富时,为什么 AI 生成的 PPT 仍然如此千篇一律

前者关乎产物(Artifact),后者则关乎表现力。

生成之后:Agent 如何重新进入一份 PPT?

年初还在 Thoughtworks 的时候,我做了一个 PPT Agent 原型,希望加速咨询师日常的复制、修改和排版。第一个版本借鉴了 ChatGPT.com 的 slide Skill,基于 PptxGenJS 和 python-pptx 实现,后来放在了 claude-code-codex-slide

真正做起来以后,我发现咨询师面对的通常不是一份空白 PPT,而是大量历史材料:找到合适的页面和对象,完成局部修改,同时保留原来的模板和布局。用户还会继续在 PowerPoint 中修改,之后又希望 Agent 能接着工作。

因此,PPT 不能只是 Agent 一次性生成的文件,它还需要成为一个能够被重新理解、定位和持续操作的 Artifact。

能力足够:为什么表达仍然千篇一律?

另一个问题则发生在生成这一侧。今天的大模型已经很会写 JavaScript,PptxGenJS 也几乎能够表达所有常见的 PPT 对象。 AI 做 PPT 早已不是“能不能画出来”的问题。

但生成得越多,就越容易发现结果不断收敛到三栏卡片、四宫格、左右分栏和时间线。底层 API 明明拥有巨大的能力空间,Agent 实际使用的却只是其中很小的一部分。

因为 Agent 真正需要表达的并不是 Shape 和坐标本身,而是观点的主次、数据中的异常、架构中的边界,以及背后的专业判断。

可编程解决的是“能不能做出来”,表现力解决的是“这个意图可以怎样被更好地表达”。

这实际上是 Runtime 演进的两个方向:先让产物变得可操作,再让操作本身变得更有表现力。前者解决 Agent 如何持续进入一份 PPT,后者解决 Agent 如何从巨大的能力空间中选择更合适的表达方式。我们先从第一步说起:从可编程文件到可操作的 Artifact。

API 让 PPT 可编程,Runtime 让 PPT 可持续操作

如果目标只是从零生成 PPT,PptxGenJS 已经足够好。Card、Grid、设计 Token、文本测量、图片裁切乃至碰撞检测,都可以继续封装成 JavaScript Helper。

但这些抽象主要服务于生成过程。一旦 PPT 被用户修改、数据发生变化,或者 Agent 需要在几天之后重新接管,真正困难的问题 就不再是“有没有一个 Helper 可以调用”,而是:

Agent 如何重新理解当前产物,并找到自己需要继续操作的对象?

产物运行时:让 Agent 持续理解和操作 PPT

Browser Use 是一个很好的参照。Playwright 早就可以 click()fill(),但 Browser Agent 真正需要的是另一层能力: 它必须先看到当前页面,找到具体对象,对对象执行操作,再观察操作后的结果。

换句话说,Agent 面对的不再是一组孤立 API,而是一个可以反复进入的工作环境。我把这样的一层抽象称为 Artifact Runtime。

产物运行时(Artifact Runtime),是位于 Agent 与专业产物之间的一层运行时:它把原本只是输入或输出的产物,转换成 Agent 可以持续观察、定位、操作和验证的工作对象。

工作循环:观察、寻址、操作与验证

也就是说,这个实际工作的过程更接近一个循环:

          Observe 
             ↓
Artifact → Address → Operate 
        ↑          ↓
        └─ Verify ─┘

Observe(观察),是让 Agent 理解产物当前是什么状态;Address(寻址),是让 Agent 能够定位并引用其中具体的对象;Operate(操作),是对这些对象执行局部操作,而不是重新生成整个产物; Verify(验证),则是在操作以后重新检查结果,再决定下一步做什么。

关键在 Address。它不只是"找到一个对象",而是让对象拥有可以被 Agent 稳定引用的身份。"第三页左边蓝色的框"不是好的寻址方式。Artifact Tool 里更接近真实工作方式的是:先 inspect 出一份带锚点的快照,再 resolve("sh/c3d4e5f6") 去改那个对象。

一次很普通的修改大概是这样:

inspect({ search: "Revenue" })
  → {"kind":"textbox","id":"sh/c3d4e5f6","name":"headline","text":"Revenue outlook"}
resolve("sh/c3d4e5f6").text.replace("Revenue", "Revenue outlook")
inspect({ target: { id: "sh/c3d4e5f6" } })

Agent 先看到当前页,拿到 sh/c3d4e5f6 这个身份,改完标题后再检视一次。用户在 PowerPoint 里改过字、挪过框, 这份文件仍然可以被重新进入。文件不再只是 Agent 的输出,而开始成为工作循环的一部分。

这也是 Artifact Tool 真正往前走的一步:它不只是另一套 PPT API,而是让 Presentation 开始成为可以被反复观察和操作的产物。

而当对象已经可以被持续操作,新的问题也随之出现:对象之间的布局、关系和规则,是否还需要 Agent 每次重新计算?这也推动 Runtime 继续向上生长。

从可操作到可表达:Runtime 接管重复决策

到这里,Agent 已经可以重新进入一份 PPT,定位对象并完成局部修改。但如果新增一张指标卡之后,它仍要重新计算卡片宽度、间距、换行和标题高度, 那它只是从"一次性生成" 变成了 "反复编程"。

Runtime 的下一步不是增加更多原子 API,而是开始维护对象之间的关系。表现力不会因为多了几个 Helper 自动出现;它出现在 Agent 不用再把注意力耗在坐标上的时候。

布局语义:保存关系,而不是保存一次排版结果

在坐标模型中,“四张指标卡等宽排列”最终只会留下四组位置和尺寸。一旦卡片数量或文字长度变化,Agent 就需要重新排版。 布局语义保存的则是对象之间的关系:等宽、等距、对齐,以及空间不足时如何换行。Agent 选择表达方式,Runtime 负责重新求解布局。

Artifact Tool 的 Compose 已经把这件事做成了页面描述方式。rowcolumngrid 描述结构,fillhug 描述空间怎么分配:

slide.compose(
  <row width="fill" gap={24}>
    <box width="fill" height="hug">ARR</box>
    <box width="fill" height="hug">NRR</box>
    <box width="fill" height="hug">Churn</box>
    <box width="fill" height="hug">Payback</box>
  </row>,
  { frame: { left: 72, top: 160, width: 1136, height: 200 } }
)

这还不是表现力本身。四张等宽卡排得再稳,仍然可能是同一套模板。但 Agent 只有先从坐标里脱身,才有机会去想:这一页该强调异常,还是该画出边界。

领域语义:从通用形状到可复用的专业对象

grid 只知道对象如何排列,并不知道它们是一组指标卡;connector 只知道节点需要连接,并不知道这条线表达的是服务依赖还是演进路径。布局语义解决的是空间关系,还解决不了专业意图。

当这些结构反复出现以后,就可以进一步沉淀为领域对象。remio 走的是这一层:Agent 不再先写 Shape,而是先写"这是一组指标 / 一条演进 / 一个架构边界",再由 Runtime 展开成可编辑的 PPT 对象。Agent 决定新增什么指标、服务或阶段;Runtime 负责继承样式、调整布局、重排连接,并检查结果是否仍然可读。

专业意图
    ↓
领域对象与关系
    ↓
布局约束
    ↓
可编辑的 PPT 对象

这条演进可以概括成:坐标与形状 → 布局关系 → 领域对象 → 专业意图。每向上一层,Agent 需要维护的实现细节就少一些,Runtime 能够确定性完成的工作就多一些。

表现力也是在这一层才真正开始分叉。面对同一组数字,坐标层的 Agent 很容易继续生成四张卡;领域层的 Agent 才有机会说:这里该强调异常,而不是再铺一张对称网格。Runtime 不会替 Agent 做这个判断,但它决定了 Agent 是在 Shape 上做选择,还是在专业对象上做选择。

Runtime 的边界:接管工程复杂度,而不是替代专业判断

Runtime 并不是抽象得越高越好。对象寻址、布局求解和格式转换,可以交给系统;页面要表达什么、采用怎样的叙事结构,仍然需要 Agent 判断。 用户最终感受到的,只是修改以后布局是否稳定、模板能否保留,以及 Agent 能否继续接管。

Agent 负责专业判断,Runtime 负责把判断稳定地展开、修改和验证。

从可编程走向表现力,不是给 Agent 更多 API,而是让 Runtime 接管已经可以被工程化的复杂度。


或许您还需要下面的文章:

关于我

Github: @phodal     微博:@phodal     知乎:@phodal    

微信公众号(Phodal)

围观我的Github Idea墙, 也许,你会遇到心仪的项目

QQ技术交流群: 321689806
comment

Feeds

RSS / Atom

最近文章

关于作者

Phodal Huang

Engineer, Consultant, Writer, Designer

ThoughtWorks 技术专家

工程师 / 咨询师 / 作家 / 设计学徒

开源深度爱好者

出版有《前端架构:从入门到微前端》、《自己动手设计物联网》、《全栈应用开发:精益实践》

联系我: h@phodal.com

微信公众号: 最新技术分享

标签