zoowork-managed-agents
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseBuilding on ZooWork Managed Agents
基于 ZooWork Managed Agents 构建
Start with the user's task, then read only the reference that owns it. The public API is a
Developer Preview, so inspect the installed SDK before relying on a remembered signature.
先从用户任务入手,然后只阅读负责该任务的参考文档。公共 API 仍处于 Developer Preview 阶段,因此不要依赖记忆中的签名,编写代码前应先检查已安装的 SDK。
Four invariants
四项不变原则
These are the most common reasons code compiles but fails at runtime:
- creates a stopped Agent. Call
createAgentand wait forstartAgent(id)before opening a Session.desired_state - Every Session method takes first.
agentId - Assistant text comes from through
agent.assistant/assistantText().assistant_text() - A Session stream does not close at turn end. Break on through
run.finished/isRunFinished().is_run_finished()
以下是代码能够编译但运行时失败的最常见原因:
- 创建的是已停止的 Agent。打开 Session 前,应调用
createAgent并等待startAgent(id)。desired_state - 每个 Session 方法都先将 作为第一个参数。
agentId - Assistant 文本通过 /
assistantText()从assistant_text()获取。agent.assistant - Session stream 不会在轮次结束时关闭。应通过 /
isRunFinished()在is_run_finished()时退出循环。run.finished
Preflight
预检查
Before writing code:
- Read ,
package.json, lockfiles, and existing imports.pyproject.toml - Determine whether the project uses or
@zoowork-ai/sdk, and record its installed version. Do not upgrade it unless the user asks.zoowork - Check whether and
ZOOWORK_API_KEYare present without printing their values.ZOOWORK_BASE_URL - Reuse the project's existing client and configuration style.
- Read the routed reference below. For an exact method or type, verify the installed declarations or Python source as the final authority.
If no project is present, state which package and runtime the example assumes. TypeScript requires
Node.js 20+; Python requires Python 3.10+. Install the published package with
or . The public docs and these
references assume 0.10.0+ and 0.5.0+; if an existing project pins an
older release, say so and ask before upgrading.
npm install @zoowork-ai/sdkpython -m pip install zoowork@zoowork-ai/sdkzoowork编写代码前:
- 阅读 、
package.json、lockfile 和现有 import。pyproject.toml - 确定项目使用的是 还是
@zoowork-ai/sdk,并记录已安装的版本。除非用户要求,否则不要升级。zoowork - 检查 和
ZOOWORK_API_KEY是否存在,但不要打印它们的值。ZOOWORK_BASE_URL - 复用项目现有的 client 和配置风格。
- 阅读下方对应的参考文档。对于确切的方法或类型,应以已安装的声明文件或 Python 源码作为最终依据。
如果不存在项目,应说明示例假定使用哪个 package 和 runtime。TypeScript 需要 Node.js 20+;Python 需要 Python 3.10+。可通过 或 安装已发布的 package。公共文档和这些参考资料假定 0.10.0+ 和 0.5.0+;如果现有项目锁定了更旧的版本,应说明情况,并在升级前询问用户。
npm install @zoowork-ai/sdkpython -m pip install zoowork@zoowork-ai/sdkzooworkRoute by task
按任务选择参考文档
| User intent | Read before acting |
|---|---|
TypeScript method, option, return shape, Agent config, model, MCP, permission, Environment, channel, schedule, approval, artifact, | |
| Python import, snake_case method, return shape, event helper, custom tool, Session cursor, Agent config, MCP, or channel | |
| Text task inputs, file outputs, Database availability, Usage, webhook registration/verification/delivery diagnostics, Run Output, or action paging/detail | |
| Stream replies, reconnect, render events or tool calls, read/export history, or write Session events | |
| Host an Agent built locally, select its Skills, deploy one Agent per user, or keep one Skill synchronized across a fleet | |
| Upload, version, list, or delete a platform Skill ZIP | |
| Credentials, binary file attachment, repository mount, worker queues, cross-Agent Session listing, rollback, or another uncertain capability | |
Read more than one reference only when the request genuinely crosses those boundaries. For example,
a basic streaming chat needs the language reference plus events; it does not need the deployment or
capability-boundary documents.
| 用户意图 | 动手前阅读 |
|---|---|
TypeScript 方法、选项、返回结构、Agent 配置、模型、MCP、权限、Environment、Channel、Schedule、审批、Artifact、 | |
| Python import、snake_case 方法、返回结构、事件 helper、自定义工具、Session cursor、Agent 配置、MCP 或 Channel | |
| 文本任务输入、文件输出、Database 可用性、Usage、webhook 注册、验证与投递诊断、Run Output,或 action 分页与详情 | |
| 流式回复、重新连接、渲染事件或工具调用、读取或导出会话历史,或写入 Session 事件 | |
| 托管本地构建的 Agent、选择其 Skill、为每位用户部署一个 Agent,或让一个 Skill 在整个 Agent 集合中保持同步 | |
| 上传、版本化、列出或删除平台 Skill ZIP | |
| 凭据、二进制文件附件、repository mount、worker queue、跨 Agent Session 列举、回滚,或其他尚不确定的能力 | |
仅当请求确实跨越这些边界时,才阅读多份参考文档。例如,基础流式聊天需要语言参考和事件参考;不需要部署或能力边界文档。
Choose the path
选择实现路径
| The user has | Give them |
|---|---|
| No API key or no running Agent | The setup flow below |
| A key and wants a chat UI | The official SDK on their backend, relaying the Session stream to their UI; follow |
| Their own backend, UI, or Agent design | The official SDK |
| A local persona and Skills that need hosted execution | |
Build the UI in the user's own stack. The backend holds , authorizes each
end user, and re-emits Session events to the browser.
ZOOWORK_API_KEY| 用户拥有 | 提供 |
|---|---|
| 没有 API key,或没有运行中的 Agent | 下方的 setup 流程 |
| 有 key,并且需要聊天 UI | 在其 backend 上使用官方 SDK,将 Session stream 转发至 UI;遵循 |
| 自有 backend、UI 或 Agent 设计 | 官方 SDK |
| 需要托管执行的本地 persona 和 Skill | |
应使用用户自己的技术栈构建 UI。backend 持有 、对每位终端用户进行授权,并向浏览器转发 Session 事件。
ZOOWORK_API_KEYAPI key onboarding
API key 接入
Create a Project API key at https://platform.zoowork.ai. Agent and Session access is scoped
to the selected Project. The secret is shown once; have the user save it in
themselves. Keep it on their backend, outside browser/mobile code, logs and chat.
ZOOWORK_API_KEYInitialize Organization billing and bind owner credentials. If the API requests rebinding,
sign in to Platform and rebind the key. / is a cheap read-only
credential check; it does not prove runtime readiness or authorize a billable test.
listModels()list_models()在 https://platform.zoowork.ai 创建 Project API key。Agent 和 Session 访问权限限定在所选 Project 内。secret 仅显示一次;应让用户自行将其保存到 中。将其保存在 backend,避免放入浏览器或移动端代码、日志和聊天记录中。
ZOOWORK_API_KEY初始化 Organization billing 并绑定 owner credentials。如果 API 请求重新绑定,应登录 Platform 并重新绑定 key。 / 是低成本的只读凭据检查;它不能证明 runtime 已就绪,也不代表已获准进行计费测试。
listModels()list_models()Minimal lifecycle
最小生命周期
Use this order:
- List models and select the platform's primary chat default: the row whose value is not
selectableand whosefalseincludesdefault_for. Persist that explicit choice.model - Create the Agent once with a stable idempotency key.
- Persist .
agent_id - Start the Agent and wait for with the SDK helper.
desired_state - Create one Session per conversation.
- Post later turns into the same Session and resume streaming from the last processed cursor.
Do not create an Agent inside the function that answers every user message. Each Agent owns a
persistent workspace and sandbox.
ts
import {
assistantText,
createZooworkClient,
isRunFinished,
runOutcome,
} from '@zoowork-ai/sdk'
const zc = createZooworkClient()
const models = await zc.listModels()
const model = models.find(
(row) => row.selectable !== false && row.default_for?.includes('model'),
)?.model
if (!model) throw new Error('No selectable default ZooWork model')
const created = await zc.createAgent(
{ resource: { name: 'support-agent', model: { primary: model } } },
'support-agent-v1',
)
const agentId = created.agent_id
await zc.startAgent(agentId)
await zc.waitUntilRunning(agentId)
const session = await zc.createSession(agentId, {
initial_events: [{ type: 'user.message', content: 'Hello' }],
})
let cursor: string | undefined
for await (const event of zc.streamEvents(agentId, session.session_id)) {
cursor = event.cursor ?? cursor
process.stdout.write(assistantText(event))
if (isRunFinished(event)) {
if (runOutcome(event) !== 'succeeded') throw new Error(`run ${runOutcome(event)}`)
break
}
}For Python, use the same lifecycle with , , ,
, , , , , and
. Read before writing the exact call shapes; nested
payloads retain public wire spelling where documented.
create_zoowork_clientlist_modelscreate_agentstart_agentwait_until_runningcreate_sessionstream_eventsassistant_textis_run_finishedreferences/python-sdk.md按以下顺序执行:
- 列出模型并选择平台的主要 chat 默认模型,即 值不为
selectable且false包含default_for的那一行。持久保存这一明确选择。model - 使用稳定的 idempotency key 创建一次 Agent。
- 持久保存 。
agent_id - 启动 Agent,并使用 SDK helper 等待 。
desired_state - 为每段对话创建一个 Session。
- 将后续轮次发布到同一个 Session,并从最后处理的 cursor 恢复 stream。
不要在处理每条用户消息的函数内部创建 Agent。每个 Agent 都拥有独立的持久 workspace 和 sandbox。
ts
import {
assistantText,
createZooworkClient,
isRunFinished,
runOutcome,
} from '@zoowork-ai/sdk'
const zc = createZooworkClient()
const models = await zc.listModels()
const model = models.find(
(row) => row.selectable !== false && row.default_for?.includes('model'),
)?.model
if (!model) throw new Error('No selectable default ZooWork model')
const created = await zc.createAgent(
{ resource: { name: 'support-agent', model: { primary: model } } },
'support-agent-v1',
)
const agentId = created.agent_id
await zc.startAgent(agentId)
await zc.waitUntilRunning(agentId)
const session = await zc.createSession(agentId, {
initial_events: [{ type: 'user.message', content: 'Hello' }],
})
let cursor: string | undefined
for await (const event of zc.streamEvents(agentId, session.session_id)) {
cursor = event.cursor ?? cursor
process.stdout.write(assistantText(event))
if (isRunFinished(event)) {
if (runOutcome(event) !== 'succeeded') throw new Error(`run ${runOutcome(event)}`)
break
}
}对于 Python,使用相同的生命周期,并采用 、、、、、、、 和 。编写准确的调用形式前应阅读 ;在已有文档说明的情况下,嵌套 payload 应保留公共 wire 拼写。
create_zoowork_clientlist_modelscreate_agentstart_agentwait_until_runningcreate_sessionstream_eventsassistant_textis_run_finishedreferences/python-sdk.mdSession and event rules
Session 和事件规则
- The event log contains user inputs, assistant replies, tool activity, and run completion.
- Resume every subsequent turn with the last processed event's opaque ; do not derive it from
cursor. Without a cursor the stream replays old turns. REST events and send receipts have no cursor, and the final REST continuation is null. There is no current-tail helper.seq - Checkpoint only after processing the event. Cursor resume does not make application side effects exactly-once.
- returns one page and drops pagination metadata. Use
listEvents()for the full history orlistAllEvents()for explicit cursor pagination.listEventsPage() - is
toolCall().phase,start, orend.blockedends a call without execution; noblockedfollows. Reasons include policy denial, approval denial/timeout/cancellation, or interruption; inspect the raw event payload'send. Approval waiting isdeniedReason/agent.approval.requested - A failed tool call does not necessarily fail the run. is the authority.
runOutcome() - Retried writes should use a stable .
idempotency_key - A valid with no active run can return
user.interrupt; that is a normal no-op.accepted: false - selects memory attribution. It is not authentication, authorization, or sandbox isolation; derive it from authenticated backend state.
actor: { ref }
Application-executed custom tools pause the current run until the user's backend resolves them.
They are not MCP tools and not a worker-registration API. Read both the language reference and the
events reference before implementing recovery.
- 事件日志包含用户输入、Assistant 回复、工具活动和运行完成事件。
- 每个后续轮次都应使用最后一个已处理事件的不透明 恢复;不要根据
cursor推导。没有 cursor 时,stream 会重放旧轮次。REST 事件和发送回执没有 cursor,REST 的最终 continuation 为seq。目前没有nullhelper。current-tail - 仅在处理完事件后才执行 Checkpoint。通过 cursor 恢复并不能让应用副作用具备 exactly-once 保证。
- 返回单页数据,并丢弃分页 metadata。获取完整历史记录应使用
listEvents();显式进行 cursor 分页应使用listAllEvents()。listEventsPage() - 的值为
toolCall().phase、start或end。blocked表示调用未执行便已结束,之后不会出现blocked。原因包括策略拒绝、审批拒绝、超时、取消或中断;应检查原始事件 payload 中的end。等待审批的状态为deniedReason/agent.approval。requested - 工具调用失败不一定会导致运行失败。是判断依据。
runOutcome() - 重试写入操作时,应使用稳定的 。
idempotency_key - 在没有活跃运行的情况下,合法的 可能返回
user.interrupt;这是正常的 no-op。accepted: false - 用于选择 memory 归属。它不是身份认证、授权或 sandbox 隔离机制;应从已通过认证的 backend 状态中派生。
actor: { ref }
由应用执行的自定义工具会暂停当前运行,直到用户的 backend 对其进行处理。它们不是 MCP 工具,也不是 worker-registration API。实现恢复逻辑前,应同时阅读语言参考和事件参考。
Platform Skills
平台 Skill
A ZooWork platform Skill is attached to a running Agent. It is different from this coding-agent
skill, which teaches a developer's assistant how to call ZooWork.
- New Agents receive global Skills by default. Set or an explicit empty Skill list to opt out.
include_global_skills: false - Create bindings accept catalog or
name; inspectskill_id/listAgentSkillsto see the resolved assignment.list_agent_skills - The source-reviewed Skill registry contract permits named Project keys to write Skills and Default Project keys to write
projectSkills. Readorgfor upload, versioning, write permissions, SDK compatibility, and deployment verification.references/skill-registry.md - Project keys do not administer root Environments or Channels. These are separate capabilities.
- Use for standing instructions and Session messages for text task inputs. Ask the Agent to create and publish output, then download it through the Artifact API. Read
persona.docsfor this flow. A workspace file is not a registered Skill. Skill ZIP publishing has its own registry flow; it is not general binary task input upload.references/developer-api.md - Prove runtime behavior with an authorized real turn; attachment state alone does not prove use.
Follow for packaging, versioning, attachment verification,
per-user isolation, scheduling, UI wiring, and teardown.
references/deploy-your-agent.mdZooWork 平台 Skill 依附于正在运行的 Agent。它与当前这个用于教开发者的 assistant 如何调用 ZooWork 的 coding-agent skill 不同。
- 新 Agent 默认获得 global Skill。可设置 ,或显式提供空 Skill 列表,以选择不使用。
include_global_skills: false - 创建绑定时可以使用 catalog 的 或
name;检查skill_id/listAgentSkills,查看解析后的分配结果。list_agent_skills - 经 source-reviewed 的 Skill registry contract 允许具名 Project key 写入 Skill,并允许 Default Project key 写入
projectSkill。阅读org,了解上传、版本管理、写入权限、SDK 兼容性和部署验证。references/skill-registry.md - Project key 无权管理 root Environment 或 Channel。它们属于独立的能力。
- 使用 存放长期指令,并使用 Session 消息传递文本任务输入。让 Agent 创建并发布输出,然后通过 Artifact API 下载。阅读
persona.docs以了解此流程。workspace 文件不是已注册的 Skill。Skill ZIP 发布采用独立的 registry 流程,不能作为通用的二进制任务输入上传。references/developer-api.md - 应通过经授权的真实轮次证明 runtime 行为;仅处于绑定状态并不能证明 Skill 已被使用。
有关打包、版本管理、绑定验证、逐用户隔离、调度、UI 接入和清理销毁,请遵循 。
references/deploy-your-agent.mdCapability and evidence boundary
能力与证据边界
“The SDK has no helper” and “the platform has no public contract” are different claims. Before
saying a feature is absent, inspect the installed SDK, public docs, , and .
A method in SDK declarations proves its signature, not that its endpoint works in production.
Use the documented message-to-Artifact flow for text inputs and file outputs; do not add direct
workspace Files calls as an input or download step.
references/developer-api.mdreferences/not-supported.mdUse these evidence labels:
- Live-verified: exercised against a named deployment.
- Source-reviewed: confirmed in public SDK source or declarations.
- Offline-tested: covered by fixtures or unit tests without a live tenant.
- Unknown: evidence is insufficient; do not invent a method or route.
Do not run live, billable, or tenant-mutating calls merely to answer a design question.
“SDK 没有 helper”和“平台没有 public contract”是两种不同的判断。在声称某项能力不存在之前,应检查已安装的 SDK、公共文档、 和 。SDK 声明中存在某个方法,只能证明其签名,不能证明对应 endpoint 可在生产环境中正常工作。文本输入和文件输出应使用有文档说明的 message-to-Artifact 流程;不要添加对 workspace Files 的直接调用来充当输入或下载步骤。
references/developer-api.mdreferences/not-supported.md使用以下证据标签:
- Live-verified: 已在指定的 deployment 上实际执行验证。
- Source-reviewed: 已通过公共 SDK 源码或声明文件确认。
- Offline-tested: 已通过 fixture 或单元测试覆盖,但未使用 live tenant。
- Unknown: 证据不足;不要虚构方法或 route。
不要仅为回答设计问题而运行会产生费用或修改 tenant 状态的 live 调用。
Common pitfalls
常见陷阱
- Wait on , never
desired_state; the latter is a chat-channel health projection.actual_state - Platform uses a managed Environment. Project keys do not administer root Environments.
- and
createAgentreturn different shapes.getAgent - Production Agent updates reject with
expected_config_version. Omit it for ordinary last-write-wins updates and serialize competing writes in your backend. A GET followed by PUT is not atomic. The separate system-prompt upgrade precondition works.400 invalid_declared_key - MCP exposure, runtime context, and permission policy are separate controls.
- Tool-policy wildcards allow an exact name, global , or one trailing
*only.prefix* - There is no public credential store for an end user's secret.
- Match and
ZooworkError.status, not message text. Usage validation can return 422 with no business type; invalid timezone can return 400.type.usage.invalid_query - A cross-tenant or unknown identifier can return 404 rather than 403. Repeated Agent deletion also returns 404 after the first 204; treat it as cleanup complete only for your known Agent with unchanged key scope.
- The production Database viewer is unavailable. Do not call its SDK helpers or HTTP routes.
Ask the Agent to query via and return results or publish an Artifact.
agent_db - A manual Schedule trigger requires , which also enables automatic firings. Disabled triggers may acknowledge
enabled: truebut are skipped; this is not a test mode.triggered: true - Create Agents one at a time within an Organization. Concurrent calls with the same key can fail with
createAgent; no Agent is created, so retry with backoff and the same idempotency key.503 platform.runtime_credentials_unavailable - For raw HTTP, use the SDK, ,
curlorrequests. The public edge rejects Python's defaulthttpxUser-Agent (urllib) withPython-urllib/...and the body403. That is not an API-key error; set an expliciterror code: 1010header if you must useUser-Agent.urllib - takes argv. A non-zero process exit can still be HTTP 200.
exec(agentId, args) - To remove a throwaway Agent, delete its schedules, call , then
stopAgent. Deletion alone neither stops the sandbox nor removes schedules. If the stop fails, readdeleteAgentand retry the stop before deleting; a deleted Agent cannot be stopped later.getAgent - Do not mix TypeScript camelCase with Python snake_case. Treat identifiers, cursors, and unknown response fields as opaque.
Public developer documentation is at https://zoowork.ai/docs/. For machine reading, use
https://zoowork.ai/docs/llms.txt (an index of per-page Markdown) or
https://zoowork.ai/docs/llms-full.txt (every page in one file).
- 应等待 ,绝不能等待
desired_state;后者是 chat channel 的健康状态投影。actual_state - Platform 使用受管理的 Environment。Project key 无权管理 root Environment。
- 和
createAgent返回不同的数据结构。getAgent - 生产环境中的 Agent 更新会拒绝 ,并返回
expected_config_version。对于普通的 last-write-wins 更新,应省略该字段,并在 backend 中串行化相互竞争的写入。GET 后接 PUT 不是原子操作。单独用于 system-prompt 升级的前置条件仍然有效。400 invalid_declared_key - MCP exposure、runtime context 和 permission policy 是相互独立的控制机制。
- Tool-policy 通配符仅允许精确名称、全局 ,或一个末尾的
*。prefix* - 没有用于保存终端用户 secret 的公共 credential store。
- 应匹配 和
ZooworkError.status,而不是匹配消息文本。Usage 校验可能返回没有业务 type 的 422;无效时区可能返回.type。400 usage.invalid_query - 跨 tenant 或未知 identifier 可能返回 404,而不是 403。首次删除返回 204 后,再次删除 Agent 也会返回 404;只有对于你已知且 key scope 未变化的 Agent,才能将其视为清理完成。
- 生产 Database viewer 不可用。不要调用其 SDK helper 或 HTTP route。应让 Agent 通过 查询并返回结果或发布 Artifact。
agent_db - 手动触发 Schedule 需要 ,这也会启用自动触发。禁用状态的 trigger 可能仍确认
enabled: true,但实际会跳过执行;这不是测试模式。triggered: true - 在 Organization 内应一次创建一个 Agent。使用相同 key 并发调用 可能失败并返回
createAgent;此时不会创建 Agent,因此应使用退避重试和相同的 idempotency key。503 platform.runtime_credentials_unavailable - 对于原始 HTTP 请求,应使用 SDK、、
curl或requests。公共 edge 会拒绝 Python 默认的httpxUser-Agent(urllib),返回 403 和Python-urllib/...。这不是 API key 错误;如果必须使用error code: 1010,应显式设置urllibheader。User-Agent - 接受 argv。进程以非零状态退出时,HTTP 响应仍可能为 200。
exec(agentId, args) - 要删除临时 Agent,应先删除其 schedule,再调用 ,最后调用
stopAgent。仅执行删除既不会停止 sandbox,也不会移除 schedule。如果停止失败,应读取deleteAgent并重试停止,然后才能删除;Agent 删除后将无法再停止。getAgent - 不要混用 TypeScript camelCase 和 Python snake_case。应以不透明方式处理 identifier、cursor 和未知响应字段。
公共开发者文档位于 https://zoowork.ai/docs/。如需供机器读取,可使用 https://zoowork.ai/docs/llms.txt(逐页 Markdown 索引)或 https://zoowork.ai/docs/llms-full.txt(包含所有页面的单一文件)。