@aralroca/gui-agent

中文文档
0.7.0发布于 2026/10/01MITTypeScriptES Module近 30 天下载 6.5万

一个开源的WebMCP驱动的页面GUI代理. 让一个自然语代理在您的网络应用中生活,并驱动其UI——没有脚本注入,没有浏览器扩展,没有无头浏览器.

中文使用文档
文档目录16 节
  1. 目录
  2. 安装
  3. 快开始
  4. 如何运作
  5. 代理如何选择工具
  6. 与页面代理相比
  7. API 密码
  8. 核心项目 @aralroca/gui-agent (中文(简体) )
  9. * 视同代理( @aralroca/gui-agent/ui (中文(简体) )
  10. 带上你的LLM
  11. AI SDK适配器( @aralroca/gui-agent/ai-sdk (中文(简体) )
  12. 反应( E) @aralroca/gui-agent/react (中文(简体) )
  13. 安全问题
  14. 演示
  15. 开发
  16. 许可证

gui-agent — a glowing ring around a button inside an app window

贵宾

一个开源的,由WebMCP驱动的GUI代理,它生活在您的网络应用中.
让一个自然语言代理来操作你的UI——点击,填充,导航,调用你的应用程序自己的动作——由你带来的任何LLM驱动.

npm version npm downloads WebMCP TypeScript MIT license

Demo: the agent invites a teammate, searches users, and builds a node-based flow on a React Flow canvas while the built-in visualizer shows status chips and a gradient glow over each element it touches — including nodes that mount asynchronously

可选 可视化器 动作中:每个工具呼叫的状态芯片,一个动画的梯度发光来巡视代理所接触的每一个元素,以及一个背景面纱来保持用户对动作的关注.


灵感来自 页面代理,但建立在新兴 网络MCP 标准通过多填充.

  • 📦 只是一个npm包. npm i @aralroca/gui-agent 财务报告和审定财务报表 import。没有脚本注入,没有浏览器扩展,也没有无头浏览器.
  • 🧩 以标准为主. 工具注册于 document.modelContext (网络MCP). 多元填充( E)@mcp-b/webmcp-polyfill)安装在浏览器尚未本土支持的地方.
  • 🎯 生产者+消费者在一中. 显示您的应用操作作为精确的工具 财务报告和审定财务报表 回到基于文本的 DOM 驱动其他一切.
  • 🧠 带上你的LLM. 一个微小的提供者-不可知界面,加上一个现成的Vercel AI SDK适配器.
  • 🪶 无头核. 没有强制的UI——把它连接到你自己的聊天,命令栏,或者声音.
  • ✨ 央视网. 每个动作的状态芯片,动画梯度会围绕被操作的元素发光,背景模糊而突出(@aralroca/gui-agent/ui) (中文(简体) ).

早期/实验性。 WebMCP 是一个移动 W3C草案; APIs可能改变.

思取取而为便宜. 但是如果你的特工们 不必那么想... 反而有.. 控制共计 您的应用程序当然{\fn黑体\fs22\bord1\shad0\3aHBE\4aH00\fscx67\fscy66\2cHFFFFFF\3cH808080}你觉得呢? 来看看 Janux 框架 超过gui -agent lib 的

目录

安装

npm i @aralroca/gui-agent
# optional peers, depending on what you use:
npm i ai zod        # for the AI SDK adapter / Zod schemas

快开始

import { defineTool, GuiAgent } from "@aralroca/gui-agent";
import { createAiSdkLlm } from "@aralroca/gui-agent/ai-sdk";

// 1. Expose your app's actions as tools (producer side, optional).
defineTool({
  name: "go_to_tab",
  description: "Switch the console to a tab.",
  inputSchema: { type: "object", properties: { tab: { type: "string" } }, required: ["tab"] },
  annotations: { readOnlyHint: true },
  execute: ({ tab }) => router.push(`/${tab}`),
});

// 2. Run the agent. It discovers your tools + synthesizes DOM tools (click/fill/read).
const agent = new GuiAgent({
  llm: createAiSdkLlm({ model: "anthropic/claude-opus-4-8" }),
  confirm: async (call) => window.confirm(`Allow "${call.name}"?`), // HITL gate
});

await agent.run("Invite [email protected] to the team as admin");

导入软件包会自动安装 WebMCP 多填充 - 没有 <script> 标签。 。 。 .

如何运作

gui-agent 统一两种办法:

  1. 出品人 (WebMCP). 你的应用电话 defineTool(...) 以登记可靠、结构化的行动 document.modelContext. 任何WebMCP代理——包括浏览器的本地代理——都可以使用.
  2. DOM倒置 (页面代理样式). 对于任何没有暴露的东西, 代理构建紧凑 文本快照 (作用、标签、值、稳定参考,例如 e7)并被合成 read_page 编号 : click 编号 : fill 编号 : select_option 编号 : drag 编号 : wait_for_text 工具。 没有截图,也不需要多式联运模式.

内置循环会发现所有可用的工具, 询问您的 LLM 该怎么办, 运行调用( 由您的可选选项决定 ) confirm),反馈结果,并重复到完成.

