Skip to content
Go to Dashboard

TypeScript SDK

本页说明如何安装、配置并使用官方 @web-agent/sdk Node / 浏览器包:起 session、跑 task、订阅事件。

bash
npm install @web-agent/sdk
# 或 pnpm add @web-agent/sdk / yarn add @web-agent/sdk / bun add @web-agent/sdk

支持 Node 20+ 与现代浏览器。

不要把 server 端 wa_ key 塞进浏览器——key 是 project 级权限,仅限 server-side 或可信运行时。

一个入口:Client

用户面 API 都挂在同一个 Client 上:

typescript
import { Client } from "@web-agent/sdk";
资源对应产品用法
client.sessions / messages / eventsDoAnything(开放型)自由输入,agent 自己定路径
client.deepResearchDeepResearch(定型 — 研究→报告)Standalone API
client.webSearchWebSearch(定型 — 查询→结果)默认 wait=true 同步糖
client.trackTrack(监控 → snapshot)长寿命 monitor + webhook 通道

DoAnything —— 开放型任务

typescript
import { Client } from "@web-agent/sdk";

const client = new Client({
  apiKey: process.env.WEBAGENT_API_KEY!,
  projectId: process.env.WEBAGENT_PROJECT_ID!,
});

const session = await client.sessions.create({
  instructions: "找出 Hacker News 现在 Top 5 的故事。",
});
const task = session.tasks[0];   // session 创建会隐式排好首个 task

for await (const event of client.events.stream(session.id, task.id)) {
  console.log(event.type, event.data);
  if (event.type === "task.completed") break;
}

wire 字段一律 snake_case 与 API 对齐;方法名 camelCase。

续传 + 心跳

typescript
for await (const event of client.events.stream(session.id, task.id, {
  lastEventId: "142",
  includeHeartbeats: false,
})) {
  if (event.type === "task.completed") break;
}

底层用 fetch + 手写 SSE parser——Node 20+ / Bun / Cloudflare Workers / 浏览器都跑得起来。

「起新 task」 vs 「往运行中 task 塞消息」

typescript
// 1. 塞消息进当前 task 的对话队列
await client.messages.send(session.id, task.id, {
  content: "顺便把每条的评论数也带上。",
});

// 2. 在同一个 session 里起新 task
const followup = await client.sessions.createTask(session.id, {
  instructions: "点进第一条,总结评论区。",
});

回应 input request

typescript
await client.messages.intervene(session.id, task.id, {
  kind: "answer_input_request",
  input_request_id: "ir_01HXX",
  response: { solved: true },
});

kind 是 discriminator,同一个端点也处理 take_control / release_control——见 Take Control

取消 / 停止 / 列表

typescript
await client.sessions.cancelTask(session.id, task.id, { reason: "user_cancelled" });
await client.sessions.stop(session.id, { force: false });
const list = await client.sessions.list({ status: "running", limit: 20 });
list.items.forEach((s) => console.log(s.id, s.status));

DeepResearch —— 研究 → 报告

DR 是 Standalone API(pidless:/v1/deep_research),项目租户从 Bearer token 解析。

typescript
const task = await client.deepResearch.run({
  topic: "2026 年开源向量数据库格局",
  depth: "deep",                  // light / standard / deep
  requireOutlineApproval: true,   // 默认开 outline HITL gate
});

// 订阅事件流(DR 走 DoAnything 的 SSE 通道)+ 响应 outline gate
for await (const event of client.events.stream(
  task.session_id as string, task.task_id as string,
)) {
  if (event.type === "task.input_request") {
    await client.deepResearch.intervene(task.task_id as string, {
      requestId: (event.data as { request_id: string }).request_id,
      response: "approve",  // 或 { action: "approve_with_edits", edits: [...] }
    });
  }
  if (event.type === "task.completed") break;
}

