diff --git a/docs/plugins.md b/docs/plugins.md index 45caadeae1..81f61c4488 100644 --- a/docs/plugins.md +++ b/docs/plugins.md @@ -474,6 +474,9 @@ path shape: a plugin can place a worktree several directories below the default Emit from the operation owner, not a client subscription. Provider history replay must not trigger live hooks. Notifications must not be awaited inside agent mutations: a handler can send a prompt or answer a permission through its own daemon session. Awaiting it there deadlocks that command. +The same holds for a hook that runs inside an agent's lifecycle lane: an `agent.open.before` hook +that awaits a write to the agent being opened (`setMetadata`, `setLabels`) waits on the open, which +waits on the hook. The hooks reference tells plugin authors to start such a write without awaiting it. ## Contribute a provider diff --git a/public-docs/plugins/hooks.md b/public-docs/plugins/hooks.md index 624c3182dc..ad16eedbcc 100644 --- a/public-docs/plugins/hooks.md +++ b/public-docs/plugins/hooks.md @@ -283,6 +283,17 @@ server.addHook("agent.create.after", async ({ agent }) => { Receives `{ request }`; only `env`, `tools`, and `mcpServers` may change, for this launch. All other fields are read-only. A throw, invalid result, or timeout fails the open. +Do not await a write to the agent being opened, such as `setMetadata`. The write waits for the open to finish, the open waits for your hook, so the hook times out and the open fails. Start the write without awaiting it; it runs right after the open: + +```ts +server.addHook("agent.open.before", async ({ request }, { paseo }) => { + void paseo.agents + .ref(request.agentId) + .setMetadata({ "my.plugin": { openedBy: "hook" } }) + .catch((error) => console.error(error)); +}); +``` + **`agent.open.before` request example:** ```json diff --git a/public-docs/plugins/hooks.zh-CN.md b/public-docs/plugins/hooks.zh-CN.md index 68c903f040..b96202e8ad 100644 --- a/public-docs/plugins/hooks.zh-CN.md +++ b/public-docs/plugins/hooks.zh-CN.md @@ -279,6 +279,17 @@ server.addHook("agent.create.after", async ({ agent }) => { 收到 `{ request }`,只能修改 `env`、`tools` 和 `mcpServers`,修改只用于此次启动。其他字段只读。抛出错误、无效返回或超时会让打开操作失败。 +不要 await 对正在打开的 Agent 的写入,例如 `setMetadata`。该写入要等打开完成,而打开在等你的钩子,结果钩子超时,打开失败。启动写入但不要 await,它会在打开完成后立即执行: + +```ts +server.addHook("agent.open.before", async ({ request }, { paseo }) => { + void paseo.agents + .ref(request.agentId) + .setMetadata({ "my.plugin": { openedBy: "hook" } }) + .catch((error) => console.error(error)); +}); +``` + **`agent.open.before` 请求示例:** ```json