代理如何选择工具

对于每一步,代理更喜欢 专门设计的 WebMCP 工具 如果一个适合,而且只有 推断DOM 当没有工作暴露时:

flowchart TD
    Goal["🗣️  Goal in natural language"] --> Loop["🧠  Agent loop · bring your own LLM<br/>(AI SDK adapter · remote LLM · React bindings)"]
    Loop --> Discover["🔍  Discover the available tools"]
    Discover --> Decide{"Is there a purpose-built<br/>WebMCP tool for this step?"}
    Decide -- "Yes · preferred" --> WebMCP["⚙️  Call the WebMCP tool<br/>structured &amp; reliable"]
    Decide -- "No · fallback" --> DOM["🖱️  Infer from the DOM<br/>read_page → click / fill / select_option / drag / wait_for_text"]
    WebMCP --> Gate{"Does the tool have<br/>readOnlyHint?"}
    DOM --> Gate
    Gate -- "No · write action" --> Confirm["🙋  Human-in-the-loop confirm()"]
    Gate -- "Yes · read-only" --> Run["Execute"]
    Confirm -- "approved" --> Run
    Confirm -- "denied" --> Feed
    Run --> Feed["Feed the result back to the LLM"]
    Feed --> Loop
    Loop -. "no more tool calls · maxSteps" .-> Done["🏁  Done"]

    subgraph MC["document.modelContext · WebMCP (polyfilled — no server, no browser extension)"]
      direction LR
      App["Your app's own actions<br/>defineTool() / useTool()"]
      Ext["Tools registered by other code<br/>discoverExternalTools() · opt-in"]
    end
    Discover -. reads .-> App
    Discover -. reads .-> Ext

特工被交给了 单一合并工具列表 并被指示更偏好您的应用程序的WebMCP工具;被合成的DOM工具是总是倒置(一个同名的应用程序工具获胜). WebMCP 工具在线 document.modelContext ——您的应用程序注册(因此任何WebMCP代理,包括浏览器的本地代理,都可以调用)和 discoverExternalTools() 能够调出其他登记代码的工具. upload_file 财务报告和审定财务报表 navigate DOM工具是选入的.

与页面代理相比

gui - agent 的灵感来自 页面代理 并分享其核心思想——一种自然语言的代理,驱动着一个真实的网页 基于文本的 DOM 带有自带LLM设计的快照(没有截图,没有多式模型). 不同之处在于Gui -agent通过在新兴的的基础上 来补充什么 网络MCP 标准而不是仅驱动 DOM :