// 拉取产物三件套(final.md / citations.json / confidence.json)
const artifacts = await client.deepResearch.listArtifacts(task.task_id as string);
const final = await client.deepResearch.getArtifact(
  task.task_id as string, artifacts[0]!.id as string,
);

WebSearch —— 查询 → 结果

WS 是 project-scoped API。run() 默认 wait: true,服务器阻塞 ≤30s 后返回 done envelope;超时退化 202,调 get(taskId) 轮询。

typescript
// 同步形态(默认)
const result = await client.webSearch.run({
  queries: ["best TypeScript ORM 2026"],
  engines: ["tavily"],
  summarize: true,
});

// 异步形态
const pending = await client.webSearch.runAsync({
  queries: ["best TypeScript ORM 2026"],
});
const detail = await client.webSearch.get(pending.task_id as string);

// Refine(同 task 内重搜)
await client.webSearch.refine(pending.task_id as string, {
  text: "再加 site:reddit.com 限制重搜",
});

Track —— 长寿命监控

Track 是 project-scoped API。一个 monitor 是长寿命后台 job:cron / interval / event 调度 + 抽取目标 + 通知通道(webhook)。每次 tick 产生一行 snapshot;trigger DSL 判定 diff 值得通知时,通道发送 payload。

typescript
const mon = await client.track.create({
  intent: "apple.com 上 iPhone 17 Pro 跌破 $999 时通知我",
  schedule: { kind: "interval", every_seconds: 3600 },
  notifyChannel: { kind: "callback_url", url: "https://hooks.example.com/track" },
});

// 生命周期 —— 通过 patch 暂停 / 恢复 / refine:
await client.track.pause(mon.id as string, { reason: "人工核对" });
await client.track.resume(mon.id as string);
await client.track.refine(mon.id as string, {
  triggerDsl: { op: "lt", field: "price", value: 999 },
});

// 手动触发一次 tick(绕开 schedule):
const outcome = await client.track.runNow(mon.id as string);

// snapshot 历史(最新优先):
const snaps = await client.track.listSnapshots(mon.id as string);
const snap = await client.track.getSnapshot(
  mon.id as string,
  snaps.items[0]!.id as string,
);

// webhook outbox + 重投:
const deliveries = await client.track.listDeliveries(mon.id as string, {
  includePayload: true,
});
await client.track.retryDelivery(
  mon.id as string,
  deliveries.items[0]!.id as number,
);

// 取消 monitor(终态):
await client.track.cancel(mon.id as string); // 等价:client.track.delete(...)

Alignment HITL(可选)

Supervisor 需要让你澄清意图时,monitor 进入 pending_clarification,发出 alignment.input_request 事件。用 intervene() 回答:

typescript
await client.track.intervene(mon.id as string, {
  requestId: "req_align_1",
  response: "SKU A",
});

也可以随时往 alignment 队列推自由文本:client.track.message(monId, { content: "…" })

错误

typescript
import {
  ApiError,
  InsufficientCreditsError,
  RateLimitedError,
  UnauthorizedError,
} from "@web-agent/sdk";

try {
  await client.sessions.create({ instructions: "…" });
} catch (err) {
  if (err instanceof InsufficientCreditsError) {
    console.log("top up:", err.detail, err.extra);
  } else if (err instanceof ApiError) {
    console.log(err.code, err.statusCode, err.detail);
  } else {
    throw err;
  }
}

每个错误类都继承 ApiError,暴露 code / statusCode / detail / extra,对应 API 错误信封

类型

DoAnything 的 request / response 类型都是顶层 export:

typescript
import type {
  Session, Task, Event, EventType,
  CreateSessionRequest, CreateTaskRequest, InterveneRequest,
  TaskStatus, SessionStatus, TerminalReason,
} from "@web-agent/sdk";

DR / DS / WS 的响应是 Record<string, unknown>(按 OpenAPI 信封原样回传),用键名访问(task.task_id / task.status)。各资源也导出自己的 option 类型(DRRunOptions / DSRunOptions / WSRunOptions)。

接下来