DoAnything
DoAnything 是开放式浏览器任务 API,也是 WebAgent 的主要执行入口。你给出自然语言目标,agent 在真实浏览器里自主决定如何打开页面、搜索、点击、填写和读取结果,并把执行过程和最终结果回传。本页先介绍它解决的问题和核心能力,再给出当前调用方式。
它解决什么问题
- 步骤写不死的网页任务:目标跨多个页面、路径随页面结构变化,传统脚本一改版就断。DoAnything 由 agent 在运行时规划和调整执行路径,你只维护目标,不维护选择器。
- 登录后的操作没有 API:很多后台系统和会员页面只有网页入口。DoAnything 在受控浏览器里复用 Profiles 的登录态,直接在页面上完成读取和操作。
- 关键动作需要人参与:执行中的确认请求以
interaction事件回传,人确认后任务继续,不必在"全自动"和"全人工"之间二选一。 - 执行过程要可观察、可追溯:每一步通过 SSE 事件流回传,可开启截图留证;失败的 run 可以取消、重连或在同一浏览器上下文继续。
核心能力
| 能力 | 说明 |
|---|---|
| 自主执行 | 一句 instruction 创建 run,agent 自主规划浏览器动作序列 |
| 真实浏览器 | 打开、搜索、点击、填写、读取都发生在受控的真实浏览器中 |
| 上下文复用 | session 复用浏览器上下文,profileId 复用登录态 |
| 事件流 | SSE 回传 progress、message、interaction、screenshot、done |
| 人工确认 | interaction 事件携带确认请求,通过 interactionHandle 响应 |
| 过程留证 | capture.screenshots 开启截图,事件流保留执行轨迹 |
| 运行控制 | limits.maxDurationMinutes 设时长上限;支持取消、暂停、恢复和重连 |
典型场景
- 登录内部系统或 SaaS 后台,查询、核对并把结果带回业务系统(见 合规风险智能体)。
- 在需要登录的站点上完成多页读取与整理(见 行程规划智能体)。
- 按既定口径逐页检查站点内容并输出报告(见 品牌一致性智能体)。
什么时候用
- 目标跨多个页面,步骤不适合写死。
- 需要复用登录态、浏览器上下文或人工确认。
- 结果形态不固定,接受 agent 根据目标组织输出。
需要固定结构的搜索结果或研究报告时,使用 WebSearch 或 DeepResearch;需要按计划长期盯守页面变化时,使用 Track。
当前调用方式
Node.js / TypeScript
const { token } = (await qoni.delegateToken({
user: { id: process.env.QONI_USER_ID! },
products: ["doAnything"],
})).data;
const run = await qoni.doAnything.run({
token,
prompt: "打开 Hacker News,列出首页前五条故事的标题和链接。",
capture: { screenshots: true },
limits: { maxDurationMinutes: 10 },
profileId: "prof_alice",
});
const result = await run.wait();
console.log(result.status, result.output);run() 返回 RunHandle,使用 run.id 取 ID;不要按旧示例使用 run["run_id"]、client.sessions 或 runAsync()。
原生 HTTP
POST /api/v1/projects/{pid}/do_anything/runs
Authorization: Bearer wa_...
Content-Type: application/json
{
"instructions": "打开 Hacker News,列出首页前五条故事。",
"max_duration_minutes": 10,
"profile_id": "prof_alice"
}不传 session_id 时,后端为本次 run 创建 session;传入已有 session_id 可以在同一浏览器上下文继续执行。创建响应是 202 和 run envelope。
生命周期
当前后端的 run 状态是:pending、running、awaiting_input、succeeded、failed、canceled。terminal_reason 可能是 done、failed、canceled 或 expired。Node SDK 用 wait() 等待终态,用 status() 刷新状态,用 cancel() 取消。
事件流
GET /api/v1/projects/{pid}/do_anything/runs/{run_id}/events
Authorization: Bearer wa_...Node SDK 把事件归一为 progress、message、interaction、screenshot 和 done;需要底层 wire 事件时通过 event.raw.event 查看。断线后带 Last-Event-ID 重连。
for await (const event of run.events()) {
switch (event.type) {
case "progress":
case "message":
console.log(event.data);
break;
case "interaction": {
const interaction = run.interactionHandle(event.data);
if (interaction.can("confirm")) await interaction.confirm();
break;
}
case "done":
console.log("finished", event.data);
break;
}
}继续执行与重连
const next = await qoni.doAnything.run({
token,
prompt: "继续打开第一条链接,整理评论区的主要观点。",
session: run.sessionRef,
});
const reattached = await qoni.doAnything.attach(run.id, { token });同一 session 的前一条 run 未结束时,后端会拒绝并发 follow-up;先等待终态再继续。
原生 HTTP 的控制端点
单 run 路径还提供 GET .../{run_id}、POST .../{run_id}/cancel、POST .../{run_id}/intervene、POST .../{run_id}/messages、GET .../{run_id}/screenshots、POST .../{run_id}/pause 和 POST .../{run_id}/resume。这些端点的请求体以 OpenAPI 为准;Node 高层 SDK 不把它们伪装成不存在的 client.messages 方法。