能力贵宾页面代理
WebMCP 标准 (单位:千美元)document.modelContext(中文(简体) )* 建于该地 W3C WebMCP草案 + 多填充QQ Not WebMCP — 它的"MCP"是一个单独的节点服务器, 允许 外部 代理驱动浏览器
应用动作作为标准工具✅ defineTool 登记册结构化行动 document.modelContext可调用 任意 WebMCP 代理商——包括浏览器的本地代理商QQ 自定义工具是客户端配置, 标记 @experimental,而不通过页面标准曝光
与其他页面工具接口✅ discoverExternalTools() 抓取其他已注册代码的工具 document.modelContext不详
人行道安全门* 内建 confirm() 门 - 所有非readOnlyHint 工具在运行前通过批准进行路由没有强制性的审批门,也没有只读/写区分(自动运行至 maxSteps(b) 提议 ask_user、生命周期钩和数据假冒
一等反应装订✅ GuiAgentProvider, (中文(简体) ), useGuiAgent, (中文(简体) ), useTool, (中文(简体) ), <AgentSteps />无( vanilla 面板 UI)
提供者不可知LLM任何形状通过一个函数 Llm 接口,加上一个 Vercel AI SDK 适配器和一个远程 LLM 帮助器带上你的,但终点必须是 OpenAI 兼容
生产者+消费单位精准结构化制作工具 财务报告和审定财务报表 a DOM 在一个循环中倒置主要为DOM驱动程序(海关工具实验)

当页面代理更适合. 页面代理非常出色,而且有真正的优势 gui代理没有: 它驱动 任何现有网站的DOM,没有选择的应用程序,因此它在遗产或第三方应用(ERP,CRM,admin boards)上工作,你并不控制——而gui-agent的制作工具需要应用来注册它们(它的DOM回落仍然在任何地方工作,但是WebMCP值来自仪器). 页面代理也运送可选 色调扩展 用于交叉任务和 a 节点 MCP 服务器 因此外部代理(Claude Desktop, Cursor)可以驱动真正的浏览器. 这两个项目都是麻省理工学院许可,TypeScript,以文字为基础,并运送活动可视化器.

简而言之:达到 页面代理 实现网站自动化 别 自有; 达到 贵宾 当你 对 拥有应用程序并想要基于标准,结构化,人性化的工具——其他所有工具都有DOM回落.

API 密码

核心项目@aralroca/gui-agent(中文(简体) )

导出目的
defineTool(def, opts?) → dispose注册一个WebMCP工具. def数字 : { name, description, inputSchema?, annotations?, execute }。 。 。 . inputSchema 接受JSON Schema或Zod计划 通过返回的函数取消注册或 opts.signal。 。 。 .
new GuiAgent(options) 编号 : agent.run(goal, signal?)代理环. 选项 : { llm, systemPrompt?, maxSteps?, domFallback?, confirm?, onStep?, domTools? }。 。 。 .
runAgent(goal, options)一发方便.
registry 编号 : ToolRegistry工具登记册(真实来源,缩写为 document.modelContext) (中文(简体) ).
discoverExternalTools()读取已注册的工具 document.modelContext 根据其他代码.
ensureModelContext() 编号 : hasModelContext()多填靴子的帮手.
DomSnapshotter 编号 : createDomTools()DOM倒地的原始人, 如果你想要他们独立.
dragAndDrop(source, target, timing?) → { dropped, refused }通过点出页面的 HTML5 拖放事件将一个元素拖放到另一个元素上 ()dragstart → dragenter → dragover → drop → dragend,一个共享 DataTransfer) (中文(简体) ). 页面本身的规则决定:不取消的目标 dragover 得到没有 drop。通过 VISIBLE_DRAG 像视觉器的指针一样加快速度.

GuiAgentOptions.domTools 转发 DomToolsOptions (单位:千美元)root, (中文(简体) ), maxNodes, (中文(简体) ), allowNavigation, (中文(简体) ), onTarget)到每个运行的DOM工具. 每次点击/ 填充/ 选择前, 解析的活性元素会被重新发送到 onStep 作为 tool-target 步( 携带原出处) ToolCall)——是视觉器发光的动力.

