Skip to content

DoAnything

DoAnything 是 WebAgent 的开放型 API。你给一句自然语言 instruction,agent 自己挑工具、定路径、跑步骤,在浏览器环境里尽力达成目标。

和 DeepResearch / WebSearch / Track 不同:那 3 个是定型 API,产物形态固定、给质量契约。DoAnything 产物形态不定——连目标最终长什么样你可能都不完全知道,交给 agent 自由发挥。因此它不承诺质量契约;要契约就走对应的定型 API。4 个 API 并列,按你要什么直接选。

什么时候用

  • 目标不定、复合,需要 agent 自主决定怎么做。
  • 任务跨多步、跨页面,可能要登录态、人工确认、长程运行。
  • 你接受「尽力而为」,而不是固定形态的结果契约。

需要固定形态的产物时,用 DeepResearch / WebSearch / Track

资源模型

Session 是一个运行时容器——它持有浏览器、profile(cookies / 登录态)、workspace(文件系统)。Run 是跑在 session 里的一条 instruction。同一 session 可以接连跑多个 run,它们共享前一个 run 留下的状态。

text
project
└── session                   id: sess_…
    ├── browser, profile, workspace
    └── run                   id: run_…
        ├── instructions      "搜 Hacker News..."
        ├── status            running | done | …
        └── events (SSE)      run.status_changed, run.message, …

生命周期(7 态)

状态含义下一步
pending已接收,等 agent slotrunningcanceled
runningagent 在跑donefailedawaiting_inputpausedcanceled
awaiting_inputagent 自己暂停了,等你回应running(通过 intervene
paused你手动暂停runningresume)、canceled
done成功完成;output 已落终态
failed报错;error.code error.detail 已落终态
canceled你取消(或 max_duration 触发)终态

非终态都占 session 资源。用 max_duration_minutes 兜底。

提交一个 run

创建 session 时,第一条 run 随 CreateSessionRequest 一起提交。请求字段:

字段类型必填说明
instructionsstring一段中文 / 英文。最多 10 000 字符
max_duration_minutesint1–10 080(一周)
recordingobject{enabled, quality, capture_during_take_control};不传 = 关
keep_aliveboolrun 结束后保持 session 热度,方便接 follow-up run
allowed_actionsstring[]允许 agent 调的工具白名单。空数组 = 全允许
profile_idstring复用 Profile 的 cookies / 登录态

完整 schema 见 OpenAPI spec

示例:

python
from web_agent import Client
from web_agent.v1.types import CreateSessionRequest, RecordingConfigRequest

session = await client.sessions.create(CreateSessionRequest(
    instructions="找出 24 小时内 Show HN 上 Top 5 的帖子。",
    max_duration_minutes=10,
    recording=RecordingConfigRequest(enabled=True),
    keep_alive=True,
))
run = session.runs[0]

Follow-up run

python
from web_agent.v1.types import CreateRunRequest

followup = await client.sessions.create_run(
    session.id,
    CreateRunRequest(instructions="点进第一篇帖子,总结一下评论区。"),
)

跑在同一个浏览器里,cookies 与上一条 run 留下的 DOM 都在。

事件

每个 run 有一条 SSE 流:

http
GET /v1/projects/{pid}/do_anything/sessions/{sid}/runs/{rid}/events
Authorization: Bearer wa_…

11 种事件类型(envelope 一致;data 内容不同):

类型何时 emit
run.status_changed状态切换
run.messagechat 里多一条(agent 或 user)
run.action.startedagent 调用某工具
run.action.completed工具返回
run.action.failed工具抛错
run.screenshot浏览器新 frame(url 短期签名)
run.input_requestagent 暂停,需要你回应
run.input_request_resolved你的 intervene 已采纳
run.cost_update一步的 cost 增量
run.completed终态;output 已落
stream.heartbeat约 15 s 一次;可忽略

断线干净续传:

http
GET …/events
Last-Event-ID: 142

server 会重放 id > 142 的事件,不漏。

Input request(人在回路)

agent 撞到 captcha、2FA、判断不准的事,会发 run.input_request

json
{
  "type": "run.input_request",
  "data": {
    "input_request_id": "ir_01HXX…",
    "prompt": "我看到一个 'Verify you're human' 挑战,你帮我点过去?",
    "schema": { "type": "object", "properties": { "solved": { "type": "boolean" } } }
  }
}

POST /intervene 回:

python
await client.messages.intervene(
    session.id, run.id,
    input_request_id="ir_01HXX…",
    response={"solved": True},
)

run 切回 running。整轮一次往返,无 polling。

Take Control(接管浏览器)

有些步骤 agent 没法独自完成——captcha、2FA、要人亲手输的密码。这时可以把浏览器交给人操作:弹出一个可交互的实时浏览器,人点完、填完,再把控制权交还给 agent。

它和上面的 input request 不同:input request 是 agent 问一个问题、你用 JSON 回答;Take Control 是人直接操作 agent 那台浏览器

接管走的是同一个 intervene 端点,用 kind 区分动作:

1. 发起接管

http
POST /v1/projects/{pid}/do_anything/sessions/{sid}/runs/{rid}/intervene
Content-Type: application/json

{ "kind": "take_control", "reason": "captcha" }

常见触发点是 agent 先发了一条 run.input_request(captcha / 需要登录),你也可以在任意时刻主动发起。

2. 拿到控制 URL,交给人操作

后端签发一个 standalone 控制 URL,通过 run.take_control_pending 事件下发(datastandalone_control_url / exp / reason)。这是一个无品牌的实时浏览器页面——可以直接转发给你的终端用户。人在这个页面里直接对 agent 浏览器点击、输入:过验证码、登录、做需要人判断的事。

发起接管后 agent 不会立刻停——只有真的有人打开 URL、连上浏览器,run 才切到 paused、agent 才暂停(事件 run.user_paused)。没人连上,URL 约 5 分钟后失效,发 run.take_control_expired

3. 交还控制

人操作完,再调一次 intervene

http
{ "kind": "release_control", "trigger": "client_release" }

run 切回 running,agent 重新观察当前页面、接着跑(事件 run.user_released)。控制页空闲约 30s 也会自动交还。URL 过期想重发,用 { "kind": "refresh_control_url" }

相关事件

事件含义
run.take_control_pending控制 URL 已签发、等人连接;data.standalone_control_url 是给人操作的页面
run.user_paused有人连上、开始操作,agent 已暂停
run.user_released控制已交还,agent 继续
run.take_control_expired没人连接,URL 超时作废

SDK 现状:Python / TypeScript SDK 的 intervene() 目前只覆盖 answer_input_request。Take Control 的 take_control / release_control / refresh_control_url 直接调 HTTP intervene 端点。完整字段见 OpenAPI spec

Profiles

Profile = 一份整体的浏览器身份(一个用户一份,累积他在所有站点的登录态)。create session 时引用:

python
await client.sessions.create(CreateSessionRequest(
    instructions="打开 LinkedIn 收件箱,回复最新一条消息。",
    profile_id="prof_alice",
))

第一次在 Console 里手动设置 Profile(把需要的站点逐个登录一遍)。后续 session 直接复用同一份。详见 Profiles

Workspaces

Workspace = 持久文件系统。agent 可读可写;run 跑完后用签名 URL 取文件。"抓这个站,写 CSV,丢回来"这种场景常用。

接下来