* 视同代理(@aralroca/gui-agent/ui(中文(简体) )

向用户显示代理在做时正在做什么:每个工具呼叫的状态芯片("点击"带有回旋器 ~","错误"上,被拒绝时被封"),转弯之间的"想..."指示器,以及一个 动画渐变发光环 围绕DOM要素采取行动——而其余部分 模糊的背景面纱 目标很突出 零依赖性,在阴影DOM中实现 所以样式永远不会漏出.

import { GuiAgent } from "@aralroca/gui-agent";
import { createAgentVisualizer } from "@aralroca/gui-agent/ui";

const viz = createAgentVisualizer({
  container: document.querySelector("#agent-steps")!, // where the chips go
});

// `bind` composes the visualizer into your agent options (it never replaces
// your own `onStep` — it chains it).
const agent = new GuiAgent(viz.bind({ llm }));
await agent.run("Invite [email protected] as admin");

一切都是可塑的:

createAgentVisualizer({
  chips: true,               // action chip list
  highlight: true,           // glow ring on the target element
  cursor: false,             // simulated mouse pointer travelling to each target
  showThinking: true,        // "Thinking…" indicator between LLM turns
  locateButton: true,        // ◎ button on chips to re-flash the target
  glowDuration: 1200,        // ms the ring holds on the last target before fading
  glowDwell: 500,            // min ms per target when several highlights queue up
  backdrop: {                // blur/dim the page around the target (or false)
    blur: 3,                 // px
    exclude: ["chat-panel"], // element ids (or Elements) to keep sharp
  },
  labels: {                  // per-tool chip labels (string or fn)
    click: "Clicking",
    invite_member: (call) => `Inviting ${call.arguments.email}`,
  },
  theme: {                   // maps to --gua-* CSS custom properties
    accent: "#2563eb",
    chipBg: "#f4f4f5",
    chipBorder: "#e4e4e7",
    chipText: "#3f3f46",
    font: "system-ui, sans-serif",
    glowColors: ["#7c8cf8", "#f0a6c8", "#7ee0c3"],
  },
});

DOM回落工具的发光自动跟踪(click, (中文(简体) ), fill, (中文(简体) ), select_option) (中文(简体) ). 制作工具通过自己的代码操作,所以他们选择通过调用 viz.highlight(target) 从他们的 execute ——每被你触摸的元素拨打一次并按顺序进行环行(代理动作跑得快于人类感知,因此要将亮点排入每个目标的最小活度).

target 可以是一个元素 或 CSS 选择器当工具同步创建目标时,通过一个选择器——反应流(@xyflow/react)节点,一个出入口,一个懒惰地倒行相接的行——和环等(最多~2s)它挂起,而不是在缺失的元素上不放:

const id = graph.addNode({ label });        // returns synchronously…
viz.highlight(`.react-flow__node[data-id="${id}"]`); // …DOM node mounts a tick later; the ring waits for it

设定 cursor: true 添加一个 模拟鼠标指针 在巡演的顶上,一个箭头 飞向每个目标 环访问和波纹 它降落的地方,所以用户看到 地点 事情发生了,而不只是它做到了。 它和戒指一样排队——包括: viz.highlight() 从自己的工具打来的电话——如果页面在它下面滚动,就跟随目标,在下面没有波纹的电信端口 prefers-reduced-motion。它是被拉平的,不是OS指针,它不开火 :hover 或真实的指向事件, 并且它从不拖延它所显示的动作.

拖来拖去. DOM倒计时器 drag 工具 ({ ref, to }拖动 a draggable="true" 元素到投放目标; 页面大纲可拖放的标记元素和投放目标(droptarget在他们自己的作用旁边)——要素 aria-dropeffect (例如:. aria-dropeffect="move" 或一个 ondrop 处理者。 与 cursor: true 指向者降落在被拖走的东西上,并携带一个惰性的复制品(没有ID,处理器,帧或活的自定义元素)到目标,它放任去——在屏幕上的目标方面,像滴出事件一样,高柱从不取出一滴从折叠下. 你自己的工具显示的一样 viz.drag(from, to) 并进行它 dragAndDrop(from, to, VISIBLE_DRAG)数字 :

defineTool({
  name: "move_card",
  description: "Move a card to another column.",
  inputSchema: { type: "object", properties: { card: { type: "string" }, column: { type: "string" } }, required: ["card", "column"] },
  execute: async ({ card, column }) => {
    const from = document.getElementById(String(card))!;
    const to = document.querySelector(`[aria-label="${column}"]`)!;
    viz.drag(from, to);
    const { dropped } = await dragAndDrop(from, to, VISIBLE_DRAG);
    return dropped ? `Moved to ${column}.` : `${column} doesn't take that card.`;
  },
});

已知限制:上层的元素(<dialog showModal>,全屏)上方涂料.

带上你的LLM

执行 Llm 接口——一个自动同步函数,一个转弯:

import type { Llm } from "@aralroca/gui-agent";

const llm: Llm = async ({ messages, tools, signal }) => {
  // call your model with `messages` + `tools`; return one turn
  return { text: "...", toolCalls: [{ id, name, arguments }] };
};

AI SDK适配器(@aralroca/gui-agent/ai-sdk(中文(简体) )

import { createAiSdkLlm, createRemoteLlm } from "@aralroca/gui-agent/ai-sdk";

// Run the model in-process (client key, demo, or server agent):
const llm = createAiSdkLlm({ model: "anthropic/claude-opus-4-8" });

// …or keep the model server-side and execute tools in the browser:
const llm = createRemoteLlm({ api: "/api/chat" });
// endpoint receives { messages, tools } and returns { text?, toolCalls? }

反应( E)@aralroca/gui-agent/react(中文(简体) )

import { useTool, GuiAgentProvider, useGuiAgent, AgentSteps } from "@aralroca/gui-agent/react";

function UsersPage() {
  // Registered while mounted; auto-unregistered (AbortSignal) on unmount.
  useTool({
    name: "search_users",
    description: "Search users by name or id",
    inputSchema: { type: "object", properties: { query: { type: "string" } }, required: ["query"] },
    annotations: { readOnlyHint: true },
    execute: ({ query }) => store.search(query),
  });
  return /* … */;
}

function Chat() {
  const { run, running, steps, visualizer } = useGuiAgent();
  // wire to your own chat UI; <AgentSteps /> renders the visualizer's chips
}

// Enable the visualizer on the provider (true, or AgentVisualizerOptions):
<GuiAgentProvider llm={llm} visualizer>
  <Chat />
  <AgentSteps />
</GuiAgentProvider>

安全问题

WebMCP工具与用户现有的会话/cookie一起运行,因此一个工具可以做真实的,特权的事情. gui-agent 给你一个 confirm 门: 任何工具 无 annotations.readOnlyHint 通过您的路径 confirm(call, tool) 运行前的回调——插入人入地的自然站. 使用 readOnlyHint: true 这样他们就不会迅速了 参见 WebMCP 规格 安全考虑。 。 。 .

演示

npm run demo   # opens a mini "console" you can drive in natural language

尝试: "邀请 [email protected] (英语) 作为管理员", (中文(简体) ), "寻找健二", (中文(简体) ), "把我的展示名称改为尼欧" (上一个使用DOM倒置——没有暴露), 将“ Fix” 登录重定向到 Done 编辑 董事会 选项卡(一个普通的 HTML5 拖放 kanban : 代理拖取带有 DOM 后退的卡片) drag 工具,指针将其带入柱子,或 "建立一个工作流程" 编辑 工作流量 选项卡——一个反应流布,其中的发光会随着代理器的添加而跟随每个节点(选择器突出显示,因为节点同步挂起)。 带可视化器的演示船 默认情况下,你可以看到芯片, 发光之旅, 和背景面纱 完全如上面的GIF.

开发

npm install
npm test          # vitest + jsdom
npm run build     # tsup → ESM + .d.ts for all entry points
npm run typecheck

许可证

麻省理工学院 咸罗迦

版本与发布记录

@aralroca/gui-agent 共发布 12 个版本,首次发布于 2026/06/26;过去 12 个月发布了 12 个版本。

版本发布日期距今
0.7.0latest2026/10/011 个月前
0.6.32026/08/272 个月前
0.6.22026/08/232 个月前
0.6.12026/08/172 个月前
0.6.02026/08/172 个月前
0.5.02026/07/093 个月前

关于 @aralroca/gui-agent 的常见问题

@aralroca/gui-agent 是什么?

一个开源的WebMCP驱动的页面GUI代理. 让一个自然语代理在您的网络应用中生活,并驱动其UI——没有脚本注入,没有浏览器扩展,没有无头浏览器.

如何安装 @aralroca/gui-agent?

在项目目录运行 npm install @aralroca/gui-agent,或使用 pnpm add / yarn add / bun add。

@aralroca/gui-agent 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@aralroca/gui-agent 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@aralroca/gui-agent 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=20。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@aralroca/gui-agent 可以商用吗?

@aralroca/gui-agent 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@aralroca/gui-agent 的下载量有多少?

根据 npm 官方下载统计,@aralroca/gui-agent 在 2026/10/07 – 2026/11/05 这 30 天内被下载 64,752 次,日均约 2,158 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@aralroca/gui-agent 还在维护吗?

最新版本 0.7.0 发布于 2026/10/01(1 个月前);至今共发布 12 个版本,其中过去 12 个月发布了 12 个;首次发布于 2026/06/26。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。