From 9ed7f57c758b2b1009338a4a33480fcd3e9a755a Mon Sep 17 00:00:00 2001 From: Dudu-0223 Date: Thu, 15 Oct 2026 17:49:03 +0800 Subject: [PATCH 01/17] fix(team): include nested descendants in the shared team --- ...6-10-15-agent-teams-as-subagents.i18n.yaml | 4 +- .../2026-10-15-agent-teams-as-subagents.md | 2 +- .../2026-10-15-agent-teams-as-subagents.zh.md | 2 +- apps/web/tests/agent-team-panel.e2e.ts | 44 ++++++++++++ docs/config-catalog.md | 2 +- docs/config-catalog.zh.md | 2 +- docs/tool-catalog.md | 2 +- docs/tool-catalog.zh.md | 2 +- .../agent-team-subagents/guide.i18n.yaml | 4 +- .../agent-team-subagents/guide.md | 2 + .../agent-team-subagents/guide.zh.md | 2 + .../experimental/agent-team/README.i18n.yaml | 20 +++--- packages/experimental/agent-team/README.md | 10 +-- packages/experimental/agent-team/README.zh.md | 10 +-- packages/experimental/agent-team/package.json | 1 + packages/experimental/agent-team/src/index.ts | 4 +- .../experimental/agent-team/src/membership.ts | 55 +++++++++----- .../experimental/agent-team/src/task-board.ts | 7 +- .../agent-team/tests/team.spec.ts | 72 +++++++++++++++++-- .../agent-team/tests/test-session-query.ts | 48 +------------ .../experimental/agent-team/tsconfig.json | 3 +- .../client-ui-agent-team/README.i18n.yaml | 8 +-- .../client-ui-agent-team/README.md | 6 +- .../client-ui-agent-team/README.zh.md | 6 +- .../src/client/TeamAction.tsx | 5 +- .../client-ui-agent-team/src/client/mount.ts | 8 +-- .../src/client/team-view.ts | 45 ++++++++++++ .../tests/browser-plugin.client.spec.ts | 19 +++++ .../tests/team-action.client.spec.tsx | 39 ++++++++++ .../tests/team-view.client.spec.ts | 59 +++++++++++++++ .../experimental/tool-agent-team/README.md | 2 +- .../experimental/tool-agent-team/README.zh.md | 2 +- .../experimental/tool-agent-team/src/index.ts | 4 +- .../team-descendant-task/session.1.v4.jsonl | 28 ++++++++ .../team-descendant-task/session.2.v4.jsonl | 18 +++++ .../team-descendant-task/session.v4.jsonl | 44 ++++++++++++ .../session/team-descendant-task/snapshot.yml | 9 +++ .../team-targets/system-prompt.expected.md | 2 +- .../team-targets/tool-schemas.expected.json | 2 +- 39 files changed, 477 insertions(+), 127 deletions(-) create mode 100644 packages/experimental/client-ui-agent-team/src/client/team-view.ts create mode 100644 packages/experimental/client-ui-agent-team/tests/team-view.client.spec.ts create mode 100644 snapshots/session/team-descendant-task/session.1.v4.jsonl create mode 100644 snapshots/session/team-descendant-task/session.2.v4.jsonl create mode 100644 snapshots/session/team-descendant-task/session.v4.jsonl create mode 100644 snapshots/session/team-descendant-task/snapshot.yml diff --git a/.agents/notes/implemented/architecture/2026-10-15-agent-teams-as-subagents.i18n.yaml b/.agents/notes/implemented/architecture/2026-10-15-agent-teams-as-subagents.i18n.yaml index 0409e65f17..4d74a9b1b6 100644 --- a/.agents/notes/implemented/architecture/2026-10-15-agent-teams-as-subagents.i18n.yaml +++ b/.agents/notes/implemented/architecture/2026-10-15-agent-teams-as-subagents.i18n.yaml @@ -15,8 +15,8 @@ en: ef0cf648ff54784f zh: 2a0b3745a54e7072 /agent-note-agent-teams-teammates-are-subagents/consequences: - en: 48e0970fdfe79cbc - zh: f36b1825ba65a673 + en: c10302148d6ea27a + zh: f96e3a1c87dde43d /agent-note-agent-teams-teammates-are-subagents/testing: en: 7ea558d6e3fab9a7 zh: d51053c7d4f0b10f diff --git a/.agents/notes/implemented/architecture/2026-10-15-agent-teams-as-subagents.md b/.agents/notes/implemented/architecture/2026-10-15-agent-teams-as-subagents.md index 29fb17bd56..0e3941c1cd 100644 --- a/.agents/notes/implemented/architecture/2026-10-15-agent-teams-as-subagents.md +++ b/.agents/notes/implemented/architecture/2026-10-15-agent-teams-as-subagents.md @@ -32,7 +32,7 @@ This supersedes the roster, provisioning, recovery, and messaging decisions in [ Ordinary continuable siblings can discover and message one another. Team retains task ownership, dependencies, waits, policy, and role identity. Its member and message-size limits and Team-owned teardown disappear; subagent capacity and lifecycle apply. Failed starts leave no Team roster row. No new Session payload generation is required, and historical member names remain decode-only data. -Deeper descendants share tasks and waits but are not roster rows; their message routes remain limited to their own parent, children, and continuable siblings. Separate working directories and cross-process coordination remain unsupported. +The Web panel combines per-Session rosters to show discovered descendants at every depth. Lead task reassignment verifies live or persisted descendant ancestry; message routes remain limited to each member’s own parent, children, and continuable siblings. Separate working directories and cross-process coordination remain unsupported. ## Testing diff --git a/.agents/notes/implemented/architecture/2026-10-15-agent-teams-as-subagents.zh.md b/.agents/notes/implemented/architecture/2026-10-15-agent-teams-as-subagents.zh.md index 52d4f7d6eb..e89dba8d5d 100644 --- a/.agents/notes/implemented/architecture/2026-10-15-agent-teams-as-subagents.zh.md +++ b/.agents/notes/implemented/architecture/2026-10-15-agent-teams-as-subagents.zh.md @@ -32,7 +32,7 @@ Status: implemented 普通可继续同级可发现彼此并发消息。Team 保留任务所有权、依赖、等待、策略和角色身份。成员数量限制、消息大小限制和 Team 自有释放被移除,改用子代理容量与生命周期。启动失败不留下 Team 成员行。不需要新的 Session 载荷代际,历史成员名称只作为解码数据保留。 -更深的后代共享任务和等待,但不显示成员行;消息路由仍限于自己的父级、子级和可继续同级。仍不支持独立工作目录和跨进程协调。 +Web 面板合并各会话的成员列表,显示所有已发现的后代。Lead 任务指派验证实时或持久后代谱系;消息路由仍限于每个成员自己的父级、子级和可继续同级。仍不支持独立工作目录和跨进程协调。 ## Testing diff --git a/apps/web/tests/agent-team-panel.e2e.ts b/apps/web/tests/agent-team-panel.e2e.ts index 2068e47a88..40e6c016fa 100644 --- a/apps/web/tests/agent-team-panel.e2e.ts +++ b/apps/web/tests/agent-team-panel.e2e.ts @@ -10,6 +10,7 @@ import * as yaml from 'js-yaml' import { entryListSchema } from '@deepseek-ai/cordis-plugin-include' import type {} from '@deepseek-ai/dsh-experimental-agent-team' import { createMessage, createUserMessage } from '@deepseek-ai/dsh-llm' +import { MockAdapter } from '../../../packages/core/agent-loop/tests/mock-adapter.ts' import { assertFixtureInventory, captureStableAria, compareOrRefreshGolden, launchWebScaffold, watchConsole, webSnapshotMode, type WebScaffold, @@ -204,6 +205,49 @@ describe('web e2e: Agent Teams panel', () => { } }) + it('shows nested teammates on the root board and opens their direct-parent conversation', async () => { + onTestFailed(() => saveFailureShot(page, 'web-e2e-agent-team-descendants')) + const root = scaffold.ctx.agents.roots()[0]! + const provider = 'team-descendant-fixture' + scaffold.ctx.effect(() => scaffold.ctx.llm.registerAdapter([provider], new MockAdapter(['hang', 'hang']))) + const branch = await scaffold.ctx.subagents.startActivation({ + provider: 'spawn', label: 'Branch reviewer', delivery: 'caller', signal: new AbortController().signal, + request: { + parent: root, prompt: [{ type: 'text', text: 'Review the branch.' }], + agentOptions: { provider, model: 'fixture' }, + }, + }) + onTestFinished(() => branch.dispose()) + const parent = await vi.waitFor(() => { + const agent = scaffold.ctx.agents.get(branch.childId) + expect(agent?.status).toBe('running') + return agent! + }) + const leaf = await scaffold.ctx.subagents.startActivation({ + provider: 'spawn', label: 'Nested reviewer', delivery: 'caller', signal: new AbortController().signal, + request: { parent, prompt: [{ type: 'text', text: 'Review nested changes.' }] }, + }) + onTestFinished(() => leaf.dispose()) + await vi.waitFor(() => { expect(scaffold.ctx.agents.get(leaf.childId)?.status).toBe('running') }) + const task = await scaffold.ctx.agentTeams.createTask(root, { subject: 'Nested task', description: 'Review nested changes.' }) + await scaffold.ctx.agentTeams.updateTask(root, { + taskId: task.id, expectedRevision: task.revision, action: 'reassign', owner: leaf.childId, + }) + const trigger = page.locator('[data-team-action]').getByRole('button', { name: 'Agent Team', exact: true }) + const panel = page.getByRole('dialog', { name: 'Agent Team', exact: true }) + await trigger.click() + await panel.getByText('Owner: Nested reviewer', { exact: true }).waitFor() + await panel.getByRole('button', { name: /Nested reviewer/u }).click() + await page.getByText('Review nested changes.', { exact: true }).first().waitFor() + await trigger.click() + await panel.getByText('Nested task', { exact: true }).waitFor() + expect(await panel.getByRole('button', { name: /Nested reviewer/u }).isDisabled()).toBe(true) + await panel.getByRole('button', { name: /Lead/u }).click() + await page.getByText('Ready.', { exact: true }).waitFor() + expect(tripwire.pageErrors).toEqual([]) + expect(tripwire.warnings).toEqual([]) + }, 60_000) + it.skipIf(MODE === 'record')('keeps the fixture inventory closed', async () => { await assertFixtureInventory(SNAPSHOT_DIR, ['task.expected.md', 'resize.expected.md']) }) diff --git a/docs/config-catalog.md b/docs/config-catalog.md index 5b7ed380d6..f8d63ce6f1 100644 --- a/docs/config-catalog.md +++ b/docs/config-catalog.md @@ -840,7 +840,7 @@ export interface Config { ## `@deepseek-ai/dsh-experimental-agent-team` -- `inject`: `agents` · `sessions` · `sessionProjections` +- `inject`: `agents` · `sessions` · `sessionProjections` · `sessionQuery` - `source`: [`packages/experimental/agent-team/src/types.ts:152`](../packages/experimental/agent-team/src/types.ts) ```ts config-catalog diff --git a/docs/config-catalog.zh.md b/docs/config-catalog.zh.md index 625c4ddb99..d5a0ec5612 100644 --- a/docs/config-catalog.zh.md +++ b/docs/config-catalog.zh.md @@ -842,7 +842,7 @@ export interface Config { ## `@deepseek-ai/dsh-experimental-agent-team` -- `inject`: `agents` · `sessions` · `sessionProjections` +- `inject`: `agents` · `sessions` · `sessionProjections` · `sessionQuery` - `source`: [`packages/experimental/agent-team/src/types.ts:152`](../packages/experimental/agent-team/src/types.ts) ```ts config-catalog diff --git a/docs/tool-catalog.md b/docs/tool-catalog.md index 811595b41f..29512bfaae 100644 --- a/docs/tool-catalog.md +++ b/docs/tool-catalog.md @@ -2426,7 +2426,7 @@ Compare-and-set a shared task action using the latest revision from team_task_ge }, "owner": { "type": "string", - "description": "Agent id of the Lead or one of its direct continuable children for Lead-only reassign; omit to unassign." + "description": "Agent id of the Lead or a continuable descendant for Lead-only reassign; omit to unassign." } }, "required": [ diff --git a/docs/tool-catalog.zh.md b/docs/tool-catalog.zh.md index 780df7e476..09d7205d5e 100644 --- a/docs/tool-catalog.zh.md +++ b/docs/tool-catalog.zh.md @@ -2432,7 +2432,7 @@ lsp 工具将提供方选择和语言服务器子进程置于 ctx.lsp 之后, }, "owner": { "type": "string", - "description": "Agent id of the Lead or one of its direct continuable children for Lead-only reassign; omit to unassign." + "description": "Agent id of the Lead or a continuable descendant for Lead-only reassign; omit to unassign." } }, "required": [ diff --git a/docs/upgrade-guide/v0.2.1-alpha.3/agent-team-subagents/guide.i18n.yaml b/docs/upgrade-guide/v0.2.1-alpha.3/agent-team-subagents/guide.i18n.yaml index de503a5d4e..2f3b17a217 100644 --- a/docs/upgrade-guide/v0.2.1-alpha.3/agent-team-subagents/guide.i18n.yaml +++ b/docs/upgrade-guide/v0.2.1-alpha.3/agent-team-subagents/guide.i18n.yaml @@ -9,8 +9,8 @@ en: 32ee389e58de25fe zh: 420fd4344f8f1214 /agent-teams-uses-subagents-and-session-ids/change: - en: fb96ccedefaa5eee - zh: 7598b8e1f2cffac7 + en: 033cc41a4943dd9f + zh: aefa4ce17925e34f /agent-teams-uses-subagents-and-session-ids/migration: en: 0ed5e22412074192 zh: 60deae7d46a21c75 diff --git a/docs/upgrade-guide/v0.2.1-alpha.3/agent-team-subagents/guide.md b/docs/upgrade-guide/v0.2.1-alpha.3/agent-team-subagents/guide.md index 278d432b62..1707c04c34 100644 --- a/docs/upgrade-guide/v0.2.1-alpha.3/agent-team-subagents/guide.md +++ b/docs/upgrade-guide/v0.2.1-alpha.3/agent-team-subagents/guide.md @@ -17,6 +17,8 @@ The experimental Agent Teams plugins share agent creation, discovery, messaging, - `ctx.agentTeams` removes `spawnTeammate()`, `sendMessage()`, `interrupt()`, and `listMembers()`. Task views expose `ownerId` instead of `ownerName`; task ownership uses Session ids, including the Lead's id. - Historical Team roster and mailbox records remain readable. Names in those records are historical data and do not resolve message recipients or task owners. Subagent catalog payloads are unchanged. +- Custom Team compositions must provide `sessionQuery` so task assignment can verify inactive descendants from persisted Sessions. Profiles built on `@deepseek-ai/dsh-base` already provide it. + ## Migration 1. Remove the obsolete configuration keys and any patch rows that disable subagent tools solely for Team support. diff --git a/docs/upgrade-guide/v0.2.1-alpha.3/agent-team-subagents/guide.zh.md b/docs/upgrade-guide/v0.2.1-alpha.3/agent-team-subagents/guide.zh.md index 408763c21d..a702d42bb2 100644 --- a/docs/upgrade-guide/v0.2.1-alpha.3/agent-team-subagents/guide.zh.md +++ b/docs/upgrade-guide/v0.2.1-alpha.3/agent-team-subagents/guide.zh.md @@ -17,6 +17,8 @@ description: "Agent Teams 使用标准 subagent 工具和 Session id;移除 Te - `ctx.agentTeams` 移除 `spawnTeammate()`、`sendMessage()`、`interrupt()` 和 `listMembers()`。任务视图以 `ownerId` 取代 `ownerName`;包括 Lead 在内,任务所有者均使用 Session id。 - 历史 Team 名册和邮箱记录仍可读取。其中的名字仅作为历史数据,不用于解析消息收件人或任务所有者。Subagent catalog 载荷不变。 +- 自定义 Team composition 必须提供 `sessionQuery`,以便任务指派通过持久 Session 验证不活动的后代。基于 `@deepseek-ai/dsh-base` 的 profile 已提供此服务。 + ## 迁移 1. 删除废弃配置键,以及仅为支持 Team 而禁用 subagent 工具的 patch 行。 diff --git a/packages/experimental/agent-team/README.i18n.yaml b/packages/experimental/agent-team/README.i18n.yaml index 8a665b241e..fe38e4f667 100644 --- a/packages/experimental/agent-team/README.i18n.yaml +++ b/packages/experimental/agent-team/README.i18n.yaml @@ -21,17 +21,17 @@ en: 12d03bedc2a7be57 zh: 27fc0dc8fef2340b /deepseek-ai-dsh-experimental-agent-team/use-this-package/smallest-working-setup: - en: 037e98afeb998730 - zh: 224b568c2d54cd92 + en: 56ef4fcdbaba4f46 + zh: 864e1e25b814cf96 /deepseek-ai-dsh-experimental-agent-team/use-this-package/teammates: - en: 6946c12e1482c65c - zh: 9320041928c49519 + en: 281583cee3488fb5 + zh: 6381cd3785c7c230 /deepseek-ai-dsh-experimental-agent-team/use-this-package/messages-between-teammates: en: 3bcd3a00b3d9de9b zh: 00a404f4cf033a16 /deepseek-ai-dsh-experimental-agent-team/use-this-package/shared-task-board: - en: 21623c0bb323b8bd - zh: 13012bad307d26f3 + en: b3e0f2ad843818ca + zh: 81461a52a7738499 /deepseek-ai-dsh-experimental-agent-team/use-this-package/waiting-and-interruption: en: 494f4d031fc69dec zh: ebaf87dbca8c4346 @@ -57,8 +57,8 @@ en: 7ab4daa9ce7989b9 zh: 4eec246570ffef35 /deepseek-ai-dsh-experimental-agent-team/understand-the-implementation/shared-task-board: - en: f6e2b30909a25d53 - zh: f4c6937dd4402f7c + en: e025987b0c648836 + zh: eeba52cfb9c5ad46 /deepseek-ai-dsh-experimental-agent-team/understand-the-implementation/waiting: en: babe6d5ed5b72077 zh: 8d112b5d6ce8235e @@ -90,8 +90,8 @@ en: e5c406af31bf0c67 zh: 987e49e0f3e5af69 /deepseek-ai-dsh-experimental-agent-team/known-limitations-and-deferred-work: - en: e101287168ed5875 - zh: 909da68681f2b408 + en: 0cb992872f6de495 + zh: 62374e3057bda3ba /deepseek-ai-dsh-experimental-agent-team/known-limitations-and-deferred-work/dev-note: en: 498e4cf9fe5741a7 zh: 9d2bab630e655c99 diff --git a/packages/experimental/agent-team/README.md b/packages/experimental/agent-team/README.md index 045b7ea5ff..2c7f16ca16 100644 --- a/packages/experimental/agent-team/README.md +++ b/packages/experimental/agent-team/README.md @@ -35,7 +35,7 @@ Choose it when delegated agents must divide and track shared work in one checkou -Mount both Team packages in a composition that already provides continuable subagents, their messaging tools, and durable session storage, such as a profile built on `@deepseek-ai/dsh-base`: +Mount both Team packages in a composition that already provides continuable subagents, their messaging tools, durable session storage, and `sessionQuery`, such as a profile built on `@deepseek-ai/dsh-base`: ```yaml # smallest Team addition over a composition with continuable subagents @@ -55,7 +55,7 @@ The generated [configuration catalog](../../../docs/config-catalog.md#deepseek-a Ask the Lead to start a subagent with a `description` of its work: `subagent` starts fresh, while `subagent_fork` inherits completed turns. The returned Session id addresses the teammate; descriptions are display text and may repeat. -Every root agent leads its own Team, and every live subagent below it, at any depth, receives Team tools. The roster lists the Lead, its direct continuable children, and historical `team/member` records. Deeper descendants work on the same board under their Session ids but have no roster row. +Every root agent leads its own Team, and every live subagent below it, at any depth, receives Team tools. The roster lists the Lead, its direct continuable children, and historical `team/member` records. The Web panel combines these per-Session rosters to include discovered descendants at every depth. ### Messages between teammates @@ -65,7 +65,7 @@ Members use standard `send_message` with Session ids: the Lead reaches direct ch Any member can add a task with a title, details, optional dependencies on other tasks, and optional hints about which files it will touch. A task is claimable only when everything it depends on is complete. -A member claims a task to start work, completes it, releases it, or reopens it. The Lead can reassign a task by Session id to itself, a direct continuable child, or an active historical member. Other members claim tasks themselves. Every change is compare-and-set, so stale updates cannot overwrite newer work. +A member claims a task to start work, completes it, releases it, or reopens it. The Lead can reassign a task by Session id to itself, a continuable descendant at any depth, or an active historical member. Other members claim tasks themselves. Every change is compare-and-set, so stale updates cannot overwrite newer work. File hints produce warnings when two in-progress tasks plan to touch overlapping paths — they never block anything. Deleted tasks remain in history but disappear from the active list. @@ -126,7 +126,7 @@ Team sends no messages. Routes, Steer delivery, cold resume, and sender framing ### Shared task board -Tasks are complete versioned snapshots; every mutation carries `expectedRevision`, and a stale caller receives `TEAM_TASK_STALE_REVISION` instead of overwriting a newer value. Numeric `task-` ids require a safe-integer suffix, and id-space exhaustion reports `TEAM_TASK_LIMIT` instead of reusing the final id. Deleted tasks remain tombstones for replay and id stability but do not consume `maxTasks` or appear in `listTasks()`. `writeScopes` are normalized workspace-relative prefixes; views warn on overlap with in-progress tasks but never block claim or authorize writes. Lead reassignment resolves the root, a direct continuable child, or an active historical member by Session id, and reports `TEAM_MEMBER_NOT_FOUND` for anything else. +Tasks are complete versioned snapshots; every mutation carries `expectedRevision`, and a stale caller receives `TEAM_TASK_STALE_REVISION` instead of overwriting a newer value. Numeric `task-` ids require a safe-integer suffix, and id-space exhaustion reports `TEAM_TASK_LIMIT` instead of reusing the final id. Deleted tasks remain tombstones for replay and id stability but do not consume `maxTasks` or appear in `listTasks()`. `writeScopes` are normalized workspace-relative prefixes; views warn on overlap with in-progress tasks but never block claim or authorize writes. Lead reassignment accepts the root, continuable descendants at any depth, and active historical members by Session id. Deep assignment reads live or persisted observations and verifies each child’s own descriptor against its direct parent’s catalog. Ordinary forks, unrelated Teams, missing ancestry, and cycles report `TEAM_MEMBER_NOT_FOUND`; storage failures remain read errors. ### Waiting @@ -194,7 +194,7 @@ These limits describe what a team cannot do yet or what needs special operationa - **Experimental prototype with no stability promise** — the package is public, but its contracts can change freely while it incubates. - **One process and one shared checkout** — members share cwd and observe edits immediately; this package provides no worktree, remote member, merge, or filesystem lock. - **Advisory write scopes** — Bash, formatters, code generators, and direct external writers can bypass filesystem version checks; Leads must coordinate ownership and review the final diff. -- **Roster covers direct continuable children** — deeper descendants share tasks and waits but have no roster row; they can claim tasks under their own ids and message only their direct parent, children, and continuable siblings. +- **Adjacent messaging** — members message only their direct parent, children, and continuable siblings, even though the task board includes all depths. - **Membership needs a live lineage** — a subagent whose parent Agent is not loaded is outside every Team, so its Team calls fail with `TEAM_NOT_MEMBER`. - **No automatic ownership release** — inactivity, interruption, process exit, and failed work do not release a task owner. - **Historical queued messages stay undelivered** — `team/message/queued` records without a matching delivery remain readable in the Lead log, but no member receives them. diff --git a/packages/experimental/agent-team/README.zh.md b/packages/experimental/agent-team/README.zh.md index 69e9bfb875..f73e369a94 100644 --- a/packages/experimental/agent-team/README.zh.md +++ b/packages/experimental/agent-team/README.zh.md @@ -35,7 +35,7 @@ kind: "package-reference" -在已经提供 continuable subagent、其消息工具和持久会话存储的组合(例如基于 `@deepseek-ai/dsh-base` 的 profile)中挂载两个 Team 包: +在已经提供 continuable subagent、其消息工具、持久会话存储和 `sessionQuery` 的组合(例如基于 `@deepseek-ai/dsh-base` 的 profile)中挂载两个 Team 包: ```yaml # smallest Team addition over a composition with continuable subagents @@ -55,7 +55,7 @@ kind: "package-reference" 让 Lead 使用 `description` 描述工作并启动子代理:`subagent` 从全新上下文开始,`subagent_fork` 继承已完成轮次。返回的 Session id 用于寻址队友;描述用于展示,可以重复。 -每个根代理领导自己的 Team,其下任意深度的在线子代理都获得 Team 工具。成员列表包含 Lead、其直接可继续子级以及历史 `team/member` 记录。更深的后代按 Session id 使用同一任务板,但不显示为成员行。 +每个根代理领导自己的 Team,其下任意深度的每个在线子代理都收到 Team 工具。每个会话的成员列表包含 Lead、直接可继续子代理和历史 `team/member` 记录。Web 面板合并这些会话列表,显示所有已发现的后代。 ### teammate 之间的消息 @@ -65,7 +65,7 @@ kind: "package-reference" 任何成员都可以添加任务,包含标题、详情、对其他任务的可选依赖,以及可选的文件触及提示。只有其全部依赖完成后,任务才可 claim。 -成员认领任务后开始工作,可以完成、释放或重新打开任务。Lead 可按 Session id 将任务重新分配给自身、直接可继续子级或活跃的历史成员。其他成员自行认领任务。每次变更都使用比较并设置,防止过期更新覆盖新工作。 +成员认领任务后开始工作,可以完成、释放或重新打开任务。Lead 可按 Session id 将任务重新分配给自身、任意深度的可继续后代或活跃的历史成员。其他成员自行认领任务。每次变更都使用比较并设置,防止过期更新覆盖新工作。 当两个 in-progress 任务计划触及重叠路径时,文件提示会产生警告——它们绝不阻止任何操作。已删除任务保留在历史中,但从活动列表中消失。 @@ -126,7 +126,7 @@ Team 不发送消息。`send_message` 的路由、Steer 投递、冷恢复和发 ### 共享任务板 -任务是完整版本化快照;每次变更都携带 `expectedRevision`,陈旧调用方会收到 `TEAM_TASK_STALE_REVISION`,而不会覆盖更新的值。数字 `task-` id 的后缀必须是安全整数,id 空间耗尽时报告 `TEAM_TASK_LIMIT`,而不是复用最后一个 id。已删除任务作为 tombstone 保留以供回放与维持 id 稳定,但不占用 `maxTasks`,也不出现在 `listTasks()` 中。`writeScopes` 是规范化后的 workspace 相对前缀;视图会对与 in-progress 任务的重叠发出警告,但绝不阻止 claim 或授予写权限。Lead reassign 按 Session id 解析根、直接可继续子级或 active 历史成员,其他目标报告 `TEAM_MEMBER_NOT_FOUND`。 +任务是完整版本化快照;每次变更都携带 `expectedRevision`,陈旧调用方会收到 `TEAM_TASK_STALE_REVISION`,而不会覆盖更新的值。数字 `task-` id 的后缀必须是安全整数,id 空间耗尽时报告 `TEAM_TASK_LIMIT`,而不是复用最后一个 id。已删除任务作为 tombstone 保留以供回放与维持 id 稳定,但不占用 `maxTasks`,也不出现在 `listTasks()` 中。`writeScopes` 是规范化后的 workspace 相对前缀;视图会对与 in-progress 任务的重叠发出警告,但绝不阻止 claim 或授予写权限。Lead 按 Session id 将任务分配给根、任意深度的 continuable 后代或活跃历史成员。深层指派读取实时或持久观察,并逐层核对孩子自己的 descriptor 与直接父代理的 catalog。普通 fork、其他 Team、缺失祖先和循环关系报告 `TEAM_MEMBER_NOT_FOUND`;存储读取失败原样报告。 ### 等待 @@ -194,7 +194,7 @@ Mailbox 投影与 checkpoint 准入保留本地声明的校验器之外获准内 - **实验原型,无稳定性承诺**——本包公开发布,但孵化期间约定仍可自由变更。 - **单进程、共享 checkout**——成员共享 cwd,修改立即可见;本包不提供 worktree、远端成员、merge 或文件锁。 - **write scope 仅作提示**——Bash、formatter、代码生成器与直接外部写入可以绕过文件版本检查;Lead 必须协调 owner 并检查最终 diff。 -- **成员列表覆盖直接可继续子级**——更深的后代共享任务和等待,但不显示成员行;它们可按自身 id 认领任务,并且只能联系直接父级、子级和可继续同级。 +- **相邻消息路由**——成员只能联系直接父级、子级和可继续同级,即使任务板覆盖所有深度。 - **成员关系需要 live 谱系**——parent Agent 未加载的 subagent 不属于任何 Team,因此其 Team 调用以 `TEAM_NOT_MEMBER` 失败。 - **不会自动释放 owner**——成员不活动、interrupt、进程退出与工作失败都不会释放任务 owner。 - **历史排队消息保持未投递**——没有对应投递记录的 `team/message/queued` 记录仍可在 Lead 日志中读取,但不会有成员收到它们。 diff --git a/packages/experimental/agent-team/package.json b/packages/experimental/agent-team/package.json index 9dadfae197..5948cae1b1 100644 --- a/packages/experimental/agent-team/package.json +++ b/packages/experimental/agent-team/package.json @@ -48,6 +48,7 @@ "@deepseek-ai/dsh-llm": "workspace:*", "@deepseek-ai/dsh-session": "workspace:*", "@deepseek-ai/dsh-session-projection": "workspace:*", + "@deepseek-ai/dsh-session-query": "workspace:*", "@deepseek-ai/dsh-subagent": "workspace:*" }, "devDependencies": { diff --git a/packages/experimental/agent-team/src/index.ts b/packages/experimental/agent-team/src/index.ts index f8c7d7b5a9..ad37b80e8b 100644 --- a/packages/experimental/agent-team/src/index.ts +++ b/packages/experimental/agent-team/src/index.ts @@ -45,7 +45,7 @@ function positiveLimit(name: string, value: number): number { /** Agent Teams service backed by the exact live Lead Session log. */ export class TeamService extends Service { - static inject = ['agents', 'sessions', 'sessionProjections'] + static inject = ['agents', 'sessions', 'sessionProjections', 'sessionQuery'] static Config: z = z.object({ maxTasks: z.number().step(1).min(1).default(DEFAULT_MAX_TASKS), @@ -71,7 +71,7 @@ export class TeamService extends Service { this.activity = new TeamActivity() this.journal = new TeamJournal(ctx, (root) => { this.activity.notify(TeamId(root.id)) }) this.members = new TeamMembers(ctx) - this.tasks = new TeamTaskBoard(this.journal, maxTasks) + this.tasks = new TeamTaskBoard(this.journal, maxTasks, this.members) const notifyMember = ({ agent }: { agent: Agent }): void => { const membership = this.members.tryMembership(agent) diff --git a/packages/experimental/agent-team/src/membership.ts b/packages/experimental/agent-team/src/membership.ts index e90f0fc6b4..2a282734ff 100644 --- a/packages/experimental/agent-team/src/membership.ts +++ b/packages/experimental/agent-team/src/membership.ts @@ -3,6 +3,7 @@ import type { Context } from '@deepseek-ai/cordis' import type { Agent } from '@deepseek-ai/dsh-agent' import type { SessionId } from '@deepseek-ai/dsh-session' +import { SessionQueryError } from '@deepseek-ai/dsh-session-query' import type {} from '@deepseek-ai/dsh-subagent' import { TeamError } from './error.ts' import type { TeamState } from './projection.ts' @@ -16,23 +17,6 @@ export interface TeamMembership { readonly role: 'lead' | 'teammate' } -/** - * Resolve one member Session id for task assignment. - * @param root - exact live Team Lead. - * @param state - current Team state. - * @param target - member Session id. - * @returns the member's durable id. - */ -export function resolveMember(root: Agent, state: TeamState, target: SessionId): SessionId { - if (target === root.id) return root.id - const child = state.children.find(candidate => candidate.id === target) - if (child !== undefined) return child.id - const member = state.members.find(candidate => candidate.phase === 'active' - && candidate.id === target) - if (member === undefined) throw new TeamError(`teammate "${target}" not found`, 'TEAM_MEMBER_NOT_FOUND') - return member.id -} - /** Resolves Team membership from the live Agent registry. */ export class TeamMembers { /** @@ -42,6 +26,43 @@ export class TeamMembers { private readonly ctx: Context, ) {} + /** + * Resolve a task assignee from direct catalog facts or a durable descendant chain. + * Every descendant edge requires a continuable child descriptor and its parent's + * own catalog entry; ordinary forks and unrelated Teams are excluded. + * @param root - exact live Team Lead. + * @param state - current Lead-owned Team state. + * @param target - member Session id, including an inactive descendant. + * @returns the member's durable id. + */ + async resolveMember(root: Agent, state: TeamState, target: SessionId): Promise { + if (target === root.id || state.children.some(child => child.id === target) + || state.members.some(member => member.phase === 'active' && member.id === target)) return target + const missing = (): TeamError => new TeamError(`teammate "${target}" not found`, 'TEAM_MEMBER_NOT_FOUND') + const observe = async (id: SessionId) => { + try { + return await this.ctx.sessionQuery.observeSession(id) + } catch (error) { + if (error instanceof SessionQueryError && error.code === 'SESSION_QUERY_SESSION_NOT_FOUND') throw missing() + throw error + } + } + const seen = new Set() + let current = target + while (!seen.has(current)) { + seen.add(current) + using child = await observe(current) + const identity = child.projections?.values.subagent + const parentId = child.header.parentSession + if (identity?.mode !== 'continuable' || identity.seq < child.inheritedEventCount || parentId === undefined) throw missing() + using parent = await observe(parentId) + if (!parent.projections?.values.subagentCatalog?.some(entry => entry.id === current && entry.mode === 'continuable')) throw missing() + if (parentId === root.id) return target + current = parentId + } + throw missing() + } + /** * Resolve one exact live Agent's Team role. * @param agent - exact live Agent used as the authority credential. diff --git a/packages/experimental/agent-team/src/task-board.ts b/packages/experimental/agent-team/src/task-board.ts index fc90c5a1cf..6a43c584af 100644 --- a/packages/experimental/agent-team/src/task-board.ts +++ b/packages/experimental/agent-team/src/task-board.ts @@ -1,11 +1,10 @@ /** Shared Team task DAG commands and runtime-enriched views. */ import type { Agent } from '@deepseek-ai/dsh-agent' -import type { TeamMembership } from './membership.ts' +import type { TeamMembers, TeamMembership } from './membership.ts' import { TeamError } from './error.ts' import type { TeamJournal } from './journal.ts' import type { TeamState } from './projection.ts' -import { resolveMember } from './membership.ts' import { assertTaskGraphCandidate, TeamTaskGraphError } from './task-graph.ts' import type { TeamTaskGraphViolation } from './task-graph.ts' import { TeamId, TeamTaskId } from './types.ts' @@ -29,10 +28,12 @@ export class TeamTaskBoard { /** * @param journal - authoritative Lead-log transaction owner. * @param maxTasks - maximum non-deleted tasks retained by one Team. + * @param members - live membership and durable assignee resolution. */ constructor( private readonly journal: TeamJournal, private readonly maxTasks: number, + private readonly members: TeamMembers, ) {} /** @@ -182,7 +183,7 @@ export class TeamTaskBoard { break } if (!taskReady(state, current)) throw new TeamError(`team task "${current.id}" is blocked`, 'TEAM_TASK_BLOCKED') - next = { ...current, status: 'in_progress', ownerId: resolveMember(root, state, request.owner) } + next = { ...current, status: 'in_progress', ownerId: await this.members.resolveMember(root, state, request.owner) } break } case 'delete': { diff --git a/packages/experimental/agent-team/tests/team.spec.ts b/packages/experimental/agent-team/tests/team.spec.ts index 76ad64897d..3132440f56 100644 --- a/packages/experimental/agent-team/tests/team.spec.ts +++ b/packages/experimental/agent-team/tests/team.spec.ts @@ -15,7 +15,7 @@ import * as SubagentSpawn from '@deepseek-ai/dsh-subagent-spawn-in-process' import { MockAdapter, textResponse } from '../../../core/agent-loop/tests/mock-adapter.ts' import { mountWorkingDirectoryFixture } from '../../../subagent/subagent/tests/working-directory-fixture.ts' import TeamService, { TeamError, TeamId, TeamTaskId } from '../src/index.ts' -import { resolveMember } from '../src/membership.ts' +import { TeamMembers } from '../src/membership.ts' import { emptyTeamState, teamProjectionDefinition } from '../src/projection.ts' import type { TeamProjectionState } from '../src/projection.ts' import { TestSessionQuery } from './test-session-query.ts' @@ -176,7 +176,8 @@ describe('Team identity and membership', () => { }) it('resolves task assignees only by id, including historical members', async () => { - const { lead } = await setup([]) + const { ctx, lead } = await setup([]) + const members = new TeamMembers(ctx) const state = { ...emptyTeamState(lead.id, SessionLogOffset(0)), children: [{ id: SessionId('named-child'), description: 'reviewer' }], @@ -186,13 +187,75 @@ describe('Team identity and membership', () => { ], } for (const id of [lead.id, SessionId('named-child'), SessionId('old-child')]) { - expect(resolveMember(lead, state, id)).toBe(id) + await expect(members.resolveMember(lead, state, id)).resolves.toBe(id) } for (const alias of ['lead', 'reviewer', 'legacy', 'broken', 'failed-child']) { - expect(() => resolveMember(lead, state, SessionId(alias))).toThrow(expect.objectContaining({ code: 'TEAM_MEMBER_NOT_FOUND' })) + await expect(members.resolveMember(lead, state, SessionId(alias))).rejects.toMatchObject({ code: 'TEAM_MEMBER_NOT_FOUND' }) } }) + it('assigns tasks to live and inactive deep descendants without admitting ordinary forks or another Team', async () => { + const { ctx, lead } = await setup(['hang', 'hang']) + const parent = await waitRunning(ctx, await spawn(ctx, lead, 'same description')) + const childId = (await ctx.subagents.startActivation({ + provider: 'spawn', label: 'same description', delivery: 'caller', signal: SIGNAL, + request: { parent, prompt: content('nested work') }, + })).childId + const child = await waitRunning(ctx, childId) + let task = await ctx.agentTeams.createTask(lead, { subject: 'nested work', description: 'shared board' }) + const assign = (owner: SessionId) => ctx.agentTeams.updateTask(lead, { + taskId: task.id, expectedRevision: task.revision, action: 'reassign', owner, + }) + task = await assign(child.id) + expect(task.ownerId).toBe(child.id) + expect(ctx.agentTeams.getTask(child, task.id)).toEqual(task) + + const fork = await ctx.agents.create({ + sessionId: SessionId('ordinary-descendant-fork'), seed: child.session.snapshotEvents(), + inheritedEventCount: SessionLogOffset(child.session.seq), + meta: { parentSession: child.id, isSeeded: true }, + agentOptions: { provider: 'mock', model: 'mock' }, + }) + await expect(assign(fork.agent.id)).rejects.toMatchObject({ code: 'TEAM_MEMBER_NOT_FOUND' }) + await fork.dispose() + const other = await ctx.agents.create({ sessionId: SessionId('other-team-root'), agentOptions: { provider: 'mock', model: 'mock' } }) + const unrelated = await waitRunning(ctx, await spawn(ctx, other.agent, 'same description')) + await expect(assign(unrelated.id)).rejects.toMatchObject({ code: 'TEAM_MEMBER_NOT_FOUND' }) + + ctx.subagents.interrupt(child.id, { kind: 'ancestor', agent: lead }) + await waitNoAgent(ctx, child.id) + task = await assign(child.id) + expect(task.ownerId).toBe(child.id) + ctx.subagents.interrupt(parent.id, { kind: 'ancestor', agent: lead }) + await waitNoAgent(ctx, parent.id) + task = await assign(child.id) + expect(task.ownerId).toBe(child.id) + ctx.subagents.interrupt(unrelated.id, { kind: 'ancestor', agent: other.agent }) + await waitNoAgent(ctx, unrelated.id) + await other.dispose() + }) + + it('rejects forged and cyclic persisted descendant chains and preserves read failures', async () => { + const { ctx, lead } = await setup([]) + const members = new TeamMembers(ctx) + const state = durable(lead) + const aId = SessionId('cycle-a') + const bId = SessionId('cycle-b') + const a = ctx.sessions.create(aId, { meta: { parentSession: bId, origin: 'subagent' } }) + const b = ctx.sessions.create(bId, { meta: { parentSession: aId, origin: 'subagent' } }) + for (const child of [a, b]) { + child.append('subagent/descriptor', { version: 3, mode: 'continuable', provider: 'spawn', label: 'review' }) + } + await expect(members.resolveMember(lead, state, aId)).rejects.toMatchObject({ code: 'TEAM_MEMBER_NOT_FOUND' }) + a.append('subagent/catalog', { version: 0, childId: bId, childCreatedAt: 0, mode: 'continuable', label: 'review' }) + b.append('subagent/catalog', { version: 0, childId: aId, childCreatedAt: 0, mode: 'continuable', label: 'review' }) + await expect(members.resolveMember(lead, state, aId)).rejects.toMatchObject({ code: 'TEAM_MEMBER_NOT_FOUND' }) + const readFailure = new Error('persistence unavailable') + const observe = vi.spyOn(ctx.sessionQuery, 'observeSession').mockRejectedValueOnce(readFailure) + await expect(members.resolveMember(lead, state, aId)).rejects.toBe(readFailure) + observe.mockRestore() + }) + it('constructs with the default task limit and serializes concurrent task commits', async () => { const { ctx, lead, teamFiber } = await setup([]) await teamFiber.dispose() @@ -574,6 +637,7 @@ describe('Team waiting', () => { const storageRoot = mkdtempSync(join(tmpdir(), 'dsh-team-wait-')) roots.push(storageRoot) await ctx.plugin(JsonlSessionPersistence, { root: storageRoot }) + await ctx.plugin(TestSessionQuery) await ctx.plugin(AgentLoop, { agents: [] }) await ctx.plugin(SubagentService) const fiber = await ctx.plugin(TeamService) diff --git a/packages/experimental/agent-team/tests/test-session-query.ts b/packages/experimental/agent-team/tests/test-session-query.ts index 233c493ad2..616d93ff85 100644 --- a/packages/experimental/agent-team/tests/test-session-query.ts +++ b/packages/experimental/agent-team/tests/test-session-query.ts @@ -1,57 +1,11 @@ -/** Minimal concrete Session query for Agent Team continuation tests. */ +/** Session query using production observations with search outside these tests. */ -import { SessionLogOffset } from '@deepseek-ai/dsh-session' -import type { SessionEvent, SessionHeader, SessionId } from '@deepseek-ai/dsh-session' import SessionQueryEngine from '@deepseek-ai/dsh-session-query' -import type { SessionObservation, SessionObservationOptions } from '@deepseek-ai/dsh-session-query' - -/** Undisposable immutable cut over one session's header and events. */ -function cut( - source: 'live' | 'prepared', - header: SessionHeader, - events: readonly SessionEvent[], -): SessionObservation { - const lease = (): SessionObservation => ({ - source, - header, - inheritedEventCount: SessionLogOffset(0), - events, - cursor: events.at(-1)?.seq ?? -1, - retain: lease, - [Symbol.dispose]: () => {}, - }) - return lease() -} /** Session query implementation whose search faces are outside these tests. */ export class TestSessionQuery extends SessionQueryEngine { static override inject = ['sessions', 'sessionPersistence'] - /** Live-preferred observation backed directly by a short-lived persistence read handle. */ - override async observeSession( - sessionId: SessionId, - options: SessionObservationOptions = {}, - ): Promise { - const live = this.ctx.sessions.get(sessionId) - if (live !== undefined) return cut('live', live.header, live.snapshotEvents()) - const handle = await this.ctx.sessionPersistence.open( - sessionId, - 'read', - options.signal === undefined ? {} : { signal: options.signal }, - ) - try { - return cut( - 'prepared', - handle.header, - (await handle.read( - 0, undefined, options.signal === undefined ? {} : { signal: options.signal }, - )).events, - ) - } finally { - await handle.close() - } - } - override searchSessions(): Promise { return Promise.reject(new Error('session search is not configured in this test')) } diff --git a/packages/experimental/agent-team/tsconfig.json b/packages/experimental/agent-team/tsconfig.json index b0562ab6c2..8e8bd64202 100644 --- a/packages/experimental/agent-team/tsconfig.json +++ b/packages/experimental/agent-team/tsconfig.json @@ -14,6 +14,7 @@ { "path": "../../core/session" }, { "path": "../../core/agent" }, { "path": "../../subagent/subagent" }, - { "path": "../../session/session-projection" } + { "path": "../../session/session-projection" }, + { "path": "../../session-query/session-query" } ] } diff --git a/packages/experimental/client-ui-agent-team/README.i18n.yaml b/packages/experimental/client-ui-agent-team/README.i18n.yaml index 9db36471d1..aa8cd4c854 100644 --- a/packages/experimental/client-ui-agent-team/README.i18n.yaml +++ b/packages/experimental/client-ui-agent-team/README.i18n.yaml @@ -18,14 +18,14 @@ en: ba021754d3ae6d9e zh: 18017b40f13e6ffd /deepseek-ai-dsh-experimental-client-ui-agent-team/use-this-package/inspect-and-navigate-the-roster: - en: d7c86840f03912b3 - zh: c6aa34d5c7550dd2 + en: f81328cbe327b88e + zh: 6f5d01325ad910a4 /deepseek-ai-dsh-experimental-client-ui-agent-team/use-this-package/inspect-the-task-board: en: 5c0ec10800cc9fda zh: b80f1e725dbb894a /deepseek-ai-dsh-experimental-client-ui-agent-team/understand-the-implementation: - en: 0bdb38c8f75101b1 - zh: fa31d7a4b1fff12d + en: 5d694551891671ce + zh: 4bdab2236f41df43 /deepseek-ai-dsh-experimental-client-ui-agent-team/further-exploration: en: 71ac041029c64d5a zh: fef2e4c5dccb8d1b diff --git a/packages/experimental/client-ui-agent-team/README.md b/packages/experimental/client-ui-agent-team/README.md index 18e163cbc6..163485f1b6 100644 --- a/packages/experimental/client-ui-agent-team/README.md +++ b/packages/experimental/client-ui-agent-team/README.md @@ -29,9 +29,9 @@ Enable this package through [`@deepseek-ai/dsh-experimental-agent-team-profile`] ### Inspect and navigate the roster -The panel shows the Lead Session's roster and task board from the shared Session store. Task and roster updates appear while the panel stays open. Opening the panel performs no projection requests. The panel shows a loading notice while the conversation or Session list is loading, and an unavailable notice when no Team value is present afterward. +The panel combines the Lead's roster with every discovered continuable descendant and shows the Lead's shared task board. It reads each member's `agentTeam` projection from the shared Session store. Task and roster updates appear while the panel stays open. Opening the panel performs no projection requests. The panel shows a loading notice while the conversation or Session list is loading, and an unavailable notice when no Team value is present afterward. -Roster rows show descriptions and durable phases. Provisioning and running members use the shared ongoing loader, inactive members use a person icon, and failed members use error. Live Session status supplies running activity; the shared `modelSelection` projection supplies a model when available. The current conversation carries a Current chat tag and cannot be selected. Selecting the Lead from a teammate conversation opens the Lead Session directly. Selecting an active teammate opens its ordinary continuable child address. The Host validates the parent, child, and mode when history opens; later human prompts use the same addressed-subagent conversation. +Roster rows show descriptions and durable phases. Provisioning and running members use the shared ongoing loader, inactive members use a person icon, and failed members use error. Live Session status supplies running activity; the shared `modelSelection` projection supplies a model when available. The current conversation carries a Current chat tag and cannot be selected. Selecting the Lead from a teammate conversation opens the Lead Session directly. Selecting an active teammate opens its cataloged address through that member’s direct parent, including when the selected member is several levels below the Lead. The Host validates the parent, child, and mode when history opens; later human prompts use the same addressed-subagent conversation. ### Inspect the task board @@ -49,7 +49,7 @@ Member rows show descriptions, which may repeat; the Lead label is localized. Th The Client export registers its locale dictionaries and one conversation-header slot through Cordis effects; it mounts no Remote namespace. Disposing the plugin fiber removes both registrations. -The panel renders outside the conversation container and stays within the viewport. Member cards use the shared elevation stroke for their outlines in resting, selected, and hover states. Hovering the trigger opens the panel after 150ms; leaving both trigger and panel closes it after a 120ms grace period. Clicking the trigger pins the panel and moves focus into it. Outside clicks and Escape dismiss the panel; Escape returns focus to the trigger only when focus was inside the panel. In a narrow header, the trigger becomes an icon and opens only on click. The component derives every row from the `useSessions`, `useSessionStatus`, and `useSession` seats: the Lead id follows the current subagent address and Session list ancestry to the ordinary root; incomplete ancestry leaves the Team unavailable, the Team view from `projectionsBySession[lead].values.agentTeam`, member activity from Session status with the list summary as fallback, and the model from `projectionsBySession[member].values.modelSelection.next`. Each roster row selects its own running state. The only injected callback opens a roster Session using the current and target Session ids. Switching conversations closes the panel and clears a navigation failure. +The panel renders outside the conversation container and stays within the viewport. Member cards use the shared elevation stroke for their outlines in resting, selected, and hover states. Hovering the trigger opens the panel after 150ms; leaving both trigger and panel closes it after a 120ms grace period. Clicking the trigger pins the panel and moves focus into it. Outside clicks and Escape dismiss the panel; Escape returns focus to the trigger only when focus was inside the panel. In a narrow header, the trigger becomes an icon and opens only on click. The component derives every row from the `useSessions`, `useSessionStatus`, and `useSession` seats: the Lead id follows the current subagent address and Session list ancestry to the ordinary root; incomplete ancestry leaves the Team unavailable, the task board from `projectionsBySession[lead].values.agentTeam` and the roster from recursive member projections, member activity from Session status with the list summary as fallback, and the model from `projectionsBySession[member].values.modelSelection.next`. Each roster row selects its own running state. The only injected callback opens a roster Session using the current and target Session ids. Switching conversations closes the panel and clears a navigation failure. | File | Role | |---|---| diff --git a/packages/experimental/client-ui-agent-team/README.zh.md b/packages/experimental/client-ui-agent-team/README.zh.md index e251b1e8e8..dbe7bf03a2 100644 --- a/packages/experimental/client-ui-agent-team/README.zh.md +++ b/packages/experimental/client-ui-agent-team/README.zh.md @@ -29,9 +29,9 @@ kind: "package-reference" ### 检查并导航 roster -面板从共享 Session store 展示 Lead Session 的 roster 与任务板。面板保持打开时,任务和成员更新会直接出现。打开面板不发起投影请求。会话或 Session 列表正在加载时,面板显示加载提示;加载结束后仍无 Team 值时,显示不可用提示。 +面板汇总 Lead 与所有已发现 continuable 后代的成员列表,并展示 Lead 的共享任务板。各成员的 `agentTeam` 投影来自共享 Session store。面板保持打开时,任务和成员更新会直接出现。打开面板不发起投影请求。会话或 Session 列表正在加载时,面板显示加载提示;加载结束后仍无 Team 值时,显示不可用提示。 -Roster 行展示描述与持久阶段。provisioning 和 running 成员使用共享 ongoing loading,inactive 成员使用人物图标,failed 成员使用 error 红点。实时 Session 状态提供运行活动;共享 `modelSelection` 投影在可用时提供模型。当前会话带有“当前会话”标签且不可选择。在 teammate 会话中选择 Lead 会直接打开 Lead Session。选择 active teammate 会打开其普通 continuable 子会话地址。Host 在打开历史时校验 parent、child 与 mode;后续人类提示词使用同一 addressed-subagent 会话。 +Roster 行展示描述与持久阶段。provisioning 和 running 成员使用共享 ongoing loading,inactive 成员使用人物图标,failed 成员使用 error 红点。实时 Session 状态提供运行活动;共享 `modelSelection` 投影在可用时提供模型。当前会话带有“当前会话”标签且不可选择。在 teammate 会话中选择 Lead 会直接打开 Lead Session。选择 active teammate 会通过该成员的直接父代理打开其 catalog 地址,包括位于 Lead 多层之下的成员。Host 在打开历史时校验 parent、child 与 mode;后续人类提示词使用同一 addressed-subagent 会话。 ### 查看任务板 @@ -49,7 +49,7 @@ Roster 行展示描述与持久阶段。provisioning 和 running 成员使用共 Client export 通过 Cordis effect 注册 locale dictionary 与一个 conversation-header slot;它不挂载任何 Remote namespace。Dispose plugin fiber 会移除这两项 registration。 -面板渲染在会话容器外,并保持在视口范围内。成员卡片在静止、选中和悬停状态下均使用共享 elevation 描边绘制轮廓。悬停触发按钮 150ms 后打开面板;指针离开触发按钮和面板后,经过 120ms 宽限关闭。点击触发按钮会固定面板并将焦点移入其中。点击外部或按 Escape 可关闭面板;仅当焦点原本位于面板内时,Escape 才将焦点返回触发按钮。页头较窄时触发按钮折叠为图标,只响应点击打开。组件从 `useSessions`、`useSessionStatus` 与 `useSession` 座位派生每一行:Lead id 从当前 subagent address 沿 Session 列表祖先查找到普通根;祖先信息不完整时 Team 暂不可用,Team 视图来自 `projectionsBySession[lead].values.agentTeam`,成员活动来自 Session 状态并以列表摘要为后备,model 来自 `projectionsBySession[member].values.modelSelection.next`。每个 roster 行只选择自己的运行状态。唯一的注入回调通过当前与目标 Session 的 id 打开 roster Session。切换会话会关闭面板并清除导航失败。 +面板渲染在会话容器外,并保持在视口范围内。成员卡片在静止、选中和悬停状态下均使用共享 elevation 描边绘制轮廓。悬停触发按钮 150ms 后打开面板;指针离开触发按钮和面板后,经过 120ms 宽限关闭。点击触发按钮会固定面板并将焦点移入其中。点击外部或按 Escape 可关闭面板;仅当焦点原本位于面板内时,Escape 才将焦点返回触发按钮。页头较窄时触发按钮折叠为图标,只响应点击打开。组件从 `useSessions`、`useSessionStatus` 与 `useSession` 座位派生每一行:Lead id 从当前 subagent address 沿 Session 列表祖先查找到普通根;祖先信息不完整时 Team 暂不可用,任务板来自 `projectionsBySession[lead].values.agentTeam`,成员列表递归汇总各成员的投影,成员活动来自 Session 状态并以列表摘要为后备,model 来自 `projectionsBySession[member].values.modelSelection.next`。每个 roster 行只选择自己的运行状态。唯一的注入回调通过当前与目标 Session 的 id 打开 roster Session。切换会话会关闭面板并清除导航失败。 | 文件 | 职责 | |---|---| diff --git a/packages/experimental/client-ui-agent-team/src/client/TeamAction.tsx b/packages/experimental/client-ui-agent-team/src/client/TeamAction.tsx index 3716e9d23c..b6ad62aff6 100644 --- a/packages/experimental/client-ui-agent-team/src/client/TeamAction.tsx +++ b/packages/experimental/client-ui-agent-team/src/client/TeamAction.tsx @@ -17,6 +17,7 @@ import type {} from '@deepseek-ai/dsh-client-ui-conversation/client' import { NS, type TeamKey } from './locales.ts' import css from './TeamAction.module.css' import { teamRootId } from './team-root.ts' +import { sameTeamView, teamView } from './team-view.ts' /** Business actions injected by the browser plugin. */ export interface TeamActionInjected { @@ -193,8 +194,8 @@ export function TeamAction({ const parentId = useSession(snapshot => snapshot.subagent?.address.parentSessionId) const team = useSessions((state) => { const rootId = teamRootId(sessionId, parentId, state.byId) - return rootId === undefined ? undefined : state.projectionsBySession[rootId]?.values.agentTeam - }) + return teamView(state, rootId) + }, sameTeamView) const opening = useSession(snapshot => snapshot.openState === 'loading') const listing = useSessions(state => state.phase === 'pending') const hoverTimer = useRef | undefined>(undefined) diff --git a/packages/experimental/client-ui-agent-team/src/client/mount.ts b/packages/experimental/client-ui-agent-team/src/client/mount.ts index 2ee31d6084..42cf53392e 100644 --- a/packages/experimental/client-ui-agent-team/src/client/mount.ts +++ b/packages/experimental/client-ui-agent-team/src/client/mount.ts @@ -44,11 +44,9 @@ export function registerAgentTeamUi(ctx: ClientContext): void { ctx.uiWorkspace.openSession(parentSessionId) return } - ctx.uiWorkspace.openSession({ - parentSessionId, - childSessionId, - mode: 'continuable', - }) + const address = sessions.subagentAddress(childSessionId) + if (address === undefined) throw new Error(ctx.locale.bind(NS)('unavailable')) + ctx.uiWorkspace.openSession(address) }, } diff --git a/packages/experimental/client-ui-agent-team/src/client/team-view.ts b/packages/experimental/client-ui-agent-team/src/client/team-view.ts new file mode 100644 index 0000000000..ce30dcbc62 --- /dev/null +++ b/packages/experimental/client-ui-agent-team/src/client/team-view.ts @@ -0,0 +1,45 @@ +/** Team display derived from the shared Session catalog and per-Session projections. */ + +import type { SessionListState } from '@deepseek-ai/dsh-api-session-controller/client' +import type { TeamProjection } from '@deepseek-ai/dsh-experimental-agent-team/client' +import type { SessionId } from '@deepseek-ai/dsh-session/types' + +/** + * Collect every discovered continuable descendant and the Lead's shared board. + * @param state - current catalog and Host-computed projections. + * @param leadSessionId - Team root resolved from the selected conversation. + * @returns the combined view, or undefined until the Lead projection arrives. + */ +export function teamView(state: SessionListState, leadSessionId: SessionId | undefined): TeamProjection | undefined { + if (leadSessionId === undefined) return undefined + const root = state.projectionsBySession[leadSessionId]?.values.agentTeam + if (root === undefined) return undefined + const members = [...root.members] + const seen = new Set(members.map(member => member.id)) + let failure = root.failure + for (const member of members) { + if (member.id === leadSessionId || member.phase !== 'active') continue + const child = state.projectionsBySession[member.id]?.values.agentTeam + if (child === undefined) continue + failure ??= child.failure + for (const descendant of child.members) { + if (descendant.role === 'lead' || seen.has(descendant.id)) continue + seen.add(descendant.id) + members.push(descendant) + } + } + return { ...root, members, ...failure === undefined ? {} : { failure } } +} + +/** + * Compare the immutable Team facts a panel displays, excluding other Sessions. + * @param left - previous combined view. + * @param right - newly selected view. + * @returns whether React can retain the previous selection. + */ +export function sameTeamView(left: TeamProjection | undefined, right: TeamProjection | undefined): boolean { + return left === right || (left !== undefined && right !== undefined + && left.failure === right.failure && left.tasks === right.tasks + && left.members.length === right.members.length + && left.members.every((member, index) => member === right.members[index])) +} diff --git a/packages/experimental/client-ui-agent-team/tests/browser-plugin.client.spec.ts b/packages/experimental/client-ui-agent-team/tests/browser-plugin.client.spec.ts index 9ff068b0c6..6ec7cc4cb0 100644 --- a/packages/experimental/client-ui-agent-team/tests/browser-plugin.client.spec.ts +++ b/packages/experimental/client-ui-agent-team/tests/browser-plugin.client.spec.ts @@ -31,6 +31,9 @@ async function bench(options: { addressed?: boolean; nested?: boolean; missingPa }, }) } } : undefined, + subagentAddress: (id: SessionId) => id === CHILD || id === NESTED + ? { parentSessionId: id === NESTED ? CHILD : SESSION, childSessionId: id, mode: 'continuable' as const } + : undefined, refreshProjections: (id: SessionId) => { navigation.push(['refresh', id]) return Promise.resolve() @@ -134,6 +137,22 @@ describe('ui-team browser plugin', () => { expect(b.navigation).toEqual([['open', SESSION]]) }) + it('opens a deep member through its direct parent and returns to the Team Lead', async () => { + const b = await bench({ nested: true }) + b.actions().openTeammate(NESTED, NESTED) + b.actions().openTeammate(NESTED, SESSION) + expect(b.navigation).toEqual([ + ['open', { parentSessionId: CHILD, childSessionId: NESTED, mode: 'continuable' }], + ['open', SESSION], + ]) + }) + + it('refuses to invent a parent address for an undiscovered member', async () => { + const b = await bench() + expect(() => { b.actions().openTeammate(SESSION, 'missing' as SessionId) }).toThrow() + expect(b.navigation).toEqual([]) + }) + it('does not open a teammate from a conversation outside the main view', async () => { const b = await bench() b.select('other-session' as SessionId) diff --git a/packages/experimental/client-ui-agent-team/tests/team-action.client.spec.tsx b/packages/experimental/client-ui-agent-team/tests/team-action.client.spec.tsx index 3736b48730..df1ce5616e 100644 --- a/packages/experimental/client-ui-agent-team/tests/team-action.client.spec.tsx +++ b/packages/experimental/client-ui-agent-team/tests/team-action.client.spec.tsx @@ -174,6 +174,45 @@ describe('TeamAction', () => { expect(screen.getByRole('button', { name: /^worker.*运行中/u })).toBeTruthy() }) + it('uses the member id when a historical row has no description', () => { + const { description: _description, ...withoutDescription } = worker + render() + openPanel() + expect(screen.getByRole('button', { name: /^worker-id/u })).toBeTruthy() + }) + + it('shares the root board and descendant roster from a grandchild conversation', () => { + const nestedId = 'nested-id' as SessionId + const nested = { ...worker, id: nestedId, description: 'nested review' } + const b = bench({ sessionId: nestedId, parentSessionId: WORKER }) + b.sessions.set({ ...b.sessions.getSnapshot(), + byId: { ...b.sessions.getSnapshot().byId, [WORKER]: { ...summary(WORKER, false), parentId: SESSION, origin: 'subagent' } }, + projectionsBySession: { + ...b.sessions.getSnapshot().projectionsBySession, + [WORKER]: { state: 'ready', error: null, values: { + agentTeam: { members: [{ ...worker, role: 'lead' }, nested], tasks: [] }, + } }, + } }) + render() + openPanel() + expect(screen.getByText(task.subject)).toBeTruthy() + expect(screen.getByRole('heading', { name: '成员3' })).toBeTruthy() + expect(screen.getByRole('button', { name: /^nested review/u }).disabled).toBe(true) + fireEvent.click(screen.getByRole('button', { name: new RegExp(`^${zh.lead}`, 'u') })) + expect(b.injected.openTeammate).toHaveBeenCalledWith(nestedId, SESSION) + act(() => { + b.sessions.set({ ...b.sessions.getSnapshot(), projectionsBySession: { + ...b.sessions.getSnapshot().projectionsBySession, + [SESSION]: { state: 'ready', error: null, values: { + agentTeam: { ...team, tasks: [{ ...task, subject: 'Updated root task' }] }, + } }, + } }) + }) + expect(screen.getByText('Updated root task')).toBeTruthy() + }) + it('reads the Lead projection from an addressed teammate conversation', () => { const b = bench({ sessionId: WORKER, parentSessionId: SESSION }) render() diff --git a/packages/experimental/client-ui-agent-team/tests/team-view.client.spec.ts b/packages/experimental/client-ui-agent-team/tests/team-view.client.spec.ts new file mode 100644 index 0000000000..5fd79a294c --- /dev/null +++ b/packages/experimental/client-ui-agent-team/tests/team-view.client.spec.ts @@ -0,0 +1,59 @@ +import { describe, expect, it } from 'vitest' +import type { SessionListState } from '@deepseek-ai/dsh-api-session-controller/client' +import type { TeamMemberProjection, TeamProjection } from '@deepseek-ai/dsh-experimental-agent-team/client' +import { SessionId } from '@deepseek-ai/dsh-session/types' +import { sameTeamView, teamView } from '../src/client/team-view.ts' + +const ROOT = SessionId('root') +const CHILD = SessionId('child') +const GRANDCHILD = SessionId('grandchild') +const row = (id: SessionId): TeamMemberProjection => ({ id, description: 'review', role: 'teammate', phase: 'active' }) + +function state(views: Record): SessionListState { + return { + ids: [], byId: {}, phase: 'ready', + projectionsBySession: Object.fromEntries(Object.entries(views).map(([id, agentTeam]) => [ + id, { state: 'ready' as const, error: null, values: { agentTeam } }, + ])), + } +} + +describe('Team display across Session projections', () => { + it('keeps repeated descriptions, deduplicates ids, and takes tasks only from the Lead', () => { + const root: TeamProjection = { members: [{ ...row(ROOT), role: 'lead' }, row(CHILD)], tasks: [] } + const child: TeamProjection = { members: [{ ...row(CHILD), role: 'lead' }, row(GRANDCHILD)], tasks: [] } + const cycle: TeamProjection = { members: [{ ...row(GRANDCHILD), role: 'lead' }, row(ROOT), row(CHILD)], tasks: [] } + const combined = teamView(state({ [ROOT]: root, [CHILD]: child, [GRANDCHILD]: cycle }), ROOT)! + expect(combined.members.map(member => member.id)).toEqual([ROOT, CHILD, GRANDCHILD]) + expect(combined.tasks).toBe(root.tasks) + }) + + it('retains known members when a descendant projection has not arrived', () => { + const root: TeamProjection = { members: [row(CHILD)], tasks: [] } + const catalog = state({ [ROOT]: root }) + expect(teamView(catalog, undefined)).toBeUndefined() + expect(teamView(catalog, CHILD)).toBeUndefined() + expect(teamView(catalog, ROOT)?.members).toEqual(root.members) + }) + + it('surfaces descendant replay failures and does not traverse failed roster entries', () => { + const root: TeamProjection = { members: [row(CHILD)], tasks: [] } + const child: TeamProjection = { members: [row(GRANDCHILD)], tasks: [], failure: 'invalid child log' } + const catalog = state({ [ROOT]: root, [CHILD]: child }) + expect(teamView(catalog, ROOT)?.failure).toBe('invalid child log') + const failed = { ...root, members: [{ ...row(CHILD), phase: 'failed' as const }], failure: 'invalid root log' } + expect(teamView(state({ [ROOT]: failed, [CHILD]: child }), ROOT)).toEqual(failed) + }) + + it('ignores unrelated updates while detecting every displayed Team change', () => { + const root: TeamProjection = { members: [row(CHILD)], tasks: [] } + expect(sameTeamView(undefined, undefined)).toBe(true) + expect(sameTeamView(undefined, root)).toBe(false) + expect(sameTeamView(root, undefined)).toBe(false) + expect(sameTeamView(root, { ...root, members: [...root.members] })).toBe(true) + expect(sameTeamView(root, { ...root, tasks: [] })).toBe(false) + expect(sameTeamView(root, { ...root, failure: 'failed' })).toBe(false) + expect(sameTeamView(root, { ...root, members: [] })).toBe(false) + expect(sameTeamView(root, { ...root, members: [row(GRANDCHILD)] })).toBe(false) + }) +}) diff --git a/packages/experimental/tool-agent-team/README.md b/packages/experimental/tool-agent-team/README.md index 60b1f9aceb..4ea592f06f 100644 --- a/packages/experimental/tool-agent-team/README.md +++ b/packages/experimental/tool-agent-team/README.md @@ -128,7 +128,7 @@ The Team Lead and all teammates share the same working directory and filesystem. Prefer read/edit/write for file changes. If a file operation returns FS_STALE_VERSION, read the current file, rebase your intended change onto the new content, and retry. Bash, formatters, code generators, and scripts are not fully protected by the filesystem version guard; coordinate them explicitly and have the Lead review the final diff and run tests. -Use agent ids as task owners. The Lead can reassign to itself, its direct continuable children, or historical members; other descendants claim tasks themselves. list_agents shows direct contacts by default; descendants scope discovers deeper agents without granting message or assignment authority. inactive means no turn is executing; it does not describe task completion, success, failure, or waiting for other agents. A successful send does not mean the recipient has processed it. Shared-task workflow is list, get, claim with the current revision, perform the work, then complete. Task readiness never starts an owner. Before wait_agent, make sure another required member is running; use send_message first for an inactive direct contact, or coordinate through its parent for a deeper member. wait_agent observes only changes after that call starts, never wakes a member, and returns noProgress immediately when no other member is running. Re-list after wakeup or timeout. The Lead must wait for required teammates before giving the final answer. +Use agent ids as task owners. The Lead can reassign to itself, continuable descendants at any depth, or active historical members. list_agents shows direct contacts by default; descendants scope discovers deeper agents for task assignment but does not grant direct messaging authority. inactive means no turn is executing; it does not describe task completion, success, failure, or waiting for other agents. A successful send does not mean the recipient has processed it. Shared-task workflow is list, get, claim with the current revision, perform the work, then complete. Task readiness never starts an owner. Before wait_agent, make sure another required member is running; use send_message first for an inactive direct contact, or coordinate through its parent for a deeper member. wait_agent observes only changes after that call starts, never wakes a member, and returns noProgress immediately when no other member is running. Re-list after wakeup or timeout. The Lead must wait for required teammates before giving the final answer. ``` #### Token effect diff --git a/packages/experimental/tool-agent-team/README.zh.md b/packages/experimental/tool-agent-team/README.zh.md index 1554bd9639..246642c913 100644 --- a/packages/experimental/tool-agent-team/README.zh.md +++ b/packages/experimental/tool-agent-team/README.zh.md @@ -128,7 +128,7 @@ The Team Lead and all teammates share the same working directory and filesystem. Prefer read/edit/write for file changes. If a file operation returns FS_STALE_VERSION, read the current file, rebase your intended change onto the new content, and retry. Bash, formatters, code generators, and scripts are not fully protected by the filesystem version guard; coordinate them explicitly and have the Lead review the final diff and run tests. -Use agent ids as task owners. The Lead can reassign to itself, its direct continuable children, or historical members; other descendants claim tasks themselves. list_agents shows direct contacts by default; descendants scope discovers deeper agents without granting message or assignment authority. inactive means no turn is executing; it does not describe task completion, success, failure, or waiting for other agents. A successful send does not mean the recipient has processed it. Shared-task workflow is list, get, claim with the current revision, perform the work, then complete. Task readiness never starts an owner. Before wait_agent, make sure another required member is running; use send_message first for an inactive direct contact, or coordinate through its parent for a deeper member. wait_agent observes only changes after that call starts, never wakes a member, and returns noProgress immediately when no other member is running. Re-list after wakeup or timeout. The Lead must wait for required teammates before giving the final answer. +Use agent ids as task owners. The Lead can reassign to itself, continuable descendants at any depth, or active historical members. list_agents shows direct contacts by default; descendants scope discovers deeper agents for task assignment but does not grant direct messaging authority. inactive means no turn is executing; it does not describe task completion, success, failure, or waiting for other agents. A successful send does not mean the recipient has processed it. Shared-task workflow is list, get, claim with the current revision, perform the work, then complete. Task readiness never starts an owner. Before wait_agent, make sure another required member is running; use send_message first for an inactive direct contact, or coordinate through its parent for a deeper member. wait_agent observes only changes after that call starts, never wakes a member, and returns noProgress immediately when no other member is running. Re-list after wakeup or timeout. The Lead must wait for required teammates before giving the final answer. ``` #### Token 影响 diff --git a/packages/experimental/tool-agent-team/src/index.ts b/packages/experimental/tool-agent-team/src/index.ts index 74b153e147..f98d5f08a2 100644 --- a/packages/experimental/tool-agent-team/src/index.ts +++ b/packages/experimental/tool-agent-team/src/index.ts @@ -29,7 +29,7 @@ The Team Lead and all teammates share the same working directory and filesystem. Prefer read/edit/write for file changes. If a file operation returns FS_STALE_VERSION, read the current file, rebase your intended change onto the new content, and retry. Bash, formatters, code generators, and scripts are not fully protected by the filesystem version guard; coordinate them explicitly and have the Lead review the final diff and run tests. -Use agent ids as task owners. The Lead can reassign to itself, its direct continuable children, or historical members; other descendants claim tasks themselves. list_agents shows direct contacts by default; descendants scope discovers deeper agents without granting message or assignment authority. inactive means no turn is executing; it does not describe task completion, success, failure, or waiting for other agents. A successful send does not mean the recipient has processed it. Shared-task workflow is list, get, claim with the current revision, perform the work, then complete. Task readiness never starts an owner. Before wait_agent, make sure another required member is running; use send_message first for an inactive direct contact, or coordinate through its parent for a deeper member. wait_agent observes only changes after that call starts, never wakes a member, and returns noProgress immediately when no other member is running. Re-list after wakeup or timeout. The Lead must wait for required teammates before giving the final answer.` +Use agent ids as task owners. The Lead can reassign to itself, continuable descendants at any depth, or active historical members. list_agents shows direct contacts by default; descendants scope discovers deeper agents for task assignment but does not grant direct messaging authority. inactive means no turn is executing; it does not describe task completion, success, failure, or waiting for other agents. A successful send does not mean the recipient has processed it. Shared-task workflow is list, get, claim with the current revision, perform the work, then complete. Task readiness never starts an owner. Before wait_agent, make sure another required member is running; use send_message first for an inactive direct contact, or coordinate through its parent for a deeper member. wait_agent observes only changes after that call starts, never wakes a member, and returns noProgress immediately when no other member is running. Re-list after wakeup or timeout. The Lead must wait for required teammates before giving the final answer.` const NO_ACTIVE_PEER_MESSAGE = 'No other Team member is running. wait_agent cannot make progress or wake inactive teammates. Re-list with list_agents and team_task_list, then use send_message to wake a required inactive direct contact before waiting again; coordinate deeper members through their parent.' @@ -245,7 +245,7 @@ function install(agent: Agent, ctx: Context): () => void { description: { type: 'string', description: 'Replacement details for edit.' }, blocked_by: { type: 'array', items: { type: 'string' }, description: 'Complete blocker list for set_dependencies.' }, write_scopes: { type: 'array', items: { type: 'string' }, description: 'Replacement advisory write scopes for edit.' }, - owner: { type: 'string', description: 'Agent id of the Lead or one of its direct continuable children for Lead-only reassign; omit to unassign.' }, + owner: { type: 'string', description: 'Agent id of the Lead or a continuable descendant for Lead-only reassign; omit to unassign.' }, }, output: jsonOutput(TASK_VIEW_SCHEMA), async execute(args, exec) { diff --git a/snapshots/session/team-descendant-task/session.1.v4.jsonl b/snapshots/session/team-descendant-task/session.1.v4.jsonl new file mode 100644 index 0000000000..25b7e30135 --- /dev/null +++ b/snapshots/session/team-descendant-task/session.1.v4.jsonl @@ -0,0 +1,28 @@ +{"type":"session","version":4,"id":"{{session:2}}","createdAt":1783951000000,"cwd":"{{cwd}}","parentSession":"{{session:1}}","isSeeded":false,"origin":"subagent","delegationDepth":1} +{"type":"subagent/descriptor","data":{"version":3,"mode":"continuable","provider":"spawn","label":"branch child 1","agentProvider":"deepseek-official","agentModel":"deepseek-v4-flash"}} +{"type":"sandbox/mode","data":{"mode":"danger-full-access","source":"delegation"}} +{"type":"approval/policy","data":{"policy":"never","source":"delegation"}} +{"type":"permission/preset","data":{"preset":"danger-full-access"}} +{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Use workflow to create a nested reviewer that replies LEAF_READY, then reply BRANCH_READY."}],"source":{"kind":"user"},"role":"user","id":"{{message:13}}"}]}} +{"type":"turn/start","data":{"turn":1}} +{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} +{"type":"step/start","data":{"turn":1,"step":1}} +{"type":"system/message","data":{"turn":1,"step":1,"message":{"role":"system","content":[{"type":"text","text":"{{system}}"}],"source":{"kind":"system-prompt"},"id":"{{message:14}}"}},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Use workflow to create a nested reviewer that replies LEAF_READY, then reply BRANCH_READY."}],"source":{"kind":"user"},"role":"user","id":"{{message:13}}"},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations.\n\nApproval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).\n\nDelegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly.\n\nDelegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly.\n\nYou are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it.\n\nYou are a teammate in the Team led by agent \"{{session:1}}\"."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations."},{"name":"approval:policy","text":"Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."},{"name":"tool:subagent:depth","text":"Delegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly."},{"name":"tool:subagent_fork:depth","text":"Delegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly."},{"name":"subagent:delegation","text":"You are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."},{"name":"team:identity","text":"You are a teammate in the Team led by agent \"{{session:1}}\"."}]},"role":"user","id":"{{message:15}}"},"surfaceOp":"append"} +{"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} +{"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} +{"type":"session/title","data":{"title":"Use workflow to create a","messageSeqs":[9],"source":{"kind":"fallback"}}} +{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"desc-2-1","name":"workflow","arguments":"{\"meta\":{\"name\":\"leaf\",\"description\":\"Create the nested reviewer.\"},\"script\":\"return await agent(\\\"Reply LEAF_READY.\\\");\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:16}}"},"stream":[{"type":"chunk","time":1792056641572,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"chunk","time":1792056641572,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"desc-2-1","name":"workflow","arguments":"{\"meta\":{\"name\":\"leaf\",\"description\":\"Create the nested reviewer.\"},\"script\":\"return await agent(\\\"Reply LEAF_READY.\\\");\"}"}}},{"type":"chunk","time":1792056641572,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":1,"callId":"desc-2-1","name":"workflow","arguments":"{\"meta\":{\"name\":\"leaf\",\"description\":\"Create the nested reviewer.\"},\"script\":\"return await agent(\\\"Reply LEAF_READY.\\\");\"}"}} +{"type":"tool-workflow/run-start","data":{"runId":"{{workflow:2}}","name":"leaf"}} +{"type":"subagent/catalog","data":{"version":0,"childId":"{{session:3}}","childCreatedAt":1792056641664,"mode":"continuable","label":"leaf child 1"}} +{"type":"tool-workflow/agent-start","data":{"runId":"{{workflow:2}}","seq":1,"label":"Reply LEAF_READY.","childId":"{{session:3}}"}} +{"type":"tool-workflow/agent-end","data":{"runId":"{{workflow:2}}","seq":1,"outcome":"completed"}} +{"type":"tool-workflow/run-end","data":{"runId":"{{workflow:2}}","stopReason":"completed"}} +{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"desc-2-1"},"toolCallId":"desc-2-1","content":[{"type":"text","text":"workflow \"leaf\" completed (1 agent).\nReturn value:\n\"LEAF_READY\""}],"isError":false,"id":"{{message:17}}"}},"sourceEventSeqs":[15],"surfaceOp":"append"} +{"type":"step/end","data":{"turn":1,"step":1}} +{"type":"step/start","data":{"turn":1,"step":2}} +{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"text","text":"BRANCH_READY"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:18}}"},"stream":[{"type":"chunk","time":1792056641741,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"chunk","time":1792056641741,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"BRANCH_READY"}}},{"type":"chunk","time":1792056641741,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"step/end","data":{"turn":1,"step":2}} +{"type":"turn/end","data":{"turn":1,"reason":{"kind":"completed"}}} diff --git a/snapshots/session/team-descendant-task/session.2.v4.jsonl b/snapshots/session/team-descendant-task/session.2.v4.jsonl new file mode 100644 index 0000000000..2f86641a6f --- /dev/null +++ b/snapshots/session/team-descendant-task/session.2.v4.jsonl @@ -0,0 +1,18 @@ +{"type":"session","version":4,"id":"{{session:3}}","createdAt":1783951000000,"cwd":"{{cwd}}","parentSession":"{{session:2}}","isSeeded":false,"origin":"subagent","delegationDepth":2} +{"type":"subagent/descriptor","data":{"version":3,"mode":"continuable","provider":"spawn","label":"leaf child 1","agentProvider":"deepseek-official","agentModel":"deepseek-v4-flash"}} +{"type":"sandbox/mode","data":{"mode":"danger-full-access","source":"delegation"}} +{"type":"approval/policy","data":{"policy":"never","source":"delegation"}} +{"type":"permission/preset","data":{"preset":"danger-full-access"}} +{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Reply LEAF_READY."}],"source":{"kind":"user"},"role":"user","id":"{{message:19}}"}]}} +{"type":"turn/start","data":{"turn":1}} +{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} +{"type":"step/start","data":{"turn":1,"step":1}} +{"type":"system/message","data":{"turn":1,"step":1,"message":{"role":"system","content":[{"type":"text","text":"{{system}}"}],"source":{"kind":"system-prompt"},"id":"{{message:20}}"}},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Reply LEAF_READY."}],"source":{"kind":"user"},"role":"user","id":"{{message:19}}"},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations.\n\nApproval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).\n\nDelegation depth for `subagent`: current 2, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly.\n\nDelegation depth for `subagent_fork`: current 2, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly.\n\nYou are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it.\n\nYou are a teammate in the Team led by agent \"{{session:1}}\"."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations."},{"name":"approval:policy","text":"Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."},{"name":"tool:subagent:depth","text":"Delegation depth for `subagent`: current 2, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly."},{"name":"tool:subagent_fork:depth","text":"Delegation depth for `subagent_fork`: current 2, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly."},{"name":"subagent:delegation","text":"You are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."},{"name":"team:identity","text":"You are a teammate in the Team led by agent \"{{session:1}}\"."}]},"role":"user","id":"{{message:21}}"},"surfaceOp":"append"} +{"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} +{"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} +{"type":"session/title","data":{"title":"Reply LEAF_READY.","messageSeqs":[9],"source":{"kind":"fallback"}}} +{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"text","text":"LEAF_READY"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:22}}"},"stream":[{"type":"chunk","time":1792056641703,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"chunk","time":1792056641703,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"LEAF_READY"}}},{"type":"chunk","time":1792056641703,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"step/end","data":{"turn":1,"step":1}} +{"type":"turn/end","data":{"turn":1,"reason":{"kind":"completed"}}} diff --git a/snapshots/session/team-descendant-task/session.v4.jsonl b/snapshots/session/team-descendant-task/session.v4.jsonl new file mode 100644 index 0000000000..2bed000ecd --- /dev/null +++ b/snapshots/session/team-descendant-task/session.v4.jsonl @@ -0,0 +1,44 @@ +{"type":"session","version":4,"id":"{{session:1}}","createdAt":1783951000000,"cwd":"{{cwd}}","isSeeded":false,"delegationDepth":0} +{"type":"permission/preset","data":{"preset":"danger-full-access"}} +{"type":"sandbox/mode","data":{"mode":"danger-full-access"}} +{"type":"approval/policy","data":{"policy":"never"}} +{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Create a nested reviewer through workflows, then assign it a shared task by its session id after both descendants finish."}],"source":{"kind":"user"},"role":"user","id":"{{message:1}}"}]}} +{"type":"turn/start","data":{"turn":1}} +{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} +{"type":"step/start","data":{"turn":1,"step":1}} +{"type":"system/message","data":{"turn":1,"step":1,"message":{"role":"system","content":[{"type":"text","text":"{{system}}"}],"source":{"kind":"system-prompt"},"id":"{{message:2}}"}},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Create a nested reviewer through workflows, then assign it a shared task by its session id after both descendants finish."}],"source":{"kind":"user"},"role":"user","id":"{{message:1}}"},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations.\n\nApproval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).\n\nYou are the Team Lead. Your agent id is \"{{session:1}}\"."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations."},{"name":"approval:policy","text":"Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."},{"name":"team:identity","text":"You are the Team Lead. Your agent id is \"{{session:1}}\"."}]},"role":"user","id":"{{message:3}}"},"surfaceOp":"append"} +{"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} +{"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} +{"type":"session/title","data":{"title":"Create a nested reviewer through","messageSeqs":[8],"source":{"kind":"fallback"}}} +{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"desc-1-1","name":"workflow","arguments":"{\"meta\":{\"name\":\"branch\",\"description\":\"Create the nested reviewer.\"},\"script\":\"return await agent(\\\"Use workflow to create a nested reviewer that replies LEAF_READY, then reply BRANCH_READY.\\\");\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"stream":[{"type":"chunk","time":1792056641409,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"chunk","time":1792056641409,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"desc-1-1","name":"workflow","arguments":"{\"meta\":{\"name\":\"branch\",\"description\":\"Create the nested reviewer.\"},\"script\":\"return await agent(\\\"Use workflow to create a nested reviewer that replies LEAF_READY, then reply BRANCH_READY.\\\");\"}"}}},{"type":"chunk","time":1792056641409,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":1,"callId":"desc-1-1","name":"workflow","arguments":"{\"meta\":{\"name\":\"branch\",\"description\":\"Create the nested reviewer.\"},\"script\":\"return await agent(\\\"Use workflow to create a nested reviewer that replies LEAF_READY, then reply BRANCH_READY.\\\");\"}"}} +{"type":"tool-workflow/run-start","data":{"runId":"{{workflow:1}}","name":"branch"}} +{"type":"subagent/catalog","data":{"version":0,"childId":"{{session:2}}","childCreatedAt":1792056641532,"mode":"continuable","label":"branch child 1"}} +{"type":"tool-workflow/agent-start","data":{"runId":"{{workflow:1}}","seq":1,"label":"Use workflow to create a nested reviewer that r…","childId":"{{session:2}}"}} +{"type":"tool-workflow/agent-end","data":{"runId":"{{workflow:1}}","seq":1,"outcome":"completed"}} +{"type":"tool-workflow/run-end","data":{"runId":"{{workflow:1}}","stopReason":"completed"}} +{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"desc-1-1"},"toolCallId":"desc-1-1","content":[{"type":"text","text":"workflow \"branch\" completed (1 agent).\nReturn value:\n\"BRANCH_READY\""}],"isError":false,"id":"{{message:5}}"}},"sourceEventSeqs":[14],"surfaceOp":"append"} +{"type":"step/end","data":{"turn":1,"step":1}} +{"type":"step/start","data":{"turn":1,"step":2}} +{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"tool-call","id":"desc-1-2","name":"team_task_create","arguments":"{\"subject\":\"Nested review\",\"description\":\"Review the shared change.\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:6}}"},"stream":[{"type":"chunk","time":1792056641776,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"chunk","time":1792056641776,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"desc-1-2","name":"team_task_create","arguments":"{\"subject\":\"Nested review\",\"description\":\"Review the shared change.\"}"}}},{"type":"chunk","time":1792056641776,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":2,"callId":"desc-1-2","name":"team_task_create","arguments":"{\"subject\":\"Nested review\",\"description\":\"Review the shared change.\"}"}} +{"type":"team/task","data":{"version":2,"teamId":"{{session:1}}","task":{"id":"task-1","revision":1,"subject":"Nested review","description":"Review the shared change.","status":"pending","blockedBy":[],"writeScopes":[]}}} +{"type":"tool/result","data":{"turn":1,"step":2,"message":{"role":"tool","source":{"kind":"tool","callId":"desc-1-2"},"toolCallId":"desc-1-2","content":[{"type":"text","text":"{\"id\":\"task-1\",\"revision\":1,\"subject\":\"Nested review\",\"description\":\"Review the shared change.\",\"status\":\"pending\",\"blockedBy\":[],\"writeScopes\":[],\"ready\":true,\"writeScopeWarnings\":[]}"}],"isError":false,"id":"{{message:7}}"}},"sourceEventSeqs":[24],"surfaceOp":"append"} +{"type":"step/end","data":{"turn":1,"step":2}} +{"type":"step/start","data":{"turn":1,"step":3}} +{"type":"assistant/message","data":{"turn":1,"step":3,"message":{"role":"assistant","content":[{"type":"tool-call","id":"desc-1-3","name":"team_task_update","arguments":"{\"task_id\":\"task-1\",\"expected_revision\":1,\"action\":\"reassign\",\"owner\":\"{{session:3}}\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:8}}"},"stream":[{"type":"chunk","time":1792056641797,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"chunk","time":1792056641797,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"desc-1-3","name":"team_task_update","arguments":"{\"task_id\":\"task-1\",\"expected_revision\":1,\"action\":\"reassign\",\"owner\":\"{{session:3}}\"}"}}},{"type":"chunk","time":1792056641797,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":3,"callId":"desc-1-3","name":"team_task_update","arguments":"{\"task_id\":\"task-1\",\"expected_revision\":1,\"action\":\"reassign\",\"owner\":\"{{session:3}}\"}"}} +{"type":"team/task","data":{"version":2,"teamId":"{{session:1}}","task":{"id":"task-1","revision":2,"subject":"Nested review","description":"Review the shared change.","status":"in_progress","blockedBy":[],"writeScopes":[],"ownerId":"{{session:3}}"}}} +{"type":"tool/result","data":{"turn":1,"step":3,"message":{"role":"tool","source":{"kind":"tool","callId":"desc-1-3"},"toolCallId":"desc-1-3","content":[{"type":"text","text":"{\"id\":\"task-1\",\"revision\":2,\"subject\":\"Nested review\",\"description\":\"Review the shared change.\",\"status\":\"in_progress\",\"blockedBy\":[],\"writeScopes\":[],\"ownerId\":\"{{session:3}}\",\"ready\":false,\"writeScopeWarnings\":[]}"}],"isError":false,"id":"{{message:9}}"}},"sourceEventSeqs":[30],"surfaceOp":"append"} +{"type":"step/end","data":{"turn":1,"step":3}} +{"type":"step/start","data":{"turn":1,"step":4}} +{"type":"assistant/message","data":{"turn":1,"step":4,"message":{"role":"assistant","content":[{"type":"tool-call","id":"desc-1-4","name":"team_task_get","arguments":"{\"task_id\":\"task-1\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:10}}"},"stream":[{"type":"chunk","time":1792056641826,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"chunk","time":1792056641826,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"desc-1-4","name":"team_task_get","arguments":"{\"task_id\":\"task-1\"}"}}},{"type":"chunk","time":1792056641826,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":4,"callId":"desc-1-4","name":"team_task_get","arguments":"{\"task_id\":\"task-1\"}"}} +{"type":"tool/result","data":{"turn":1,"step":4,"message":{"role":"tool","source":{"kind":"tool","callId":"desc-1-4"},"toolCallId":"desc-1-4","content":[{"type":"text","text":"{\"id\":\"task-1\",\"revision\":2,\"subject\":\"Nested review\",\"description\":\"Review the shared change.\",\"status\":\"in_progress\",\"blockedBy\":[],\"writeScopes\":[],\"ownerId\":\"{{session:3}}\",\"ready\":false,\"writeScopeWarnings\":[]}"}],"isError":false,"id":"{{message:11}}"}},"sourceEventSeqs":[36],"surfaceOp":"append"} +{"type":"step/end","data":{"turn":1,"step":4}} +{"type":"step/start","data":{"turn":1,"step":5}} +{"type":"assistant/message","data":{"turn":1,"step":5,"message":{"role":"assistant","content":[{"type":"text","text":"TEAM_DESCENDANT_ASSIGNED"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:12}}"},"stream":[{"type":"chunk","time":1792056641842,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"chunk","time":1792056641842,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"TEAM_DESCENDANT_ASSIGNED"}}},{"type":"chunk","time":1792056641842,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"step/end","data":{"turn":1,"step":5}} +{"type":"turn/end","data":{"turn":1,"reason":{"kind":"completed"}}} diff --git a/snapshots/session/team-descendant-task/snapshot.yml b/snapshots/session/team-descendant-task/snapshot.yml new file mode 100644 index 0000000000..63bc394d7b --- /dev/null +++ b/snapshots/session/team-descendant-task/snapshot.yml @@ -0,0 +1,9 @@ +version: 1 +scenario: team-descendant-task +profile: headless +composition: team-targets +recording: authored +header: + class: team-targets + systemPromptSource: team-targets + toolSchemasSource: team-targets diff --git a/snapshots/session/team-targets/system-prompt.expected.md b/snapshots/session/team-targets/system-prompt.expected.md index 5f3134b65f..ce01b0e104 100644 --- a/snapshots/session/team-targets/system-prompt.expected.md +++ b/snapshots/session/team-targets/system-prompt.expected.md @@ -11,7 +11,7 @@ The Team Lead and all teammates share the same working directory and filesystem. Prefer read/edit/write for file changes. If a file operation returns FS_STALE_VERSION, read the current file, rebase your intended change onto the new content, and retry. Bash, formatters, code generators, and scripts are not fully protected by the filesystem version guard; coordinate them explicitly and have the Lead review the final diff and run tests. -Use agent ids as task owners. The Lead can reassign to itself, its direct continuable children, or historical members; other descendants claim tasks themselves. list_agents shows direct contacts by default; descendants scope discovers deeper agents without granting message or assignment authority. inactive means no turn is executing; it does not describe task completion, success, failure, or waiting for other agents. A successful send does not mean the recipient has processed it. Shared-task workflow is list, get, claim with the current revision, perform the work, then complete. Task readiness never starts an owner. Before wait_agent, make sure another required member is running; use send_message first for an inactive direct contact, or coordinate through its parent for a deeper member. wait_agent observes only changes after that call starts, never wakes a member, and returns noProgress immediately when no other member is running. Re-list after wakeup or timeout. The Lead must wait for required teammates before giving the final answer. +Use agent ids as task owners. The Lead can reassign to itself, continuable descendants at any depth, or active historical members. list_agents shows direct contacts by default; descendants scope discovers deeper agents for task assignment but does not grant direct messaging authority. inactive means no turn is executing; it does not describe task completion, success, failure, or waiting for other agents. A successful send does not mean the recipient has processed it. Shared-task workflow is list, get, claim with the current revision, perform the work, then complete. Task readiness never starts an owner. Before wait_agent, make sure another required member is running; use send_message first for an inactive direct contact, or coordinate through its parent for a deeper member. wait_agent observes only changes after that call starts, never wakes a member, and returns noProgress immediately when no other member is running. Re-list after wakeup or timeout. The Lead must wait for required teammates before giving the final answer. Check the [exit code: N] marker on every bash result; investigate failures before moving on. diff --git a/snapshots/session/team-targets/tool-schemas.expected.json b/snapshots/session/team-targets/tool-schemas.expected.json index a888f50485..558677d543 100644 --- a/snapshots/session/team-targets/tool-schemas.expected.json +++ b/snapshots/session/team-targets/tool-schemas.expected.json @@ -524,7 +524,7 @@ }, "owner": { "type": "string", - "description": "Agent id of the Lead or one of its direct continuable children for Lead-only reassign; omit to unassign." + "description": "Agent id of the Lead or a continuable descendant for Lead-only reassign; omit to unassign." } }, "required": [ From 7ec9cc2c6dff5275b9cd36b8d1df7bbf8529e1d5 Mon Sep 17 00:00:00 2001 From: Dudu-0223 Date: Thu, 15 Oct 2026 17:57:49 +0800 Subject: [PATCH 02/17] docs(team): refresh the session query dependency graph --- docs/module-graph.md | 3 ++- docs/module-graph.zh.md | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/module-graph.md b/docs/module-graph.md index 284116e967..238abcceb3 100644 --- a/docs/module-graph.md +++ b/docs/module-graph.md @@ -1330,6 +1330,7 @@ flowchart TD pkg_experimental_agent_team --> pkg_llm pkg_experimental_agent_team --> pkg_session pkg_experimental_agent_team --> pkg_session_projection + pkg_experimental_agent_team --> pkg_session_query pkg_experimental_agent_team --> pkg_subagent pkg_hooks_claude_code --> pkg_agent pkg_hooks_claude_code --> pkg_hook_protocol @@ -1749,7 +1750,7 @@ flowchart TD | [`headless`](../packages/bundle/headless) | `bundle` | [`agent`](../packages/core/agent), [`agent-default-model`](../packages/core/agent-default-model), [`fs`](../packages/fs/fs), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-query`](../packages/session-query/session-query), [`subagent`](../packages/subagent/subagent) | | [`compaction-basic`](../packages/compaction/compaction-basic) | `compaction` | [`agent`](../packages/core/agent), [`commands`](../packages/interaction/commands), [`compaction`](../packages/compaction/compaction), [`compaction-tool-result-pruner`](../packages/compaction/compaction-tool-result-pruner), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`token-meter`](../packages/llm/token-meter) | | [`session-reference`](../packages/context/session-reference) | `context` | [`agent`](../packages/core/agent), [`compaction`](../packages/compaction/compaction), [`llm`](../packages/llm/llm), [`output-retention`](../packages/util/output-retention), [`session`](../packages/core/session), [`session-projection`](../packages/session/session-projection), [`session-projection-cache`](../packages/session/session-projection-cache), [`session-query`](../packages/session-query/session-query), [`session-title`](../packages/session/session-title), [`spill`](../packages/spill/spill), [`subagent`](../packages/subagent/subagent), [`system-prompt`](../packages/core/system-prompt), [`typert-protocol`](../packages/typert/protocol) | -| [`experimental-agent-team`](../packages/experimental/agent-team) | `experimental` | [`agent`](../packages/core/agent), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-projection`](../packages/session/session-projection), [`subagent`](../packages/subagent/subagent) | +| [`experimental-agent-team`](../packages/experimental/agent-team) | `experimental` | [`agent`](../packages/core/agent), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-projection`](../packages/session/session-projection), [`session-query`](../packages/session-query/session-query), [`subagent`](../packages/subagent/subagent) | | [`hooks-claude-code`](../packages/experimental/hooks-claude-code) | `experimental` | [`agent`](../packages/core/agent), [`hook-protocol`](../packages/experimental/hook-protocol), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-projection`](../packages/session/session-projection), [`subagent`](../packages/subagent/subagent), [`tools`](../packages/core/tools), [`working-directory`](../packages/session/working-directory) | | [`tool-ralph`](../packages/experimental/tool-ralph) | `experimental` | [`agent`](../packages/core/agent), [`llm`](../packages/llm/llm), [`subagent`](../packages/subagent/subagent), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools), [`workflow`](../packages/workflow/workflow) | | [`sdk-protocol`](../packages/sdk/protocol) | `sdk` | [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`subagent`](../packages/subagent/subagent) | diff --git a/docs/module-graph.zh.md b/docs/module-graph.zh.md index 165641d138..fc8324e6ab 100644 --- a/docs/module-graph.zh.md +++ b/docs/module-graph.zh.md @@ -1332,6 +1332,7 @@ flowchart TD pkg_experimental_agent_team --> pkg_llm pkg_experimental_agent_team --> pkg_session pkg_experimental_agent_team --> pkg_session_projection + pkg_experimental_agent_team --> pkg_session_query pkg_experimental_agent_team --> pkg_subagent pkg_hooks_claude_code --> pkg_agent pkg_hooks_claude_code --> pkg_hook_protocol @@ -1751,7 +1752,7 @@ flowchart TD | [`headless`](../packages/bundle/headless) | `bundle` | [`agent`](../packages/core/agent), [`agent-default-model`](../packages/core/agent-default-model), [`fs`](../packages/fs/fs), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-query`](../packages/session-query/session-query), [`subagent`](../packages/subagent/subagent) | | [`compaction-basic`](../packages/compaction/compaction-basic) | `compaction` | [`agent`](../packages/core/agent), [`commands`](../packages/interaction/commands), [`compaction`](../packages/compaction/compaction), [`compaction-tool-result-pruner`](../packages/compaction/compaction-tool-result-pruner), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`token-meter`](../packages/llm/token-meter) | | [`session-reference`](../packages/context/session-reference) | `context` | [`agent`](../packages/core/agent), [`compaction`](../packages/compaction/compaction), [`llm`](../packages/llm/llm), [`output-retention`](../packages/util/output-retention), [`session`](../packages/core/session), [`session-projection`](../packages/session/session-projection), [`session-projection-cache`](../packages/session/session-projection-cache), [`session-query`](../packages/session-query/session-query), [`session-title`](../packages/session/session-title), [`spill`](../packages/spill/spill), [`subagent`](../packages/subagent/subagent), [`system-prompt`](../packages/core/system-prompt), [`typert-protocol`](../packages/typert/protocol) | -| [`experimental-agent-team`](../packages/experimental/agent-team) | `experimental` | [`agent`](../packages/core/agent), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-projection`](../packages/session/session-projection), [`subagent`](../packages/subagent/subagent) | +| [`experimental-agent-team`](../packages/experimental/agent-team) | `experimental` | [`agent`](../packages/core/agent), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-projection`](../packages/session/session-projection), [`session-query`](../packages/session-query/session-query), [`subagent`](../packages/subagent/subagent) | | [`hooks-claude-code`](../packages/experimental/hooks-claude-code) | `experimental` | [`agent`](../packages/core/agent), [`hook-protocol`](../packages/experimental/hook-protocol), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-projection`](../packages/session/session-projection), [`subagent`](../packages/subagent/subagent), [`tools`](../packages/core/tools), [`working-directory`](../packages/session/working-directory) | | [`tool-ralph`](../packages/experimental/tool-ralph) | `experimental` | [`agent`](../packages/core/agent), [`llm`](../packages/llm/llm), [`subagent`](../packages/subagent/subagent), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools), [`workflow`](../packages/workflow/workflow) | | [`sdk-protocol`](../packages/sdk/protocol) | `sdk` | [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`subagent`](../packages/subagent/subagent) | From 7fd0dba80d0a656ec1a59fa1b2fd1359ccb390fb Mon Sep 17 00:00:00 2001 From: Dudu-0223 Date: Fri, 16 Oct 2026 12:33:15 +0800 Subject: [PATCH 03/17] Add tree-wide names for subagent collaboration --- ...6-10-15-agent-teams-as-subagents.i18n.yaml | 4 +- .../2026-10-15-agent-teams-as-subagents.md | 2 + .../2026-10-15-agent-teams-as-subagents.zh.md | 2 + ...2026-10-16-tree-wide-agent-names.i18n.yaml | 22 + .../2026-10-16-tree-wide-agent-names.md | 31 + .../2026-10-16-tree-wide-agent-names.zh.md | 31 + .../headless/tests/fixtures/team-llm.mjs | 12 +- .../headless/tests/headless.expected.e2e.ts | 4 +- .../web/tests/official-subagent-bundle.e2e.ts | 2 +- .../tests/sidebar-subagent-activity.e2e.ts | 3 +- apps/web/tests/subagent-conversation.e2e.ts | 3 +- .../tests/subagent-fork-schedule.snapshot.ts | 2 +- apps/web/tests/subagent-interrupt-ui.e2e.ts | 5 +- apps/web/tests/subagent-interrupt.e2e.ts | 4 +- docs/config-catalog.md | 8 +- docs/config-catalog.zh.md | 8 +- docs/development.i18n.yaml | 4 +- docs/development.md | 2 +- docs/development.zh.md | 2 +- docs/event-producer-consumer.md | 8 +- docs/event-producer-consumer.zh.md | 8 +- docs/persistence-catalog.i18n.yaml | 32 +- docs/persistence-catalog.md | 56 + docs/persistence-catalog.zh.md | 56 + ...2026-10-16-tree-wide-agent-names.i18n.yaml | 28 + .../2026-10-16-tree-wide-agent-names.md | 48 + ...26-10-16-tree-wide-agent-names.schema.json | 81 ++ .../2026-10-16-tree-wide-agent-names.zh.md | 48 + .../historical-formats/README.i18n.yaml | 4 +- .../historical-formats/README.md | 2 +- .../historical-formats/README.zh.md | 2 +- docs/persistence-schema.json | 94 ++ docs/subsystems/subagent.i18n.yaml | 3 + docs/subsystems/subagent.md | 42 + docs/subsystems/subagent.zh.md | 42 + docs/tool-catalog.i18n.yaml | 14 +- docs/tool-catalog.md | 31 +- docs/tool-catalog.zh.md | 33 +- .../agent-team-subagents/guide.i18n.yaml | 22 +- .../agent-team-subagents/guide.md | 20 +- .../agent-team-subagents/guide.zh.md | 28 +- packages/acp/acp/tests/turns.spec.ts | 3 +- .../bundle/headless/tests/headless.spec.ts | 3 +- packages/client/ui-tool/README.i18n.yaml | 4 +- packages/client/ui-tool/README.md | 2 +- packages/client/ui-tool/README.zh.md | 2 +- .../tool/models/control-details-model.ts | 2 +- .../tests/details-models.client.spec.ts | 4 +- .../core/session/src/known-event-types.ts | 1 + .../experimental/agent-team/README.i18n.yaml | 18 +- packages/experimental/agent-team/README.md | 8 +- packages/experimental/agent-team/README.zh.md | 10 +- .../agent-team/tests/persistence.spec.ts | 3 +- .../agent-team/tests/team.spec.ts | 5 +- .../tool-agent-team/README.i18n.yaml | 12 +- .../experimental/tool-agent-team/README.md | 10 +- .../experimental/tool-agent-team/README.zh.md | 10 +- .../experimental/tool-agent-team/src/index.ts | 57 +- .../tool-agent-team/tests/tool-team.spec.ts | 36 +- .../extensions/tool-cordis/src/api-catalog.ts | 19 +- packages/sdk/server/tests/shutdown.spec.ts | 3 +- packages/sdk/server/tests/wait.spec.ts | 5 +- .../fixtures/loader/mock-delegating-llm.ts | 2 +- .../tests/loader-composition.e2e.ts | 2 +- .../fixtures/loader/mock-delegating-llm.ts | 2 +- .../tests/fixtures/loader/nested-mock-llm.ts | 2 +- .../tests/loader-composition.e2e.ts | 2 +- packages/subagent/subagent/README.i18n.yaml | 12 +- packages/subagent/subagent/README.md | 7 +- packages/subagent/subagent/README.zh.md | 7 +- packages/subagent/subagent/src/activation.ts | 2 + .../subagent/src/continuation-messages.ts | 28 +- packages/subagent/subagent/src/index.ts | 24 + packages/subagent/subagent/src/manager.ts | 24 +- packages/subagent/subagent/src/names.ts | 164 +++ packages/subagent/subagent/src/types.ts | 4 + .../subagent/tests/activation-policy.spec.ts | 2 +- .../tests/continuation-inheritance.spec.ts | 19 +- .../continuation-messages-adapter.spec.ts | 5 +- .../tests/continuation-messages.spec.ts | 10 +- .../tests/continuation-presets.spec.ts | 2 + .../subagent/tests/continuation.spec.ts | 415 +++--- .../tests/external-activation-helpers.ts | 2 +- .../tests/external-activation.spec.ts | 7 +- .../subagent/tests/external-lifecycle.spec.ts | 3 +- .../subagent/tests/list-children.spec.ts | 3 +- .../subagent/tests/local-activation.ts | 2 +- .../subagent/subagent/tests/names.spec.ts | 158 +++ .../subagent/tests/parent-result.spec.ts | 5 +- .../subagent/tests/parked-wait.spec.ts | 3 +- .../subagent/tests/schedule-tools.spec.ts | 3 +- .../subagent/subagent/tests/service.spec.ts | 11 +- .../subagent/tests/sibling-messages.spec.ts | 4 +- .../subagent/tests/structured.spec.ts | 5 +- .../subagent/tests/working-directory.spec.ts | 5 +- .../tool-subagent-control/README.i18n.yaml | 36 +- .../subagent/tool-subagent-control/README.md | 18 +- .../tool-subagent-control/README.zh.md | 18 +- .../tool-subagent-control/src/index.ts | 22 +- .../tool-subagent-control/src/list-agents.ts | 39 +- .../tests/list-agents.spec.ts | 61 +- .../tests/tool-subagent-control.spec.ts | 108 +- .../subagent/tool-subagent/README.i18n.yaml | 14 +- packages/subagent/tool-subagent/README.md | 8 +- packages/subagent/tool-subagent/README.zh.md | 6 +- packages/subagent/tool-subagent/src/index.ts | 20 +- .../tests/model-selection-settings.spec.ts | 9 +- .../tests/model-selection.spec.ts | 40 +- .../tests/preset-selection.spec.ts | 3 +- .../tool-subagent/tests/tool-subagent.spec.ts | 65 +- .../test-support/llm-replay/README.i18n.yaml | 4 +- packages/test-support/llm-replay/README.md | 2 +- packages/test-support/llm-replay/README.zh.md | 2 +- packages/test-support/llm-replay/src/index.ts | 20 - .../llm-replay/tests/llm-replay.spec.ts | 7 +- .../session-snapshot/README.i18n.yaml | 4 +- .../test-support/session-snapshot/README.md | 2 +- .../session-snapshot/README.zh.md | 2 +- .../session-snapshot/src/identity.ts | 7 + .../fixtures/subagent-structured-parent.ts | 2 +- .../session-snapshot/tests/identity.spec.ts | 20 + packages/workflow/workflow-ptc/src/host.ts | 1 + .../workflow/workflow-ptc/tests/host.spec.ts | 6 +- .../workflow-ptc/tests/workflow-ptc.spec.ts | 1 + scripts/doc-typecheck-paths.spec.ts | 10 +- scripts/doc-typecheck-paths.ts | 11 + scripts/doc-typecheck.ts | 5 +- scripts/gen-tool-catalog.ts | 5 +- .../python-snapshot-workflow-order.spec.ts | 2 +- scripts/smoke-python-runtime.py | 1 + .../advanced/result.json | 208 +-- .../advanced/session.v4.jsonl | 18 +- scripts/type-equiv.manifest.json | 10 + .../sdk/bash-tool/tool-schemas.expected.json | 28 +- .../replay.override.json | 8 +- .../session.1.v4.jsonl | 4 +- .../session.v4.jsonl | 21 +- .../tool-schemas.1.expected.json | 28 +- .../session.1.v4.jsonl | 4 +- .../session.v4.jsonl | 13 +- .../tool-schemas.1.expected.json | 28 +- .../subagent-continuable/session.1.v4.jsonl | 12 +- .../sdk/subagent-continuable/session.v4.jsonl | 33 +- .../tool-schemas.1.expected.json | 28 +- .../notifications.expected.jsonl | 46 +- .../session.v4.jsonl | 32 +- .../tool-schemas.expected.json | 42 +- .../notifications.expected.jsonl | 23 +- .../session.v4.jsonl | 15 +- .../tool-schemas.1.expected.json | 28 +- .../tool-schemas.expected.json | 28 +- .../session.1.v4.jsonl | 4 +- .../subagent-fork-in-process/session.v4.jsonl | 15 +- .../subagent-list-agents/session.1.v4.jsonl | 4 +- .../sdk/subagent-list-agents/session.v4.jsonl | 21 +- .../tool-schemas.1.expected.json | 28 +- .../sdk/subagent-mixed/session.1.v4.jsonl | 4 +- .../sdk/subagent-mixed/session.2.v4.jsonl | 4 +- snapshots/sdk/subagent-mixed/session.v4.jsonl | 26 +- .../subagent-send-message/session.1.v4.jsonl | 10 +- .../subagent-send-message/session.v4.jsonl | 21 +- .../tool-schemas.1.expected.json | 28 +- .../notifications.expected.jsonl | 27 +- .../session.1.v4.jsonl | 4 +- .../session.v4.jsonl | 13 +- .../sdk/text-turn/tool-schemas.expected.json | 28 +- .../system-prompt.expected.md | 28 +- .../tool-schemas.expected.json | 28 +- .../session.1.v4.jsonl | 4 +- .../session.v4.jsonl | 28 +- .../advanced-toolchain/session.1.v4.jsonl | 4 +- .../advanced-toolchain/session.v4.jsonl | 30 +- .../system-prompt.expected.md | 28 +- .../tool-schemas.expected.json | 56 +- .../tool-schemas.expected.json | 56 +- .../tool-schemas.expected.json | 28 +- .../both-mode-turn/system-prompt.expected.md | 28 +- .../tool-schemas.expected.json | 28 +- .../tool-schemas.expected.json | 28 +- .../tool-schemas.expected.json | 28 +- .../tool-schemas.expected.json | 28 +- .../tool-schemas.expected.json | 56 +- .../tool-schemas.expected.json | 28 +- .../tool-schemas.expected.json | 28 +- .../tool-schemas.expected.json | 28 +- .../cua-native/tool-schemas.expected.json | 28 +- .../session/cua-ptc/system-prompt.expected.md | 28 +- .../tool-schemas.expected.json | 28 +- .../tool-schemas.expected.json | 28 +- .../tool-schemas.expected.json | 84 +- .../tool-schemas.expected.json | 28 +- .../tool-schemas.expected.json | 28 +- snapshots/session/headless.snapshot.ts | 2 +- .../lsp-definition/tool-schemas.expected.json | 28 +- .../system-prompt.expected.md | 28 +- .../mcp-resources/tool-schemas.expected.json | 28 +- .../tool-schemas.expected.json | 28 +- .../tool-schemas.expected.json | 28 +- .../system-prompt.expected.md | 28 +- .../office-skills/tool-schemas.expected.json | 28 +- .../tool-schemas.expected.json | 28 +- .../tool-schemas.expected.json | 56 +- .../plugin-manager/tool-schemas.expected.json | 28 +- .../tool-schemas.expected.json | 56 +- .../tool-schemas.expected.json | 42 +- .../replay.override.json | 20 +- .../session.v4.jsonl | 67 +- .../tool-schemas.expected.json | 35 +- .../provider-cwd/tool-schemas.expected.json | 28 +- .../system-prompt.expected.md | 28 +- .../system-prompt.expected.md | 28 +- .../ptc-persistent/system-prompt.expected.md | 28 +- .../system-prompt.expected.md | 28 +- .../ptc-python-turn/system-prompt.expected.md | 28 +- .../ptc-read-image/system-prompt.expected.md | 28 +- .../ptc-turn/system-prompt.expected.md | 28 +- .../tool-schemas.expected.json | 28 +- .../pwsh-tool-turn/tool-schemas.expected.json | 28 +- snapshots/session/ralph-loop/session.v4.jsonl | 10 +- .../ralph-loop/tool-schemas.1.expected.json | 28 +- .../ralph-loop/tool-schemas.2.expected.json | 28 +- .../ralph-loop/tool-schemas.expected.json | 28 +- .../tool-schemas.expected.json | 28 +- .../replay.override.json | 8 +- .../subagent-acp-diagnostic/session.v4.jsonl | 28 +- .../tool-schemas.expected.json | 35 +- .../subagent-agent-preset/session.1.v4.jsonl | 4 +- .../subagent-agent-preset/session.v4.jsonl | 17 +- .../tool-schemas.1.expected.json | 35 +- .../tool-schemas.expected.json | 28 +- .../session.1.v4.jsonl | 4 +- .../session.v4.jsonl | 17 +- .../tool-schemas.expected.json | 28 +- .../session.v4.jsonl | 4 +- .../replay.override.json | 4 +- .../session.1.v4.jsonl | 14 +- .../session.2.v4.jsonl | 8 +- .../session.v4.jsonl | 18 +- .../session.1.v4.jsonl | 10 +- .../session.v4.jsonl | 17 +- .../subagent-multi/replay.override.json | 1136 +++++++++++++++++ snapshots/session/subagent-multi/snapshot.yml | 2 + .../subagent-multi/writer.1.expected.jsonl | 6 +- .../subagent-multi/writer.2.expected.jsonl | 6 +- .../subagent-multi/writer.expected.jsonl | 28 +- .../subagent-no-message-tool/session.v4.jsonl | 17 +- .../tool-schemas.1.expected.json | 16 +- .../subagent-parallel/session.1.v4.jsonl | 4 +- .../subagent-parallel/session.2.v4.jsonl | 4 +- .../subagent-parallel/session.v4.jsonl | 26 +- .../replay.override.json | 76 +- .../session.v4.jsonl | 4 +- .../session.1.v4.jsonl | 4 +- .../session.v4.jsonl | 17 +- .../session.1.v4.jsonl | 8 +- .../session.v4.jsonl | 11 +- .../tool-schemas.1.expected.json | 28 +- .../tool-schemas.expected.json | 28 +- .../subagent-tool-filter/session.1.v4.jsonl | 4 +- .../subagent-tool-filter/session.v4.jsonl | 17 +- .../tool-schemas.1.expected.json | 28 +- .../tool-schemas.expected.json | 28 +- .../team-direct-inbox/session.1.v4.jsonl | 12 +- .../team-direct-inbox/session.v4.jsonl | 33 +- .../session/team-targets/session.v4.jsonl | 8 +- .../team-targets/system-prompt.expected.md | 4 +- .../team-targets/tool-schemas.expected.json | 32 +- .../text-turn/tool-schemas.expected.json | 28 +- .../session/text-turn/writer.expected.jsonl | 2 +- .../web-fetch/tool-schemas.expected.json | 28 +- .../tool-schemas.expected.json | 28 +- .../tool-schemas.expected.json | 28 +- .../worktree/tool-schemas.expected.json | 28 +- .../tool-schemas.expected.json | 28 +- .../official-subagent-bundle/session.v4.jsonl | 21 +- .../system-prompt.expected.md | 34 +- .../system-prompt.expected.md | 28 +- .../web/ptc-round/system-prompt.expected.md | 28 +- .../subagent-fork-schedule/session.v4.jsonl | 5 +- 279 files changed, 5299 insertions(+), 2098 deletions(-) create mode 100644 .agents/notes/implemented/architecture/2026-10-16-tree-wide-agent-names.i18n.yaml create mode 100644 .agents/notes/implemented/architecture/2026-10-16-tree-wide-agent-names.md create mode 100644 .agents/notes/implemented/architecture/2026-10-16-tree-wide-agent-names.zh.md create mode 100644 docs/persistence-changes/2026-10-16-tree-wide-agent-names.i18n.yaml create mode 100644 docs/persistence-changes/2026-10-16-tree-wide-agent-names.md create mode 100644 docs/persistence-changes/2026-10-16-tree-wide-agent-names.schema.json create mode 100644 docs/persistence-changes/2026-10-16-tree-wide-agent-names.zh.md create mode 100644 packages/subagent/subagent/src/names.ts create mode 100644 packages/subagent/subagent/tests/names.spec.ts create mode 100644 snapshots/session/subagent-multi/replay.override.json diff --git a/.agents/notes/implemented/architecture/2026-10-15-agent-teams-as-subagents.i18n.yaml b/.agents/notes/implemented/architecture/2026-10-15-agent-teams-as-subagents.i18n.yaml index f156fed8f2..d962a60190 100644 --- a/.agents/notes/implemented/architecture/2026-10-15-agent-teams-as-subagents.i18n.yaml +++ b/.agents/notes/implemented/architecture/2026-10-15-agent-teams-as-subagents.i18n.yaml @@ -3,8 +3,8 @@ # After editing either side, bring the other along and re-record with: # pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-10-15-agent-teams-as-subagents.md /agent-note-agent-teams-teammates-are-subagents: - en: 067bfa44266e764e - zh: dcdeff6c10e492be + en: 3a3c59709e08af73 + zh: 3ea1dd59c0f9866b /agent-note-agent-teams-teammates-are-subagents/problem: en: ca2848e3bbc3a009 zh: 0551e32ff6d187d0 diff --git a/.agents/notes/implemented/architecture/2026-10-15-agent-teams-as-subagents.md b/.agents/notes/implemented/architecture/2026-10-15-agent-teams-as-subagents.md index 6003614631..5134b602d5 100644 --- a/.agents/notes/implemented/architecture/2026-10-15-agent-teams-as-subagents.md +++ b/.agents/notes/implemented/architecture/2026-10-15-agent-teams-as-subagents.md @@ -4,6 +4,8 @@ Status: implemented English | [中文](2026-10-15-agent-teams-as-subagents.zh.md) +The name-free model interface below is superseded by [tree-wide agent names](2026-10-16-tree-wide-agent-names.md). Session identity, lineage authority, and Team reuse remain current. + ## Problem Teammates already use the subagent runtime for creation, Session identity, catalog membership, capacity, cold resume, settlement, and interruption. A separate Team roster duplicates identity, provisioning recovery, and teardown. Team-scoped messaging and control tools shadow the standard subagent tools, forcing profiles to disable ordinary delegation and making fork tool schemas diverge from their parent. diff --git a/.agents/notes/implemented/architecture/2026-10-15-agent-teams-as-subagents.zh.md b/.agents/notes/implemented/architecture/2026-10-15-agent-teams-as-subagents.zh.md index 7a49c11e4f..02bf310fae 100644 --- a/.agents/notes/implemented/architecture/2026-10-15-agent-teams-as-subagents.zh.md +++ b/.agents/notes/implemented/architecture/2026-10-15-agent-teams-as-subagents.zh.md @@ -4,6 +4,8 @@ Status: implemented [English](2026-10-15-agent-teams-as-subagents.md) | 中文 +下述不使用名字的模型接口已被[树内唯一 agent 名字](2026-10-16-tree-wide-agent-names.zh.md)取代。Session 身份、谱系权限和 Team 复用决策仍然有效。 + ## Problem 队友已经使用子代理运行时完成创建、Session 身份、目录成员关系、容量、冷恢复、结算和中断。独立 Team 成员列表重复了身份、创建恢复和释放职责。Team 作用域内的消息及控制工具覆盖标准子代理工具,迫使 profile 禁用普通委派,并使分叉工具模式偏离父级。 diff --git a/.agents/notes/implemented/architecture/2026-10-16-tree-wide-agent-names.i18n.yaml b/.agents/notes/implemented/architecture/2026-10-16-tree-wide-agent-names.i18n.yaml new file mode 100644 index 0000000000..3c44737efa --- /dev/null +++ b/.agents/notes/implemented/architecture/2026-10-16-tree-wide-agent-names.i18n.yaml @@ -0,0 +1,22 @@ +# Bilingual-pair consistency record for 2026-10-16-tree-wide-agent-names.md (docs/i18n/README.md): per heading +# section, a hash of its English and Chinese blocks outside code blocks and generated regions. +# After editing either side, bring the other along and re-record with: +# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-10-16-tree-wide-agent-names.md +/agent-note-tree-wide-agent-names: + en: e976b1e450bda2b9 + zh: e7a35fec64a52cb7 +/agent-note-tree-wide-agent-names/problem: + en: 45ad48d0442bbd54 + zh: 46837f64f46568b8 +/agent-note-tree-wide-agent-names/decision: + en: 53822735b4ce3e4e + zh: 316cb613b22a3e80 +/agent-note-tree-wide-agent-names/alternatives-considered: + en: 93964747050c9265 + zh: 2acb9708d145894b +/agent-note-tree-wide-agent-names/consequences: + en: 7810ae426c76bfcd + zh: 4b954c0f0672c534 +/agent-note-tree-wide-agent-names/testing: + en: 4210801f0de47c2c + zh: fe4d154a15796478 diff --git a/.agents/notes/implemented/architecture/2026-10-16-tree-wide-agent-names.md b/.agents/notes/implemented/architecture/2026-10-16-tree-wide-agent-names.md new file mode 100644 index 0000000000..cbede93c82 --- /dev/null +++ b/.agents/notes/implemented/architecture/2026-10-16-tree-wide-agent-names.md @@ -0,0 +1,31 @@ +# Agent Note: Tree-wide agent names + +Status: implemented + +English | [中文](2026-10-16-tree-wide-agent-names.zh.md) + +## Problem + +Session ids identify executions durably but make model coordination difficult to read. Descriptions can repeat and cannot identify recipients. The user requires explicit, unique names for subagents and teammates, with `lead` reserved for the root. + +## Decision + +Keep Session ids for persistence and authorization. Model tools accept immutable names unique throughout one agent tree. A root-owned `subagent/named` event records each successful assignment; the projection excludes fork-inherited facts. The manager reserves names before asynchronous preparation and releases failed unpublished reservations. Committed names remain taken after settlement so delayed messages cannot reach a different agent. + +This supersedes the name-free interface in [Agent Teams as subagents](2026-10-15-agent-teams-as-subagents.md). Its lineage authority and shared subagent lifecycle remain unchanged. Resolution never grants messaging, interruption, or task-assignment authority. Older unnamed descendants receive stable `legacy:` addresses; Team assignment also accepts such addresses for active historical members. + +## Alternatives considered + +**Parent-local names.** Descendant discovery would require path-qualified names. One tree-wide namespace gives every caller the same address. + +**Recyclable names.** Reuse could redirect queued or delayed work after the original agent settles. Retaining assignments keeps recipient identity stable. + +**A second committed registry.** The root projection already reconstructs assignments after restart. A second cache would require synchronization and recovery; only unpublished reservations need separate state. + +## Consequences + +Creation requires a name and rejects duplicates before dispatch. Independent roots can reuse names. Tool results, initial child guidance, message prefixes, and settlement notices use names. Internal Session and task-owner ids stay stable. The [upgrade guide](../../../../docs/upgrade-guide/v0.2.1-alpha.4/agent-team-subagents/guide.md) lists changed tool arguments and results. + +## Testing + +Name tests exercise concurrent duplicate rejection, failed-start release, nested-tree uniqueness, independent roots, retained projection state, invalid durable assignments, and legacy lookup. Recorded Headless and SDK sessions cover creation, messages, listing, and completion notices; Team tests preserve historical assignment without granting message authority. diff --git a/.agents/notes/implemented/architecture/2026-10-16-tree-wide-agent-names.zh.md b/.agents/notes/implemented/architecture/2026-10-16-tree-wide-agent-names.zh.md new file mode 100644 index 0000000000..1e7d0480ee --- /dev/null +++ b/.agents/notes/implemented/architecture/2026-10-16-tree-wide-agent-names.zh.md @@ -0,0 +1,31 @@ +# Agent Note: 树内唯一 agent 名字 + +Status: implemented + +[English](2026-10-16-tree-wide-agent-names.md) | 中文 + +## 问题 + +Session id 提供持久执行身份,但模型协作时难以阅读。描述可以重复,不能标识接收方。用户要求 subagent 和 teammate 显式使用唯一名字,并为根保留 `lead`。 + +## 决策 + +持久化与授权保留 Session id。模型工具接受整棵 agent 树内唯一且不可变的名字。根拥有的 `subagent/named` 事件记录每次成功分配;投影排除分叉继承的事实。管理器在异步准备前预留名字,释放失败且未发布的预留。执行结束后已提交名字仍被占用,避免延迟消息到达其他 agent。 + +本决策取代 [Agent Teams 作为 subagent](2026-10-15-agent-teams-as-subagents.zh.md) 中不使用名字的接口。谱系权限与共享子代理生命周期保持不变。名字解析不授予消息、中断或任务分配权限。旧的无名后代获得稳定的 `legacy:` 地址;Team 分配任务也接受活跃历史成员的此类地址。 + +## 考虑过的替代方案 + +**父级内唯一的名字。** 发现后代时需要限定路径。整棵树共享一个命名空间,使每个调用方使用相同地址。 + +**可回收的名字。** 原 agent 结束后复用名字,可能改变排队或延迟工作的接收方。保留分配使接收方身份稳定。 + +**第二份已提交注册表。** 根投影已经可以在重启后重建分配。第二份缓存需要同步与恢复;只有未发布的预留需要独立状态。 + +## 影响 + +创建必须提供名字,分发前拒绝重名。独立根可以复用名字。工具结果、子级初始指引、消息前缀与结束通知使用名字。内部 Session 和任务负责人 id 保持稳定。[升级指南](../../../../docs/upgrade-guide/v0.2.1-alpha.4/agent-team-subagents/guide.zh.md)列出变化的工具参数与结果。 + +## 测试 + +命名测试覆盖并发重名拒绝、启动失败释放、嵌套树唯一性、独立根、保留的投影状态、无效持久化分配与旧地址查找。Headless 和 SDK 录制会话覆盖创建、消息、列表与完成通知;Team 测试保留历史任务分配,同时拒绝消息权限。 diff --git a/apps/cli/tests/profiles/headless/tests/fixtures/team-llm.mjs b/apps/cli/tests/profiles/headless/tests/fixtures/team-llm.mjs index a61376043d..de08759da9 100644 --- a/apps/cli/tests/profiles/headless/tests/fixtures/team-llm.mjs +++ b/apps/cli/tests/profiles/headless/tests/fixtures/team-llm.mjs @@ -81,13 +81,13 @@ function researcher(messages) { if (!names.includes('send_message')) { return toolChunks([ { name: 'team_task_update', args: { task_id: 'task-1', expected_revision: 2, action: 'complete' } }, - { name: 'send_message', args: { agent_id: sibling, message: 'Research complete: use the deterministic finding.' } }, + { name: 'send_message', args: { name: sibling, message: 'Research complete: use the deterministic finding.' } }, ]) } return textChunks('Research teammate complete.') } -function implementer(messages, parentId) { +function implementer(messages, parentName) { const names = calls(messages) const last = latestAssistantCalls(messages) const text = latestToolText(messages) @@ -128,7 +128,7 @@ function implementer(messages, parentId) { if (!names.includes('send_message')) { return toolChunks([ { name: 'team_task_update', args: { task_id: 'task-2', expected_revision: 2, action: 'complete' } }, - { name: 'send_message', args: { agent_id: parentId, message: 'Implementation complete and verified.' } }, + { name: 'send_message', args: { name: parentName, message: 'Implementation complete and verified.' } }, ]) } return textChunks('Implementation teammate complete.') @@ -148,6 +148,7 @@ function lead(messages) { return toolChunks([{ name: 'subagent', args: { + name: 'implementer', description: 'Own deterministic implementation.', prompt: 'IMPLEMENTER_MARK: wait for research, complete dependent task 2, report to lead.', }, @@ -157,6 +158,7 @@ function lead(messages) { return toolChunks([{ name: 'subagent', args: { + name: 'researcher', description: 'Own deterministic research.', prompt: 'RESEARCHER_MARK: complete research task 1, message implementer, then finish.', }, @@ -186,7 +188,7 @@ class TeamFixtureAdapter extends LlmAdapter { const context = options.messages.findLast(message => message.source?.kind === 'runtime-context') const section = name => context?.source.sections?.find(candidate => candidate.name === name)?.text const role = section('team:identity') - const parentId = role?.match(/led by agent "([^"]+)"/u)?.[1] + const parentName = role?.match(/led by "([^"]+)"/u)?.[1] const task = initial?.content.filter(block => block.type === 'text').map(block => block.text).join('\n') if (!workflowChild && (!tools.includes('subagent') || !tools.includes('workflow') || !tools.includes('team_task_create'))) { throw new Error('Team profile is missing delegation, workflow, or task tools') @@ -194,7 +196,7 @@ class TeamFixtureAdapter extends LlmAdapter { let chunks if (workflowChild) chunks = textChunks('Fresh workflow child complete.') else if (task?.startsWith('RESEARCHER_MARK:')) chunks = researcher(options.messages) - else if (task?.startsWith('IMPLEMENTER_MARK:')) chunks = implementer(options.messages, parentId) + else if (task?.startsWith('IMPLEMENTER_MARK:')) chunks = implementer(options.messages, parentName) else if (role?.startsWith('You are the Team Lead.')) chunks = lead(options.messages) else throw new Error('Team runtime context is missing a recognized identity') for (const chunk of chunks) { diff --git a/apps/cli/tests/profiles/headless/tests/headless.expected.e2e.ts b/apps/cli/tests/profiles/headless/tests/headless.expected.e2e.ts index a7b1472f88..3803d655ab 100644 --- a/apps/cli/tests/profiles/headless/tests/headless.expected.e2e.ts +++ b/apps/cli/tests/profiles/headless/tests/headless.expected.e2e.ts @@ -1041,8 +1041,8 @@ describe('headless stream-json snapshots', () => { "checkedRoster": true, "deliveredMessages": 0, "identities": [ - "You are a teammate in the Team led by agent "".", - "You are a teammate in the Team led by agent "".", + "Your name is "implementer". You are a teammate in the Team led by "lead".", + "Your name is "researcher". You are a teammate in the Team led by "lead".", ], "queuedMessages": 0, "sessions": 4, diff --git a/apps/web/tests/official-subagent-bundle.e2e.ts b/apps/web/tests/official-subagent-bundle.e2e.ts index 8a21671b29..2e3ec6a617 100644 --- a/apps/web/tests/official-subagent-bundle.e2e.ts +++ b/apps/web/tests/official-subagent-bundle.e2e.ts @@ -156,7 +156,7 @@ describe.skipIf(MODE === 'record')('web snapshot: Official native subagent bundl if (notice?.data.source.kind !== 'subagent-settled') throw new Error('Native completion was not delivered to the parent') expect(notice.data.source.senderSessionId).toBe(catalog[0]?.childId) expect(notice.data.content).toContainEqual({ type: 'text', text: RESPONSE }) - expect(dispatches[0]?.content).toEqual([{ type: 'text', text: `started subagent ${notice.data.source.senderSessionId}` }]) + expect(dispatches[0]?.content).toEqual([{ type: 'text', text: 'started subagent native-worker' }]) expect(events.filter(event => event.type === 'turn/end')).toHaveLength(2) expect(server.requests).toHaveLength(1) expect(server.requests[0]?.body).toMatchObject({ model: 'fixture-model' }) diff --git a/apps/web/tests/sidebar-subagent-activity.e2e.ts b/apps/web/tests/sidebar-subagent-activity.e2e.ts index f2c8eb3434..33290d6287 100644 --- a/apps/web/tests/sidebar-subagent-activity.e2e.ts +++ b/apps/web/tests/sidebar-subagent-activity.e2e.ts @@ -1,3 +1,4 @@ +import { randomUUID } from 'node:crypto' import { mkdir } from 'node:fs/promises' import { join } from 'node:path' import { fileURLToPath } from 'node:url' @@ -96,7 +97,7 @@ describe('web e2e: sidebar subagent activity', () => { source: { kind: 'user' }, })) await parentHandle.agent.whenIdle() - const started = await scaffold.ctx.subagents.startActivation({ + const started = await scaffold.ctx.subagents.startActivation({ name: `child-${randomUUID()}`, delivery: 'parent', provider: 'spawn', label: 'sidebar activity child', diff --git a/apps/web/tests/subagent-conversation.e2e.ts b/apps/web/tests/subagent-conversation.e2e.ts index 2324f0ae2b..5ef77670e3 100644 --- a/apps/web/tests/subagent-conversation.e2e.ts +++ b/apps/web/tests/subagent-conversation.e2e.ts @@ -1,3 +1,4 @@ +import { randomUUID } from 'node:crypto' import { mkdir, mkdtemp, readFile, readdir, rm, writeFile } from 'node:fs/promises' import { tmpdir } from 'node:os' import { fileURLToPath } from 'node:url' @@ -144,7 +145,7 @@ describe('web e2e: persisted subagent conversation and human continuation', () = await parentInput.press('Enter') expect(await parentSettled).toBe(parent.id) - const started = await scaffold.ctx.subagents.startActivation({ + const started = await scaffold.ctx.subagents.startActivation({ name: `child-${randomUUID()}`, delivery: 'parent', provider: 'spawn', label: LABEL, diff --git a/apps/web/tests/subagent-fork-schedule.snapshot.ts b/apps/web/tests/subagent-fork-schedule.snapshot.ts index 62f42cb69a..387963bd0d 100644 --- a/apps/web/tests/subagent-fork-schedule.snapshot.ts +++ b/apps/web/tests/subagent-fork-schedule.snapshot.ts @@ -45,7 +45,7 @@ it.skipIf(MODE === 'record')('replays inherited schedule tools and refusals in a const childPrompt = parseSessionLog(expected[1]!).findLast(event => event.type === 'user/message' && event.data.source.kind === 'user') if (childPrompt?.type !== 'user/message') throw new Error('child fixture has no user prompt') - const activation = await scaffold.ctx.subagents.startActivation({ + const activation = await scaffold.ctx.subagents.startActivation({ name: 'scheduled-child', provider: 'fork', label: 'Check child reminder refusal', delivery: 'caller', signal: new AbortController().signal, request: { parent, prompt: [...childPrompt.data.content] }, diff --git a/apps/web/tests/subagent-interrupt-ui.e2e.ts b/apps/web/tests/subagent-interrupt-ui.e2e.ts index 7afeaa9a10..943cf88de6 100644 --- a/apps/web/tests/subagent-interrupt-ui.e2e.ts +++ b/apps/web/tests/subagent-interrupt-ui.e2e.ts @@ -1,3 +1,4 @@ +import { randomUUID } from 'node:crypto' // Web e2e scenario: the composer's independent Stop interrupts a running // continuable child. The child holds its model turn open through a replay // hang entry; the browser proves Send and Stop coexist, the parent-offline @@ -148,7 +149,7 @@ describe.skipIf(MODE === 'record')('web e2e: composer interrupt for a running co if (root === undefined) throw new Error('fresh workspace did not publish its parent Agent') parent = root // The child's first model call claims the primary override and holds. - const started = await scaffold.ctx.subagents.startActivation({ + const started = await scaffold.ctx.subagents.startActivation({ name: `child-${randomUUID()}`, delivery: 'parent', provider: 'spawn', label: LABEL, @@ -378,7 +379,7 @@ describe.skipIf(MODE === 'record')('web e2e: composer interrupt for a running co ? event.data.content.flatMap(block => block.type === 'text' ? [block.text] : []) : []) expect(userTexts[0]).toBe(INITIAL) - expect(userTexts[1]).toMatch(/^Your parent agent id is .+send_message\(\{ agent_id: /) + expect(userTexts[1]).toMatch(/^Your name is .+Your parent agent name is .+send_message\(\{ name: /) expect(userTexts.slice(2)).toEqual([REARM, REARM_WAKE, EDITED_FOLLOWUP, WAKING]) const imageMessage = events.find(event => event.type === 'user/message' && event.data.content.some(block => block.type === 'image')) diff --git a/apps/web/tests/subagent-interrupt.e2e.ts b/apps/web/tests/subagent-interrupt.e2e.ts index 7a35bcfcb9..1b992547a2 100644 --- a/apps/web/tests/subagent-interrupt.e2e.ts +++ b/apps/web/tests/subagent-interrupt.e2e.ts @@ -108,7 +108,7 @@ describe.skipIf(MODE === 'record')('web e2e: subagents/interruptByParent over th const parent = scaffold.ctx.agents.get(parentId) if (parent === undefined) throw new Error('created parent session did not publish a live Agent') - const started = await scaffold.ctx.subagents.startActivation({ + const started = await scaffold.ctx.subagents.startActivation({ name: `child-${randomUUID()}`, delivery: 'parent', provider: 'spawn', label: 'event-sourcing researcher', @@ -189,7 +189,7 @@ describe.skipIf(MODE === 'record')('web e2e: subagents/interruptByParent over th ? event.data.content.flatMap(block => block.type === 'text' ? [block.text] : []) : []) expect(userTexts[0]).toBe(INITIAL) - expect(userTexts[1]).toMatch(/^Your parent agent id is .+send_message\(\{ agent_id: /) + expect(userTexts[1]).toMatch(/^Your name is .+Your parent agent name is .+send_message\(\{ name: /) expect(userTexts.slice(2)).toEqual([FOLLOWUP, WAKING]) const turnEndKinds = events .filter(event => event.type === 'turn/end') diff --git a/docs/config-catalog.md b/docs/config-catalog.md index 5b7ed380d6..ce2f2c9c63 100644 --- a/docs/config-catalog.md +++ b/docs/config-catalog.md @@ -1260,8 +1260,8 @@ export interface Config { ## `@deepseek-ai/dsh-experimental-tool-agent-team` -- `inject`: `agents` · `agentTeams` · `tools` · `systemPrompt` -- `source`: [`packages/experimental/tool-agent-team/src/index.ts:17`](../packages/experimental/tool-agent-team/src/index.ts) +- `inject`: `agents` · `agentTeams` · `subagents` · `tools` · `systemPrompt` +- `source`: [`packages/experimental/tool-agent-team/src/index.ts:18`](../packages/experimental/tool-agent-team/src/index.ts) ```ts config-catalog /** The Team tool plugin takes no configuration. */ @@ -2039,7 +2039,7 @@ export type PiAiThinkingTokenBudgetField = NonNullable + +#### `subagent/named` — log-only + +```ts persistence-catalog +/** + * A tree-wide agent name, retained after its execution ends. + * @param data - the name and durable child identity. + */ +'subagent/named': SubagentNameData +``` + +Source: [`packages/subagent/subagent/src/names.ts:26`](../packages/subagent/subagent/src/names.ts) + ### `system/*` @@ -2609,6 +2624,14 @@ SHA-256: `0a8a062bc9c3c0d97fd97742262f2ea53dd32297f834e81114870d38ac3dc6da` `"subagent/model-selection-policy"` + + +### `"subagent/named"` + +SHA-256: `fdca5e24e7a0bb1af1f3536b8c85787ca1dbca2802f632bf4a5347a2ba62fdb1` + +`"subagent/named"` + ### `"success"` @@ -4848,6 +4871,23 @@ One of: - [`ContinuableSubagentDescriptorData`](#persistence-type-sha256-6487b10ba7542f3c447b1e41a1c6a590b7bfafe0b9b66b49f34028da85bb970f) - [`OneShotSubagentDescriptorData`](#persistence-type-sha256-5f758f3de5f00c18968a7c6d347083aac5c9ae13f6a79c78f6611b23c4973564) + + + + + + +### `SubagentNameData` + +SHA-256: `b0b7b7f4d127101c49bfd0128e6f37c4627ebbc8baddf5b2e9edff1dac8c84b8` + +Sources: [`packages/subagent/subagent/src/names.ts:15`](../packages/subagent/subagent/src/names.ts) + +| Property | Presence | Type | +|---|---|---| +| `id` | required | `string` | +| `name` | required | `string` | + @@ -8679,6 +8719,22 @@ SHA-256: `a6567ccb2e530606b775371eb4fa31468d72084339968e8b0440a516a23b39dc` | `time` | required | `number` | | `type` | required | `"subagent/model-selection-policy"` | + + + + +### `{ type: "subagent/named" }` + +SHA-256: `273f07aea05d56ffbb8b43508bcfb4a20cce230819feadb3fe740bceb8b12ca6` + +| Property | Presence | Type | +|---|---|---| +| `data` | required | [`SubagentNameData`](#persistence-type-sha256-b0b7b7f4d127101c49bfd0128e6f37c4627ebbc8baddf5b2e9edff1dac8c84b8) | +| `ignorable` | optional | `true` | +| `seq` | required | `number` | +| `time` | required | `number` | +| `type` | required | `"subagent/named"` | + diff --git a/docs/persistence-catalog.zh.md b/docs/persistence-catalog.zh.md index aeffdcd496..e07c0ad810 100644 --- a/docs/persistence-catalog.zh.md +++ b/docs/persistence-catalog.zh.md @@ -66,6 +66,7 @@ | `event:subagent/catalog` | event | `53750b9abf61efb7992b0aadc3e247ec927449c63266df28230fd1139f5590ac` | [`{ type: "subagent/catalog" }`](#persistence-type-sha256-53750b9abf61efb7992b0aadc3e247ec927449c63266df28230fd1139f5590ac) | | `event:subagent/descriptor` | event | `b79ada42962cad0190a9d465805260567621fa3a4abd757eb31e6016b52d5ab5` | [`{ type: "subagent/descriptor" }`](#persistence-type-sha256-b79ada42962cad0190a9d465805260567621fa3a4abd757eb31e6016b52d5ab5) | | `event:subagent/model-selection-policy` | event | `a6567ccb2e530606b775371eb4fa31468d72084339968e8b0440a516a23b39dc` | [`{ type: "subagent/model-selection-policy" }`](#persistence-type-sha256-a6567ccb2e530606b775371eb4fa31468d72084339968e8b0440a516a23b39dc) | +| `event:subagent/named` | event | `273f07aea05d56ffbb8b43508bcfb4a20cce230819feadb3fe740bceb8b12ca6` | [`{ type: "subagent/named" }`](#persistence-type-sha256-273f07aea05d56ffbb8b43508bcfb4a20cce230819feadb3fe740bceb8b12ca6) | | `event:system/message` | event | `69081694be231d56fd9580ba14645fd5e35373202605d5c5c841a9435b5fa3b1` | [`{ type: "system/message" }`](#persistence-type-sha256-69081694be231d56fd9580ba14645fd5e35373202605d5c5c841a9435b5fa3b1) | | `event:team/member` | event | `4fb59762612c3e3ac3a3bd4f84c9c148d3c3893bd422ba2b201cc039fabd49bc` | [`{ type: "team/member" }`](#persistence-type-sha256-4fb59762612c3e3ac3a3bd4f84c9c148d3c3893bd422ba2b201cc039fabd49bc) | | `event:team/message/delivered` | event | `48f9c19417a1abbedfa59f4667bba36b93ac2db407adf5e84cb3ba0de30942cb` | [`{ type: "team/message/delivered" }`](#persistence-type-sha256-48f9c19417a1abbedfa59f4667bba36b93ac2db407adf5e84cb3ba0de30942cb) | @@ -978,6 +979,20 @@ export type SessionEvent = { 来源:[`packages/subagent/tool-subagent/src/model-selection-state.ts:17`](../packages/subagent/tool-subagent/src/model-selection-state.ts) + + +#### `subagent/named` — log-only + +```ts persistence-catalog +/** + * A tree-wide agent name, retained after its execution ends. + * @param data - the name and durable child identity. + */ +'subagent/named': SubagentNameData +``` + +来源:[`packages/subagent/subagent/src/names.ts:26`](../packages/subagent/subagent/src/names.ts) + ### `system/*` @@ -2611,6 +2626,14 @@ SHA-256: `0a8a062bc9c3c0d97fd97742262f2ea53dd32297f834e81114870d38ac3dc6da` `"subagent/model-selection-policy"` + + +### `"subagent/named"` + +SHA-256: `fdca5e24e7a0bb1af1f3536b8c85787ca1dbca2802f632bf4a5347a2ba62fdb1` + +`"subagent/named"` + ### `"success"` @@ -4850,6 +4873,23 @@ SHA-256: `86d1d0e9cfebb240421187e3dc37fb71cc38a1501885cf32f8f9adef7b0a2bde` - [`ContinuableSubagentDescriptorData`](#persistence-type-sha256-6487b10ba7542f3c447b1e41a1c6a590b7bfafe0b9b66b49f34028da85bb970f) - [`OneShotSubagentDescriptorData`](#persistence-type-sha256-5f758f3de5f00c18968a7c6d347083aac5c9ae13f6a79c78f6611b23c4973564) + + + + + + +### `SubagentNameData` + +SHA-256: `b0b7b7f4d127101c49bfd0128e6f37c4627ebbc8baddf5b2e9edff1dac8c84b8` + +来源:[`packages/subagent/subagent/src/names.ts:15`](../packages/subagent/subagent/src/names.ts) + +| 属性 | 存在性 | 类型 | +|---|---|---| +| `id` | 必需 | `string` | +| `name` | 必需 | `string` | + @@ -8681,6 +8721,22 @@ SHA-256: `a6567ccb2e530606b775371eb4fa31468d72084339968e8b0440a516a23b39dc` | `time` | 必需 | `number` | | `type` | 必需 | `"subagent/model-selection-policy"` | + + + + +### `{ type: "subagent/named" }` + +SHA-256: `273f07aea05d56ffbb8b43508bcfb4a20cce230819feadb3fe740bceb8b12ca6` + +| 属性 | 存在性 | 类型 | +|---|---|---| +| `data` | 必需 | [`SubagentNameData`](#persistence-type-sha256-b0b7b7f4d127101c49bfd0128e6f37c4627ebbc8baddf5b2e9edff1dac8c84b8) | +| `ignorable` | 可选 | `true` | +| `seq` | 必需 | `number` | +| `time` | 必需 | `number` | +| `type` | 必需 | `"subagent/named"` | + diff --git a/docs/persistence-changes/2026-10-16-tree-wide-agent-names.i18n.yaml b/docs/persistence-changes/2026-10-16-tree-wide-agent-names.i18n.yaml new file mode 100644 index 0000000000..ce87995972 --- /dev/null +++ b/docs/persistence-changes/2026-10-16-tree-wide-agent-names.i18n.yaml @@ -0,0 +1,28 @@ +# Bilingual-pair consistency record for 2026-10-16-tree-wide-agent-names.md (docs/i18n/README.md): per heading +# section, a hash of its English and Chinese blocks outside code blocks and generated regions. +# After editing either side, bring the other along and re-record with: +# pnpm run verify-translation-pairing --write docs/persistence-changes/2026-10-16-tree-wide-agent-names.md +/: + en: 3d5a424ae7d7e46b + zh: c22a8e4a62d8cc1a +/2026-10-16-tree-wide-agent-names: + en: a5bae46eec7e5c5b + zh: 190923c7b9b397d9 +/2026-10-16-tree-wide-agent-names/summary: + en: 3f16c8de27431ce8 + zh: d3db668518da7e37 +/2026-10-16-tree-wide-agent-names/table-of-contents: + en: 6cf314a069ceb451 + zh: 9adff678e9ecab3b +/2026-10-16-tree-wide-agent-names/declaration: + en: 6907136f28e48c90 + zh: 02f8298485f3d8e7 +/2026-10-16-tree-wide-agent-names/compatibility: + en: fbdcc4f1b829bb9c + zh: 2454c11be18019c7 +/2026-10-16-tree-wide-agent-names/verification: + en: 1b417eb5cdfa4ce6 + zh: ec3f2dfcddd16b25 +/2026-10-16-tree-wide-agent-names/dev-note: + en: b75c8458928b72b9 + zh: 003ba4e17b4b5269 diff --git a/docs/persistence-changes/2026-10-16-tree-wide-agent-names.md b/docs/persistence-changes/2026-10-16-tree-wide-agent-names.md new file mode 100644 index 0000000000..8c2afd21d0 --- /dev/null +++ b/docs/persistence-changes/2026-10-16-tree-wide-agent-names.md @@ -0,0 +1,48 @@ +--- +description: "Records a persistence type transition and its compatibility acknowledgement." +kind: persistence-change +--- + +# 2026-10-16-tree-wide-agent-names + +English | [中文](2026-10-16-tree-wide-agent-names.zh.md) + +## Summary + +Records immutable tree-wide agent names in the root Session. + +## Table of Contents + +- [Declaration](#declaration) +- [Compatibility](#compatibility) +- [Verification](#verification) +- [Dev Note](#dev-note) + + +## Declaration + +```yaml persistence-change +schemaVersion: 1 +id: 2026-10-16-tree-wide-agent-names +baseline: false +changes: + - root: "event:subagent/named" + previous: null + after: "273f07aea05d56ffbb8b43508bcfb4a20cce230819feadb3fe740bceb8b12ca6" + decision: same-version +``` + + +## Compatibility + +New readers accept older Sessions without assignments and expose stable legacy addresses. Older readers reject the new non-ignorable subagent/named discriminator instead of silently losing identity; existing catalog records and Session ids are unchanged. No writer format bump is needed. + + +## Verification + +The names.spec.ts and tool-team.spec.ts tests passed (33 cases); names.ts reached 100% statement, branch, function, and line coverage. Headless and TypeScript SDK replay exercised named creation, messages, discovery, and completion. + + +## Dev Note + +None. diff --git a/docs/persistence-changes/2026-10-16-tree-wide-agent-names.schema.json b/docs/persistence-changes/2026-10-16-tree-wide-agent-names.schema.json new file mode 100644 index 0000000000..80f2da85f3 --- /dev/null +++ b/docs/persistence-changes/2026-10-16-tree-wide-agent-names.schema.json @@ -0,0 +1,81 @@ +{ + "formatVersion": 2, + "roots": [ + { + "key": "event:subagent/named", + "kind": "event", + "event": "subagent/named", + "surface": false, + "digest": "273f07aea05d56ffbb8b43508bcfb4a20cce230819feadb3fe740bceb8b12ca6", + "schema": { + "root": 0, + "nodes": [ + { + "kind": "object", + "properties": [ + { + "name": "data", + "type": 1, + "optional": false + }, + { + "name": "ignorable", + "type": 3, + "optional": true + }, + { + "name": "seq", + "type": 4, + "optional": false + }, + { + "name": "time", + "type": 4, + "optional": false + }, + { + "name": "type", + "type": 5, + "optional": false + } + ], + "indices": [] + }, + { + "kind": "object", + "properties": [ + { + "name": "id", + "type": 2, + "optional": false + }, + { + "name": "name", + "type": 2, + "optional": false + } + ], + "indices": [] + }, + { + "kind": "primitive", + "type": "string" + }, + { + "kind": "literal", + "value": true + }, + { + "kind": "primitive", + "type": "number" + }, + { + "kind": "literal", + "value": "subagent/named" + } + ] + } + } + ], + "types": [] +} diff --git a/docs/persistence-changes/2026-10-16-tree-wide-agent-names.zh.md b/docs/persistence-changes/2026-10-16-tree-wide-agent-names.zh.md new file mode 100644 index 0000000000..a1154dc5a0 --- /dev/null +++ b/docs/persistence-changes/2026-10-16-tree-wide-agent-names.zh.md @@ -0,0 +1,48 @@ +--- +description: "记录持久化类型更改及其兼容性确认。" +kind: persistence-change +--- + +# 2026-10-16-tree-wide-agent-names + +[English](2026-10-16-tree-wide-agent-names.md) | 中文 + +## 概述 + +在根 Session 记录整棵树内唯一且不可变的 agent 名字。 + +## 目录 + +- [声明](#declaration) +- [兼容性](#compatibility) +- [验证](#verification) +- [开发备注](#dev-note) + + +## 声明 + +```yaml persistence-change +schemaVersion: 1 +id: 2026-10-16-tree-wide-agent-names +baseline: false +changes: + - root: "event:subagent/named" + previous: null + after: "273f07aea05d56ffbb8b43508bcfb4a20cce230819feadb3fe740bceb8b12ca6" + decision: same-version +``` + + +## 兼容性 + +新读取方接受没有名字分配的旧 Session,并公开稳定的旧地址。旧读取方拒绝新的非可忽略 subagent/named 判别值,避免静默丢失身份;现有目录记录与 Session id 不变。无需提升写入格式版本。 + + +## 验证 + +names.spec.ts 与 tool-team.spec.ts 的 33 个用例通过;names.ts 的语句、分支、函数与行覆盖率均为 100%。Headless 与 TypeScript SDK 回放覆盖按名字创建、消息、发现和完成通知。 + + +## 开发备注 + +无。 diff --git a/docs/persistence-changes/historical-formats/README.i18n.yaml b/docs/persistence-changes/historical-formats/README.i18n.yaml index e24f17e991..9c8279cc2b 100644 --- a/docs/persistence-changes/historical-formats/README.i18n.yaml +++ b/docs/persistence-changes/historical-formats/README.i18n.yaml @@ -15,8 +15,8 @@ en: 14c57f30e676f6e3 zh: b1a0ccf26fab3727 /session-persistence-formats/format-references: - en: 43a4a6600fa37a1a - zh: 72174fab8355c344 + en: 57e3fe7dd9e36b70 + zh: 2dac8a29964d982f /session-persistence-formats/scope-and-evidence: en: b220062139ddac1e zh: 7c4c0efe05dafa9c diff --git a/docs/persistence-changes/historical-formats/README.md b/docs/persistence-changes/historical-formats/README.md index 2bc0daa565..42fa40c74c 100644 --- a/docs/persistence-changes/historical-formats/README.md +++ b/docs/persistence-changes/historical-formats/README.md @@ -32,7 +32,7 @@ The index is generated from validated snapshots and the current writer constant. | 1 | PR #3349 | [V1](v1.md) | [JSON](v1.schema.json) | 54 / 415 | | 2 | `dsh-v0.1.3-alpha.2` | [V2](v2.md) | [JSON](v2.schema.json) | 56 / 435 | | 3 | PR #4320 | [V3](v3.md) | [JSON](v3.schema.json) | 60 / 467 | -| 4 | Current checkout | [Current catalog](../../persistence-catalog.md) | [JSON](../../persistence-schema.json) | 65 / 612 | +| 4 | Current checkout | [Current catalog](../../persistence-catalog.md) | [JSON](../../persistence-schema.json) | 66 / 615 | diff --git a/docs/persistence-changes/historical-formats/README.zh.md b/docs/persistence-changes/historical-formats/README.zh.md index 15b08f318d..fdcb780700 100644 --- a/docs/persistence-changes/historical-formats/README.zh.md +++ b/docs/persistence-changes/historical-formats/README.zh.md @@ -32,7 +32,7 @@ description: "查找从 V0 到工作区写入器版本的每个 Session 格式 | 1 | PR #3349 | [V1](v1.zh.md) | [JSON](v1.schema.json) | 54 / 415 | | 2 | `dsh-v0.1.3-alpha.2` | [V2](v2.zh.md) | [JSON](v2.schema.json) | 56 / 435 | | 3 | PR #4320 | [V3](v3.zh.md) | [JSON](v3.schema.json) | 60 / 467 | -| 4 | 当前工作树 | [当前目录](../../persistence-catalog.zh.md) | [JSON](../../persistence-schema.json) | 65 / 612 | +| 4 | 当前工作树 | [当前目录](../../persistence-catalog.zh.md) | [JSON](../../persistence-schema.json) | 66 / 615 | diff --git a/docs/persistence-schema.json b/docs/persistence-schema.json index 09652d65bd..63d1aa221d 100644 --- a/docs/persistence-schema.json +++ b/docs/persistence-schema.json @@ -15907,6 +15907,81 @@ ] } }, + { + "key": "event:subagent/named", + "kind": "event", + "event": "subagent/named", + "surface": false, + "digest": "273f07aea05d56ffbb8b43508bcfb4a20cce230819feadb3fe740bceb8b12ca6", + "schema": { + "root": 0, + "nodes": [ + { + "kind": "object", + "properties": [ + { + "name": "data", + "type": 1, + "optional": false + }, + { + "name": "ignorable", + "type": 3, + "optional": true + }, + { + "name": "seq", + "type": 4, + "optional": false + }, + { + "name": "time", + "type": 4, + "optional": false + }, + { + "name": "type", + "type": 5, + "optional": false + } + ], + "indices": [] + }, + { + "kind": "object", + "properties": [ + { + "name": "id", + "type": 2, + "optional": false + }, + { + "name": "name", + "type": 2, + "optional": false + } + ], + "indices": [] + }, + { + "kind": "primitive", + "type": "string" + }, + { + "kind": "literal", + "value": true + }, + { + "kind": "primitive", + "type": "number" + }, + { + "kind": "literal", + "value": "subagent/named" + } + ] + } + }, { "key": "event:system/message", "kind": "event", @@ -22996,6 +23071,11 @@ "names": [], "sources": [] }, + { + "digest": "273f07aea05d56ffbb8b43508bcfb4a20cce230819feadb3fe740bceb8b12ca6", + "names": [], + "sources": [] + }, { "digest": "2765e9119edf5816ac1ab4c95c5ee32c90403f3742962eff11544f7752d59d2e", "names": [], @@ -25071,6 +25151,15 @@ "packages/attachment/attachment/src/types.ts:11" ] }, + { + "digest": "b0b7b7f4d127101c49bfd0128e6f37c4627ebbc8baddf5b2e9edff1dac8c84b8", + "names": [ + "packages/subagent/subagent/src/names.ts#SubagentNameData" + ], + "sources": [ + "packages/subagent/subagent/src/names.ts:15" + ] + }, { "digest": "b158f3ff6923714807c0d73882f0b05dc87f8fa85c9e90814852d48bbc866081", "names": [ @@ -26117,6 +26206,11 @@ "names": [], "sources": [] }, + { + "digest": "fdca5e24e7a0bb1af1f3536b8c85787ca1dbca2802f632bf4a5347a2ba62fdb1", + "names": [], + "sources": [] + }, { "digest": "fe1a7acdeed4d0f5ab483396eaa5b3dc97263b7c10eb4da2f0028cb01728bfc9", "names": [], diff --git a/docs/subsystems/subagent.i18n.yaml b/docs/subsystems/subagent.i18n.yaml index 4a92a3473e..43a690ae52 100644 --- a/docs/subsystems/subagent.i18n.yaml +++ b/docs/subsystems/subagent.i18n.yaml @@ -26,3 +26,6 @@ /subagents/durable-enumeration-listchildren-listdescendants-and-their-entries: en: d8ce7969b65ad86e zh: d39dac6592681bf2 +/subagents/agent-names: + en: 934e8a775e67a697 + zh: df4c9f5d0f5c0171 diff --git a/docs/subsystems/subagent.md b/docs/subsystems/subagent.md index 21d3b167b1..1b164454d4 100644 --- a/docs/subsystems/subagent.md +++ b/docs/subsystems/subagent.md @@ -29,6 +29,8 @@ interface SubagentCapabilities { ```ts type-equiv /** One managed child execution and its result delivery policy. */ interface SubagentActivationSpec { + /** Immutable name, unique across the parent's whole subagent tree. */ + readonly name: string /** Registered backend to use. */ readonly provider: string /** Short task label retained in cataloged child membership. */ @@ -47,6 +49,8 @@ interface SubagentActivationSpec { ```ts type-equiv /** A managed execution; disposal addresses this exact activation, never a later resume. */ interface SubagentActivation { + /** Immutable name used by model-facing collaboration tools. */ + readonly name: string /** Stable identity of the child. */ readonly childId: SessionId /** Accepted inbox message, when the backend has a local inbox. */ @@ -392,6 +396,26 @@ type SubagentDescendantListEntry = SubagentListEntry & { +## Agent names + +Names are unique in one live subagent tree; the root is `lead`. The root Session owns immutable assignments and the projection excludes inherited facts. See the [naming rules](../../packages/subagent/subagent/README.md#local-and-external-children). + +```ts type-equiv +/** One immutable name assigned in the root Session before child publication. */ +interface SubagentNameData { + readonly name: string + readonly id: SessionId +} +``` + +```ts type-equiv +/** Root-owned name assignments, excluding fork-inherited events. */ +interface SubagentNamesState { + readonly inheritedEventCount: SessionLogOffset + readonly entries: readonly SubagentNameData[] +} +``` + @@ -444,6 +468,24 @@ startActivation(spec: SubagentActivationSpec & { readonly childId: SessionId }): */ startActivation(spec: SubagentActivationSpec): Promise +/** + * Read a model-facing name in the caller's tree, retaining legacy addresses for older unnamed children. + * @param caller - exact live Agent selecting the tree. + * @param id - target identity; omission selects the caller. + * @returns lead, the immutable assigned name, or a legacy address. + */ +nameOf(caller: Agent, id: SessionId = caller.id): string + +/** + * Resolve a tree-wide name without granting authority to act on its Agent. + * @param caller - exact live Agent selecting the tree. + * @param name - a name returned by creation or discovery. + * @param signal - cancellation during historical discovery. + * @returns the durable Session identity for the consuming operation to authorize. + * @throws when the name is absent or the caller's live tree is unavailable. + */ +resolveName(caller: Agent, name: string, signal?: AbortSignal): Promise + /** * Join progressing descendants without cancelling them. Idle descendants whose * inboxes require a later wake stay resident and do not delay host completion. diff --git a/docs/subsystems/subagent.zh.md b/docs/subsystems/subagent.zh.md index c33562e186..b1b5ac8fb7 100644 --- a/docs/subsystems/subagent.zh.md +++ b/docs/subsystems/subagent.zh.md @@ -29,6 +29,8 @@ interface SubagentCapabilities { ```ts type-equiv /** One managed child execution and its result delivery policy. */ interface SubagentActivationSpec { + /** Immutable name, unique across the parent's whole subagent tree. */ + readonly name: string /** Registered backend to use. */ readonly provider: string /** Short task label retained in cataloged child membership. */ @@ -47,6 +49,8 @@ interface SubagentActivationSpec { ```ts type-equiv /** A managed execution; disposal addresses this exact activation, never a later resume. */ interface SubagentActivation { + /** Immutable name used by model-facing collaboration tools. */ + readonly name: string /** Stable identity of the child. */ readonly childId: SessionId /** Accepted inbox message, when the backend has a local inbox. */ @@ -394,6 +398,26 @@ type SubagentDescendantListEntry = SubagentListEntry & { +## Agent 名字 + +名字在一棵在线子代理树内唯一;根名为 `lead`。根 Session 拥有不可变的名字分配,投影排除继承的事实。详见[命名规则](../../packages/subagent/subagent/README.zh.md#local-and-external-children)。 + +```ts type-equiv +/** One immutable name assigned in the root Session before child publication. */ +interface SubagentNameData { + readonly name: string + readonly id: SessionId +} +``` + +```ts type-equiv +/** Root-owned name assignments, excluding fork-inherited events. */ +interface SubagentNamesState { + readonly inheritedEventCount: SessionLogOffset + readonly entries: readonly SubagentNameData[] +} +``` + @@ -446,6 +470,24 @@ startActivation(spec: SubagentActivationSpec & { readonly childId: SessionId }): */ startActivation(spec: SubagentActivationSpec): Promise +/** + * Read a model-facing name in the caller's tree, retaining legacy addresses for older unnamed children. + * @param caller - exact live Agent selecting the tree. + * @param id - target identity; omission selects the caller. + * @returns lead, the immutable assigned name, or a legacy address. + */ +nameOf(caller: Agent, id: SessionId = caller.id): string + +/** + * Resolve a tree-wide name without granting authority to act on its Agent. + * @param caller - exact live Agent selecting the tree. + * @param name - a name returned by creation or discovery. + * @param signal - cancellation during historical discovery. + * @returns the durable Session identity for the consuming operation to authorize. + * @throws when the name is absent or the caller's live tree is unavailable. + */ +resolveName(caller: Agent, name: string, signal?: AbortSignal): Promise + /** * Join progressing descendants without cancelling them. Idle descendants whose * inboxes require a later wake stay resident and do not delay host completion. diff --git a/docs/tool-catalog.i18n.yaml b/docs/tool-catalog.i18n.yaml index 6391fcaf7f..17ee886d0f 100644 --- a/docs/tool-catalog.i18n.yaml +++ b/docs/tool-catalog.i18n.yaml @@ -9,8 +9,8 @@ en: 6cc2cd9ced70bb09 zh: 1c0e6cb4ba2ed637 /tool-schema-catalog/tool-package-map: - en: aff10b6cad96bfcb - zh: 800df4738667d1cc + en: b5a48ad99a91a27a + zh: b14ccf7ed0b503be /tool-schema-catalog/deepseek-ai-dsh-plugin-manager: en: e0143916bb634762 zh: e0143916bb634762 @@ -234,17 +234,17 @@ en: c89084b31ffccbce zh: d7b3b7000f2d2be9 /tool-schema-catalog/deepseek-ai-dsh-tool-subagent/subagent: - en: 9270966e03a2a62b - zh: 0544ac614aed3144 + en: c53129ca536b0d17 + zh: bbadc2251304388b /tool-schema-catalog/deepseek-ai-dsh-tool-subagent-control: en: ab82e130c3413f04 zh: ab82e130c3413f04 /tool-schema-catalog/deepseek-ai-dsh-tool-subagent-control/interrupt-agent: en: 9190a32df5e10ddd - zh: 48e1b05956d63e26 + zh: 6ece9cbd62eb4d8e /tool-schema-catalog/deepseek-ai-dsh-tool-subagent-control/list-agents: - en: b68f6c31d72980d1 - zh: 38be7bfea793043c + en: 6caa1abcb5ac1aaf + zh: f99f93111177da5f /tool-schema-catalog/deepseek-ai-dsh-tool-subagent-control/send-message: en: 69c1c0a80c24e3a4 zh: 8d3e8b8b1137e5c5 diff --git a/docs/tool-catalog.md b/docs/tool-catalog.md index 18914b13c3..60373cd81c 100644 --- a/docs/tool-catalog.md +++ b/docs/tool-catalog.md @@ -38,10 +38,10 @@ This table connects model-visible tool names to the plugin package and service s | `@deepseek-ai/dsh-tool-ralph` | `ralph` | `ctx.tools`, `ctx.workflowEngine`, `ctx.subagents`, `ctx.systemPrompt`, `a calling Agent (exec.agent parents every fresh round)` | `tool/call`, `tool/result`, `workflow and child session events during execution` | - | A fixed foreground workflow starts one fresh structured child per round; the model selects only the immutable objective and an optional round cap. | | `@deepseek-ai/dsh-tool-skill` | `skill` | `ctx.workingDirectory`, `ctx.tools`, `ctx.agents`, `ctx.skills` | `tool/call`, `tool/result`, `user/message replacement catalogs via agent.inject()` | - | - | | `@deepseek-ai/dsh-tool-session-query` | `session_event_read`, `session_event_search`, `session_event_trace`, `session_search`, `session_trace` | `ctx.tools`, `ctx.systemPrompt`, `ctx.sessionQuery`, `a calling Agent for workspace authority` | `tool/call`, `tool/result` | - | The five read-only tools hide provider cursors and authorize every result from the immutable calling agent session. The package is opt-in; compositions that need enforced deadlines or bounded inline output also mount the generic timeout or spill policies. | -| `@deepseek-ai/dsh-tool-subagent` | `list_subagent_models`, `subagent` | `ctx.tools`, `ctx.subagents`, `ctx.systemPrompt`, `ctx.llm for model discovery and selected-route validation` | `tool/call`, `tool/result`, `child session events through the chosen provider` | `subagent`, `subagent_fork` | The registered delegation name is the load-time `toolName` config (default `subagent`); the default schema above has model selection off, while the discovery schema is shown as the fixed companion available in an enabled Session. Web presets sample the Plugins preference for each new top-level Session and preserve that decision for its child Sessions; `subagent_fork` remains fixed-route. Each instance selects its backend through `provider` and reads model-selection settings through `modelSelectionSettings`. Every delegation returns a child id promptly; local children accept follow-ups, while external backends report their single execution automatically. | +| `@deepseek-ai/dsh-tool-subagent` | `list_subagent_models`, `subagent` | `ctx.tools`, `ctx.subagents`, `ctx.systemPrompt`, `ctx.llm for model discovery and selected-route validation` | `tool/call`, `tool/result`, `child session events through the chosen provider` | `subagent`, `subagent_fork` | The registered delegation name is the load-time `toolName` config (default `subagent`); the default schema above has model selection off, while the discovery schema is shown as the fixed companion available in an enabled Session. Web presets sample the Plugins preference for each new top-level Session and preserve that decision for its child Sessions; `subagent_fork` remains fixed-route. Each instance selects its backend through `provider` and reads model-selection settings through `modelSelectionSettings`. Every delegation returns a unique agent name promptly; local children accept follow-ups, while external backends report their single execution automatically. | | `@deepseek-ai/dsh-tool-subagent-control` | `interrupt_agent`, `list_agents`, `send_message` | `ctx.tools`, `ctx.subagents`, `ctx.agents and ctx.sessionProjections (list_agents only)` | `tool/call`, `tool/result`, `child session events through ctx.subagents` | - | The globally named discovery, interruption, and local-message tools over managed subagents: provider-bound `tool-subagent` instances register distinct delegation tools, while this package registers `send_message` and `interrupt_agent` once, plus `list_agents` from its separately loaded `/list-agents` plugin (whose catalog rows use the sessionProjections and live Agent registries). | | `@deepseek-ai/dsh-tool-jobs` | `job_kill`, `job_list`, `job_output` | `ctx.tools`, `ctx.jobs`, `ctx.systemPrompt` | `tool/call`, `tool/result`, `user/message via agent.inject() for background completion notices` | - | The kind-agnostic background-job controller: background bash commands and PTY sends are read, listed, and killed through the same three tools. Loading the plugin attaches the controller that arms producers' `ctx.jobs.start()`. | -| `@deepseek-ai/dsh-experimental-tool-agent-team` | `team_task_create`, `team_task_get`, `team_task_list`, `team_task_update`, `wait_agent` | `ctx.tools`, `ctx.systemPrompt`, `ctx.agentTeams`, `an exact live Team member Agent` | `tool/call`, `team/task`, `tool/result` | - | Five task-board and wait tools are scoped to the Lead and its live subagents. The optional Agent Teams profile adds this package while retaining the standard subagent delegation and control tools. | +| `@deepseek-ai/dsh-experimental-tool-agent-team` | `team_task_create`, `team_task_get`, `team_task_list`, `team_task_update`, `wait_agent` | `ctx.tools`, `ctx.systemPrompt`, `ctx.agentTeams`, `ctx.subagents`, `an exact live Team member Agent` | `tool/call`, `team/task`, `tool/result` | - | Five task-board and wait tools are scoped to the Lead and its live subagents. The optional Agent Teams profile adds this package while retaining the standard subagent delegation and control tools. | | `@deepseek-ai/dsh-tool-todo` | `todo_write` | `ctx.tools`, `owning Agent session` | `tool/call`, `todo/write`, `tool/result` | - | todo_write is session-owned state; UIs render the latest todo/write event as a checklist. `allowParallelInProgress` is required with no default, so the catalog states its choice: `true`, whose description invites several `in_progress` items. A deployment choosing `false` receives the same tool with a description asking for exactly one active task. | | `@deepseek-ai/dsh-tool-working-directory` | `working_directory` | `ctx.tools`, `ctx.workingDirectory` | `tool/call`, `working-directory/change`, `user context for directory changes`, `tool/result` | - | Reads or changes the calling Session directory. Existing shells and processes retain their own directories; origin metadata and permission roots stay fixed. | | `@deepseek-ai/dsh-experimental-tool-worktree` | `create_worktree` | `ctx.tools`, `ctx.worktrees`, `a calling Agent` | `tool/call`, `Git branch and checkout`, `working-directory/change`, `tool/result` | - | Explicit experimental composition only. Creates a new branch and checkout from a pinned local commit under existing write permissions, then changes the Session directory. Leaving retains the branch and checkout. | @@ -2090,12 +2090,16 @@ Source: [`packages/subagent/tool-subagent/src/list-models.ts`](../packages/subag ### `subagent` -Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. +Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. ```json { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -2110,6 +2114,7 @@ Delegate a self-contained task to a subagent (a separate agent that works in its } }, "required": [ + "name", "description", "prompt" ] @@ -2118,7 +2123,7 @@ Delegate a self-contained task to a subagent (a separate agent that works in its Source: [`packages/subagent/tool-subagent/src/index.ts`](../packages/subagent/tool-subagent/src/index.ts) -The registered delegation name is the load-time `toolName` config (default `subagent`); the default schema above has model selection off, while the discovery schema is shown as the fixed companion available in an enabled Session. Web presets sample the Plugins preference for each new top-level Session and preserve that decision for its child Sessions; `subagent_fork` remains fixed-route. Each instance selects its backend through `provider` and reads model-selection settings through `modelSelectionSettings`. Every delegation returns a child id promptly; local children accept follow-ups, while external backends report their single execution automatically. +The registered delegation name is the load-time `toolName` config (default `subagent`); the default schema above has model selection off, while the discovery schema is shown as the fixed companion available in an enabled Session. Web presets sample the Plugins preference for each new top-level Session and preserve that decision for its child Sessions; `subagent_fork` remains fixed-route. Each instance selects its backend through `provider` and reads model-selection settings through `modelSelectionSettings`. Every delegation returns a unique agent name promptly; local children accept follow-ups, while external backends report their single execution automatically. @@ -2132,13 +2137,13 @@ Ask a subagent to stop its current work. This call returns without waiting for i { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } ``` @@ -2147,7 +2152,7 @@ Source: [`packages/subagent/tool-subagent-control/src/index.ts`](../packages/sub ### `list_agents` -List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation. +List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation. ```json { @@ -2166,9 +2171,9 @@ Send a message to an agent. A working agent receives it at its next step; an idl { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -2176,7 +2181,7 @@ Send a message to an agent. A working agent receives it at its next step; an idl } }, "required": [ - "agent_id", + "name", "message" ] } @@ -2343,7 +2348,7 @@ List shared tasks, including readiness, owner, revision, blockers, and write-sco }, "owner": { "type": "string", - "description": "Optional exact ownerId filter; use unowned for tasks without an owner." + "description": "Optional exact ownerName filter; use unowned for tasks without an owner." }, "ready": { "type": "boolean", @@ -2417,7 +2422,7 @@ Compare-and-set a shared task action using the latest revision from team_task_ge }, "owner": { "type": "string", - "description": "Agent id of the Lead or one of its direct continuable children for Lead-only reassign; omit to unassign." + "description": "Agent name of the Lead or one of its direct continuable children for Lead-only reassign; omit to unassign." } }, "required": [ diff --git a/docs/tool-catalog.zh.md b/docs/tool-catalog.zh.md index 1c76491da8..2aed3a2b9c 100644 --- a/docs/tool-catalog.zh.md +++ b/docs/tool-catalog.zh.md @@ -42,10 +42,10 @@ | `@deepseek-ai/dsh-tool-ralph` | `ralph` | `ctx.tools`、`ctx.workflowEngine`、`ctx.subagents`、`ctx.systemPrompt`、`a calling Agent (exec.agent parents every fresh round)` | `tool/call`、`tool/result`、`workflow and child session events during execution` | - | 固定的前台工作流会在每个 Round 启动一个全新的结构化子级;模型只能选择不可变目标和可选的 Round 上限。 | | `@deepseek-ai/dsh-tool-skill` | `skill` | `ctx.workingDirectory`、`ctx.tools`、`ctx.agents`、`ctx.skills` | `tool/call`、`tool/result`、`user/message replacement catalogs via agent.inject()` | - | - | | `@deepseek-ai/dsh-tool-session-query` | `session_event_read`、`session_event_search`、`session_event_trace`、`session_search`、`session_trace` | `ctx.tools`、`ctx.systemPrompt`、`ctx.sessionQuery`、`a calling Agent for workspace authority` | `tool/call`、`tool/result` | - | 这 5 个只读工具会隐藏提供方游标,并根据不可变的调用 agent 会话为每个结果授权。该包需要选择启用;需要强制截止时间或限制行内输出的组合还会挂载通用超时或 spill 策略。 | -| `@deepseek-ai/dsh-tool-subagent` | `list_subagent_models`、`subagent` | `ctx.tools`、`ctx.subagents`、`ctx.systemPrompt`、`用于模型发现和所选路由校验的 ctx.llm` | `tool/call`、`tool/result`、`child session events through the chosen provider` | `subagent`、`subagent_fork` | 注册的委派工具名称取决于加载时 `toolName` 配置(默认为 `subagent`);上述默认 schema 关闭模型选择,而发现 schema 则展示为已启用 Session 中可用的固定配套工具。Web preset 会在每个新顶层 Session 创建时读取插件页偏好,并为其子 Session 保留该决定;`subagent_fork` 始终使用固定路由。每个实例通过 `provider` 选择后端,通过 `modelSelectionSettings` 读取模型选择设置。每次委派都会立即返回子代理 id;本地子代理接受后续消息,外部后端自动汇报单次执行结果。 | +| `@deepseek-ai/dsh-tool-subagent` | `list_subagent_models`、`subagent` | `ctx.tools`、`ctx.subagents`、`ctx.systemPrompt`、`用于模型发现和所选路由校验的 ctx.llm` | `tool/call`、`tool/result`、`child session events through the chosen provider` | `subagent`、`subagent_fork` | 注册的委派工具名称取决于加载时 `toolName` 配置(默认为 `subagent`);上述默认 schema 关闭模型选择,而发现 schema 则展示为已启用 Session 中可用的固定配套工具。Web preset 会在每个新顶层 Session 创建时读取插件页偏好,并为其子 Session 保留该决定;`subagent_fork` 始终使用固定路由。每个实例通过 `provider` 选择后端,通过 `modelSelectionSettings` 读取模型选择设置。每次委派都会立即返回唯一 agent 名字;本地子代理接受后续消息,外部后端自动汇报单次执行结果。 | | `@deepseek-ai/dsh-tool-subagent-control` | `interrupt_agent`、`list_agents`、`send_message` | `ctx.tools`、`ctx.subagents`、`ctx.agents and ctx.sessionProjections (list_agents only)` | `tool/call`、`tool/result`、`child session events through ctx.subagents` | - | 这些是用于发现、中断托管 subagent 和向本地子代理发送消息的全局命名工具:绑定提供方的 `tool-subagent` 实例注册不同的委派工具;本包注册一次 `send_message` 和 `interrupt_agent`,另由 `list_agents` 通过单独加载的 `/list-agents` 插件提供,其目录行使用 sessionProjections 和实时 Agent 注册表。 | | `@deepseek-ai/dsh-tool-jobs` | `job_kill`、`job_list`、`job_output` | `ctx.tools`、`ctx.jobs`、`ctx.systemPrompt` | `tool/call`、`tool/result`、`user/message via agent.inject() for background completion notices` | - | 与任务种类无关的后台任务控制器:后台 bash 命令与 PTY 发送 都通过相同的 3 个工具读取、列出和终止。加载该插件会挂接控制器,从而启用生产方的 `ctx.jobs.start()`。 | -| `@deepseek-ai/dsh-experimental-tool-agent-team` | `team_task_create`, `team_task_get`, `team_task_list`, `team_task_update`, `wait_agent` | `ctx.tools`, `ctx.systemPrompt`, `ctx.agentTeams`, `an exact live Team member Agent` | `tool/call`, `team/task`, `tool/result` | - | 五个任务板和等待工具作用于 Lead 及其在线子代理。可选 Agent Teams profile 增加本包,同时保留标准子代理委派和控制工具。 | +| `@deepseek-ai/dsh-experimental-tool-agent-team` | `team_task_create`, `team_task_get`, `team_task_list`, `team_task_update`, `wait_agent` | `ctx.tools`, `ctx.systemPrompt`, `ctx.agentTeams`, `ctx.subagents`, `an exact live Team member Agent` | `tool/call`, `team/task`, `tool/result` | - | 五个任务板和等待工具作用于 Lead 及其在线子代理。可选 Agent Teams profile 增加本包,同时保留标准子代理委派和控制工具。 | | `@deepseek-ai/dsh-tool-todo` | `todo_write` | `ctx.tools`、`owning Agent session` | `tool/call`、`todo/write`、`tool/result` | - | todo_write 是会话所有的状态;UI 将最新的 todo/write 事件渲染为检查清单。`allowParallelInProgress` 是没有默认值的必填项,因此本目录明确选择 `true`,对应描述允许同时存在多个 `in_progress` 项。选择 `false` 的部署会获得同一工具,但描述会要求只能有 1 个活动任务。 | | `@deepseek-ai/dsh-tool-working-directory` | `working_directory` | `ctx.tools`, `ctx.workingDirectory` | `tool/call`, `working-directory/change`, `user context for directory changes`, `tool/result` | - | 读取或改变调用方 Session 的目录。已有 shell 和进程保留自己的目录;原始元数据和权限根目录保持不变。 | | `@deepseek-ai/dsh-experimental-tool-worktree` | `create_worktree` | `ctx.tools`, `ctx.worktrees`, `a calling Agent` | `tool/call`, `Git branch and checkout`, `working-directory/change`, `tool/result` | - | 仅通过显式实验组合加载。在现有写权限下从固定的本地提交创建新分支与检出目录,再改变 Session 工作目录。离开时保留分支与检出目录。 | @@ -2096,12 +2096,16 @@ lsp 工具将提供方选择和语言服务器子进程置于 ctx.lsp 之后, ### `subagent` -将一项自包含任务委派给 subagent(在自身上下文中工作的独立 agent),用它卸载聚焦且独立的工作,例如研究、限定范围的实现或分析,以免消耗当前对话的上下文。subagent 会返回结果,但不会返回中间步骤。请提供完整、独立的提示词,因为它看不到当前对话。此工具启动独立管理的 subagent 并立即返回其 id。运行时会在任务结束时通知你。子代理通过 `send_message` 汇报结果;你可以使用 `send_message` 在运行时引导它,或在结束后继续对话。 +将一项自包含任务委派给 subagent(在自身上下文中工作的独立 agent),用它卸载聚焦且独立的工作,例如研究、限定范围的实现或分析,以免消耗当前对话的上下文。subagent 会返回结果,但不会返回中间步骤。请提供完整、独立的提示词,因为它看不到当前对话。此工具启动独立管理的 subagent 并立即返回其名字。运行时会在任务结束时通知你。子代理通过 `send_message` 汇报结果;你可以使用 `send_message` 在运行时引导它,或在结束后继续对话。 ```json { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -2116,6 +2120,7 @@ lsp 工具将提供方选择和语言服务器子进程置于 ctx.lsp 之后, } }, "required": [ + "name", "description", "prompt" ] @@ -2124,7 +2129,7 @@ lsp 工具将提供方选择和语言服务器子进程置于 ctx.lsp 之后, 来源:[`packages/subagent/tool-subagent/src/index.ts`](../packages/subagent/tool-subagent/src/index.ts) -注册的委派工具名称取决于加载时 `toolName` 配置(默认为 `subagent`);上述默认 schema 关闭模型选择,而发现 schema 则展示为已启用 Session 中可用的固定配套工具。Web preset 会在每个新顶层 Session 创建时读取插件页偏好,并为其子 Session 保留该决定;`subagent_fork` 始终使用固定路由。每个实例通过 `provider` 选择后端,通过 `modelSelectionSettings` 读取模型选择设置。每次委派都会立即返回子代理 id;本地子代理接受后续消息,外部后端自动汇报单次执行结果。 +注册的委派工具名称取决于加载时 `toolName` 配置(默认为 `subagent`);上述默认 schema 关闭模型选择,而发现 schema 则展示为已启用 Session 中可用的固定配套工具。Web preset 会在每个新顶层 Session 创建时读取插件页偏好,并为其子 Session 保留该决定;`subagent_fork` 始终使用固定路由。每个实例通过 `provider` 选择后端,通过 `modelSelectionSettings` 读取模型选择设置。每次委派都会立即返回唯一 agent 名字;本地子代理接受后续消息,外部后端自动汇报单次执行结果。 @@ -2132,19 +2137,19 @@ lsp 工具将提供方选择和语言服务器子进程置于 ctx.lsp 之后, ### `interrupt_agent` -根据 agent id 请求取消后台 agent 的当前轮次。目标可以是你的直接子级,也可以是在你下方创建的更深层 agent。对于本地 agent,只有当前轮次会停止:已经排队发给该 agent 的消息会一直搁置到后续的 send_message;它启动的 agent 会继续运行;该 agent 本身仍可接受后续操作。外部执行会永久停止,无法接收后续消息。停止请求被接受后,此调用立即返回,因此目标可能还会短暂运行;中断一个已经完成的 agent 是可接受的空操作。 +根据 agent 名字请求取消后台 agent 的当前轮次。目标可以是你的直接子级,也可以是在你下方创建的更深层 agent。对于本地 agent,只有当前轮次会停止:已经排队发给该 agent 的消息会一直搁置到后续的 send_message;它启动的 agent 会继续运行;该 agent 本身仍可接受后续操作。外部执行会永久停止,无法接收后续消息。停止请求被接受后,此调用立即返回,因此目标可能还会短暂运行;中断一个已经完成的 agent 是可接受的空操作。 ```json { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } ``` @@ -2153,7 +2158,7 @@ lsp 工具将提供方选择和语言服务器子进程置于 ctx.lsp 之后, ### `list_agents` -列出全部可达的可继续后代;如果调用方是可继续子代理,还列出父代理和可继续同级。行包含 id、描述和状态;后代行还包含父级 id 和深度。可以向父代理、可继续同级和直接子级发送消息,更深后代只接受 interrupt_agent。running 表示正在工作;inactive 表示当前没有工作。直属子代理结束时会收到通知,无需反复查询其状态。使用 send_message 继续对话。 +列出全部可达的可继续后代;如果调用方是可继续子代理,还列出父代理和可继续同级。行包含名字、描述和状态;后代行还包含父级名字和深度。可以向父代理、可继续同级和直接子级发送消息,更深后代只接受 interrupt_agent。running 表示正在工作;inactive 表示当前没有工作。直属子代理结束时会收到通知,无需反复查询其状态。使用 send_message 继续对话。 ```json { @@ -2172,9 +2177,9 @@ lsp 工具将提供方选择和语言服务器子进程置于 ctx.lsp 之后, { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -2182,7 +2187,7 @@ lsp 工具将提供方选择和语言服务器子进程置于 ctx.lsp 之后, } }, "required": [ - "agent_id", + "name", "message" ] } @@ -2349,7 +2354,7 @@ lsp 工具将提供方选择和语言服务器子进程置于 ctx.lsp 之后, }, "owner": { "type": "string", - "description": "Optional exact ownerId filter; use unowned for tasks without an owner." + "description": "Optional exact ownerName filter; use unowned for tasks without an owner." }, "ready": { "type": "boolean", @@ -2423,7 +2428,7 @@ lsp 工具将提供方选择和语言服务器子进程置于 ctx.lsp 之后, }, "owner": { "type": "string", - "description": "Agent id of the Lead or one of its direct continuable children for Lead-only reassign; omit to unassign." + "description": "Agent name of the Lead or one of its direct continuable children for Lead-only reassign; omit to unassign." } }, "required": [ diff --git a/docs/upgrade-guide/v0.2.1-alpha.4/agent-team-subagents/guide.i18n.yaml b/docs/upgrade-guide/v0.2.1-alpha.4/agent-team-subagents/guide.i18n.yaml index 867a0c0505..fd94f27e4b 100644 --- a/docs/upgrade-guide/v0.2.1-alpha.4/agent-team-subagents/guide.i18n.yaml +++ b/docs/upgrade-guide/v0.2.1-alpha.4/agent-team-subagents/guide.i18n.yaml @@ -3,14 +3,14 @@ # After editing either side, bring the other along and re-record with: # pnpm run verify-translation-pairing --write docs/upgrade-guide/v0.2.1-alpha.4/agent-team-subagents/guide.md /: - en: 1f073189776760d8 - zh: cfbb0403aea96f84 -/agent-teams-uses-subagents-and-session-ids: - en: a6aba40e910d4ecb - zh: 11881b6e9d8228d9 -/agent-teams-uses-subagents-and-session-ids/change: - en: 208add38ac8dc327 - zh: c34fce9b2a978e5f -/agent-teams-uses-subagents-and-session-ids/migration: - en: 0ed5e22412074192 - zh: 60deae7d46a21c75 + en: 9a266a4f19673f89 + zh: 0b716c060f3e568d +/agent-teams-uses-subagents-and-unique-agent-names: + en: e2fd55138832d6e1 + zh: 5fc33b77673c6ea0 +/agent-teams-uses-subagents-and-unique-agent-names/change: + en: 955ec629b091e254 + zh: 219985a87010acca +/agent-teams-uses-subagents-and-unique-agent-names/migration: + en: b971e8801c9b5590 + zh: a3656d78aad1a5c1 diff --git a/docs/upgrade-guide/v0.2.1-alpha.4/agent-team-subagents/guide.md b/docs/upgrade-guide/v0.2.1-alpha.4/agent-team-subagents/guide.md index 70d6e7ead2..13965e1468 100644 --- a/docs/upgrade-guide/v0.2.1-alpha.4/agent-team-subagents/guide.md +++ b/docs/upgrade-guide/v0.2.1-alpha.4/agent-team-subagents/guide.md @@ -1,27 +1,27 @@ --- kind: upgrade-guide -description: "Agent Teams uses the standard subagent tools and Session ids; Team-specific creation, messaging, listing, interruption, and their configuration keys are removed." +description: "Agent Teams uses the standard subagent tools and unique agent names; Team-specific creation, messaging, listing, interruption, and their configuration keys are removed." --- -# Agent Teams uses subagents and Session ids +# Agent Teams uses subagents and unique agent names English | [中文](guide.zh.md) ## Change -The experimental Agent Teams plugins share agent creation, discovery, messaging, and interruption with subagents. Start a teammate with `subagent` or `subagent_fork`, describe its responsibility with `description`, and use its returned agent id for messages and task assignment. Descriptions may repeat and never identify a recipient. +The experimental Agent Teams plugins share agent creation, discovery, messaging, and interruption with subagents. Start a teammate with `subagent` or `subagent_fork`, give it a tree-wide unique `name`, describe its responsibility with `description`, and use its returned name for messages and task assignment. Descriptions may repeat and never identify a recipient. -- `spawn_teammate` and the Team-scoped `send_message`, `list_agents`, and `interrupt_agent` are removed. The standard control tools use `agent_id`, not `target`. Continuable children of one live parent can message each other by id. +- `spawn_teammate` and the Team-scoped `send_message`, `list_agents`, and `interrupt_agent` are removed. The standard control tools use `name`, not `agent_id` or `target`. Continuable children of one live parent can message each other by name. - `list_agents` takes no arguments and always lists all reachable continuable descendants, plus a continuable caller’s live parent and siblings. Remove the `scope` argument from scripted calls. Listing deeper descendants does not grant messaging or task-assignment authority. - The Team profile no longer disables the subagent tools. Team adds only task tools, `wait_agent`, and collaboration guidance. - `agent-team` rejects `maxMembers`, `maxMessageBytes`, and `disposalTimeoutMs`; `tool-agent-team` rejects `interrupt`, `freshProvider`, and `forkProvider`. -- `ctx.agentTeams` removes `spawnTeammate()`, `sendMessage()`, `interrupt()`, and `listMembers()`. Task views expose `ownerId` instead of `ownerName`; task ownership uses Session ids, including the Lead's id. -- Historical Team roster and mailbox records remain readable. Names in those records are historical data and do not resolve message recipients or task owners. Subagent catalog payloads are unchanged. +- `ctx.agentTeams` removes `spawnTeammate()`, `sendMessage()`, `interrupt()`, and `listMembers()`. Host task views retain `ownerId` Session identities; model-facing task results expose `ownerName`, and task `owner` arguments use names. The root agent is always `lead`. +- Historical Team roster and mailbox records remain readable. Names in those records are historical data and do not resolve message recipients or task owners. Subagent catalog payloads are unchanged. New names are recorded in the root Session and remain reserved after settlement; older unnamed children receive `legacy:` addresses during discovery. ## Migration 1. Remove the obsolete configuration keys and any patch rows that disable subagent tools solely for Team support. -2. Replace `spawn_teammate({ name, description, prompt, context })` with `subagent({ description, prompt })`, or `subagent_fork` for inherited conversation history. Save the returned agent id. -3. Use `send_message({ agent_id, message })` and `interrupt_agent({ agent_id })`. Discover parent and sibling ids with `list_agents`. -4. Pass member Session ids to task `owner` fields and read `ownerId` in results. Use the Lead's Session id instead of the alias `lead`. -5. Replace removed service calls with `ctx.subagents.startActivation()`, `sendMessage()`, `interrupt()`, and `listChildren()`. Start a Team-enabled profile and verify that a child's description appears in the Team panel and that an id-addressed message reaches it. +2. Replace `spawn_teammate({ name, description, prompt, context })` with `subagent({ name, description, prompt })`, or `subagent_fork` for inherited conversation history. Choose a unique lower-case name with letters, digits, underscores, or hyphens; start with a letter. `lead` and `unowned` are reserved. Duplicate names fail before creation. +3. Use `send_message({ name, message })` and `interrupt_agent({ name })`. Discover parent and sibling names with `list_agents`. +4. Pass member names to task `owner` fields and read `ownerName` in tool results. Use `lead` for the root agent. +5. Replace removed service calls with `ctx.subagents.startActivation()`, `sendMessage()`, `interrupt()`, and `listChildren()`. Supply `name` to `startActivation()`; host control APIs still use Session ids. Start a Team-enabled profile and verify that a child's description appears in the Team panel and that a name-addressed message reaches it. diff --git a/docs/upgrade-guide/v0.2.1-alpha.4/agent-team-subagents/guide.zh.md b/docs/upgrade-guide/v0.2.1-alpha.4/agent-team-subagents/guide.zh.md index 01ca6ec858..2b99211444 100644 --- a/docs/upgrade-guide/v0.2.1-alpha.4/agent-team-subagents/guide.zh.md +++ b/docs/upgrade-guide/v0.2.1-alpha.4/agent-team-subagents/guide.zh.md @@ -1,27 +1,27 @@ --- kind: upgrade-guide -description: "Agent Teams 使用标准 subagent 工具和 Session id;移除 Team 专属创建、消息、列举、中断操作及其配置键。" +description: "Agent Teams 使用标准 subagent 工具与唯一 agent 名字;Team 专用创建、消息、列表、中断工具及其配置键被移除。" --- -# Agent Teams 使用子代理和 Session id +# Agent Teams 使用 subagent 与唯一 agent 名字 [English](guide.md) | 中文 ## 变更 -实验性 Agent Teams 插件与 subagent 共用代理创建、发现、消息和中断能力。使用 `subagent` 或 `subagent_fork` 创建队友,以 `description` 描述职责,并用返回的 agent id 发送消息和分配任务。描述可以重复,不能作为收件人标识。 +实验性 Agent Teams 插件与 subagent 共享创建、发现、消息与中断。使用 `subagent` 或 `subagent_fork` 启动队友,为其指定树内唯一的 `name`,用 `description` 描述职责,并以返回的名字发送消息和分配任务。描述可以重复,不标识接收方。 -- 移除 `spawn_teammate` 以及 Team 作用域的 `send_message`、`list_agents` 和 `interrupt_agent`。标准控制工具使用 `agent_id` 而非 `target`。同一个在线父代理的可继续子代理可以通过 id 互发消息。 -- `list_agents` 不接收参数,始终列出全部可达的可继续后代,以及可继续调用方的在线父级和同级。从脚本调用中移除 `scope` 参数。列出更深后代不会授予消息或任务指派权限。 -- Team profile 不再禁用 subagent 工具。Team 只增加任务工具、`wait_agent` 和协作提示。 -- `agent-team` 拒绝 `maxMembers`、`maxMessageBytes` 和 `disposalTimeoutMs`;`tool-agent-team` 拒绝 `interrupt`、`freshProvider` 和 `forkProvider`。 -- `ctx.agentTeams` 移除 `spawnTeammate()`、`sendMessage()`、`interrupt()` 和 `listMembers()`。任务视图以 `ownerId` 取代 `ownerName`;包括 Lead 在内,任务所有者均使用 Session id。 -- 历史 Team 名册和邮箱记录仍可读取。其中的名字仅作为历史数据,不用于解析消息收件人或任务所有者。Subagent catalog 载荷不变。 +- `spawn_teammate` 及 Team 作用域的 `send_message`、`list_agents`、`interrupt_agent` 被移除。标准控制工具使用 `name`,而非 `agent_id` 或 `target`。同一在线父级的可继续子级可以按名字互发消息。 +- `list_agents` 不接受参数,始终列出所有可达的可继续后代,以及可继续调用方的在线父级和同级。脚本调用需移除 `scope` 参数。列出更深后代不授予消息或任务分配权限。 +- Team profile 不再禁用 subagent 工具。Team 只增加任务工具、`wait_agent` 和协作指引。 +- `agent-team` 拒绝 `maxMembers`、`maxMessageBytes` 与 `disposalTimeoutMs`;`tool-agent-team` 拒绝 `interrupt`、`freshProvider` 与 `forkProvider`。 +- `ctx.agentTeams` 移除 `spawnTeammate()`、`sendMessage()`、`interrupt()` 与 `listMembers()`。宿主任务视图保留 `ownerId` Session 身份;面向模型的任务结果公开 `ownerName`,任务 `owner` 参数使用名字。根 agent 始终名为 `lead`。 +- 历史 Team 成员列表和邮箱记录仍可读取。其中的名字属于历史数据,不解析消息接收方或任务负责人。subagent 目录载荷不变。新名字记录在根 Session 中,执行结束后仍被占用;旧的无名子级在发现时获得 `legacy:` 地址。 ## 迁移 -1. 删除废弃配置键,以及仅为支持 Team 而禁用 subagent 工具的 patch 行。 -2. 将 `spawn_teammate({ name, description, prompt, context })` 替换为 `subagent({ description, prompt })`;继承对话历史时使用 `subagent_fork`。保存返回的 agent id。 -3. 使用 `send_message({ agent_id, message })` 和 `interrupt_agent({ agent_id })`。通过 `list_agents` 查询父代理和兄弟代理的 id。 -4. 任务的 `owner` 字段传入成员 Session id,结果读取 `ownerId`。以 Lead 的 Session id 取代 `lead` 别名。 -5. 将已移除的服务调用替换为 `ctx.subagents.startActivation()`、`sendMessage()`、`interrupt()` 和 `listChildren()`。启动启用 Team 的 profile,确认面板显示子代理描述,且通过 id 发送的消息到达该子代理。 +1. 移除废弃配置键,以及仅为 Team 支持而禁用 subagent 工具的 patch 行。 +2. 将 `spawn_teammate({ name, description, prompt, context })` 改为 `subagent({ name, description, prompt })`,需要继承会话历史时使用 `subagent_fork`。选择唯一的小写名字,只含字母、数字、下划线或连字符,并以字母开头。`lead` 和 `unowned` 为保留名。重名在创建前失败。 +3. 使用 `send_message({ name, message })` 与 `interrupt_agent({ name })`。通过 `list_agents` 发现父级和同级名字。 +4. 向任务 `owner` 字段传成员名字,读取工具结果中的 `ownerName`。根 agent 使用 `lead`。 +5. 将移除的服务调用改为 `ctx.subagents.startActivation()`、`sendMessage()`、`interrupt()` 与 `listChildren()`。向 `startActivation()` 提供 `name`;宿主控制 API 仍使用 Session id。启动启用 Team 的 profile,确认子级描述出现在 Team 面板,并且按名字发送的消息能够到达。 diff --git a/packages/acp/acp/tests/turns.spec.ts b/packages/acp/acp/tests/turns.spec.ts index 1ef2bc94ce..9ed8c85fc7 100644 --- a/packages/acp/acp/tests/turns.spec.ts +++ b/packages/acp/acp/tests/turns.spec.ts @@ -1,3 +1,4 @@ +import { randomUUID } from 'node:crypto' import { mountWorkingDirectoryFixture } from '../../../subagent/subagent/tests/working-directory-fixture.ts' import { createUserMessage, type StreamChunk } from '@deepseek-ai/dsh-llm' import type { ContextFormed } from '@deepseek-ai/dsh-llm' @@ -47,7 +48,7 @@ async function installDelegationTool(ctx: BridgeHarness['ctx']): Promise<() => b name: 'delegate_again', description: 'Run a later child.', parameters: {}, execute: async (_args, exec) => { if (exec.agent === undefined) throw new Error('delegation fixture requires an Agent') - const child = await ctx.subagents.startActivation({ + const child = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, provider: 'local-test', label: 'later child', delivery: 'caller', signal: exec.signal, request: { parent: exec.agent, prompt: [{ type: 'text', text: 'later child task' }] }, }) diff --git a/packages/bundle/headless/tests/headless.spec.ts b/packages/bundle/headless/tests/headless.spec.ts index 468c1e67a9..582eb551c9 100644 --- a/packages/bundle/headless/tests/headless.spec.ts +++ b/packages/bundle/headless/tests/headless.spec.ts @@ -1,3 +1,4 @@ +import { randomUUID } from 'node:crypto' /** Direct one-shot Agent driving, exact Session adoption, machine-readable projection, and exit mapping. */ import { Readable } from 'node:stream' @@ -242,7 +243,7 @@ describe('headless runner', () => { async afterPrompt(session, message, parent) { turns += 1 if (turns === 1) { - await test.ctx.subagents.startActivation({ + await test.ctx.subagents.startActivation({ name: `child-${randomUUID()}`, provider: 'external', label: 'work', delivery: 'parent', signal: new AbortController().signal, request: { parent, prompt: [] }, }) diff --git a/packages/client/ui-tool/README.i18n.yaml b/packages/client/ui-tool/README.i18n.yaml index 86d8299c11..298c24248a 100644 --- a/packages/client/ui-tool/README.i18n.yaml +++ b/packages/client/ui-tool/README.i18n.yaml @@ -15,8 +15,8 @@ en: d152484eb41ac6b4 zh: 09388d293f9be9cb /deepseek-ai-dsh-client-ui-tool/use-this-package: - en: c6d4e666191521b2 - zh: 2498020e7080e172 + en: 34321c376896ba9c + zh: b847f7a33458caf0 /deepseek-ai-dsh-client-ui-tool/use-this-package/registering-a-business-tool-view: en: 2e3c306b13d3bc25 zh: 77127f01763b3976 diff --git a/packages/client/ui-tool/README.md b/packages/client/ui-tool/README.md index 32d394cdaf..9e940735da 100644 --- a/packages/client/ui-tool/README.md +++ b/packages/client/ui-tool/README.md @@ -25,7 +25,7 @@ English | [中文](README.zh.md) ## Use this package -Tool calls appear in the conversation as cards: a root call tree with its nested subcalls, each atomic call rendered by its owning view. Every lifecycle state retains the tool's ordinary business glyph; failure and interruption remain explicit through the frozen call/result state, accessible status text, and failure summary. Users can open files or inspect calls through the Host callbacks. A collapsed `web_fetch` row links its http(s) URL, which opens in a new browser tab. +Tool calls appear in the conversation as cards: a root call tree with its nested subcalls, each atomic call rendered by its owning view. Every lifecycle state retains the tool's ordinary business glyph; failure and interruption remain explicit through the frozen call/result state, accessible status text, and failure summary. Users can open files or inspect calls through the Host callbacks. A collapsed `web_fetch` row links its http(s) URL, which opens in a new browser tab. Control receipts display agent `name` arguments; historical `agent_id` recordings remain readable. Settled foreground commands with a nonzero exit code, a terminating signal, or an explicit missing exit code keep their description in the ordinary gray text and show a neutral capsule with a red dot immediately after it. The capsule displays only the recorded code, signal, or localized missing-code status and stays on the same line; the description truncates with an ellipsis to reserve its space. Running, successful, and background calls omit it. Generic execution errors and stopped summaries retain their error and warning colors, including on hover. diff --git a/packages/client/ui-tool/README.zh.md b/packages/client/ui-tool/README.zh.md index 7f3d0ef79d..7367df1112 100644 --- a/packages/client/ui-tool/README.zh.md +++ b/packages/client/ui-tool/README.zh.md @@ -25,7 +25,7 @@ kind: "package-reference" ## 使用本包 -工具调用在对话中显示为卡片:一个根调用树带其嵌套子调用,每个原子调用由所属视图渲染。所有生命周期状态都保留工具的普通业务图标;失败与中断仍通过冻结调用/结果状态、无障碍状态文本和失败摘要明确表达。用户可通过宿主回调打开文件或检查调用。折叠的 `web_fetch` 行把其 http(s) URL 显示为链接,在新浏览器标签页中打开。 +工具调用在对话中显示为卡片:一个根调用树带其嵌套子调用,每个原子调用由所属视图渲染。所有生命周期状态都保留工具的普通业务图标;失败与中断仍通过冻结调用/结果状态、无障碍状态文本和失败摘要明确表达。用户可通过宿主回调打开文件或检查调用。折叠的 `web_fetch` 行把其 http(s) URL 显示为链接,在新浏览器标签页中打开。 控制工具回执显示 agent 的 `name` 参数;历史 `agent_id` 记录仍可读取。 已结束的前台命令若返回非零退出码、终止信号,或明确记录为无退出码,描述保持普通灰色,后面紧接带红点的中性胶囊。胶囊仅显示记录的退出码、信号或本地化的“未正常退出”状态,并保持在同一行;描述超出可用宽度时显示省略号,为胶囊预留空间。运行中、成功和后台调用不显示胶囊。通用执行错误与停止摘要仍保留错误色和警告色,悬停时也不改变。 diff --git a/packages/client/ui-tool/src/client/tool/models/control-details-model.ts b/packages/client/ui-tool/src/client/tool/models/control-details-model.ts index 47d6edceb8..b8074b1885 100644 --- a/packages/client/ui-tool/src/client/tool/models/control-details-model.ts +++ b/packages/client/ui-tool/src/client/tool/models/control-details-model.ts @@ -109,7 +109,7 @@ function lspDetails(args: Record, text: string, t: DetailTransl export function controlDetails( name: string, args: Record, text: string, json: unknown, t: DetailTranslate, ): ToolDetailsModel | null { - const target = arg(args, 'target') || arg(args, 'agent_id') || arg(args, 'sessionId') || arg(args, 'job_id') + const target = arg(args, 'name') || arg(args, 'target') || arg(args, 'agent_id') || arg(args, 'sessionId') || arg(args, 'job_id') switch (name) { case 'list_agents': return agentList(text, json, t) case 'job_list': return jobList(text, t) diff --git a/packages/client/ui-tool/tests/details-models.client.spec.ts b/packages/client/ui-tool/tests/details-models.client.spec.ts index 9642bd55f7..a3537f793f 100644 --- a/packages/client/ui-tool/tests/details-models.client.spec.ts +++ b/packages/client/ui-tool/tests/details-models.client.spec.ts @@ -89,7 +89,7 @@ describe('control detail adapters', () => { expect(details('team_task_create', '{"id":"task-1","subject":"Review","status":"pending"}')?.summary).toBe('Review') expect(details('team_task_list', '{"tasks":[{"id":"task-1","subject":"Review"}],"nextCursor":3}')?.caption).toBe('More tasks available; next cursor is 3') expect(details('send_message', '{"status":"queued"}', { agent_id: 'a1', message: 'hello' })?.items[0]?.badge?.label).toBe('Queued') - expect(details('send_message', 'message delivered to agent a1', { agent_id: 'a1', message: 'hello' })?.summary).toBe('a1 · Message delivered') + expect(details('send_message', 'message delivered to agent reviewer', { name: 'reviewer', message: 'hello' })?.summary).toBe('reviewer · Message delivered') expect(details('interrupt_agent', '{"previousStatus":"running"}', { agent_id: 'a1' })?.items[0]?.fields).toContainEqual({ label: 'Previous status', value: 'Running' }) expect(details('wait_agent', '{"timedOut":true}')?.summary).toBe('Subagent activity · Wait timed out') expect(details('wait_agent', '{"timedOut":false,"noProgress":{"message":"No peer"}}')?.items[0]?.description).toBe('No peer') @@ -110,7 +110,7 @@ describe('control detail adapters', () => { expect(details('unknown', 'x')).toBeNull() expect(details('team_task_list', '{"tasks":[],"nextCursor":"bad"}')).toBeNull() expect(details('terminal_read', 'bad', { sessionId: 'pty-1' })).toBeNull() - expect(details('interrupt_agent', 'interrupt requested for agent a1', { agent_id: 'a1' })?.summary).toContain('Interrupt') + expect(details('interrupt_agent', 'interrupt requested for agent reviewer', { name: 'reviewer' })?.summary).toContain('Interrupt') expect(details('interrupt_agent', 'unexpected', { agent_id: 'a1' })).toBeNull() expect(details('job_kill', 'unexpected', { job_id: 'j1' })).toBeNull() expect(details('terminal_close', 'unexpected', { sessionId: 'pty-1' })).toBeNull() diff --git a/packages/core/session/src/known-event-types.ts b/packages/core/session/src/known-event-types.ts index a0f5c17795..84607e67f1 100644 --- a/packages/core/session/src/known-event-types.ts +++ b/packages/core/session/src/known-event-types.ts @@ -62,6 +62,7 @@ export const KNOWN_SESSION_EVENT_TYPES: ReadonlySet = new Set([ 'subagent/catalog', 'subagent/descriptor', 'subagent/model-selection-policy', + 'subagent/named', 'system/message', 'team/member', 'team/message/delivered', diff --git a/packages/experimental/agent-team/README.i18n.yaml b/packages/experimental/agent-team/README.i18n.yaml index 7fd3c2a41a..6433b77a59 100644 --- a/packages/experimental/agent-team/README.i18n.yaml +++ b/packages/experimental/agent-team/README.i18n.yaml @@ -10,7 +10,7 @@ zh: 59e3d49c3d63baf9 /deepseek-ai-dsh-experimental-agent-team/summary: en: 829b0c91f9659037 - zh: 58031bda875765e5 + zh: 18971a134a874bce /deepseek-ai-dsh-experimental-agent-team/table-of-contents: en: d152484eb41ac6b4 zh: 09388d293f9be9cb @@ -24,14 +24,14 @@ en: 0eab809f5f1af167 zh: 21a5960927603bf2 /deepseek-ai-dsh-experimental-agent-team/use-this-package/teammates: - en: 6946c12e1482c65c - zh: 9320041928c49519 + en: 77cbb59eee00c536 + zh: 1cc55a924392b4dd /deepseek-ai-dsh-experimental-agent-team/use-this-package/messages-between-teammates: - en: 3bcd3a00b3d9de9b - zh: 00a404f4cf033a16 + en: 301a1b1d29dd7323 + zh: 6936fb87e017d701 /deepseek-ai-dsh-experimental-agent-team/use-this-package/shared-task-board: - en: 21623c0bb323b8bd - zh: 13012bad307d26f3 + en: a365f36c0aa710a5 + zh: af7b2b71add4319b /deepseek-ai-dsh-experimental-agent-team/use-this-package/waiting-and-interruption: en: 494f4d031fc69dec zh: ebaf87dbca8c4346 @@ -81,8 +81,8 @@ en: 8b29cb821f80db40 zh: 43e402736a553ce5 /deepseek-ai-dsh-experimental-agent-team/model-experience/task-views-and-errors/what-the-model-sees: - en: 2353fe861b9fa710 - zh: 34a92639c01f57f5 + en: 8aabdf12a2b74f7e + zh: bf786d251f9702f1 /deepseek-ai-dsh-experimental-agent-team/model-experience/task-views-and-errors/token-effect: en: d5f77a18bfca1051 zh: b988301e31491408 diff --git a/packages/experimental/agent-team/README.md b/packages/experimental/agent-team/README.md index 8cdb8d97c5..ef92cddf60 100644 --- a/packages/experimental/agent-team/README.md +++ b/packages/experimental/agent-team/README.md @@ -53,19 +53,19 @@ The generated [configuration catalog](../../../docs/config-catalog.md#deepseek-a ### Teammates -Ask the Lead to start a subagent with a `description` of its work: `subagent` starts fresh, while `subagent_fork` inherits completed turns. The returned Session id addresses the teammate; descriptions are display text and may repeat. +Ask the Lead to start a subagent with a unique `name` and a `description` of its work: `subagent` starts fresh, while `subagent_fork` inherits completed turns. The returned name addresses the teammate; descriptions may repeat. Every root agent leads its own Team, and every live subagent below it, at any depth, receives Team tools. The roster lists the Lead, its direct continuable children, and historical `team/member` records. Deeper descendants work on the same board under their Session ids but have no roster row. ### Messages between teammates -Members use standard `send_message` with Session ids: the Lead reaches direct children, and resident continuable children reach their parent and continuable siblings. Steer delivers into the target inbox and can cold-resume children or siblings. Team stores no messages; accepted messages follow ordinary Agent persistence. +Members use standard `send_message` with agent names: the Lead reaches direct children, and resident continuable children reach their parent and continuable siblings. Steer delivers into the target inbox and can cold-resume children or siblings. Team stores no messages; accepted messages follow ordinary Agent persistence. ### Shared task board Any member can add a task with a title, details, optional dependencies on other tasks, and optional hints about which files it will touch. A task is claimable only when everything it depends on is complete. -A member claims a task to start work, completes it, releases it, or reopens it. The Lead can reassign a task by Session id to itself, a direct continuable child, or an active historical member. Other members claim tasks themselves. Every change is compare-and-set, so stale updates cannot overwrite newer work. +A member claims a task to start work, completes it, releases it, or reopens it. The Lead can reassign a task by agent name to itself, a direct continuable child, or an active historical member. Other members claim tasks themselves. Every change is compare-and-set, so stale updates cannot overwrite newer work. File hints produce warnings when two in-progress tasks plan to touch overlapping paths — they never block anything. Deleted tasks remain in history but disappear from the active list. @@ -173,7 +173,7 @@ Read these pages when the package-level contract is not enough. They move from t #### What the model sees -The model sees Team state through task-tool results; coordination events never enter the conversation. Task views identify their owner through `ownerId`. Failures surface as tool errors with the `TeamError` message, including the current revision for stale updates. +The model sees Team state through task-tool results; coordination events never enter the conversation. Model-facing task views identify their owner through `ownerName`; host views retain `ownerId`. Failures surface as tool errors with the `TeamError` message, including the current revision for stale updates. #### Token effect diff --git a/packages/experimental/agent-team/README.zh.md b/packages/experimental/agent-team/README.zh.md index a5b8ddacfb..1d7ecf2d1f 100644 --- a/packages/experimental/agent-team/README.zh.md +++ b/packages/experimental/agent-team/README.zh.md @@ -9,7 +9,7 @@ kind: "package-reference" ## 概述 -`dsh-experimental-agent-team` 将代理及其子代理组成共享持久任务板的 Team。标准 subagent 工具负责创建队友并按 id 发消息。Team 增加比较并设置的任务所有权、进度等待和 Web 面板成员列表。模型工具由 `dsh-experimental-tool-agent-team` 提供。该包为实验性功能,成员共享同一工作树。 +`dsh-experimental-agent-team` 将代理及其子代理组成共享持久任务板的 Team。标准 subagent 工具负责创建队友并按名字发消息。Team 增加比较并设置的任务所有权、进度等待和 Web 面板成员列表。模型工具由 `dsh-experimental-tool-agent-team` 提供。该包为实验性功能,成员共享同一工作树。 ## 目录 @@ -53,19 +53,19 @@ kind: "package-reference" ### Teammate -让 Lead 使用 `description` 描述工作并启动子代理:`subagent` 从全新上下文开始,`subagent_fork` 继承已完成轮次。返回的 Session id 用于寻址队友;描述用于展示,可以重复。 +让 Lead 使用唯一的 `name` 和工作 `description` 启动子代理:`subagent` 从全新上下文开始,`subagent_fork` 继承已完成轮次。返回的名字用于寻址队友;描述可以重复。 每个根代理领导自己的 Team,其下任意深度的在线子代理都获得 Team 工具。成员列表包含 Lead、其直接可继续子级以及历史 `team/member` 记录。更深的后代按 Session id 使用同一任务板,但不显示为成员行。 ### teammate 之间的消息 -成员使用标准 `send_message` 按 Session id 发消息:Lead 联系直接子级,驻留的可继续子级联系父级和可继续同级。Steer 投递到目标收件箱,并可冷恢复子级或同级。Team 不存储消息;已接受消息遵循普通 Agent 持久化。 +成员使用标准 `send_message` 按 agent 名字 发消息:Lead 联系直接子级,驻留的可继续子级联系父级和可继续同级。Steer 投递到目标收件箱,并可冷恢复子级或同级。Team 不存储消息;已接受消息遵循普通 Agent 持久化。 ### 共享任务板 任何成员都可以添加任务,包含标题、详情、对其他任务的可选依赖,以及可选的文件触及提示。只有其全部依赖完成后,任务才可 claim。 -成员认领任务后开始工作,可以完成、释放或重新打开任务。Lead 可按 Session id 将任务重新分配给自身、直接可继续子级或活跃的历史成员。其他成员自行认领任务。每次变更都使用比较并设置,防止过期更新覆盖新工作。 +成员认领任务后开始工作,可以完成、释放或重新打开任务。Lead 可按 agent 名字 将任务重新分配给自身、直接可继续子级或活跃的历史成员。其他成员自行认领任务。每次变更都使用比较并设置,防止过期更新覆盖新工作。 当两个 in-progress 任务计划触及重叠路径时,文件提示会产生警告——它们绝不阻止任何操作。已删除任务保留在历史中,但从活动列表中消失。 @@ -173,7 +173,7 @@ Mailbox 投影与 checkpoint 准入保留本地声明的校验器之外获准内 #### 模型看到什么 -模型通过任务工具结果查看 Team 状态;协调事件不进入对话。任务视图通过 `ownerId` 标识负责人。失败以携带 `TeamError` 消息的工具错误显示,过期更新错误包含当前修订。 +模型通过任务工具结果查看 Team 状态;协调事件不进入对话。面向模型的任务视图通过 `ownerName` 标识负责人;宿主视图保留 `ownerId`。失败以携带 `TeamError` 消息的工具错误显示,过期更新错误包含当前修订。 #### Token 影响 diff --git a/packages/experimental/agent-team/tests/persistence.spec.ts b/packages/experimental/agent-team/tests/persistence.spec.ts index fa9b4b3406..b92f0439be 100644 --- a/packages/experimental/agent-team/tests/persistence.spec.ts +++ b/packages/experimental/agent-team/tests/persistence.spec.ts @@ -1,3 +1,4 @@ +import { randomUUID } from 'node:crypto' import { afterEach, describe, expect, it, vi } from 'vitest' import { mkdtempSync } from 'node:fs' import { rm } from 'node:fs/promises' @@ -117,7 +118,7 @@ for (const backend of backends) { const first = await stack(backend, storageRoot, [textResponse('initial teammate answer')]) const firstLead = await first.ctx.agentLoop.create(rootId, { provider: 'mock', model: 'mock' }) - const started = await first.ctx.subagents.startActivation({ + const started = await first.ctx.subagents.startActivation({ name: `child-${randomUUID()}`, provider: 'spawn', label: 'restart worker', request: { prompt: [{ type: 'text', text: 'finish before restart' }], parent: firstLead }, diff --git a/packages/experimental/agent-team/tests/team.spec.ts b/packages/experimental/agent-team/tests/team.spec.ts index 76ad64897d..71ed025f74 100644 --- a/packages/experimental/agent-team/tests/team.spec.ts +++ b/packages/experimental/agent-team/tests/team.spec.ts @@ -1,3 +1,4 @@ +import { randomUUID } from 'node:crypto' import { afterEach, describe, expect, it, vi } from 'vitest' import { mkdtempSync, rmSync } from 'node:fs' import { tmpdir } from 'node:os' @@ -79,7 +80,7 @@ function teamInternals(ctx: Context): TeamServiceInternals { /** Start one teammate: a continuable child of the Lead. */ async function spawn(ctx: Context, lead: Agent, description: string | undefined, provider = 'spawn'): Promise { - const started = await ctx.subagents.startActivation({ + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, provider, label: `${description ?? 'shared'} responsibility`, request: { prompt: content(`${description ?? 'shared'} initial`), parent: lead }, @@ -130,7 +131,7 @@ describe('Team identity and membership', () => { const { ctx, lead } = await setup(['hang', 'hang', 'hang']) const named = await waitRunning(ctx, await spawn(ctx, lead, 'alpha')) const unnamed = await waitRunning(ctx, await spawn(ctx, lead, undefined)) - const grandchildId = (await ctx.subagents.startActivation({ + const grandchildId = (await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, provider: 'spawn', label: 'nested', delivery: 'caller', signal: SIGNAL, request: { prompt: content('nested'), parent: named }, })).childId diff --git a/packages/experimental/tool-agent-team/README.i18n.yaml b/packages/experimental/tool-agent-team/README.i18n.yaml index 754eb77591..5c577e0bdb 100644 --- a/packages/experimental/tool-agent-team/README.i18n.yaml +++ b/packages/experimental/tool-agent-team/README.i18n.yaml @@ -24,8 +24,8 @@ en: 8dca5e3fa72a3bb7 zh: 51cdf2eb834dd746 /deepseek-ai-dsh-experimental-tool-agent-team/use-this-package/what-the-model-can-do: - en: de03950e2e41ba1f - zh: eeb52afda9bd2249 + en: 624b472c31463fbc + zh: a066b1d9c577461e /deepseek-ai-dsh-experimental-tool-agent-team/use-this-package/what-success-and-failure-look-like: en: 8b6cd7c8bd1b8abc zh: d281898bdd1db783 @@ -45,8 +45,8 @@ en: c2b29f27a74c02c0 zh: 026f2ef93dd604d8 /deepseek-ai-dsh-experimental-tool-agent-team/further-exploration: - en: c0b484e56b3a3990 - zh: becaf4dc193f00d5 + en: e557874da4eba7ff + zh: 2f580bea15598603 /deepseek-ai-dsh-experimental-tool-agent-team/model-experience: en: 215e7ba838619b7b zh: a311da3843709f90 @@ -69,8 +69,8 @@ en: ed8642015d306d6d zh: 09d1970fb8e02ff3 /deepseek-ai-dsh-experimental-tool-agent-team/model-experience/team-identity-runtime-context/what-the-model-sees: - en: 4d17511e1d5fb4f2 - zh: c98734115d753a57 + en: a71a80314cfe8922 + zh: 6cf10566bc0f4e4a /deepseek-ai-dsh-experimental-tool-agent-team/model-experience/team-identity-runtime-context/token-effect: en: f0dc7b201c8b3cf0 zh: b5f16ef4a133257c diff --git a/packages/experimental/tool-agent-team/README.md b/packages/experimental/tool-agent-team/README.md index 1433e60b78..63acc779f6 100644 --- a/packages/experimental/tool-agent-team/README.md +++ b/packages/experimental/tool-agent-team/README.md @@ -52,7 +52,7 @@ The five tools cover two capabilities; the standard subagent tools cover the thi - **Wait for teammates** — `wait_agent` waits for the next task, member status, or inbox change after the call starts. - **Create and reach teammates** — `subagent`, `subagent_fork`, `send_message`, `list_agents`, and `interrupt_agent` come from the subagent tool packages and are unchanged by this package. -Task `owner` arguments and `ownerId` results use Session ids. Descriptions are display text and may repeat. Any member can use the board; only the Lead reassigns tasks. Updates enforce ownership and revision checks, rejecting stale edits. +Task `owner` arguments and `ownerName` results use agent names; the root is `lead`. Descriptions may repeat. Any member can use the board; only the Lead reassigns tasks. Updates enforce ownership and revision checks, rejecting stale edits. ### What success and failure look like @@ -104,7 +104,7 @@ Read these pages when the package-level contract is not enough. They move from t - [agent-team package](../agent-team/README.md) — the `ctx.agentTeams` domain service behind these tools. - [Agent Teams subsystem](../../../docs/subsystems/agent-team.md) — durable Team types and service API. -- [Subagent control tools](../../subagent/tool-subagent-control/README.md) — messaging, listing, and interruption by Session id. +- [Subagent control tools](../../subagent/tool-subagent-control/README.md) — messaging, listing, and interruption by agent name. - [Generated tool catalog](../../../docs/tool-catalog.md#deepseek-aidsh-experimental-tool-agent-team) — every tool schema the model receives. - [Subagent teammates Agent Note](../../../.agents/notes/implemented/architecture/2026-10-15-agent-teams-as-subagents.md) — model-facing, scoping, and tool-family decisions. @@ -122,13 +122,13 @@ Every Team member's system prompt carries one `team:policy` section; the Lead an ##### Team policy ```markdown -Agent Teams is available in this session. Teammates are subagents. Use agent ids with send_message to reach your direct continuable children or, as a continuable subagent, your parent and continuable siblings. Descriptions explain responsibilities and may repeat. +Agent Teams is available in this session. Teammates are subagents. Use agent names with send_message to reach your direct continuable children or, as a continuable subagent, your parent and continuable siblings. Descriptions explain responsibilities and may repeat. The Team Lead and all teammates share the same working directory and filesystem. Edits are immediately visible to every member. Split write work into disjoint scopes, record expected write scopes on shared tasks, and use task dependencies when work must be ordered. Write-scope overlap is advisory, not a lock. Prefer read/edit/write for file changes. If a file operation returns FS_STALE_VERSION, read the current file, rebase your intended change onto the new content, and retry. Bash, formatters, code generators, and scripts are not fully protected by the filesystem version guard; coordinate them explicitly and have the Lead review the final diff and run tests. -Use agent ids as task owners. The Lead can reassign to itself, its direct continuable children, or historical members; other descendants claim tasks themselves. list_agents shows direct contacts and all reachable continuable descendants; discovery does not grant message or assignment authority. inactive means no turn is executing; it does not describe task completion, success, failure, or waiting for other agents. A successful send does not mean the recipient has processed it. Shared-task workflow is list, get, claim with the current revision, perform the work, then complete. Task readiness never starts an owner. Before wait_agent, make sure another required member is running; use send_message first for an inactive direct contact, or coordinate through its parent for a deeper member. wait_agent observes only changes after that call starts, never wakes a member, and returns noProgress immediately when no other member is running. Re-list after wakeup or timeout. The Lead must wait for required teammates before giving the final answer. +Use agent names as task owners; the root agent is named lead. The Lead can reassign to itself, its direct continuable children, or historical members; other descendants claim tasks themselves. list_agents shows direct contacts and all reachable continuable descendants; discovery does not grant message or assignment authority. inactive means no turn is executing; it does not describe task completion, success, failure, or waiting for other agents. A successful send does not mean the recipient has processed it. Shared-task workflow is list, get, claim with the current revision, perform the work, then complete. Task readiness never starts an owner. Before wait_agent, make sure another required member is running; use send_message first for an inactive direct contact, or coordinate through its parent for a deeper member. wait_agent observes only changes after that call starts, never wakes a member, and returns noProgress immediately when no other member is running. Re-list after wakeup or timeout. The Lead must wait for required teammates before giving the final answer. ``` #### Token effect @@ -143,7 +143,7 @@ The text is identical for the Lead and every descendant and does not change whil #### What the model sees -Required `team:identity` runtime context states `You are the Team Lead. Your agent id is "".` for a root and `You are a teammate in the Team led by agent "".` for a subagent. It follows current membership, survives optional-context suppression, and is restored after compaction. An ordinary fork of a teammate is a new root and receives the Lead statement. +Required `team:identity` runtime context states `You are the Team Lead. Your name is lead.` for a root and `Your name is "". You are a teammate in the Team led by "lead".` for a subagent. It follows current membership, survives optional-context suppression, and is restored after compaction. An ordinary fork of a teammate is a new root and receives the Lead statement. #### Token effect diff --git a/packages/experimental/tool-agent-team/README.zh.md b/packages/experimental/tool-agent-team/README.zh.md index 54eebee8fd..20a6761ccd 100644 --- a/packages/experimental/tool-agent-team/README.zh.md +++ b/packages/experimental/tool-agent-team/README.zh.md @@ -52,7 +52,7 @@ kind: "package-reference" - **等待 teammate**——`wait_agent` 等待调用开始后的下一次任务、成员状态或 inbox 变化。 - **创建和联系队友**——`subagent`、`subagent_fork`、`send_message`、`list_agents` 和 `interrupt_agent` 来自子代理工具包,本包不修改它们。 -任务 `owner` 参数和 `ownerId` 结果使用 Session id。描述用于展示,可以重复。任何成员均可使用任务板;只有 Lead 能重新分配任务。更新校验所有权和修订,拒绝过期编辑。 +任务 `owner` 参数与 `ownerName` 结果使用 agent 名字;根名为 `lead`。描述可以重复。任何成员均可使用任务板;只有 Lead 能重新分配任务。更新校验所有权和修订,拒绝过期编辑。 ### 成功与失败的表现 @@ -104,7 +104,7 @@ member scope 上的一个 `team:policy` 段落和一个必需的 `team:identity` - [agent-team 包](../agent-team/README.zh.md)——这些工具背后的 `ctx.agentTeams` 领域服务。 - [Agent Teams 子系统](../../../docs/subsystems/agent-team.zh.md)——持久 Team 类型与服务 API。 -- [子代理控制工具](../../subagent/tool-subagent-control/README.zh.md)——按 Session id 发消息、列举和中断。 +- [子代理控制工具](../../subagent/tool-subagent-control/README.zh.md)——按 agent 名字 发消息、列举和中断。 - [生成的工具目录](../../../docs/tool-catalog.zh.md#deepseek-aidsh-experimental-tool-agent-team)——模型接收的每个工具 schema。 - [subagent teammate Agent Note](../../../.agents/notes/implemented/architecture/2026-10-15-agent-teams-as-subagents.zh.md)——模型侧、scoping 与工具族决策。 @@ -122,13 +122,13 @@ member scope 上的一个 `team:policy` 段落和一个必需的 `team:identity` ##### Team 策略 ```markdown -Agent Teams is available in this session. Teammates are subagents. Use agent ids with send_message to reach your direct continuable children or, as a continuable subagent, your parent and continuable siblings. Descriptions explain responsibilities and may repeat. +Agent Teams is available in this session. Teammates are subagents. Use agent names with send_message to reach your direct continuable children or, as a continuable subagent, your parent and continuable siblings. Descriptions explain responsibilities and may repeat. The Team Lead and all teammates share the same working directory and filesystem. Edits are immediately visible to every member. Split write work into disjoint scopes, record expected write scopes on shared tasks, and use task dependencies when work must be ordered. Write-scope overlap is advisory, not a lock. Prefer read/edit/write for file changes. If a file operation returns FS_STALE_VERSION, read the current file, rebase your intended change onto the new content, and retry. Bash, formatters, code generators, and scripts are not fully protected by the filesystem version guard; coordinate them explicitly and have the Lead review the final diff and run tests. -Use agent ids as task owners. The Lead can reassign to itself, its direct continuable children, or historical members; other descendants claim tasks themselves. list_agents shows direct contacts and all reachable continuable descendants; discovery does not grant message or assignment authority. inactive means no turn is executing; it does not describe task completion, success, failure, or waiting for other agents. A successful send does not mean the recipient has processed it. Shared-task workflow is list, get, claim with the current revision, perform the work, then complete. Task readiness never starts an owner. Before wait_agent, make sure another required member is running; use send_message first for an inactive direct contact, or coordinate through its parent for a deeper member. wait_agent observes only changes after that call starts, never wakes a member, and returns noProgress immediately when no other member is running. Re-list after wakeup or timeout. The Lead must wait for required teammates before giving the final answer. +Use agent names as task owners; the root agent is named lead. The Lead can reassign to itself, its direct continuable children, or historical members; other descendants claim tasks themselves. list_agents shows direct contacts and all reachable continuable descendants; discovery does not grant message or assignment authority. inactive means no turn is executing; it does not describe task completion, success, failure, or waiting for other agents. A successful send does not mean the recipient has processed it. Shared-task workflow is list, get, claim with the current revision, perform the work, then complete. Task readiness never starts an owner. Before wait_agent, make sure another required member is running; use send_message first for an inactive direct contact, or coordinate through its parent for a deeper member. wait_agent observes only changes after that call starts, never wakes a member, and returns noProgress immediately when no other member is running. Re-list after wakeup or timeout. The Lead must wait for required teammates before giving the final answer. ``` #### Token 影响 @@ -143,7 +143,7 @@ Use agent ids as task owners. The Lead can reassign to itself, its direct contin #### 模型看到什么 -必需的 `team:identity` 运行时上下文对根显示 `You are the Team Lead. Your agent id is "".`,对子代理显示 `You are a teammate in the Team led by agent "".`。它跟随当前成员身份,不受可选上下文关闭影响,并在压缩后恢复。队友的普通分叉是新的根,接收 Lead 声明。 +必需的 `team:identity` runtime context 对根声明 `You are the Team Lead. Your name is lead.`,对子代理声明 `Your name is "". You are a teammate in the Team led by "lead".`。它跟随当前成员关系,不受可选上下文抑制影响,压缩后会恢复。队友的普通分叉是新的根,收到 Lead 声明。 #### Token 影响 diff --git a/packages/experimental/tool-agent-team/src/index.ts b/packages/experimental/tool-agent-team/src/index.ts index cf3b411e21..4fb423494d 100644 --- a/packages/experimental/tool-agent-team/src/index.ts +++ b/packages/experimental/tool-agent-team/src/index.ts @@ -2,16 +2,17 @@ import type { Context } from '@deepseek-ai/cordis' import z from '@deepseek-ai/schemastery' -import type { Agent } from '@deepseek-ai/dsh-agent' import { SessionId } from '@deepseek-ai/dsh-session' -import { TeamTaskId } from '@deepseek-ai/dsh-experimental-agent-team' +import type { Agent } from '@deepseek-ai/dsh-agent' +import { TeamTaskId, type TeamTaskView } from '@deepseek-ai/dsh-experimental-agent-team' +import type {} from '@deepseek-ai/dsh-subagent' import { defineTool } from '@deepseek-ai/dsh-tools' import type { InferValue, ValueSchemaSpec } from '@deepseek-ai/dsh-tools' /** Cordis plugin name. */ export const name = 'tool-agent-team' /** Services required by the Team tool plugin. */ -export const inject = ['agents', 'agentTeams', 'tools', 'systemPrompt'] +export const inject = ['agents', 'agentTeams', 'subagents', 'tools', 'systemPrompt'] /** The Team tool plugin takes no configuration. */ export type Config = Record @@ -23,13 +24,13 @@ export const Config: z = z.object({}) const REMOVED_CONFIG_KEYS = ['interrupt', 'freshProvider', 'forkProvider'] as const /** Model-facing collaboration guidance shared by Lead and teammates. */ -const TEAM_POLICY = `Agent Teams is available in this session. Teammates are subagents. Use agent ids with send_message to reach your direct continuable children or, as a continuable subagent, your parent and continuable siblings. Descriptions explain responsibilities and may repeat. +const TEAM_POLICY = `Agent Teams is available in this session. Teammates are subagents. Use agent names with send_message to reach your direct continuable children or, as a continuable subagent, your parent and continuable siblings. Descriptions explain responsibilities and may repeat. The Team Lead and all teammates share the same working directory and filesystem. Edits are immediately visible to every member. Split write work into disjoint scopes, record expected write scopes on shared tasks, and use task dependencies when work must be ordered. Write-scope overlap is advisory, not a lock. Prefer read/edit/write for file changes. If a file operation returns FS_STALE_VERSION, read the current file, rebase your intended change onto the new content, and retry. Bash, formatters, code generators, and scripts are not fully protected by the filesystem version guard; coordinate them explicitly and have the Lead review the final diff and run tests. -Use agent ids as task owners. The Lead can reassign to itself, its direct continuable children, or historical members; other descendants claim tasks themselves. list_agents shows direct contacts and all reachable continuable descendants; discovery does not grant message or assignment authority. inactive means no turn is executing; it does not describe task completion, success, failure, or waiting for other agents. A successful send does not mean the recipient has processed it. Shared-task workflow is list, get, claim with the current revision, perform the work, then complete. Task readiness never starts an owner. Before wait_agent, make sure another required member is running; use send_message first for an inactive direct contact, or coordinate through its parent for a deeper member. wait_agent observes only changes after that call starts, never wakes a member, and returns noProgress immediately when no other member is running. Re-list after wakeup or timeout. The Lead must wait for required teammates before giving the final answer.` +Use agent names as task owners; the root agent is named lead. The Lead can reassign to itself, its direct continuable children, or historical members; other descendants claim tasks themselves. list_agents shows direct contacts and all reachable continuable descendants; discovery does not grant message or assignment authority. inactive means no turn is executing; it does not describe task completion, success, failure, or waiting for other agents. A successful send does not mean the recipient has processed it. Shared-task workflow is list, get, claim with the current revision, perform the work, then complete. Task readiness never starts an owner. Before wait_agent, make sure another required member is running; use send_message first for an inactive direct contact, or coordinate through its parent for a deeper member. wait_agent observes only changes after that call starts, never wakes a member, and returns noProgress immediately when no other member is running. Re-list after wakeup or timeout. The Lead must wait for required teammates before giving the final answer.` const NO_ACTIVE_PEER_MESSAGE = 'No other Team member is running. wait_agent cannot make progress or wake inactive teammates. Re-list with list_agents and team_task_list, then use send_message to wake a required inactive direct contact before waiting again; coordinate deeper members through their parent.' @@ -43,7 +44,7 @@ const TASK_VIEW_SCHEMA = { subject: { type: 'string', required: true }, description: { type: 'string', required: true }, status: { type: 'string', required: true, enum: ['pending', 'in_progress', 'completed', 'deleted'] }, - ownerId: { type: 'string' }, + ownerName: { type: 'string' }, blockedBy: { type: 'array', required: true, items: { type: 'string' } }, writeScopes: { type: 'array', required: true, items: { type: 'string' } }, ready: { type: 'boolean', required: true }, @@ -94,6 +95,12 @@ function jsonOutput(schema: S): { } } +/** Project durable task ownership to the names used by collaboration tools. */ +function namedTask(ctx: Context, caller: Agent, task: TeamTaskView) { + const { ownerId, ...view } = task + return { ...view, ...ownerId === undefined ? {} : { ownerName: ctx.subagents.nameOf(caller, ownerId) } } +} + /** Recover the exact caller guaranteed by Agent-scoped tool discovery. */ function callingAgent(agent: Agent | undefined, toolName: string): Agent { /* v8 ignore next 2 -- Team tools are registered only in an exact Agent scope, so discovery supplies this carrier. */ @@ -120,8 +127,8 @@ function install(agent: Agent, ctx: Context): () => void { text: () => { const { role, root } = ctx.agentTeams.membership(agent) return role === 'lead' - ? `You are the Team Lead. Your agent id is ${JSON.stringify(agent.id)}.` - : `You are a teammate in the Team led by agent ${JSON.stringify(root.id)}.` + ? 'You are the Team Lead. Your name is lead.' + : `Your name is ${JSON.stringify(ctx.subagents.nameOf(agent))}. You are a teammate in the Team led by ${JSON.stringify(ctx.subagents.nameOf(agent, root.id))}.` }, })) @@ -173,12 +180,13 @@ function install(agent: Agent, ctx: Context): () => void { }, output: jsonOutput(TASK_VIEW_SCHEMA), async execute(args, exec) { - return await ctx.agentTeams.createTask(callingAgent(exec.agent, 'team_task_create'), { + const caller = callingAgent(exec.agent, 'team_task_create') + return namedTask(ctx, caller, await ctx.agentTeams.createTask(caller, { subject: args.subject, description: args.description, ...args.blocked_by === undefined ? {} : { blockedBy: args.blocked_by.map(TeamTaskId) }, ...args.write_scopes === undefined ? {} : { writeScopes: args.write_scopes }, - }) + })) }, }))) @@ -191,7 +199,7 @@ function install(agent: Agent, ctx: Context): () => void { enum: ['pending', 'in_progress', 'completed'], description: 'Optional exact status filter.', }, - owner: { type: 'string', description: 'Optional exact ownerId filter; use unowned for tasks without an owner.' }, + owner: { type: 'string', description: 'Optional exact ownerName filter; use unowned for tasks without an owner.' }, ready: { type: 'boolean', description: 'Optional readiness filter.' }, cursor: { type: 'integer', description: 'Zero-based result offset. Defaults to 0.' }, limit: { type: 'integer', description: 'Number of rows, 1 through 100. Defaults to 50.' }, @@ -199,9 +207,10 @@ function install(agent: Agent, ctx: Context): () => void { output: jsonOutput(TASK_LIST_VALUE_SCHEMA), execute(args, exec) { const status = args.status - const filtered = ctx.agentTeams.listTasks(callingAgent(exec.agent, 'team_task_list')).filter(task => + const caller = callingAgent(exec.agent, 'team_task_list') + const filtered = ctx.agentTeams.listTasks(caller).map(task => namedTask(ctx, caller, task)).filter(task => (status === undefined || task.status === status) - && (args.owner === undefined || (args.owner === 'unowned' ? task.ownerId === undefined : task.ownerId === args.owner)) + && (args.owner === undefined || (args.owner === 'unowned' ? task.ownerName === undefined : task.ownerName === args.owner)) && (args.ready === undefined || task.ready === args.ready)) const cursor = args.cursor ?? 0 const limit = args.limit ?? 50 @@ -221,11 +230,9 @@ function install(agent: Agent, ctx: Context): () => void { task_id: { type: 'string', required: true, description: 'Shared task id.' }, }, output: jsonOutput(TASK_VIEW_SCHEMA), - async execute(args, exec) { - return Promise.resolve(ctx.agentTeams.getTask( - callingAgent(exec.agent, 'team_task_get'), - TeamTaskId(args.task_id), - )) + execute(args, exec) { + const caller = callingAgent(exec.agent, 'team_task_get') + return Promise.resolve(namedTask(ctx, caller, ctx.agentTeams.getTask(caller, TeamTaskId(args.task_id)))) }, }))) @@ -245,11 +252,17 @@ function install(agent: Agent, ctx: Context): () => void { description: { type: 'string', description: 'Replacement details for edit.' }, blocked_by: { type: 'array', items: { type: 'string' }, description: 'Complete blocker list for set_dependencies.' }, write_scopes: { type: 'array', items: { type: 'string' }, description: 'Replacement advisory write scopes for edit.' }, - owner: { type: 'string', description: 'Agent id of the Lead or one of its direct continuable children for Lead-only reassign; omit to unassign.' }, + owner: { type: 'string', description: 'Agent name of the Lead or one of its direct continuable children for Lead-only reassign; omit to unassign.' }, }, output: jsonOutput(TASK_VIEW_SCHEMA), async execute(args, exec) { - return await ctx.agentTeams.updateTask(callingAgent(exec.agent, 'team_task_update'), { + const caller = callingAgent(exec.agent, 'team_task_update') + // Team authorizes historical members that predate subagent catalogs. + const legacyId = args.owner?.startsWith('legacy:') ? SessionId(args.owner.slice('legacy:'.length)) : undefined + const owner = args.owner === undefined ? undefined + : legacyId !== undefined && ctx.subagents.nameOf(caller, legacyId) === args.owner ? legacyId + : await ctx.subagents.resolveName(caller, args.owner, exec.signal) + return namedTask(ctx, caller, await ctx.agentTeams.updateTask(caller, { taskId: TeamTaskId(args.task_id), expectedRevision: args.expected_revision, action: args.action, @@ -257,8 +270,8 @@ function install(agent: Agent, ctx: Context): () => void { ...args.description === undefined ? {} : { description: args.description }, ...args.blocked_by === undefined ? {} : { blockedBy: args.blocked_by.map(TeamTaskId) }, ...args.write_scopes === undefined ? {} : { writeScopes: args.write_scopes }, - ...args.owner === undefined ? {} : { owner: SessionId(args.owner) }, - }) + ...owner === undefined ? {} : { owner }, + })) }, }))) } catch (error: unknown) { diff --git a/packages/experimental/tool-agent-team/tests/tool-team.spec.ts b/packages/experimental/tool-agent-team/tests/tool-team.spec.ts index 7f0b879066..f23dd92591 100644 --- a/packages/experimental/tool-agent-team/tests/tool-team.spec.ts +++ b/packages/experimental/tool-agent-team/tests/tool-team.spec.ts @@ -1,3 +1,4 @@ +import { randomUUID } from 'node:crypto' import { afterEach, describe, expect, it, vi } from 'vitest' import { mkdtempSync, rmSync } from 'node:fs' import { tmpdir } from 'node:os' @@ -23,7 +24,7 @@ import { serialize } from '@deepseek-ai/dsh-llm-deepseek/src/serialize.ts' import type { GenerateOptions } from '@deepseek-ai/dsh-llm' import { MockAdapter, textResponse, toolCallResponse } from '../../../core/agent-loop/tests/mock-adapter.ts' import { mountWorkingDirectoryFixture } from '../../../subagent/subagent/tests/working-directory-fixture.ts' -import TeamService from '../../agent-team/src/index.ts' +import TeamService, { TeamId } from '../../agent-team/src/index.ts' import * as toolTeam from '../src/index.ts' function serializeRequest(request: GenerateOptions) { @@ -44,7 +45,7 @@ const TEAM_TOOLS = [ 'team_task_update', 'wait_agent', ] -const leadIdentity = (agent: Agent): string => `You are the Team Lead. Your agent id is ${JSON.stringify(agent.id)}.` +const leadIdentity = (_agent: Agent): string => 'You are the Team Lead. Your name is lead.' const roots: string[] = [] const contexts = new Set() @@ -112,7 +113,7 @@ function text(result: Awaited>): string { /** Start a continuable child of the Lead with a task description. */ async function spawn(ctx: Context, lead: Agent, description: string | undefined, prompt: string, provider = 'spawn'): Promise { - const started = await ctx.subagents.startActivation({ + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, provider, label: `${description ?? 'shared'} task`, request: { prompt: [{ type: 'text', text: prompt }], parent: lead }, @@ -132,8 +133,8 @@ function teamTools(assembled: Awaited>): string[] { return assembled.tools.map(schema => schema.name).filter(name => TEAM_TOOLS.includes(name)).sort() } -function teammateIdentity(lead: Agent): string { - return `You are a teammate in the Team led by agent ${JSON.stringify(lead.id)}.` +function teammateIdentity(_lead: Agent): string { + return 'You are a teammate in the Team led by \"lead\".' } async function runTurn(agent: Agent, text: string): Promise { @@ -367,7 +368,7 @@ describe('dsh-tool-team', () => { expected_revision: task.revision, action: 'claim', }) - expect(JSON.parse(text(claimed))).toMatchObject({ status: 'in_progress', ownerId: childId }) + expect(JSON.parse(text(claimed))).toMatchObject({ status: 'in_progress', ownerName: ctx.subagents.nameOf(lead, childId) }) const stale = await execute(ctx, lead, 'team_task_update', { task_id: task.id, expected_revision: task.revision, @@ -412,7 +413,7 @@ describe('dsh-tool-team', () => { const claim = JSON.parse(text(claimed)) as { revision: number } expect(JSON.parse(text(await execute(ctx, lead, 'team_task_list', { - status: 'in_progress', owner: lead.id, cursor: 0, limit: 1, + status: 'in_progress', owner: 'lead', cursor: 0, limit: 1, })))).toMatchObject({ tasks: [{ id: first.id }] }) expect(JSON.parse(text(await execute(ctx, lead, 'team_task_list', { owner: 'unowned', limit: 1, @@ -447,7 +448,7 @@ describe('dsh-tool-team', () => { task_id: first.id, expected_revision: dependency.revision, action: 'reassign', - owner: childId, + owner: ctx.subagents.nameOf(lead, childId), })).isError).toBe(true) const wait = execute(ctx, lead, 'wait_agent', {}) @@ -465,6 +466,23 @@ describe('dsh-tool-team', () => { await waitNoAgent(ctx, childId) }) + it('reassigns by a historical member address without granting message authority', async () => { + const { ctx, lead } = await setup([]) + const id = SessionId('historical-worker') + for (const phase of ['provisioning', 'active'] as const) lead.session.append('team/member', { + version: 2, teamId: TeamId(lead.id), + member: { id, name: 'old-name', description: 'historical member', provider: 'spawn', context: 'fresh', phase }, + }) + const created = await ctx.agentTeams.createTask(lead, { subject: 'Review', description: 'Review history' }) + expect(JSON.parse(text(await execute(ctx, lead, 'team_task_update', { + task_id: created.id, expected_revision: created.revision, action: 'reassign', owner: 'legacy:historical-worker', + })))).toMatchObject({ ownerName: 'legacy:historical-worker' }) + expect((await execute(ctx, lead, 'send_message', { name: 'legacy:historical-worker', message: 'hello' })).isError).toBe(true) + expect((await execute(ctx, lead, 'team_task_update', { + task_id: created.id, expected_revision: 2, action: 'reassign', owner: 'legacy:missing', + })).isError).toBe(true) + }) + it('removes and reinstalls every scoped registration across plugin HMR without stopping the child', async () => { const { ctx, lead, fiber } = await setup(['hang']) const childId = await spawn(ctx, lead, 'hmr-worker', 'wait') @@ -557,6 +575,6 @@ describe('dsh-tool-team', () => { expect(text(result)).toContain('unknown tool "wait_agent"') expect('default' in toolTeam).toBe(false) expect(toolTeam.name).toBe('tool-agent-team') - expect(toolTeam.inject).toEqual(['agents', 'agentTeams', 'tools', 'systemPrompt']) + expect(toolTeam.inject).toEqual(['agents', 'agentTeams', 'subagents', 'tools', 'systemPrompt']) }) }) diff --git a/packages/extensions/tool-cordis/src/api-catalog.ts b/packages/extensions/tool-cordis/src/api-catalog.ts index f506223049..888e4a96d9 100644 --- a/packages/extensions/tool-cordis/src/api-catalog.ts +++ b/packages/extensions/tool-cordis/src/api-catalog.ts @@ -3017,6 +3017,19 @@ export const SERVICE_API: readonly ServiceApiEntry[] = [ parameters: [{ name: 'spec', description: 'task, backend, and result recipient.' }], returns: 'activation with a message id only for local children.', }, + { + signature: 'nameOf(caller: Agent, id: SessionId = caller.id): string', + description: 'Read a model-facing name in the caller\'s tree, retaining legacy addresses for older unnamed children.', + parameters: [{ name: 'caller', description: 'exact live Agent selecting the tree.' }, { name: 'id', description: 'target identity; omission selects the caller.' }], + returns: 'lead, the immutable assigned name, or a legacy address.', + }, + { + signature: 'resolveName(caller: Agent, name: string, signal?: AbortSignal): Promise', + description: 'Resolve a tree-wide name without granting authority to act on its Agent.', + parameters: [{ name: 'caller', description: 'exact live Agent selecting the tree.' }, { name: 'name', description: 'a name returned by creation or discovery.' }, { name: 'signal', description: 'cancellation during historical discovery.' }], + returns: 'the durable Session identity for the consuming operation to authorize.', + throws: ['when the name is absent or the caller\'s live tree is unavailable.'], + }, { signature: 'async waitForChildren(parent: Agent): Promise', description: 'Join progressing descendants without cancelling them. Idle descendants whose inboxes require a later wake stay resident and do not delay host completion.', @@ -7785,11 +7798,11 @@ export const TYPE_API: readonly TypeApiEntry[] = [ }, { name: 'SubagentActivation', - declaration: 'export interface SubagentActivation {\n readonly childId: SessionId;\n readonly messageId?: MessageId;\n readonly result: Promise;\n dispose(): Promise;\n}', + declaration: 'export interface SubagentActivation {\n readonly name: string;\n readonly childId: SessionId;\n readonly messageId?: MessageId;\n readonly result: Promise;\n dispose(): Promise;\n}', }, { name: 'SubagentActivationSpec', - declaration: 'export interface SubagentActivationSpec {\n readonly provider: string;\n readonly label: string;\n readonly childId?: SessionId;\n readonly request: Omit;\n readonly signal: AbortSignal;\n readonly delivery: \'parent\' | \'caller\';\n}', + declaration: 'export interface SubagentActivationSpec {\n readonly name: string;\n readonly provider: string;\n readonly label: string;\n readonly childId?: SessionId;\n readonly request: Omit;\n readonly signal: AbortSignal;\n readonly delivery: \'parent\' | \'caller\';\n}', }, { name: 'SubagentCapabilities', @@ -7857,7 +7870,7 @@ export const TYPE_API: readonly TypeApiEntry[] = [ }, { name: 'SubagentRuntime', - declaration: 'export class SubagentRuntime extends TypertRemoteService {\n static Config;\n static inject;\n constructor(ctx: Context, private config: Config);\n resolveMaxDepth(configured?: number | \'provider-managed\'): number | undefined;\n startActivation(spec: SubagentActivationSpec & {\n readonly childId: SessionId;\n }): Promise;\n startActivation(spec: SubagentActivationSpec): Promise;\n async startActivation(spec: SubagentActivationSpec): Promise;\n async waitForChildren(parent: Agent): Promise;\n async sendMessage(sender: Agent, targetId: SessionId, content: ContentBlock[], options: SubagentSendMessageOptions): Promise;\n interrupt(targetSessionId: SessionId, authority: SubagentInterruptAuthority): void;\n async drainDescendants(parents: readonly Agent[]): Promise;\n async drainChildren(parent: Agent, childIds: readonly SessionId[]): Promise;\n listChildren(parentSessionId: SessionId, signal?: AbortSignal): Promise;\n listDescendants(rootSessionId: SessionId, signal?: AbortSignal): Promise;\n @Remote(\'prompt\')\n async prompt(request: SubagentPromptRequest, signal: AbortSignal): Promise;\n @Remote(\'interruptByParent\')\n interruptByParent(childSessionId: SessionId, parentSessionId: SessionId, mode: \'continuable\'): SubagentIn /* …truncated — full shape in source */', + declaration: 'export class SubagentRuntime extends TypertRemoteService {\n static Config;\n static inject;\n constructor(ctx: Context, private config: Config);\n resolveMaxDepth(configured?: number | \'provider-managed\'): number | undefined;\n startActivation(spec: SubagentActivationSpec & {\n readonly childId: SessionId;\n }): Promise;\n startActivation(spec: SubagentActivationSpec): Promise;\n async startActivation(spec: SubagentActivationSpec): Promise;\n nameOf(caller: Agent, id: SessionId = caller.id): string;\n resolveName(caller: Agent, name: string, signal?: AbortSignal): Promise;\n async waitForChildren(parent: Agent): Promise;\n async sendMessage(sender: Agent, targetId: SessionId, content: ContentBlock[], options: SubagentSendMessageOptions): Promise;\n interrupt(targetSessionId: SessionId, authority: SubagentInterruptAuthority): void;\n async drainDescendants(parents: readonly Agent[]): Promise;\n async drainChildren(parent: Agent, childIds: readonly SessionId[]): Promise;\n listChildren(parentSessionId: SessionId, signal?: AbortSignal): Promise;\n listDescendants(rootSessionId: SessionId, signal?: AbortSignal): Promise;\n @Remote(\'prompt\')\n async prompt(request: SubagentPromptRequest, signal: AbortSignal): Promise { const start = async (parent: Agent, id: SessionId): Promise => { const gate = { entered: Promise.withResolvers(), release: Promise.withResolvers() } gates.set(id, gate) - const receipt = await ctx.subagents.startActivation({ + const receipt = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, provider: 'local-test', childId: id, label: 'parked child', delivery: 'caller', signal: new AbortController().signal, request: { parent, prompt: [{ type: 'text', text: 'work' }] }, }) diff --git a/packages/sdk/server/tests/wait.spec.ts b/packages/sdk/server/tests/wait.spec.ts index 7da1b35f21..b147e366a1 100644 --- a/packages/sdk/server/tests/wait.spec.ts +++ b/packages/sdk/server/tests/wait.spec.ts @@ -1,3 +1,4 @@ +import { randomUUID } from 'node:crypto' import { mountWorkingDirectoryFixture } from '../../../subagent/subagent/tests/working-directory-fixture.ts' /** SDK task completion retains live failures that have no durable terminal outcome. */ import { Context } from '@deepseek-ai/cordis' @@ -64,7 +65,7 @@ describe('SDK session/wait with parked child input', () => { let owner = parent let child = parent for (let level = 0; level < depth; level++) { - const started = await ctx.subagents.startActivation({ + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, provider: 'local-test', label: 'interruptible child', delivery: 'caller', signal: new AbortController().signal, request: { parent: owner, prompt: [{ type: 'text', text: 'work' }] }, }) @@ -116,7 +117,7 @@ describe('SDK session/wait failures', () => { prepareContinuable: () => Promise.resolve({}), }) const warnings = vi.spyOn(ctx.logger, 'warn') - const child = await ctx.subagents.startActivation({ + const child = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, provider: 'local-test', label: 'child failure', delivery: 'caller', signal: new AbortController().signal, request: { parent, prompt: [{ type: 'text', text: 'delegated task' }] }, }) diff --git a/packages/subagent/subagent-acp/tests/fixtures/loader/mock-delegating-llm.ts b/packages/subagent/subagent-acp/tests/fixtures/loader/mock-delegating-llm.ts index d1e51f5ee5..07f52d9b42 100644 --- a/packages/subagent/subagent-acp/tests/fixtures/loader/mock-delegating-llm.ts +++ b/packages/subagent/subagent-acp/tests/fixtures/loader/mock-delegating-llm.ts @@ -14,7 +14,7 @@ class MockDelegatingAdapter extends LlmAdapter { : '' if (!options.messages.some(message => message.role === 'tool')) { - const args = JSON.stringify({ description: 'cwd probe', prompt: 'report your workspace' }) + const args = JSON.stringify({ name: 'loader-child', description: 'cwd probe', prompt: 'report your workspace' }) yield { type: 'block-start', index: 0, blockType: 'tool-call' } yield { type: 'tool-call-delta', index: 0, id: ToolCallId('call-delegate'), name: 'subagent', argumentsDelta: args } yield { type: 'block-end', index: 0, block: { type: 'tool-call', id: ToolCallId('call-delegate'), name: 'subagent', arguments: args } } diff --git a/packages/subagent/subagent-acp/tests/loader-composition.e2e.ts b/packages/subagent/subagent-acp/tests/loader-composition.e2e.ts index 7d32f04fee..d153c1883f 100644 --- a/packages/subagent/subagent-acp/tests/loader-composition.e2e.ts +++ b/packages/subagent/subagent-acp/tests/loader-composition.e2e.ts @@ -43,7 +43,7 @@ function settlementText(events: SessionEvent[]): string[] { const notice = notices[0]! if (notice.type !== 'user/message' || notice.data.source.kind !== 'subagent-settled') throw new Error('missing completion notice') expect(results[0]!.data.message.content).toEqual([ - { type: 'text', text: `started subagent ${notice.data.source.senderSessionId}` }, + { type: 'text', text: 'started subagent loader-child' }, ]) return notice.data.content.slice(1).filter(block => block.type === 'text').map(block => block.text) } diff --git a/packages/subagent/subagent-dsh-sdk/tests/fixtures/loader/mock-delegating-llm.ts b/packages/subagent/subagent-dsh-sdk/tests/fixtures/loader/mock-delegating-llm.ts index dee4ac0f45..c11bb25269 100644 --- a/packages/subagent/subagent-dsh-sdk/tests/fixtures/loader/mock-delegating-llm.ts +++ b/packages/subagent/subagent-dsh-sdk/tests/fixtures/loader/mock-delegating-llm.ts @@ -32,7 +32,7 @@ class MockDelegatingAdapter extends LlmAdapter { const selectedRoute = process.env.DSH_TEST_CHILD_DEFAULT_ROUTE === '1' ? { reasoning_effort: 'max' } : { provider: 'mock', model: 'mock-routed', reasoning_effort: 'max' } - const args = JSON.stringify({ + const args = JSON.stringify({ name: 'loader-child', description: 'route probe', prompt: 'report your route and workspace', ...selectedRoute, diff --git a/packages/subagent/subagent-dsh-sdk/tests/fixtures/loader/nested-mock-llm.ts b/packages/subagent/subagent-dsh-sdk/tests/fixtures/loader/nested-mock-llm.ts index 25748da58a..d20609db83 100644 --- a/packages/subagent/subagent-dsh-sdk/tests/fixtures/loader/nested-mock-llm.ts +++ b/packages/subagent/subagent-dsh-sdk/tests/fixtures/loader/nested-mock-llm.ts @@ -20,7 +20,7 @@ class NestedAdapter extends LlmAdapter { } answer = 'nested child result' } else if (!options.messages.some(message => message.role === 'tool')) { - const args = JSON.stringify({ description: 'nested fork', prompt: 'nested-child-task' }) + const args = JSON.stringify({ name: 'loader-child', description: 'nested fork', prompt: 'nested-child-task' }) const id = ToolCallId('nested-fork') yield { type: 'block-start', index: 0, blockType: 'tool-call' } yield { type: 'tool-call-delta', index: 0, id, name: 'subagent_fork', argumentsDelta: args } diff --git a/packages/subagent/subagent-dsh-sdk/tests/loader-composition.e2e.ts b/packages/subagent/subagent-dsh-sdk/tests/loader-composition.e2e.ts index 3e8b4c2b4d..d4b4a9be51 100644 --- a/packages/subagent/subagent-dsh-sdk/tests/loader-composition.e2e.ts +++ b/packages/subagent/subagent-dsh-sdk/tests/loader-composition.e2e.ts @@ -47,7 +47,7 @@ function settlementText(events: SessionEvent[]): string[] { const notice = notices[0]! if (notice.type !== 'user/message' || notice.data.source.kind !== 'subagent-settled') throw new Error('missing completion notice') expect(results[0]!.data.message.content).toEqual([ - { type: 'text', text: `started subagent ${notice.data.source.senderSessionId}` }, + { type: 'text', text: 'started subagent loader-child' }, ]) return notice.data.content.slice(1).filter(block => block.type === 'text').map(block => block.text) } diff --git a/packages/subagent/subagent/README.i18n.yaml b/packages/subagent/subagent/README.i18n.yaml index 2e2a850a13..3201620685 100644 --- a/packages/subagent/subagent/README.i18n.yaml +++ b/packages/subagent/subagent/README.i18n.yaml @@ -18,17 +18,17 @@ en: 924b8c15f9529028 zh: 9fb0c399b5a79e3e /deepseek-ai-dsh-subagent/use-this-package/enabling-delegation: - en: 388ae5427c869173 - zh: aff830f4986cf1b3 + en: ae565bb3cf491799 + zh: 6c71c30e5e284a31 /deepseek-ai-dsh-subagent/use-this-package/delegation-settings: en: 86c982223fab1a3a zh: 3d220d8ed84eab9a /deepseek-ai-dsh-subagent/use-this-package/activation-capacity: - en: 7c9548b9d02efe1f - zh: e23bd30b4c9cdabd + en: c888e23af70b5635 + zh: f9be27ef7833c4fc /deepseek-ai-dsh-subagent/use-this-package/local-and-external-children: - en: 013644290e74493e - zh: 05014c3c3773edeb + en: bd9389d8daac973d + zh: 942a10b183cacc47 /deepseek-ai-dsh-subagent/use-this-package/child-presets: en: a740e5e9bdd661d9 zh: 712a5458fc8b3615 diff --git a/packages/subagent/subagent/README.md b/packages/subagent/subagent/README.md index a1d9fcd93f..1405400040 100644 --- a/packages/subagent/subagent/README.md +++ b/packages/subagent/subagent/README.md @@ -42,7 +42,7 @@ Mount the service with a provider and the delegation tool. The provider register toolName: subagent ``` -The tool returns a child session id immediately. The parent receives a completion notice when the background activation settles. Mounting the service alone enables no delegation. +The tool requires a unique agent name and returns it immediately. The parent receives a completion notice when the background activation settles. Mounting the service alone enables no delegation. ### Delegation settings @@ -56,9 +56,12 @@ The current `maxActiveSubagents` value is sampled before every new or cold-resum At capacity, creation or cold resume rejects with `ACTIVATION_LIMIT_REACHED` (browser prompts receive `subagent/delivery-unavailable`): wait for a child to finish or continue using the existing agents. Admission does not queue, because a parent waiting for descendants must not wait for its own occupied slot. Slots are process-local and do not constrain cumulative Session history or token usage. + ### Local and external children -`startActivation({ provider, label, request, signal, delivery })` returns `{ childId, messageId?, result, dispose }`. Supplying `childId` selects a local backend and guarantees `messageId`. Local children accept later messages and can cold-resume; external children expose one execution and reject continuation. `request.agentOptions` overrides supported child model settings. `delivery: 'parent'` supplies the model-facing completion notice; `delivery: 'caller'` lets workflows await the result without a parent notice or initial return guidance. Local parent delivery requires persistence; caller delivery can use an ephemeral local session. Cold resume requires persistence and Session query. +`startActivation({ name, provider, label, request, signal, delivery })` returns `{ childId, name, messageId?, result, dispose }`. Supplying `childId` selects a local backend and guarantees `messageId`. Local children accept later messages and can cold-resume; external children expose one execution and reject continuation. `request.agentOptions` overrides supported child model settings. `delivery: 'parent'` supplies the model-facing completion notice; `delivery: 'caller'` lets workflows await the result without a parent notice or initial return guidance. Local parent delivery requires persistence; caller delivery can use an ephemeral local session. Cold resume requires persistence and Session query. + +Agent names are immutable and unique throughout one agent tree; its root is `lead`. Creation requires a lower-case letter followed by lower-case letters, digits, underscores, or hyphens; `lead` and `unowned` are reserved. `SubagentNames` reserves before asynchronous preparation, releases failed unpublished starts, and records successful assignments as `subagent/named` in the root Session. The `subagentNames` projection retains assignments after settlement and restart and excludes fork-inherited events. `nameOf()` and `resolveName()` translate between names and stable Session ids without granting operation authority. Older unnamed descendants use `legacy:` addresses. ### Child presets diff --git a/packages/subagent/subagent/README.zh.md b/packages/subagent/subagent/README.zh.md index 624591227b..795a7ffc1c 100644 --- a/packages/subagent/subagent/README.zh.md +++ b/packages/subagent/subagent/README.zh.md @@ -42,7 +42,7 @@ kind: "package-reference" toolName: subagent ``` -工具立即返回子会话 ID,后台 activation 结算后父级收到完成通知。仅挂载服务本身不会启用委派。 +工具要求唯一的 agent 名字,并立即返回该名字。后台 activation 结束时,父级收到完成通知。只挂载服务不会启用委派。 ### 委派设置 @@ -56,9 +56,12 @@ kind: "package-reference" 容量耗尽时,新建或冷恢复以 `ACTIVATION_LIMIT_REACHED` 拒绝(浏览器消息返回 `subagent/delivery-unavailable`):等待子代理完成,或继续使用现有代理。接纳不会排队,避免等待后代的父代理又等待自己占用的名额。名额仅存在于当前进程,不限制累计 Session 历史或 token 用量。 + ### 本地与外部子级 -`startActivation({ provider, label, request, signal, delivery })` 返回 `{ childId, messageId?, result, dispose }`。提供 `childId` 会选择本地后端,并保证返回 `messageId`。本地子级接受后续消息并支持冷恢复;外部子级只暴露一次执行,拒绝继续输入。`request.agentOptions` 覆盖后端支持的子级模型设置。`delivery: 'parent'` 提供面向模型的完成通知;`delivery: 'caller'` 让工作流等待结果,不发送父级通知,也不附加初始返回指导。本地父级投递需要持久化,调用方投递可以使用临时本地会话;冷恢复需要持久化与 Session 查询服务。 +`startActivation({ name, provider, label, request, signal, delivery })` 返回 `{ childId, name, messageId?, result, dispose }`。提供 `childId` 会选择本地后端,并保证返回 `messageId`。本地子级接受后续消息,支持冷恢复;外部子级只执行一次,拒绝继续执行。`request.agentOptions` 覆盖受支持的子级模型设置。`delivery: 'parent'` 提供面向模型的完成通知;`delivery: 'caller'` 允许 workflow 等待结果,不发送父级通知或初始返回指引。本地 parent 交付要求持久化;caller 交付可使用临时本地会话。冷恢复要求持久化和 Session query。 + +agent 名字不可变,在整棵 agent 树内唯一;根名为 `lead`。创建时必须以小写字母开头,后续只能包含小写字母、数字、下划线或连字符;`lead` 和 `unowned` 为保留名。`SubagentNames` 在异步准备前预留名字,释放失败且未发布的启动,并将成功分配作为 `subagent/named` 记录在根 Session 中。`subagentNames` 投影在结束和重启后保留分配,排除分叉继承的事件。`nameOf()` 和 `resolveName()` 在名字与稳定 Session id 之间转换,不授予操作权限。旧的无名后代使用 `legacy:` 地址。 ### 子级 preset diff --git a/packages/subagent/subagent/src/activation.ts b/packages/subagent/subagent/src/activation.ts index ec66fa9ece..b3385ac38e 100644 --- a/packages/subagent/subagent/src/activation.ts +++ b/packages/subagent/subagent/src/activation.ts @@ -40,6 +40,8 @@ export class ActivationPool { * The manager owns admission, execution handles, and resource release. */ interface ActivationBase { + /** Immutable model-facing name retained through teardown. */ + readonly name: string /** Shared capacity for this Activation and all its managed descendants. */ readonly pool: ActivationPool /** Return this epoch's slot after its handle has finished disposal. */ diff --git a/packages/subagent/subagent/src/continuation-messages.ts b/packages/subagent/subagent/src/continuation-messages.ts index 7e80a9e007..cf80589c42 100644 --- a/packages/subagent/subagent/src/continuation-messages.ts +++ b/packages/subagent/subagent/src/continuation-messages.ts @@ -56,15 +56,17 @@ function agentMessageSource(sender: Agent): AgentMessageSource { * Build the model-visible and durable representation of one adjacent-Agent message. * @param sender - exact live Agent that authored the message. * @param content - model-visible message blocks supplied by the sender. + * @param senderName - immutable tree-wide name shown to the recipient. * @returns the durable user-message representation delivered to the recipient. */ export function createAgentMessage( sender: Agent, content: ContentBlock[], + senderName: string, ): ReturnType { return createUserMessage({ content: [ - { type: 'text' as const, text: `Agent ${sender.id} sent a message: ` }, + { type: 'text' as const, text: `Agent ${senderName} sent a message: ` }, ...content, ], source: agentMessageSource(sender), @@ -73,21 +75,23 @@ export function createAgentMessage( /** * Append adjacent-Agent return guidance to a continuable child's initial task. - * @param parentId - durable parent session id named in the guidance. + * @param parentName - name of the direct parent. + * @param childName - name assigned to this child. * @param prompt - initial model-visible task blocks. * @returns task blocks followed by the continuable return guidance. */ export function withContinuableReturnGuidance( - parentId: SessionId, + parentName: string, + childName: string, prompt: ContentBlock[], ): ContentBlock[] { - const encodedParentId = JSON.stringify(parentId) + const encodedParentName = JSON.stringify(parentName) return [ ...prompt, { type: 'text', - text: `Your parent agent id is ${encodedParentId}. Before you finish, send your result to that agent with ` - + `send_message({ agent_id: ${encodedParentId}, message: "" }). The parent shares ` + text: `Your name is ${JSON.stringify(childName)}. Your parent agent name is ${encodedParentName}. Before you finish, send your result to that agent with ` + + `send_message({ name: ${encodedParentName}, message: "" }). The parent shares ` + 'your workspace but does not automatically receive your transcript, tool output, or reasoning. Send ' + 'earlier messages as well when a finding changes what the parent should do next; sending a message ' + 'does not end your turn.', @@ -98,13 +102,13 @@ export function withContinuableReturnGuidance( /** * One line telling a parent that a background child is finished and why, in * the parent's own task vocabulary. - * @param childId - the durable child the parent knows by id. + * @param childName - the immutable name the parent uses for the child. * @param stopReason - how the child's last ordinary turn ended. * @param continuable - whether the child accepts a later message. * @returns the model-facing opening line of the settlement notice. */ -function settlementSummary(childId: SessionId, stopReason: SubagentResult['stopReason'], continuable: boolean): string { - const subject = `Background subagent ${childId}` +function settlementSummary(childName: string, stopReason: SubagentResult['stopReason'], continuable: boolean): string { + const subject = `Background subagent ${childName}` switch (stopReason) { case 'completed': return continuable @@ -130,17 +134,19 @@ function settlementSummary(childId: SessionId, stopReason: SubagentResult['stopR /** * Build the runtime-owned settlement notice from the child's nonempty closing text. - * @param childId - durable child session id named in the notice. + * @param childId - durable child identity retained in message attribution. + * @param childName - immutable name shown in the notice. * @param terminal - recorded terminal state for the settled Activation. * @param continuable - whether the child can accept another task. * @returns the durable user-message representation delivered to the parent. */ export function createSettlementMessage( childId: SessionId, + childName: string, terminal: SubagentResult, continuable = true, ): ReturnType { - const summary = settlementSummary(childId, terminal.stopReason, continuable) + const summary = settlementSummary(childName, terminal.stopReason, continuable) // Parent providers receive this notice as a user message and may reject // nontext assistant blocks. Keep this conversion local so SDK/UI consumers // retain the complete child output. diff --git a/packages/subagent/subagent/src/index.ts b/packages/subagent/subagent/src/index.ts index b9fcd36922..3056cd53ec 100644 --- a/packages/subagent/subagent/src/index.ts +++ b/packages/subagent/subagent/src/index.ts @@ -75,6 +75,7 @@ import { installSubagentArchiveAdmission } from './archive-admission.ts' import type { SubagentCatalogEntry } from './projection-types.ts' import { subagentIdentityProjectionDefinition, subagentTimingProjectionDefinition } from './projection.ts' import { subagentCatalogProjectionDefinition } from './catalog.ts' +import { subagentNamesProjectionDefinition } from './names.ts' import { deliverSubagentPrompt } from './internal.ts' export type {} from './catalog.ts' @@ -227,6 +228,7 @@ export class SubagentRuntime extends TypertRemoteService { }) ctx.inject(['sessionProjections'], (projectionCtx) => { projectionCtx.sessionProjections.register(subagentCatalogProjectionDefinition) + projectionCtx.sessionProjections.register(subagentNamesProjectionDefinition) projectionCtx.sessionProjections.register(subagentTimingProjectionDefinition) projectionCtx.sessionProjections.register(subagentIdentityProjectionDefinition) }) @@ -284,6 +286,28 @@ export class SubagentRuntime extends TypertRemoteService { : manager.startLocal(spec) } + /** + * Read a model-facing name in the caller's tree, retaining legacy addresses for older unnamed children. + * @param caller - exact live Agent selecting the tree. + * @param id - target identity; omission selects the caller. + * @returns lead, the immutable assigned name, or a legacy address. + */ + nameOf(caller: Agent, id: SessionId = caller.id): string { + return this.requireManager().names.nameOf(caller, id) + } + + /** + * Resolve a tree-wide name without granting authority to act on its Agent. + * @param caller - exact live Agent selecting the tree. + * @param name - a name returned by creation or discovery. + * @param signal - cancellation during historical discovery. + * @returns the durable Session identity for the consuming operation to authorize. + * @throws when the name is absent or the caller's live tree is unavailable. + */ + resolveName(caller: Agent, name: string, signal?: AbortSignal): Promise { + return this.requireManager().names.resolve(caller, name, signal) + } + /** * Join progressing descendants without cancelling them. Idle descendants whose * inboxes require a later wake stay resident and do not delay host completion. diff --git a/packages/subagent/subagent/src/manager.ts b/packages/subagent/subagent/src/manager.ts index 998c7e7913..1755557b44 100644 --- a/packages/subagent/subagent/src/manager.ts +++ b/packages/subagent/subagent/src/manager.ts @@ -33,6 +33,7 @@ import type { SubagentDescriptorData } from './descriptor.ts' import { establishCatalogChild, establishExternalCatalogChild, liveCatalogEntries } from './catalog.ts' import type { SubagentCatalogEntry } from './projection-types.ts' import { SubagentError } from './error.ts' +import { SubagentNames } from './names.ts' import { isAdjacentAgentSendMessageTool } from './internal.ts' import type { ActivationObserver } from './lifecycle.ts' import type { @@ -70,6 +71,7 @@ interface SubagentHost { /** Inputs shared by fresh and resumed Activation materialization. */ interface MaterializeBase { + name: string childId: SessionId provider: string parent: Agent @@ -131,6 +133,8 @@ function failureMessage(error: unknown): string { /** Own subagent requests and the resources of every live activation. */ export class SubagentManager { + /** Tree-wide durable names and pending creation reservations. */ + readonly names: SubagentNames /** Child session id → its live Activation. Process-local, never durable. */ private readonly resident = new Map() /** Root identities retain their pool across child settlement without retaining dead roots. */ @@ -167,6 +171,7 @@ export class SubagentManager { // the drain before releasing the scope; a cleanup effect on the same scope // as the Agent handles would let structural handle disposal bypass // child-first ordering. + this.names = new SubagentNames(ctx) const scope = ctx.plugin(function activationOwner() {}) this.ownerCtx = scope.ctx ctx.on('agent/disposed', ({ agent }) => { @@ -387,6 +392,7 @@ export class SubagentManager { assertSubagentMaxDepth(request.maxDepth) const childId = spec.childId ?? brandString(randomUUID()) this.assertChildIdAvailable(childId) + using reservation = this.names.reserve(parent, spec.name) const childDepth = resolveChildDepth(parent, request.maxDepth) // Snapshot before any await: invalid descriptor JSON rejects the call // before a child exists, and the detached value is what reaches the log. @@ -439,6 +445,7 @@ export class SubagentManager { } const activation = await this.materialize({ kind: 'local', + name: spec.name, childId, provider: spec.provider, parent, @@ -462,12 +469,13 @@ export class SubagentManager { return await this.submitMaterialized( activation, spec.delivery !== 'caller' && isAdjacentAgentSendMessageTool(this.ctx.get('tools')?.get('send_message', child)) - ? withContinuableReturnGuidance(parent.id, request.prompt) + ? withContinuableReturnGuidance(this.names.nameOf(parent), spec.name, request.prompt) : request.prompt, { source: { kind: 'user' }, signal: spec.signal, delivery: 'queue' }, parent, () => { establishCatalogChild(parent.session, childHeader, descriptor) + reservation.commit(childId) }, ) }) @@ -495,6 +503,7 @@ export class SubagentManager { async startExternal(spec: SubagentActivationSpec): Promise { const parent = spec.request.parent this.assertAdmitting(parent) + using reservation = this.names.reserve(parent, spec.name) const pendingId = brandString(randomUUID()) const releaseHold = this.holdOwnership(parent, pendingId) let activation: Activation | undefined @@ -502,6 +511,7 @@ export class SubagentManager { const cwd = await this.resolveDirectory(spec.request, spec.signal) activation = await this.materialize({ kind: 'external', + name: spec.name, childId: pendingId, provider: spec.provider, parent, @@ -517,6 +527,7 @@ export class SubagentManager { if (spec.delivery === 'parent') { establishExternalCatalogChild(parent.session, activation.childId, spec.label) } + reservation.commit(activation.childId) this.announce(activation) return this.receipt(activation) } catch (error: unknown) { @@ -576,7 +587,7 @@ export class SubagentManager { } if (resident !== undefined && targetId !== sender.id && this.catalogOf(resident.parent.session).some(child => child.id === targetId && child.mode === 'continuable')) { - const message = createAgentMessage(sender, content) + const message = createAgentMessage(sender, content, this.names.nameOf(sender)) return this.deliverToChild(resident.parent, targetId, [...message.content], { signal: options.signal, delivery: 'steer', @@ -942,6 +953,7 @@ export class SubagentManager { const observer = this.host.observeActivation(provider, childId, parent) const activation: Activation = { + name: inputs.name, pool, releaseSlot, childId, @@ -1206,7 +1218,7 @@ export class SubagentManager { const parent = this.ctx.agents.get(activation.parent.id) if (parent !== activation.parent) return const message = createSettlementMessage( - activation.childId, terminal, activationAgent(activation) !== undefined, + activation.childId, activation.name, terminal, activationAgent(activation) !== undefined, ) if (this.closingTeardownFor(parent) !== undefined) { parent.inject(message) @@ -1237,6 +1249,7 @@ export class SubagentManager { private receipt(activation: Activation): SubagentActivation { return { childId: activation.childId, + name: activation.name, result: activation.result.promise, dispose: () => this.dispose(activation), } @@ -1317,7 +1330,7 @@ export class SubagentManager { 'PARENT_UNAVAILABLE', ) } - const message = createAgentMessage(sender, content) + const message = createAgentMessage(sender, content, this.names.nameOf(sender)) this.sendAgentMessage(parent, message) return message.id } @@ -1378,6 +1391,7 @@ export class SubagentManager { } activation = await this.materialize({ kind: 'local', + name: this.names.nameOf(parent, childId), childId, provider: descriptor.provider, parent, @@ -1442,7 +1456,7 @@ export class SubagentManager { parent: Agent, ): MessageId { const message = options.source === undefined - ? createAgentMessage(parent, content) + ? createAgentMessage(parent, content, this.names.nameOf(parent)) : createUserMessage({ content, source: options.source }) options.signal.throwIfAborted() this.assertAdmitting(parent) diff --git a/packages/subagent/subagent/src/names.ts b/packages/subagent/subagent/src/names.ts new file mode 100644 index 0000000000..d4a2244956 --- /dev/null +++ b/packages/subagent/subagent/src/names.ts @@ -0,0 +1,164 @@ +/** Durable tree-wide agent names and unpublished creation reservations. + * @module @deepseek-ai/dsh-subagent/names + */ + +import type { Context } from '@deepseek-ai/cordis' +import type { Agent } from '@deepseek-ai/dsh-agent' +import { SessionId, SessionLogOffset } from '@deepseek-ai/dsh-session' +import type { Session, SessionEvent, SessionHeader } from '@deepseek-ai/dsh-session' +import type { ProjectionDefinition } from '@deepseek-ai/dsh-session-projection' +import { z } from 'zod' +import { SubagentError } from './error.ts' +import { listDescendants } from './list-children.ts' + +/** One immutable name assigned in the root Session before child publication. */ +export interface SubagentNameData { + readonly name: string + readonly id: SessionId +} + +declare module '@deepseek-ai/dsh-session/types' { + interface SessionEventMap { + /** + * A tree-wide agent name, retained after its execution ends. + * @param data - the name and durable child identity. + */ + 'subagent/named': SubagentNameData + } +} + +/** Root-owned name assignments, excluding fork-inherited events. */ +export interface SubagentNamesState { + readonly inheritedEventCount: SessionLogOffset + readonly entries: readonly SubagentNameData[] +} + +declare module '@deepseek-ai/dsh-session-projection/types' { + interface SessionProjectionStateMap { + subagentNames: SubagentNamesState + } +} + +const nameSchema = z.string().regex(/^[a-z][a-z0-9_-]*$/).refine(value => value !== 'lead' && value !== 'unowned') +const entrySchema = z.object({ name: nameSchema, id: z.string().transform(SessionId) }).strict() + +const stateSchema: z.ZodType = z.object({ + inheritedEventCount: z.number().int().nonnegative().transform(SessionLogOffset), + entries: z.array(entrySchema), +}).strict().refine(state => new Set(state.entries.map(entry => entry.name)).size === state.entries.length + && new Set(state.entries.map(entry => entry.id)).size === state.entries.length, 'duplicate persisted agent name or identity') + +/** Host-only name projection; corrupt duplicate assignments reject restoration. */ +export const subagentNamesProjectionDefinition = { + key: 'subagentNames', + stateVersion: 0, + stateSchema, + init: (_header: SessionHeader, inheritedEventCount: SessionLogOffset): SubagentNamesState => ({ inheritedEventCount, entries: [] }), + apply: (state, event: SessionEvent) => { + if (event.type !== 'subagent/named' || event.seq < state.inheritedEventCount) return state + const entry = entrySchema.parse(event.data) + if (state.entries.some(existing => existing.name === entry.name || existing.id === entry.id)) { + throw new SubagentError('duplicate persisted agent name or identity; restore a valid Session log', 'CORRUPT_AGENT_NAMES') + } + return { ...state, entries: [...state.entries, entry] } + }, +} satisfies ProjectionDefinition<'subagentNames', SubagentNamesState> + +/** Owns creation reservations; committed assignments come only from the root projection. */ +export class SubagentNames { + private readonly pending = new WeakMap>() + + /** @param ctx - subagent service context with live Agents and Session projections. */ + constructor(private readonly ctx: Context) {} + + /** + * Reserve a unique name before asynchronous child preparation. + * @param parent - exact live spawning Agent. + * @param name - explicit lower-case name; lead and unowned are reserved. + * @returns a publication operation and an idempotent unpublished-reservation release. + * @throws when the name is invalid, taken, or the live tree is unavailable. + */ + reserve(parent: Agent, name: string): { commit(id: SessionId): void; [Symbol.dispose](): void } { + if (!nameSchema.safeParse(name).success) { + throw new SubagentError('agent name must start with a lower-case letter and contain only lower-case letters, digits, underscores, or hyphens; lead and unowned are reserved', 'INVALID_AGENT_NAME') + } + const root = this.rootOf(parent) + let pending = this.pending.get(root.session) + if (pending === undefined) { + pending = new Set() + this.pending.set(root.session, pending) + } + if (pending.has(name) || this.entries(root.session).some(entry => entry.name === name)) { + throw new SubagentError(`agent name "${name}" is already in use in this tree; choose another name`, 'DUPLICATE_AGENT_NAME') + } + pending.add(name) + return { + commit: (id) => { + if (this.rootOf(parent) !== root) throw new SubagentError('agent tree changed during creation', 'AGENT_TREE_UNAVAILABLE') + root.session.append('subagent/named', { name, id }) + }, + [Symbol.dispose]: () => { pending.delete(name) }, + } + } + + /** + * Read an agent's model-facing name in the caller's tree. + * @param caller - exact live Agent selecting the tree. + * @param id - target identity; defaults to the caller. + * @returns lead, an assigned name, or a stable legacy address for an older unnamed identity. + */ + nameOf(caller: Agent, id: SessionId = caller.id): string { + const root = this.rootOf(caller) + if (id === root.id) return 'lead' + return this.entries(root.session).find(entry => entry.id === id)?.name ?? `legacy:${id}` + } + + /** + * Resolve a name without granting message, interrupt, or assignment authority. + * @param caller - exact live Agent selecting the tree. + * @param name - assigned name or a legacy address returned by discovery. + * @param signal - cancellation during legacy catalog discovery. + * @returns the durable identity; the consuming operation still authorizes access. + * @throws when the name is absent from the caller's tree. + */ + async resolve(caller: Agent, name: string, signal?: AbortSignal): Promise { + signal?.throwIfAborted() + const root = this.rootOf(caller) + if (name === 'lead') return root.id + const entries = this.entries(root.session) + const entry = entries.find(candidate => candidate.name === name) + if (entry !== undefined) return entry.id + if (name.startsWith('legacy:')) { + const id = SessionId(name.slice('legacy:'.length)) + if (!entries.some(candidate => candidate.id === id) + && (await listDescendants(this.ctx, root.id, signal)).some(candidate => candidate.id === id)) return id + } + throw new SubagentError(`agent name "${name}" was not found; use list_agents to discover available names`, 'AGENT_NAME_NOT_FOUND') + } + + /** Resolve only uninterrupted live subagent ancestry, never a fork's inherited parent. */ + private rootOf(caller: Agent): Agent { + if (this.ctx.agents.get(caller.id) !== caller) { + throw new SubagentError('agent naming requires the exact live caller', 'UNAUTHORIZED') + } + let root = caller + const seen = new Set() + while (root.session.header.origin === 'subagent') { + const parentId = root.session.header.parentSession + const parent = parentId === undefined ? undefined : this.ctx.agents.get(parentId) + seen.add(root.id) + if (parent === undefined || seen.has(parent.id)) { + throw new SubagentError('agent naming requires the live parent tree', 'AGENT_TREE_UNAVAILABLE') + } + root = parent + } + return root + } + + /** Read the authoritative root projection without keeping a second name index. */ + private entries(root: Session): readonly SubagentNameData[] { + const state = this.ctx.get('sessionProjections')?.stateOf(root, 'subagentNames') + if (state === undefined) throw new SubagentError('agent names require the subagentNames projection', 'CONTINUATION_UNAVAILABLE') + return state.entries + } +} diff --git a/packages/subagent/subagent/src/types.ts b/packages/subagent/subagent/src/types.ts index 2a99fef1bd..ed3ad170bf 100644 --- a/packages/subagent/subagent/src/types.ts +++ b/packages/subagent/subagent/src/types.ts @@ -29,6 +29,8 @@ export function SubagentRunId(id: string): SubagentRunId { /** One managed child execution and its result delivery policy. */ export interface SubagentActivationSpec { + /** Immutable name, unique across the parent's whole subagent tree. */ + readonly name: string /** Registered backend to use. */ readonly provider: string /** Short task label retained in cataloged child membership. */ @@ -45,6 +47,8 @@ export interface SubagentActivationSpec { /** A managed execution; disposal addresses this exact activation, never a later resume. */ export interface SubagentActivation { + /** Immutable name used by model-facing collaboration tools. */ + readonly name: string /** Stable identity of the child. */ readonly childId: SessionId /** Accepted inbox message, when the backend has a local inbox. */ diff --git a/packages/subagent/subagent/tests/activation-policy.spec.ts b/packages/subagent/subagent/tests/activation-policy.spec.ts index 38d9d44005..4cb2e27062 100644 --- a/packages/subagent/subagent/tests/activation-policy.spec.ts +++ b/packages/subagent/subagent/tests/activation-policy.spec.ts @@ -194,7 +194,7 @@ describe('in-process policy inheritance', () => { .join('\n') expect(systemText).not.toContain('Approval prompts are disabled') expect(systemText).not.toContain('You are a delegated subagent') - expect(parent.session.snapshotEvents().filter(event => event.type !== 'subagent/catalog')).toHaveLength(parentLogLength) + expect(parent.session.snapshotEvents().filter(event => event.type !== 'subagent/catalog' && event.type !== 'subagent/named')).toHaveLength(parentLogLength) } finally { await run.dispose() } diff --git a/packages/subagent/subagent/tests/continuation-inheritance.spec.ts b/packages/subagent/subagent/tests/continuation-inheritance.spec.ts index df8542f988..711d73f8cc 100644 --- a/packages/subagent/subagent/tests/continuation-inheritance.spec.ts +++ b/packages/subagent/subagent/tests/continuation-inheritance.spec.ts @@ -1,3 +1,4 @@ +import { randomUUID } from 'node:crypto' import { mountWorkingDirectoryFixture } from './working-directory-fixture.ts' /** * Continuable-child delegation policy: a fresh continuable start seeds the @@ -98,7 +99,7 @@ describe('continuable policy inheritance', () => { const current = vi.fn((session: Session) => session === parent.session ? preset : 'custom') ctx.provide('permissionPresets', { current } as never) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await waitNoActivation(ctx, started.childId) const loaded = await loadStoredSession(ctx.sessionPersistence, started.childId) @@ -145,7 +146,7 @@ describe('continuable policy inheritance', () => { current: (session: Session) => session === parent.session ? currentPreset : 'custom', } as never) - const starting = ctx.subagents.startActivation({ ...startSpec(parent, 'fork'), delivery: 'parent' }) + const starting = ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent, 'fork'), delivery: 'parent' }) currentPreset = seedPreset parent.session.append('permission/preset', { preset: seedPreset }) const started = await starting @@ -167,7 +168,7 @@ describe('continuable policy inheritance', () => { if (agent !== parent) child = agent }) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) // The delegation events are appended in the creation window, so they are // already the child's effective policy at inbox acceptance. if (child === undefined) throw new Error('expected the continuable child to be created') @@ -198,7 +199,7 @@ describe('continuable policy inheritance', () => { const { ctx, parent } = await setup([textResponse('child done')]) setSandboxMode(parent.session, 'read-only') - const starting = ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const starting = ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) // A parent switch after the synchronous capture belongs to the parent's // future, not to this child. setSandboxMode(parent.session, 'danger-full-access') @@ -213,7 +214,7 @@ describe('continuable policy inheritance', () => { it('leaves an unswitched sandbox on the deployment default while still pinning approval', { timeout: 20_000 }, async () => { const { ctx, parent } = await setup([textResponse('child done')]) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await waitNoActivation(ctx, started.childId) const loaded = await loadStoredSession(ctx.sessionPersistence, started.childId) @@ -231,7 +232,7 @@ describe('continuable policy inheritance', () => { })) await parent.whenIdle() - const started = await ctx.subagents.startActivation({ ...startSpec(parent, 'fork'), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent, 'fork'), delivery: 'parent' }) await waitNoActivation(ctx, started.childId) const loaded = await loadStoredSession(ctx.sessionPersistence, started.childId) @@ -250,7 +251,7 @@ describe('continuable policy inheritance', () => { if (agent !== parent) child = agent }) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) if (child === undefined) throw new Error('expected the continuable child to be created') expect(ctx.sandboxPolicy.overrideOf(child.session)).toBe('danger-full-access') // Last event wins: the child's own runtime switch beats the seeded snapshot. @@ -265,7 +266,7 @@ describe('continuable policy inheritance', () => { it('cold-resumes on the persisted snapshot without re-capturing the parent', { timeout: 20_000 }, async () => { const { ctx, parent } = await setup([textResponse('first'), textResponse('after resume')]) setSandboxMode(parent.session, 'read-only') - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await waitNoActivation(ctx, started.childId) // The parent widens AFTER the child was created; the resumed child keeps @@ -303,7 +304,7 @@ describe('continuable policy inheritance', () => { await parent.whenIdle() setSandboxMode(parent.session, 'read-only') - const started = await ctx.subagents.startActivation({ ...startSpec(parent, 'fork'), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent, 'fork'), delivery: 'parent' }) await waitNoActivation(ctx, started.childId) const loaded = await loadStoredSession(ctx.sessionPersistence, started.childId) diff --git a/packages/subagent/subagent/tests/continuation-messages-adapter.spec.ts b/packages/subagent/subagent/tests/continuation-messages-adapter.spec.ts index 7d4a5a266c..3196cc058d 100644 --- a/packages/subagent/subagent/tests/continuation-messages-adapter.spec.ts +++ b/packages/subagent/subagent/tests/continuation-messages-adapter.spec.ts @@ -1,3 +1,4 @@ +import { randomUUID } from 'node:crypto' import { mountWorkingDirectoryFixture } from './working-directory-fixture.ts' import { mkdtempSync, rmSync } from 'node:fs' import { tmpdir } from 'node:os' @@ -57,7 +58,7 @@ it('continues the parent through default Messages after a reasoning-bearing cont settled.resolve(undefined) }) - const started = await ctx.subagents.startActivation({ + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, delivery: 'parent', provider: 'spawn', label: 'child task', @@ -79,7 +80,7 @@ it('continues the parent through default Messages after a reasoning-bearing cont expect(requests.map(request => request.path)).toEqual(['/anthropic/v1/messages', '/anthropic/v1/messages']) const notice = parent.session.deriveMessages().find(message => message.source.kind === 'subagent-settled') const closingContent = [ - { type: 'text', text: `Background subagent ${started.childId} finished and will do no further work unless you send it more.` }, + { type: 'text', text: `Background subagent ${started.name} finished and will do no further work unless you send it more.` }, { type: 'text', text: 'Its closing message:' }, { type: 'text', text: 'child answer' }, ] diff --git a/packages/subagent/subagent/tests/continuation-messages.spec.ts b/packages/subagent/subagent/tests/continuation-messages.spec.ts index 9d91df3be3..20cf0eed7d 100644 --- a/packages/subagent/subagent/tests/continuation-messages.spec.ts +++ b/packages/subagent/subagent/tests/continuation-messages.spec.ts @@ -4,7 +4,7 @@ import { SessionId } from '@deepseek-ai/dsh-session' import { createSettlementMessage } from '../src/continuation-messages.ts' const childId = SessionId('settled-child') -const summary = { type: 'text', text: `Background subagent ${childId} finished and will do no further work unless you send it more.` } +const summary = { type: 'text', text: 'Background subagent reviewer finished and will do no further work unless you send it more.' } const reasoning: ContentBlock = { type: 'reasoning', text: 'private child reasoning' } const toolCall: ContentBlock = { type: 'tool-call', id: ToolCallId('child-call'), name: 'read', arguments: '{}' } @@ -14,7 +14,7 @@ describe('continuable settlement content', () => { ['a tool call after the answer', [{ type: 'text', text: 'answer' }, toolCall]], ] satisfies [string, ContentBlock[]][])('reports only the closing text with %s', (_label, output) => { const original = structuredClone(output) - const message = createSettlementMessage(childId, { stopReason: 'completed', output }) + const message = createSettlementMessage(childId, 'reviewer', { stopReason: 'completed', output }) expect(message.role).toBe('user') expect(message.content).toEqual([ @@ -30,7 +30,7 @@ describe('continuable settlement content', () => { ['reasoning-only output', [reasoning]], ['empty text', [{ type: 'text', text: '' }]], ] satisfies [string, ContentBlock[]][])('reports no closing message for %s', (_label, output) => { - const message = createSettlementMessage(childId, { stopReason: 'completed', output }) + const message = createSettlementMessage(childId, 'reviewer', { stopReason: 'completed', output }) expect(message.content).toEqual([ summary, @@ -41,7 +41,7 @@ describe('continuable settlement content', () => { it('preserves text block order and bytes around omitted reasoning and tool calls', () => { const first: ContentBlock = { type: 'text', text: ' first\n' } const second: ContentBlock = { type: 'text', text: '\n第二段 ' } - const message = createSettlementMessage(childId, { + const message = createSettlementMessage(childId, 'reviewer', { stopReason: 'completed', output: [reasoning, first, toolCall, second], }) @@ -56,7 +56,7 @@ describe('continuable settlement content', () => { }) it('includes closing text alongside structured results and diagnostics', () => { - expect(createSettlementMessage(childId, { + expect(createSettlementMessage(childId, 'reviewer', { stopReason: 'completed', output: [{ type: 'text', text: 'final answer' }], structured: { answer: 42 }, diagnostic: 'safe diagnostic', }).content).toEqual([ diff --git a/packages/subagent/subagent/tests/continuation-presets.spec.ts b/packages/subagent/subagent/tests/continuation-presets.spec.ts index 8e56926b4b..9cb78d5690 100644 --- a/packages/subagent/subagent/tests/continuation-presets.spec.ts +++ b/packages/subagent/subagent/tests/continuation-presets.spec.ts @@ -1,3 +1,4 @@ +import { randomUUID } from 'node:crypto' /** Independent spawn presets and compatibility of persisted child compositions. */ import { mountWorkingDirectoryFixture } from './working-directory-fixture.ts' @@ -80,6 +81,7 @@ function parkParent(ctx: Context, parent: Agent): void { function startSpec(parent: Agent, agentPreset?: string, provider = 'separate') { return { provider, + name: `child-${randomUUID()}`, label: 'preset work', delivery: 'parent' as const, request: { diff --git a/packages/subagent/subagent/tests/continuation.spec.ts b/packages/subagent/subagent/tests/continuation.spec.ts index afe176af9b..b3ee32b319 100644 --- a/packages/subagent/subagent/tests/continuation.spec.ts +++ b/packages/subagent/subagent/tests/continuation.spec.ts @@ -1,3 +1,4 @@ +import { randomUUID } from 'node:crypto' import { mountWorkingDirectoryFixture } from './working-directory-fixture.ts' import { afterEach, describe, expect, it, vi } from 'vitest' import { mkdtempSync, rmSync } from 'node:fs' @@ -16,7 +17,7 @@ import * as SubagentSpawn from '@deepseek-ai/dsh-subagent-spawn-in-process' import * as SubagentFork from '@deepseek-ai/dsh-subagent-fork-in-process' import * as SubagentControl from '@deepseek-ai/dsh-tool-subagent-control' import type { ContentBlock, GenerateOptions, MessageId, StreamChunk } from '@deepseek-ai/dsh-llm' -import { ToolCallId, createUserMessage, LlmAdapter, ReasoningEffortId } from '@deepseek-ai/dsh-llm' +import { boundContextSummary, ToolCallId, createUserMessage, LlmAdapter, ReasoningEffortId } from '@deepseek-ai/dsh-llm' import { defineTool } from '@deepseek-ai/dsh-tools' import { MockAdapter, maxTokensResponse, textResponse, toolCallResponse } from '../../../core/agent-loop/tests/mock-adapter.ts' import SubagentRuntime, { @@ -144,7 +145,7 @@ function hasAssistantText(events: readonly SessionEvent[], text: string): boolea function userTexts(events: readonly SessionEvent[]): string[] { return events.flatMap(event => event.type === 'user/message' && event.data.source.kind !== 'runtime-context' ? event.data.content.flatMap(block => block.type === 'text' - && !block.text.startsWith('Your parent agent id is ') + && !block.text.startsWith('Your name is ') ? [block.text] : []) : []) @@ -299,16 +300,16 @@ describe('continuable activation capacity', () => { const { ctx, parent } = await setupWith(adapter, { maxActiveSubagents: 1 }) parkParent(ctx, parent) try { - const first = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) - await expect(ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' })).rejects.toMatchObject({ code: 'ACTIVATION_LIMIT_REACHED' }) + const first = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) + await expect(ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' })).rejects.toMatchObject({ code: 'ACTIVATION_LIMIT_REACHED' }) await subagentConfigs.get(ctx)!.update({ maxActiveSubagents: 2 }) - const second = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const second = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await subagentConfigs.get(ctx)!.update({ maxActiveSubagents: 1 }) expect(ctx.agents.get(first.childId)).toBeDefined() expect(ctx.agents.get(second.childId)).toBeDefined() - await expect(ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' })).rejects.toMatchObject({ code: 'ACTIVATION_LIMIT_REACHED' }) + await expect(ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' })).rejects.toMatchObject({ code: 'ACTIVATION_LIMIT_REACHED' }) await subagentConfigs.get(ctx)!.update({ maxActiveSubagents: 3 }) - const third = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const third = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) release.resolve(undefined) await Promise.all([first, second, third].map(child => waitNoActivation(ctx, child.childId))) } finally { @@ -326,11 +327,11 @@ describe('continuable activation capacity', () => { const { ctx, parent } = await setupWith(adapter) parkParent(ctx, parent) try { - const started = await Promise.all(Array.from({ length: 8 }, () => ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }))) - await expect(ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' })).rejects.toMatchObject({ code: 'ACTIVATION_LIMIT_REACHED' }) + const started = await Promise.all(Array.from({ length: 8 }, () => ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }))) + await expect(ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' })).rejects.toMatchObject({ code: 'ACTIVATION_LIMIT_REACHED' }) release.resolve(undefined) await Promise.all(started.map(child => waitNoActivation(ctx, child.childId))) - const replacement = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const replacement = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await waitNoActivation(ctx, replacement.childId) } finally { release.resolve(undefined) @@ -350,21 +351,21 @@ describe('continuable activation capacity', () => { parkParent(ctx, parent) parkParent(ctx, other) try { - const first = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const first = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) const child = ctx.agents.get(first.childId)! await vi.waitFor(() => { expect(adapter.requests).toHaveLength(1) }) - const nested = await ctx.subagents.startActivation({ ...startSpec(child, 'fork'), delivery: 'parent' }) - const sibling = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) - await expect(ctx.subagents.startActivation({ ...startSpec(ctx.agents.get(nested.childId)!), delivery: 'parent' })) + const nested = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(child, 'fork'), delivery: 'parent' }) + const sibling = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) + await expect(ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(ctx.agents.get(nested.childId)!), delivery: 'parent' })) .rejects.toMatchObject({ code: 'ACTIVATION_LIMIT_REACHED' }) - await expect(ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' })) + await expect(ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' })) .rejects.toMatchObject({ code: 'ACTIVATION_LIMIT_REACHED' }) - const independent = await ctx.subagents.startActivation({ ...startSpec(other), delivery: 'parent' }) + const independent = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(other), delivery: 'parent' }) parkParent(ctx, child) releaseParent.resolve(undefined) await child.whenIdle() expect(managerState(ctx).resident.get(first.childId)).toBeDefined() - await expect(ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' })) + await expect(ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' })) .rejects.toMatchObject({ code: 'ACTIVATION_LIMIT_REACHED' }) release.resolve(undefined) await Promise.all([first, nested, sibling, independent].map(entry => waitNoActivation(ctx, entry.childId))) @@ -386,16 +387,16 @@ describe('continuable activation capacity', () => { await release.promise throw new Error('creation failed') }) - const starting = ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const starting = ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) const rejected = expect(starting).rejects.toThrow('creation failed') try { await entered.promise - await expect(ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' })).rejects.toMatchObject({ code: 'ACTIVATION_LIMIT_REACHED' }) + await expect(ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' })).rejects.toMatchObject({ code: 'ACTIVATION_LIMIT_REACHED' }) expect(createSpy).toHaveBeenCalledTimes(1) release.resolve(undefined) await rejected createSpy.mockRestore() - const replacement = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const replacement = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await waitNoActivation(ctx, replacement.childId) } finally { release.resolve(undefined) @@ -415,16 +416,16 @@ describe('continuable activation capacity', () => { const { ctx, parent } = await setupWith(adapter, { maxActiveSubagents: 1 }) parkParent(ctx, parent) try { - const child = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const child = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(1) }) - await expect(ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'caller' })) + await expect(ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'caller' })) .rejects.toMatchObject({ code: 'ACTIVATION_LIMIT_REACHED' }) release.resolve(undefined) await waitNoActivation(ctx, child.childId) - const caller = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'caller' }) + const caller = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'caller' }) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(2) }) - await expect(ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' })) + await expect(ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' })) .rejects.toMatchObject({ code: 'ACTIVATION_LIMIT_REACHED' }) releaseCaller.resolve(undefined) expect((await caller.result).output).toEqual(message('caller-awaited')) @@ -448,9 +449,9 @@ describe('continuable activation capacity', () => { const { ctx, parent } = await setupWith(adapter, { maxActiveSubagents: 1 }) parkParent(ctx, parent) try { - const old = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const old = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await waitNoActivation(ctx, old.childId) - const busy = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const busy = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(2) }) await expect(queuePrompt(ctx, parent, old.childId, message('resume'))).rejects.toMatchObject({ code: 'ACTIVATION_LIMIT_REACHED' }) await queuePrompt(ctx, parent, busy.childId, message('queue at capacity')) @@ -477,7 +478,7 @@ describe('continuable activation capacity', () => { const entered = Promise.withResolvers() const releaseDisposal = Promise.withResolvers() try { - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(1) }) const activation = managerState(ctx).resident.get(started.childId)! const handle = requireLocalActivation(activation).handle @@ -492,10 +493,10 @@ describe('continuable activation capacity', () => { const outcome = drained.catch((error: unknown) => error) releaseRun.resolve(undefined) await entered.promise - await expect(ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' })).rejects.toMatchObject({ code: 'ACTIVATION_LIMIT_REACHED' }) + await expect(ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' })).rejects.toMatchObject({ code: 'ACTIVATION_LIMIT_REACHED' }) releaseDisposal.resolve(undefined) expect(await outcome).toEqual(failDisposal ? expect.objectContaining({ code: 'ACTIVATION_TEARDOWN_FAILED' }) : undefined) - const replacement = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const replacement = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await waitNoActivation(ctx, replacement.childId) } finally { releaseRun.resolve(undefined) @@ -515,7 +516,7 @@ describe('SubagentRuntime.startActivation', () => { enqueued.push({ id: message.id, loggedYet: hasUserText(agent.session.snapshotEvents(), 'child task') }) }) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) expect(started.childId).toMatch(/[0-9a-f-]{36}/) // The returned id is exactly the accepted inbox message's id, and nothing @@ -536,7 +537,7 @@ describe('SubagentRuntime.startActivation', () => { const { ctx, parent } = await setupWith(adapter) const reservedId = SessionId('00000000-0000-4000-8000-000000000123') - const started = await ctx.subagents.startActivation({ + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, delivery: 'parent', ...startSpec(parent), childId: reservedId, @@ -544,7 +545,7 @@ describe('SubagentRuntime.startActivation', () => { expect(started.childId).toBe(reservedId) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(1) }) - await expect(ctx.subagents.startActivation({ + await expect(ctx.subagents.startActivation({ name: `child-${randomUUID()}`, delivery: 'parent', ...startSpec(parent), childId: reservedId, @@ -555,7 +556,7 @@ describe('SubagentRuntime.startActivation', () => { const loaded = await loadStoredSession(ctx.sessionPersistence, reservedId) expect(loaded.meta.id).toBe(reservedId) - await expect(ctx.subagents.startActivation({ + await expect(ctx.subagents.startActivation({ name: `child-${randomUUID()}`, delivery: 'parent', ...startSpec(parent), childId: reservedId, @@ -573,7 +574,7 @@ describe('SubagentRuntime.startActivation', () => { start, }) - await expect(ctx.subagents.startActivation({ ...startSpec(parent, 'one-shot'), delivery: 'parent', childId: SessionId('reserved-external') })) + await expect(ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent, 'one-shot'), delivery: 'parent', childId: SessionId('reserved-external') })) .rejects.toThrow(/reserved child ids require a local backend/) expect(start).not.toHaveBeenCalled() // No child Agent and no session were created. @@ -582,13 +583,13 @@ describe('SubagentRuntime.startActivation', () => { it('rejects synchronously when persistence is not configured', async () => { const { ctx, parent } = await setup([textResponse('unused')], { persistence: false }) - await expect(ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' })) + await expect(ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' })) .rejects.toThrow(/require session persistence/) }) it('publishes the reserved child id and appends the pre-turn descriptor', async () => { const { ctx, parent } = await setup([textResponse('answer')]) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await waitNoActivation(ctx, started.childId) const loaded = await loadStoredSession(ctx.sessionPersistence, started.childId) @@ -628,7 +629,7 @@ describe('SubagentRuntime.startActivation', () => { if (agent !== parent) childEfforts.push(agent.options.reasoningEffort) }) - const started = await ctx.subagents.startActivation({ + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, delivery: 'parent', ...startSpec(parent), request: { @@ -655,7 +656,7 @@ describe('SubagentRuntime.startActivation', () => { if (child !== parent) controller.abort('caller gave up') }) - await expect(ctx.subagents.startActivation({ ...startSpec(parent, 'spawn', controller.signal), delivery: 'parent' })) + await expect(ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent, 'spawn', controller.signal), delivery: 'parent' })) .rejects.toThrow() // No Activation, no live child Agent, and no parent ownership remains. await vi.waitFor(() => { @@ -670,7 +671,7 @@ describe('SubagentRuntime.startActivation', () => { // submitted, so cancelling here lands squarely in the handoff window. ctx.on('subagent/start', () => { controller.abort('caller gave up') }) - await expect(ctx.subagents.startActivation({ ...startSpec(parent, 'spawn', controller.signal), delivery: 'parent' })) + await expect(ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent, 'spawn', controller.signal), delivery: 'parent' })) .rejects.toThrow() // No resident child and no queued turn survive the abort. @@ -703,7 +704,7 @@ describe('SubagentRuntime.startActivation', () => { return appendCatalog('subagent/catalog', data as SessionEventMap['subagent/catalog']) }) as typeof parent.session.append) - await expect(ctx.subagents.startActivation({ + await expect(ctx.subagents.startActivation({ name: `child-${randomUUID()}`, delivery, ...startSpec(parent), childId, @@ -733,7 +734,7 @@ describe('SubagentRuntime.startActivation', () => { controller.abort(admissionFailure) }) - await expect(ctx.subagents.startActivation({ + await expect(ctx.subagents.startActivation({ name: `child-${randomUUID()}`, delivery: 'parent', ...startSpec(parent, 'spawn', controller.signal), childId, @@ -752,7 +753,7 @@ describe('SubagentRuntime.startActivation', () => { if (eventName === 'subagent/start') throw new Error('start publication failed') }, { global: true }) - await expect(ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' })) + await expect(ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' })) .rejects.toThrow(/start publication failed/) await vi.waitFor(() => { @@ -764,7 +765,7 @@ describe('SubagentRuntime.startActivation', () => { it('rejects a continuable child that would exceed the configured depth cap', async () => { const { ctx, parent } = await setup([]) - await expect(ctx.subagents.startActivation({ + await expect(ctx.subagents.startActivation({ name: `child-${randomUUID()}`, delivery: 'parent', ...startSpec(parent), request: { prompt: message('deep'), parent, maxDepth: 0 }, @@ -774,7 +775,7 @@ describe('SubagentRuntime.startActivation', () => { it('rejects an invalid continuable depth cap before provider preparation', async () => { const { ctx, parent } = await setup([]) - await expect(ctx.subagents.startActivation({ + await expect(ctx.subagents.startActivation({ name: `child-${randomUUID()}`, delivery: 'parent', ...startSpec(parent), request: { prompt: message('deep'), parent, maxDepth: Number.NaN }, @@ -785,7 +786,7 @@ describe('SubagentRuntime.startActivation', () => { it('omits undeclared composition fields from the descriptor', async () => { const { ctx } = await setup([]) const routeless = await ctx.agentLoop.create(SessionId('routeless'), {}) - const started = await ctx.subagents.startActivation({ ...startSpec(routeless), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(routeless), delivery: 'parent' }) const child = await vi.waitFor(() => { const found = ctx.agents.get(started.childId) expect(found).toBeDefined() @@ -805,7 +806,7 @@ describe('SubagentRuntime.startActivation', () => { it('cold-resumes without inventing a model route the descriptor never declared', async () => { const { ctx, root } = await setup([textResponse('first')]) const routeless = await ctx.agentLoop.create(SessionId('routeless-resume'), {}) - const started = await ctx.subagents.startActivation({ ...startSpec(routeless), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(routeless), delivery: 'parent' }) await waitNoActivation(ctx, started.childId) // End the first lifecycle so its write leases release before the fresh // context re-creates the parent identity and cold-resumes the child. @@ -846,7 +847,7 @@ describe('SubagentRuntime.startActivation', () => { parent.followup(createUserMessage({ content: message('parent work'), source: { kind: 'user' } })) await parent.whenIdle() - const started = await ctx.subagents.startActivation({ ...startSpec(parent, 'fork'), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent, 'fork'), delivery: 'parent' }) await waitNoActivation(ctx, started.childId) const loaded = await loadStoredSession(ctx.sessionPersistence, started.childId) @@ -873,7 +874,7 @@ describe('continuable image Queue prompts', () => { it('refuses an image follow-up when the child model declines image input, leaving no partial message', async () => { const { ctx, parent } = await setup([textResponse('child work')]) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await waitNoActivation(ctx, started.childId) const resolve = vi.spyOn(ctx.llm, 'resolveModelInfo') .mockResolvedValue({ inputModalities: ['text'] } as never) @@ -897,7 +898,7 @@ describe('continuable image Queue prompts', () => { { chunks: textResponse('image reply') }, ]) const { ctx, parent } = await setupWith(adapter) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(1) }) @@ -925,7 +926,7 @@ describe('continuable image Queue prompts', () => { const releaseFirst = Promise.withResolvers() const adapter = new GatedAdapter([{ chunks: textResponse('child work'), gate: releaseFirst.promise }]) const { ctx, parent } = await setupWith(adapter) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(1) }) const capability = Promise.withResolvers<{ inputModalities: string[] }>() const readingCapability = Promise.withResolvers() @@ -952,7 +953,7 @@ describe('continuable image Queue prompts', () => { it('rejects a materialized image follow-up whose capability read raced a drain', async () => { const { ctx, parent } = await setup([textResponse('child work')]) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await waitNoActivation(ctx, started.childId) const capability = Promise.withResolvers<{ inputModalities: string[] }>() const readingCapability = Promise.withResolvers() @@ -981,7 +982,7 @@ describe('continuable image Queue prompts', () => { it('defers to the text-only projection when the descriptor declares no model route', async () => { const { ctx } = await setup([]) const routeless = await ctx.agentLoop.create(SessionId('routeless-image'), {}) - const started = await ctx.subagents.startActivation({ ...startSpec(routeless), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(routeless), delivery: 'parent' }) await waitNoActivation(ctx, started.childId) const resolve = vi.spyOn(ctx.llm, 'resolveModelInfo') @@ -1013,7 +1014,7 @@ describe('direct-child Queue residency routing', () => { { chunks: textResponse('third') }, ]) const { ctx, parent } = await setupWith(adapter) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(1) }) const child = ctx.agents.get(started.childId) expect(child?.status).toBe('running') @@ -1033,7 +1034,7 @@ describe('direct-child Queue residency routing', () => { it('cold-resumes a settled child into a new Activation', async () => { const { ctx, parent } = await setup([textResponse('first'), textResponse('after resume')]) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await waitNoActivation(ctx, started.childId) const messageId = await queuePrompt(ctx, parent, started.childId, message('continue please')) @@ -1060,7 +1061,7 @@ describe('direct-child Queue residency routing', () => { ctx.on('subagent/start', info => void starts.push(info)) ctx.on('subagent/end', info => void ends.push(info)) - const started = await ctx.subagents.startActivation({ ...startSpec(parent, 'retired'), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent, 'retired'), delivery: 'parent' }) await waitNoActivation(ctx, started.childId) disposeProvider() expect(ctx.subagents.getProvider('retired')).toBeUndefined() @@ -1085,14 +1086,14 @@ describe('direct-child Queue residency routing', () => { { chunks: textResponse('woken') }, ]) const { ctx, parent } = await setupWith(adapter) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) const child = await vi.waitFor(() => { const found = ctx.agents.get(started.childId) expect(found).toBeDefined() return found! }) // The child starts its own continuable grandchild, then goes quiescent. - const grandchild = await ctx.subagents.startActivation({ ...startSpec(child), delivery: 'parent' }) + const grandchild = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(child), delivery: 'parent' }) await vi.waitFor(() => { expect(adapter.requests.length).toBeGreaterThanOrEqual(2) }) await vi.waitFor(() => { expect(child.status).toBe('idle') @@ -1123,7 +1124,7 @@ describe('direct-child Queue residency routing', () => { { chunks: textResponse('extra delivery') }, ]) const { ctx, parent } = await setupWith(adapter) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) const child = await vi.waitFor(() => { const found = ctx.agents.get(started.childId) expect(found).toBeDefined() @@ -1132,7 +1133,7 @@ describe('direct-child Queue residency routing', () => { // startActivation held the child→grandchild ownership edge; a followup // from the same managed parent to the same child re-holds it as a no-op, // and its failure-path release must not drop the established edge. - const grandchild = await ctx.subagents.startActivation({ ...startSpec(child), delivery: 'parent' }) + const grandchild = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(child), delivery: 'parent' }) const aborted = AbortSignal.abort(new Error('followup abandoned')) await expect(queuePrompt(ctx, child, grandchild.childId, message('while owned'), aborted)) .rejects.toThrow('followup abandoned') @@ -1148,7 +1149,7 @@ describe('direct-child Queue residency routing', () => { it('rejects a parent that is not the durable direct parent', async () => { const { ctx, parent } = await setup([textResponse('first')]) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await waitNoActivation(ctx, started.childId) const stranger = await ctx.agentLoop.create(SessionId('stranger'), { provider: 'mock', model: 'mock' }) @@ -1184,7 +1185,7 @@ describe('direct-child Queue residency routing', () => { it('propagates cancellation while inspecting a cold child', async () => { const { ctx, parent } = await setup([textResponse('first')]) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await waitNoActivation(ctx, started.childId) const inspectStarted = Promise.withResolvers() const inspect = vi.spyOn(ctx.sessionPersistence, 'open').mockImplementation((_id, _access, options) => { @@ -1215,7 +1216,7 @@ describe('direct-child Queue residency routing', () => { it('preserves a SubagentError raised while cold-materializing a child', async () => { const { ctx, parent } = await setup([textResponse('first')]) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await waitNoActivation(ctx, started.childId) const failure = new SubagentError('materialization denied', 'UNAUTHORIZED') ctx.agents.resume = () => Promise.reject(failure) @@ -1226,7 +1227,7 @@ describe('direct-child Queue residency routing', () => { it('cold-resumes a delivery that lost the race with final disposal', async () => { const { ctx, parent } = await setup([textResponse('first'), textResponse('after the race')]) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) const child = await vi.waitFor(() => { const found = ctx.agents.get(started.childId) expect(found).toBeDefined() @@ -1254,7 +1255,7 @@ describe('continuable human steering delivery', () => { ]) const { ctx, parent } = await setupWith(adapter) parkParent(ctx, parent) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(1) }) const child = ctx.agents.get(started.childId)! @@ -1272,7 +1273,7 @@ describe('continuable human steering delivery', () => { it('cold-resumes steering into nextStep instead of inventing another queue', async () => { const { ctx, parent } = await setup([textResponse('first'), textResponse('steered')]) parkParent(ctx, parent) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await waitNoActivation(ctx, started.childId) const receipt = await humanPrompt(ctx, parent, started.childId, 'cold steer', 'steer') @@ -1293,7 +1294,7 @@ describe('continuable child ownership', () => { { chunks: textResponse('grandchild'), gate: releaseGrandchild.promise }, ]) const { ctx, parent } = await setupWith(adapter) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) const child = await vi.waitFor(() => { const found = ctx.agents.get(started.childId) expect(found).toBeDefined() @@ -1301,7 +1302,7 @@ describe('continuable child ownership', () => { }) expect(ctx.agents.roots()).toEqual([parent]) expect(ctx.agents.isOwnedBy(child.id, parent)).toBe(true) - const grandchild = await ctx.subagents.startActivation({ ...startSpec(child), delivery: 'parent' }) + const grandchild = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(child), delivery: 'parent' }) await vi.waitFor(() => { expect(child.status).toBe('idle') @@ -1318,7 +1319,7 @@ describe('continuable child ownership', () => { it('does not add a top-level parent to the waiting graph', async () => { const { ctx, parent } = await setup([textResponse('done')]) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await waitNoActivation(ctx, started.childId) // The top-level parent remains independently registered after its child settles. expect(ctx.agents.get(parent.id)).toBe(parent) @@ -1345,7 +1346,7 @@ describe('continuable durability and teardown', () => { await releaseFlush.promise }) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) const child = ctx.agents.get(started.childId)! const cancelSpy = vi.spyOn(child, 'cancel') releaseFirstTurn.resolve(undefined) @@ -1384,7 +1385,7 @@ describe('continuable durability and teardown', () => { await releaseFlush.promise }) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) const child = ctx.agents.get(started.childId)! releaseFirstTurn.resolve(undefined) await flushing.promise @@ -1419,11 +1420,11 @@ describe('continuable durability and teardown', () => { await releaseFlush.promise }) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) const child = ctx.agents.get(started.childId)! releaseFirstTurn.resolve(undefined) await flushing.promise - const grandchild = await ctx.subagents.startActivation({ ...startSpec(child), delivery: 'parent' }) + const grandchild = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(child), delivery: 'parent' }) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(2) }) releaseFlush.resolve(undefined) @@ -1452,7 +1453,7 @@ describe('continuable durability and teardown', () => { await releaseFlush.promise }) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) releaseFirstTurn.resolve(undefined) await flushing.promise const drained = drainManager(ctx) @@ -1478,7 +1479,7 @@ describe('continuable durability and teardown', () => { await releaseFlush.promise }) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) const child = ctx.agents.get(started.childId)! const cancelSpy = vi.spyOn(child, 'cancel') releaseFirstTurn.resolve(undefined) @@ -1516,7 +1517,7 @@ describe('continuable durability and teardown', () => { const warnings: string[] = [] ctx.logger.warn = (message: string) => { warnings.push(message) } - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(1) }) // Tear down the whole backend under the child's open write path: its // teardown closes the handle (draining what was buffered) and detaches @@ -1543,7 +1544,7 @@ describe('continuable durability and teardown', () => { if (session.header.parentSession !== undefined) peerFlushed = true }) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await waitNoActivation(ctx, started.childId) expect(peerFlushed).toBe(true) expect(warnings.some(warning => warning.includes('best-effort final session flush failed'))).toBe(true) @@ -1557,7 +1558,7 @@ describe('continuable durability and teardown', () => { const warnings: string[] = [] ctx.logger.warn = (message: string) => { warnings.push(message) } - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(1) }) const activation = managerState(ctx).resident.get(started.childId)! const handle = requireLocalActivation(activation).handle @@ -1582,13 +1583,13 @@ describe('continuable durability and teardown', () => { { chunks: textResponse('grandchild'), gate: hold.promise }, ]) const { ctx, parent } = await setupWith(adapter) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) const child = await vi.waitFor(() => { const found = ctx.agents.get(started.childId) expect(found).toBeDefined() return found! }) - const grandchild = await ctx.subagents.startActivation({ ...startSpec(child), delivery: 'parent' }) + const grandchild = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(child), delivery: 'parent' }) await vi.waitFor(() => { expect(ctx.agents.get(grandchild.childId)).toBeDefined() }) const disposals: SessionId[] = [] @@ -1622,12 +1623,12 @@ describe('continuable durability and teardown', () => { SessionId('sibling-parent'), { provider: 'mock', model: 'mock' }, ) - const target = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) - const sibling = await ctx.subagents.startActivation({ ...startSpec(siblingParent), delivery: 'parent' }) + const target = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) + const sibling = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(siblingParent), delivery: 'parent' }) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(2) }) const targetChild = ctx.agents.get(target.childId)! const siblingChild = ctx.agents.get(sibling.childId)! - const grandchild = await ctx.subagents.startActivation({ ...startSpec(targetChild), delivery: 'parent' }) + const grandchild = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(targetChild), delivery: 'parent' }) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(3) }) const cancellations: SessionId[] = [] observeCancel(targetChild, () => { cancellations.push(targetChild.id) }) @@ -1645,7 +1646,7 @@ describe('continuable durability and teardown', () => { expect(ctx.agents.get(sibling.childId)).toBe(siblingChild) await expect(queuePrompt(ctx, siblingParent, sibling.childId, message('still live'))) .resolves.toBeTypeOf('string') - await expect(ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' })) + await expect(ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' })) .rejects.toMatchObject({ code: 'DRAINING' }) await expect(queuePrompt(ctx, parent, target.childId, message('too late'))) .rejects.toMatchObject({ code: 'DRAINING' }) @@ -1658,7 +1659,7 @@ describe('continuable durability and teardown', () => { expect(ctx.agents.get(sibling.childId)).toBe(siblingChild) // The exact root remains closed until its host disposes it, even after all // current descendants are gone. - await expect(ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' })) + await expect(ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' })) .rejects.toMatchObject({ code: 'DRAINING' }) releaseSibling.resolve(undefined) @@ -1673,10 +1674,10 @@ describe('continuable durability and teardown', () => { { chunks: textResponse('grandchild'), gate: releaseGrandchild.promise }, ]) const { ctx, parent } = await setupWith(adapter) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(1) }) const child = ctx.agents.get(started.childId)! - const grandchild = await ctx.subagents.startActivation({ ...startSpec(child), delivery: 'parent' }) + const grandchild = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(child), delivery: 'parent' }) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(2) }) const cancellations: SessionId[] = [] const grandchildAgent = ctx.agents.get(grandchild.childId)! @@ -1690,7 +1691,7 @@ describe('continuable durability and teardown', () => { await drained expect(ctx.agents.get(grandchild.childId)).toBeUndefined() expect(ctx.agents.get(started.childId)).toBe(child) - await expect(ctx.subagents.startActivation({ ...startSpec(child), delivery: 'parent' })) + await expect(ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(child), delivery: 'parent' })) .rejects.toMatchObject({ code: 'DRAINING' }) releaseChild.resolve(undefined) @@ -1707,12 +1708,12 @@ describe('continuable durability and teardown', () => { { chunks: textResponse('grandchild'), gate: releaseGrandchild.promise }, ]) const { ctx, parent } = await setupWith(adapter) - const target = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) - const sibling = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const target = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) + const sibling = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(2) }) const targetAgent = ctx.agents.get(target.childId)! const siblingAgent = ctx.agents.get(sibling.childId)! - const grandchild = await ctx.subagents.startActivation({ ...startSpec(targetAgent), delivery: 'parent' }) + const grandchild = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(targetAgent), delivery: 'parent' }) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(3) }) const cancel = vi.spyOn(targetAgent, 'cancel') @@ -1745,7 +1746,7 @@ describe('continuable durability and teardown', () => { const hold = Promise.withResolvers() const adapter = new GatedAdapter([{ chunks: textResponse('target'), gate: hold.promise }]) const { ctx, parent } = await setupWith(adapter) - const target = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const target = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(1) }) const activation = managerState(ctx).resident.get(target.childId)! const handle = requireLocalActivation(activation).handle @@ -1767,7 +1768,7 @@ describe('continuable durability and teardown', () => { const adapter = new GatedAdapter([{ chunks: textResponse('target'), gate: release.promise }]) const { ctx, parent } = await setupWith(adapter) const other = await ctx.agentLoop.create(SessionId('other-parent'), { provider: 'mock', model: 'mock' }) - const target = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const target = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(1) }) await expect(ctx.subagents.drainChildren(other, [target.childId])) @@ -1803,7 +1804,7 @@ describe('continuable durability and teardown', () => { const intermediate = handle.agent intermediate.followup(createUserMessage({ content: message('host task'), source: { kind: 'user' } })) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(1) }) - const descendant = await ctx.subagents.startActivation({ ...startSpec(intermediate), delivery: 'parent' }) + const descendant = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(intermediate), delivery: 'parent' }) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(2) }) const intermediateId = intermediate.id @@ -1843,7 +1844,7 @@ describe('continuable durability and teardown', () => { }) try { - const starting = ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const starting = ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) const childId = await published.promise let drainResolved = false const drained = ctx.subagents.drainDescendants([parent]).then(() => { @@ -1866,7 +1867,7 @@ describe('continuable durability and teardown', () => { const stale = { ...parent, id: parent.id } as Agent await ctx.subagents.drainDescendants([stale]) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await waitNoActivation(ctx, started.childId) }) @@ -1877,7 +1878,7 @@ describe('continuable durability and teardown', () => { { chunks: textResponse('target child'), gate: hold.promise }, ]) const { ctx, parent } = await setupWith(adapter) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(1) }) const activation = managerState(ctx).resident.get(started.childId)! const handle = requireLocalActivation(activation).handle @@ -1896,12 +1897,12 @@ describe('continuable durability and teardown', () => { it('rejects new materialization and delivery once draining begins', async () => { const { ctx, parent } = await setup([textResponse('done')]) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await waitNoActivation(ctx, started.childId) await drainManager(ctx) - await expect(ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' })) + await expect(ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' })) .rejects.toMatchObject({ code: 'DRAINING' }) await expect(queuePrompt(ctx, parent, started.childId, message('too late'))) .rejects.toMatchObject({ code: 'DRAINING' }) @@ -1914,7 +1915,7 @@ describe('continuable durability and teardown', () => { ctx.on('subagent/start', () => { drains.push(drainManager(ctx)) }) ctx.on('agent/inbox/inserted', ({ message }) => { accepted.push(message.id) }) - await expect(ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' })) + await expect(ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' })) .rejects.toMatchObject({ code: 'DRAINING' }) await Promise.all(drains) @@ -1937,7 +1938,7 @@ describe('continuable durability and teardown', () => { // `agent/created` runs after registry publication but before materialize() // receives the handle and installs the Activation. - await expect(ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' })) + await expect(ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' })) .rejects.toMatchObject({ code: 'DRAINING' }) await Promise.all(drains) @@ -1949,7 +1950,7 @@ describe('continuable durability and teardown', () => { const hold = Promise.withResolvers() const adapter = new GatedAdapter([{ chunks: textResponse('working'), gate: hold.promise }]) const { ctx, parent } = await setupWith(adapter) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(1) }) const child = ctx.agents.get(started.childId)! const order: string[] = [] @@ -1976,7 +1977,7 @@ describe('continuable durability and teardown', () => { const hold = Promise.withResolvers() const adapter = new GatedAdapter([{ chunks: textResponse('first'), gate: hold.promise }]) const { ctx, parent } = await setupWith(adapter) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(1) }) // Accepted into the inbox, but this queued turn never opens. await queuePrompt(ctx, parent, started.childId, message('never logged')) @@ -2000,7 +2001,7 @@ describe('continuable review regressions', () => { sessionId: parentId, agentOptions: { provider: 'mock', model: 'mock' }, }) - const started = await ctx.subagents.startActivation({ ...startSpec(originalParent.agent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(originalParent.agent), delivery: 'parent' }) await waitNoActivation(ctx, started.childId) const ownerAgents = managerState(ctx).ownerCtx.agents @@ -2044,7 +2045,7 @@ describe('continuable review regressions', () => { const hold = Promise.withResolvers() const adapter = new GatedAdapter([{ chunks: textResponse('working'), gate: hold.promise }]) const { ctx, parent } = await setupWith(adapter) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(1) }) const child = ctx.agents.get(started.childId)! const realFollowup = child.followup.bind(child) @@ -2074,7 +2075,7 @@ describe('continuable review regressions', () => { const ends: SubagentRunEndInfo[] = [] ctx.on('subagent/end', (info) => { ends.push(info) }) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await waitNoActivation(ctx, started.childId) await vi.waitFor(() => { expect(ends).toHaveLength(1) }) @@ -2098,7 +2099,7 @@ describe('continuable review regressions', () => { return (append as (...args: never[]) => unknown)(type as never, ...rest) }) as never) }) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'caller' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'caller' }) try { let settled = false const result = started.result.then((value) => { settled = true; return value }) @@ -2138,7 +2139,7 @@ describe('continuable review regressions', () => { agent.cancel({ kind: 'hook', reason: 'replace failed task with its retry' }) agent.followup(createUserMessage({ content: message('retry'), source: { kind: 'user' } })) }) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'caller' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'caller' }) try { await expect(started.result).resolves.toMatchObject({ stopReason: 'completed', output: [{ type: 'text', text: 'recovered' }], @@ -2158,7 +2159,7 @@ describe('continuable review regressions', () => { turn: event.data.turn, step: 0, error: new Error('terminal observer failure'), }) }, { prepend: true }) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'caller' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'caller' }) try { await expect(started.result).resolves.toMatchObject({ stopReason: 'error' }) } finally { @@ -2173,7 +2174,7 @@ describe('continuable review regressions', () => { const child = ctx.agents.get(id)! child.ctx.emit('agent/error', { agent: parent, turn: 0, step: 0, error: new Error('unrelated failure') }) }) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'caller' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'caller' }) try { await expect(started.result).resolves.toMatchObject({ stopReason: 'completed' }) } finally { @@ -2186,7 +2187,7 @@ describe('continuable review regressions', () => { const releaseFirst = Promise.withResolvers() const adapter = new GatedAdapter([{ chunks: textResponse('working'), gate: releaseFirst.promise }]) const { ctx, parent } = await setupWith(adapter) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(1) }) const child = ctx.agents.get(started.childId)! const before = child.session.snapshotEvents().length @@ -2210,7 +2211,7 @@ describe('continuable review regressions', () => { const ends: SubagentRunEndInfo[] = [] ctx.on('subagent/end', (info) => { ends.push(info) }) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await waitNoActivation(ctx, started.childId) await vi.waitFor(() => { expect(ends).toHaveLength(1) }) // Handle disposal unregisters the child, so the edge's content must have @@ -2252,7 +2253,7 @@ describe('continuable review regressions', () => { const ends: SubagentRunEndInfo[] = [] ctx.on('subagent/end', (info) => { ends.push(info) }) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await waitNoActivation(ctx, started.childId) await vi.waitFor(() => { expect(ends).toHaveLength(1) }) @@ -2265,7 +2266,7 @@ describe('continuable review regressions', () => { it('reports a resumed epoch that opened no turn without the previous answer', async () => { const { ctx, parent } = await setup([textResponse('first answer')]) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await waitNoActivation(ctx, started.childId) const ends: SubagentRunEndInfo[] = [] @@ -2295,7 +2296,7 @@ describe('continuable review regressions', () => { const steer = vi.spyOn(parent, 'steer') const ended = vi.fn() ctx.on('subagent/end', ended) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) const activation = managerState(ctx).resident.get(started.childId)! const handle = requireLocalActivation(activation).handle const realDispose = handle.dispose.bind(handle) @@ -2330,7 +2331,7 @@ describe('continuable review regressions', () => { const ends: SubagentRunEndInfo[] = [] ctx.on('subagent/end', (info) => { ends.push(info) }) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) const activation = await vi.waitFor(() => { const found = managerState(ctx).resident.get(started.childId) expect(found).toBeDefined() @@ -2356,7 +2357,7 @@ describe('continuable review regressions', () => { const ends: SubagentRunEndInfo[] = [] ctx.on('subagent/end', info => void ends.push(info)) - await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) const capture = vi.spyOn(activationResults, 'captureLocalResult').mockImplementationOnce(() => { throw new Error('capture failed') }) try { @@ -2378,7 +2379,7 @@ describe('continuable review regressions', () => { const ends: SubagentRunEndInfo[] = [] ctx.on('subagent/end', info => void ends.push(info)) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) const child = ctx.agents.get(started.childId)! const flushing = Promise.withResolvers() const releaseFlush = Promise.withResolvers() @@ -2424,7 +2425,7 @@ describe('continuable review regressions', () => { const hold = Promise.withResolvers() const adapter = new GatedAdapter([{ chunks: textResponse('answer'), gate: hold.promise }]) const { ctx, parent } = await setupWith(adapter) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) const activation = managerState(ctx).resident.get(started.childId)! const handle = requireLocalActivation(activation).handle const realDispose = handle.dispose.bind(handle) @@ -2458,7 +2459,7 @@ describe('continuable review regressions', () => { if (session.header.parentSession !== undefined) order.push('flush') }) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) const child = await vi.waitFor(() => { const found = ctx.agents.get(started.childId) expect(found).toBeDefined() @@ -2479,7 +2480,7 @@ describe('continuable review regressions', () => { const hold = Promise.withResolvers() const adapter = new GatedAdapter([{ chunks: textResponse('working'), gate: hold.promise }]) const { ctx, parent } = await setupWith(adapter) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(1) }) // Queue a turn, then cancel so it is discarded rather than dequeued. The // Activation must still reach settlement instead of waiting on that id. @@ -2498,7 +2499,7 @@ describe('continuable review regressions', () => { const release = Promise.withResolvers() const adapter = new GatedAdapter([{ chunks: textResponse('working'), gate: release.promise }]) const { ctx, parent } = await setupWith(adapter) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(1) }) const child = ctx.agents.get(started.childId)! const messageId = await queuePrompt(ctx, parent, started.childId, message('queued')) @@ -2514,7 +2515,7 @@ describe('continuable review regressions', () => { const turn = Promise.withResolvers() const adapter = new GatedAdapter([{ chunks: textResponse('answer'), gate: turn.promise }]) const { ctx, parent } = await setupWith(adapter) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'caller' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'caller' }) const activation = managerState(ctx).resident.get(started.childId)! const child = ctx.agents.get(started.childId)! const handle = requireLocalActivation(activation).handle @@ -2541,7 +2542,7 @@ describe('continuable review regressions', () => { const release = Promise.withResolvers() const adapter = new GatedAdapter([{ chunks: textResponse('working'), gate: release.promise }]) const { ctx, parent } = await setupWith(adapter) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(1) }) const child = ctx.agents.get(started.childId)! // Held while the child still runs, so the watcher observes idle and then @@ -2569,7 +2570,7 @@ describe('continuable review regressions', () => { const release = Promise.withResolvers() const adapter = new GatedAdapter([{ chunks: textResponse('working'), gate: release.promise }]) const { ctx, parent } = await setupWith(adapter) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(1) }) const child = ctx.agents.get(started.childId)! const lock = await holdChildLock(ctx, started.childId) @@ -2595,7 +2596,7 @@ describe('continuable review regressions', () => { const release = Promise.withResolvers() const adapter = new GatedAdapter([{ chunks: textResponse('working'), gate: release.promise }]) const { ctx, parent } = await setupWith(adapter) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(1) }) const child = ctx.agents.get(started.childId)! const lock = await holdChildLock(ctx, started.childId) @@ -2616,7 +2617,7 @@ describe('continuable review regressions', () => { const release = Promise.withResolvers() const adapter = new GatedAdapter([{ chunks: textResponse('working'), gate: release.promise }]) const { ctx, parent } = await setupWith(adapter) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(1) }) const child = ctx.agents.get(started.childId)! // A cordis-host-runner failure report: `steer()` from a plugin still wakes @@ -2639,7 +2640,7 @@ describe('continuable review regressions', () => { const release = Promise.withResolvers() const adapter = new GatedAdapter([{ chunks: textResponse('working'), gate: release.promise }]) const { ctx, parent } = await setupWith(adapter) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(1) }) const child = ctx.agents.get(started.childId)! await humanPrompt(ctx, parent, started.childId, 'steered', 'steer') @@ -2657,7 +2658,7 @@ describe('continuable review regressions', () => { const releaseFirst = Promise.withResolvers() const adapter = new GatedAdapter([{ chunks: textResponse('working'), gate: releaseFirst.promise }]) const { ctx, parent } = await setupWith(adapter) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(1) }) const child = ctx.agents.get(started.childId)! @@ -2682,7 +2683,7 @@ describe('continuable review regressions', () => { const releaseFirst = Promise.withResolvers() const adapter = new GatedAdapter([{ chunks: textResponse('working'), gate: releaseFirst.promise }]) const { ctx, parent } = await setupWith(adapter) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(1) }) const child = ctx.agents.get(started.childId)! @@ -2714,7 +2715,7 @@ describe('continuable review regressions', () => { return { kind: 'reject' } }) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await waitNoActivation(ctx, started.childId) // The parent would otherwise believe a vetoed delivery was done and never @@ -2739,7 +2740,7 @@ describe('continuable review regressions', () => { } }) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(1) }) const child = ctx.agents.get(started.childId) await queuePrompt(ctx, parent, started.childId, message('queued')) @@ -2807,7 +2808,7 @@ describe('continuable adjacent-Agent delivery', () => { { chunks: textResponse('parent settlement ack') }, ]) const { ctx, parent } = await setupWith(adapter) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await vi.waitFor(() => { expect(adapter.requests.filter(request => request.sessionId === started.childId)).toHaveLength(1) }) @@ -2830,7 +2831,7 @@ describe('continuable adjacent-Agent delivery', () => { senderSessionId: started.childId, }) expect(delivered?.content).toEqual([ - { type: 'text', text: `Agent ${started.childId} sent a message: ` }, + { type: 'text', text: `Agent ${started.name} sent a message: ` }, { type: 'text', text: 'an explicit message' }, ]) @@ -2847,7 +2848,7 @@ describe('continuable adjacent-Agent delivery', () => { { chunks: textResponse('child answer'), gate: releaseChild.promise }, ]) const { ctx, parent } = await setupWith(adapter) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) const child = await vi.waitFor(() => { const found = ctx.agents.get(started.childId) expect(found).toBeDefined() @@ -2873,7 +2874,7 @@ describe('continuable adjacent-Agent delivery', () => { { chunks: textResponse('child answer'), gate: releaseChild.promise }, ]) const { ctx, parent } = await setupWith(adapter) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) const child = await vi.waitFor(() => { const found = ctx.agents.get(started.childId) expect(found).toBeDefined() @@ -2895,24 +2896,24 @@ describe('continuable settlement delivery', () => { it('includes the child answer when messaging is available', async () => { const { ctx, parent } = await setup([textResponse('the answer'), textResponse('parent ack')]) await ctx.plugin(SubagentControl) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await waitNoActivation(ctx, started.childId) await vi.waitFor(() => { expect(settlementNotices(parent)).toHaveLength(1) }) const notice = settlementNotices(parent)[0]! expect(notice.sender).toBe(started.childId) expect(notice.text).toBe( - `Background subagent ${started.childId} finished and will do no further work unless you send it more.\nIts closing message:\nthe answer`, + `Background subagent ${started.name} finished and will do no further work unless you send it more.\nIts closing message:\nthe answer`, ) // The collapsed row states the outcome without the child's content. - expect(notice.summary).toBe( - `Background subagent ${started.childId} finished and will do no further work unless you send it more.`, - ) + expect(notice.summary).toBe(boundContextSummary( + `Background subagent ${started.name} finished and will do no further work unless you send it more.`, + )) }) it('delivers settlement even when the child already sent a message', async () => { const { ctx, parent } = await setup([textResponse('the answer'), textResponse('parent ack')]) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) const child = await vi.waitFor(() => { const live = ctx.agents.get(started.childId) expect(live).toBeDefined() @@ -2931,12 +2932,12 @@ describe('continuable settlement delivery', () => { it('delivers the terminal reason when the child never had a chance to report', async () => { const { ctx, parent } = await setup([maxTokensResponse('half an ans'), textResponse('parent ack')]) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await waitNoActivation(ctx, started.childId) await vi.waitFor(() => { expect(settlementNotices(parent)).toHaveLength(1) }) expect(settlementNotices(parent)[0]!.text).toBe( - `Background subagent ${started.childId} ran out of room before it finished.\nIts closing message:\nhalf an ans`, + `Background subagent ${started.name} ran out of room before it finished.\nIts closing message:\nhalf an ans`, ) }) @@ -2949,12 +2950,12 @@ describe('continuable settlement delivery', () => { return { kind: 'reject' } }) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await waitNoActivation(ctx, started.childId) await vi.waitFor(() => { expect(settlementNotices(parent)).toHaveLength(1) }) expect(settlementNotices(parent)[0]!.text).toBe( - `Background subagent ${started.childId} declined the task.\nIt left no closing message.`, + `Background subagent ${started.name} declined the task.\nIt left no closing message.`, ) }) @@ -2973,7 +2974,7 @@ describe('continuable settlement delivery', () => { throw new Error('ENOSPC: no space left on device') }) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await queuePrompt(ctx, parent, started.childId, message('second task')) releaseFirst.resolve(undefined) await waitNoActivation(ctx, started.childId) @@ -2984,7 +2985,7 @@ describe('continuable settlement delivery', () => { const child = await loadStoredSession(ctx.sessionPersistence, started.childId) expect(hasUserText(child.events, 'second task')).toBe(false) expect(settlementNotices(parent)[0]!.text).toBe( - `Background subagent ${started.childId} failed before it finished.\nIts closing message:\nthe answer`, + `Background subagent ${started.name} failed before it finished.\nIts closing message:\nthe answer`, ) }) @@ -3004,7 +3005,7 @@ describe('continuable settlement delivery', () => { return next() }) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) // Queued while turn 1 still runs, so turn 2 opens and claims it without a // second model call: the Activation is mid-turn when the drain cancels it. await queuePrompt(ctx, parent, started.childId, message('second task')) @@ -3019,7 +3020,7 @@ describe('continuable settlement delivery', () => { // task had finished. await vi.waitFor(() => { expect(settlementNotices(parent)).toHaveLength(1) }) expect(settlementNotices(parent)[0]!.text).toBe( - `Background subagent ${started.childId} was stopped before it finished.\nIts closing message:\nthe answer`, + `Background subagent ${started.name} was stopped before it finished.\nIts closing message:\nthe answer`, ) }) @@ -3034,7 +3035,7 @@ describe('continuable settlement delivery', () => { return next() }) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await atCheckpoint.promise const drained = drainManager(ctx) releaseCheckpoint.resolve(undefined) @@ -3045,7 +3046,7 @@ describe('continuable settlement delivery', () => { // that genuinely finished with no output. await vi.waitFor(() => { expect(settlementNotices(parent)).toHaveLength(1) }) expect(settlementNotices(parent)[0]!.text).toBe( - `Background subagent ${started.childId} was stopped before it finished.\nIt left no closing message.`, + `Background subagent ${started.name} was stopped before it finished.\nIt left no closing message.`, ) }) @@ -3061,7 +3062,7 @@ describe('continuable settlement delivery', () => { return next() }) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await atCheckpoint.promise // The shipped interrupt path: nothing about it runs inside this manager, so // no pre-cancel sample could see it — the child's own log has to say so. @@ -3071,7 +3072,7 @@ describe('continuable settlement delivery', () => { await vi.waitFor(() => { expect(settlementNotices(parent)).toHaveLength(1) }) expect(settlementNotices(parent)[0]!.text).toBe( - `Background subagent ${started.childId} was stopped before it finished.\nIt left no closing message.`, + `Background subagent ${started.name} was stopped before it finished.\nIt left no closing message.`, ) }) @@ -3084,7 +3085,7 @@ describe('continuable settlement delivery', () => { { chunks: textResponse('grandchild'), gate: releaseGrandchild.promise }, ]) const { ctx, parent } = await setupWith(adapter) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) const child = await vi.waitFor(() => { const live = ctx.agents.get(started.childId) expect(live).toBeDefined() @@ -3092,7 +3093,7 @@ describe('continuable settlement delivery', () => { }) // A descendant keeps the child resident once its own turn closes, so the // maintenance phase below is reachable without racing settlement. - const grandchild = await ctx.subagents.startActivation({ ...startSpec(child), delivery: 'parent' }) + const grandchild = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(child), delivery: 'parent' }) await vi.waitFor(() => { expect(ctx.agents.get(grandchild.childId)).toBeDefined() }) releaseChild.resolve(undefined) await vi.waitFor(() => { expect(child.status).toBe('idle') }) @@ -3112,13 +3113,13 @@ describe('continuable settlement delivery', () => { expect(hasUserText(child.session.snapshotEvents(), 'never runs')).toBe(false) await vi.waitFor(() => { expect(settlementNotices(parent)).toHaveLength(1) }) expect(settlementNotices(parent)[0]!.text).toBe( - `Background subagent ${started.childId} was stopped before it finished.\nIts closing message:\nthe answer`, + `Background subagent ${started.name} was stopped before it finished.\nIts closing message:\nthe answer`, ) }) it('delivers the captured answer when local handle cleanup fails', async () => { const { ctx, parent } = await setup([textResponse('the answer'), textResponse('parent ack')]) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) const activation = await vi.waitFor(() => { const live = managerState(ctx).resident.get(started.childId) expect(live).toBeDefined() @@ -3134,7 +3135,7 @@ describe('continuable settlement delivery', () => { await waitNoActivation(ctx, started.childId) await vi.waitFor(() => { expect(settlementNotices(parent)).toHaveLength(1) }) expect(settlementNotices(parent)[0]!.text).toBe( - `Background subagent ${started.childId} finished and will do no further work unless you send it more.\nIts closing message:\nthe answer`, + `Background subagent ${started.name} finished and will do no further work unless you send it more.\nIts closing message:\nthe answer`, ) await expect(started.result).resolves.toMatchObject({ stopReason: 'completed' }) await expect(started.dispose()).rejects.toThrow('scope unwind failed') @@ -3147,7 +3148,7 @@ describe('continuable settlement delivery', () => { if (session.id === parent.id && event.type === 'turn/start') turnStarts.push(event.data.turn) }) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await waitNoActivation(ctx, started.childId) await vi.waitFor(() => { expect(adapter.requests.filter(request => request.sessionId === parent.id)).toHaveLength(1) @@ -3169,8 +3170,8 @@ describe('continuable settlement delivery', () => { parent.followup(createUserMessage({ content: message('start working'), source: { kind: 'user' } })) await vi.waitFor(() => { expect(parent.status).toBe('running') }) - const first = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) - const second = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const first = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) + const second = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) releaseChildren.resolve(undefined) await waitNoActivation(ctx, first.childId) await waitNoActivation(ctx, second.childId) @@ -3201,14 +3202,14 @@ describe('continuable settlement delivery', () => { { chunks: textResponse('root reacts') }, ]) const { ctx, parent } = await setupWith(adapter) - const outer = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const outer = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) const middle = await vi.waitFor(() => { const live = ctx.agents.get(outer.childId) expect(live).toBeDefined() return live! }) - const first = await ctx.subagents.startActivation({ ...startSpec(middle), delivery: 'parent' }) - const second = await ctx.subagents.startActivation({ ...startSpec(middle), delivery: 'parent' }) + const first = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(middle), delivery: 'parent' }) + const second = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(middle), delivery: 'parent' }) await vi.waitFor(() => { expect(middle.status).toBe('idle') }) // `whenIdle()` follows maintenance and the deferred wake it releases, so @@ -3237,13 +3238,13 @@ describe('continuable settlement delivery', () => { { chunks: textResponse('outer reacts') }, ]) const { ctx, parent } = await setupWith(adapter) - const outer = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const outer = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) const middle = await vi.waitFor(() => { const live = ctx.agents.get(outer.childId) expect(live).toBeDefined() return live! }) - const inner = await ctx.subagents.startActivation({ ...startSpec(middle), delivery: 'parent' }) + const inner = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(middle), delivery: 'parent' }) await vi.waitFor(() => { expect(middle.status).toBe('idle') }) let ownedAtDelivery: SessionId[] | undefined @@ -3264,7 +3265,7 @@ describe('continuable settlement delivery', () => { const hold = Promise.withResolvers() const adapter = new GatedAdapter([{ chunks: textResponse('interrupted'), gate: hold.promise }]) const { ctx, parent } = await setupWith(adapter) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await vi.waitFor(() => { expect(ctx.agents.get(started.childId)).toBeDefined() }) const drained = drainManager(ctx) @@ -3276,7 +3277,7 @@ describe('continuable settlement delivery', () => { // message when that parent is disposed next is pinned by the test below. expect(settlementNotices(parent)).toHaveLength(1) expect(settlementNotices(parent)[0]!.text).toBe( - `Background subagent ${started.childId} was stopped before it finished.\nIt left no closing message.`, + `Background subagent ${started.name} was stopped before it finished.\nIt left no closing message.`, ) expect(parent.session.snapshotEvents().some(event => event.type === 'agent/inbox/spliced')).toBe(true) expect(parent.session.snapshotEvents().some(event => event.type === 'turn/start')).toBe(false) @@ -3287,7 +3288,7 @@ describe('continuable settlement delivery', () => { const hold = Promise.withResolvers() const adapter = new GatedAdapter([{ chunks: textResponse('interrupted'), gate: hold.promise }]) const { ctx, parent } = await setupWith(adapter) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await vi.waitFor(() => { expect(ctx.agents.get(started.childId)).toBeDefined() }) const drained = ctx.subagents.drainDescendants([parent]) @@ -3307,7 +3308,7 @@ describe('continuable settlement delivery', () => { sessionId: parentId, agentOptions: { provider: 'mock', model: 'mock' }, }) - const started = await ctx.subagents.startActivation({ ...startSpec(host.agent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(host.agent), delivery: 'parent' }) await vi.waitFor(() => { expect(ctx.agents.get(started.childId)).toBeDefined() }) const drained = ctx.subagents.drainDescendants([host.agent]) @@ -3343,7 +3344,7 @@ describe('continuable settlement delivery', () => { sessionId: SessionId('disposable-parent'), agentOptions: { provider: 'mock', model: 'mock' }, }) - const started = await ctx.subagents.startActivation({ ...startSpec(host.agent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(host.agent), delivery: 'parent' }) const ends: SubagentRunEndInfo[] = [] ctx.on('subagent/end', (info) => { ends.push(info) }) @@ -3364,7 +3365,7 @@ describe('continuable settlement delivery', () => { const ends: SubagentRunEndInfo[] = [] ctx.on('subagent/end', (info) => { ends.push(info) }) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await waitNoActivation(ctx, started.childId) await vi.waitFor(() => { expect(ends).toHaveLength(1) }) expect(ends[0]!.stopReason).toBe('completed') @@ -3376,7 +3377,7 @@ describe('continuable settlement delivery', () => { const drains: Promise[] = [] ctx.on('subagent/start', () => { drains.push(drainManager(ctx)) }) - await expect(ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' })) + await expect(ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' })) .rejects.toMatchObject({ code: 'DRAINING' }) await Promise.all(drains) expect(settlementNotices(parent)).toEqual([]) @@ -3392,7 +3393,7 @@ describe('continuable lifecycle observation', () => { ctx.on('subagent/start', (info) => { starts.push(info) }) ctx.on('subagent/end', (info) => { ends.push(info) }) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await waitNoActivation(ctx, started.childId) await vi.waitFor(() => { expect(ends).toHaveLength(1) }) @@ -3436,7 +3437,7 @@ describe('continuable public API', () => { it('catalogs caller-awaited local work without a notice and permits cold continuation', async () => { const { ctx, parent } = await setup([textResponse('first answer'), textResponse('second answer')]) parkParent(ctx, parent) - const run = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'caller' }) + const run = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'caller' }) expect('steer' in run).toBe(false) expect((await run.result).output).toEqual(message('first answer')) await run.dispose() @@ -3457,7 +3458,7 @@ describe('continuable public API', () => { it('reports a caller-signal abort before acceptance without delivering', async () => { const { ctx, parent } = await setup([textResponse('first')]) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await waitNoActivation(ctx, started.childId) const controller = new AbortController() @@ -3476,7 +3477,7 @@ describe('continuable public API', () => { { chunks: textResponse('second') }, ]) const { ctx, parent } = await setupWith(adapter) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(1) }) const controller = new AbortController() @@ -3496,7 +3497,7 @@ describe('continuable errors', () => { const hold = Promise.withResolvers() const adapter = new GatedAdapter([{ chunks: textResponse('working'), gate: hold.promise }]) const { ctx, parent } = await setupWith(adapter) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) const child = await vi.waitFor(() => { const found = ctx.agents.get(started.childId) expect(found).toBeDefined() @@ -3514,7 +3515,7 @@ describe('continuable errors', () => { it('rejects a parent that is no longer the live registry entry', async () => { const { ctx, parent } = await setup([textResponse('first')]) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) const child = await vi.waitFor(() => { const found = ctx.agents.get(started.childId) expect(found).toBeDefined() @@ -3532,7 +3533,7 @@ describe('continuable errors', () => { const hold = Promise.withResolvers() const adapter = new GatedAdapter([{ chunks: textResponse('child'), gate: hold.promise }]) const { ctx, parent } = await setupWith(adapter) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) const child = await vi.waitFor(() => { const found = ctx.agents.get(started.childId) expect(found).toBeDefined() @@ -3541,7 +3542,7 @@ describe('continuable errors', () => { // Begin the parent Activation's teardown, then try to give it a child. const drained = drainManager(ctx) - await expect(ctx.subagents.startActivation({ ...startSpec(child), delivery: 'parent' })) + await expect(ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(child), delivery: 'parent' })) .rejects.toMatchObject({ code: 'DRAINING' }) hold.resolve(undefined) await drained @@ -3549,7 +3550,7 @@ describe('continuable errors', () => { it.each([1, 2])('disposes a local activation only after pending startup at depth %s rolls back', async (depth) => { const { ctx, parent } = await setup(Array.from({ length: depth }, () => 'hang' as const)) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'caller' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'caller' }) const child = ctx.agents.get(started.childId)! const entered = Promise.withResolvers() const releaseStartup = Promise.withResolvers() @@ -3560,7 +3561,7 @@ describe('continuable errors', () => { try { let owner = child for (let level = 1; level < depth; level++) { - const nested = await ctx.subagents.startActivation({ ...startSpec(owner), delivery: 'caller' }) + const nested = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(owner), delivery: 'caller' }) owner = ctx.agents.get(nested.childId)! } ctx.subagents.registerProvider({ @@ -3578,14 +3579,14 @@ describe('continuable errors', () => { } }, }) - starting = ctx.subagents.startActivation({ ...startSpec(owner, 'external'), delivery: 'caller' }) + starting = ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(owner, 'external'), delivery: 'caller' }) .catch((error: unknown) => error) const signal = await entered.promise disposal = started.dispose() const disposed = vi.fn() void disposal.then(disposed, disposed) expect(signal.aborted).toBe(true) - await expect(ctx.subagents.startActivation({ ...startSpec(child), delivery: 'caller' })) + await expect(ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(child), delivery: 'caller' })) .rejects.toMatchObject({ code: 'ACTIVATION_CLOSING' }) releaseStartup.resolve(undefined) await cleaning.promise @@ -3613,13 +3614,13 @@ describe('continuable errors', () => { { chunks: textResponse('grandchild'), gate: hold.promise }, ]) const { ctx, parent } = await setupWith(adapter) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) const child = await vi.waitFor(() => { const found = ctx.agents.get(started.childId) expect(found).toBeDefined() return found! }) - const grandchild = await ctx.subagents.startActivation({ ...startSpec(child), delivery: 'parent' }) + const grandchild = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(child), delivery: 'parent' }) await vi.waitFor(() => { expect(ctx.agents.get(grandchild.childId)).toBeDefined() }) // Make the grandchild's own handle disposal reject: scope teardown failure // propagates, unlike a contained `agent/disposed` listener throw. @@ -3647,7 +3648,7 @@ describe('continuable errors', () => { { chunks: textResponse('unused') }, ]) const { ctx, parent } = await setupWith(adapter) - const outer = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const outer = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) const child = await vi.waitFor(() => { const found = ctx.agents.get(outer.childId) expect(found).toBeDefined() @@ -3659,7 +3660,7 @@ describe('continuable errors', () => { const disposal = outer.dispose() try { - await expect(ctx.subagents.startActivation({ ...startSpec(child), delivery: 'parent' })) + await expect(ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(child), delivery: 'parent' })) .rejects.toMatchObject({ code: 'ACTIVATION_CLOSING' }) await vi.waitFor(() => { expect(ctx.agents.list().map(agent => agent.id).filter(id => !before.has(id))).toEqual([]) @@ -3677,7 +3678,7 @@ describe('continuable errors', () => { { chunks: textResponse('unused') }, ]) const { ctx, parent } = await setupWith(adapter) - const outer = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const outer = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) const child = await vi.waitFor(() => { const found = ctx.agents.get(outer.childId) expect(found).toBeDefined() @@ -3688,7 +3689,7 @@ describe('continuable errors', () => { const detach = ctx.on(event, () => { disposal = outer.dispose() }) try { - await expect(ctx.subagents.startActivation({ ...startSpec(child), delivery: 'parent' })) + await expect(ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(child), delivery: 'parent' })) .rejects.toMatchObject(event === 'agent/created' ? { name: 'AbortError' } : { code: 'ACTIVATION_CLOSING' }) await vi.waitFor(() => { expect(ctx.agents.list().map(agent => agent.id).filter(id => !before.has(id))).toEqual([]) @@ -3706,7 +3707,7 @@ describe('continuable errors', () => { { chunks: textResponse('child done'), gate: release.promise }, ]) const { ctx, parent } = await setupWith(adapter) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) const child = await vi.waitFor(() => { const found = ctx.agents.get(started.childId) expect(found).toBeDefined() @@ -3730,13 +3731,13 @@ describe('continuable errors', () => { { chunks: textResponse('follow-up answer') }, ]) const { ctx, parent } = await setupWith(adapter) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) const child = await vi.waitFor(() => { const found = ctx.agents.get(started.childId) expect(found).toBeDefined() return found! }) - const grandchild = await ctx.subagents.startActivation({ ...startSpec(child), delivery: 'parent' }) + const grandchild = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(child), delivery: 'parent' }) await vi.waitFor(() => { expect(adapter.requests.length).toBeGreaterThanOrEqual(2) }) // The delivering parent already owns this running child, so the entry hold @@ -3756,7 +3757,7 @@ describe('continuable errors', () => { defaultEffort: effort, }) const { ctx, parent } = await setupWith(adapter) - const started = await ctx.subagents.startActivation({ + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, delivery: 'parent', ...startSpec(parent), request: { @@ -3806,7 +3807,7 @@ describe('continuable errors', () => { await ctx.plugin(SubagentSpawn, { providerName: 'spawn' }) ctx.llm.registerAdapter(['mock'], adapter) const parent = await ctx.agentLoop.create(SessionId('parent'), { provider: 'mock', model: 'mock' }) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await vi.waitFor(() => { expect(ctx.agents.get(started.childId)).toBeDefined() }) // Manager unload uses the same drain, so no child outlives its runtime. @@ -3827,7 +3828,7 @@ describe('SubagentRuntime.interrupt', () => { { chunks: textResponse('fourth') }, ]) const { ctx, parent } = await setupWith(adapter) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(1) }) const child = ctx.agents.get(started.childId)! await queuePrompt(ctx, parent, started.childId, message('parked B')) @@ -3869,10 +3870,10 @@ describe('SubagentRuntime.interrupt', () => { { chunks: textResponse('grandchild'), gate: releaseGrandchild.promise }, ]) const { ctx, parent } = await setupWith(adapter) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(1) }) const child = ctx.agents.get(started.childId)! - const grandchild = await ctx.subagents.startActivation({ ...startSpec(child), delivery: 'parent' }) + const grandchild = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(child), delivery: 'parent' }) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(2) }) const grandchildAgent = ctx.agents.get(grandchild.childId)! const childCancel = vi.spyOn(child, 'cancel') @@ -3903,7 +3904,7 @@ describe('SubagentRuntime.interrupt', () => { const hold = Promise.withResolvers() const adapter = new GatedAdapter([{ chunks: textResponse('working'), gate: hold.promise }]) const { ctx, parent } = await setupWith(adapter) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(1) }) const child = ctx.agents.get(started.childId)! const cancelSpy = vi.spyOn(child, 'cancel') @@ -3928,10 +3929,10 @@ describe('SubagentRuntime.interrupt', () => { { chunks: textResponse('grandchild'), gate: releaseGrandchild.promise }, ]) const { ctx, parent } = await setupWith(adapter) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(1) }) const child = ctx.agents.get(started.childId)! - const grandchild = await ctx.subagents.startActivation({ ...startSpec(child), delivery: 'parent' }) + const grandchild = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(child), delivery: 'parent' }) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(2) }) const grandchildAgent = ctx.agents.get(grandchild.childId)! const childCancel = vi.spyOn(child, 'cancel') @@ -3958,10 +3959,10 @@ describe('SubagentRuntime.interrupt', () => { { chunks: textResponse('b'), gate: releaseB.promise }, ]) const { ctx, parent } = await setupWith(adapter) - const targetStart = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const targetStart = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(1) }) const target = ctx.agents.get(targetStart.childId)! - const siblingStart = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const siblingStart = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(2) }) const sibling = ctx.agents.get(siblingStart.childId)! const stranger = await ctx.agentLoop.create(SessionId('stranger'), { provider: 'mock', model: 'mock' }) @@ -3996,7 +3997,7 @@ describe('SubagentRuntime.interrupt', () => { ctx.subagents.interrupt(SessionId('missing'), { kind: 'ancestor', agent: parent }) try { - const run = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'caller' }) + const run = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'caller' }) const child = ctx.agents.get(run.childId)! const cancelSpy = vi.spyOn(child, 'cancel') ctx.subagents.interrupt(run.childId, { kind: 'user', parentSessionId: parent.id }) @@ -4014,7 +4015,7 @@ describe('SubagentRuntime.interrupt', () => { it('accepts an interrupt after natural completion', async () => { const { ctx, parent } = await setup([textResponse('done')]) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await waitNoActivation(ctx, started.childId) ctx.subagents.interrupt(started.childId, { kind: 'user', parentSessionId: parent.id }) ctx.subagents.interrupt(started.childId, { kind: 'ancestor', agent: parent }) @@ -4024,7 +4025,7 @@ describe('SubagentRuntime.interrupt', () => { const hold = Promise.withResolvers() const adapter = new GatedAdapter([{ chunks: textResponse('working'), gate: hold.promise }]) const { ctx, parent } = await setupWith(adapter) - const started = await ctx.subagents.startActivation({ ...startSpec(parent), delivery: 'parent' }) + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, ...startSpec(parent), delivery: 'parent' }) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(1) }) const child = ctx.agents.get(started.childId)! const cancelSpy = vi.spyOn(child, 'cancel') diff --git a/packages/subagent/subagent/tests/external-activation-helpers.ts b/packages/subagent/subagent/tests/external-activation-helpers.ts index 389ce804d6..4235c2ce68 100644 --- a/packages/subagent/subagent/tests/external-activation-helpers.ts +++ b/packages/subagent/subagent/tests/external-activation-helpers.ts @@ -66,7 +66,7 @@ export async function startExternalActivation( registry.set(request.parent, parent) } const { label, signal, ...execution } = request - return ctx.subagents.startActivation({ + return ctx.subagents.startActivation({ name: `child-${randomUUID()}`, provider, label: label ?? 'External test task', request: { ...execution, parent }, diff --git a/packages/subagent/subagent/tests/external-activation.spec.ts b/packages/subagent/subagent/tests/external-activation.spec.ts index 7d33de2bf6..d26d8186e1 100644 --- a/packages/subagent/subagent/tests/external-activation.spec.ts +++ b/packages/subagent/subagent/tests/external-activation.spec.ts @@ -1,3 +1,4 @@ +import { randomUUID } from 'node:crypto' import { mountWorkingDirectoryFixture } from './working-directory-fixture.ts' /** External execution ownership, result delivery, and process cleanup. */ @@ -26,7 +27,7 @@ async function setup(start: (request: SubagentStartRequest) => Promise ctx.subagents.startActivation({ + start: (delivery: 'parent' | 'caller' = 'caller') => ctx.subagents.startActivation({ name: `child-${randomUUID()}`, provider: 'external', label: 'External work', signal: controller.signal, delivery, request: { parent, prompt: [{ type: 'text', text: 'Work independently' }] }, }), @@ -102,7 +103,7 @@ describe('external subagent activations', () => { } }) try { - await expect(fixture.ctx.subagents.startActivation({ + await expect(fixture.ctx.subagents.startActivation({ name: `child-${randomUUID()}`, provider: 'external', label: 'Unpublished work', signal: fixture.controller.signal, delivery: 'parent', request: { parent, prompt: [{ type: 'text', text: 'Must not publish' }] }, })).rejects.toMatchObject({ code: change === 'drain' ? 'DRAINING' : 'UNAUTHORIZED' }) @@ -365,7 +366,7 @@ it('records external membership at creation without publishing settlement update it('refuses a reserved Session id for an external provider before dispatch', async () => { const start = vi.fn() const fixture = await setup(start) - await expect(fixture.ctx.subagents.startActivation({ + await expect(fixture.ctx.subagents.startActivation({ name: `child-${randomUUID()}`, provider: 'external', childId: SessionId('reserved'), label: 'External', delivery: 'parent', signal: fixture.controller.signal, request: { parent: fixture.parent, prompt: [] }, })).rejects.toMatchObject({ code: 'UNSUPPORTED_CAPABILITY' }) diff --git a/packages/subagent/subagent/tests/external-lifecycle.spec.ts b/packages/subagent/subagent/tests/external-lifecycle.spec.ts index c6df558c36..3430941711 100644 --- a/packages/subagent/subagent/tests/external-lifecycle.spec.ts +++ b/packages/subagent/subagent/tests/external-lifecycle.spec.ts @@ -1,3 +1,4 @@ +import { randomUUID } from 'node:crypto' import { mountWorkingDirectoryFixture } from './working-directory-fixture.ts' /** External activation admission and resource ownership across parent lifetimes. */ @@ -25,7 +26,7 @@ async function setup(start: (request: SubagentStartRequest) => Promise ctx.subagents.startActivation({ + start: (owner: Agent = parent) => ctx.subagents.startActivation({ name: `child-${randomUUID()}`, provider: 'external', label: 'External work', signal: new AbortController().signal, delivery, request: { parent: owner, prompt: [{ type: 'text', text: 'work' }] }, }), diff --git a/packages/subagent/subagent/tests/list-children.spec.ts b/packages/subagent/subagent/tests/list-children.spec.ts index 053bcdf7dc..6a2b99473c 100644 --- a/packages/subagent/subagent/tests/list-children.spec.ts +++ b/packages/subagent/subagent/tests/list-children.spec.ts @@ -1,3 +1,4 @@ +import { randomUUID } from 'node:crypto' import { mountWorkingDirectoryFixture } from './working-directory-fixture.ts' import { afterEach, describe, expect, it, vi } from 'vitest' import { mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, writeFileSync } from 'node:fs' @@ -71,7 +72,7 @@ async function startChild( parent: Agent, label: string, ): Promise { - const started = await ctx.subagents.startActivation({ delivery: 'parent', + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, delivery: 'parent', provider: 'spawn', label, request: { prompt: [{ type: 'text', text: `task: ${label}` }], parent }, diff --git a/packages/subagent/subagent/tests/local-activation.ts b/packages/subagent/subagent/tests/local-activation.ts index 02b9d594c5..5f0a4d51a8 100644 --- a/packages/subagent/subagent/tests/local-activation.ts +++ b/packages/subagent/subagent/tests/local-activation.ts @@ -36,7 +36,7 @@ export async function startTestActivation( request: Omit & { signal?: AbortSignal }, ) { const { signal = new AbortController().signal, label = provider, ...task } = request - const activation = await ctx.get('subagents')!.startActivation({ provider, label, request: task, signal, delivery: 'caller' }) + const activation = await ctx.get('subagents')!.startActivation({ name: `child-${randomUUID()}`, provider, label, request: task, signal, delivery: 'caller' }) return { ...activation, id: activation.childId, localAgent: ctx.get('agents')!.get(activation.childId)! } } diff --git a/packages/subagent/subagent/tests/names.spec.ts b/packages/subagent/subagent/tests/names.spec.ts new file mode 100644 index 0000000000..54260d13f1 --- /dev/null +++ b/packages/subagent/subagent/tests/names.spec.ts @@ -0,0 +1,158 @@ +import { describe, expect, it, onTestFinished, vi } from 'vitest' +import { Context } from '@deepseek-ai/cordis' +import { SessionId, SessionLogOffset, SessionSeq } from '@deepseek-ai/dsh-session' +import SessionProjectionRegistry from '@deepseek-ai/dsh-session-projection' +import SubagentRuntime from '../src/index.ts' +import { SubagentNames, subagentNamesProjectionDefinition } from '../src/names.ts' +import { externalTestParent } from './external-activation-helpers.ts' +import { mountWorkingDirectoryFixture } from './working-directory-fixture.ts' +import { TestSessionQuery } from './test-session-query.ts' + +async function setup() { + const ctx = new Context() + const parent = await externalTestParent(ctx) + await ctx.plugin(SessionProjectionRegistry) + await mountWorkingDirectoryFixture(ctx) + await ctx.plugin(SubagentRuntime) + await ctx.plugin(TestSessionQuery) + return { ctx, parent, names: new SubagentNames(ctx) } +} + +describe('tree-wide agent names', () => { + it('reserves lead for each root and isolates independent trees', async () => { + const { ctx, parent, names } = await setup() + const other = await externalTestParent(ctx) + expect(names.nameOf(parent)).toBe('lead') + expect(await names.resolve(other, 'lead')).toBe(other.id) + using first = names.reserve(parent, 'reviewer') + first.commit(SessionId('first')) + using second = names.reserve(other, 'reviewer') + second.commit(SessionId('second')) + expect(await names.resolve(parent, 'reviewer')).toBe('first') + expect(await names.resolve(other, 'reviewer')).toBe('second') + }) + + it.each(['lead', 'unowned', '', 'Reviewer', 'has space', '1worker', 'legacy:old'])( + 'rejects invalid or reserved creation name %j before writing a fact', async (name) => { + const { parent, names } = await setup() + const seq = parent.session.seq + expect(() => names.reserve(parent, name)).toThrow(expect.objectContaining({ code: 'INVALID_AGENT_NAME' })) + expect(parent.session.seq).toBe(seq) + }, + ) + + it('rejects duplicates across nested parents and retains assignments after release', async () => { + const { ctx, parent, names } = await setup() + const session = ctx.sessions.create(SessionId('nested'), { meta: { origin: 'subagent', parentSession: parent.id } }) + const nested = { ...parent, id: session.id, session } + onTestFinished(ctx.agents.enter(nested, undefined)) + { + using reservation = names.reserve(parent, 'reviewer') + expect(() => names.reserve(nested, 'reviewer')).toThrow(expect.objectContaining({ code: 'DUPLICATE_AGENT_NAME' })) + reservation.commit(session.id) + } + expect(names.nameOf(nested)).toBe('reviewer') + expect(() => names.reserve(nested, 'reviewer')).toThrow(expect.objectContaining({ code: 'DUPLICATE_AGENT_NAME' })) + expect(await names.resolve(nested, 'lead')).toBe(parent.id) + const restoredManager = new SubagentNames(ctx) + expect(await restoredManager.resolve(parent, 'reviewer')).toBe(session.id) + expect(() => restoredManager.reserve(parent, 'reviewer')).toThrow(expect.objectContaining({ code: 'DUPLICATE_AGENT_NAME' })) + }) + + it('releases failed startup reservations and refuses a concurrent duplicate before provider dispatch', async () => { + const { ctx, parent } = await setup() + const entered = Promise.withResolvers() + const gate = Promise.withResolvers() + const start = vi.fn(async () => { + entered.resolve(undefined) + await gate.promise + throw new Error('provider failed') + }) + ctx.subagents.registerProvider({ + name: 'external', inheritsParentContext: false, + capabilities: { agentOptions: false, agentPreset: false, outputSchema: false, depthLimit: false }, + start, + }) + const spec = { + name: 'reviewer', provider: 'external', label: 'review', delivery: 'caller' as const, + request: { parent, prompt: [{ type: 'text' as const, text: 'Review' }] }, + signal: new AbortController().signal, + } + const first = ctx.subagents.startActivation(spec) + const rejected = expect(first).rejects.toThrow('provider failed') + try { + await entered.promise + await expect(ctx.subagents.startActivation(spec)).rejects.toMatchObject({ code: 'DUPLICATE_AGENT_NAME' }) + expect(start).toHaveBeenCalledTimes(1) + } finally { + gate.resolve(undefined) + await rejected + } + await expect(ctx.subagents.startActivation(spec)).rejects.toThrow('provider failed') + expect(start).toHaveBeenCalledTimes(2) + expect(parent.session.snapshotEvents().filter(event => event.type === 'subagent/named')).toEqual([]) + }) + + it('resolves historical addresses only for unnamed descendants in the same tree', async () => { + const { ctx, parent, names } = await setup() + const child = ctx.sessions.create(SessionId('old-child'), { meta: { origin: 'subagent', parentSession: parent.id } }) + parent.session.append('subagent/catalog', { + version: 0, childId: child.id, childCreatedAt: 0, mode: 'continuable', label: 'Old child', + }) + expect(names.nameOf(parent, child.id)).toBe('legacy:old-child') + expect(await names.resolve(parent, 'legacy:old-child')).toBe(child.id) + await expect(names.resolve(parent, 'legacy:missing')).rejects.toMatchObject({ code: 'AGENT_NAME_NOT_FOUND' }) + await expect(names.resolve(parent, 'missing')).rejects.toMatchObject({ code: 'AGENT_NAME_NOT_FOUND' }) + using reservation = names.reserve(parent, 'reviewer') + reservation.commit(child.id) + await expect(names.resolve(parent, 'legacy:old-child')).rejects.toMatchObject({ code: 'AGENT_NAME_NOT_FOUND' }) + const aborted = AbortSignal.abort(new Error('cancel lookup')) + await expect(names.resolve(parent, 'lead', aborted)).rejects.toThrow('cancel lookup') + }) + + it('rejects stale callers and a detached child instead of treating it as a new root', async () => { + const { ctx, parent, names } = await setup() + expect(() => names.nameOf({ ...parent })).toThrow(expect.objectContaining({ code: 'UNAUTHORIZED' })) + const session = ctx.sessions.create(SessionId('orphan'), { + meta: { origin: 'subagent', parentSession: SessionId('missing') }, + }) + const child = { ...parent, id: session.id, session } + onTestFinished(ctx.agents.enter(child, undefined)) + expect(() => names.nameOf(child)).toThrow(expect.objectContaining({ code: 'AGENT_TREE_UNAVAILABLE' })) + }) + + it('refuses publication after ancestor replacement and missing naming state', async () => { + const { ctx, parent, names } = await setup() + const session = ctx.sessions.create(SessionId('nested'), { meta: { origin: 'subagent', parentSession: parent.id } }) + const child = { ...parent, id: session.id, session } + onTestFinished(ctx.agents.enter(child, undefined)) + using reservation = names.reserve(child, 'reviewer') + const get = ctx.agents.get.bind(ctx.agents) + const replacement = { ...parent } + const lookup = vi.spyOn(ctx.agents, 'get').mockImplementation(id => id === parent.id ? replacement : get(id)) + expect(() => { reservation.commit(SessionId('new-child')) }).toThrow(expect.objectContaining({ code: 'AGENT_TREE_UNAVAILABLE' })) + lookup.mockRestore() + const state = vi.spyOn(ctx.sessionProjections, 'stateOf').mockReturnValue(undefined) + expect(() => names.reserve(parent, 'other')).toThrow(expect.objectContaining({ code: 'CONTINUATION_UNAVAILABLE' })) + state.mockRestore() + const orphan = ctx.sessions.create(SessionId('no-parent'), { meta: { origin: 'subagent' } }) + const detached = { ...parent, id: orphan.id, session: orphan } + onTestFinished(ctx.agents.enter(detached, undefined)) + expect(() => names.nameOf(detached)).toThrow(expect.objectContaining({ code: 'AGENT_TREE_UNAVAILABLE' })) + }) + + it('ignores fork-inherited names and refuses duplicate durable names or identities', async () => { + const { parent } = await setup() + const event = { type: 'subagent/named' as const, seq: SessionSeq(0), time: 0, data: { name: 'reviewer', id: SessionId('child') } } + const inherited = subagentNamesProjectionDefinition.init(parent.session.header, SessionLogOffset(1)) + expect(subagentNamesProjectionDefinition.apply(inherited, event)).toBe(inherited) + const empty = subagentNamesProjectionDefinition.init(parent.session.header, SessionLogOffset(0)) + const state = subagentNamesProjectionDefinition.apply(empty, event) + expect(subagentNamesProjectionDefinition.stateSchema.parse(JSON.parse(JSON.stringify(state)))).toEqual(state) + for (const data of [{ name: 'reviewer', id: SessionId('other') }, { name: 'writer', id: SessionId('child') }]) { + expect(subagentNamesProjectionDefinition.stateSchema.safeParse({ ...state, entries: [...state.entries, data] }).success).toBe(false) + expect(() => subagentNamesProjectionDefinition.apply(state, { ...event, data, seq: SessionSeq(1) })) + .toThrow(expect.objectContaining({ code: 'CORRUPT_AGENT_NAMES' })) + } + }) +}) diff --git a/packages/subagent/subagent/tests/parent-result.spec.ts b/packages/subagent/subagent/tests/parent-result.spec.ts index 1019a7d58b..0ccf3699fd 100644 --- a/packages/subagent/subagent/tests/parent-result.spec.ts +++ b/packages/subagent/subagent/tests/parent-result.spec.ts @@ -1,3 +1,4 @@ +import { randomUUID } from 'node:crypto' import { mountWorkingDirectoryFixture } from './working-directory-fixture.ts' /** Parent result delivery independent of a local child's messaging tool. */ @@ -24,7 +25,7 @@ it.each(['absent', 'unused'] as const)('returns the closing answer when send_mes const adapter = new MockAdapter([textResponse('CHILD_RESULT_42'), textResponse('Parent received the answer.')]) ctx.llm.registerAdapter(['mock'], adapter) const parent = await ctx.agentLoop.create(SessionId('parent'), { provider: 'mock', model: 'mock' }) - const activation = await ctx.subagents.startActivation({ + const activation = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, provider: 'spawn', label: 'Compute the answer', delivery: 'parent', signal: new AbortController().signal, request: { parent, prompt: [{ type: 'text', text: 'Find the answer.' }], @@ -58,7 +59,7 @@ it('delivers structured output to the parent when the child has send_message', a ]) ctx.llm.registerAdapter(['mock'], adapter) const parent = await ctx.agentLoop.create(SessionId('parent'), { provider: 'mock', model: 'mock' }) - const activation = await ctx.subagents.startActivation({ + const activation = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, provider: 'spawn', label: 'Compute the answer', delivery: 'parent', signal: new AbortController().signal, request: { parent, prompt: [{ type: 'text', text: 'Find the answer.' }], diff --git a/packages/subagent/subagent/tests/parked-wait.spec.ts b/packages/subagent/subagent/tests/parked-wait.spec.ts index 83dd729732..02d0e816ea 100644 --- a/packages/subagent/subagent/tests/parked-wait.spec.ts +++ b/packages/subagent/subagent/tests/parked-wait.spec.ts @@ -1,3 +1,4 @@ +import { randomUUID } from 'node:crypto' import { mountWorkingDirectoryFixture } from './working-directory-fixture.ts' /** Host completion races around idle local children with preserved input. */ import { setImmediate } from 'node:timers/promises' @@ -49,7 +50,7 @@ async function setup() { } function start(owner = parent, provider = 'local') { - const started = ctx.subagents.startActivation({ + const started = ctx.subagents.startActivation({ name: `child-${randomUUID()}`, provider, label: 'child task', delivery: 'caller', diff --git a/packages/subagent/subagent/tests/schedule-tools.spec.ts b/packages/subagent/subagent/tests/schedule-tools.spec.ts index 11c44b9707..41f992e36f 100644 --- a/packages/subagent/subagent/tests/schedule-tools.spec.ts +++ b/packages/subagent/subagent/tests/schedule-tools.spec.ts @@ -1,3 +1,4 @@ +import { randomUUID } from 'node:crypto' import { mountWorkingDirectoryFixture } from './working-directory-fixture.ts' /** * A preset-mounted Schedule tool reaches a delegated child, and the Host @@ -93,7 +94,7 @@ function toolResultTexts(agent: Agent): string[] { describe('a delegated child under a preset that mounts the Schedule tools', () => { it('sees schedule_create and is refused with subagent_session without storing a task', async () => { const { ctx, parent, dispatched } = await setupScheduleHost() - const run = await ctx.subagents.startActivation({ + const run = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, provider: 'spawn', label: 'child task', delivery: 'caller', diff --git a/packages/subagent/subagent/tests/service.spec.ts b/packages/subagent/subagent/tests/service.spec.ts index fb105074c8..d0778ea4c5 100644 --- a/packages/subagent/subagent/tests/service.spec.ts +++ b/packages/subagent/subagent/tests/service.spec.ts @@ -1,3 +1,4 @@ +import { randomUUID } from 'node:crypto' import { mountWorkingDirectoryFixture } from './working-directory-fixture.ts' import { describe, expect, expectTypeOf, it, onTestFinished, vi } from 'vitest' import { Context } from '@deepseek-ai/cordis' @@ -98,7 +99,7 @@ async function start(subagents: SubagentRuntime, provider: string, request: Suba const parent = ctx.agents.get(request.parent.id) ?? (await ctx.agents.create({ sessionId: request.parent.id })).agent const { label, signal, ...options } = request - return subagents.startActivation({ + return subagents.startActivation({ name: `child-${randomUUID()}`, provider, label: label ?? provider, request: { ...options, parent }, signal, delivery, }) } @@ -205,7 +206,7 @@ describe('SubagentRuntime', () => { it('rejects continuable operations when their runtime services are absent', async () => { const { subagents } = await service(false) - await expect(subagents.startActivation({ + await expect(subagents.startActivation({ name: `child-${randomUUID()}`, delivery: 'parent', provider: 'unused', label: 'unused child', @@ -224,7 +225,7 @@ describe('SubagentRuntime', () => { const { subagents } = await service(false) const provider = new StubProvider('external') subagents.registerProvider(provider) - await expect(subagents.startActivation({ + await expect(subagents.startActivation({ name: `child-${randomUUID()}`, provider: provider.name, label: 'Unavailable runtime', request: baseRequest(), @@ -252,7 +253,7 @@ describe('SubagentRuntime', () => { const provider = new StubProvider('external') subagents.registerProvider(provider) const { agent: parent } = await ctx.agents.create({ sessionId: SessionId('reserved-parent') }) - await expect(subagents.startActivation({ + await expect(subagents.startActivation({ name: `child-${randomUUID()}`, provider: provider.name, label: 'Reserved team child', childId: SessionId('reserved-child'), @@ -648,7 +649,7 @@ it('rejects a disposed parent before starting provider execution', async () => { subagents.registerProvider(provider) const handle = await ctx.agents.create({ sessionId: SessionId('disposed-parent') }) await handle.dispose() - await expect(subagents.startActivation({ + await expect(subagents.startActivation({ name: `child-${randomUUID()}`, provider: provider.name, label: 'work', delivery: 'caller', signal: new AbortController().signal, request: { parent: handle.agent, prompt: [] }, })).rejects.toMatchObject({ code: 'UNAUTHORIZED' }) diff --git a/packages/subagent/subagent/tests/sibling-messages.spec.ts b/packages/subagent/subagent/tests/sibling-messages.spec.ts index a06f654cab..a77f158052 100644 --- a/packages/subagent/subagent/tests/sibling-messages.spec.ts +++ b/packages/subagent/subagent/tests/sibling-messages.spec.ts @@ -78,7 +78,7 @@ const signal = new AbortController().signal /** Start one caller-delivery child whose history carries `TASK:`. */ async function start(ctx: Context, parent: Agent, marker: string, description = 'shared responsibility'): Promise { - const started = await ctx.subagents.startActivation({ + const started = await ctx.subagents.startActivation({ name: marker, provider: 'spawn', label: description, request: { prompt: [{ type: 'text', text: `TASK:${marker}` }], parent }, @@ -128,7 +128,7 @@ describe('subagent sibling messages', () => { await ctx.subagents.sendMessage(sender, b, [{ type: 'text', text: 'hello' }], { signal }) const delivered = (await storedUserMessages(ctx, b)).find(event => event.data.source.kind === 'agent-message')! - expect(textOf(delivered)).toBe(`Agent ${a} sent a message: hello`) + expect(textOf(delivered)).toBe('Agent a sent a message: hello') expect(delivered.data.source).toEqual({ kind: 'agent-message', form: 'relay', senderSessionId: a }) ctx.subagents.interrupt(a, { kind: 'ancestor', agent: parent }) await settled(ctx, a) diff --git a/packages/subagent/subagent/tests/structured.spec.ts b/packages/subagent/subagent/tests/structured.spec.ts index 64d5817dd5..bb8d9eaebe 100644 --- a/packages/subagent/subagent/tests/structured.spec.ts +++ b/packages/subagent/subagent/tests/structured.spec.ts @@ -1,3 +1,4 @@ +import { randomUUID } from 'node:crypto' import { mountWorkingDirectoryFixture } from './working-directory-fixture.ts' import { describe, expect, it } from 'vitest' import { Context } from '@deepseek-ai/cordis' @@ -386,7 +387,7 @@ describe('in-process structured output', () => { name: 'start_descendant', description: 'Start delegated work', parameters: {}, async execute(_args, exec): Promise { if (exec.agent === undefined) throw new Error('expected the structured parent') - descendant = await ctx.subagents.startActivation({ + descendant = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, provider: 'spawn', label: 'Nested work', signal: testToolSignal, delivery: 'parent', request: { parent: exec.agent, prompt: [{ type: 'text', text: 'Work until released' }], @@ -450,7 +451,7 @@ describe('in-process structured output', () => { name: 'delegate_answer', description: 'Delegate answer computation', parameters: {}, async execute(_args, exec): Promise { if (exec.agent === undefined) throw new Error('expected the structured parent') - await ctx.subagents.startActivation({ + await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, provider: 'delayed-answer', label: 'Compute answer', signal: testToolSignal, delivery: 'parent', request: { parent: exec.agent, prompt: [{ type: 'text', text: 'Compute the answer' }] }, }) diff --git a/packages/subagent/subagent/tests/working-directory.spec.ts b/packages/subagent/subagent/tests/working-directory.spec.ts index bd8e680cd8..69b018bdee 100644 --- a/packages/subagent/subagent/tests/working-directory.spec.ts +++ b/packages/subagent/subagent/tests/working-directory.spec.ts @@ -1,3 +1,4 @@ +import { randomUUID } from 'node:crypto' import { startTestActivation } from './local-activation.ts' import { mountWorkingDirectoryFixture } from './working-directory-fixture.ts' import { mkdtemp, mkdir, realpath, rm } from 'node:fs/promises' @@ -68,7 +69,7 @@ describe('subagent working directories', () => { it.each(['relative', 'absolute'])('retains an explicit %s directory when a continuable child cold-resumes', async (form) => { const { ctx, parent, origin, first, second } = await fixture() const selected = await realpath(second) - const started = await ctx.subagents.startActivation({ + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, delivery: 'caller', provider: 'spawn', label: 'directory child', request: { parent, cwd: form === 'absolute' ? second : 'second', prompt: [{ type: 'text', text: 'child' }] }, @@ -96,7 +97,7 @@ describe('subagent working directories', () => { setup: (childCtx, child) => options.setup?.(childCtx.isolate('workingDirectory'), child), })) try { - await expect(ctx.subagents.startActivation({ + await expect(ctx.subagents.startActivation({ name: `child-${randomUUID()}`, delivery: 'caller', provider: 'spawn', label: 'unavailable directory service', childId, request: { parent, cwd: second, prompt: [{ type: 'text', text: 'child' }] }, diff --git a/packages/subagent/tool-subagent-control/README.i18n.yaml b/packages/subagent/tool-subagent-control/README.i18n.yaml index c91f1a708e..11ff64d4f0 100644 --- a/packages/subagent/tool-subagent-control/README.i18n.yaml +++ b/packages/subagent/tool-subagent-control/README.i18n.yaml @@ -21,23 +21,23 @@ en: 4a52c81317ec9001 zh: ebd9f1ba920da50a /deepseek-ai-dsh-tool-subagent-control/use-this-package/send-message: - en: b160d6a41a73d64f - zh: 902a8e74db0c17a0 + en: 91882e24297b19f2 + zh: 4d7bd27e76e825e7 /deepseek-ai-dsh-tool-subagent-control/use-this-package/interrupt-agent: - en: 4ccd504f8886d8b0 - zh: 480ab8cba905ac02 + en: caf1c74171c10bf9 + zh: 5031c99d8724e2b1 /deepseek-ai-dsh-tool-subagent-control/use-this-package/list-agents: - en: 22cd16d544be9f7f - zh: 52aa3655d8091ec4 + en: 3b6b212b133f94ce + zh: 725d4875bda0ce22 /deepseek-ai-dsh-tool-subagent-control/understand-the-implementation: en: c5cdf01a78c990f2 zh: 53c180d726ce4502 /deepseek-ai-dsh-tool-subagent-control/understand-the-implementation/design-concept: - en: 18102f0d2d227c32 - zh: 0fa0350be29f9353 + en: 8d317409d4a6029c + zh: 045538831dbaa0bb /deepseek-ai-dsh-tool-subagent-control/understand-the-implementation/delivery-and-signal-ownership: - en: b596c53c18b3e7f5 - zh: bd17f4216a3a6301 + en: 6f47d91f63f8007c + zh: 1a3c63e18ece210b /deepseek-ai-dsh-tool-subagent-control/understand-the-implementation/listing-projection: en: 05a40d0cd5acd045 zh: 1914d078d4263753 @@ -54,8 +54,8 @@ en: e4c7376d4f29dbd5 zh: 6b7a9eaf69c9ea53 /deepseek-ai-dsh-tool-subagent-control/model-experience/tool-schema/what-the-model-sees: - en: b558efb37bc78acf - zh: 8534c438edd306cd + en: 8a397d9426162983 + zh: cac68d77712bb321 /deepseek-ai-dsh-tool-subagent-control/model-experience/tool-schema/token-effect: en: 282c65ac0eebfbdd zh: e9610d49f72918b0 @@ -66,8 +66,8 @@ en: d64e936e83e89a2b zh: b9905c33af6cca45 /deepseek-ai-dsh-tool-subagent-control/model-experience/interrupt-result/what-the-model-sees: - en: 89305619897680ba - zh: e610a844fc09c53f + en: f62d986ac7c1f6cc + zh: 047e2f72a7e34614 /deepseek-ai-dsh-tool-subagent-control/model-experience/interrupt-result/token-effect: en: 5d1bcef28b5f18da zh: 027d67d93d660e76 @@ -78,11 +78,11 @@ en: ab964e307bd37dca zh: 03f975252f838a42 /deepseek-ai-dsh-tool-subagent-control/model-experience/delivery-result/what-the-model-sees: - en: c562b973653a1465 - zh: 543e0877d9620114 + en: cbce90fab7d1700a + zh: 0b68d13bb4d4e03d /deepseek-ai-dsh-tool-subagent-control/model-experience/delivery-result/token-effect: - en: fba7eb5d4c53013a - zh: 4e481bbb133c8263 + en: 9fcc3cae6b23815d + zh: fcc2a9fe0dcb2909 /deepseek-ai-dsh-tool-subagent-control/model-experience/delivery-result/kv-cache-effect: en: f5d5f97a153f7c70 zh: 3d6bc05b9eadfbc2 diff --git a/packages/subagent/tool-subagent-control/README.md b/packages/subagent/tool-subagent-control/README.md index b1992fc46f..8d7c17db78 100644 --- a/packages/subagent/tool-subagent-control/README.md +++ b/packages/subagent/tool-subagent-control/README.md @@ -45,15 +45,15 @@ This package takes no configuration: the root plugin provides `send_message` and ### send_message -Sends a message to the Session id in `agent_id`. Any exact live Agent may target its direct continuable child; a resident continuable child may also target its direct parent or continuable siblings. Sibling delivery uses the shared live parent’s authority and preserves the actual sender. A working target receives the message at its nearest step boundary through Steer; an inactive child or sibling starts or resumes a turn. Success returns inbox acceptance (`messageId`), never a reply. An unsupported target, unavailable parent, unknown child, missing descriptor, or rejected admission returns an error. +Sends a message to the agent `name`. Any exact live Agent may target its direct continuable child; a resident continuable child may also target its direct parent or continuable siblings. Sibling delivery uses the shared live parent’s authority and preserves the actual sender. A working target receives the message at its nearest step boundary through Steer; an inactive child or sibling starts or resumes a turn. Success returns inbox acceptance (`messageId`), never a reply. An unsupported target, unavailable parent, unknown name, missing descriptor, or rejected admission returns an error. ### interrupt_agent -`agent_id` identifies a descendant by Session id. External executions stop permanently and cannot receive follow-ups. Local targets stop only their current turn: queued messages stay parked until a later `send_message`, descendants keep running, and the child stays available for follow-ups. The call returns when the stop request is accepted, not when the target is quiet; interrupting an already-finished agent is an accepted no-op, and self, sibling, stale, and non-ancestor callers get errored results. +`name` identifies a descendant. External executions stop permanently and cannot receive follow-ups. Local targets stop only their current turn: queued messages stay parked until a later `send_message`, descendants keep running, and the child stays available for follow-ups. The call returns when the stop request is accepted, not when the target is quiet; interrupting an already-finished agent is an accepted no-op, and self, sibling, stale, and non-ancestor callers get errored results. ### list_agents -Lists all reachable continuable descendants in stable pre-order, with each row’s direct parent id and depth. A continuable subagent with a live parent first sees that parent and its continuable siblings. Live status is `running` or `inactive`. External entries are omitted without reading child Sessions; readable one-shot children are traversal nodes but not output rows. Unknown modes and unreadable child catalogs produce diagnostics. Ordinary Session forks are not catalog entries. +Lists all reachable continuable descendants in stable pre-order, with each row’s direct parent name and depth. A continuable subagent with a live parent first sees that parent and its continuable siblings. Live status is `running` or `inactive`. External entries are omitted without reading child Sessions; readable one-shot children are traversal nodes but not output rows. Unknown modes and unreadable child catalogs produce diagnostics. Ordinary Session forks are not catalog entries. ----- @@ -67,11 +67,11 @@ This section explains what the tools delegate to the subagent service; the obser ### Design concept -Thin adapters over `ctx.subagents.sendMessage()`, `interrupt()`, and the list projections; residency, cold resume, and authorization belong to the service. Tools pass the exact live calling Agent (`exec.agent`) as sender and authority, and convert `agent_id` to the branded Session id. +Thin adapters resolve names through `ctx.subagents.resolveName()` before calling `sendMessage()` or `interrupt()`. Residency, cold resume, and authorization belong to the service. Tools pass the exact live calling Agent (`exec.agent`) as sender and authority. ### Delivery and signal ownership -The tool forwards its execution signal, which owns admission only until inbox acceptance. Accepted messages cannot be cancelled through this tool. Every message is framed as `Agent sent a message:` and recorded with `{ kind: 'agent-message', form: 'relay', senderSessionId: sender.id }`, including sibling delivery under the parent’s authority. Attribution never grants authority. +The tool forwards its execution signal, which owns admission only until inbox acceptance. Accepted messages cannot be cancelled through this tool. Every message is framed as `Agent sent a message:` and recorded with `{ kind: 'agent-message', form: 'relay', senderSessionId: sender.id }`, including sibling delivery under the parent’s authority. Attribution never grants authority. ### Listing projection @@ -106,7 +106,7 @@ Read these pages when the package-level contract is not enough; they move from t #### What the model sees -The generated [schemas](../../../docs/tool-catalog.md#deepseek-aidsh-tool-subagent-control): `send_message` takes an `agent_id` and `message`; `interrupt_agent` takes an `agent_id`; `list_agents` takes no arguments. All addresses are Session ids; descriptions are display text and may repeat. +The generated [schemas](../../../docs/tool-catalog.md#deepseek-aidsh-tool-subagent-control): `send_message` takes `name` and `message`; `interrupt_agent` takes `name`; `list_agents` takes no arguments. The root is `lead`; descriptions may repeat. Older unnamed agents have stable `legacy:` addresses. #### Token effect @@ -120,7 +120,7 @@ Prefix-stable; the schemas do not change at runtime, and a parent and its contin #### What the model sees -`interrupt requested for agent ` on acceptance. An unauthorized caller — self, sibling, stale, or non-ancestor — is an errored result naming the rejection; an absent or settled target still renders the acceptance line. +`interrupt requested for agent ` on acceptance. An unknown name or unauthorized caller — self, sibling, stale, or non-ancestor — returns an error; a known settled target still renders the acceptance line. #### Token effect @@ -134,11 +134,11 @@ Append-only; each result follows the reusable request prefix. #### What the model sees -`message delivered to agent ` on acceptance; canonical output carries the accepted `messageId`. A target outside the caller’s supported parent, child, and sibling routes, or rejected admission, produces an errored result. +`message delivered to agent ` on acceptance; canonical output carries the accepted `messageId`. A target outside the caller’s supported parent, child, and sibling routes, or rejected admission, produces an errored result. #### Token effect -One short acknowledgement per call; the target’s response never returns through this call. Children use parent and sibling ids from `list_agents` for follow-up messages. +One short acknowledgement per call; the target’s response never returns through this call. Children use parent and sibling names from `list_agents` for follow-up messages. #### KV Cache effect diff --git a/packages/subagent/tool-subagent-control/README.zh.md b/packages/subagent/tool-subagent-control/README.zh.md index 3f491f4093..4f2cdc74d0 100644 --- a/packages/subagent/tool-subagent-control/README.zh.md +++ b/packages/subagent/tool-subagent-control/README.zh.md @@ -45,15 +45,15 @@ kind: "package-reference" ### send_message -向 `agent_id` 中的 Session id 发消息。确切在线的 Agent 可联系直接可继续子级;驻留的可继续子级还可联系直接父级或可继续同级。同级投递使用共同在线父级的权限,并保留实际发送方。工作中的目标通过 Steer 在最近步骤边界接收消息;不活跃的子级或同级会启动或恢复轮次。成功返回收件箱接受标识(`messageId`),而非回复。不支持的目标、不可用的父级、未知子级、缺失描述符或被拒绝的准入均返回错误。 +向 agent 的 `name` 发消息。确切在线的 Agent 可联系直接可继续子级;驻留的可继续子级还可联系直接父级或可继续同级。同级投递使用共同在线父级的权限,并保留实际发送方。工作中的目标通过 Steer 在最近步骤边界接收消息;不活跃的子级或同级会启动或恢复轮次。成功返回收件箱接受标识(`messageId`),而非回复。不支持的目标、不可用的父级、未知名字、缺失描述符或被拒绝的准入均返回错误。 ### interrupt_agent -`agent_id` 使用 Session id 指定后代。外部执行永久停止,不能接收后续消息。本地目标只停止当前轮次:排队消息保留到后续 `send_message`,后代继续运行,子级仍可接受后续任务。调用在停止请求被接受时返回,不等待目标静止;中断已结束代理是成功的空操作,自身、同级、过期或非祖先调用方会收到错误。 +`name` 指定后代。外部执行永久停止,不能接收后续消息。本地目标只停止当前轮次:排队消息保留到后续 `send_message`,后代继续运行,子级仍可接受后续任务。调用在停止请求被接受时返回,不等待目标静止;中断已结束代理是成功的空操作,自身、同级、过期或非祖先调用方会收到错误。 ### list_agents -按稳定前序列出全部可达的可继续后代,每行带直接父级 id 和深度。父级在线的可继续子代理先看到父级及可继续同级。在线状态为 `running` 或 `inactive`。外部条目无需读取子 Session 即被省略;可读的一次性子级用于遍历,但不输出行。未知模式和无法读取的子级目录产生诊断。普通 Session 分叉不是目录条目。 +按稳定前序列出全部可达的可继续后代,每行带直接父级名字 和深度。父级在线的可继续子代理先看到父级及可继续同级。在线状态为 `running` 或 `inactive`。外部条目无需读取子 Session 即被省略;可读的一次性子级用于遍历,但不输出行。未知模式和无法读取的子级目录产生诊断。普通 Session 分叉不是目录条目。 ----- @@ -67,11 +67,11 @@ kind: "package-reference" ### 设计理念 -这些工具是 `ctx.subagents.sendMessage()`、`interrupt()` 和列表投影的薄适配层;驻留、冷恢复和授权属于服务。工具使用确切在线的调用 Agent(`exec.agent`)作为发送方和权限凭据,并将 `agent_id` 转为品牌化 Session id。 +工具先通过 `ctx.subagents.resolveName()` 解析名字,再调用 `sendMessage()` 或 `interrupt()`。驻留、冷恢复和授权属于服务。工具以确切在线的调用 Agent(`exec.agent`)作为发送方和权限凭据。 ### 投递与信号所有权 -工具转发执行信号,它只在收件箱接受前控制准入。已接受的消息不能通过此工具取消。每条消息以 `Agent sent a message:` 开头,并记录 `{ kind: 'agent-message', form: 'relay', senderSessionId: sender.id }`,使用父级权限的同级投递也一样。归属信息不授予权限。 +工具转发执行信号,它只在收件箱接受前控制准入。已接受的消息不能通过此工具取消。每条消息以 `Agent sent a message:` 开头,并记录 `{ kind: 'agent-message', form: 'relay', senderSessionId: sender.id }`,使用父级权限的同级投递也一样。归属信息不授予权限。 ### 列表投影 @@ -106,7 +106,7 @@ kind: "package-reference" #### 模型看到什么 -生成的[模式](../../../docs/tool-catalog.zh.md#deepseek-aidsh-tool-subagent-control):`send_message` 接收 `agent_id` 和 `message`;`interrupt_agent` 接收 `agent_id`;`list_agents` 不接收参数。地址统一为 Session id;描述用于展示,可以重复。 +生成的 [schema](../../../docs/tool-catalog.zh.md#deepseek-aidsh-tool-subagent-control):`send_message` 接收 `name` 与 `message`;`interrupt_agent` 接收 `name`;`list_agents` 无参数。根名为 `lead`;描述可以重复。旧的无名 agent 使用稳定的 `legacy:` 地址。 #### Token 影响 @@ -120,7 +120,7 @@ kind: "package-reference" #### 模型看到什么 -接受时返回 `interrupt requested for agent `。未授权的调用方——self、sibling、陈旧或非 ancestor——会成为指明拒绝原因的出错结果;目标不存在或已结算仍渲染接受行。 +接受后返回 `interrupt requested for agent `。未知名字或未授权调用方(自身、同级、过期或非祖先)返回错误;已知且已结束的目标仍返回接受提示。 #### Token 影响 @@ -134,11 +134,11 @@ kind: "package-reference" #### 模型看到什么 -接受后返回 `message delivered to agent `;规范输出携带已接受的 `messageId`。目标不在调用方支持的父级、子级或同级路由内,或准入被拒绝时,返回错误结果。 +接受后返回 `message delivered to agent `;规范输出携带已接受的 `messageId`。目标不在调用方支持的父级、子级或同级路由内,或准入被拒绝时,返回错误结果。 #### Token 影响 -每次调用一条简短确认;目标回复不通过此调用返回。子级使用 `list_agents` 提供的父级和同级 id 发送后续消息。 +每次调用一条简短确认;目标回复不通过此调用返回。子级使用 `list_agents` 提供的父级和同级名字 发送后续消息。 #### KV Cache 影响 diff --git a/packages/subagent/tool-subagent-control/src/index.ts b/packages/subagent/tool-subagent-control/src/index.ts index 6c87cf3958..50bb3828fa 100644 --- a/packages/subagent/tool-subagent-control/src/index.ts +++ b/packages/subagent/tool-subagent-control/src/index.ts @@ -10,10 +10,8 @@ */ import type { Context } from '@deepseek-ai/cordis' -import { brandString } from '@deepseek-ai/dsh-brand' import { defineTool } from '@deepseek-ai/dsh-tools' import type { ContentBlock } from '@deepseek-ai/dsh-llm' -import type { SessionId } from '@deepseek-ai/dsh-session' import type {} from '@deepseek-ai/dsh-subagent' import { markAdjacentAgentSendMessageTool } from '@deepseek-ai/dsh-subagent/internal' @@ -31,10 +29,10 @@ export function apply(ctx: Context): void { 'Send a message to an agent. A working agent receives it at its next step; an idle agent starts a new turn with it. ' + 'Returns delivery confirmation, not the agent\'s answer.', parameters: { - agent_id: { + name: { type: 'string', required: true, - description: 'The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child.', + description: 'The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child.', }, message: { type: 'string', @@ -52,7 +50,7 @@ export function apply(ctx: Context): void { }, render: (args, _value) => [{ type: 'text', - text: `message delivered to agent ${args.agent_id}`, + text: `message delivered to agent ${args.name}`, }], }, async execute(args, exec) { @@ -63,7 +61,7 @@ export function apply(ctx: Context): void { const message: ContentBlock[] = [{ type: 'text', text: args.message }] const messageId = await ctx.subagents.sendMessage( sender, - brandString(args.agent_id), + await ctx.subagents.resolveName(sender, args.name, exec.signal), message, { signal: exec.signal }, ) @@ -78,10 +76,10 @@ export function apply(ctx: Context): void { + 'You can continue a local direct child\'s conversation later with send_message. ' + 'External executions stop permanently and cannot receive follow-ups. Subagents it started will keep running.', parameters: { - agent_id: { + name: { type: 'string', required: true, - description: 'The id of an agent created under you: your direct child or a deeper descendant.', + description: 'The name of an agent created under you: your direct child or a deeper descendant.', }, }, output: { @@ -94,10 +92,10 @@ export function apply(ctx: Context): void { }, render: (args, _value) => [{ type: 'text', - text: `interrupt requested for agent ${args.agent_id}`, + text: `interrupt requested for agent ${args.name}`, }], }, - execute(args, exec) { + async execute(args, exec) { const caller = exec.agent if (!caller) { // Ancestor authority requires an exact live calling agent. @@ -105,8 +103,8 @@ export function apply(ctx: Context): void { } // The service authorizes the exact live caller against the target's // recorded lineage; the tool adds no authority of its own. - ctx.subagents.interrupt(brandString(args.agent_id), { kind: 'ancestor', agent: caller }) - return Promise.resolve({ accepted: true }) + ctx.subagents.interrupt(await ctx.subagents.resolveName(caller, args.name, exec.signal), { kind: 'ancestor', agent: caller }) + return { accepted: true } }, })) } diff --git a/packages/subagent/tool-subagent-control/src/list-agents.ts b/packages/subagent/tool-subagent-control/src/list-agents.ts index f46fcdfeda..78d5bbf746 100644 --- a/packages/subagent/tool-subagent-control/src/list-agents.ts +++ b/packages/subagent/tool-subagent-control/src/list-agents.ts @@ -19,22 +19,22 @@ export const inject = ['tools', 'subagents', 'agents'] type ListAgentsEntry = | { readonly kind: 'parent' - readonly id: SessionId + readonly name: string readonly status: 'running' | 'inactive' } | { readonly kind: 'child' | 'sibling' - readonly id: SessionId + readonly name: string readonly label: string readonly status: 'running' | 'inactive' - readonly parent?: SessionId + readonly parent?: string readonly depth?: number } | { readonly kind: 'diagnostic' - readonly id: SessionId + readonly name: string readonly reason: 'corrupt' | 'unsupported' | 'unavailable' - readonly parent?: SessionId + readonly parent?: string readonly depth?: number } @@ -47,17 +47,18 @@ function statusOf(agents: { get(id: SessionId): Agent | undefined }, id: Session function project( agents: { get(id: SessionId): Agent | undefined }, entry: SubagentDescendantListEntry, + nameOf: (id: SessionId) => string, ): ListAgentsEntry | undefined { - const at = { parent: entry.parentId, depth: entry.depth } + const at = { parent: nameOf(entry.parentId), depth: entry.depth } if (entry.kind === 'diagnostic') { - return { kind: 'diagnostic', id: entry.id, reason: entry.reason, ...at } + return { kind: 'diagnostic', name: nameOf(entry.id), reason: entry.reason, ...at } } // One-shot children cannot be continued by send_message, so the model // never selects them; discovery still traversed them for descendants. if (entry.mode !== 'continuable') return undefined return { kind: 'child', - id: entry.id, + name: nameOf(entry.id), label: entry.label, status: statusOf(agents, entry.id), ...at, @@ -77,13 +78,13 @@ async function family(ctx: Context, caller: Agent, signal: AbortSignal): Promise ? ctx.agents.get(header.parentSession) : undefined if (parent === undefined) return [] - const rows: ListAgentsEntry[] = [{ kind: 'parent', id: parent.id, status: statusOf(ctx.agents, parent.id) }] + const rows: ListAgentsEntry[] = [{ kind: 'parent', name: ctx.subagents.nameOf(caller, parent.id), status: statusOf(ctx.agents, parent.id) }] const children = await ctx.subagents.listChildren(parent.id, signal) const own = children.find(entry => entry.id === caller.id) if (own?.mode !== 'continuable') return [] for (const entry of children) { if (entry.id === caller.id || entry.mode !== 'continuable') continue - rows.push({ kind: 'sibling', id: entry.id, label: entry.label, status: statusOf(ctx.agents, entry.id) }) + rows.push({ kind: 'sibling', name: ctx.subagents.nameOf(caller, entry.id), label: entry.label, status: statusOf(ctx.agents, entry.id) }) } return rows } @@ -97,7 +98,7 @@ export function apply(ctx: Context): void { name: 'list_agents', description: 'List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. ' - + 'Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. ' + + 'Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. ' + 'You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. ' + 'running means it is working; inactive means it is not currently working. ' + 'You will be notified when a direct child finishes; there is no need to keep checking its status. ' @@ -113,7 +114,7 @@ export function apply(ctx: Context): void { additionalProperties: false, properties: { kind: { type: 'string', required: true, enum: ['parent'] }, - id: { type: 'string', required: true }, + name: { type: 'string', required: true }, status: { type: 'string', required: true, enum: ['running', 'inactive'] }, }, }, @@ -122,7 +123,7 @@ export function apply(ctx: Context): void { additionalProperties: false, properties: { kind: { type: 'string', required: true, enum: ['child', 'sibling'] }, - id: { type: 'string', required: true }, + name: { type: 'string', required: true }, label: { type: 'string', required: true }, status: { type: 'string', required: true, enum: ['running', 'inactive'] }, parent: { type: 'string' }, @@ -134,7 +135,7 @@ export function apply(ctx: Context): void { additionalProperties: false, properties: { kind: { type: 'string', required: true, enum: ['diagnostic'] }, - id: { type: 'string', required: true }, + name: { type: 'string', required: true }, reason: { type: 'string', required: true, enum: ['corrupt', 'unsupported', 'unavailable'] }, parent: { type: 'string' }, depth: { type: 'number' }, @@ -149,12 +150,12 @@ export function apply(ctx: Context): void { text: entries.length === 0 ? '(no subagents)' : entries.map((entry) => { - if (entry.kind === 'parent') return `${entry.id} [${entry.status}] — your parent` - if (entry.kind === 'sibling') return `${entry.id} [${entry.status}] — sibling: ${entry.label}` + if (entry.kind === 'parent') return `${entry.name} [${entry.status}] — your parent` + if (entry.kind === 'sibling') return `${entry.name} [${entry.status}] — sibling: ${entry.label}` const at = ` parent=${String(entry.parent)} depth=${String(entry.depth)}` return entry.kind === 'diagnostic' - ? `${entry.id} [diagnostic: ${entry.reason}]${at}` - : `${entry.id} [${entry.status}]${at} — ${entry.label}` + ? `${entry.name} [diagnostic: ${entry.reason}]${at}` + : `${entry.name} [${entry.status}]${at} — ${entry.label}` }).join('\n'), }] }, @@ -170,7 +171,7 @@ export function apply(ctx: Context): void { return [ ...adjacent, ...entries - .map(entry => project(ctx.agents, entry)) + .map(entry => project(ctx.agents, entry, id => ctx.subagents.nameOf(parent, id))) .filter(entry => entry !== undefined), ] }, diff --git a/packages/subagent/tool-subagent-control/tests/list-agents.spec.ts b/packages/subagent/tool-subagent-control/tests/list-agents.spec.ts index c9d84c3746..0efb83f921 100644 --- a/packages/subagent/tool-subagent-control/tests/list-agents.spec.ts +++ b/packages/subagent/tool-subagent-control/tests/list-agents.spec.ts @@ -1,3 +1,4 @@ +import { randomUUID } from 'node:crypto' import { mountWorkingDirectoryFixture } from '../../subagent/tests/working-directory-fixture.ts' import { afterEach, describe, expect, it, vi } from 'vitest' import { mkdtempSync, rmSync } from 'node:fs' @@ -110,7 +111,7 @@ async function waitNoActivation(ctx: Context, childId: SessionId): Promise describe('dsh-tool-subagent-control/list-agents', () => { it('lists a settled caller-delivery local child with its tree position', async () => { const { ctx, parent } = await setup([textResponse('private result')]) - const started = await ctx.subagents.startActivation({ + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, delivery: 'caller', provider: 'spawn', label: 'workflow child', request: { prompt: [{ type: 'text', text: 'child task' }], parent }, signal: testToolSignal, @@ -120,7 +121,7 @@ describe('dsh-tool-subagent-control/list-agents', () => { const result = await callTool(ctx, 'list_agents', {}, parent) expect(result.isError).toBe(false) - expect(text(result)).toBe(`${started.childId} [inactive] parent=${parent.id} depth=1 — workflow child`) + expect(text(result)).toBe(`${started.name} [inactive] parent=lead depth=1 — workflow child`) }) it('omits external leaves without diagnostics', async () => { @@ -158,7 +159,7 @@ describe('dsh-tool-subagent-control/list-agents', () => { it('renders direct children in array order with registry statuses', async () => { const { ctx, parent } = await setup([textResponse('done')]) - const started = await ctx.subagents.startActivation({ delivery: 'parent', + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, delivery: 'parent', provider: 'spawn', label: 'real child', request: { prompt: [{ type: 'text', text: 'child task' }], parent }, @@ -204,13 +205,13 @@ describe('dsh-tool-subagent-control/list-agents', () => { ['running-child', { status: 'running' }], ['waiting-child', { status: 'idle' }], ]) - vi.spyOn(ctx.agents, 'get').mockImplementation(id => agents.get(id) as never) + vi.spyOn(ctx.agents, 'get').mockImplementation(id => id === parent.id ? parent : agents.get(id) as never) const result = await callTool(ctx, 'list_agents', {}, parent) expect(result.isError).toBe(false) expect(text(result)).toBe( - `${started.childId} [inactive] parent=${parent.id} depth=1 — real child\n` - + `running-child [running] parent=${parent.id} depth=1 — still working\n` - + `waiting-child [inactive] parent=${parent.id} depth=1 — waiting on descendants`, + `${started.name} [inactive] parent=lead depth=1 — real child\n` + + 'legacy:running-child [running] parent=lead depth=1 — still working\n' + + 'legacy:waiting-child [inactive] parent=lead depth=1 — waiting on descendants', ) }) @@ -231,7 +232,7 @@ describe('dsh-tool-subagent-control/list-agents', () => { version: 1, childId: SessionId('historical-one-shot'), childCreatedAt: 1, mode: 'one-shot', label: 'finished once', }) - const started = await ctx.subagents.startActivation({ delivery: 'parent', + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, delivery: 'parent', provider: 'spawn', label: 'summarize the doc', request: { prompt: [{ type: 'text', text: 'child task' }], parent }, @@ -241,8 +242,8 @@ describe('dsh-tool-subagent-control/list-agents', () => { const result = await callTool(ctx, 'list_agents', {}, parent) expect(result.isError).toBe(false) expect(text(result)).toBe( - `historical-one-shot [diagnostic: unavailable] parent=${parent.id} depth=1\n` - + `${started.childId} [inactive] parent=${parent.id} depth=1 — summarize the doc`, + 'legacy:historical-one-shot [diagnostic: unavailable] parent=lead depth=1\n' + + `${started.name} [inactive] parent=lead depth=1 — summarize the doc`, ) }) @@ -295,7 +296,7 @@ describe('dsh-tool-subagent-control/list-agents', () => { { chunks: textResponse('grandchild'), gate: releaseGrandchild.promise }, ]) const { ctx, parent } = await setupWith(adapter) - const started = await ctx.subagents.startActivation({ delivery: 'parent', + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, delivery: 'parent', provider: 'spawn', label: 'waiting branch', request: { prompt: [{ type: 'text', text: 'branch work' }], parent }, @@ -303,7 +304,7 @@ describe('dsh-tool-subagent-control/list-agents', () => { }) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(1) }) const child = ctx.agents.get(started.childId)! - const grandchild = await ctx.subagents.startActivation({ delivery: 'parent', + const grandchild = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, delivery: 'parent', provider: 'spawn', label: 'nested leaf', request: { prompt: [{ type: 'text', text: 'leaf work' }], parent: child }, @@ -320,8 +321,8 @@ describe('dsh-tool-subagent-control/list-agents', () => { const result = await callTool(ctx, 'list_agents', {}, parent) expect(result.isError).toBe(false) expect(text(result)).toBe( - `${started.childId} [inactive] parent=${parent.id} depth=1 — waiting branch\n` - + `${grandchild.childId} [running] parent=${started.childId} depth=2 — nested leaf`, + `${started.name} [inactive] parent=lead depth=1 — waiting branch\n` + + `${grandchild.name} [running] parent=${started.name} depth=2 — nested leaf`, ) releaseGrandchild.resolve(undefined) @@ -365,12 +366,12 @@ describe('dsh-tool-subagent-control/list-agents', () => { const result = await callTool(ctx, 'list_agents', {}, parent) expect(result.isError).toBe(false) expect(text(result)).toBe( - 'deep-leaf [inactive] parent=one-shot-mid depth=2 — deep leaf\n' - + `broken-node [diagnostic: unavailable] parent=${parent.id} depth=1`, + 'legacy:deep-leaf [inactive] parent=legacy:one-shot-mid depth=2 — deep leaf\n' + + 'legacy:broken-node [diagnostic: unavailable] parent=lead depth=1', ) }) - it('shows each continuable child its parent and siblings by id with their descriptions', async () => { + it('shows each continuable child its parent and siblings by name with their descriptions', async () => { const release = Promise.withResolvers() const releaseDelta = Promise.withResolvers() const adapter = new GatedAdapter([ @@ -380,7 +381,7 @@ describe('dsh-tool-subagent-control/list-agents', () => { { chunks: textResponse('delta'), gate: releaseDelta.promise }, ]) const { ctx, parent } = await setupWith(adapter) - const start = async (label: string) => (await ctx.subagents.startActivation({ + const start = async (label: string) => (await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, delivery: 'caller', provider: 'spawn', label, request: { prompt: [{ type: 'text', text: label }], parent }, signal: testToolSignal, })).childId @@ -396,24 +397,24 @@ describe('dsh-tool-subagent-control/list-agents', () => { const fromAlpha = await callTool(ctx, 'list_agents', {}, ctx.agents.get(alpha)) expect(fromAlpha.isError).toBe(false) expect(text(fromAlpha)).toBe([ - `${parent.id} [inactive] — your parent`, - `${beta} [inactive] — sibling: beta task`, - `${gamma} [inactive] — sibling: gamma task`, - `${delta} [running] — sibling: delta task`, + 'lead [inactive] — your parent', + `${ctx.subagents.nameOf(parent, beta)} [inactive] — sibling: beta task`, + `${ctx.subagents.nameOf(parent, gamma)} [inactive] — sibling: gamma task`, + `${ctx.subagents.nameOf(parent, delta)} [running] — sibling: delta task`, ].join('\n')) const fromDelta = await callTool(ctx, 'list_agents', {}, ctx.agents.get(delta)) expect(text(fromDelta)).toBe([ - `${parent.id} [inactive] — your parent`, - `${alpha} [running] — sibling: alpha task`, - `${beta} [inactive] — sibling: beta task`, - `${gamma} [inactive] — sibling: gamma task`, + 'lead [inactive] — your parent', + `${ctx.subagents.nameOf(parent, alpha)} [running] — sibling: alpha task`, + `${ctx.subagents.nameOf(parent, beta)} [inactive] — sibling: beta task`, + `${ctx.subagents.nameOf(parent, gamma)} [inactive] — sibling: gamma task`, ].join('\n')) const fromParent = await callTool(ctx, 'list_agents', {}, parent) expect(text(fromParent)).toBe([ - `${alpha} [running] parent=${parent.id} depth=1 — alpha task`, - `${beta} [inactive] parent=${parent.id} depth=1 — beta task`, - `${gamma} [inactive] parent=${parent.id} depth=1 — gamma task`, - `${delta} [running] parent=${parent.id} depth=1 — delta task`, + `${ctx.subagents.nameOf(parent, alpha)} [running] parent=lead depth=1 — alpha task`, + `${ctx.subagents.nameOf(parent, beta)} [inactive] parent=lead depth=1 — beta task`, + `${ctx.subagents.nameOf(parent, gamma)} [inactive] parent=lead depth=1 — gamma task`, + `${ctx.subagents.nameOf(parent, delta)} [running] parent=lead depth=1 — delta task`, ].join('\n')) const catalog = vi.spyOn(ctx.subagents, 'listChildren').mockResolvedValue([]) diff --git a/packages/subagent/tool-subagent-control/tests/tool-subagent-control.spec.ts b/packages/subagent/tool-subagent-control/tests/tool-subagent-control.spec.ts index 69a8b268ff..4fb56760c8 100644 --- a/packages/subagent/tool-subagent-control/tests/tool-subagent-control.spec.ts +++ b/packages/subagent/tool-subagent-control/tests/tool-subagent-control.spec.ts @@ -1,3 +1,4 @@ +import { randomUUID } from 'node:crypto' import { mountWorkingDirectoryFixture } from '../../subagent/tests/working-directory-fixture.ts' import { afterEach, describe, expect, it, vi } from 'vitest' import { mkdtempSync, rmSync } from 'node:fs' @@ -114,13 +115,13 @@ describe('dsh-tool-subagent-control', () => { const schemas = ctx.tools.schemas().filter(schema => schema.name === 'send_message') expect(schemas).toHaveLength(1) const props = (schemas[0]!.parameters as { properties?: Record }).properties ?? {} - expect(Object.keys(props).sort()).toEqual(['agent_id', 'message']) + expect(Object.keys(props).sort()).toEqual(['message', 'name']) // The continuable path has no Task, so the schema must not promise one. expect(schemas[0]!.description).not.toContain('job_output') expect(schemas[0]!.description).not.toContain('job id') expect(schemas[0]!.description).toContain('receives it at its next step') - expect(props.agent_id).toMatchObject({ - description: 'The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child.', + expect(props.name).toMatchObject({ + description: 'The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child.', }) }) @@ -136,7 +137,7 @@ describe('dsh-tool-subagent-control', () => { })) await parent.whenIdle() parkParent(ctx, parent) - const started = await ctx.subagents.startActivation({ + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, delivery: 'parent', provider: 'fork', label: 'fork child', @@ -163,16 +164,16 @@ describe('dsh-tool-subagent-control', () => { if (prompt?.type !== 'user/message') throw new Error('expected the initial fork task') const texts = prompt.data.content.flatMap(block => block.type === 'text' ? [block.text] : []) expect(texts[0]).toBe('fork task') - expect(texts[1]).toContain(`Your parent agent id is ${JSON.stringify(parent.id)}`) - expect(texts[1]).toContain(`send_message({ agent_id: ${JSON.stringify(parent.id)}`) + expect(texts[1]).toContain(`Your parent agent name is ${JSON.stringify('lead')}`) + expect(texts[1]).toContain(`send_message({ name: ${JSON.stringify('lead')}`) expect(texts[1]).not.toContain('report tool') }) - it('JSON-encodes a caller-supplied parent id in the initial return instruction', async () => { + it('uses lead in return guidance even when the root Session id contains punctuation', async () => { const { ctx } = await setup([textResponse('child done')]) const parent = await ctx.agentLoop.create(SessionId('parent"\nagent'), { provider: 'mock', model: 'mock' }) parkParent(ctx, parent) - const started = await ctx.subagents.startActivation({ + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, delivery: 'parent', provider: 'spawn', label: 'encoded parent', @@ -186,8 +187,8 @@ describe('dsh-tool-subagent-control', () => { if (prompt?.type !== 'user/message') throw new Error('expected the encoded initial task') const guidance = prompt.data.content.findLast(block => block.type === 'text')?.text ?? '' - expect(guidance).toContain(`Your parent agent id is ${JSON.stringify(parent.id)}`) - expect(guidance).toContain(`agent_id: ${JSON.stringify(parent.id)}`) + expect(guidance).toContain(`Your parent agent name is ${JSON.stringify('lead')}`) + expect(guidance).toContain(`name: ${JSON.stringify('lead')}`) expect(guidance).not.toContain(parent.id) }) @@ -196,7 +197,7 @@ describe('dsh-tool-subagent-control', () => { const { ctx, parent, adapter } = await setupWith(new GatedAdapter([ { chunks: textResponse('child done'), gate: release.promise }, ])) - const started = await ctx.subagents.startActivation({ + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, delivery: 'parent', provider: 'spawn', label: 'child task', @@ -212,12 +213,12 @@ describe('dsh-tool-subagent-control', () => { }) const result = await callTool(ctx, 'send_message', { - agent_id: parent.id, + name: 'lead', message: 'CHILD_FINDING', }, child) expect(result.isError).toBe(false) - expect(text(result)).toBe(`message delivered to agent ${parent.id}`) + expect(text(result)).toBe('message delivered to agent lead') expect(delivered).toHaveLength(1) expect(delivered[0]?.message.source).toEqual({ kind: 'agent-message', @@ -225,7 +226,7 @@ describe('dsh-tool-subagent-control', () => { senderSessionId: started.childId, }) expect(delivered[0]?.message.content).toEqual([ - { type: 'text', text: `Agent ${started.childId} sent a message: ` }, + { type: 'text', text: `Agent ${started.name} sent a message: ` }, { type: 'text', text: 'CHILD_FINDING' }, ]) @@ -235,7 +236,7 @@ describe('dsh-tool-subagent-control', () => { it('cold-resumes a settled child and reports delivery', async () => { const { ctx, parent } = await setup([textResponse('first answer'), textResponse('second answer')]) - const started = await ctx.subagents.startActivation({ + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, delivery: 'parent', provider: 'spawn', label: 'child task', @@ -245,12 +246,12 @@ describe('dsh-tool-subagent-control', () => { await waitNoActivation(ctx, started.childId) const result = await callTool(ctx, 'send_message', { - agent_id: started.childId, + name: started.name, message: 'and then?', }, parent) expect(result.isError).toBe(false) - expect(text(result)).toBe(`message delivered to agent ${started.childId}`) + expect(text(result)).toBe(`message delivered to agent ${started.name}`) await waitNoActivation(ctx, started.childId) const loaded = await loadStoredSession(ctx.sessionPersistence, started.childId) @@ -262,14 +263,14 @@ describe('dsh-tool-subagent-control', () => { senderSessionId: parent.id, }) expect(followUp?.type === 'user/message' && followUp.data.content).toEqual([ - { type: 'text', text: `Agent ${parent.id} sent a message: ` }, + { type: 'text', text: 'Agent lead sent a message: ' }, { type: 'text', text: 'and then?' }, ]) }) it('steers the nearest step of an open turn', async () => { const { ctx, parent, adapter } = await setup([textResponse('first'), textResponse('second')]) - const started = await ctx.subagents.startActivation({ + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, delivery: 'parent', provider: 'spawn', label: 'long work', @@ -279,7 +280,7 @@ describe('dsh-tool-subagent-control', () => { await vi.waitFor(() => { expect(adapter.requests).toHaveLength(1) }) const result = await callTool(ctx, 'send_message', { - agent_id: started.childId, + name: started.name, message: 'also consider Y', }, parent) expect(result.isError).toBe(false) @@ -288,13 +289,13 @@ describe('dsh-tool-subagent-control', () => { const loaded = await loadStoredSession(ctx.sessionPersistence, started.childId) const prompts = loaded.events.flatMap(event => event.type === 'user/message' && event.data.source.kind !== 'runtime-context' ? event.data.content.flatMap(block => block.type === 'text' - && !block.text.startsWith('Your parent agent id is ') + && !block.text.startsWith('Your name is ') ? [block.text] : []) : []) expect(prompts).toEqual([ 'long work', - `Agent ${parent.id} sent a message: `, + 'Agent lead sent a message: ', 'also consider Y', ]) }) @@ -302,16 +303,16 @@ describe('dsh-tool-subagent-control', () => { it('reports a delivery failure as an errored, not-delivered result', async () => { const { ctx, parent } = await setup([]) const result = await callTool(ctx, 'send_message', { - agent_id: 'no-such-child', + name: 'no-such-child', message: 'hello?', }, parent) expect(result.isError).toBe(true) - expect(text(result)).toContain('unavailable') + expect(text(result)).toContain('was not found') }) it('rejects a caller that is not the child\'s durable direct parent', async () => { const { ctx, parent } = await setup([textResponse('first')]) - const started = await ctx.subagents.startActivation({ + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, delivery: 'parent', provider: 'spawn', label: 'child task', @@ -322,16 +323,16 @@ describe('dsh-tool-subagent-control', () => { const stranger = await ctx.agentLoop.create(SessionId('stranger'), { provider: 'mock', model: 'mock' }) const result = await callTool(ctx, 'send_message', { - agent_id: started.childId, + name: started.name, message: 'mine now', }, stranger) expect(result.isError).toBe(true) - expect(text(result)).toContain('another parent session') + expect(text(result)).toContain('was not found') }) it('fails loud when invoked without a calling agent', async () => { const { ctx } = await setup([]) - const result = await callTool(ctx, 'send_message', { agent_id: 'x', message: 'y' }) + const result = await callTool(ctx, 'send_message', { name: 'x', message: 'y' }) expect(result.isError).toBe(true) expect(text(result)).toContain('requires a calling agent') }) @@ -360,12 +361,12 @@ describe('dsh-tool-subagent-control', () => { }) describe('dsh-tool-subagent-control interrupt_agent', () => { - it('registers interrupt_agent with the single agent_id parameter and current-turn wording', async () => { + it('registers interrupt_agent with the single name parameter and current-turn wording', async () => { const { ctx } = await setup([]) const schemas = ctx.tools.schemas().filter(schema => schema.name === 'interrupt_agent') expect(schemas).toHaveLength(1) const props = (schemas[0]!.parameters as { properties?: Record }).properties ?? {} - expect(Object.keys(props)).toEqual(['agent_id']) + expect(Object.keys(props)).toEqual(['name']) expect(schemas[0]!.description).toContain('stop its current work') expect(schemas[0]!.description).toContain('send_message') }) @@ -378,7 +379,7 @@ describe('dsh-tool-subagent-control interrupt_agent', () => { { chunks: textResponse('waking answer') }, ]) const { ctx, parent } = await setupWith(adapter) - const started = await ctx.subagents.startActivation({ + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, delivery: 'parent', provider: 'spawn', label: 'long work', @@ -388,16 +389,16 @@ describe('dsh-tool-subagent-control interrupt_agent', () => { await vi.waitFor(() => { expect(adapter.requests).toHaveLength(1) }) const child = ctx.agents.get(started.childId)! const queued = await callTool(ctx, 'send_message', { - agent_id: started.childId, + name: started.name, message: 'parked follow-up', }, parent) expect(queued.isError).toBe(false) const cancelSpy = vi.spyOn(child, 'cancel') - const result = await callTool(ctx, 'interrupt_agent', { agent_id: started.childId }, parent) + const result = await callTool(ctx, 'interrupt_agent', { name: started.name }, parent) expect(result.isError).toBe(false) - expect(text(result)).toBe(`interrupt requested for agent ${started.childId}`) + expect(text(result)).toBe(`interrupt requested for agent ${started.name}`) expect(cancelSpy).toHaveBeenCalledExactlyOnceWith({ kind: 'parent' }, { keepInbox: true }) releaseFirst.resolve(undefined) await child.whenIdle() @@ -406,7 +407,7 @@ describe('dsh-tool-subagent-control interrupt_agent', () => { expect(child.inbox.nextStep).toHaveLength(1) const waking = await callTool(ctx, 'send_message', { - agent_id: started.childId, + name: started.name, message: 'wake up', }, parent) expect(waking.isError).toBe(false) @@ -414,15 +415,15 @@ describe('dsh-tool-subagent-control interrupt_agent', () => { const loaded = await loadStoredSession(ctx.sessionPersistence, started.childId) const prompts = loaded.events.flatMap(event => event.type === 'user/message' && event.data.source.kind !== 'runtime-context' ? event.data.content.flatMap(block => block.type === 'text' - && !block.text.startsWith('Your parent agent id is ') + && !block.text.startsWith('Your name is ') ? [block.text] : []) : []) expect(prompts).toEqual([ 'long work', - `Agent ${parent.id} sent a message: `, + 'Agent lead sent a message: ', 'parked follow-up', - `Agent ${parent.id} sent a message: `, + 'Agent lead sent a message: ', 'wake up', ]) }) @@ -435,7 +436,7 @@ describe('dsh-tool-subagent-control interrupt_agent', () => { { chunks: textResponse('grandchild'), gate: releaseGrandchild.promise }, ]) const { ctx, parent } = await setupWith(adapter) - const started = await ctx.subagents.startActivation({ + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, delivery: 'parent', provider: 'spawn', label: 'child', @@ -444,7 +445,7 @@ describe('dsh-tool-subagent-control interrupt_agent', () => { }) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(1) }) const child = ctx.agents.get(started.childId)! - const grandchild = await ctx.subagents.startActivation({ + const grandchild = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, delivery: 'parent', provider: 'spawn', label: 'grandchild', @@ -455,7 +456,7 @@ describe('dsh-tool-subagent-control interrupt_agent', () => { const grandchildAgent = ctx.agents.get(grandchild.childId)! const cancelSpy = vi.spyOn(grandchildAgent, 'cancel') - const result = await callTool(ctx, 'interrupt_agent', { agent_id: grandchild.childId }, parent) + const result = await callTool(ctx, 'interrupt_agent', { name: grandchild.name }, parent) expect(result.isError).toBe(false) expect(cancelSpy).toHaveBeenCalledExactlyOnceWith({ kind: 'parent' }, { keepInbox: true }) @@ -473,7 +474,7 @@ describe('dsh-tool-subagent-control interrupt_agent', () => { { chunks: textResponse('b'), gate: releaseB.promise }, ]) const { ctx, parent } = await setupWith(adapter) - const target = await ctx.subagents.startActivation({ + const target = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, delivery: 'parent', provider: 'spawn', label: 'target', @@ -481,7 +482,7 @@ describe('dsh-tool-subagent-control interrupt_agent', () => { signal: testToolSignal, }) await vi.waitFor(() => { expect(adapter.requests).toHaveLength(1) }) - const sibling = await ctx.subagents.startActivation({ + const sibling = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, delivery: 'parent', provider: 'spawn', label: 'sibling', @@ -494,15 +495,15 @@ describe('dsh-tool-subagent-control interrupt_agent', () => { const stranger = await ctx.agentLoop.create(SessionId('stranger'), { provider: 'mock', model: 'mock' }) const cancelSpy = vi.spyOn(targetAgent, 'cancel') - const self = await callTool(ctx, 'interrupt_agent', { agent_id: target.childId }, targetAgent) + const self = await callTool(ctx, 'interrupt_agent', { name: target.name }, targetAgent) expect(self.isError).toBe(true) expect(text(self)).toContain('cannot interrupt itself') - const fromSibling = await callTool(ctx, 'interrupt_agent', { agent_id: target.childId }, siblingAgent) + const fromSibling = await callTool(ctx, 'interrupt_agent', { name: target.name }, siblingAgent) expect(fromSibling.isError).toBe(true) expect(text(fromSibling)).toContain('not a live descendant') - const fromStranger = await callTool(ctx, 'interrupt_agent', { agent_id: target.childId }, stranger) + const fromStranger = await callTool(ctx, 'interrupt_agent', { name: target.name }, stranger) expect(fromStranger.isError).toBe(true) - expect(text(fromStranger)).toContain('not a live descendant') + expect(text(fromStranger)).toContain('was not found') expect(cancelSpy).not.toHaveBeenCalled() releaseA.resolve(undefined) @@ -513,7 +514,7 @@ describe('dsh-tool-subagent-control interrupt_agent', () => { it('accepts an absent target as a no-op without cold-resuming it', async () => { const { ctx, parent } = await setup([textResponse('done')]) - const started = await ctx.subagents.startActivation({ + const started = await ctx.subagents.startActivation({ name: `child-${randomUUID()}`, delivery: 'parent', provider: 'spawn', label: 'settled child', @@ -522,18 +523,19 @@ describe('dsh-tool-subagent-control interrupt_agent', () => { }) await waitNoActivation(ctx, started.childId) - const settled = await callTool(ctx, 'interrupt_agent', { agent_id: started.childId }, parent) + const settled = await callTool(ctx, 'interrupt_agent', { name: started.name }, parent) expect(settled.isError).toBe(false) - expect(text(settled)).toBe(`interrupt requested for agent ${started.childId}`) - const unknown = await callTool(ctx, 'interrupt_agent', { agent_id: 'no-such-agent' }, parent) - expect(unknown.isError).toBe(false) + expect(text(settled)).toBe(`interrupt requested for agent ${started.name}`) + const unknown = await callTool(ctx, 'interrupt_agent', { name: 'no-such-agent' }, parent) + expect(unknown.isError).toBe(true) + expect(text(unknown)).toContain('was not found') // No cold resume: the settled target never rematerialized. expect(ctx.agents.get(started.childId)).toBeUndefined() }) it('fails loud when invoked without a calling agent', async () => { const { ctx } = await setup([]) - const result = await callTool(ctx, 'interrupt_agent', { agent_id: 'x' }) + const result = await callTool(ctx, 'interrupt_agent', { name: 'x' }) expect(result.isError).toBe(true) expect(text(result)).toContain('requires a calling agent') }) diff --git a/packages/subagent/tool-subagent/README.i18n.yaml b/packages/subagent/tool-subagent/README.i18n.yaml index 48a9af01ed..68ff81e2ba 100644 --- a/packages/subagent/tool-subagent/README.i18n.yaml +++ b/packages/subagent/tool-subagent/README.i18n.yaml @@ -9,7 +9,7 @@ en: 686fb5136bef0a3b zh: d25d6569174a01b5 /deepseek-ai-dsh-tool-subagent/summary: - en: c09d40329253a9d8 + en: 687fc30b7ff74abe zh: 91c1bbe5557bdda9 /deepseek-ai-dsh-tool-subagent/table-of-contents: en: d152484eb41ac6b4 @@ -21,8 +21,8 @@ en: 6a82283a51912841 zh: 35728acc16931bb4 /deepseek-ai-dsh-tool-subagent/use-this-package/managed-delegation: - en: bb715d037cde14bd - zh: a88e98c07115fbd1 + en: 7152dc21ad217453 + zh: caa76981a41e8d82 /deepseek-ai-dsh-tool-subagent/use-this-package/selecting-a-child-preset: en: 1950ef92bab0f46e zh: 593f5f64ed9b5631 @@ -39,8 +39,8 @@ en: ef692c4d17290920 zh: b1d0d3dab011e2cd /deepseek-ai-dsh-tool-subagent/understand-the-implementation/result-acknowledgement: - en: 3cdb913209febc42 - zh: ea6ebfbe9d21fb3e + en: 3c2d70d479be8e38 + zh: 9aebdb72223a086e /deepseek-ai-dsh-tool-subagent/understand-the-implementation/context-sensitive-wording: en: 1733728ac5aa6bb0 zh: 341ffc6e21a289af @@ -111,8 +111,8 @@ en: 45854c8f4da73af7 zh: 7a9803ca8c03c40f /deepseek-ai-dsh-tool-subagent/model-experience/start-result/what-the-model-sees: - en: 15772cb4c28bf562 - zh: 7452e7a7114d587c + en: bb31504cc6e1e675 + zh: 753f069afd6505c4 /deepseek-ai-dsh-tool-subagent/model-experience/start-result/token-effect: en: 807d71626c81c858 zh: ba4b85709fa46c84 diff --git a/packages/subagent/tool-subagent/README.md b/packages/subagent/tool-subagent/README.md index ae753f2b45..af4bfcd940 100644 --- a/packages/subagent/tool-subagent/README.md +++ b/packages/subagent/tool-subagent/README.md @@ -9,7 +9,7 @@ English | [中文](README.zh.md) ## Summary -Use this package to give an agent a named tool that delegates work to a configured backend. Every call starts a managed activation and returns a child id; the runtime owns completion notices and cleanup. Local children support messages and restoration, while external backends execute one task and return their final answer through the completion notice. Supported backends can expose approved child LLM routes. Each instance can select a child preset and depth limit. +Use this package to give an agent a named tool that delegates work to a configured backend. Every call starts a managed activation and returns its name; the runtime owns completion notices and cleanup. Local children support messages and restoration, while external backends execute one task and return their final answer through the completion notice. Supported backends can expose approved child LLM routes. Each instance can select a child preset and depth limit. ## Table of Contents @@ -56,7 +56,7 @@ The generated [configuration catalog](../../../docs/config-catalog.md#deepseek-a ### Managed delegation -Every call returns `started subagent ` after the runtime accepts the child. It does not wait for the child's result. The activation owns the work independently of the completed tool call; the runtime sends a completion notice and releases execution resources. +Every call requires a tree-wide unique `name` and returns `started subagent ` after the runtime accepts the child. It does not wait for the result. Names follow the [subagent naming rules](../subagent/README.md#local-and-external-children). The activation owns the work independently of the completed tool call; the runtime sends a completion notice and releases execution resources. Every backend’s completion notice carries its final answer. Local Spawn and Fork children can also send messages, accept more work through `send_message` while active, or resume after settling. Codex, Claude Code, ACP, and DSH SDK backends do not accept follow-up messages. @@ -97,7 +97,7 @@ The tool calls `ctx.subagents.startActivation()` with parent delivery selected. ### Result acknowledgement -The canonical tool result is `{ kind: 'activation', subagentId }`. It contains no execution Promise or final output; programmatic consumers that need to await results use the subagent service directly. +The canonical tool result is `{ kind: 'activation', name }`. It contains no execution Promise or final output; programmatic consumers that need to await results use the subagent service directly. ### Context-sensitive wording @@ -206,7 +206,7 @@ Depth changes do not alter the system prompt or tool schemas. Updated runtime co #### What the model sees -The call retains the task description and prompt. Success returns `started subagent `; startup rejection returns an error. Child execution details are delivered separately from this acknowledgement. +The call retains the task description and prompt. Success returns `started subagent `; startup rejection returns an error. Child execution details are delivered separately from this acknowledgement. #### Token effect diff --git a/packages/subagent/tool-subagent/README.zh.md b/packages/subagent/tool-subagent/README.zh.md index 2629d3928a..2c7d2af277 100644 --- a/packages/subagent/tool-subagent/README.zh.md +++ b/packages/subagent/tool-subagent/README.zh.md @@ -56,7 +56,7 @@ kind: "package-reference" ### 受管理的委派 -运行时接受子任务后,每次调用都会返回 `started subagent `,不等待子任务结果。activation 独立于已完成的工具调用拥有这项工作;运行时发送完成通知并释放执行资源。 +每次调用都要求树内唯一的 `name`,运行时接受子级后返回 `started subagent `,不等待结果。名字遵循[子代理命名规则](../subagent/README.zh.md#local-and-external-children)。activation 独立于已完成的工具调用拥有这项工作;运行时发送完成通知并释放执行资源。 所有后端的完成通知都会附带最终回答。本地 Spawn 和 Fork 子任务还可以发送消息,在活跃期间通过 `send_message` 接受更多工作,或在结束后恢复。Codex、Claude Code、ACP 与 DSH SDK 后端不接受后续消息。 @@ -97,7 +97,7 @@ kind: "package-reference" ### 结果确认 -规范工具结果为 `{ kind: 'activation', subagentId }`。其中没有执行 Promise 或最终输出;需要等待结果的程序调用方直接使用 subagent 服务。 +规范工具结果为 `{ kind: 'activation', name }`。其中没有执行 Promise 或最终输出;需要等待结果的程序调用方直接使用 subagent 服务。 ### 随上下文变化的措辞 @@ -206,7 +206,7 @@ Delegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do no #### 模型看到什么 -调用保留任务描述与提示词。成功返回 `started subagent `;启动被拒绝则返回错误。子任务执行详情独立于这条确认交付。 +调用保留任务描述与提示词。成功返回 `started subagent `;启动被拒绝则返回错误。子任务执行详情独立于这条确认交付。 #### Token 影响 diff --git a/packages/subagent/tool-subagent/src/index.ts b/packages/subagent/tool-subagent/src/index.ts index 02d8cc4e50..08c41dadb7 100644 --- a/packages/subagent/tool-subagent/src/index.ts +++ b/packages/subagent/tool-subagent/src/index.ts @@ -1,8 +1,8 @@ /** * Model-facing delegation through one configured `ctx.subagents` provider. * Provider lifecycle controls tool registration and context-sensitive schema - * wording. Every delegation starts a managed activation and returns its child - * id; the subagent runtime owns result delivery and resource cleanup. + * wording. Every delegation starts a managed activation and returns its + * name; the subagent runtime owns result delivery and resource cleanup. * @module @deepseek-ai/dsh-tool-subagent */ @@ -212,12 +212,17 @@ export async function apply(ctx: Context, config: Config, session?: Session): Pr const definition = defineTool({ name: toolName, description: wording.description - + ' This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes.' + + ' This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes.' + (subagentProvider.prepareContinuable !== undefined ? ' The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.' : ' The completion notice includes its final answer. This backend does not accept follow-up messages.') + choiceDescription, parameters: { + name: { + type: 'string', + required: true, + description: 'Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish.', + }, cwd: { type: 'string', description: 'Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent.', @@ -267,10 +272,10 @@ export async function apply(ctx: Context, config: Config, session?: Session): Pr additionalProperties: false, properties: { kind: { type: 'string', required: true, const: 'activation' }, - subagentId: { type: 'string', required: true }, + name: { type: 'string', required: true }, }, }, - render: (_args, value) => [{ type: 'text', text: `started subagent ${value.subagentId}` }], + render: (_args, value) => [{ type: 'text', text: `started subagent ${value.name}` }], }, isConcurrencySafe: () => true, async execute(args, exec) { @@ -327,14 +332,15 @@ export async function apply(ctx: Context, config: Config, session?: Session): Pr ...maxDepth !== undefined ? { maxDepth } : {}, } - const started = await runtimeCtx.subagents.startActivation({ + await runtimeCtx.subagents.startActivation({ + name: args.name, provider: config.provider, label: args.description, request, signal: exec.signal, delivery: 'parent', }) - return { kind: 'activation' as const, subagentId: started.childId } + return { kind: 'activation' as const, name: args.name } }, }) const disposeTool = runtimeCtx.effect(() => { diff --git a/packages/subagent/tool-subagent/tests/model-selection-settings.spec.ts b/packages/subagent/tool-subagent/tests/model-selection-settings.spec.ts index e7ef63b0d5..bcf8b916eb 100644 --- a/packages/subagent/tool-subagent/tests/model-selection-settings.spec.ts +++ b/packages/subagent/tool-subagent/tests/model-selection-settings.spec.ts @@ -1,3 +1,4 @@ +import { randomUUID } from 'node:crypto' import { mountWorkingDirectoryFixture } from '../../subagent/tests/working-directory-fixture.ts' /** Default-off settings and per-session model-selection decisions. */ @@ -224,7 +225,7 @@ describe('SubagentModelSelectionConfig', () => { signal: new AbortController().signal, callId: ToolCallId('disallowed-session-route'), name: 'subagent', - arguments: { + arguments: { name: `child-${randomUUID()}`, description: 'forced route', prompt: 'do it', provider: 'alpha', @@ -432,12 +433,12 @@ it('reads the saved default depth at each delegation without remounting the tool const initial = await ctx.systemPrompt.assemble(assembleContextFor(agent)) expect(initial.contexts.find(part => part.name === 'tool:subagent:depth')?.text) .toBe('') - await callSubagent(ctx, { description: 'first', prompt: 'work' }) + await callSubagent(ctx, { name: `child-${randomUUID()}`, description: 'first', prompt: 'work' }) await subagentConfigs.get(ctx)!.update({ maxDepth: 5 }) const updated = ctx.systemPrompt.refreshContext(initial, assembleContextFor(agent)) expect(updated.contexts.find(part => part.name === 'tool:subagent:depth')?.text) .toBe('') - await callSubagent(ctx, { description: 'second', prompt: 'work' }) + await callSubagent(ctx, { name: `child-${randomUUID()}`, description: 'second', prompt: 'work' }) await subagentConfigs.get(ctx)!.update({ maxDepth: 0 }) const disabled = ctx.systemPrompt.refreshContext(initial, assembleContextFor(agent)) expect(disabled.contexts.find(part => part.name === 'tool:subagent:depth')?.text) @@ -448,7 +449,7 @@ it('reads the saved default depth at each delegation without remounting the tool expect(ctx.systemPrompt.refreshContext(disabled, assembleContextFor(agent)) .contexts.find(part => part.name === 'tool:subagent:depth')?.text).toBe('') await subagentConfigs.get(ctx)!.update({ maxDepth: 0 }) - await callSubagent(ctx, { description: 'disabled', prompt: 'work' }) + await callSubagent(ctx, { name: `child-${randomUUID()}`, description: 'disabled', prompt: 'work' }) expect(depths).toEqual([1, 5, 0]) } finally { await ctx.fiber.dispose() diff --git a/packages/subagent/tool-subagent/tests/model-selection.spec.ts b/packages/subagent/tool-subagent/tests/model-selection.spec.ts index 5182ecfcc0..d2d7aaf41a 100644 --- a/packages/subagent/tool-subagent/tests/model-selection.spec.ts +++ b/packages/subagent/tool-subagent/tests/model-selection.spec.ts @@ -1,3 +1,4 @@ +import { randomUUID } from 'node:crypto' import { mountWorkingDirectoryFixture } from '../../subagent/tests/working-directory-fixture.ts' import { describe, expect, it, vi } from 'vitest' import { Context } from '@deepseek-ai/cordis' @@ -103,7 +104,7 @@ describe('dsh-tool-subagent model selection', () => { model: 'deployment-model', } - const result = await callSubagent(ctx, { description: 'default route', prompt: 'do it' }) + const result = await callSubagent(ctx, { name: `child-${randomUUID()}`, description: 'default route', prompt: 'do it' }) expect(result.isError).toBe(false) expect(starts).toBe(1) @@ -117,6 +118,7 @@ describe('dsh-tool-subagent model selection', () => { 'cwd', 'description', 'model', + 'name', 'prompt', 'provider', 'reasoning_effort', @@ -136,11 +138,11 @@ describe('dsh-tool-subagent model selection', () => { const ctx = await setup({ provider: 'mock' }) const schema = ctx.tools.schemas().find(entry => entry.name === 'subagent')! const props = (schema.parameters as { properties?: Record }).properties ?? {} - expect(Object.keys(props).sort()).toEqual(['cwd', 'description', 'prompt']) + expect(Object.keys(props).sort()).toEqual(['cwd', 'description', 'name', 'prompt']) expect(schema.description).not.toContain('list_subagent_models') expect(ctx.tools.get('list_subagent_models')).toBeUndefined() - const result = await callSubagent(ctx, { + const result = await callSubagent(ctx, { name: `child-${randomUUID()}`, description: 'forced route', prompt: 'do it', provider: 'alpha', @@ -173,7 +175,7 @@ describe('dsh-tool-subagent model selection', () => { const parent = modelSelectionSetupAgent(ctx) ;(parent as { options: Agent['options'] }).options = parentWithRoute().options - const selected = await callSubagent(ctx, { + const selected = await callSubagent(ctx, { name: `child-${randomUUID()}`, description: 'route work', prompt: 'do it', provider: 'alpha', @@ -186,7 +188,7 @@ describe('dsh-tool-subagent model selection', () => { maxTokens: 321, }) - const effort = await callSubagent(ctx, { + const effort = await callSubagent(ctx, { name: `child-${randomUUID()}`, description: 'same route effort', prompt: 'do it', provider: 'alpha', @@ -213,7 +215,7 @@ describe('dsh-tool-subagent model selection', () => { const parent = modelSelectionSetupAgent(ctx) ;(parent as { options: Agent['options'] }).options = parentWithRoute().options - const result = await callSubagent(ctx, { + const result = await callSubagent(ctx, { name: `child-${randomUUID()}`, description: 'effort work', prompt: 'do it', reasoning_effort: 'low', @@ -225,7 +227,7 @@ describe('dsh-tool-subagent model selection', () => { inherited.llm.registerAdapter(['alpha'], new MockAdapter([], REASONING)) const inheritedParent = modelSelectionSetupAgent(inherited) ;(inheritedParent as { options: Agent['options'] }).options = parentWithRoute().options - const inheritedResult = await callSubagent(inherited, { + const inheritedResult = await callSubagent(inherited, { name: `child-${randomUUID()}`, description: 'parent effort work', prompt: 'do it', reasoning_effort: 'low', @@ -238,7 +240,7 @@ describe('dsh-tool-subagent model selection', () => { ctx.llm.registerAdapter(['alpha'], new MockAdapter([], REASONING)) const parent = modelSelectionSetupAgent(ctx) ;(parent as { options: Agent['options'] }).options = parentWithRoute().options - const result = await callSubagent(ctx, { + const result = await callSubagent(ctx, { name: `child-${randomUUID()}`, description: 'same route work', prompt: 'do it', provider: 'alpha', @@ -264,7 +266,7 @@ describe('dsh-tool-subagent model selection', () => { reason: 'initial', }) - const result = await callSubagent(ctx, { + const result = await callSubagent(ctx, { name: `child-${randomUUID()}`, description: 'same current route', prompt: 'do it', provider: 'current-provider', @@ -281,7 +283,7 @@ describe('dsh-tool-subagent model selection', () => { it('rejects an effort without any effective route', async () => { const ctx = await setup({ provider: 'mock', withModelSelection: true }) - const result = await callSubagent(ctx, { + const result = await callSubagent(ctx, { name: `child-${randomUUID()}`, description: 'missing route', prompt: 'do it', reasoning_effort: 'low', @@ -302,7 +304,7 @@ describe('dsh-tool-subagent model selection', () => { ])('rejects a partial model-facing route before child creation', async (route) => { let starts = 0 const ctx = await setup({ provider: 'mock', withModelSelection: true }, { onStart: () => { starts += 1 } }) - const result = await callSubagent(ctx, { description: 'partial route', prompt: 'do it', ...route }) + const result = await callSubagent(ctx, { name: `child-${randomUUID()}`, description: 'partial route', prompt: 'do it', ...route }) expect(result.isError).toBe(true) expect(text(result)).toContain('`provider` and `model` must be supplied together') expect(starts).toBe(0) @@ -314,7 +316,7 @@ describe('dsh-tool-subagent model selection', () => { { reasoning_effort: '', expected: '`reasoning_effort` must be non-empty' }, ])('rejects empty model-facing values', async ({ expected, ...selection }) => { const ctx = await setup({ provider: 'mock', withModelSelection: true }) - const result = await callSubagent(ctx, { description: 'empty route', prompt: 'do it', ...selection }) + const result = await callSubagent(ctx, { name: `child-${randomUUID()}`, description: 'empty route', prompt: 'do it', ...selection }) expect(result.isError).toBe(true) expect(text(result)).toContain(expected) }) @@ -324,7 +326,7 @@ describe('dsh-tool-subagent model selection', () => { const ctx = await setup({ provider: 'mock', withModelSelection: true }, { onStart: () => { starts += 1 } }) ctx.llm.registerAdapter(['alpha'], new MockAdapter([], REASONING)) - const unsupported = await callSubagent(ctx, { + const unsupported = await callSubagent(ctx, { name: `child-${randomUUID()}`, description: 'bad effort', prompt: 'do it', provider: 'alpha', @@ -334,7 +336,7 @@ describe('dsh-tool-subagent model selection', () => { expect(unsupported.isError).toBe(true) expect(text(unsupported)).toContain('does not support reasoning effort "max"') - const missing = await callSubagent(ctx, { + const missing = await callSubagent(ctx, { name: `child-${randomUUID()}`, description: 'bad provider', prompt: 'do it', provider: 'missing', @@ -362,7 +364,7 @@ describe('dsh-tool-subagent model selection', () => { const result = await callSubagent( ctx, - { description: 'same route', prompt: 'do it' }, + { name: `child-${randomUUID()}`, description: 'same route', prompt: 'do it' }, { agent: parentWithRoute() }, ) expect(result.isError).toBe(true) @@ -379,7 +381,7 @@ describe('dsh-tool-subagent model selection', () => { const result = await callSubagent( ctx, - { description: 'configured route', prompt: 'do it' }, + { name: `child-${randomUUID()}`, description: 'configured route', prompt: 'do it' }, { agent: parentWithRoute() }, ) @@ -405,7 +407,7 @@ describe('dsh-tool-subagent model selection', () => { }, }) - const configured = await callSubagent(ctx, { description: 'configured effort', prompt: 'do it' }, { agent: parentWithRoute() }) + const configured = await callSubagent(ctx, { name: `child-${randomUUID()}`, description: 'configured effort', prompt: 'do it' }, { agent: parentWithRoute() }) expect(configured.isError).toBe(true) expect(text(configured)).toContain('`llm` service is unavailable') @@ -418,7 +420,7 @@ describe('dsh-tool-subagent model selection', () => { const resolve = vi.spyOn(adapter, 'resolveModel') ctx.llm.registerAdapter(['alpha'], adapter) - const result = await callSubagent(ctx, { description: 'inherit route', prompt: 'do it' }) + const result = await callSubagent(ctx, { name: `child-${randomUUID()}`, description: 'inherit route', prompt: 'do it' }) expect(result.isError).toBe(false) expect(started).toHaveBeenCalledOnce() expect(resolve).not.toHaveBeenCalled() @@ -438,7 +440,7 @@ describe('dsh-tool-subagent model selection', () => { vi.spyOn(adapter, 'resolveModel').mockRejectedValue(new Error('selected route unavailable')) ctx.llm.registerAdapter(['alpha'], adapter) - const result = await callSubagent(ctx, { + const result = await callSubagent(ctx, { name: `child-${randomUUID()}`, description: 'route work', prompt: 'do it', provider: 'alpha', diff --git a/packages/subagent/tool-subagent/tests/preset-selection.spec.ts b/packages/subagent/tool-subagent/tests/preset-selection.spec.ts index c53d9501d8..d2ff230d2b 100644 --- a/packages/subagent/tool-subagent/tests/preset-selection.spec.ts +++ b/packages/subagent/tool-subagent/tests/preset-selection.spec.ts @@ -1,3 +1,4 @@ +import { randomUUID } from 'node:crypto' /** Deployment configuration and model-facing selection for spawn presets. */ import { mountWorkingDirectoryFixture } from '../../subagent/tests/working-directory-fixture.ts' import { Context } from '@deepseek-ai/cordis' @@ -46,7 +47,7 @@ async function setup(config: Omit, providerConfig: Part return { ctx, onStart, provider, presets } } -const args = { description: 'review task', prompt: 'Review this change.' } +const args = { name: `child-${randomUUID()}`, description: 'review task', prompt: 'Review this change.' } describe('spawn preset selection', () => { it('advertises configured ids and forwards a model selection without child composition overrides', async () => { diff --git a/packages/subagent/tool-subagent/tests/tool-subagent.spec.ts b/packages/subagent/tool-subagent/tests/tool-subagent.spec.ts index 8a4e356828..4f2446a6fa 100644 --- a/packages/subagent/tool-subagent/tests/tool-subagent.spec.ts +++ b/packages/subagent/tool-subagent/tests/tool-subagent.spec.ts @@ -1,3 +1,4 @@ +import { randomUUID } from 'node:crypto' import { mountWorkingDirectoryFixture } from '../../subagent/tests/working-directory-fixture.ts' import { afterEach, describe, expect, it, vi } from 'vitest' import { mkdtempSync, rmSync } from 'node:fs' @@ -61,16 +62,16 @@ describe('dsh-tool-subagent', () => { )).rejects.toThrow('does not support child agentOptions') }) - it('starts a managed subagent and returns its id without collecting its output', async () => { + it('starts a managed subagent and returns its name without collecting its output', async () => { const ctx = await setup({ provider: 'mock' }, { reply: 'child says hi' }) - const result = await callSubagent(ctx, { + const result = await callSubagent(ctx, { name: `child-${randomUUID()}`, description: 'do a thing', prompt: 'go research X', }) expect(result.isError).toBe(false) if (result.isError) throw new Error('expected subagent success') expect(result.value).toHaveProperty('kind', 'activation') - expect(result.value).toHaveProperty('subagentId', expect.any(String)) + expect(result.value).toHaveProperty('name', expect.any(String)) expect(text(result)).toMatch(/^started subagent /) }) @@ -82,7 +83,7 @@ describe('dsh-tool-subagent', () => { const parent = modelSelectionSetupAgent(ctx) const parentCwd = ctx.workingDirectory.get(parent.session) try { - const result = await callSubagent(ctx, { + const result = await callSubagent(ctx, { name: `child-${randomUUID()}`, description: 'inspect packages', prompt: 'list the packages', cwd: 'packages', @@ -102,6 +103,7 @@ describe('dsh-tool-subagent', () => { expect(Object.keys(props).sort()).toEqual([ 'cwd', 'description', + 'name', 'prompt', ]) expect(schema!.description).not.toContain('job_output') @@ -113,13 +115,13 @@ describe('dsh-tool-subagent', () => { signal: testToolSignal, callId: ToolCallId('subagent-first'), name: 'subagent', - arguments: { description: 'do work', prompt: 'Reply OK' }, + arguments: { name: `child-${randomUUID()}`, description: 'do work', prompt: 'Reply OK' }, })).toEqual({ kind: 'parallel' }) expect(ctx.tools.executionMode({ signal: testToolSignal, callId: ToolCallId('subagent-second'), name: 'subagent', - arguments: { description: 'do work', prompt: 'Reply OK' }, + arguments: { name: `child-${randomUUID()}`, description: 'do work', prompt: 'Reply OK' }, })).toEqual({ kind: 'parallel' }) }) @@ -138,8 +140,8 @@ describe('dsh-tool-subagent', () => { }, }) const results = await Promise.all([ - callSubagent(ctx, { description: 'first', prompt: 'p1' }), - callSubagent(ctx, { description: 'second', prompt: 'p2' }), + callSubagent(ctx, { name: `child-${randomUUID()}`, description: 'first', prompt: 'p1' }), + callSubagent(ctx, { name: `child-${randomUUID()}`, description: 'second', prompt: 'p2' }), ]) expect(started.sort()).toEqual(['first', 'second']) for (const result of results) expect(result.isError).toBe(false) @@ -161,8 +163,8 @@ describe('dsh-tool-subagent', () => { expect(names).toEqual(['subagent', 'subagent_acp']) const parent = (await ctx.agents.create({ sessionId: SessionId('multi-provider-parent') })).agent - const viaSpawn = await ctx.tools.execute({ signal: testToolSignal, callId: ToolCallId('c-spawn'), name: 'subagent', arguments: { description: 'd', prompt: 'p' }, agent: parent }) - const viaAcp = await ctx.tools.execute({ signal: testToolSignal, callId: ToolCallId('c-acp'), name: 'subagent_acp', arguments: { description: 'd', prompt: 'p' }, agent: parent }) + const viaSpawn = await ctx.tools.execute({ signal: testToolSignal, callId: ToolCallId('c-spawn'), name: 'subagent', arguments: { name: `child-${randomUUID()}`, description: 'd', prompt: 'p' }, agent: parent }) + const viaAcp = await ctx.tools.execute({ signal: testToolSignal, callId: ToolCallId('c-acp'), name: 'subagent_acp', arguments: { name: `child-${randomUUID()}`, description: 'd', prompt: 'p' }, agent: parent }) expect(text(viaSpawn)).toMatch(/^started subagent /) expect(text(viaAcp)).toMatch(/^started subagent /) }) @@ -184,7 +186,7 @@ describe('dsh-tool-subagent', () => { ctx.llm.registerAdapter(['alpha'], adapter) const controller = new AbortController() - const resultPromise = callSubagent(ctx, { + const resultPromise = callSubagent(ctx, { name: `child-${randomUUID()}`, description: 'cancelled selection', prompt: 'do it', }, { agent: parent, signal: controller.signal }) @@ -217,7 +219,7 @@ describe('dsh-tool-subagent', () => { }) ctx.llm.registerAdapter(['alpha'], adapter) - const pending = callSubagent(ctx, { + const pending = callSubagent(ctx, { name: `child-${randomUUID()}`, description: 'swapped provider', prompt: 'do it', provider: 'alpha', @@ -256,7 +258,7 @@ describe('dsh-tool-subagent', () => { efforts: [{ id: ReasoningEffortId('high'), name: 'High' }], })) - await callSubagent(ctx, { + await callSubagent(ctx, { name: `child-${randomUUID()}`, description: 'd', prompt: 'p', provider: 'alpha', @@ -290,7 +292,7 @@ describe('dsh-tool-subagent', () => { ctx.llm.registerAdapter(['alpha'], new MockAdapter([])) const parent = modelSelectionSetupAgent(ctx) - const result = await callSubagent(ctx, { + const result = await callSubagent(ctx, { name: `child-${randomUUID()}`, description: 'd', prompt: 'p', provider: 'alpha', @@ -329,13 +331,13 @@ describe('dsh-tool-subagent', () => { await new Promise(r => setTimeout(r, 10)) expect(ctx.tools.schemas().some(s => s.name === 'subagent')).toBe(true) - await callSubagent(ctx, { description: 'd', prompt: 'p' }) + await callSubagent(ctx, { name: `child-${randomUUID()}`, description: 'd', prompt: 'p' }) expect(seen?.agentOptions).toBeUndefined() }) it('fails loud when invoked without a calling agent', async () => { const ctx = await setup({ provider: 'mock' }) - const result = await callSubagent(ctx, { description: 'd', prompt: 'p' }, { agent: undefined }) + const result = await callSubagent(ctx, { name: `child-${randomUUID()}`, description: 'd', prompt: 'p' }, { agent: undefined }) expect(result.isError).toBe(true) expect(text(result)).toContain('requires a calling agent') }) @@ -352,7 +354,7 @@ describe('dsh-tool-subagent', () => { // Backend arrives (as a delayed sibling fiber would): the tool appears. await mock.mountScriptedProvider(ctx, { name: 'mock', reply: 'late but fine' }) expect(ctx.tools.schemas().some(s => s.name === 'subagent')).toBe(true) - const result = await callSubagent(ctx, { description: 'd', prompt: 'p' }) + const result = await callSubagent(ctx, { name: `child-${randomUUID()}`, description: 'd', prompt: 'p' }) expect(text(result)).toMatch(/^started subagent /) }) @@ -533,7 +535,7 @@ describe('dsh-tool-subagent', () => { const controller = new AbortController() controller.abort() // already aborted BEFORE the tool runs - const result = await callSubagent(ctx, { description: 'd', prompt: 'p' }, { signal: controller.signal }) + const result = await callSubagent(ctx, { name: `child-${randomUUID()}`, description: 'd', prompt: 'p' }, { signal: controller.signal }) expect(sawAborted).not.toHaveBeenCalled() expect(result.isError).toBe(true) expect(result.error).toEqual({ @@ -599,7 +601,7 @@ describe('dsh-tool-subagent', () => { maxDepth: 2, }) - await callSubagent(ctx, { description: 'd', prompt: 'p' }) + await callSubagent(ctx, { name: `child-${randomUUID()}`, description: 'd', prompt: 'p' }) expect(seen?.maxDepth).toBe(2) }) @@ -657,7 +659,7 @@ describe('dsh-tool-subagent', () => { }, }) await ctx.plugin(tool, { provider: 'capture4', maxDepth: 'provider-managed' }) - await callSubagent(ctx, { description: 'd', prompt: 'p' }) + await callSubagent(ctx, { name: `child-${randomUUID()}`, description: 'd', prompt: 'p' }) expect(seen).toBeDefined() expect(seen).not.toHaveProperty('agentOptions') }) @@ -698,11 +700,11 @@ describe('dsh-tool-subagent local activation', () => { signal: testToolSignal, callId: ToolCallId('subagent-continuable'), name: 'subagent', - arguments: { description: 'do work', prompt: 'Reply OK' }, + arguments: { name: `child-${randomUUID()}`, description: 'do work', prompt: 'Reply OK' }, })).toEqual({ kind: 'parallel' }) }) - it('starts a local activation and returns only its durable id', async () => { + it('starts a local activation and returns only its name', async () => { const { ctx, parent } = await continuableSetup() const schema = ctx.tools.schemas().find(s => s.name === 'subagent')! // Continuable delegation has no Task, so the schema promises no collection. @@ -711,7 +713,7 @@ describe('dsh-tool-subagent local activation', () => { expect(schema.description).toContain('send_message') expect(schema.description).toContain('steer it while running') expect(schema.description).not.toContain('send_message` starts a later turn') - expect(schema.description).toContain('immediately returns its id') + expect(schema.description).toContain('immediately returns its name') expect(schema.description).not.toContain('never poll or wait on it') const properties = (schema.parameters as { properties: Record @@ -723,20 +725,21 @@ describe('dsh-tool-subagent local activation', () => { const started = await callSubagent( ctx, - { description: 'continuable work', prompt: 'dig in' }, + { name: `child-${randomUUID()}`, description: 'continuable work', prompt: 'dig in' }, { agent: parent }, ) expect(started.isError).toBe(false) const match = /^started subagent (\S+)$/.exec(text(started)) expect(match).not.toBeNull() - const [, childId] = match! + const [, childName] = match! + const childId = await ctx.subagents.resolveName(parent, childName!) // No Task was created for the continuable child. await vi.waitFor(() => { - expect(ctx.agents.get(SessionId(childId!))).toBeUndefined() + expect(ctx.agents.get(SessionId(childId))).toBeUndefined() }, { timeout: 5_000 }) // The child id names a durable session carrying its continuation descriptor. - const loaded = await loadStoredSession(ctx.sessionPersistence, SessionId(childId!)) + const loaded = await loadStoredSession(ctx.sessionPersistence, SessionId(childId)) expect(loaded.events.some(event => event.type === 'subagent/descriptor')).toBe(true) expect(loaded.events.some(event => event.type === 'assistant/message')).toBe(true) }) @@ -782,7 +785,7 @@ describe('dsh-tool-subagent local activation', () => { signal, callId: ToolCallId(callId), name: 'subagent_gated', - arguments: { description, prompt: 'work' }, + arguments: { name: `child-${randomUUID()}`, description, prompt: 'work' }, agent: parent, }) const cancelledResult = execute('continuable-cancelled', 'cancelled sibling', cancelled.signal) @@ -802,7 +805,7 @@ describe('dsh-tool-subagent local activation', () => { expect(succeeded.isError ? undefined : succeeded.value).toEqual({ kind: 'activation', - subagentId: survivingChildId, + name: ctx.subagents.nameOf(parent, survivingChildId), }) await vi.waitFor(() => { expect(ctx.agents.get(survivingChildId!)).toBeUndefined() @@ -840,7 +843,7 @@ describe('depth budget configuration', () => { it('defaults maxDepth to 1 and forwards it in the start request', async () => { const { ctx, requests } = await captureSetup() - await callSubagent(ctx, { description: 'd', prompt: 'p' }) + await callSubagent(ctx, { name: `child-${randomUUID()}`, description: 'd', prompt: 'p' }) expect(requests[0]?.label).toBe('d') expect(requests[0]?.maxDepth).toBe(1) }) @@ -878,7 +881,7 @@ describe('depth budget configuration', () => { }, }) await ctx.plugin(tool, { provider: 'external', maxDepth: 'provider-managed' }) - await callSubagent(ctx, { description: 'd', prompt: 'p' }) + await callSubagent(ctx, { name: `child-${randomUUID()}`, description: 'd', prompt: 'p' }) expect(requests[0]?.maxDepth).toBeUndefined() }) }) diff --git a/packages/test-support/llm-replay/README.i18n.yaml b/packages/test-support/llm-replay/README.i18n.yaml index 60d4ffe071..70b7eff19c 100644 --- a/packages/test-support/llm-replay/README.i18n.yaml +++ b/packages/test-support/llm-replay/README.i18n.yaml @@ -24,8 +24,8 @@ en: d7dd048cd69e723d zh: 9f5dfa5186549cd0 /deepseek-ai-dsh-llm-replay/use-this-package/nested-agents: - en: 7745c49d10a63b0e - zh: 937b954c664f1973 + en: 73685597262e291d + zh: fbdf89bef2f9841b /deepseek-ai-dsh-llm-replay/use-this-package/failure-modes-and-overrides: en: 319e95521a4a06fe zh: 884c8299028df8a3 diff --git a/packages/test-support/llm-replay/README.md b/packages/test-support/llm-replay/README.md index 85f57ded39..e2c20ae541 100644 --- a/packages/test-support/llm-replay/README.md +++ b/packages/test-support/llm-replay/README.md @@ -71,7 +71,7 @@ The fixture is a projection of one selected persisted Session generation produce ### Nested agents -A scenario where a parent agent delegates to in-process subagents records one role per Session: parent `session[.vN].jsonl`, then contiguous children `session.[.vN].jsonl`. The snapshot harness supplies only the highest generation of each role. Live Session ids are freshly random each run, so replay binds each live Session to a recorded script by first-call order: the first live Session to make a model call claims the parent script, the next new Session the next child script, and so on, with each Session advancing its own cursor. More distinct live Sessions than recorded scripts fails loud. +A scenario where a parent agent delegates to in-process subagents records one role per Session: parent `session[.vN].jsonl`, then contiguous children `session.[.vN].jsonl`. The snapshot harness supplies only the highest generation of each role. Live Session ids are freshly random each run, so replay binds each live Session to a recorded script by first-call order: the first live Session to make a model call claims the parent script, the next new Session the next child script, and so on, with each Session advancing its own cursor. More distinct live Sessions than recorded scripts fails loud. Agent names in tool results do not bind Session identities; a typed Session token requires that Session’s first model call. ### Failure modes and overrides diff --git a/packages/test-support/llm-replay/README.zh.md b/packages/test-support/llm-replay/README.zh.md index d962445ead..076ccb8185 100644 --- a/packages/test-support/llm-replay/README.zh.md +++ b/packages/test-support/llm-replay/README.zh.md @@ -71,7 +71,7 @@ fixture 是运行一次真实 agent 所产生的一份选定持久化 Session ge ### 嵌套 agent -parent agent 委托给进程内 subagent 的场景会为每个 Session 记录一个角色:parent 为 `session[.vN].jsonl`,随后是连续 child `session.[.vN].jsonl`。snapshot harness 只提供每个角色的最高 generation。live Session id 每次运行都会重新随机生成,因此 replay 按首次调用顺序把每个 live Session 绑定到已记录脚本:第一个发起模型调用的 live Session 取得 parent 脚本,下一个新 Session 取得下一条 child 脚本,依此类推,每个 Session 分别推进自己的 cursor。不同 live Session 数量超过已记录脚本数时会明确报错。 +parent agent 委托给进程内 subagent 的场景会为每个 Session 记录一个角色:parent 为 `session[.vN].jsonl`,随后是连续 child `session.[.vN].jsonl`。snapshot harness 只提供每个角色的最高 generation。live Session id 每次运行都会重新随机生成,因此 replay 按首次调用顺序把每个 live Session 绑定到已记录脚本:第一个发起模型调用的 live Session 取得 parent 脚本,下一个新 Session 取得下一条 child 脚本,依此类推,每个 Session 分别推进自己的 cursor。不同 live Session 数量超过已记录脚本数时会明确报错。 工具结果中的 agent 名字不绑定 Session 身份;带类型的 Session token 要求该 Session 已发起首次模型调用。 ### 失败模式与覆盖 diff --git a/packages/test-support/llm-replay/src/index.ts b/packages/test-support/llm-replay/src/index.ts index 656ec3bcb6..7c878333c1 100644 --- a/packages/test-support/llm-replay/src/index.ts +++ b/packages/test-support/llm-replay/src/index.ts @@ -645,25 +645,6 @@ function materializeSessionTokens(entry: ReplayEntry, liveSessionIds: readonly ( return replace(entry) as ReplayEntry } -/** Learn a background child id from the stable tool-result text before that child reaches its first model call. */ -function inferStartedSubagents( - messages: GenerateOptions['messages'], - liveSessionIds: (string | undefined)[], -): void { - const leaves: string[] = [] - collectStrings(messages, leaves) - for (const leaf of leaves) { - for (const match of leaf.matchAll(/started subagent ([^\s"'<>]+)/g)) { - const id = match[1] - /* v8 ignore next -- the fixed regular expression always has capture group 1. */ - if (id === undefined || liveSessionIds.includes(id)) continue - const index = liveSessionIds.findIndex((value, candidate) => candidate > 0 && value === undefined) - if (index < 0) return - liveSessionIds[index] = id - } - } -} - function isRecord(value: unknown): value is Record { return typeof value === 'object' && value !== null && !Array.isArray(value) } @@ -1079,7 +1060,6 @@ export function installLlmReplay(ctx: Context, config: ReplayConfig): ReplayHand + `but its script has only ${boundState.entries.length}; re-record the scenario`, ) } - inferStartedSubagents(options.messages, liveSessionIds) const resolved = resolveScriptedEntry(materializeSessionTokens(entry, liveSessionIds), options.messages) if (options.provider === 'deepseek-official' && providerAccepted(resolved)) { const extensions = ctx.get('deepseekLlmApiExtensions') diff --git a/packages/test-support/llm-replay/tests/llm-replay.spec.ts b/packages/test-support/llm-replay/tests/llm-replay.spec.ts index 6684677a0b..fa0303c793 100644 --- a/packages/test-support/llm-replay/tests/llm-replay.spec.ts +++ b/packages/test-support/llm-replay/tests/llm-replay.spec.ts @@ -2073,7 +2073,7 @@ describe('installLlmReplay (per-session keying)', () => { await expect(drain(ctx.llm.stream(live('live-parent')))).rejects.toThrow(/used before.*bound/) }) - it('learns a background child id from its started-subagent tool result', async () => { + it('does not interpret a started subagent name as a bound session identity', async () => { const reference: StreamChunk[] = [ { type: 'text-delta', index: 0, text: '{{session:2}}' }, { type: 'finish', reason: { kind: 'stop' } }, @@ -2091,10 +2091,7 @@ describe('installLlmReplay (per-session keying)', () => { })], } - expect(await drain(ctx.llm.stream(options))).toEqual([ - { type: 'text-delta', index: 0, text: 'live-child-before-call' }, - { type: 'finish', reason: { kind: 'stop' } }, - ]) + await expect(drain(ctx.llm.stream(options))).rejects.toThrow(/used before.*bound/) }) it('ignores started-subagent text after every recorded session has bound', async () => { diff --git a/packages/test-support/session-snapshot/README.i18n.yaml b/packages/test-support/session-snapshot/README.i18n.yaml index 7df8a50f25..25d99fa433 100644 --- a/packages/test-support/session-snapshot/README.i18n.yaml +++ b/packages/test-support/session-snapshot/README.i18n.yaml @@ -18,8 +18,8 @@ en: 594ad1f3e6f02054 zh: 7ca4f565976704be /deepseek-ai-dsh-session-snapshot/use-this-package/writing-a-snapshot-suite: - en: 57ff7c89e7696ee8 - zh: b885ac1b4edc8c56 + en: 79fb42dbf18674de + zh: cf61f69241da899d /deepseek-ai-dsh-session-snapshot/use-this-package/record-replay-and-refresh: en: 2bea67c686715289 zh: aecc6ea7b4ae5623 diff --git a/packages/test-support/session-snapshot/README.md b/packages/test-support/session-snapshot/README.md index ad26047830..3e0c4311d9 100644 --- a/packages/test-support/session-snapshot/README.md +++ b/packages/test-support/session-snapshot/README.md @@ -70,7 +70,7 @@ defineAcpSnapshotSuite({ Each recorded-session directory carries a closed `snapshot.yml` manifest plus canonical parent and contiguous child roles. Parent filenames are `session[.vN].jsonl`; children are `session.[.vN].jsonl`; v0 omits `.v0`, positive versions use lowercase `.vN`, and every filename agrees with its header. A role may retain older generations, but the harness selects the numerically highest one. An owning manifest may declare `sessionFormat.version` plus one or more closed `coverage` names to keep that historical generation as an explicit migration fixture. Without that declaration, record and refresh write the current generation; replay independently accepts the retained V3 baseline or the current generation for each parent/child role under the [corpus policy](../../../snapshots/AGENTS.md). An explicit `sessionFormat.version` requires every selected role to match that version. The manifest also names the scenario, shipped profile, composition/header class, recording source, and only the replay, platform, permission, environment, workspace, or input facts the completed Session cannot reconstruct. Storage guards check tool results and portable paths in every selected parent and child role. Prompt/schema scrubbing, message identity, and prompt-before-request ordering apply to current generations; retained predecessors keep their historical representation. The adapter registers expected-output, Session-log, and optional `workspace.expected/` comparisons; guards reject orphan directories, missing roles, noncanonical names, absolute paths, malformed manifests, and platform-specific separators. -`normalizeSessionSnapshot` retains the complete Session header and event payloads but omits top-level `seq`/`time` envelopes from committed fixtures after normalizing paths and scrubbing system-prompt text and tool schemas; it also normalizes embedded stream clocks and historical packed-row `seq0`/`time0` envelopes, and catalog child-creation clocks. Event order and source-event reference order are preserved. Record and refresh write top-level `sourceEventSeqs` as expanded arrays. Replay synthesizes the top-level envelopes in memory, while runtime persistence continues to write complete logs. Multi-session comparison validates expected and harvested logs through the strict build-static Session format catalog before identity redaction and normalization; source filenames cannot alter format validation. A retained historical replay input is not the native current-format writer-output oracle: structural migration preserves request meaning but can produce a different event layout. Normalization preserves unexpected request-header fields, including `system`, so regressions remain visible. Versionless protocol-adapter unit fixtures remain outside the released Session format corpus. Fixtures in the [current writer format](../../../docs/session-format-status.md) use one row per event; retained v0/v1 fixtures may use canonical packed rows. The [temporary repository migrator](../../../scripts/migrate-packed-session-fixtures.ts) (`pnpm run migrate:packed-session-fixtures`) rewrites older historical layouts, and its [removal proposal](../../../.agents/notes/proposed/process/2026-07-26-remove-packed-session-fixture-migrator.md) owns its deletion. +`normalizeSessionSnapshot` retains the complete Session header and event payloads but omits top-level `seq`/`time` envelopes from committed fixtures after normalizing paths and scrubbing system-prompt text and tool schemas; it also normalizes embedded stream clocks and historical packed-row `seq0`/`time0` envelopes, and catalog child-creation clocks. In `subagent/named` events, names matching the generated `workflow--` format retain their ordinal while the embedded run identity receives a typed workflow token. Event order and source-event reference order are preserved. Record and refresh write top-level `sourceEventSeqs` as expanded arrays. Replay synthesizes the top-level envelopes in memory, while runtime persistence continues to write complete logs. Multi-session comparison validates expected and harvested logs through the strict build-static Session format catalog before identity redaction and normalization; source filenames cannot alter format validation. A retained historical replay input is not the native current-format writer-output oracle: structural migration preserves request meaning but can produce a different event layout. Normalization preserves unexpected request-header fields, including `system`, so regressions remain visible. Versionless protocol-adapter unit fixtures remain outside the released Session format corpus. Fixtures in the [current writer format](../../../docs/session-format-status.md) use one row per event; retained v0/v1 fixtures may use canonical packed rows. The [temporary repository migrator](../../../scripts/migrate-packed-session-fixtures.ts) (`pnpm run migrate:packed-session-fixtures`) rewrites older historical layouts, and its [removal proposal](../../../.agents/notes/proposed/process/2026-07-26-remove-packed-session-fixture-migrator.md) owns its deletion. Spill scenarios save through the real local provider under a private temporary root. Their fixture adapter exposes fixed-length logical locators and maps only this run’s saved locators back to real files for retrieval, preserving preview budgets without writing into a shared logical path. Known snapshot spill paths normalize to stable locator tokens, including paths quoted inside JSON omission notices with JSON-escaped Windows separators. Refresh extraction preserves the matched serialized path spelling for literal replacement. Normalization changes only the locator: saved byte lengths and omission counts remain comparison evidence. diff --git a/packages/test-support/session-snapshot/README.zh.md b/packages/test-support/session-snapshot/README.zh.md index 161ad64cc7..58638d31a2 100644 --- a/packages/test-support/session-snapshot/README.zh.md +++ b/packages/test-support/session-snapshot/README.zh.md @@ -70,7 +70,7 @@ defineAcpSnapshotSuite({ 每个已记录 Session 目录携带封闭的 `snapshot.yml` manifest,以及规范 parent 与连续 child 角色。parent 文件名是 `session[.vN].jsonl`;child 是 `session.[.vN].jsonl`;v0 省略 `.v0`,正版本使用小写 `.vN`,且每个文件名与其 header 一致。一个角色可以保留旧 generation,但 harness 会选择数值最高的一项。拥有 fixture 的 manifest 可以声明 `sessionFormat.version` 与一个或多个封闭 `coverage` 名称,把该历史 generation 保留为显式迁移 fixture。未声明时,record 与 refresh 写入当前 generation;replay 按[语料策略](../../../snapshots/AGENTS.md)对每个 parent/child 角色独立接受保留的 V3 基线或当前 generation。显式声明 `sessionFormat.version` 时,每个选定角色都必须匹配该版本。manifest 还会指名场景、随附 profile、组合/header 类别、录制来源,以及已完成 Session 无法重建的 replay、平台、权限、环境、workspace 或输入事实。存储保护检查每个选定 parent 与 child 角色的工具结果和可移植路径。提示词/schema 擦除、消息身份及提示词先于请求的顺序检查适用于当前 generation;保留的前代维持其历史表示。适配器注册预期输出、Session 日志与可选 `workspace.expected/` 比较;保护会拒绝遗留目录、缺失角色、非规范名称、绝对路径、格式错误的 manifest 与平台专用分隔符。 -`normalizeSessionSnapshot` 在规范化路径并擦除系统提示文本与工具 schema 后,会保留完整 Session header 与事件 payload,但从已提交 fixture 中省略顶层 `seq`/`time` envelope;它还会规范化嵌入式 stream clock 与历史 packed-row 的 `seq0`/`time0` envelope 与 catalog child 创建时钟。事件顺序与来源事件引用的顺序保持不变。录制与刷新会将顶层 `sourceEventSeqs` 以展开数组的形式写入 fixture。Replay 只在内存中合成顶层 envelope,而运行时持久化仍写入完整日志。多 Session 比较会先通过严格的构建期静态 Session 格式目录校验预期日志与收集日志,再进行身份脱敏与规范化;来源文件名不能改变格式校验。保留的历史 replay 输入不是原生当前格式 writer 输出的比较基准:结构迁移保留请求含义,但可以产生不同的事件布局。归一化保留意外的 request-header 字段(包括 `system`),使回归保持可见。无版本的协议适配器单元测试 fixture 不属于已发布 Session 格式语料。[当前写入器格式](../../../docs/session-format-status.zh.md)的 fixture 每个事件占一行;保留的 v0/v1 fixture 可以使用规范 packed row。[临时仓库迁移器](../../../scripts/migrate-packed-session-fixtures.ts)(`pnpm run migrate:packed-session-fixtures`)会改写更旧的历史布局,由其[移除提案](../../../.agents/notes/proposed/process/2026-07-26-remove-packed-session-fixture-migrator.zh.md)负责删除该迁移器。 +`normalizeSessionSnapshot` 在规范化路径并擦除系统提示文本与工具 schema 后,会保留完整 Session header 与事件 payload,但从已提交 fixture 中省略顶层 `seq`/`time` envelope;它还会规范化嵌入式 stream clock 与历史 packed-row 的 `seq0`/`time0` envelope 与 catalog child 创建时钟。在 `subagent/named` 事件中,符合自动生成格式 `workflow--` 的名称保留序号,其中的运行身份替换为带类型的 workflow token。事件顺序与来源事件引用的顺序保持不变。录制与刷新会将顶层 `sourceEventSeqs` 以展开数组的形式写入 fixture。Replay 只在内存中合成顶层 envelope,而运行时持久化仍写入完整日志。多 Session 比较会先通过严格的构建期静态 Session 格式目录校验预期日志与收集日志,再进行身份脱敏与规范化;来源文件名不能改变格式校验。保留的历史 replay 输入不是原生当前格式 writer 输出的比较基准:结构迁移保留请求含义,但可以产生不同的事件布局。归一化保留意外的 request-header 字段(包括 `system`),使回归保持可见。无版本的协议适配器单元测试 fixture 不属于已发布 Session 格式语料。[当前写入器格式](../../../docs/session-format-status.zh.md)的 fixture 每个事件占一行;保留的 v0/v1 fixture 可以使用规范 packed row。[临时仓库迁移器](../../../scripts/migrate-packed-session-fixtures.ts)(`pnpm run migrate:packed-session-fixtures`)会改写更旧的历史布局,由其[移除提案](../../../.agents/notes/proposed/process/2026-07-26-remove-packed-session-fixture-migrator.zh.md)负责删除该迁移器。 spill 场景通过真实本地提供方保存到私有临时根目录。fixture 适配器提供固定长度的逻辑定位符,并仅将本次运行已保存的定位符映射回实际文件以供检索,在不写入共享逻辑路径的情况下保留预览预算。已知的快照 spill 路径会规范化为稳定的定位符 token,包括 JSON 省略通知中带引号、使用 JSON 转义 Windows 分隔符的路径。刷新提取会保留匹配路径的序列化写法,以便进行字面替换。规范化只改变定位符:保存字节数与省略计数仍作为比较证据。 diff --git a/packages/test-support/session-snapshot/src/identity.ts b/packages/test-support/session-snapshot/src/identity.ts index cca42657c2..d3a1dc0661 100644 --- a/packages/test-support/session-snapshot/src/identity.ts +++ b/packages/test-support/session-snapshot/src/identity.ts @@ -5,6 +5,8 @@ const SHORT_JOB_ID_RE = /-[0-9a-f]{16}$/i const LEGACY_TOKEN_RE = /^\{\{(?:sessionId|messageId)\}\}$/ const CANONICAL_TOKEN_RE = /^\{\{(session|message|approval|workflow|command|rpc|retry|id):([1-9]\d*)\}\}$/ const ID_KEY_RE = /(?:^id$|Id$|Ids$)/ +const WORKFLOW_AGENT_NAME_RE + = /^workflow-([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}|\{\{workflow:[1-9]\d*\}\})-[1-9]\d*$/ type IdentityKind = 'session' | 'message' | 'approval' | 'workflow' | 'command' | 'rpc' | 'retry' | 'id' @@ -107,6 +109,11 @@ export function redactSessionSnapshotIds(logs: readonly string[]): string[] { if (record.type === 'feedback/message-put' && isRecord(record.data) && isRecord(record.data.item)) { claim(record.data.item.version, 'id') } + // Workflow-owned children embed their run identity even when the caller does not log workflow progress. + if (record.type === 'subagent/named' && isRecord(record.data) && typeof record.data.name === 'string') { + const workflow = WORKFLOW_AGENT_NAME_RE.exec(record.data.name) + if (workflow !== null) claim(workflow[1], 'workflow') + } collect(record, record.type) } } diff --git a/packages/test-support/session-snapshot/tests/fixtures/subagent-structured-parent.ts b/packages/test-support/session-snapshot/tests/fixtures/subagent-structured-parent.ts index 454f509a0a..9f63eaeb65 100644 --- a/packages/test-support/session-snapshot/tests/fixtures/subagent-structured-parent.ts +++ b/packages/test-support/session-snapshot/tests/fixtures/subagent-structured-parent.ts @@ -28,7 +28,7 @@ export function apply(ctx: Context): void { return next() }) try { - const activation = await ctx.subagents.startActivation({ + const activation = await ctx.subagents.startActivation({ name: 'structured-child', provider: 'spawn', label: 'Structured answer', delivery: 'parent', signal: exec.signal, request: { parent, prompt: [{ type: 'text', text: 'Submit answer 41 through structured_output.' }], diff --git a/packages/test-support/session-snapshot/tests/identity.spec.ts b/packages/test-support/session-snapshot/tests/identity.spec.ts index b6d0fef836..9cc828a8ab 100644 --- a/packages/test-support/session-snapshot/tests/identity.spec.ts +++ b/packages/test-support/session-snapshot/tests/identity.spec.ts @@ -10,6 +10,26 @@ const otherId = '66666666-6666-4666-8666-666666666666' const proseUuid = '77777777-7777-4777-8777-777777777777' describe('session snapshot identity redaction', () => { + it('preserves workflow child ordinals and explicit names while redacting generated run identities', () => { + const source = [ + { type: 'session', id: parentId }, + { type: 'subagent/named', data: { id: childId, name: `workflow-${runId}-1` } }, + { type: 'subagent/named', data: { id: otherId, name: `workflow-${runId}-2` } }, + { type: 'subagent/named', data: { name: 'researcher' } }, + { type: 'subagent/named', data: { name: `researcher-${proseUuid}` } }, + { type: 'example', data: { name: `workflow-${proseUuid}-1` } }, + { type: 'subagent/named', data: {} }, + { type: 'subagent/named' }, + ].map(record => JSON.stringify(record)).join('\n') + const [output] = redactSessionSnapshotIds([source]) + expect(output).toContain('"name":"workflow-{{workflow:1}}-1"') + expect(output).toContain('"name":"workflow-{{workflow:1}}-2"') + expect(output).toContain('"name":"researcher"') + expect(output).toContain(`"name":"researcher-${proseUuid}"`) + expect(output).toContain(`"name":"workflow-${proseUuid}-1"`) + expect(redactSessionSnapshotIds([output!])).toEqual([output]) + }) + it('preserves feedback versions and target relationships without redacting unrelated prose', () => { const source = [ { type: 'session', id: parentId }, diff --git a/packages/workflow/workflow-ptc/src/host.ts b/packages/workflow/workflow-ptc/src/host.ts index 7a2266e778..3ebe68f0f0 100644 --- a/packages/workflow/workflow-ptc/src/host.ts +++ b/packages/workflow/workflow-ptc/src/host.ts @@ -202,6 +202,7 @@ export class PtcWorkflowRun implements WorkflowRun { const callId = ++this.started const run = await this.subagents.startActivation({ provider: this.provider, + name: `workflow-${this.id}-${callId}`, label: `${this.meta.name} child ${callId}`, delivery: 'caller', signal: this.controller.signal, diff --git a/packages/workflow/workflow-ptc/tests/host.spec.ts b/packages/workflow/workflow-ptc/tests/host.spec.ts index 4a866175a5..e391e92b7e 100644 --- a/packages/workflow/workflow-ptc/tests/host.spec.ts +++ b/packages/workflow/workflow-ptc/tests/host.spec.ts @@ -197,6 +197,7 @@ describe('workflow runtime outcomes', () => { }) const activation = vi.spyOn(ctx.subagents, 'startActivation').mockResolvedValue({ childId: SessionId('ready-child'), + name: 'workflow-child', result: Promise.resolve({ output: [], structured: { answer: 42 }, stopReason: 'completed' }), dispose: () => { disposing.resolve(undefined); return released.promise }, }) @@ -212,7 +213,7 @@ describe('workflow runtime outcomes', () => { const { parent: delegatedParent, ...request } = delegation.request expect(delegatedParent).toBe(parent) expect({ ...delegation, request }).toEqual({ - provider: 'stub', label: 'host-test child 1', delivery: 'caller', + provider: 'stub', name: `workflow-${run.id}-1`, label: 'host-test child 1', delivery: 'caller', request: { cwd: ctx.workingDirectory.get(parent.session), prompt: [{ type: 'text', text: 'answer' }], outputSchema: schema, agentOptions: { model: 'selected' }, @@ -278,6 +279,7 @@ describe('workflow runtime outcomes', () => { }) const child: SubagentActivation = { childId: SessionId('late-child'), + name: 'workflow-child', result: Promise.resolve({ output: [], stopReason: 'aborted' }), dispose: disposed, } @@ -305,7 +307,7 @@ describe('workflow runtime outcomes', () => { return completed }) vi.spyOn(ctx.subagents, 'startActivation').mockResolvedValue({ - childId: SessionId('output-pending'), result: childResult.promise, dispose: disposed, + childId: SessionId('output-pending'), name: 'workflow-child', result: childResult.promise, dispose: disposed, }) const handle = start() let settled = false diff --git a/packages/workflow/workflow-ptc/tests/workflow-ptc.spec.ts b/packages/workflow/workflow-ptc/tests/workflow-ptc.spec.ts index 29ae47d05f..78afba2045 100644 --- a/packages/workflow/workflow-ptc/tests/workflow-ptc.spec.ts +++ b/packages/workflow/workflow-ptc/tests/workflow-ptc.spec.ts @@ -514,6 +514,7 @@ describe('dsh-workflow-ptc', { timeout: 120_000 }, () => { } as unknown as SubagentResult const start = vi.spyOn(ctx.subagents, 'startActivation').mockResolvedValue({ childId: SessionId('raw-invalid-child'), + name: 'workflow-child', result: Promise.resolve(invalid), dispose: () => Promise.resolve(), }) diff --git a/scripts/doc-typecheck-paths.spec.ts b/scripts/doc-typecheck-paths.spec.ts index a4e8839556..dcde59c294 100644 --- a/scripts/doc-typecheck-paths.spec.ts +++ b/scripts/doc-typecheck-paths.spec.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from 'vitest' -import { builtDeclarationPath } from './doc-typecheck-paths.ts' +import { builtDeclarationPath, usesCurrentDocumentApi } from './doc-typecheck-paths.ts' describe('builtDeclarationPath', () => { it('maps package source directories and exact entry files to built declarations', () => { @@ -17,3 +17,11 @@ describe('builtDeclarationPath', () => { .toThrow('cannot map workspace source path') }) }) + +it('checks current guides and ordinary docs but preserves frozen release examples', () => { + expect(usesCurrentDocumentApi('docs/upgrade-guide/v0.2.1-alpha.4/subagents/guide.md', '0.2.1-alpha.4')).toBe(true) + expect(usesCurrentDocumentApi('docs/upgrade-guide/v0.2.1-alpha.1/subagents/guide.md', '0.2.1-alpha.4')).toBe(false) + expect(usesCurrentDocumentApi('docs/upgrade-guide/v0.2.1-alpha.4/subagents/guide.zh.md', '0.2.1-alpha.4')).toBe(true) + expect(usesCurrentDocumentApi('packages/subagent/subagent/README.md', '0.2.1-alpha.4')).toBe(true) + expect(usesCurrentDocumentApi('docs\\upgrade-guide\\v0.2.0\\subagents\\guide.md', '0.2.1-alpha.4')).toBe(false) +}) diff --git a/scripts/doc-typecheck-paths.ts b/scripts/doc-typecheck-paths.ts index ee09d7a27a..b3f4af0529 100644 --- a/scripts/doc-typecheck-paths.ts +++ b/scripts/doc-typecheck-paths.ts @@ -22,3 +22,14 @@ export function builtDeclarationPath(candidate: string): string { } throw new Error(`doc-typecheck: cannot map workspace source path to built declarations: ${candidate}`) } + +/** + * Exclude frozen release guides from checks against the current API. + * @param path - repository-relative Markdown path, with either separator. + * @param currentVersion - root package version whose upgrade guides remain editable. + * @returns whether current workspace declarations apply to this document. + */ +export function usesCurrentDocumentApi(path: string, currentVersion: string): boolean { + const guide = /^docs\/upgrade-guide\/v([^/]+)\//.exec(path.replaceAll('\\', '/')) + return guide === null || guide[1] === currentVersion +} diff --git a/scripts/doc-typecheck.ts b/scripts/doc-typecheck.ts index 87de14ea6f..3ff9b4e5f1 100644 --- a/scripts/doc-typecheck.ts +++ b/scripts/doc-typecheck.ts @@ -9,7 +9,7 @@ import { execFileSync } from 'node:child_process' import { globSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs' import { join, relative, resolve } from 'node:path' import ts from 'typescript' -import { builtDeclarationPath } from './doc-typecheck-paths.ts' +import { builtDeclarationPath, usesCurrentDocumentApi } from './doc-typecheck-paths.ts' import { markdownFences } from './markdown.ts' import { partitionPairedMarkdownDerivatives } from './paired-markdown-derivatives.ts' import { isArchivedAgentNotePath } from './repo-files.ts' @@ -204,10 +204,11 @@ function remapBlockPaths(output: string, blocks: Block[]): string { const markdownGlobs = ['README.md', '.agents/notes/**/*.md', 'docs/**/*.md', 'packages/*/*.md', 'packages/*/*/*.md'] +const { version: currentVersion } = JSON.parse(readFileSync(join(root, 'package.json'), 'utf8')) as { version: string } const files: string[] = [] for (const pattern of markdownGlobs) { for (const match of globSync(pattern, { cwd: root })) { - if (!isArchivedAgentNotePath(match)) files.push(resolve(root, match)) + if (!isArchivedAgentNotePath(match) && usesCurrentDocumentApi(match, currentVersion)) files.push(resolve(root, match)) } } files.sort() diff --git a/scripts/gen-tool-catalog.ts b/scripts/gen-tool-catalog.ts index 1cb123feee..81d192b0d9 100644 --- a/scripts/gen-tool-catalog.ts +++ b/scripts/gen-tool-catalog.ts @@ -536,7 +536,7 @@ const TOOL_PACKAGES: ToolPackage[] = [ registerListSubagentModels(ctx, { routes: [{ provider: 'mock', model: 'mock' }] }) }, note: - 'The registered delegation name is the load-time `toolName` config (default `subagent`); the default schema above has model selection off, while the discovery schema is shown as the fixed companion available in an enabled Session. Web presets sample the Plugins preference for each new top-level Session and preserve that decision for its child Sessions; `subagent_fork` remains fixed-route. Each instance selects its backend through `provider` and reads model-selection settings through `modelSelectionSettings`. Every delegation returns a child id promptly; local children accept follow-ups, while external backends report their single execution automatically.', + 'The registered delegation name is the load-time `toolName` config (default `subagent`); the default schema above has model selection off, while the discovery schema is shown as the fixed companion available in an enabled Session. Web presets sample the Plugins preference for each new top-level Session and preserve that decision for its child Sessions; `subagent_fork` remains fixed-route. Each instance selects its backend through `provider` and reads model-selection settings through `modelSelectionSettings`. Every delegation returns a unique agent name promptly; local children accept follow-ups, while external backends report their single execution automatically.', }, { pkg: '@deepseek-ai/dsh-tool-subagent-control', @@ -576,11 +576,12 @@ const TOOL_PACKAGES: ToolPackage[] = [ pkg: '@deepseek-ai/dsh-experimental-tool-agent-team', dir: 'tool-agent-team', source: 'packages/experimental/tool-agent-team/src/index.ts', - requires: ['ctx.tools', 'ctx.systemPrompt', 'ctx.agentTeams', 'an exact live Team member Agent'], + requires: ['ctx.tools', 'ctx.systemPrompt', 'ctx.agentTeams', 'ctx.subagents', 'an exact live Team member Agent'], writes: ['tool/call', 'team/task', 'tool/result'], async mount(ctx) { await ctx.plugin(AgentRegistry) await ctx.plugin(SessionStore) + await ctx.plugin(SubagentRuntime) const session = ctx.sessions.create(SessionId('tool-catalog-team-lead')) let agent!: Agent const membership = { diff --git a/scripts/python-snapshot-workflow-order.spec.ts b/scripts/python-snapshot-workflow-order.spec.ts index b82796cb52..ef15df81b8 100644 --- a/scripts/python-snapshot-workflow-order.spec.ts +++ b/scripts/python-snapshot-workflow-order.spec.ts @@ -76,7 +76,7 @@ describe('advanced Python snapshot workflow ordering', () => { await assembly ctx.llm.registerAdapter(['mock'], adapter) const parent = await ctx.agentLoop.create(SessionId(config.parentSessionId), { provider: 'mock', model: 'mock' }) - const run = await ctx.subagents.startActivation({ + const run = await ctx.subagents.startActivation({ name: 'workflow-child', provider: 'spawn', label: 'workflow-child', delivery: 'caller', request: { parent, prompt: [{ type: 'text', text: config.prompt }] }, signal: new AbortController().signal, }) diff --git a/scripts/smoke-python-runtime.py b/scripts/smoke-python-runtime.py index 73c9bba3b3..020c17a546 100644 --- a/scripts/smoke-python-runtime.py +++ b/scripts/smoke-python-runtime.py @@ -661,6 +661,7 @@ def advanced_tool_followup( "advanced-direct-child", "subagent", { + "name": "direct-child", "description": "Check direct child", "prompt": SNAPSHOT_DIRECT_CHILD_PROMPT, }, diff --git a/scripts/snapshots/python-sdk-single-exe/advanced/result.json b/scripts/snapshots/python-sdk-single-exe/advanced/result.json index 33e0c033e8..9ebac48d0e 100644 --- a/scripts/snapshots/python-sdk-single-exe/advanced/result.json +++ b/scripts/snapshots/python-sdk-single-exe/advanced/result.json @@ -763,7 +763,7 @@ "type": "tool-call", "id": "advanced-direct-child", "name": "subagent", - "arguments": "{\"description\": \"Check direct child\", \"prompt\": \"Reply with exactly DIRECT_CHILD_OK and nothing else.\"}" + "arguments": "{\"name\": \"direct-child\", \"description\": \"Check direct child\", \"prompt\": \"Reply with exactly DIRECT_CHILD_OK and nothing else.\"}" } ], "source": { @@ -818,7 +818,7 @@ "dt": [], "id": "advanced-direct-child", "args": [ - "{\"description\": \"Check direct child\", \"prompt\": \"Reply with exactly DIRECT_CHILD_OK and nothing else.\"}" + "{\"name\": \"direct-child\", \"description\": \"Check direct child\", \"prompt\": \"Reply with exactly DIRECT_CHILD_OK and nothing else.\"}" ] }, { @@ -831,7 +831,7 @@ "type": "tool-call", "id": "advanced-direct-child", "name": "subagent", - "arguments": "{\"description\": \"Check direct child\", \"prompt\": \"Reply with exactly DIRECT_CHILD_OK and nothing else.\"}" + "arguments": "{\"name\": \"direct-child\", \"description\": \"Check direct child\", \"prompt\": \"Reply with exactly DIRECT_CHILD_OK and nothing else.\"}" } } }, @@ -882,7 +882,7 @@ "step": 3, "callId": "advanced-direct-child", "name": "subagent", - "arguments": "{\"description\": \"Check direct child\", \"prompt\": \"Reply with exactly DIRECT_CHILD_OK and nothing else.\"}" + "arguments": "{\"name\": \"direct-child\", \"description\": \"Check direct child\", \"prompt\": \"Reply with exactly DIRECT_CHILD_OK and nothing else.\"}" } }, { @@ -898,9 +898,18 @@ } }, { - "type": "tool/result", + "type": "subagent/named", "seq": 38, "time": 0, + "data": { + "name": "direct-child", + "id": "{{child-1}}" + } + }, + { + "type": "tool/result", + "seq": 39, + "time": 0, "data": { "turn": 1, "step": 3, @@ -914,7 +923,7 @@ "content": [ { "type": "text", - "text": "started subagent {{child-1}}" + "text": "started subagent direct-child" } ], "isError": false, @@ -928,7 +937,7 @@ }, { "type": "step/end", - "seq": 39, + "seq": 40, "time": 0, "data": { "turn": 1, @@ -937,7 +946,7 @@ }, { "type": "step/start", - "seq": 40, + "seq": 41, "time": 0, "data": { "turn": 1, @@ -946,17 +955,17 @@ }, { "type": "session-log-deepseek/delivery-accepted", - "seq": 41, + "seq": 42, "time": 0, "data": { "sessionId": "{{parent}}", "sessionFormatVersion": 4, - "throughSeq": 40 + "throughSeq": 41 } }, { "type": "agent/inbox/spliced", - "seq": 42, + "seq": 43, "time": 0, "data": { "target": "next-step", @@ -966,7 +975,7 @@ "content": [ { "type": "text", - "text": "Background subagent {{child-1}} finished and will do no further work unless you send it more." + "text": "Background subagent direct-child finished and will do no further work unless you send it more." }, { "type": "text", @@ -980,7 +989,7 @@ "source": { "kind": "subagent-settled", "form": "notice", - "summary": "Background subagent {{child-1}} finished and will do no further work unless you send it more.", + "summary": "Background subagent direct-child finished and will do no further work unless you send it more.", "senderSessionId": "{{child-1}}" }, "role": "user", @@ -991,7 +1000,7 @@ }, { "type": "assistant/message", - "seq": 43, + "seq": 44, "time": 0, "data": { "turn": 1, @@ -1115,7 +1124,7 @@ }, { "type": "tool/call", - "seq": 44, + "seq": 45, "time": 0, "data": { "turn": 1, @@ -1127,7 +1136,7 @@ }, { "type": "tool-workflow/run-start", - "seq": 45, + "seq": 46, "time": 0, "data": { "runId": "{{workflow-run}}", @@ -1136,7 +1145,7 @@ }, { "type": "subagent/catalog", - "seq": 46, + "seq": 47, "time": 0, "data": { "version": 0, @@ -1146,9 +1155,18 @@ "label": "advanced-exe-snapshot child 1" } }, + { + "type": "subagent/named", + "seq": 48, + "time": 0, + "data": { + "name": "workflow-{{workflow-run}}-1", + "id": "{{child-2}}" + } + }, { "type": "tool-workflow/agent-start", - "seq": 47, + "seq": 49, "time": 0, "data": { "runId": "{{workflow-run}}", @@ -1160,7 +1178,7 @@ }, { "type": "tool-workflow/agent-end", - "seq": 48, + "seq": 50, "time": 0, "data": { "runId": "{{workflow-run}}", @@ -1170,7 +1188,7 @@ }, { "type": "tool-workflow/run-end", - "seq": 49, + "seq": 51, "time": 0, "data": { "runId": "{{workflow-run}}", @@ -1179,7 +1197,7 @@ }, { "type": "tool/result", - "seq": 50, + "seq": 52, "time": 0, "data": { "turn": 1, @@ -1202,13 +1220,13 @@ } }, "sourceEventSeqs": [ - 44 + 45 ], "surfaceOp": "append" }, { "type": "step/end", - "seq": 51, + "seq": 53, "time": 0, "data": { "turn": 1, @@ -1217,7 +1235,7 @@ }, { "type": "agent/inbox/spliced", - "seq": 52, + "seq": 54, "time": 0, "data": { "target": "next-step", @@ -1228,7 +1246,7 @@ }, { "type": "step/start", - "seq": 53, + "seq": 55, "time": 0, "data": { "turn": 1, @@ -1237,13 +1255,13 @@ }, { "type": "user/message", - "seq": 54, + "seq": 56, "time": 0, "data": { "content": [ { "type": "text", - "text": "Background subagent {{child-1}} finished and will do no further work unless you send it more." + "text": "Background subagent direct-child finished and will do no further work unless you send it more." }, { "type": "text", @@ -1257,7 +1275,7 @@ "source": { "kind": "subagent-settled", "form": "notice", - "summary": "Background subagent {{child-1}} finished and will do no further work unless you send it more.", + "summary": "Background subagent direct-child finished and will do no further work unless you send it more.", "senderSessionId": "{{child-1}}" }, "role": "user", @@ -1267,17 +1285,17 @@ }, { "type": "session-log-deepseek/delivery-accepted", - "seq": 55, + "seq": 57, "time": 0, "data": { "sessionId": "{{parent}}", "sessionFormatVersion": 4, - "throughSeq": 54 + "throughSeq": 56 } }, { "type": "assistant/message", - "seq": 56, + "seq": 58, "time": 0, "data": { "turn": 1, @@ -1385,7 +1403,7 @@ }, { "type": "step/end", - "seq": 57, + "seq": 59, "time": 0, "data": { "turn": 1, @@ -1394,7 +1412,7 @@ }, { "type": "command/run", - "seq": 58, + "seq": 60, "time": 0, "data": { "commandId": "{{command:1}}", @@ -1406,7 +1424,7 @@ }, { "type": "feedback/record", - "seq": 59, + "seq": 61, "time": 0, "data": { "text": "The session needs a clearer explanation." @@ -1414,7 +1432,7 @@ }, { "type": "command/done", - "seq": 60, + "seq": 62, "time": 0, "data": { "commandId": "{{command:1}}", @@ -1424,7 +1442,7 @@ }, { "type": "feedback/record", - "seq": 61, + "seq": 63, "time": 0, "data": { "category": "other" @@ -1432,7 +1450,7 @@ }, { "type": "feedback/message-put", - "seq": 62, + "seq": 64, "time": 0, "data": { "sessionId": "{{parent}}", @@ -1449,7 +1467,7 @@ }, { "type": "feedback/message-put", - "seq": 63, + "seq": 65, "time": 0, "data": { "sessionId": "{{parent}}", @@ -1465,7 +1483,7 @@ }, { "type": "feedback/message-delete", - "seq": 64, + "seq": 66, "time": 0, "data": { "sessionId": "{{parent}}", @@ -1474,7 +1492,7 @@ }, { "type": "turn/end", - "seq": 65, + "seq": 67, "time": 0, "data": { "turn": 1, @@ -2443,7 +2461,7 @@ "type": "tool-call", "id": "advanced-direct-child", "name": "subagent", - "arguments": "{\"description\": \"Check direct child\", \"prompt\": \"Reply with exactly DIRECT_CHILD_OK and nothing else.\"}" + "arguments": "{\"name\": \"direct-child\", \"description\": \"Check direct child\", \"prompt\": \"Reply with exactly DIRECT_CHILD_OK and nothing else.\"}" } ], "source": { @@ -2498,7 +2516,7 @@ "dt": [], "id": "advanced-direct-child", "args": [ - "{\"description\": \"Check direct child\", \"prompt\": \"Reply with exactly DIRECT_CHILD_OK and nothing else.\"}" + "{\"name\": \"direct-child\", \"description\": \"Check direct child\", \"prompt\": \"Reply with exactly DIRECT_CHILD_OK and nothing else.\"}" ] }, { @@ -2511,7 +2529,7 @@ "type": "tool-call", "id": "advanced-direct-child", "name": "subagent", - "arguments": "{\"description\": \"Check direct child\", \"prompt\": \"Reply with exactly DIRECT_CHILD_OK and nothing else.\"}" + "arguments": "{\"name\": \"direct-child\", \"description\": \"Check direct child\", \"prompt\": \"Reply with exactly DIRECT_CHILD_OK and nothing else.\"}" } } }, @@ -2568,7 +2586,7 @@ "step": 3, "callId": "advanced-direct-child", "name": "subagent", - "arguments": "{\"description\": \"Check direct child\", \"prompt\": \"Reply with exactly DIRECT_CHILD_OK and nothing else.\"}" + "arguments": "{\"name\": \"direct-child\", \"description\": \"Check direct child\", \"prompt\": \"Reply with exactly DIRECT_CHILD_OK and nothing else.\"}" } } } @@ -2718,9 +2736,24 @@ "payload": { "sessionId": "{{parent}}", "event": { - "type": "tool/result", + "type": "subagent/named", "seq": 38, "time": 0, + "data": { + "name": "direct-child", + "id": "{{child-1}}" + } + } + } + }, + { + "method": "session.event", + "payload": { + "sessionId": "{{parent}}", + "event": { + "type": "tool/result", + "seq": 39, + "time": 0, "data": { "turn": 1, "step": 3, @@ -2734,7 +2767,7 @@ "content": [ { "type": "text", - "text": "started subagent {{child-1}}" + "text": "started subagent direct-child" } ], "isError": false, @@ -2754,7 +2787,7 @@ "sessionId": "{{parent}}", "event": { "type": "step/end", - "seq": 39, + "seq": 40, "time": 0, "data": { "turn": 1, @@ -2769,7 +2802,7 @@ "sessionId": "{{parent}}", "event": { "type": "step/start", - "seq": 40, + "seq": 41, "time": 0, "data": { "turn": 1, @@ -2784,12 +2817,12 @@ "sessionId": "{{parent}}", "event": { "type": "session-log-deepseek/delivery-accepted", - "seq": 41, + "seq": 42, "time": 0, "data": { "sessionId": "{{parent}}", "sessionFormatVersion": 4, - "throughSeq": 40 + "throughSeq": 41 } } } @@ -3183,7 +3216,7 @@ "sessionId": "{{parent}}", "event": { "type": "agent/inbox/spliced", - "seq": 42, + "seq": 43, "time": 0, "data": { "target": "next-step", @@ -3193,7 +3226,7 @@ "content": [ { "type": "text", - "text": "Background subagent {{child-1}} finished and will do no further work unless you send it more." + "text": "Background subagent direct-child finished and will do no further work unless you send it more." }, { "type": "text", @@ -3207,7 +3240,7 @@ "source": { "kind": "subagent-settled", "form": "notice", - "summary": "Background subagent {{child-1}} finished and will do no further work unless you send it more.", + "summary": "Background subagent direct-child finished and will do no further work unless you send it more.", "senderSessionId": "{{child-1}}" }, "role": "user", @@ -3241,7 +3274,7 @@ "sessionId": "{{parent}}", "event": { "type": "assistant/message", - "seq": 43, + "seq": 44, "time": 0, "data": { "turn": 1, @@ -3371,7 +3404,7 @@ "sessionId": "{{parent}}", "event": { "type": "tool/call", - "seq": 44, + "seq": 45, "time": 0, "data": { "turn": 1, @@ -3389,7 +3422,7 @@ "sessionId": "{{parent}}", "event": { "type": "tool-workflow/run-start", - "seq": 45, + "seq": 46, "time": 0, "data": { "runId": "{{workflow-run}}", @@ -3526,7 +3559,7 @@ "sessionId": "{{parent}}", "event": { "type": "subagent/catalog", - "seq": 46, + "seq": 47, "time": 0, "data": { "version": 0, @@ -3538,13 +3571,28 @@ } } }, + { + "method": "session.event", + "payload": { + "sessionId": "{{parent}}", + "event": { + "type": "subagent/named", + "seq": 48, + "time": 0, + "data": { + "name": "workflow-{{workflow-run}}-1", + "id": "{{child-2}}" + } + } + } + }, { "method": "session.event", "payload": { "sessionId": "{{parent}}", "event": { "type": "tool-workflow/agent-start", - "seq": 47, + "seq": 49, "time": 0, "data": { "runId": "{{workflow-run}}", @@ -3962,7 +4010,7 @@ "sessionId": "{{parent}}", "event": { "type": "tool-workflow/agent-end", - "seq": 48, + "seq": 50, "time": 0, "data": { "runId": "{{workflow-run}}", @@ -3978,7 +4026,7 @@ "sessionId": "{{parent}}", "event": { "type": "tool-workflow/run-end", - "seq": 49, + "seq": 51, "time": 0, "data": { "runId": "{{workflow-run}}", @@ -3993,7 +4041,7 @@ "sessionId": "{{parent}}", "event": { "type": "tool/result", - "seq": 50, + "seq": 52, "time": 0, "data": { "turn": 1, @@ -4016,7 +4064,7 @@ } }, "sourceEventSeqs": [ - 44 + 45 ], "surfaceOp": "append" } @@ -4028,7 +4076,7 @@ "sessionId": "{{parent}}", "event": { "type": "step/end", - "seq": 51, + "seq": 53, "time": 0, "data": { "turn": 1, @@ -4043,7 +4091,7 @@ "sessionId": "{{parent}}", "event": { "type": "agent/inbox/spliced", - "seq": 52, + "seq": 54, "time": 0, "data": { "target": "next-step", @@ -4060,7 +4108,7 @@ "sessionId": "{{parent}}", "event": { "type": "step/start", - "seq": 53, + "seq": 55, "time": 0, "data": { "turn": 1, @@ -4075,13 +4123,13 @@ "sessionId": "{{parent}}", "event": { "type": "user/message", - "seq": 54, + "seq": 56, "time": 0, "data": { "content": [ { "type": "text", - "text": "Background subagent {{child-1}} finished and will do no further work unless you send it more." + "text": "Background subagent direct-child finished and will do no further work unless you send it more." }, { "type": "text", @@ -4095,7 +4143,7 @@ "source": { "kind": "subagent-settled", "form": "notice", - "summary": "Background subagent {{child-1}} finished and will do no further work unless you send it more.", + "summary": "Background subagent direct-child finished and will do no further work unless you send it more.", "senderSessionId": "{{child-1}}" }, "role": "user", @@ -4111,12 +4159,12 @@ "sessionId": "{{parent}}", "event": { "type": "session-log-deepseek/delivery-accepted", - "seq": 55, + "seq": 57, "time": 0, "data": { "sessionId": "{{parent}}", "sessionFormatVersion": 4, - "throughSeq": 54 + "throughSeq": 56 } } } @@ -4127,7 +4175,7 @@ "sessionId": "{{parent}}", "event": { "type": "assistant/message", - "seq": 56, + "seq": 58, "time": 0, "data": { "turn": 1, @@ -4241,7 +4289,7 @@ "sessionId": "{{parent}}", "event": { "type": "step/end", - "seq": 57, + "seq": 59, "time": 0, "data": { "turn": 1, @@ -4256,7 +4304,7 @@ "sessionId": "{{parent}}", "event": { "type": "command/run", - "seq": 58, + "seq": 60, "time": 0, "data": { "commandId": "{{command:1}}", @@ -4274,7 +4322,7 @@ "sessionId": "{{parent}}", "event": { "type": "feedback/record", - "seq": 59, + "seq": 61, "time": 0, "data": { "text": "The session needs a clearer explanation." @@ -4288,7 +4336,7 @@ "sessionId": "{{parent}}", "event": { "type": "command/done", - "seq": 60, + "seq": 62, "time": 0, "data": { "commandId": "{{command:1}}", @@ -4304,7 +4352,7 @@ "sessionId": "{{parent}}", "event": { "type": "feedback/record", - "seq": 61, + "seq": 63, "time": 0, "data": { "category": "other" @@ -4318,7 +4366,7 @@ "sessionId": "{{parent}}", "event": { "type": "feedback/message-put", - "seq": 62, + "seq": 64, "time": 0, "data": { "sessionId": "{{parent}}", @@ -4341,7 +4389,7 @@ "sessionId": "{{parent}}", "event": { "type": "feedback/message-put", - "seq": 63, + "seq": 65, "time": 0, "data": { "sessionId": "{{parent}}", @@ -4363,7 +4411,7 @@ "sessionId": "{{parent}}", "event": { "type": "feedback/message-delete", - "seq": 64, + "seq": 66, "time": 0, "data": { "sessionId": "{{parent}}", @@ -4378,7 +4426,7 @@ "sessionId": "{{parent}}", "event": { "type": "turn/end", - "seq": 65, + "seq": 67, "time": 0, "data": { "turn": 1, diff --git a/scripts/snapshots/python-sdk-single-exe/advanced/session.v4.jsonl b/scripts/snapshots/python-sdk-single-exe/advanced/session.v4.jsonl index dcd09c277c..8fec165e5b 100644 --- a/scripts/snapshots/python-sdk-single-exe/advanced/session.v4.jsonl +++ b/scripts/snapshots/python-sdk-single-exe/advanced/session.v4.jsonl @@ -34,27 +34,29 @@ {"type":"step/end","data":{"turn":1,"step":2}} {"type":"step/start","data":{"turn":1,"step":3}} {"type":"session-log-deepseek/delivery-accepted","data":{"sessionId":"{{parent}}","sessionFormatVersion":4,"throughSeq":33}} -{"type":"assistant/message","data":{"turn":1,"step":3,"message":{"role":"assistant","content":[{"type":"tool-call","id":"advanced-direct-child","name":"subagent","arguments":"{\"description\": \"Check direct child\", \"prompt\": \"Reply with exactly DIRECT_CHILD_OK and nothing else.\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"smoke-model","replayState":{"response":{"kind":"deepseek-messages","version":1,"model":"smoke-model"},"blocks":[{"type":"tool-call"}]}},"id":"{{messageId}}"},"usage":{"inputTokens":3,"outputTokens":3,"totalTokens":6},"stream":[{"type":"chunk","time":0,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":0,"index":0,"dt":[],"id":"advanced-direct-child","name":"subagent","args":[""]},{"type":"tool-call-chunks","time0":0,"index":0,"dt":[],"id":"advanced-direct-child","args":["{\"description\": \"Check direct child\", \"prompt\": \"Reply with exactly DIRECT_CHILD_OK and nothing else.\"}"]},{"type":"chunk","time":0,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"advanced-direct-child","name":"subagent","arguments":"{\"description\": \"Check direct child\", \"prompt\": \"Reply with exactly DIRECT_CHILD_OK and nothing else.\"}"}}},{"type":"chunk","time":0,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3,"totalTokens":6}}},{"type":"chunk","time":0,"chunk":{"type":"finish","reason":{"kind":"tool-calls"},"replayState":{"response":{"kind":"deepseek-messages","version":1,"model":"smoke-model"},"blocks":[{"type":"tool-call"}]}}}]},"surfaceOp":"append"} -{"type":"tool/call","data":{"turn":1,"step":3,"callId":"advanced-direct-child","name":"subagent","arguments":"{\"description\": \"Check direct child\", \"prompt\": \"Reply with exactly DIRECT_CHILD_OK and nothing else.\"}"}} +{"type":"assistant/message","data":{"turn":1,"step":3,"message":{"role":"assistant","content":[{"type":"tool-call","id":"advanced-direct-child","name":"subagent","arguments":"{\"name\": \"direct-child\", \"description\": \"Check direct child\", \"prompt\": \"Reply with exactly DIRECT_CHILD_OK and nothing else.\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"smoke-model","replayState":{"response":{"kind":"deepseek-messages","version":1,"model":"smoke-model"},"blocks":[{"type":"tool-call"}]}},"id":"{{messageId}}"},"usage":{"inputTokens":3,"outputTokens":3,"totalTokens":6},"stream":[{"type":"chunk","time":0,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":0,"index":0,"dt":[],"id":"advanced-direct-child","name":"subagent","args":[""]},{"type":"tool-call-chunks","time0":0,"index":0,"dt":[],"id":"advanced-direct-child","args":["{\"name\": \"direct-child\", \"description\": \"Check direct child\", \"prompt\": \"Reply with exactly DIRECT_CHILD_OK and nothing else.\"}"]},{"type":"chunk","time":0,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"advanced-direct-child","name":"subagent","arguments":"{\"name\": \"direct-child\", \"description\": \"Check direct child\", \"prompt\": \"Reply with exactly DIRECT_CHILD_OK and nothing else.\"}"}}},{"type":"chunk","time":0,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3,"totalTokens":6}}},{"type":"chunk","time":0,"chunk":{"type":"finish","reason":{"kind":"tool-calls"},"replayState":{"response":{"kind":"deepseek-messages","version":1,"model":"smoke-model"},"blocks":[{"type":"tool-call"}]}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":3,"callId":"advanced-direct-child","name":"subagent","arguments":"{\"name\": \"direct-child\", \"description\": \"Check direct child\", \"prompt\": \"Reply with exactly DIRECT_CHILD_OK and nothing else.\"}"}} {"type":"subagent/catalog","data":{"version":0,"childId":"{{child-1}}","childCreatedAt":0,"mode":"continuable","label":"Check direct child"}} -{"type":"tool/result","data":{"turn":1,"step":3,"message":{"role":"tool","source":{"kind":"tool","callId":"advanced-direct-child"},"toolCallId":"advanced-direct-child","content":[{"type":"text","text":"started subagent {{child-1}}"}],"isError":false,"id":"{{messageId}}"}},"sourceEventSeqs":[36],"surfaceOp":"append"} +{"type":"subagent/named","data":{"name":"direct-child","id":"{{child-1}}"}} +{"type":"tool/result","data":{"turn":1,"step":3,"message":{"role":"tool","source":{"kind":"tool","callId":"advanced-direct-child"},"toolCallId":"advanced-direct-child","content":[{"type":"text","text":"started subagent direct-child"}],"isError":false,"id":"{{messageId}}"}},"sourceEventSeqs":[36],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":3}} {"type":"step/start","data":{"turn":1,"step":4}} -{"type":"session-log-deepseek/delivery-accepted","data":{"sessionId":"{{parent}}","sessionFormatVersion":4,"throughSeq":40}} -{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent {{child-1}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"DIRECT_CHILD_OK"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{child-1}} finished and will do no further work unless you send it more.","senderSessionId":"{{child-1}}"},"role":"user","id":"{{messageId}}"}]}} +{"type":"session-log-deepseek/delivery-accepted","data":{"sessionId":"{{parent}}","sessionFormatVersion":4,"throughSeq":41}} +{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent direct-child finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"DIRECT_CHILD_OK"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent direct-child finished and will do no further work unless you send it more.","senderSessionId":"{{child-1}}"},"role":"user","id":"{{messageId}}"}]}} {"type":"assistant/message","data":{"turn":1,"step":4,"message":{"role":"assistant","content":[{"type":"tool-call","id":"advanced-workflow","name":"workflow","arguments":"{\"script\": \"phase('Delegate')\\nconst reply = await agent('Reply with exactly WORKFLOW_CHILD_OK and nothing else.', { label: 'workflow-child' })\\nreturn { reply }\", \"meta\": {\"name\": \"advanced-exe-snapshot\", \"description\": \"exercise one packaged workflow child\"}}"}],"source":{"kind":"model","provider":"deepseek-official","model":"smoke-model","replayState":{"response":{"kind":"deepseek-messages","version":1,"model":"smoke-model"},"blocks":[{"type":"tool-call"}]}},"id":"{{messageId}}"},"usage":{"inputTokens":3,"outputTokens":3,"totalTokens":6},"stream":[{"type":"chunk","time":0,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":0,"index":0,"dt":[],"id":"advanced-workflow","name":"workflow","args":[""]},{"type":"tool-call-chunks","time0":0,"index":0,"dt":[],"id":"advanced-workflow","args":["{\"script\": \"phase('Delegate')\\nconst reply = await agent('Reply with exactly WORKFLOW_CHILD_OK and nothing else.', { label: 'workflow-child' })\\nreturn { reply }\", \"meta\": {\"name\": \"advanced-exe-snapshot\", \"description\": \"exercise one packaged workflow child\"}}"]},{"type":"chunk","time":0,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"advanced-workflow","name":"workflow","arguments":"{\"script\": \"phase('Delegate')\\nconst reply = await agent('Reply with exactly WORKFLOW_CHILD_OK and nothing else.', { label: 'workflow-child' })\\nreturn { reply }\", \"meta\": {\"name\": \"advanced-exe-snapshot\", \"description\": \"exercise one packaged workflow child\"}}"}}},{"type":"chunk","time":0,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3,"totalTokens":6}}},{"type":"chunk","time":0,"chunk":{"type":"finish","reason":{"kind":"tool-calls"},"replayState":{"response":{"kind":"deepseek-messages","version":1,"model":"smoke-model"},"blocks":[{"type":"tool-call"}]}}}]},"surfaceOp":"append"} {"type":"tool/call","data":{"turn":1,"step":4,"callId":"advanced-workflow","name":"workflow","arguments":"{\"script\": \"phase('Delegate')\\nconst reply = await agent('Reply with exactly WORKFLOW_CHILD_OK and nothing else.', { label: 'workflow-child' })\\nreturn { reply }\", \"meta\": {\"name\": \"advanced-exe-snapshot\", \"description\": \"exercise one packaged workflow child\"}}"}} {"type":"tool-workflow/run-start","data":{"runId":"{{workflow-run}}","name":"advanced-exe-snapshot"}} {"type":"subagent/catalog","data":{"version":0,"childId":"{{child-2}}","childCreatedAt":0,"mode":"continuable","label":"advanced-exe-snapshot child 1"}} +{"type":"subagent/named","data":{"name":"workflow-{{workflow-run}}-1","id":"{{child-2}}"}} {"type":"tool-workflow/agent-start","data":{"runId":"{{workflow-run}}","seq":1,"label":"workflow-child","phase":"Delegate","childId":"{{child-2}}"}} {"type":"tool-workflow/agent-end","data":{"runId":"{{workflow-run}}","seq":1,"outcome":"completed"}} {"type":"tool-workflow/run-end","data":{"runId":"{{workflow-run}}","stopReason":"completed"}} -{"type":"tool/result","data":{"turn":1,"step":4,"message":{"role":"tool","source":{"kind":"tool","callId":"advanced-workflow"},"toolCallId":"advanced-workflow","content":[{"type":"text","text":"workflow \"advanced-exe-snapshot\" completed (1 agent).\nReturn value:\n{\n \"reply\": \"WORKFLOW_CHILD_OK\"\n}"}],"isError":false,"id":"{{messageId}}"}},"sourceEventSeqs":[44],"surfaceOp":"append"} +{"type":"tool/result","data":{"turn":1,"step":4,"message":{"role":"tool","source":{"kind":"tool","callId":"advanced-workflow"},"toolCallId":"advanced-workflow","content":[{"type":"text","text":"workflow \"advanced-exe-snapshot\" completed (1 agent).\nReturn value:\n{\n \"reply\": \"WORKFLOW_CHILD_OK\"\n}"}],"isError":false,"id":"{{messageId}}"}},"sourceEventSeqs":[45],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":4}} {"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":1,"step":5}} -{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent {{child-1}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"DIRECT_CHILD_OK"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{child-1}} finished and will do no further work unless you send it more.","senderSessionId":"{{child-1}}"},"role":"user","id":"{{messageId}}"},"surfaceOp":"append"} -{"type":"session-log-deepseek/delivery-accepted","data":{"sessionId":"{{parent}}","sessionFormatVersion":4,"throughSeq":54}} +{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent direct-child finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"DIRECT_CHILD_OK"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent direct-child finished and will do no further work unless you send it more.","senderSessionId":"{{child-1}}"},"role":"user","id":"{{messageId}}"},"surfaceOp":"append"} +{"type":"session-log-deepseek/delivery-accepted","data":{"sessionId":"{{parent}}","sessionFormatVersion":4,"throughSeq":56}} {"type":"assistant/message","data":{"turn":1,"step":5,"message":{"role":"assistant","content":[{"type":"text","text":"ADVANCED_EXECUTABLE_OK"}],"source":{"kind":"model","provider":"deepseek-official","model":"smoke-model","replayState":{"response":{"kind":"deepseek-messages","version":1,"model":"smoke-model"},"blocks":[{"type":"text"}]}},"id":"{{message:1}}"},"usage":{"inputTokens":3,"outputTokens":3,"totalTokens":6},"stream":[{"type":"chunk","time":0,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":0,"index":0,"dt":[],"texts":["ADVANCED_EXECUTABLE_OK"]},{"type":"chunk","time":0,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"ADVANCED_EXECUTABLE_OK"}}},{"type":"chunk","time":0,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3,"totalTokens":6}}},{"type":"chunk","time":0,"chunk":{"type":"finish","reason":{"kind":"stop"},"replayState":{"response":{"kind":"deepseek-messages","version":1,"model":"smoke-model"},"blocks":[{"type":"text"}]}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":5}} {"type":"command/run","data":{"commandId":"{{command:1}}","name":"feedback","source":{"kind":"user"}}} diff --git a/scripts/type-equiv.manifest.json b/scripts/type-equiv.manifest.json index 637c9d7bf5..e4e54158aa 100644 --- a/scripts/type-equiv.manifest.json +++ b/scripts/type-equiv.manifest.json @@ -2481,6 +2481,16 @@ "doc": "docs/subsystems/boot.md", "symbol": "PendingModule", "source": "packages/boot/hmr/src/index.ts" + }, + { + "doc": "docs/subsystems/subagent.md", + "symbol": "SubagentNameData", + "source": "packages/subagent/subagent/src/names.ts" + }, + { + "doc": "docs/subsystems/subagent.md", + "symbol": "SubagentNamesState", + "source": "packages/subagent/subagent/src/names.ts" } ] } diff --git a/snapshots/sdk/bash-tool/tool-schemas.expected.json b/snapshots/sdk/bash-tool/tool-schemas.expected.json index b546a748a7..99b37246de 100644 --- a/snapshots/sdk/bash-tool/tool-schemas.expected.json +++ b/snapshots/sdk/bash-tool/tool-schemas.expected.json @@ -181,13 +181,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -245,7 +245,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -297,9 +297,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -307,7 +307,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -330,10 +330,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -348,6 +352,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -355,10 +360,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -373,6 +382,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/sdk/subagent-activation-limit/replay.override.json b/snapshots/sdk/subagent-activation-limit/replay.override.json index 003683b8a1..f31bb1e826 100644 --- a/snapshots/sdk/subagent-activation-limit/replay.override.json +++ b/snapshots/sdk/subagent-activation-limit/replay.override.json @@ -12,7 +12,7 @@ "index": 0, "id": "call_first", "name": "subagent", - "argumentsDelta": "{\"description\":\"Reply CHILD_OK\",\"prompt\":\"Reply with exactly CHILD_OK.\"}" + "argumentsDelta": "{\"description\":\"Reply CHILD_OK\",\"prompt\":\"Reply with exactly CHILD_OK.\",\"name\":\"worker-1\"}" }, { "type": "block-end", @@ -21,7 +21,7 @@ "type": "tool-call", "id": "call_first", "name": "subagent", - "arguments": "{\"description\":\"Reply CHILD_OK\",\"prompt\":\"Reply with exactly CHILD_OK.\"}" + "arguments": "{\"description\":\"Reply CHILD_OK\",\"prompt\":\"Reply with exactly CHILD_OK.\",\"name\":\"worker-1\"}" } }, { @@ -52,7 +52,7 @@ "index": 0, "id": "call_over_capacity", "name": "subagent", - "argumentsDelta": "{\"description\":\"Reply CHILD_OK\",\"prompt\":\"Reply with exactly CHILD_OK.\"}" + "argumentsDelta": "{\"description\":\"Reply CHILD_OK\",\"prompt\":\"Reply with exactly CHILD_OK.\",\"name\":\"worker-2\"}" }, { "type": "block-end", @@ -61,7 +61,7 @@ "type": "tool-call", "id": "call_over_capacity", "name": "subagent", - "arguments": "{\"description\":\"Reply CHILD_OK\",\"prompt\":\"Reply with exactly CHILD_OK.\"}" + "arguments": "{\"description\":\"Reply CHILD_OK\",\"prompt\":\"Reply with exactly CHILD_OK.\",\"name\":\"worker-2\"}" } }, { diff --git a/snapshots/sdk/subagent-activation-limit/session.1.v4.jsonl b/snapshots/sdk/subagent-activation-limit/session.1.v4.jsonl index 7ac8c0e148..ed474fe039 100644 --- a/snapshots/sdk/subagent-activation-limit/session.1.v4.jsonl +++ b/snapshots/sdk/subagent-activation-limit/session.1.v4.jsonl @@ -3,12 +3,12 @@ {"type":"sandbox/mode","data":{"mode":"danger-full-access","source":"delegation"}} {"type":"approval/policy","data":{"policy":"never","source":"delegation"}} {"type":"permission/preset","data":{"preset":"danger-full-access"}} -{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Reply with exactly CHILD_OK."},{"type":"text","text":"Your parent agent id is \"{{session:1}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{session:1}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:11}}"}]}} +{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Reply with exactly CHILD_OK."},{"type":"text","text":"Your name is \"worker-1\". Your parent agent name is \"lead\". Before you finish, send your result to that agent with send_message({ name: \"lead\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:11}}"}]}} {"type":"turn/start","data":{"turn":1}} {"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":1,"step":1}} {"type":"system/message","data":{"turn":1,"step":1,"message":{"role":"system","content":[{"type":"text","text":"{{system}}"}],"source":{"kind":"system-prompt"},"id":"{{message:12}}"}},"surfaceOp":"append"} -{"type":"user/message","data":{"content":[{"type":"text","text":"Reply with exactly CHILD_OK."},{"type":"text","text":"Your parent agent id is \"{{session:1}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{session:1}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:11}}"},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Reply with exactly CHILD_OK."},{"type":"text","text":"Your name is \"worker-1\". Your parent agent name is \"lead\". Before you finish, send your result to that agent with send_message({ name: \"lead\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:11}}"},"surfaceOp":"append"} {"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations.\n\nApproval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).\n\nDelegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly.\n\nDelegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly.\n\nYou are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations."},{"name":"approval:policy","text":"Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."},{"name":"tool:subagent:depth","text":"Delegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly."},{"name":"tool:subagent_fork:depth","text":"Delegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly."},{"name":"subagent:delegation","text":"You are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}]},"role":"user","id":"{{message:13}}"},"surfaceOp":"append"} {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} diff --git a/snapshots/sdk/subagent-activation-limit/session.v4.jsonl b/snapshots/sdk/subagent-activation-limit/session.v4.jsonl index 0d436a6bf9..f0f2ca2640 100644 --- a/snapshots/sdk/subagent-activation-limit/session.v4.jsonl +++ b/snapshots/sdk/subagent-activation-limit/session.v4.jsonl @@ -12,25 +12,26 @@ {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} {"type":"session/title","data":{"title":"Start one background subagent that","messageSeqs":[8],"source":{"kind":"fallback"}}} -{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_first","name":"subagent","arguments":"{\"description\":\"Reply CHILD_OK\",\"prompt\":\"Reply with exactly CHILD_OK.\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1789485621963,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1789485621963,"index":0,"dt":[],"id":"call_first","name":"subagent","args":["{\"description\":\"Reply CHILD_OK\",\"prompt\":\"Reply with exactly CHILD_OK.\"}"]},{"type":"chunk","time":1789485621963,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_first","name":"subagent","arguments":"{\"description\":\"Reply CHILD_OK\",\"prompt\":\"Reply with exactly CHILD_OK.\"}"}}},{"type":"chunk","time":1789485621964,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1789485621964,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} -{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_first","name":"subagent","arguments":"{\"description\":\"Reply CHILD_OK\",\"prompt\":\"Reply with exactly CHILD_OK.\"}"}} +{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_first","name":"subagent","arguments":"{\"description\":\"Reply CHILD_OK\",\"prompt\":\"Reply with exactly CHILD_OK.\",\"name\":\"worker-1\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1792123808225,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792123808225,"index":0,"dt":[],"id":"call_first","name":"subagent","args":["{\"description\":\"Reply CHILD_OK\",\"prompt\":\"Reply with exactly CHILD_OK.\",\"name\":\"worker-1\"}"]},{"type":"chunk","time":1792123808225,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_first","name":"subagent","arguments":"{\"description\":\"Reply CHILD_OK\",\"prompt\":\"Reply with exactly CHILD_OK.\",\"name\":\"worker-1\"}"}}},{"type":"chunk","time":1792123808225,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1792123808225,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_first","name":"subagent","arguments":"{\"description\":\"Reply CHILD_OK\",\"prompt\":\"Reply with exactly CHILD_OK.\",\"name\":\"worker-1\"}"}} {"type":"subagent/catalog","data":{"version":0,"childId":"{{session:2}}","childCreatedAt":1789000001000,"mode":"continuable","label":"Reply CHILD_OK"}} -{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_first"},"toolCallId":"call_first","content":[{"type":"text","text":"started subagent {{session:2}}"}],"isError":false,"id":"{{message:5}}"}},"sourceEventSeqs":[14],"surfaceOp":"append"} +{"type":"subagent/named","data":{"name":"worker-1","id":"{{session:2}}"}} +{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_first"},"toolCallId":"call_first","content":[{"type":"text","text":"started subagent worker-1"}],"isError":false,"id":"{{message:5}}"}},"sourceEventSeqs":[14],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":1}} {"type":"step/start","data":{"turn":1,"step":2}} -{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_over_capacity","name":"subagent","arguments":"{\"description\":\"Reply CHILD_OK\",\"prompt\":\"Reply with exactly CHILD_OK.\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:6}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1789485622009,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1789485622009,"index":0,"dt":[],"id":"call_over_capacity","name":"subagent","args":["{\"description\":\"Reply CHILD_OK\",\"prompt\":\"Reply with exactly CHILD_OK.\"}"]},{"type":"chunk","time":1789485622009,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_over_capacity","name":"subagent","arguments":"{\"description\":\"Reply CHILD_OK\",\"prompt\":\"Reply with exactly CHILD_OK.\"}"}}},{"type":"chunk","time":1789485622009,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1789485622009,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} -{"type":"tool/call","data":{"turn":1,"step":2,"callId":"call_over_capacity","name":"subagent","arguments":"{\"description\":\"Reply CHILD_OK\",\"prompt\":\"Reply with exactly CHILD_OK.\"}"}} -{"type":"tool/result","data":{"turn":1,"step":2,"message":{"role":"tool","source":{"kind":"tool","callId":"call_over_capacity"},"toolCallId":"call_over_capacity","content":[{"type":"text","text":"Error: subagent limit reached (active child limit: 1); wait for an existing child to finish or complete this work with the current agents"}],"isError":true,"id":"{{message:7}}"},"error":{"name":"SubagentError","code":"ACTIVATION_LIMIT_REACHED"}},"sourceEventSeqs":[20],"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_over_capacity","name":"subagent","arguments":"{\"description\":\"Reply CHILD_OK\",\"prompt\":\"Reply with exactly CHILD_OK.\",\"name\":\"worker-2\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:6}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1792123808264,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792123808264,"index":0,"dt":[],"id":"call_over_capacity","name":"subagent","args":["{\"description\":\"Reply CHILD_OK\",\"prompt\":\"Reply with exactly CHILD_OK.\",\"name\":\"worker-2\"}"]},{"type":"chunk","time":1792123808264,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_over_capacity","name":"subagent","arguments":"{\"description\":\"Reply CHILD_OK\",\"prompt\":\"Reply with exactly CHILD_OK.\",\"name\":\"worker-2\"}"}}},{"type":"chunk","time":1792123808264,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1792123808264,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":2,"callId":"call_over_capacity","name":"subagent","arguments":"{\"description\":\"Reply CHILD_OK\",\"prompt\":\"Reply with exactly CHILD_OK.\",\"name\":\"worker-2\"}"}} +{"type":"tool/result","data":{"turn":1,"step":2,"message":{"role":"tool","source":{"kind":"tool","callId":"call_over_capacity"},"toolCallId":"call_over_capacity","content":[{"type":"text","text":"Error: subagent limit reached (active child limit: 1); wait for an existing child to finish or complete this work with the current agents"}],"isError":true,"id":"{{message:7}}"},"error":{"name":"SubagentError","code":"ACTIVATION_LIMIT_REACHED"}},"sourceEventSeqs":[21],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":2}} {"type":"step/start","data":{"turn":1,"step":3}} -{"type":"assistant/message","data":{"turn":1,"step":3,"message":{"role":"assistant","content":[{"type":"text","text":"ROOT_DONE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:8}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1789485622031,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1789485622031,"index":0,"dt":[],"texts":["ROOT_DONE"]},{"type":"chunk","time":1789485622031,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"ROOT_DONE"}}},{"type":"chunk","time":1789485622031,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1789485622031,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":3,"message":{"role":"assistant","content":[{"type":"text","text":"ROOT_DONE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:8}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1792123808279,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1792123808279,"index":0,"dt":[],"texts":["ROOT_DONE"]},{"type":"chunk","time":1792123808279,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"ROOT_DONE"}}},{"type":"chunk","time":1792123808279,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1792123808279,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":3}} {"type":"turn/end","data":{"turn":1,"reason":{"kind":"completed"}}} -{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent {{session:2}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"CHILD_OK"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{session:2}} finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:9}}"}]}} +{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent worker-1 finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"CHILD_OK"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:9}}"}]}} {"type":"turn/start","data":{"turn":2}} {"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":2,"step":1}} -{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent {{session:2}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"CHILD_OK"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{session:2}} finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:9}}"},"surfaceOp":"append"} -{"type":"assistant/message","data":{"turn":2,"step":1,"message":{"role":"assistant","content":[{"type":"text","text":"LIMIT_OK"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:10}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1789485622082,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1789485622082,"index":0,"dt":[],"texts":["LIMIT_OK"]},{"type":"chunk","time":1789485622083,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"LIMIT_OK"}}},{"type":"chunk","time":1789485622083,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1789485622083,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent worker-1 finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"CHILD_OK"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:9}}"},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":2,"step":1,"message":{"role":"assistant","content":[{"type":"text","text":"LIMIT_OK"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:10}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1792123808319,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1792123808319,"index":0,"dt":[],"texts":["LIMIT_OK"]},{"type":"chunk","time":1792123808319,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"LIMIT_OK"}}},{"type":"chunk","time":1792123808319,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1792123808319,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":2,"step":1}} {"type":"turn/end","data":{"turn":2,"reason":{"kind":"completed"}}} diff --git a/snapshots/sdk/subagent-activation-limit/tool-schemas.1.expected.json b/snapshots/sdk/subagent-activation-limit/tool-schemas.1.expected.json index b546a748a7..99b37246de 100644 --- a/snapshots/sdk/subagent-activation-limit/tool-schemas.1.expected.json +++ b/snapshots/sdk/subagent-activation-limit/tool-schemas.1.expected.json @@ -181,13 +181,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -245,7 +245,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -297,9 +297,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -307,7 +307,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -330,10 +330,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -348,6 +352,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -355,10 +360,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -373,6 +382,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/sdk/subagent-continuable-inheritance/session.1.v4.jsonl b/snapshots/sdk/subagent-continuable-inheritance/session.1.v4.jsonl index 1174199fdd..11e3a8c717 100644 --- a/snapshots/sdk/subagent-continuable-inheritance/session.1.v4.jsonl +++ b/snapshots/sdk/subagent-continuable-inheritance/session.1.v4.jsonl @@ -2,12 +2,12 @@ {"type":"subagent/descriptor","data":{"version":3,"mode":"continuable","provider":"spawn","label":"Reply with CHILD_OK","agentProvider":"deepseek-official","agentModel":"deepseek-v4-flash"}} {"type":"sandbox/mode","data":{"mode":"read-only","source":"delegation"}} {"type":"approval/policy","data":{"policy":"never","source":"delegation"}} -{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Reply with exactly the word CHILD_OK and nothing else."},{"type":"text","text":"Your parent agent id is \"{{session:1}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{session:1}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:8}}"}]}} +{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Reply with exactly the word CHILD_OK and nothing else."},{"type":"text","text":"Your name is \"worker-1\". Your parent agent name is \"lead\". Before you finish, send your result to that agent with send_message({ name: \"lead\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:8}}"}]}} {"type":"turn/start","data":{"turn":1}} {"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":1,"step":1}} {"type":"system/message","data":{"turn":1,"step":1,"message":{"role":"system","content":[{"type":"text","text":"{{system}}"}],"source":{"kind":"system-prompt"},"id":"{{message:9}}"}},"surfaceOp":"append"} -{"type":"user/message","data":{"content":[{"type":"text","text":"Reply with exactly the word CHILD_OK and nothing else."},{"type":"text","text":"Your parent agent id is \"{{session:1}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{session:1}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:8}}"},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Reply with exactly the word CHILD_OK and nothing else."},{"type":"text","text":"Your name is \"worker-1\". Your parent agent name is \"lead\". Before you finish, send your result to that agent with send_message({ name: \"lead\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:8}}"},"surfaceOp":"append"} {"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: read-only. Any available operation enforced by the DSH file sandbox cannot modify files in the standing mode. Do not refuse a required modification from this policy alone: try an available tool normally and follow any denial and escalation guidance it returns.\n\nApproval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).\n\nDelegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly.\n\nDelegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly.\n\nYou are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: read-only. Any available operation enforced by the DSH file sandbox cannot modify files in the standing mode. Do not refuse a required modification from this policy alone: try an available tool normally and follow any denial and escalation guidance it returns."},{"name":"approval:policy","text":"Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."},{"name":"tool:subagent:depth","text":"Delegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly."},{"name":"tool:subagent_fork:depth","text":"Delegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly."},{"name":"subagent:delegation","text":"You are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}]},"role":"user","id":"{{message:10}}"},"surfaceOp":"append"} {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} diff --git a/snapshots/sdk/subagent-continuable-inheritance/session.v4.jsonl b/snapshots/sdk/subagent-continuable-inheritance/session.v4.jsonl index 36ddb02145..145d3194bc 100644 --- a/snapshots/sdk/subagent-continuable-inheritance/session.v4.jsonl +++ b/snapshots/sdk/subagent-continuable-inheritance/session.v4.jsonl @@ -13,15 +13,16 @@ {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} {"type":"session/title","data":{"title":"Follow these steps exactly, then","messageSeqs":[9],"source":{"kind":"fallback"}}} -{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_bg_start","name":"subagent","arguments":"{\"description\":\"Reply with CHILD_OK\",\"prompt\":\"Reply with exactly the word CHILD_OK and nothing else.\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1789626540344,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1789626540344,"index":0,"dt":[],"id":"call_bg_start","name":"subagent","args":["{\"description\":\"Reply with CHILD_OK\",\"prompt\":\"Reply with exactly the word CHILD_OK and nothing else.\"}"]},{"type":"chunk","time":1789626540344,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_bg_start","name":"subagent","arguments":"{\"description\":\"Reply with CHILD_OK\",\"prompt\":\"Reply with exactly the word CHILD_OK and nothing else.\"}"}}},{"type":"chunk","time":1789626540344,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1789626540344,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} -{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_bg_start","name":"subagent","arguments":"{\"description\":\"Reply with CHILD_OK\",\"prompt\":\"Reply with exactly the word CHILD_OK and nothing else.\"}"}} +{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_bg_start","name":"subagent","arguments":"{\"description\":\"Reply with CHILD_OK\",\"prompt\":\"Reply with exactly the word CHILD_OK and nothing else.\",\"name\":\"worker-1\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1792123809613,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792123809613,"index":0,"dt":[],"id":"call_bg_start","name":"subagent","args":["{\"description\":\"Reply with CHILD_OK\",\"prompt\":\"Reply with exactly the word CHILD_OK and nothing else.\",\"name\":\"worker-1\"}"]},{"type":"chunk","time":1792123809613,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_bg_start","name":"subagent","arguments":"{\"description\":\"Reply with CHILD_OK\",\"prompt\":\"Reply with exactly the word CHILD_OK and nothing else.\",\"name\":\"worker-1\"}"}}},{"type":"chunk","time":1792123809613,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1792123809613,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_bg_start","name":"subagent","arguments":"{\"description\":\"Reply with CHILD_OK\",\"prompt\":\"Reply with exactly the word CHILD_OK and nothing else.\",\"name\":\"worker-1\"}"}} {"type":"subagent/catalog","data":{"version":0,"childId":"{{session:2}}","childCreatedAt":1789000001000,"mode":"continuable","label":"Reply with CHILD_OK"}} -{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent {{session:2}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"CHILD_OK"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{session:2}} finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:5}}"}]}} -{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_bg_start"},"toolCallId":"call_bg_start","content":[{"type":"text","text":"started subagent {{session:2}}"}],"isError":false,"id":"{{message:6}}"}},"sourceEventSeqs":[15],"surfaceOp":"append"} +{"type":"subagent/named","data":{"name":"worker-1","id":"{{session:2}}"}} +{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent worker-1 finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"CHILD_OK"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:5}}"}]}} +{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_bg_start"},"toolCallId":"call_bg_start","content":[{"type":"text","text":"started subagent worker-1"}],"isError":false,"id":"{{message:6}}"}},"sourceEventSeqs":[15],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":1}} {"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":1,"step":2}} -{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent {{session:2}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"CHILD_OK"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{session:2}} finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:5}}"},"surfaceOp":"append"} -{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"text","text":"SUBAGENT_SETTLED_NOTED"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:7}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1789626540403,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1789626540403,"index":0,"dt":[],"texts":["SUBAGENT_SETTLED_NOTED"]},{"type":"chunk","time":1789626540403,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"SUBAGENT_SETTLED_NOTED"}}},{"type":"chunk","time":1789626540403,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1789626540403,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent worker-1 finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"CHILD_OK"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:5}}"},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"text","text":"SUBAGENT_SETTLED_NOTED"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:7}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1792123809681,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1792123809681,"index":0,"dt":[],"texts":["SUBAGENT_SETTLED_NOTED"]},{"type":"chunk","time":1792123809681,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"SUBAGENT_SETTLED_NOTED"}}},{"type":"chunk","time":1792123809681,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1792123809681,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":2}} {"type":"turn/end","data":{"turn":1,"reason":{"kind":"completed"}}} diff --git a/snapshots/sdk/subagent-continuable-inheritance/tool-schemas.1.expected.json b/snapshots/sdk/subagent-continuable-inheritance/tool-schemas.1.expected.json index b546a748a7..99b37246de 100644 --- a/snapshots/sdk/subagent-continuable-inheritance/tool-schemas.1.expected.json +++ b/snapshots/sdk/subagent-continuable-inheritance/tool-schemas.1.expected.json @@ -181,13 +181,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -245,7 +245,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -297,9 +297,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -307,7 +307,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -330,10 +330,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -348,6 +352,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -355,10 +360,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -373,6 +382,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/sdk/subagent-continuable/session.1.v4.jsonl b/snapshots/sdk/subagent-continuable/session.1.v4.jsonl index 5e6ae650ad..4089877d30 100644 --- a/snapshots/sdk/subagent-continuable/session.1.v4.jsonl +++ b/snapshots/sdk/subagent-continuable/session.1.v4.jsonl @@ -3,15 +3,15 @@ {"type":"sandbox/mode","data":{"mode":"danger-full-access","source":"delegation"}} {"type":"approval/policy","data":{"policy":"never","source":"delegation"}} {"type":"permission/preset","data":{"preset":"danger-full-access"}} -{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Reply with exactly the word CHILD_OK and nothing else."},{"type":"text","text":"Your parent agent id is \"{{session:1}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{session:1}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:15}}"}]}} +{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Reply with exactly the word CHILD_OK and nothing else."},{"type":"text","text":"Your name is \"worker-1\". Your parent agent name is \"lead\". Before you finish, send your result to that agent with send_message({ name: \"lead\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:15}}"}]}} {"type":"turn/start","data":{"turn":1}} {"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} -{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Agent {{session:1}} sent a message: "},{"type":"text","text":"Now reply with exactly SECOND_OK."}],"source":{"kind":"agent-message","form":"relay","senderSessionId":"{{session:1}}"},"role":"user","id":"{{message:16}}"}]}} -{"type":"agent/inbox/spliced","data":{"target":"next-step","start":1,"inserted":[{"content":[{"type":"text","text":"Agent {{session:1}} sent a message: "},{"type":"text","text":"Now reply with exactly THIRD_OK."}],"source":{"kind":"agent-message","form":"relay","senderSessionId":"{{session:1}}"},"role":"user","id":"{{message:17}}"}]}} +{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Agent lead sent a message: "},{"type":"text","text":"Now reply with exactly SECOND_OK."}],"source":{"kind":"agent-message","form":"relay","senderSessionId":"{{session:1}}"},"role":"user","id":"{{message:16}}"}]}} +{"type":"agent/inbox/spliced","data":{"target":"next-step","start":1,"inserted":[{"content":[{"type":"text","text":"Agent lead sent a message: "},{"type":"text","text":"Now reply with exactly THIRD_OK."}],"source":{"kind":"agent-message","form":"relay","senderSessionId":"{{session:1}}"},"role":"user","id":"{{message:17}}"}]}} {"type":"agent/inbox/spliced","data":{"target":"next-step","start":2,"inserted":[{"content":[{"type":"text","text":"Human priority: keep the requested exact reply."}],"source":{"kind":"user","rpcId":"{{rpc:1}}"},"role":"user","id":"{{message:18}}"}]}} {"type":"step/start","data":{"turn":1,"step":1}} {"type":"system/message","data":{"turn":1,"step":1,"message":{"role":"system","content":[{"type":"text","text":"{{system}}"}],"source":{"kind":"system-prompt"},"id":"{{message:19}}"}},"surfaceOp":"append"} -{"type":"user/message","data":{"content":[{"type":"text","text":"Reply with exactly the word CHILD_OK and nothing else."},{"type":"text","text":"Your parent agent id is \"{{session:1}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{session:1}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:15}}"},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Reply with exactly the word CHILD_OK and nothing else."},{"type":"text","text":"Your name is \"worker-1\". Your parent agent name is \"lead\". Before you finish, send your result to that agent with send_message({ name: \"lead\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:15}}"},"surfaceOp":"append"} {"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations.\n\nApproval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).\n\nDelegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly.\n\nDelegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly.\n\nYou are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations."},{"name":"approval:policy","text":"Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."},{"name":"tool:subagent:depth","text":"Delegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly."},{"name":"tool:subagent_fork:depth","text":"Delegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly."},{"name":"subagent:delegation","text":"You are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}]},"role":"user","id":"{{message:20}}"},"surfaceOp":"append"} {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} @@ -20,8 +20,8 @@ {"type":"step/end","data":{"turn":1,"step":1}} {"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"removedCount":3,"inserted":[]}} {"type":"step/start","data":{"turn":1,"step":2}} -{"type":"user/message","data":{"content":[{"type":"text","text":"Agent {{session:1}} sent a message: "},{"type":"text","text":"Now reply with exactly SECOND_OK."}],"source":{"kind":"agent-message","form":"relay","senderSessionId":"{{session:1}}"},"role":"user","id":"{{message:16}}"},"surfaceOp":"append"} -{"type":"user/message","data":{"content":[{"type":"text","text":"Agent {{session:1}} sent a message: "},{"type":"text","text":"Now reply with exactly THIRD_OK."}],"source":{"kind":"agent-message","form":"relay","senderSessionId":"{{session:1}}"},"role":"user","id":"{{message:17}}"},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Agent lead sent a message: "},{"type":"text","text":"Now reply with exactly SECOND_OK."}],"source":{"kind":"agent-message","form":"relay","senderSessionId":"{{session:1}}"},"role":"user","id":"{{message:16}}"},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Agent lead sent a message: "},{"type":"text","text":"Now reply with exactly THIRD_OK."}],"source":{"kind":"agent-message","form":"relay","senderSessionId":"{{session:1}}"},"role":"user","id":"{{message:17}}"},"surfaceOp":"append"} {"type":"user/message","data":{"content":[{"type":"text","text":"Human priority: keep the requested exact reply."}],"source":{"kind":"user","rpcId":"{{rpc:1}}"},"role":"user","id":"{{message:18}}"},"surfaceOp":"append"} {"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"reasoning","text":"I will return the requested exact reply."},{"type":"text","text":"SECOND_OK"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:22}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1788767375189,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1788767375189,"index":0,"dt":[],"texts":["I will return the requested exact reply."]},{"type":"chunk","time":1788767375189,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"I will return the requested exact reply."}}},{"type":"chunk","time":1788767375189,"chunk":{"type":"block-start","index":1,"blockType":"text"}},{"type":"text-chunks","time0":1788767375190,"index":1,"dt":[],"texts":["SECOND_OK"]},{"type":"chunk","time":1788767375190,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"SECOND_OK"}}},{"type":"chunk","time":1788767375190,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1788767375190,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":2}} diff --git a/snapshots/sdk/subagent-continuable/session.v4.jsonl b/snapshots/sdk/subagent-continuable/session.v4.jsonl index 28f5aea046..dec14af5e9 100644 --- a/snapshots/sdk/subagent-continuable/session.v4.jsonl +++ b/snapshots/sdk/subagent-continuable/session.v4.jsonl @@ -12,35 +12,36 @@ {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} {"type":"session/title","data":{"title":"Follow these steps exactly, then","messageSeqs":[8],"source":{"kind":"fallback"}}} -{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_bg_start","name":"subagent","arguments":"{\"description\": \"Reply with CHILD_OK\", \"prompt\": \"Reply with exactly the word CHILD_OK and nothing else.\", \"run_in_background\": true}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1788880385121,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1788880385122,"index":0,"dt":[],"id":"call_bg_start","name":"subagent","args":["{\"description\": \"Reply with CHILD_OK\", \"prompt\": \"Reply with exactly the word CHILD_OK and nothing else.\", \"run_in_background\": true}"]},{"type":"chunk","time":1788880385122,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_bg_start","name":"subagent","arguments":"{\"description\": \"Reply with CHILD_OK\", \"prompt\": \"Reply with exactly the word CHILD_OK and nothing else.\", \"run_in_background\": true}"}}},{"type":"chunk","time":1788880385122,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1788880385122,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} -{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_bg_start","name":"subagent","arguments":"{\"description\": \"Reply with CHILD_OK\", \"prompt\": \"Reply with exactly the word CHILD_OK and nothing else.\", \"run_in_background\": true}"}} +{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_bg_start","name":"subagent","arguments":"{\"description\":\"Reply with CHILD_OK\",\"prompt\":\"Reply with exactly the word CHILD_OK and nothing else.\",\"run_in_background\":true,\"name\":\"worker-1\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1792123808892,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792123808892,"index":0,"dt":[],"id":"call_bg_start","name":"subagent","args":["{\"description\":\"Reply with CHILD_OK\",\"prompt\":\"Reply with exactly the word CHILD_OK and nothing else.\",\"run_in_background\":true,\"name\":\"worker-1\"}"]},{"type":"chunk","time":1792123808892,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_bg_start","name":"subagent","arguments":"{\"description\":\"Reply with CHILD_OK\",\"prompt\":\"Reply with exactly the word CHILD_OK and nothing else.\",\"run_in_background\":true,\"name\":\"worker-1\"}"}}},{"type":"chunk","time":1792123808892,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1792123808892,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_bg_start","name":"subagent","arguments":"{\"description\":\"Reply with CHILD_OK\",\"prompt\":\"Reply with exactly the word CHILD_OK and nothing else.\",\"run_in_background\":true,\"name\":\"worker-1\"}"}} {"type":"subagent/catalog","data":{"version":0,"childId":"{{session:2}}","childCreatedAt":1789000001000,"mode":"continuable","label":"Reply with CHILD_OK"}} -{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_bg_start"},"toolCallId":"call_bg_start","content":[{"type":"text","text":"started subagent {{session:2}}"}],"isError":false,"id":"{{message:5}}"}},"sourceEventSeqs":[14],"surfaceOp":"append"} +{"type":"subagent/named","data":{"name":"worker-1","id":"{{session:2}}"}} +{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_bg_start"},"toolCallId":"call_bg_start","content":[{"type":"text","text":"started subagent worker-1"}],"isError":false,"id":"{{message:5}}"}},"sourceEventSeqs":[14],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":1}} {"type":"step/start","data":{"turn":1,"step":2}} -{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_followup_1","name":"send_message","arguments":"{\"agent_id\": \"{{session:2}}\", \"message\": \"Now reply with exactly SECOND_OK.\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:6}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1788880385160,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1788880385160,"index":0,"dt":[],"id":"call_followup_1","name":"send_message","args":["{\"agent_id\": \"{{session:2}}\", \"message\": \"Now reply with exactly SECOND_OK.\"}"]},{"type":"chunk","time":1788880385160,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_followup_1","name":"send_message","arguments":"{\"agent_id\": \"{{session:2}}\", \"message\": \"Now reply with exactly SECOND_OK.\"}"}}},{"type":"chunk","time":1788880385160,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1788880385160,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} -{"type":"tool/call","data":{"turn":1,"step":2,"callId":"call_followup_1","name":"send_message","arguments":"{\"agent_id\": \"{{session:2}}\", \"message\": \"Now reply with exactly SECOND_OK.\"}"}} -{"type":"tool/result","data":{"turn":1,"step":2,"message":{"role":"tool","source":{"kind":"tool","callId":"call_followup_1"},"toolCallId":"call_followup_1","content":[{"type":"text","text":"message delivered to agent {{session:2}}"}],"isError":false,"id":"{{message:7}}"}},"sourceEventSeqs":[20],"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_followup_1","name":"send_message","arguments":"{\"message\":\"Now reply with exactly SECOND_OK.\",\"name\":\"worker-1\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:6}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1792123808934,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792123808934,"index":0,"dt":[],"id":"call_followup_1","name":"send_message","args":["{\"message\":\"Now reply with exactly SECOND_OK.\",\"name\":\"worker-1\"}"]},{"type":"chunk","time":1792123808934,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_followup_1","name":"send_message","arguments":"{\"message\":\"Now reply with exactly SECOND_OK.\",\"name\":\"worker-1\"}"}}},{"type":"chunk","time":1792123808934,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1792123808934,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":2,"callId":"call_followup_1","name":"send_message","arguments":"{\"message\":\"Now reply with exactly SECOND_OK.\",\"name\":\"worker-1\"}"}} +{"type":"tool/result","data":{"turn":1,"step":2,"message":{"role":"tool","source":{"kind":"tool","callId":"call_followup_1"},"toolCallId":"call_followup_1","content":[{"type":"text","text":"message delivered to agent worker-1"}],"isError":false,"id":"{{message:7}}"}},"sourceEventSeqs":[21],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":2}} {"type":"step/start","data":{"turn":1,"step":3}} -{"type":"assistant/message","data":{"turn":1,"step":3,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_followup_2","name":"send_message","arguments":"{\"agent_id\": \"{{session:2}}\", \"message\": \"Now reply with exactly THIRD_OK.\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:8}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1788880385181,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1788880385181,"index":0,"dt":[],"id":"call_followup_2","name":"send_message","args":["{\"agent_id\": \"{{session:2}}\", \"message\": \"Now reply with exactly THIRD_OK.\"}"]},{"type":"chunk","time":1788880385181,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_followup_2","name":"send_message","arguments":"{\"agent_id\": \"{{session:2}}\", \"message\": \"Now reply with exactly THIRD_OK.\"}"}}},{"type":"chunk","time":1788880385181,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1788880385181,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} -{"type":"tool/call","data":{"turn":1,"step":3,"callId":"call_followup_2","name":"send_message","arguments":"{\"agent_id\": \"{{session:2}}\", \"message\": \"Now reply with exactly THIRD_OK.\"}"}} -{"type":"tool/result","data":{"turn":1,"step":3,"message":{"role":"tool","source":{"kind":"tool","callId":"call_followup_2"},"toolCallId":"call_followup_2","content":[{"type":"text","text":"message delivered to agent {{session:2}}"}],"isError":false,"id":"{{message:9}}"}},"sourceEventSeqs":[25],"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":3,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_followup_2","name":"send_message","arguments":"{\"message\":\"Now reply with exactly THIRD_OK.\",\"name\":\"worker-1\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:8}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1792123808950,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792123808950,"index":0,"dt":[],"id":"call_followup_2","name":"send_message","args":["{\"message\":\"Now reply with exactly THIRD_OK.\",\"name\":\"worker-1\"}"]},{"type":"chunk","time":1792123808950,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_followup_2","name":"send_message","arguments":"{\"message\":\"Now reply with exactly THIRD_OK.\",\"name\":\"worker-1\"}"}}},{"type":"chunk","time":1792123808950,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1792123808950,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":3,"callId":"call_followup_2","name":"send_message","arguments":"{\"message\":\"Now reply with exactly THIRD_OK.\",\"name\":\"worker-1\"}"}} +{"type":"tool/result","data":{"turn":1,"step":3,"message":{"role":"tool","source":{"kind":"tool","callId":"call_followup_2"},"toolCallId":"call_followup_2","content":[{"type":"text","text":"message delivered to agent worker-1"}],"isError":false,"id":"{{message:9}}"}},"sourceEventSeqs":[26],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":3}} {"type":"step/start","data":{"turn":1,"step":4}} -{"type":"assistant/message","data":{"turn":1,"step":4,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_followup_unknown","name":"send_message","arguments":"{\"agent_id\": \"22222222-2222-4222-8222-222222222222\", \"message\": \"Please continue.\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:10}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1788880385198,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1788880385198,"index":0,"dt":[],"id":"call_followup_unknown","name":"send_message","args":["{\"agent_id\": \"22222222-2222-4222-8222-222222222222\", \"message\": \"Please continue.\"}"]},{"type":"chunk","time":1788880385198,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_followup_unknown","name":"send_message","arguments":"{\"agent_id\": \"22222222-2222-4222-8222-222222222222\", \"message\": \"Please continue.\"}"}}},{"type":"chunk","time":1788880385198,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1788880385198,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} -{"type":"tool/call","data":{"turn":1,"step":4,"callId":"call_followup_unknown","name":"send_message","arguments":"{\"agent_id\": \"22222222-2222-4222-8222-222222222222\", \"message\": \"Please continue.\"}"}} -{"type":"tool/result","data":{"turn":1,"step":4,"message":{"role":"tool","source":{"kind":"tool","callId":"call_followup_unknown"},"toolCallId":"call_followup_unknown","content":[{"type":"text","text":"Error: subagent \"22222222-2222-4222-8222-222222222222\" is unavailable"}],"isError":true,"id":"{{message:11}}"},"error":{"name":"SubagentError","code":"NOT_RESUMABLE"}},"sourceEventSeqs":[30],"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":4,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_followup_unknown","name":"send_message","arguments":"{\"message\":\"Please continue.\",\"name\":\"22222222-2222-4222-8222-222222222222\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:10}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1792123808966,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792123808966,"index":0,"dt":[],"id":"call_followup_unknown","name":"send_message","args":["{\"message\":\"Please continue.\",\"name\":\"22222222-2222-4222-8222-222222222222\"}"]},{"type":"chunk","time":1792123808966,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_followup_unknown","name":"send_message","arguments":"{\"message\":\"Please continue.\",\"name\":\"22222222-2222-4222-8222-222222222222\"}"}}},{"type":"chunk","time":1792123808966,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1792123808966,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":4,"callId":"call_followup_unknown","name":"send_message","arguments":"{\"message\":\"Please continue.\",\"name\":\"22222222-2222-4222-8222-222222222222\"}"}} +{"type":"tool/result","data":{"turn":1,"step":4,"message":{"role":"tool","source":{"kind":"tool","callId":"call_followup_unknown"},"toolCallId":"call_followup_unknown","content":[{"type":"text","text":"Error: agent name \"22222222-2222-4222-8222-222222222222\" was not found; use list_agents to discover available names"}],"isError":true,"id":"{{message:11}}"},"error":{"name":"SubagentError","code":"AGENT_NAME_NOT_FOUND"}},"sourceEventSeqs":[31],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":4}} {"type":"step/start","data":{"turn":1,"step":5}} -{"type":"assistant/message","data":{"turn":1,"step":5,"message":{"role":"assistant","content":[{"type":"text","text":"DONE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:12}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1788880385215,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1788880385215,"index":0,"dt":[],"texts":["DONE"]},{"type":"chunk","time":1788880385215,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"DONE"}}},{"type":"chunk","time":1788880385215,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1788880385215,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":5,"message":{"role":"assistant","content":[{"type":"text","text":"DONE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:12}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1792123808983,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1792123808983,"index":0,"dt":[],"texts":["DONE"]},{"type":"chunk","time":1792123808983,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"DONE"}}},{"type":"chunk","time":1792123808983,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1792123808983,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":5}} {"type":"turn/end","data":{"turn":1,"reason":{"kind":"completed"}}} -{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent {{session:2}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"SECOND_OK"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{session:2}} finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:13}}"}]}} +{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent worker-1 finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"SECOND_OK"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:13}}"}]}} {"type":"turn/start","data":{"turn":2}} {"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":2,"step":1}} -{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent {{session:2}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"SECOND_OK"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{session:2}} finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:13}}"},"surfaceOp":"append"} -{"type":"assistant/message","data":{"turn":2,"step":1,"message":{"role":"assistant","content":[{"type":"text","text":"SUBAGENT_SETTLED_NOTED"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:14}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1788880385266,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1788880385266,"index":0,"dt":[],"texts":["SUBAGENT_SETTLED_NOTED"]},{"type":"chunk","time":1788880385266,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"SUBAGENT_SETTLED_NOTED"}}},{"type":"chunk","time":1788880385266,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1788880385266,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent worker-1 finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"SECOND_OK"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:13}}"},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":2,"step":1,"message":{"role":"assistant","content":[{"type":"text","text":"SUBAGENT_SETTLED_NOTED"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:14}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1792123809042,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1792123809042,"index":0,"dt":[],"texts":["SUBAGENT_SETTLED_NOTED"]},{"type":"chunk","time":1792123809042,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"SUBAGENT_SETTLED_NOTED"}}},{"type":"chunk","time":1792123809042,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1792123809042,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":2,"step":1}} {"type":"turn/end","data":{"turn":2,"reason":{"kind":"completed"}}} diff --git a/snapshots/sdk/subagent-continuable/tool-schemas.1.expected.json b/snapshots/sdk/subagent-continuable/tool-schemas.1.expected.json index b546a748a7..99b37246de 100644 --- a/snapshots/sdk/subagent-continuable/tool-schemas.1.expected.json +++ b/snapshots/sdk/subagent-continuable/tool-schemas.1.expected.json @@ -181,13 +181,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -245,7 +245,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -297,9 +297,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -307,7 +307,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -330,10 +330,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -348,6 +352,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -355,10 +360,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -373,6 +382,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/sdk/subagent-dsh-sdk-diagnostic/notifications.expected.jsonl b/snapshots/sdk/subagent-dsh-sdk-diagnostic/notifications.expected.jsonl index 96cd8efb6b..9395718dc3 100644 --- a/snapshots/sdk/subagent-dsh-sdk-diagnostic/notifications.expected.jsonl +++ b/snapshots/sdk/subagent-dsh-sdk-diagnostic/notifications.expected.jsonl @@ -10,27 +10,29 @@ {"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"request/context","seq":11,"time":0,"data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}}}} {"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"session/title","seq":12,"time":0,"data":{"title":"Observe the DSH SDK diagnostic","messageSeqs":[8],"source":{"kind":"fallback"}}}}} {"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"session-log-deepseek/delivery-accepted","seq":13,"time":0,"data":{"sessionId":"{{sessionId}}","sessionFormatVersion":4,"throughSeq":12}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/message","seq":14,"time":0,"data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_dsh_sdk_first","name":"subagent_dsh_sdk","arguments":"{\"description\":\"Observe first DSH SDK failure\",\"prompt\":\"Return the scripted DSH SDK failure.\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{sessionId}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":0,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":0,"index":0,"dt":[],"id":"call_dsh_sdk_first","name":"subagent_dsh_sdk","args":["{\"description\":\"Observe first DSH SDK failure\",\"prompt\":\"Return the scripted DSH SDK failure.\"}"]},{"type":"chunk","time":0,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_dsh_sdk_first","name":"subagent_dsh_sdk","arguments":"{\"description\":\"Observe first DSH SDK failure\",\"prompt\":\"Return the scripted DSH SDK failure.\"}"}}},{"type":"chunk","time":0,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":0,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"tool/call","seq":15,"time":0,"data":{"turn":1,"step":1,"callId":"call_dsh_sdk_first","name":"subagent_dsh_sdk","arguments":"{\"description\":\"Observe first DSH SDK failure\",\"prompt\":\"Return the scripted DSH SDK failure.\"}"}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/message","seq":14,"time":0,"data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_dsh_sdk_first","name":"subagent_dsh_sdk","arguments":"{\"description\":\"Observe first DSH SDK failure\",\"prompt\":\"Return the scripted DSH SDK failure.\",\"name\":\"worker-1\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{sessionId}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":0,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":0,"index":0,"dt":[],"id":"call_dsh_sdk_first","name":"subagent_dsh_sdk","args":["{\"description\":\"Observe first DSH SDK failure\",\"prompt\":\"Return the scripted DSH SDK failure.\",\"name\":\"worker-1\"}"]},{"type":"chunk","time":0,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_dsh_sdk_first","name":"subagent_dsh_sdk","arguments":"{\"description\":\"Observe first DSH SDK failure\",\"prompt\":\"Return the scripted DSH SDK failure.\",\"name\":\"worker-1\"}"}}},{"type":"chunk","time":0,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":0,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"tool/call","seq":15,"time":0,"data":{"turn":1,"step":1,"callId":"call_dsh_sdk_first","name":"subagent_dsh_sdk","arguments":"{\"description\":\"Observe first DSH SDK failure\",\"prompt\":\"Return the scripted DSH SDK failure.\",\"name\":\"worker-1\"}"}}}} {"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"subagent/catalog","seq":16,"time":0,"data":{"version":2,"childId":"{{sessionId}}","childCreatedAt":0,"mode":"external","label":"Observe first DSH SDK failure"}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"agent/inbox/spliced","seq":17,"time":0,"data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent {{sessionId}} failed before it finished."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"partial child loader answer"},{"type":"text","text":"Subagent failure (provider: DSH SDK; stage: session-run; category: child-error)"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{sessionId}} failed before it finished.","senderSessionId":"{{sessionId}}"},"role":"user","id":"{{sessionId}}"}]}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"tool/result","seq":18,"time":0,"data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_dsh_sdk_first"},"toolCallId":"call_dsh_sdk_first","content":[{"type":"text","text":"started subagent {{sessionId}}"}],"isError":false,"id":"{{sessionId}}"}},"sourceEventSeqs":[15],"surfaceOp":"append"}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/end","seq":19,"time":0,"data":{"turn":1,"step":1}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"agent/inbox/spliced","seq":20,"time":0,"data":{"target":"next-step","start":0,"removedCount":1,"inserted":[]}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/start","seq":21,"time":0,"data":{"turn":1,"step":2}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"user/message","seq":22,"time":0,"data":{"content":[{"type":"text","text":"Background subagent {{sessionId}} failed before it finished."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"partial child loader answer"},{"type":"text","text":"Subagent failure (provider: DSH SDK; stage: session-run; category: child-error)"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{sessionId}} failed before it finished.","senderSessionId":"{{sessionId}}"},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"session-log-deepseek/delivery-accepted","seq":23,"time":0,"data":{"sessionId":"{{sessionId}}","sessionFormatVersion":4,"throughSeq":22}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/message","seq":24,"time":0,"data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_dsh_sdk_second","name":"subagent_dsh_sdk_second","arguments":"{\"description\":\"Observe second DSH SDK failure\",\"prompt\":\"Return the scripted DSH SDK failure.\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{sessionId}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":0,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":0,"index":0,"dt":[],"id":"call_dsh_sdk_second","name":"subagent_dsh_sdk_second","args":["{\"description\":\"Observe second DSH SDK failure\",\"prompt\":\"Return the scripted DSH SDK failure.\"}"]},{"type":"chunk","time":0,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_dsh_sdk_second","name":"subagent_dsh_sdk_second","arguments":"{\"description\":\"Observe second DSH SDK failure\",\"prompt\":\"Return the scripted DSH SDK failure.\"}"}}},{"type":"chunk","time":0,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":0,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"tool/call","seq":25,"time":0,"data":{"turn":1,"step":2,"callId":"call_dsh_sdk_second","name":"subagent_dsh_sdk_second","arguments":"{\"description\":\"Observe second DSH SDK failure\",\"prompt\":\"Return the scripted DSH SDK failure.\"}"}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"subagent/catalog","seq":26,"time":0,"data":{"version":2,"childId":"{{sessionId}}","childCreatedAt":0,"mode":"external","label":"Observe second DSH SDK failure"}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"agent/inbox/spliced","seq":27,"time":0,"data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent {{sessionId}} failed before it finished."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"partial child loader answer"},{"type":"text","text":"Subagent failure (provider: DSH SDK; stage: session-run; category: child-error)"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{sessionId}} failed before it finished.","senderSessionId":"{{sessionId}}"},"role":"user","id":"{{sessionId}}"}]}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"tool/result","seq":28,"time":0,"data":{"turn":1,"step":2,"message":{"role":"tool","source":{"kind":"tool","callId":"call_dsh_sdk_second"},"toolCallId":"call_dsh_sdk_second","content":[{"type":"text","text":"started subagent {{sessionId}}"}],"isError":false,"id":"{{sessionId}}"}},"sourceEventSeqs":[25],"surfaceOp":"append"}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/end","seq":29,"time":0,"data":{"turn":1,"step":2}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"agent/inbox/spliced","seq":30,"time":0,"data":{"target":"next-step","start":0,"removedCount":1,"inserted":[]}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/start","seq":31,"time":0,"data":{"turn":1,"step":3}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"user/message","seq":32,"time":0,"data":{"content":[{"type":"text","text":"Background subagent {{sessionId}} failed before it finished."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"partial child loader answer"},{"type":"text","text":"Subagent failure (provider: DSH SDK; stage: session-run; category: child-error)"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{sessionId}} failed before it finished.","senderSessionId":"{{sessionId}}"},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"session-log-deepseek/delivery-accepted","seq":33,"time":0,"data":{"sessionId":"{{sessionId}}","sessionFormatVersion":4,"throughSeq":32}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/message","seq":34,"time":0,"data":{"turn":1,"step":3,"message":{"role":"assistant","content":[{"type":"text","text":"PARENT_OBSERVED_DSH_SDK_DIAGNOSTIC"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{sessionId}}"},"usage":{"inputTokens":10,"outputTokens":2},"stream":[{"type":"chunk","time":0,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":0,"index":0,"dt":[],"texts":["PARENT_OBSERVED_DSH_SDK_DIAGNOSTIC"]},{"type":"chunk","time":0,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"PARENT_OBSERVED_DSH_SDK_DIAGNOSTIC"}}},{"type":"chunk","time":0,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":2}}},{"type":"chunk","time":0,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/end","seq":35,"time":0,"data":{"turn":1,"step":3}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"turn/end","seq":36,"time":0,"data":{"turn":1,"reason":{"kind":"completed"}}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"subagent/named","seq":17,"time":0,"data":{"name":"worker-1","id":"{{sessionId}}"}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"agent/inbox/spliced","seq":18,"time":0,"data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent worker-1 failed before it finished."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"partial child loader answer"},{"type":"text","text":"Subagent failure (provider: DSH SDK; stage: session-run; category: child-error)"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 failed before it finished.","senderSessionId":"{{sessionId}}"},"role":"user","id":"{{sessionId}}"}]}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"tool/result","seq":19,"time":0,"data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_dsh_sdk_first"},"toolCallId":"call_dsh_sdk_first","content":[{"type":"text","text":"started subagent worker-1"}],"isError":false,"id":"{{sessionId}}"}},"sourceEventSeqs":[15],"surfaceOp":"append"}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/end","seq":20,"time":0,"data":{"turn":1,"step":1}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"agent/inbox/spliced","seq":21,"time":0,"data":{"target":"next-step","start":0,"removedCount":1,"inserted":[]}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/start","seq":22,"time":0,"data":{"turn":1,"step":2}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"user/message","seq":23,"time":0,"data":{"content":[{"type":"text","text":"Background subagent worker-1 failed before it finished."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"partial child loader answer"},{"type":"text","text":"Subagent failure (provider: DSH SDK; stage: session-run; category: child-error)"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 failed before it finished.","senderSessionId":"{{sessionId}}"},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"session-log-deepseek/delivery-accepted","seq":24,"time":0,"data":{"sessionId":"{{sessionId}}","sessionFormatVersion":4,"throughSeq":23}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/message","seq":25,"time":0,"data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_dsh_sdk_second","name":"subagent_dsh_sdk_second","arguments":"{\"description\":\"Observe second DSH SDK failure\",\"prompt\":\"Return the scripted DSH SDK failure.\",\"name\":\"worker-2\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{sessionId}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":0,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":0,"index":0,"dt":[],"id":"call_dsh_sdk_second","name":"subagent_dsh_sdk_second","args":["{\"description\":\"Observe second DSH SDK failure\",\"prompt\":\"Return the scripted DSH SDK failure.\",\"name\":\"worker-2\"}"]},{"type":"chunk","time":0,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_dsh_sdk_second","name":"subagent_dsh_sdk_second","arguments":"{\"description\":\"Observe second DSH SDK failure\",\"prompt\":\"Return the scripted DSH SDK failure.\",\"name\":\"worker-2\"}"}}},{"type":"chunk","time":0,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":0,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"tool/call","seq":26,"time":0,"data":{"turn":1,"step":2,"callId":"call_dsh_sdk_second","name":"subagent_dsh_sdk_second","arguments":"{\"description\":\"Observe second DSH SDK failure\",\"prompt\":\"Return the scripted DSH SDK failure.\",\"name\":\"worker-2\"}"}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"subagent/catalog","seq":27,"time":0,"data":{"version":2,"childId":"{{sessionId}}","childCreatedAt":0,"mode":"external","label":"Observe second DSH SDK failure"}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"subagent/named","seq":28,"time":0,"data":{"name":"worker-2","id":"{{sessionId}}"}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"agent/inbox/spliced","seq":29,"time":0,"data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent worker-2 failed before it finished."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"partial child loader answer"},{"type":"text","text":"Subagent failure (provider: DSH SDK; stage: session-run; category: child-error)"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-2 failed before it finished.","senderSessionId":"{{sessionId}}"},"role":"user","id":"{{sessionId}}"}]}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"tool/result","seq":30,"time":0,"data":{"turn":1,"step":2,"message":{"role":"tool","source":{"kind":"tool","callId":"call_dsh_sdk_second"},"toolCallId":"call_dsh_sdk_second","content":[{"type":"text","text":"started subagent worker-2"}],"isError":false,"id":"{{sessionId}}"}},"sourceEventSeqs":[26],"surfaceOp":"append"}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/end","seq":31,"time":0,"data":{"turn":1,"step":2}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"agent/inbox/spliced","seq":32,"time":0,"data":{"target":"next-step","start":0,"removedCount":1,"inserted":[]}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/start","seq":33,"time":0,"data":{"turn":1,"step":3}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"user/message","seq":34,"time":0,"data":{"content":[{"type":"text","text":"Background subagent worker-2 failed before it finished."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"partial child loader answer"},{"type":"text","text":"Subagent failure (provider: DSH SDK; stage: session-run; category: child-error)"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-2 failed before it finished.","senderSessionId":"{{sessionId}}"},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"session-log-deepseek/delivery-accepted","seq":35,"time":0,"data":{"sessionId":"{{sessionId}}","sessionFormatVersion":4,"throughSeq":34}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/message","seq":36,"time":0,"data":{"turn":1,"step":3,"message":{"role":"assistant","content":[{"type":"text","text":"PARENT_OBSERVED_DSH_SDK_DIAGNOSTIC"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{sessionId}}"},"usage":{"inputTokens":10,"outputTokens":2},"stream":[{"type":"chunk","time":0,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":0,"index":0,"dt":[],"texts":["PARENT_OBSERVED_DSH_SDK_DIAGNOSTIC"]},{"type":"chunk","time":0,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"PARENT_OBSERVED_DSH_SDK_DIAGNOSTIC"}}},{"type":"chunk","time":0,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":2}}},{"type":"chunk","time":0,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/end","seq":37,"time":0,"data":{"turn":1,"step":3}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"turn/end","seq":38,"time":0,"data":{"turn":1,"reason":{"kind":"completed"}}}}} {"method":"session.status","params":{"sessionId":"{{sessionId}}","status":"idle"}} diff --git a/snapshots/sdk/subagent-dsh-sdk-diagnostic/session.v4.jsonl b/snapshots/sdk/subagent-dsh-sdk-diagnostic/session.v4.jsonl index 1b64a3f642..c5ca885681 100644 --- a/snapshots/sdk/subagent-dsh-sdk-diagnostic/session.v4.jsonl +++ b/snapshots/sdk/subagent-dsh-sdk-diagnostic/session.v4.jsonl @@ -13,26 +13,28 @@ {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} {"type":"session/title","data":{"title":"Observe the DSH SDK diagnostic","messageSeqs":[8],"source":{"kind":"fallback"}}} {"type":"session-log-deepseek/delivery-accepted","data":{"sessionId":"{{session:1}}","sessionFormatVersion":4,"throughSeq":12}} -{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_dsh_sdk_first","name":"subagent_dsh_sdk","arguments":"{\"description\":\"Observe first DSH SDK failure\",\"prompt\":\"Return the scripted DSH SDK failure.\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1789820381724,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1789820381724,"index":0,"dt":[],"id":"call_dsh_sdk_first","name":"subagent_dsh_sdk","args":["{\"description\":\"Observe first DSH SDK failure\",\"prompt\":\"Return the scripted DSH SDK failure.\"}"]},{"type":"chunk","time":1789820381724,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_dsh_sdk_first","name":"subagent_dsh_sdk","arguments":"{\"description\":\"Observe first DSH SDK failure\",\"prompt\":\"Return the scripted DSH SDK failure.\"}"}}},{"type":"chunk","time":1789820381724,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1789820381724,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} -{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_dsh_sdk_first","name":"subagent_dsh_sdk","arguments":"{\"description\":\"Observe first DSH SDK failure\",\"prompt\":\"Return the scripted DSH SDK failure.\"}"}} -{"type":"subagent/catalog","data":{"version":2,"childId":"{{id:1}}","childCreatedAt":1789820382130,"mode":"external","label":"Observe first DSH SDK failure"}} -{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent {{id:1}} failed before it finished."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"partial child loader answer"},{"type":"text","text":"Subagent failure (provider: DSH SDK; stage: session-run; category: child-error)"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{id:1}} failed before it finished.","senderSessionId":"{{id:1}}"},"role":"user","id":"{{message:5}}"}]}} -{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_dsh_sdk_first"},"toolCallId":"call_dsh_sdk_first","content":[{"type":"text","text":"started subagent {{id:1}}"}],"isError":false,"id":"{{message:6}}"}},"sourceEventSeqs":[15],"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_dsh_sdk_first","name":"subagent_dsh_sdk","arguments":"{\"description\":\"Observe first DSH SDK failure\",\"prompt\":\"Return the scripted DSH SDK failure.\",\"name\":\"worker-1\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1792123810244,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792123810244,"index":0,"dt":[],"id":"call_dsh_sdk_first","name":"subagent_dsh_sdk","args":["{\"description\":\"Observe first DSH SDK failure\",\"prompt\":\"Return the scripted DSH SDK failure.\",\"name\":\"worker-1\"}"]},{"type":"chunk","time":1792123810244,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_dsh_sdk_first","name":"subagent_dsh_sdk","arguments":"{\"description\":\"Observe first DSH SDK failure\",\"prompt\":\"Return the scripted DSH SDK failure.\",\"name\":\"worker-1\"}"}}},{"type":"chunk","time":1792123810244,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1792123810244,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_dsh_sdk_first","name":"subagent_dsh_sdk","arguments":"{\"description\":\"Observe first DSH SDK failure\",\"prompt\":\"Return the scripted DSH SDK failure.\",\"name\":\"worker-1\"}"}} +{"type":"subagent/catalog","data":{"version":2,"childId":"{{id:1}}","childCreatedAt":1792123810690,"mode":"external","label":"Observe first DSH SDK failure"}} +{"type":"subagent/named","data":{"name":"worker-1","id":"{{id:1}}"}} +{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent worker-1 failed before it finished."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"partial child loader answer"},{"type":"text","text":"Subagent failure (provider: DSH SDK; stage: session-run; category: child-error)"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 failed before it finished.","senderSessionId":"{{id:1}}"},"role":"user","id":"{{message:5}}"}]}} +{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_dsh_sdk_first"},"toolCallId":"call_dsh_sdk_first","content":[{"type":"text","text":"started subagent worker-1"}],"isError":false,"id":"{{message:6}}"}},"sourceEventSeqs":[15],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":1}} {"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":1,"step":2}} -{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent {{id:1}} failed before it finished."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"partial child loader answer"},{"type":"text","text":"Subagent failure (provider: DSH SDK; stage: session-run; category: child-error)"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{id:1}} failed before it finished.","senderSessionId":"{{id:1}}"},"role":"user","id":"{{message:5}}"},"surfaceOp":"append"} -{"type":"session-log-deepseek/delivery-accepted","data":{"sessionId":"{{session:1}}","sessionFormatVersion":4,"throughSeq":22}} -{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_dsh_sdk_second","name":"subagent_dsh_sdk_second","arguments":"{\"description\":\"Observe second DSH SDK failure\",\"prompt\":\"Return the scripted DSH SDK failure.\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:7}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1789820382241,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1789820382241,"index":0,"dt":[],"id":"call_dsh_sdk_second","name":"subagent_dsh_sdk_second","args":["{\"description\":\"Observe second DSH SDK failure\",\"prompt\":\"Return the scripted DSH SDK failure.\"}"]},{"type":"chunk","time":1789820382241,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_dsh_sdk_second","name":"subagent_dsh_sdk_second","arguments":"{\"description\":\"Observe second DSH SDK failure\",\"prompt\":\"Return the scripted DSH SDK failure.\"}"}}},{"type":"chunk","time":1789820382241,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1789820382241,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} -{"type":"tool/call","data":{"turn":1,"step":2,"callId":"call_dsh_sdk_second","name":"subagent_dsh_sdk_second","arguments":"{\"description\":\"Observe second DSH SDK failure\",\"prompt\":\"Return the scripted DSH SDK failure.\"}"}} -{"type":"subagent/catalog","data":{"version":2,"childId":"{{id:2}}","childCreatedAt":1789820382616,"mode":"external","label":"Observe second DSH SDK failure"}} -{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent {{id:2}} failed before it finished."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"partial child loader answer"},{"type":"text","text":"Subagent failure (provider: DSH SDK; stage: session-run; category: child-error)"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{id:2}} failed before it finished.","senderSessionId":"{{id:2}}"},"role":"user","id":"{{message:8}}"}]}} -{"type":"tool/result","data":{"turn":1,"step":2,"message":{"role":"tool","source":{"kind":"tool","callId":"call_dsh_sdk_second"},"toolCallId":"call_dsh_sdk_second","content":[{"type":"text","text":"started subagent {{id:2}}"}],"isError":false,"id":"{{message:9}}"}},"sourceEventSeqs":[25],"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent worker-1 failed before it finished."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"partial child loader answer"},{"type":"text","text":"Subagent failure (provider: DSH SDK; stage: session-run; category: child-error)"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 failed before it finished.","senderSessionId":"{{id:1}}"},"role":"user","id":"{{message:5}}"},"surfaceOp":"append"} +{"type":"session-log-deepseek/delivery-accepted","data":{"sessionId":"{{session:1}}","sessionFormatVersion":4,"throughSeq":23}} +{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_dsh_sdk_second","name":"subagent_dsh_sdk_second","arguments":"{\"description\":\"Observe second DSH SDK failure\",\"prompt\":\"Return the scripted DSH SDK failure.\",\"name\":\"worker-2\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:7}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1792123810840,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792123810840,"index":0,"dt":[],"id":"call_dsh_sdk_second","name":"subagent_dsh_sdk_second","args":["{\"description\":\"Observe second DSH SDK failure\",\"prompt\":\"Return the scripted DSH SDK failure.\",\"name\":\"worker-2\"}"]},{"type":"chunk","time":1792123810840,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_dsh_sdk_second","name":"subagent_dsh_sdk_second","arguments":"{\"description\":\"Observe second DSH SDK failure\",\"prompt\":\"Return the scripted DSH SDK failure.\",\"name\":\"worker-2\"}"}}},{"type":"chunk","time":1792123810840,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1792123810840,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":2,"callId":"call_dsh_sdk_second","name":"subagent_dsh_sdk_second","arguments":"{\"description\":\"Observe second DSH SDK failure\",\"prompt\":\"Return the scripted DSH SDK failure.\",\"name\":\"worker-2\"}"}} +{"type":"subagent/catalog","data":{"version":2,"childId":"{{id:2}}","childCreatedAt":1792123811291,"mode":"external","label":"Observe second DSH SDK failure"}} +{"type":"subagent/named","data":{"name":"worker-2","id":"{{id:2}}"}} +{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent worker-2 failed before it finished."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"partial child loader answer"},{"type":"text","text":"Subagent failure (provider: DSH SDK; stage: session-run; category: child-error)"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-2 failed before it finished.","senderSessionId":"{{id:2}}"},"role":"user","id":"{{message:8}}"}]}} +{"type":"tool/result","data":{"turn":1,"step":2,"message":{"role":"tool","source":{"kind":"tool","callId":"call_dsh_sdk_second"},"toolCallId":"call_dsh_sdk_second","content":[{"type":"text","text":"started subagent worker-2"}],"isError":false,"id":"{{message:9}}"}},"sourceEventSeqs":[26],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":2}} {"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":1,"step":3}} -{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent {{id:2}} failed before it finished."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"partial child loader answer"},{"type":"text","text":"Subagent failure (provider: DSH SDK; stage: session-run; category: child-error)"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{id:2}} failed before it finished.","senderSessionId":"{{id:2}}"},"role":"user","id":"{{message:8}}"},"surfaceOp":"append"} -{"type":"session-log-deepseek/delivery-accepted","data":{"sessionId":"{{session:1}}","sessionFormatVersion":4,"throughSeq":32}} -{"type":"assistant/message","data":{"turn":1,"step":3,"message":{"role":"assistant","content":[{"type":"text","text":"PARENT_OBSERVED_DSH_SDK_DIAGNOSTIC"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:10}}"},"usage":{"inputTokens":10,"outputTokens":2},"stream":[{"type":"chunk","time":1789820382721,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1789820382721,"index":0,"dt":[],"texts":["PARENT_OBSERVED_DSH_SDK_DIAGNOSTIC"]},{"type":"chunk","time":1789820382721,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"PARENT_OBSERVED_DSH_SDK_DIAGNOSTIC"}}},{"type":"chunk","time":1789820382721,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":2}}},{"type":"chunk","time":1789820382721,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent worker-2 failed before it finished."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"partial child loader answer"},{"type":"text","text":"Subagent failure (provider: DSH SDK; stage: session-run; category: child-error)"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-2 failed before it finished.","senderSessionId":"{{id:2}}"},"role":"user","id":"{{message:8}}"},"surfaceOp":"append"} +{"type":"session-log-deepseek/delivery-accepted","data":{"sessionId":"{{session:1}}","sessionFormatVersion":4,"throughSeq":34}} +{"type":"assistant/message","data":{"turn":1,"step":3,"message":{"role":"assistant","content":[{"type":"text","text":"PARENT_OBSERVED_DSH_SDK_DIAGNOSTIC"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:10}}"},"usage":{"inputTokens":10,"outputTokens":2},"stream":[{"type":"chunk","time":1792123811439,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1792123811439,"index":0,"dt":[],"texts":["PARENT_OBSERVED_DSH_SDK_DIAGNOSTIC"]},{"type":"chunk","time":1792123811439,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"PARENT_OBSERVED_DSH_SDK_DIAGNOSTIC"}}},{"type":"chunk","time":1792123811439,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":2}}},{"type":"chunk","time":1792123811439,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":3}} {"type":"turn/end","data":{"turn":1,"reason":{"kind":"completed"}}} diff --git a/snapshots/sdk/subagent-dsh-sdk-diagnostic/tool-schemas.expected.json b/snapshots/sdk/subagent-dsh-sdk-diagnostic/tool-schemas.expected.json index 31b1dbfb2b..dbed3d6fff 100644 --- a/snapshots/sdk/subagent-dsh-sdk-diagnostic/tool-schemas.expected.json +++ b/snapshots/sdk/subagent-dsh-sdk-diagnostic/tool-schemas.expected.json @@ -181,13 +181,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -245,7 +245,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -297,9 +297,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -307,7 +307,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -330,10 +330,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -348,6 +352,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -355,10 +360,14 @@ }, { "name": "subagent_dsh_sdk", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The completion notice includes its final answer. This backend does not accept follow-up messages.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The completion notice includes its final answer. This backend does not accept follow-up messages.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -373,6 +382,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -380,10 +390,14 @@ }, { "name": "subagent_dsh_sdk_second", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The completion notice includes its final answer. This backend does not accept follow-up messages.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The completion notice includes its final answer. This backend does not accept follow-up messages.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -398,6 +412,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -405,10 +420,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -423,6 +442,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/sdk/subagent-dsh-sdk-dynamic-route/notifications.expected.jsonl b/snapshots/sdk/subagent-dsh-sdk-dynamic-route/notifications.expected.jsonl index 3d115de999..31307da244 100644 --- a/snapshots/sdk/subagent-dsh-sdk-dynamic-route/notifications.expected.jsonl +++ b/snapshots/sdk/subagent-dsh-sdk-dynamic-route/notifications.expected.jsonl @@ -9,16 +9,17 @@ {"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"request/header","seq":11,"time":0,"data":{"header":{"config":{"provider":"deepseek-official","model":"mock-delegate"},"tools":"{{tools}}"},"reason":"initial"}}}} {"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"request/context","seq":12,"time":0,"data":{"provider":"deepseek-official","model":"mock-delegate"}}}} {"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"session/title","seq":13,"time":0,"data":{"title":"Delegate once using the requested","messageSeqs":[9],"source":{"kind":"fallback"}}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/message","seq":14,"time":0,"data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call-delegate","name":"subagent","arguments":"{\"description\":\"route probe\",\"prompt\":\"report your route and workspace\",\"provider\":\"mock\",\"model\":\"mock-routed\",\"reasoning_effort\":\"max\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"mock-delegate"},"id":"{{sessionId}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":0,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":0,"index":0,"dt":[],"id":"call-delegate","name":"subagent","args":["{\"description\":\"route probe\",\"prompt\":\"report your route and workspace\",\"provider\":\"mock\",\"model\":\"mock-routed\",\"reasoning_effort\":\"max\"}"]},{"type":"chunk","time":0,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call-delegate","name":"subagent","arguments":"{\"description\":\"route probe\",\"prompt\":\"report your route and workspace\",\"provider\":\"mock\",\"model\":\"mock-routed\",\"reasoning_effort\":\"max\"}"}}},{"type":"chunk","time":0,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":0,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"tool/call","seq":15,"time":0,"data":{"turn":1,"step":1,"callId":"call-delegate","name":"subagent","arguments":"{\"description\":\"route probe\",\"prompt\":\"report your route and workspace\",\"provider\":\"mock\",\"model\":\"mock-routed\",\"reasoning_effort\":\"max\"}"}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/message","seq":14,"time":0,"data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call-delegate","name":"subagent","arguments":"{\"description\":\"route probe\",\"prompt\":\"report your route and workspace\",\"provider\":\"mock\",\"model\":\"mock-routed\",\"reasoning_effort\":\"max\",\"name\":\"worker-1\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"mock-delegate"},"id":"{{sessionId}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":0,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":0,"index":0,"dt":[],"id":"call-delegate","name":"subagent","args":["{\"description\":\"route probe\",\"prompt\":\"report your route and workspace\",\"provider\":\"mock\",\"model\":\"mock-routed\",\"reasoning_effort\":\"max\",\"name\":\"worker-1\"}"]},{"type":"chunk","time":0,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call-delegate","name":"subagent","arguments":"{\"description\":\"route probe\",\"prompt\":\"report your route and workspace\",\"provider\":\"mock\",\"model\":\"mock-routed\",\"reasoning_effort\":\"max\",\"name\":\"worker-1\"}"}}},{"type":"chunk","time":0,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":0,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"tool/call","seq":15,"time":0,"data":{"turn":1,"step":1,"callId":"call-delegate","name":"subagent","arguments":"{\"description\":\"route probe\",\"prompt\":\"report your route and workspace\",\"provider\":\"mock\",\"model\":\"mock-routed\",\"reasoning_effort\":\"max\",\"name\":\"worker-1\"}"}}}} {"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"subagent/catalog","seq":16,"time":0,"data":{"version":2,"childId":"{{sessionId}}","childCreatedAt":0,"mode":"external","label":"route probe"}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"agent/inbox/spliced","seq":17,"time":0,"data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent {{sessionId}} finished. It cannot receive follow-up messages."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"child route: mock/mock-routed/max/777; cwd: {{cwd}}"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{sessionId}} finished. It cannot receive follow-up messages.","senderSessionId":"{{sessionId}}"},"role":"user","id":"{{sessionId}}"}]}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"tool/result","seq":18,"time":0,"data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call-delegate"},"toolCallId":"call-delegate","content":[{"type":"text","text":"started subagent {{sessionId}}"}],"isError":false,"id":"{{sessionId}}"}},"sourceEventSeqs":[15],"surfaceOp":"append"}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/end","seq":19,"time":0,"data":{"turn":1,"step":1}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"agent/inbox/spliced","seq":20,"time":0,"data":{"target":"next-step","start":0,"removedCount":1,"inserted":[]}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/start","seq":21,"time":0,"data":{"turn":1,"step":2}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"user/message","seq":22,"time":0,"data":{"content":[{"type":"text","text":"Background subagent {{sessionId}} finished. It cannot receive follow-up messages."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"child route: mock/mock-routed/max/777; cwd: {{cwd}}"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{sessionId}} finished. It cannot receive follow-up messages.","senderSessionId":"{{sessionId}}"},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/message","seq":23,"time":0,"data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"text","text":"child reported:\nchild route: mock/mock-routed/max/777; cwd: {{cwd}}"}],"source":{"kind":"model","provider":"deepseek-official","model":"mock-delegate"},"id":"{{sessionId}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":0,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":0,"index":0,"dt":[],"texts":["child reported:\nchild route: mock/mock-routed/max/777; cwd: {{cwd}}"]},{"type":"chunk","time":0,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"child reported:\nchild route: mock/mock-routed/max/777; cwd: {{cwd}}"}}},{"type":"chunk","time":0,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":0,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/end","seq":24,"time":0,"data":{"turn":1,"step":2}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"turn/end","seq":25,"time":0,"data":{"turn":1,"reason":{"kind":"completed"}}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"subagent/named","seq":17,"time":0,"data":{"name":"worker-1","id":"{{sessionId}}"}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"agent/inbox/spliced","seq":18,"time":0,"data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent worker-1 finished. It cannot receive follow-up messages."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"child route: mock/mock-routed/max/777; cwd: {{cwd}}"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 finished. It cannot receive follow-up messages.","senderSessionId":"{{sessionId}}"},"role":"user","id":"{{sessionId}}"}]}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"tool/result","seq":19,"time":0,"data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call-delegate"},"toolCallId":"call-delegate","content":[{"type":"text","text":"started subagent worker-1"}],"isError":false,"id":"{{sessionId}}"}},"sourceEventSeqs":[15],"surfaceOp":"append"}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/end","seq":20,"time":0,"data":{"turn":1,"step":1}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"agent/inbox/spliced","seq":21,"time":0,"data":{"target":"next-step","start":0,"removedCount":1,"inserted":[]}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/start","seq":22,"time":0,"data":{"turn":1,"step":2}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"user/message","seq":23,"time":0,"data":{"content":[{"type":"text","text":"Background subagent worker-1 finished. It cannot receive follow-up messages."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"child route: mock/mock-routed/max/777; cwd: {{cwd}}"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 finished. It cannot receive follow-up messages.","senderSessionId":"{{sessionId}}"},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/message","seq":24,"time":0,"data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"text","text":"child reported:\nchild route: mock/mock-routed/max/777; cwd: {{cwd}}"}],"source":{"kind":"model","provider":"deepseek-official","model":"mock-delegate"},"id":"{{sessionId}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":0,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":0,"index":0,"dt":[],"texts":["child reported:\nchild route: mock/mock-routed/max/777; cwd: {{cwd}}"]},{"type":"chunk","time":0,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"child reported:\nchild route: mock/mock-routed/max/777; cwd: {{cwd}}"}}},{"type":"chunk","time":0,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":0,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/end","seq":25,"time":0,"data":{"turn":1,"step":2}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"turn/end","seq":26,"time":0,"data":{"turn":1,"reason":{"kind":"completed"}}}}} {"method":"session.status","params":{"sessionId":"{{sessionId}}","status":"idle"}} diff --git a/snapshots/sdk/subagent-dsh-sdk-dynamic-route/session.v4.jsonl b/snapshots/sdk/subagent-dsh-sdk-dynamic-route/session.v4.jsonl index 528ef1fcf4..3a14fbf31a 100644 --- a/snapshots/sdk/subagent-dsh-sdk-dynamic-route/session.v4.jsonl +++ b/snapshots/sdk/subagent-dsh-sdk-dynamic-route/session.v4.jsonl @@ -13,15 +13,16 @@ {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"mock-delegate"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"mock-delegate"}} {"type":"session/title","data":{"title":"Delegate once using the requested","messageSeqs":[9],"source":{"kind":"fallback"}}} -{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call-delegate","name":"subagent","arguments":"{\"description\":\"route probe\",\"prompt\":\"report your route and workspace\",\"provider\":\"mock\",\"model\":\"mock-routed\",\"reasoning_effort\":\"max\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"mock-delegate"},"id":"{{message:4}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1789820383205,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1789820383205,"index":0,"dt":[],"id":"call-delegate","name":"subagent","args":["{\"description\":\"route probe\",\"prompt\":\"report your route and workspace\",\"provider\":\"mock\",\"model\":\"mock-routed\",\"reasoning_effort\":\"max\"}"]},{"type":"chunk","time":1789820383205,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call-delegate","name":"subagent","arguments":"{\"description\":\"route probe\",\"prompt\":\"report your route and workspace\",\"provider\":\"mock\",\"model\":\"mock-routed\",\"reasoning_effort\":\"max\"}"}}},{"type":"chunk","time":1789820383205,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1789820383205,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} -{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call-delegate","name":"subagent","arguments":"{\"description\":\"route probe\",\"prompt\":\"report your route and workspace\",\"provider\":\"mock\",\"model\":\"mock-routed\",\"reasoning_effort\":\"max\"}"}} -{"type":"subagent/catalog","data":{"version":2,"childId":"{{id:1}}","childCreatedAt":1789820383554,"mode":"external","label":"route probe"}} -{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent {{id:1}} finished. It cannot receive follow-up messages."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"child route: mock/mock-routed/max/777; cwd: {{cwd}}"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{id:1}} finished. It cannot receive follow-up messages.","senderSessionId":"{{id:1}}"},"role":"user","id":"{{message:5}}"}]}} -{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call-delegate"},"toolCallId":"call-delegate","content":[{"type":"text","text":"started subagent {{id:1}}"}],"isError":false,"id":"{{message:6}}"}},"sourceEventSeqs":[15],"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call-delegate","name":"subagent","arguments":"{\"description\":\"route probe\",\"prompt\":\"report your route and workspace\",\"provider\":\"mock\",\"model\":\"mock-routed\",\"reasoning_effort\":\"max\",\"name\":\"worker-1\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"mock-delegate"},"id":"{{message:4}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1792123811985,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792123811985,"index":0,"dt":[],"id":"call-delegate","name":"subagent","args":["{\"description\":\"route probe\",\"prompt\":\"report your route and workspace\",\"provider\":\"mock\",\"model\":\"mock-routed\",\"reasoning_effort\":\"max\",\"name\":\"worker-1\"}"]},{"type":"chunk","time":1792123811985,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call-delegate","name":"subagent","arguments":"{\"description\":\"route probe\",\"prompt\":\"report your route and workspace\",\"provider\":\"mock\",\"model\":\"mock-routed\",\"reasoning_effort\":\"max\",\"name\":\"worker-1\"}"}}},{"type":"chunk","time":1792123811985,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1792123811985,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call-delegate","name":"subagent","arguments":"{\"description\":\"route probe\",\"prompt\":\"report your route and workspace\",\"provider\":\"mock\",\"model\":\"mock-routed\",\"reasoning_effort\":\"max\",\"name\":\"worker-1\"}"}} +{"type":"subagent/catalog","data":{"version":2,"childId":"{{id:1}}","childCreatedAt":1792123812432,"mode":"external","label":"route probe"}} +{"type":"subagent/named","data":{"name":"worker-1","id":"{{id:1}}"}} +{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent worker-1 finished. It cannot receive follow-up messages."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"child route: mock/mock-routed/max/777; cwd: {{cwd}}"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 finished. It cannot receive follow-up messages.","senderSessionId":"{{id:1}}"},"role":"user","id":"{{message:5}}"}]}} +{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call-delegate"},"toolCallId":"call-delegate","content":[{"type":"text","text":"started subagent worker-1"}],"isError":false,"id":"{{message:6}}"}},"sourceEventSeqs":[15],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":1}} {"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":1,"step":2}} -{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent {{id:1}} finished. It cannot receive follow-up messages."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"child route: mock/mock-routed/max/777; cwd: {{cwd}}"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{id:1}} finished. It cannot receive follow-up messages.","senderSessionId":"{{id:1}}"},"role":"user","id":"{{message:5}}"},"surfaceOp":"append"} -{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"text","text":"child reported:\nchild route: mock/mock-routed/max/777; cwd: {{cwd}}"}],"source":{"kind":"model","provider":"deepseek-official","model":"mock-delegate"},"id":"{{message:7}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1789820383641,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1789820383641,"index":0,"dt":[],"texts":["child reported:\nchild route: mock/mock-routed/max/777; cwd: {{cwd}}"]},{"type":"chunk","time":1789820383641,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"child reported:\nchild route: mock/mock-routed/max/777; cwd: {{cwd}}"}}},{"type":"chunk","time":1789820383641,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1789820383641,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent worker-1 finished. It cannot receive follow-up messages."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"child route: mock/mock-routed/max/777; cwd: {{cwd}}"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 finished. It cannot receive follow-up messages.","senderSessionId":"{{id:1}}"},"role":"user","id":"{{message:5}}"},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"text","text":"child reported:\nchild route: mock/mock-routed/max/777; cwd: {{cwd}}"}],"source":{"kind":"model","provider":"deepseek-official","model":"mock-delegate"},"id":"{{message:7}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1792123812569,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1792123812569,"index":0,"dt":[],"texts":["child reported:\nchild route: mock/mock-routed/max/777; cwd: {{cwd}}"]},{"type":"chunk","time":1792123812569,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"child reported:\nchild route: mock/mock-routed/max/777; cwd: {{cwd}}"}}},{"type":"chunk","time":1792123812569,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1792123812569,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":2}} {"type":"turn/end","data":{"turn":1,"reason":{"kind":"completed"}}} diff --git a/snapshots/sdk/subagent-dsh-sdk-dynamic-route/tool-schemas.1.expected.json b/snapshots/sdk/subagent-dsh-sdk-dynamic-route/tool-schemas.1.expected.json index b546a748a7..99b37246de 100644 --- a/snapshots/sdk/subagent-dsh-sdk-dynamic-route/tool-schemas.1.expected.json +++ b/snapshots/sdk/subagent-dsh-sdk-dynamic-route/tool-schemas.1.expected.json @@ -181,13 +181,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -245,7 +245,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -297,9 +297,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -307,7 +307,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -330,10 +330,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -348,6 +352,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -355,10 +360,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -373,6 +382,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/sdk/subagent-dsh-sdk-dynamic-route/tool-schemas.expected.json b/snapshots/sdk/subagent-dsh-sdk-dynamic-route/tool-schemas.expected.json index d09f364adc..a6183b1f39 100644 --- a/snapshots/sdk/subagent-dsh-sdk-dynamic-route/tool-schemas.expected.json +++ b/snapshots/sdk/subagent-dsh-sdk-dynamic-route/tool-schemas.expected.json @@ -181,13 +181,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -245,7 +245,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -314,9 +314,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -324,7 +324,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -347,10 +347,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The completion notice includes its final answer. This backend does not accept follow-up messages. Child LLM selection is optional. Omit `provider`, `model`, and `reasoning_effort` to use configured child defaults and this provider's route defaults. Supply `provider` and `model` together after using `list_subagent_models` to inspect advertised routes and efforts. Changing the effective route without naming an effort uses the selected model's default effort.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The completion notice includes its final answer. This backend does not accept follow-up messages. Child LLM selection is optional. Omit `provider`, `model`, and `reasoning_effort` to use configured child defaults and this provider's route defaults. Supply `provider` and `model` together after using `list_subagent_models` to inspect advertised routes and efforts. Changing the effective route without naming an effort uses the selected model's default effort.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -377,6 +381,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -384,10 +389,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -402,6 +411,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/sdk/subagent-fork-in-process/session.1.v4.jsonl b/snapshots/sdk/subagent-fork-in-process/session.1.v4.jsonl index 068c476005..f1516da155 100644 --- a/snapshots/sdk/subagent-fork-in-process/session.1.v4.jsonl +++ b/snapshots/sdk/subagent-fork-in-process/session.1.v4.jsonl @@ -20,11 +20,11 @@ {"type":"sandbox/mode","data":{"mode":"danger-full-access","source":"delegation"}} {"type":"approval/policy","data":{"policy":"never","source":"delegation"}} {"type":"permission/preset","data":{"preset":"danger-full-access"}} -{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"What is the project codeword mentioned earlier in this conversation? Reply with exactly that one word and nothing else."},{"type":"text","text":"Your parent agent id is \"{{session:1}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{session:1}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:10}}"}]}} +{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"What is the project codeword mentioned earlier in this conversation? Reply with exactly that one word and nothing else."},{"type":"text","text":"Your name is \"worker-1\". Your parent agent name is \"lead\". Before you finish, send your result to that agent with send_message({ name: \"lead\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:10}}"}]}} {"type":"turn/start","data":{"turn":2}} {"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":2,"step":1}} -{"type":"user/message","data":{"content":[{"type":"text","text":"What is the project codeword mentioned earlier in this conversation? Reply with exactly that one word and nothing else."},{"type":"text","text":"Your parent agent id is \"{{session:1}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{session:1}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:10}}"},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"What is the project codeword mentioned earlier in this conversation? Reply with exactly that one word and nothing else."},{"type":"text","text":"Your name is \"worker-1\". Your parent agent name is \"lead\". Before you finish, send your result to that agent with send_message({ name: \"lead\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:10}}"},"surfaceOp":"append"} {"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations.\n\nApproval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).\n\nDelegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly.\n\nDelegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly.\n\nYou are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations."},{"name":"approval:policy","text":"Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."},{"name":"tool:subagent:depth","text":"Delegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly."},{"name":"tool:subagent_fork:depth","text":"Delegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly."},{"name":"subagent:delegation","text":"You are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}]},"role":"user","id":"{{message:11}}"},"surfaceOp":"append"} {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"resume"}} {"type":"assistant/message","data":{"turn":2,"step":1,"message":{"role":"assistant","content":[{"type":"reasoning","text":"The user asked me to remember the project codeword \"MARMALADE\" and now they're asking what it is. I should just reply with that word."},{"type":"text","text":"MARMALADE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:12}}"},"usage":{"inputTokens":97,"outputTokens":39,"cacheReadTokens":2816,"reasoningTokens":34},"stream":[{"type":"chunk","time":1789819981845,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1789819981845,"index":0,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"texts":["The"," user"," asked"," me"," to"," remember"," the"," project"," cod","ew","ord"," \"","M","ARM","AL","ADE","\""," and"," now"," they","'re"," asking"," what"," it"," is","."," I"," should"," just"," reply"," with"," that"," word","."]},{"type":"chunk","time":1789819981845,"chunk":{"type":"block-start","index":1,"blockType":"text"}},{"type":"text-chunks","time0":1789819981845,"index":1,"dt":[0,0,1],"texts":["M","ARM","AL","ADE"]},{"type":"chunk","time":1789819981846,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The user asked me to remember the project codeword \"MARMALADE\" and now they're asking what it is. I should just reply with that word."}}},{"type":"chunk","time":1789819981846,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"MARMALADE"}}},{"type":"chunk","time":1789819981846,"chunk":{"type":"usage","usage":{"inputTokens":97,"outputTokens":39,"cacheReadTokens":2816,"reasoningTokens":34}}},{"type":"chunk","time":1789819981846,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} diff --git a/snapshots/sdk/subagent-fork-in-process/session.v4.jsonl b/snapshots/sdk/subagent-fork-in-process/session.v4.jsonl index f38325efea..d787cae760 100644 --- a/snapshots/sdk/subagent-fork-in-process/session.v4.jsonl +++ b/snapshots/sdk/subagent-fork-in-process/session.v4.jsonl @@ -12,7 +12,7 @@ {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} {"type":"session/title","data":{"title":"Remember this fact for later:","messageSeqs":[8],"source":{"kind":"fallback"}}} -{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"reasoning","text":"The user wants me to remember the codeword \"MARMALADE\" and reply with just \"OK\"."},{"type":"text","text":"OK"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":2885,"outputTokens":25,"cacheReadTokens":0,"reasoningTokens":23},"stream":[{"type":"chunk","time":1789819981788,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1789819981788,"index":0,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"texts":["The"," user"," wants"," me"," to"," remember"," the"," cod","ew","ord"," \"","M","ARM","AL","ADE","\""," and"," reply"," with"," just"," \"","OK","\"."]},{"type":"chunk","time":1789819981788,"chunk":{"type":"block-start","index":1,"blockType":"text"}},{"type":"text-chunks","time0":1789819981788,"index":1,"dt":[],"texts":["OK"]},{"type":"chunk","time":1789819981788,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The user wants me to remember the codeword \"MARMALADE\" and reply with just \"OK\"."}}},{"type":"chunk","time":1789819981788,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"OK"}}},{"type":"chunk","time":1789819981788,"chunk":{"type":"usage","usage":{"inputTokens":2885,"outputTokens":25,"cacheReadTokens":0,"reasoningTokens":23}}},{"type":"chunk","time":1789819981788,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"reasoning","text":"The user wants me to remember the codeword \"MARMALADE\" and reply with just \"OK\"."},{"type":"text","text":"OK"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":2885,"outputTokens":25,"cacheReadTokens":0,"reasoningTokens":23},"stream":[{"type":"chunk","time":1792123813131,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1792123813131,"index":0,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"texts":["The"," user"," wants"," me"," to"," remember"," the"," cod","ew","ord"," \"","M","ARM","AL","ADE","\""," and"," reply"," with"," just"," \"","OK","\"."]},{"type":"chunk","time":1792123813131,"chunk":{"type":"block-start","index":1,"blockType":"text"}},{"type":"text-chunks","time0":1792123813131,"index":1,"dt":[],"texts":["OK"]},{"type":"chunk","time":1792123813131,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The user wants me to remember the codeword \"MARMALADE\" and reply with just \"OK\"."}}},{"type":"chunk","time":1792123813131,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"OK"}}},{"type":"chunk","time":1792123813131,"chunk":{"type":"usage","usage":{"inputTokens":2885,"outputTokens":25,"cacheReadTokens":0,"reasoningTokens":23}}},{"type":"chunk","time":1792123813131,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":1}} {"type":"turn/end","data":{"turn":1,"reason":{"kind":"completed"}}} {"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Use the subagent_fork tool exactly once to delegate this subtask to a forked child agent: 'What is the project codeword mentioned earlier in this conversation? Reply with exactly that one word and nothing else.' The forked child inherits this conversation, so it can answer. After the subagent returns, reply with the single word PARENT_DONE and stop. Do not use the bash tool."}],"source":{"kind":"user"},"role":"user","id":"{{message:5}}"}]}} @@ -20,15 +20,16 @@ {"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":2,"step":1}} {"type":"user/message","data":{"content":[{"type":"text","text":"Use the subagent_fork tool exactly once to delegate this subtask to a forked child agent: 'What is the project codeword mentioned earlier in this conversation? Reply with exactly that one word and nothing else.' The forked child inherits this conversation, so it can answer. After the subagent returns, reply with the single word PARENT_DONE and stop. Do not use the bash tool."}],"source":{"kind":"user"},"role":"user","id":"{{message:5}}"},"surfaceOp":"append"} -{"type":"assistant/message","data":{"turn":2,"step":1,"message":{"role":"assistant","content":[{"type":"reasoning","text":"The user wants me to use subagent_fork to delegate a question to a child agent. The child agent inherits this conversation and should be able to answer: the project codeword is MARMALADE. After the subagent returns, I should reply with PARENT_DONE."},{"type":"tool-call","id":"call_00_sAtKUseRzHRBvL4CF7XF1334","name":"subagent_fork","arguments":"{\"description\": \"Recall project codeword\", \"prompt\": \"What is the project codeword mentioned earlier in this conversation? Reply with exactly that one word and nothing else.\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:6}}"},"usage":{"inputTokens":158,"outputTokens":147,"cacheReadTokens":2816,"reasoningTokens":59},"stream":[{"type":"chunk","time":1789819981806,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1789819981806,"index":0,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0],"texts":["The"," user"," wants"," me"," to"," use"," sub","agent","_f","ork"," to"," delegate"," a"," question"," to"," a"," child"," agent","."," The"," child"," agent"," inher","its"," this"," conversation"," and"," should"," be"," able"," to"," answer",":"," the"," project"," cod","ew","ord"," is"," MAR","M","AL","ADE","."," After"," the"," sub","agent"," returns",","," I"," should"," reply"," with"," PAR","ENT","_D","ONE","."]},{"type":"chunk","time":1789819981807,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1789819981807,"index":1,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"id":"call_00_sAtKUseRzHRBvL4CF7XF1334","name":"subagent_fork","args":["","{","\"","description","\"",": ","\"","Recall"," project"," cod","ew","ord","\"",", ","\"","prom","pt","\"",": ","\"","What"," is"," the"," project"," cod","ew","ord"," mentioned"," earlier"," in"," this"," conversation","?"," Reply"," with"," exactly"," that"," one"," word"," and"," nothing"," else",".","\"","}"]},{"type":"chunk","time":1789819981807,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The user wants me to use subagent_fork to delegate a question to a child agent. The child agent inherits this conversation and should be able to answer: the project codeword is MARMALADE. After the subagent returns, I should reply with PARENT_DONE."}}},{"type":"chunk","time":1789819981807,"chunk":{"type":"block-end","index":1,"block":{"type":"tool-call","id":"call_00_sAtKUseRzHRBvL4CF7XF1334","name":"subagent_fork","arguments":"{\"description\": \"Recall project codeword\", \"prompt\": \"What is the project codeword mentioned earlier in this conversation? Reply with exactly that one word and nothing else.\"}"}}},{"type":"chunk","time":1789819981807,"chunk":{"type":"usage","usage":{"inputTokens":158,"outputTokens":147,"cacheReadTokens":2816,"reasoningTokens":59}}},{"type":"chunk","time":1789819981807,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} -{"type":"tool/call","data":{"turn":2,"step":1,"callId":"call_00_sAtKUseRzHRBvL4CF7XF1334","name":"subagent_fork","arguments":"{\"description\": \"Recall project codeword\", \"prompt\": \"What is the project codeword mentioned earlier in this conversation? Reply with exactly that one word and nothing else.\"}"}} +{"type":"assistant/message","data":{"turn":2,"step":1,"message":{"role":"assistant","content":[{"type":"reasoning","text":"The user wants me to use subagent_fork to delegate a question to a child agent. The child agent inherits this conversation and should be able to answer: the project codeword is MARMALADE. After the subagent returns, I should reply with PARENT_DONE."},{"type":"tool-call","id":"call_00_sAtKUseRzHRBvL4CF7XF1334","name":"subagent_fork","arguments":"{\"description\":\"Recall project codeword\",\"prompt\":\"What is the project codeword mentioned earlier in this conversation? Reply with exactly that one word and nothing else.\",\"name\":\"worker-1\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:6}}"},"usage":{"inputTokens":158,"outputTokens":147,"cacheReadTokens":2816,"reasoningTokens":59},"stream":[{"type":"chunk","time":1792123813150,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1792123813150,"index":0,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"texts":["The"," user"," wants"," me"," to"," use"," sub","agent","_f","ork"," to"," delegate"," a"," question"," to"," a"," child"," agent","."," The"," child"," agent"," inher","its"," this"," conversation"," and"," should"," be"," able"," to"," answer",":"," the"," project"," cod","ew","ord"," is"," MAR","M","AL","ADE","."," After"," the"," sub","agent"," returns",","," I"," should"," reply"," with"," PAR","ENT","_D","ONE","."]},{"type":"chunk","time":1792123813150,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792123813150,"index":1,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"id":"call_00_sAtKUseRzHRBvL4CF7XF1334","name":"subagent_fork","args":["{\"description\":\"Recall project codeword\",\"prompt\":\"What is the project codeword mentioned earlier in this conversation? Reply with exactly that one word and nothing else.\",\"name\":\"worker-1\"}","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""]},{"type":"chunk","time":1792123813150,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The user wants me to use subagent_fork to delegate a question to a child agent. The child agent inherits this conversation and should be able to answer: the project codeword is MARMALADE. After the subagent returns, I should reply with PARENT_DONE."}}},{"type":"chunk","time":1792123813150,"chunk":{"type":"block-end","index":1,"block":{"type":"tool-call","id":"call_00_sAtKUseRzHRBvL4CF7XF1334","name":"subagent_fork","arguments":"{\"description\":\"Recall project codeword\",\"prompt\":\"What is the project codeword mentioned earlier in this conversation? Reply with exactly that one word and nothing else.\",\"name\":\"worker-1\"}"}}},{"type":"chunk","time":1792123813150,"chunk":{"type":"usage","usage":{"inputTokens":158,"outputTokens":147,"cacheReadTokens":2816,"reasoningTokens":59}}},{"type":"chunk","time":1792123813150,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":2,"step":1,"callId":"call_00_sAtKUseRzHRBvL4CF7XF1334","name":"subagent_fork","arguments":"{\"description\":\"Recall project codeword\",\"prompt\":\"What is the project codeword mentioned earlier in this conversation? Reply with exactly that one word and nothing else.\",\"name\":\"worker-1\"}"}} {"type":"subagent/catalog","data":{"version":0,"childId":"{{session:2}}","childCreatedAt":1783352137161,"mode":"continuable","label":"Recall project codeword"}} -{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent {{session:2}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"MARMALADE"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{session:2}} finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:7}}"}]}} -{"type":"tool/result","data":{"turn":2,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_00_sAtKUseRzHRBvL4CF7XF1334"},"toolCallId":"call_00_sAtKUseRzHRBvL4CF7XF1334","content":[{"type":"text","text":"started subagent {{session:2}}"}],"isError":false,"id":"{{message:8}}"}},"sourceEventSeqs":[22],"surfaceOp":"append"} +{"type":"subagent/named","data":{"name":"worker-1","id":"{{session:2}}"}} +{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent worker-1 finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"MARMALADE"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:7}}"}]}} +{"type":"tool/result","data":{"turn":2,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_00_sAtKUseRzHRBvL4CF7XF1334"},"toolCallId":"call_00_sAtKUseRzHRBvL4CF7XF1334","content":[{"type":"text","text":"started subagent worker-1"}],"isError":false,"id":"{{message:8}}"}},"sourceEventSeqs":[22],"surfaceOp":"append"} {"type":"step/end","data":{"turn":2,"step":1}} {"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":2,"step":2}} -{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent {{session:2}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"MARMALADE"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{session:2}} finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:7}}"},"surfaceOp":"append"} -{"type":"assistant/message","data":{"turn":2,"step":2,"message":{"role":"assistant","content":[{"type":"reasoning","text":"The forked child agent correctly returned \"MARMALADE\". Now I need to reply with \"PARENT_DONE\"."},{"type":"text","text":"PARENT_DONE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:9}}"},"usage":{"inputTokens":65,"outputTokens":30,"cacheReadTokens":3072,"reasoningTokens":25},"stream":[{"type":"chunk","time":1789819981865,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1789819981865,"index":0,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"texts":["The"," for","ked"," child"," agent"," correctly"," returned"," \"","M","ARM","AL","ADE","\"."," Now"," I"," need"," to"," reply"," with"," \"","PAR","ENT","_D","ONE","\"."]},{"type":"chunk","time":1789819981865,"chunk":{"type":"block-start","index":1,"blockType":"text"}},{"type":"text-chunks","time0":1789819981865,"index":1,"dt":[0,0,0],"texts":["PAR","ENT","_D","ONE"]},{"type":"chunk","time":1789819981865,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The forked child agent correctly returned \"MARMALADE\". Now I need to reply with \"PARENT_DONE\"."}}},{"type":"chunk","time":1789819981865,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"PARENT_DONE"}}},{"type":"chunk","time":1789819981865,"chunk":{"type":"usage","usage":{"inputTokens":65,"outputTokens":30,"cacheReadTokens":3072,"reasoningTokens":25}}},{"type":"chunk","time":1789819981865,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent worker-1 finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"MARMALADE"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:7}}"},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":2,"step":2,"message":{"role":"assistant","content":[{"type":"reasoning","text":"The forked child agent correctly returned \"MARMALADE\". Now I need to reply with \"PARENT_DONE\"."},{"type":"text","text":"PARENT_DONE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:9}}"},"usage":{"inputTokens":65,"outputTokens":30,"cacheReadTokens":3072,"reasoningTokens":25},"stream":[{"type":"chunk","time":1792123813211,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1792123813211,"index":0,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"texts":["The"," for","ked"," child"," agent"," correctly"," returned"," \"","M","ARM","AL","ADE","\"."," Now"," I"," need"," to"," reply"," with"," \"","PAR","ENT","_D","ONE","\"."]},{"type":"chunk","time":1792123813211,"chunk":{"type":"block-start","index":1,"blockType":"text"}},{"type":"text-chunks","time0":1792123813211,"index":1,"dt":[0,0,0],"texts":["PAR","ENT","_D","ONE"]},{"type":"chunk","time":1792123813211,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The forked child agent correctly returned \"MARMALADE\". Now I need to reply with \"PARENT_DONE\"."}}},{"type":"chunk","time":1792123813211,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"PARENT_DONE"}}},{"type":"chunk","time":1792123813211,"chunk":{"type":"usage","usage":{"inputTokens":65,"outputTokens":30,"cacheReadTokens":3072,"reasoningTokens":25}}},{"type":"chunk","time":1792123813211,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":2,"step":2}} {"type":"turn/end","data":{"turn":2,"reason":{"kind":"completed"}}} diff --git a/snapshots/sdk/subagent-list-agents/session.1.v4.jsonl b/snapshots/sdk/subagent-list-agents/session.1.v4.jsonl index 65c8f479ef..2f39d4b5ab 100644 --- a/snapshots/sdk/subagent-list-agents/session.1.v4.jsonl +++ b/snapshots/sdk/subagent-list-agents/session.1.v4.jsonl @@ -3,12 +3,12 @@ {"type":"sandbox/mode","data":{"mode":"danger-full-access","source":"delegation"}} {"type":"approval/policy","data":{"policy":"never","source":"delegation"}} {"type":"permission/preset","data":{"preset":"danger-full-access"}} -{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Reply with exactly the word CHILD_OK and nothing else."},{"type":"text","text":"Your parent agent id is \"{{session:1}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{session:1}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:13}}"}]}} +{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Reply with exactly the word CHILD_OK and nothing else."},{"type":"text","text":"Your name is \"worker-1\". Your parent agent name is \"lead\". Before you finish, send your result to that agent with send_message({ name: \"lead\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:13}}"}]}} {"type":"turn/start","data":{"turn":1}} {"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":1,"step":1}} {"type":"system/message","data":{"turn":1,"step":1,"message":{"role":"system","content":[{"type":"text","text":"{{system}}"}],"source":{"kind":"system-prompt"},"id":"{{message:14}}"}},"surfaceOp":"append"} -{"type":"user/message","data":{"content":[{"type":"text","text":"Reply with exactly the word CHILD_OK and nothing else."},{"type":"text","text":"Your parent agent id is \"{{session:1}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{session:1}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:13}}"},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Reply with exactly the word CHILD_OK and nothing else."},{"type":"text","text":"Your name is \"worker-1\". Your parent agent name is \"lead\". Before you finish, send your result to that agent with send_message({ name: \"lead\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:13}}"},"surfaceOp":"append"} {"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations.\n\nApproval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).\n\nDelegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly.\n\nDelegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly.\n\nYou are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations."},{"name":"approval:policy","text":"Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."},{"name":"tool:subagent:depth","text":"Delegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly."},{"name":"tool:subagent_fork:depth","text":"Delegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly."},{"name":"subagent:delegation","text":"You are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}]},"role":"user","id":"{{message:15}}"},"surfaceOp":"append"} {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} diff --git a/snapshots/sdk/subagent-list-agents/session.v4.jsonl b/snapshots/sdk/subagent-list-agents/session.v4.jsonl index fad282a574..9246b00912 100644 --- a/snapshots/sdk/subagent-list-agents/session.v4.jsonl +++ b/snapshots/sdk/subagent-list-agents/session.v4.jsonl @@ -12,21 +12,22 @@ {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} {"type":"session/title","data":{"title":"Call the subagent tool once","messageSeqs":[8],"source":{"kind":"fallback"}}} -{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_bg_start","name":"subagent","arguments":"{\"description\": \"Reply with CHILD_OK\", \"prompt\": \"Reply with exactly the word CHILD_OK and nothing else.\", \"run_in_background\": true}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1788880389574,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1788880389574,"index":0,"dt":[],"id":"call_bg_start","name":"subagent","args":["{\"description\": \"Reply with CHILD_OK\", \"prompt\": \"Reply with exactly the word CHILD_OK and nothing else.\", \"run_in_background\": true}"]},{"type":"chunk","time":1788880389574,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_bg_start","name":"subagent","arguments":"{\"description\": \"Reply with CHILD_OK\", \"prompt\": \"Reply with exactly the word CHILD_OK and nothing else.\", \"run_in_background\": true}"}}},{"type":"chunk","time":1788880389574,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1788880389574,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} -{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_bg_start","name":"subagent","arguments":"{\"description\": \"Reply with CHILD_OK\", \"prompt\": \"Reply with exactly the word CHILD_OK and nothing else.\", \"run_in_background\": true}"}} +{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_bg_start","name":"subagent","arguments":"{\"description\":\"Reply with CHILD_OK\",\"prompt\":\"Reply with exactly the word CHILD_OK and nothing else.\",\"run_in_background\":true,\"name\":\"worker-1\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1792123813741,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792123813741,"index":0,"dt":[],"id":"call_bg_start","name":"subagent","args":["{\"description\":\"Reply with CHILD_OK\",\"prompt\":\"Reply with exactly the word CHILD_OK and nothing else.\",\"run_in_background\":true,\"name\":\"worker-1\"}"]},{"type":"chunk","time":1792123813742,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_bg_start","name":"subagent","arguments":"{\"description\":\"Reply with CHILD_OK\",\"prompt\":\"Reply with exactly the word CHILD_OK and nothing else.\",\"run_in_background\":true,\"name\":\"worker-1\"}"}}},{"type":"chunk","time":1792123813742,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1792123813742,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_bg_start","name":"subagent","arguments":"{\"description\":\"Reply with CHILD_OK\",\"prompt\":\"Reply with exactly the word CHILD_OK and nothing else.\",\"run_in_background\":true,\"name\":\"worker-1\"}"}} {"type":"subagent/catalog","data":{"version":0,"childId":"{{session:2}}","childCreatedAt":1789000001000,"mode":"continuable","label":"Reply with CHILD_OK"}} -{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_bg_start"},"toolCallId":"call_bg_start","content":[{"type":"text","text":"started subagent {{session:2}}"}],"isError":false,"id":"{{message:5}}"}},"sourceEventSeqs":[14],"surfaceOp":"append"} +{"type":"subagent/named","data":{"name":"worker-1","id":"{{session:2}}"}} +{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_bg_start"},"toolCallId":"call_bg_start","content":[{"type":"text","text":"started subagent worker-1"}],"isError":false,"id":"{{message:5}}"}},"sourceEventSeqs":[14],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":1}} {"type":"step/start","data":{"turn":1,"step":2}} -{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"text","text":"STARTED"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:6}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1788880389609,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1788880389609,"index":0,"dt":[],"texts":["STARTED"]},{"type":"chunk","time":1788880389609,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"STARTED"}}},{"type":"chunk","time":1788880389609,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1788880389609,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"text","text":"STARTED"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:6}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1792123813796,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1792123813796,"index":0,"dt":[],"texts":["STARTED"]},{"type":"chunk","time":1792123813796,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"STARTED"}}},{"type":"chunk","time":1792123813796,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1792123813796,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":2}} {"type":"turn/end","data":{"turn":1,"reason":{"kind":"completed"}}} -{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent {{session:2}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"CHILD_OK"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{session:2}} finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:7}}"}]}} +{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent worker-1 finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"CHILD_OK"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:7}}"}]}} {"type":"turn/start","data":{"turn":2}} {"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":2,"step":1}} -{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent {{session:2}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"CHILD_OK"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{session:2}} finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:7}}"},"surfaceOp":"append"} -{"type":"assistant/message","data":{"turn":2,"step":1,"message":{"role":"assistant","content":[{"type":"text","text":"SUBAGENT_SETTLED_NOTED"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:8}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1788880389644,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1788880389644,"index":0,"dt":[],"texts":["SUBAGENT_SETTLED_NOTED"]},{"type":"chunk","time":1788880389644,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"SUBAGENT_SETTLED_NOTED"}}},{"type":"chunk","time":1788880389644,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1788880389644,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent worker-1 finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"CHILD_OK"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:7}}"},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":2,"step":1,"message":{"role":"assistant","content":[{"type":"text","text":"SUBAGENT_SETTLED_NOTED"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:8}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1792123813820,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1792123813820,"index":0,"dt":[],"texts":["SUBAGENT_SETTLED_NOTED"]},{"type":"chunk","time":1792123813820,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"SUBAGENT_SETTLED_NOTED"}}},{"type":"chunk","time":1792123813820,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1792123813820,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":2,"step":1}} {"type":"turn/end","data":{"turn":2,"reason":{"kind":"completed"}}} {"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Call list_agents once and observe the subagent you started. Then call interrupt_agent once with agent_id set to {{session:2}}. Then reply with the single word DONE. Do not call any other tool."}],"source":{"kind":"user"},"role":"user","id":"{{message:9}}"}]}} @@ -34,11 +35,11 @@ {"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":3,"step":1}} {"type":"user/message","data":{"content":[{"type":"text","text":"Call list_agents once and observe the subagent you started. Then call interrupt_agent once with agent_id set to {{session:2}}. Then reply with the single word DONE. Do not call any other tool."}],"source":{"kind":"user"},"role":"user","id":"{{message:9}}"},"surfaceOp":"append"} -{"type":"assistant/message","data":{"turn":3,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_list","name":"list_agents","arguments":"{}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:10}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1788880389662,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1788880389662,"index":0,"dt":[],"id":"call_list","name":"list_agents","args":["{}"]},{"type":"chunk","time":1788880389662,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_list","name":"list_agents","arguments":"{}"}}},{"type":"chunk","time":1788880389662,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1788880389662,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":3,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_list","name":"list_agents","arguments":"{}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:10}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1792123813841,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792123813841,"index":0,"dt":[],"id":"call_list","name":"list_agents","args":["{}"]},{"type":"chunk","time":1792123813841,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_list","name":"list_agents","arguments":"{}"}}},{"type":"chunk","time":1792123813841,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1792123813841,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} {"type":"tool/call","data":{"turn":3,"step":1,"callId":"call_list","name":"list_agents","arguments":"{}"}} -{"type":"tool/result","data":{"turn":3,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_list"},"toolCallId":"call_list","content":[{"type":"text","text":"{{session:2}} [inactive] parent={{session:1}} depth=1 — Reply with CHILD_OK"}],"isError":false,"id":"{{message:11}}"}},"sourceEventSeqs":[36],"surfaceOp":"append"} +{"type":"tool/result","data":{"turn":3,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_list"},"toolCallId":"call_list","content":[{"type":"text","text":"worker-1 [inactive] parent=lead depth=1 — Reply with CHILD_OK"}],"isError":false,"id":"{{message:11}}"}},"sourceEventSeqs":[37],"surfaceOp":"append"} {"type":"step/end","data":{"turn":3,"step":1}} {"type":"step/start","data":{"turn":3,"step":2}} -{"type":"assistant/message","data":{"turn":3,"step":2,"message":{"role":"assistant","content":[{"type":"text","text":"DONE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:12}}"},"usage":{"inputTokens":10,"outputTokens":2},"stream":[{"type":"chunk","time":1788880389684,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1788880389684,"index":0,"dt":[],"texts":["DONE"]},{"type":"chunk","time":1788880389684,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"DONE"}}},{"type":"chunk","time":1788880389684,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":2}}},{"type":"chunk","time":1788880389684,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":3,"step":2,"message":{"role":"assistant","content":[{"type":"text","text":"DONE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:12}}"},"usage":{"inputTokens":10,"outputTokens":2},"stream":[{"type":"chunk","time":1792123813869,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1792123813869,"index":0,"dt":[],"texts":["DONE"]},{"type":"chunk","time":1792123813869,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"DONE"}}},{"type":"chunk","time":1792123813869,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":2}}},{"type":"chunk","time":1792123813869,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":3,"step":2}} {"type":"turn/end","data":{"turn":3,"reason":{"kind":"completed"}}} diff --git a/snapshots/sdk/subagent-list-agents/tool-schemas.1.expected.json b/snapshots/sdk/subagent-list-agents/tool-schemas.1.expected.json index b546a748a7..99b37246de 100644 --- a/snapshots/sdk/subagent-list-agents/tool-schemas.1.expected.json +++ b/snapshots/sdk/subagent-list-agents/tool-schemas.1.expected.json @@ -181,13 +181,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -245,7 +245,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -297,9 +297,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -307,7 +307,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -330,10 +330,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -348,6 +352,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -355,10 +360,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -373,6 +382,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/sdk/subagent-mixed/session.1.v4.jsonl b/snapshots/sdk/subagent-mixed/session.1.v4.jsonl index 81be13ecd2..ae745626d6 100644 --- a/snapshots/sdk/subagent-mixed/session.1.v4.jsonl +++ b/snapshots/sdk/subagent-mixed/session.1.v4.jsonl @@ -3,12 +3,12 @@ {"type":"sandbox/mode","data":{"mode":"danger-full-access","source":"delegation"}} {"type":"approval/policy","data":{"policy":"never","source":"delegation"}} {"type":"permission/preset","data":{"preset":"danger-full-access"}} -{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Reply with exactly the word ALPHA and nothing else."},{"type":"text","text":"Your parent agent id is \"{{session:1}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{session:1}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:13}}"}]}} +{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Reply with exactly the word ALPHA and nothing else."},{"type":"text","text":"Your name is \"worker-1\". Your parent agent name is \"lead\". Before you finish, send your result to that agent with send_message({ name: \"lead\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:13}}"}]}} {"type":"turn/start","data":{"turn":1}} {"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":1,"step":1}} {"type":"system/message","data":{"turn":1,"step":1,"message":{"role":"system","content":[{"type":"text","text":"{{system}}"}],"source":{"kind":"system-prompt"},"id":"{{message:14}}"}},"surfaceOp":"append"} -{"type":"user/message","data":{"content":[{"type":"text","text":"Reply with exactly the word ALPHA and nothing else."},{"type":"text","text":"Your parent agent id is \"{{session:1}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{session:1}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:13}}"},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Reply with exactly the word ALPHA and nothing else."},{"type":"text","text":"Your name is \"worker-1\". Your parent agent name is \"lead\". Before you finish, send your result to that agent with send_message({ name: \"lead\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:13}}"},"surfaceOp":"append"} {"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations.\n\nApproval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).\n\nDelegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly.\n\nDelegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly.\n\nYou are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations."},{"name":"approval:policy","text":"Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."},{"name":"tool:subagent:depth","text":"Delegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly."},{"name":"tool:subagent_fork:depth","text":"Delegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly."},{"name":"subagent:delegation","text":"You are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}]},"role":"user","id":"{{message:15}}"},"surfaceOp":"append"} {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} diff --git a/snapshots/sdk/subagent-mixed/session.2.v4.jsonl b/snapshots/sdk/subagent-mixed/session.2.v4.jsonl index 1755265bef..6f7cc08db5 100644 --- a/snapshots/sdk/subagent-mixed/session.2.v4.jsonl +++ b/snapshots/sdk/subagent-mixed/session.2.v4.jsonl @@ -20,11 +20,11 @@ {"type":"sandbox/mode","data":{"mode":"danger-full-access","source":"delegation"}} {"type":"approval/policy","data":{"policy":"never","source":"delegation"}} {"type":"permission/preset","data":{"preset":"danger-full-access"}} -{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"What is the project codeword mentioned earlier in this conversation? Reply with exactly that one word and nothing else."},{"type":"text","text":"Your parent agent id is \"{{session:1}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{session:1}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:17}}"}]}} +{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"What is the project codeword mentioned earlier in this conversation? Reply with exactly that one word and nothing else."},{"type":"text","text":"Your name is \"worker-2\". Your parent agent name is \"lead\". Before you finish, send your result to that agent with send_message({ name: \"lead\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:17}}"}]}} {"type":"turn/start","data":{"turn":2}} {"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":2,"step":1}} -{"type":"user/message","data":{"content":[{"type":"text","text":"What is the project codeword mentioned earlier in this conversation? Reply with exactly that one word and nothing else."},{"type":"text","text":"Your parent agent id is \"{{session:1}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{session:1}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:17}}"},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"What is the project codeword mentioned earlier in this conversation? Reply with exactly that one word and nothing else."},{"type":"text","text":"Your name is \"worker-2\". Your parent agent name is \"lead\". Before you finish, send your result to that agent with send_message({ name: \"lead\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:17}}"},"surfaceOp":"append"} {"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations.\n\nApproval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).\n\nDelegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly.\n\nDelegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly.\n\nYou are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations."},{"name":"approval:policy","text":"Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."},{"name":"tool:subagent:depth","text":"Delegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly."},{"name":"tool:subagent_fork:depth","text":"Delegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly."},{"name":"subagent:delegation","text":"You are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}]},"role":"user","id":"{{message:18}}"},"surfaceOp":"append"} {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"resume"}} {"type":"assistant/message","data":{"turn":2,"step":1,"message":{"role":"assistant","content":[{"type":"reasoning","text":"The user is asking me to recall the project codeword that was mentioned earlier in the conversation. I was told to remember it: SAFFRON."},{"type":"text","text":"SAFFRON"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:19}}"},"usage":{"inputTokens":95,"outputTokens":35,"cacheReadTokens":2816,"reasoningTokens":31},"stream":[{"type":"chunk","time":1789819983005,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1789819983005,"index":0,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0],"texts":["The"," user"," is"," asking"," me"," to"," recall"," the"," project"," cod","ew","ord"," that"," was"," mentioned"," earlier"," in"," the"," conversation","."," I"," was"," told"," to"," remember"," it",":"," SA","FF","RON","."]},{"type":"chunk","time":1789819983006,"chunk":{"type":"block-start","index":1,"blockType":"text"}},{"type":"text-chunks","time0":1789819983006,"index":1,"dt":[0,0],"texts":["SA","FF","RON"]},{"type":"chunk","time":1789819983006,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The user is asking me to recall the project codeword that was mentioned earlier in the conversation. I was told to remember it: SAFFRON."}}},{"type":"chunk","time":1789819983006,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"SAFFRON"}}},{"type":"chunk","time":1789819983006,"chunk":{"type":"usage","usage":{"inputTokens":95,"outputTokens":35,"cacheReadTokens":2816,"reasoningTokens":31}}},{"type":"chunk","time":1789819983006,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} diff --git a/snapshots/sdk/subagent-mixed/session.v4.jsonl b/snapshots/sdk/subagent-mixed/session.v4.jsonl index 513984e0aa..3136d321c2 100644 --- a/snapshots/sdk/subagent-mixed/session.v4.jsonl +++ b/snapshots/sdk/subagent-mixed/session.v4.jsonl @@ -12,7 +12,7 @@ {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} {"type":"session/title","data":{"title":"Remember this fact for later:","messageSeqs":[8],"source":{"kind":"fallback"}}} -{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"reasoning","text":"The user wants me to remember a codeword and just reply with \"OK\"."},{"type":"text","text":"OK"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":2883,"outputTokens":19,"cacheReadTokens":0,"reasoningTokens":17},"stream":[{"type":"chunk","time":1789819982880,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1789819982880,"index":0,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"texts":["The"," user"," wants"," me"," to"," remember"," a"," cod","ew","ord"," and"," just"," reply"," with"," \"","OK","\"."]},{"type":"chunk","time":1789819982880,"chunk":{"type":"block-start","index":1,"blockType":"text"}},{"type":"text-chunks","time0":1789819982880,"index":1,"dt":[],"texts":["OK"]},{"type":"chunk","time":1789819982880,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The user wants me to remember a codeword and just reply with \"OK\"."}}},{"type":"chunk","time":1789819982880,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"OK"}}},{"type":"chunk","time":1789819982880,"chunk":{"type":"usage","usage":{"inputTokens":2883,"outputTokens":19,"cacheReadTokens":0,"reasoningTokens":17}}},{"type":"chunk","time":1789819982880,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"reasoning","text":"The user wants me to remember a codeword and just reply with \"OK\"."},{"type":"text","text":"OK"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":2883,"outputTokens":19,"cacheReadTokens":0,"reasoningTokens":17},"stream":[{"type":"chunk","time":1792123814420,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1792123814420,"index":0,"dt":[0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0],"texts":["The"," user"," wants"," me"," to"," remember"," a"," cod","ew","ord"," and"," just"," reply"," with"," \"","OK","\"."]},{"type":"chunk","time":1792123814421,"chunk":{"type":"block-start","index":1,"blockType":"text"}},{"type":"text-chunks","time0":1792123814421,"index":1,"dt":[],"texts":["OK"]},{"type":"chunk","time":1792123814421,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The user wants me to remember a codeword and just reply with \"OK\"."}}},{"type":"chunk","time":1792123814421,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"OK"}}},{"type":"chunk","time":1792123814421,"chunk":{"type":"usage","usage":{"inputTokens":2883,"outputTokens":19,"cacheReadTokens":0,"reasoningTokens":17}}},{"type":"chunk","time":1792123814421,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":1}} {"type":"turn/end","data":{"turn":1,"reason":{"kind":"completed"}}} {"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Do these two delegations, once at a time. First, use the subagent tool (fresh child) exactly once: 'Reply with exactly the word ALPHA and nothing else.' Then, after it returns, use the subagent_fork tool (forked child that inherits this conversation) exactly once: 'What is the project codeword mentioned earlier in this conversation? Reply with exactly that one word and nothing else.' After both subagents return, reply with the single word PARENT_DONE and stop. Do not use the bash tool."}],"source":{"kind":"user"},"role":"user","id":"{{message:5}}"}]}} @@ -20,24 +20,26 @@ {"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":2,"step":1}} {"type":"user/message","data":{"content":[{"type":"text","text":"Do these two delegations, once at a time. First, use the subagent tool (fresh child) exactly once: 'Reply with exactly the word ALPHA and nothing else.' Then, after it returns, use the subagent_fork tool (forked child that inherits this conversation) exactly once: 'What is the project codeword mentioned earlier in this conversation? Reply with exactly that one word and nothing else.' After both subagents return, reply with the single word PARENT_DONE and stop. Do not use the bash tool."}],"source":{"kind":"user"},"role":"user","id":"{{message:5}}"},"surfaceOp":"append"} -{"type":"assistant/message","data":{"turn":2,"step":1,"message":{"role":"assistant","content":[{"type":"reasoning","text":"Let me do these two delegations one at a time as requested.\n\nFirst, I'll use the subagent tool (fresh child) to reply with \"ALPHA\"."},{"type":"tool-call","id":"call_00_YvHr2bGomk5HhpgDTvE81896","name":"subagent","arguments":"{\"description\": \"Reply ALPHA only\", \"prompt\": \"Reply with exactly the word ALPHA and nothing else.\", \"run_in_background\":false}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:6}}"},"usage":{"inputTokens":185,"outputTokens":110,"cacheReadTokens":2816,"reasoningTokens":35},"stream":[{"type":"chunk","time":1789819982900,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1789819982900,"index":0,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"texts":["Let"," me"," do"," these"," two"," deleg","ations"," one"," at"," a"," time"," as"," requested",".\n\n","First",","," I","'ll"," use"," the"," sub","agent"," tool"," (","fresh"," child",")"," to"," reply"," with"," \"","AL","P","HA","\"."]},{"type":"chunk","time":1789819982900,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1789819982900,"index":1,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"id":"call_00_YvHr2bGomk5HhpgDTvE81896","name":"subagent","args":["","{","\"","description","\"",": ","\"","Reply"," AL","P","HA"," only","\"",", ","\"","prom","pt","\"",": ","\"","Reply"," with"," exactly"," the"," word"," AL","P","HA"," and"," nothing"," else",".","\"",", \"run_in_background\":false}"]},{"type":"chunk","time":1789819982900,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"Let me do these two delegations one at a time as requested.\n\nFirst, I'll use the subagent tool (fresh child) to reply with \"ALPHA\"."}}},{"type":"chunk","time":1789819982900,"chunk":{"type":"block-end","index":1,"block":{"type":"tool-call","id":"call_00_YvHr2bGomk5HhpgDTvE81896","name":"subagent","arguments":"{\"description\": \"Reply ALPHA only\", \"prompt\": \"Reply with exactly the word ALPHA and nothing else.\", \"run_in_background\":false}"}}},{"type":"chunk","time":1789819982900,"chunk":{"type":"usage","usage":{"inputTokens":185,"outputTokens":110,"cacheReadTokens":2816,"reasoningTokens":35}}},{"type":"chunk","time":1789819982900,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} -{"type":"tool/call","data":{"turn":2,"step":1,"callId":"call_00_YvHr2bGomk5HhpgDTvE81896","name":"subagent","arguments":"{\"description\": \"Reply ALPHA only\", \"prompt\": \"Reply with exactly the word ALPHA and nothing else.\", \"run_in_background\":false}"}} +{"type":"assistant/message","data":{"turn":2,"step":1,"message":{"role":"assistant","content":[{"type":"reasoning","text":"Let me do these two delegations one at a time as requested.\n\nFirst, I'll use the subagent tool (fresh child) to reply with \"ALPHA\"."},{"type":"tool-call","id":"call_00_YvHr2bGomk5HhpgDTvE81896","name":"subagent","arguments":"{\"description\":\"Reply ALPHA only\",\"prompt\":\"Reply with exactly the word ALPHA and nothing else.\",\"run_in_background\":false,\"name\":\"worker-1\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:6}}"},"usage":{"inputTokens":185,"outputTokens":110,"cacheReadTokens":2816,"reasoningTokens":35},"stream":[{"type":"chunk","time":1792123814440,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1792123814440,"index":0,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"texts":["Let"," me"," do"," these"," two"," deleg","ations"," one"," at"," a"," time"," as"," requested",".\n\n","First",","," I","'ll"," use"," the"," sub","agent"," tool"," (","fresh"," child",")"," to"," reply"," with"," \"","AL","P","HA","\"."]},{"type":"chunk","time":1792123814440,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792123814440,"index":1,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"id":"call_00_YvHr2bGomk5HhpgDTvE81896","name":"subagent","args":["{\"description\":\"Reply ALPHA only\",\"prompt\":\"Reply with exactly the word ALPHA and nothing else.\",\"run_in_background\":false,\"name\":\"worker-1\"}","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""]},{"type":"chunk","time":1792123814440,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"Let me do these two delegations one at a time as requested.\n\nFirst, I'll use the subagent tool (fresh child) to reply with \"ALPHA\"."}}},{"type":"chunk","time":1792123814440,"chunk":{"type":"block-end","index":1,"block":{"type":"tool-call","id":"call_00_YvHr2bGomk5HhpgDTvE81896","name":"subagent","arguments":"{\"description\":\"Reply ALPHA only\",\"prompt\":\"Reply with exactly the word ALPHA and nothing else.\",\"run_in_background\":false,\"name\":\"worker-1\"}"}}},{"type":"chunk","time":1792123814440,"chunk":{"type":"usage","usage":{"inputTokens":185,"outputTokens":110,"cacheReadTokens":2816,"reasoningTokens":35}}},{"type":"chunk","time":1792123814440,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":2,"step":1,"callId":"call_00_YvHr2bGomk5HhpgDTvE81896","name":"subagent","arguments":"{\"description\":\"Reply ALPHA only\",\"prompt\":\"Reply with exactly the word ALPHA and nothing else.\",\"run_in_background\":false,\"name\":\"worker-1\"}"}} {"type":"subagent/catalog","data":{"version":0,"childId":"{{session:2}}","childCreatedAt":1783352145223,"mode":"continuable","label":"Reply ALPHA only"}} -{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent {{session:2}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"ALPHA"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{session:2}} finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:7}}"}]}} -{"type":"tool/result","data":{"turn":2,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_00_YvHr2bGomk5HhpgDTvE81896"},"toolCallId":"call_00_YvHr2bGomk5HhpgDTvE81896","content":[{"type":"text","text":"started subagent {{session:2}}"}],"isError":false,"id":"{{message:8}}"}},"sourceEventSeqs":[22],"surfaceOp":"append"} +{"type":"subagent/named","data":{"name":"worker-1","id":"{{session:2}}"}} +{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent worker-1 finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"ALPHA"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:7}}"}]}} +{"type":"tool/result","data":{"turn":2,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_00_YvHr2bGomk5HhpgDTvE81896"},"toolCallId":"call_00_YvHr2bGomk5HhpgDTvE81896","content":[{"type":"text","text":"started subagent worker-1"}],"isError":false,"id":"{{message:8}}"}},"sourceEventSeqs":[22],"surfaceOp":"append"} {"type":"step/end","data":{"turn":2,"step":1}} {"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":2,"step":2}} -{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent {{session:2}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"ALPHA"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{session:2}} finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:7}}"},"surfaceOp":"append"} -{"type":"assistant/message","data":{"turn":2,"step":2,"message":{"role":"assistant","content":[{"type":"reasoning","text":"The first subagent returned \"ALPHA\". Now I need to use the subagent_fork tool (forked child that inherits this conversation) to ask about the project codeword."},{"type":"tool-call","id":"call_00_JSr5rhREq23wSmwSkCP77184","name":"subagent_fork","arguments":"{\"description\": \"Recall project codeword\", \"prompt\": \"What is the project codeword mentioned earlier in this conversation? Reply with exactly that one word and nothing else.\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:9}}"},"usage":{"inputTokens":54,"outputTokens":128,"cacheReadTokens":3072,"reasoningTokens":40},"stream":[{"type":"chunk","time":1789819982964,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1789819982964,"index":0,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"texts":["The"," first"," sub","agent"," returned"," \"","AL","P","HA","\"."," Now"," I"," need"," to"," use"," the"," sub","agent","_f","ork"," tool"," (","fork","ed"," child"," that"," inher","its"," this"," conversation",")"," to"," ask"," about"," the"," project"," cod","ew","ord","."]},{"type":"chunk","time":1789819982965,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1789819982965,"index":1,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"id":"call_00_JSr5rhREq23wSmwSkCP77184","name":"subagent_fork","args":["","{","\"","description","\"",": ","\"","Recall"," project"," cod","ew","ord","\"",", ","\"","prom","pt","\"",": ","\"","What"," is"," the"," project"," cod","ew","ord"," mentioned"," earlier"," in"," this"," conversation","?"," Reply"," with"," exactly"," that"," one"," word"," and"," nothing"," else",".","\"","}"]},{"type":"chunk","time":1789819982965,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The first subagent returned \"ALPHA\". Now I need to use the subagent_fork tool (forked child that inherits this conversation) to ask about the project codeword."}}},{"type":"chunk","time":1789819982965,"chunk":{"type":"block-end","index":1,"block":{"type":"tool-call","id":"call_00_JSr5rhREq23wSmwSkCP77184","name":"subagent_fork","arguments":"{\"description\": \"Recall project codeword\", \"prompt\": \"What is the project codeword mentioned earlier in this conversation? Reply with exactly that one word and nothing else.\"}"}}},{"type":"chunk","time":1789819982965,"chunk":{"type":"usage","usage":{"inputTokens":54,"outputTokens":128,"cacheReadTokens":3072,"reasoningTokens":40}}},{"type":"chunk","time":1789819982965,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} -{"type":"tool/call","data":{"turn":2,"step":2,"callId":"call_00_JSr5rhREq23wSmwSkCP77184","name":"subagent_fork","arguments":"{\"description\": \"Recall project codeword\", \"prompt\": \"What is the project codeword mentioned earlier in this conversation? Reply with exactly that one word and nothing else.\"}"}} +{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent worker-1 finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"ALPHA"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:7}}"},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":2,"step":2,"message":{"role":"assistant","content":[{"type":"reasoning","text":"The first subagent returned \"ALPHA\". Now I need to use the subagent_fork tool (forked child that inherits this conversation) to ask about the project codeword."},{"type":"tool-call","id":"call_00_JSr5rhREq23wSmwSkCP77184","name":"subagent_fork","arguments":"{\"description\":\"Recall project codeword\",\"prompt\":\"What is the project codeword mentioned earlier in this conversation? Reply with exactly that one word and nothing else.\",\"name\":\"worker-2\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:9}}"},"usage":{"inputTokens":54,"outputTokens":128,"cacheReadTokens":3072,"reasoningTokens":40},"stream":[{"type":"chunk","time":1792123814503,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1792123814503,"index":0,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"texts":["The"," first"," sub","agent"," returned"," \"","AL","P","HA","\"."," Now"," I"," need"," to"," use"," the"," sub","agent","_f","ork"," tool"," (","fork","ed"," child"," that"," inher","its"," this"," conversation",")"," to"," ask"," about"," the"," project"," cod","ew","ord","."]},{"type":"chunk","time":1792123814503,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792123814503,"index":1,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"id":"call_00_JSr5rhREq23wSmwSkCP77184","name":"subagent_fork","args":["{\"description\":\"Recall project codeword\",\"prompt\":\"What is the project codeword mentioned earlier in this conversation? Reply with exactly that one word and nothing else.\",\"name\":\"worker-2\"}","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""]},{"type":"chunk","time":1792123814503,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The first subagent returned \"ALPHA\". Now I need to use the subagent_fork tool (forked child that inherits this conversation) to ask about the project codeword."}}},{"type":"chunk","time":1792123814503,"chunk":{"type":"block-end","index":1,"block":{"type":"tool-call","id":"call_00_JSr5rhREq23wSmwSkCP77184","name":"subagent_fork","arguments":"{\"description\":\"Recall project codeword\",\"prompt\":\"What is the project codeword mentioned earlier in this conversation? Reply with exactly that one word and nothing else.\",\"name\":\"worker-2\"}"}}},{"type":"chunk","time":1792123814503,"chunk":{"type":"usage","usage":{"inputTokens":54,"outputTokens":128,"cacheReadTokens":3072,"reasoningTokens":40}}},{"type":"chunk","time":1792123814503,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":2,"step":2,"callId":"call_00_JSr5rhREq23wSmwSkCP77184","name":"subagent_fork","arguments":"{\"description\":\"Recall project codeword\",\"prompt\":\"What is the project codeword mentioned earlier in this conversation? Reply with exactly that one word and nothing else.\",\"name\":\"worker-2\"}"}} {"type":"subagent/catalog","data":{"version":0,"childId":"{{session:3}}","childCreatedAt":1783352147504,"mode":"continuable","label":"Recall project codeword"}} -{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent {{session:3}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"SAFFRON"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{session:3}} finished and will do no further work unless you send it more.","senderSessionId":"{{session:3}}"},"role":"user","id":"{{message:10}}"}]}} -{"type":"tool/result","data":{"turn":2,"step":2,"message":{"role":"tool","source":{"kind":"tool","callId":"call_00_JSr5rhREq23wSmwSkCP77184"},"toolCallId":"call_00_JSr5rhREq23wSmwSkCP77184","content":[{"type":"text","text":"started subagent {{session:3}}"}],"isError":false,"id":"{{message:11}}"}},"sourceEventSeqs":[31],"surfaceOp":"append"} +{"type":"subagent/named","data":{"name":"worker-2","id":"{{session:3}}"}} +{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent worker-2 finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"SAFFRON"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-2 finished and will do no further work unless you send it more.","senderSessionId":"{{session:3}}"},"role":"user","id":"{{message:10}}"}]}} +{"type":"tool/result","data":{"turn":2,"step":2,"message":{"role":"tool","source":{"kind":"tool","callId":"call_00_JSr5rhREq23wSmwSkCP77184"},"toolCallId":"call_00_JSr5rhREq23wSmwSkCP77184","content":[{"type":"text","text":"started subagent worker-2"}],"isError":false,"id":"{{message:11}}"}},"sourceEventSeqs":[32],"surfaceOp":"append"} {"type":"step/end","data":{"turn":2,"step":2}} {"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":2,"step":3}} -{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent {{session:3}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"SAFFRON"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{session:3}} finished and will do no further work unless you send it more.","senderSessionId":"{{session:3}}"},"role":"user","id":"{{message:10}}"},"surfaceOp":"append"} -{"type":"assistant/message","data":{"turn":2,"step":3,"message":{"role":"assistant","content":[{"type":"reasoning","text":"Both subagents returned:\n1. First (fresh child): \"ALPHA\"\n2. Second (forked child): \"SAFFRON\" - correctly inherited the conversation context where I was asked to remember the codeword \"SAFFRON\".\n\nNow I reply with \"PARENT_DONE\" as instructed."},{"type":"text","text":"PARENT_DONE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:12}}"},"usage":{"inputTokens":69,"outputTokens":69,"cacheReadTokens":3200,"reasoningTokens":64},"stream":[{"type":"chunk","time":1789819983022,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1789819983023,"index":0,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"texts":["Both"," sub","agents"," returned",":\n","1","."," First"," (","fresh"," child","):"," \"","AL","P","HA","\"\n","2","."," Second"," (","fork","ed"," child","):"," \"","SA","FF","RON","\""," -"," correctly"," inherited"," the"," conversation"," context"," where"," I"," was"," asked"," to"," remember"," the"," cod","ew","ord"," \"","SA","FF","RON","\".\n\n","Now"," I"," reply"," with"," \"","PAR","ENT","_D","ONE","\""," as"," instructed","."]},{"type":"chunk","time":1789819983023,"chunk":{"type":"block-start","index":1,"blockType":"text"}},{"type":"text-chunks","time0":1789819983023,"index":1,"dt":[0,0,0],"texts":["PAR","ENT","_D","ONE"]},{"type":"chunk","time":1789819983023,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"Both subagents returned:\n1. First (fresh child): \"ALPHA\"\n2. Second (forked child): \"SAFFRON\" - correctly inherited the conversation context where I was asked to remember the codeword \"SAFFRON\".\n\nNow I reply with \"PARENT_DONE\" as instructed."}}},{"type":"chunk","time":1789819983023,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"PARENT_DONE"}}},{"type":"chunk","time":1789819983023,"chunk":{"type":"usage","usage":{"inputTokens":69,"outputTokens":69,"cacheReadTokens":3200,"reasoningTokens":64}}},{"type":"chunk","time":1789819983023,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent worker-2 finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"SAFFRON"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-2 finished and will do no further work unless you send it more.","senderSessionId":"{{session:3}}"},"role":"user","id":"{{message:10}}"},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":2,"step":3,"message":{"role":"assistant","content":[{"type":"reasoning","text":"Both subagents returned:\n1. First (fresh child): \"ALPHA\"\n2. Second (forked child): \"SAFFRON\" - correctly inherited the conversation context where I was asked to remember the codeword \"SAFFRON\".\n\nNow I reply with \"PARENT_DONE\" as instructed."},{"type":"text","text":"PARENT_DONE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:12}}"},"usage":{"inputTokens":69,"outputTokens":69,"cacheReadTokens":3200,"reasoningTokens":64},"stream":[{"type":"chunk","time":1792123814571,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1792123814571,"index":0,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"texts":["Both"," sub","agents"," returned",":\n","1","."," First"," (","fresh"," child","):"," \"","AL","P","HA","\"\n","2","."," Second"," (","fork","ed"," child","):"," \"","SA","FF","RON","\""," -"," correctly"," inherited"," the"," conversation"," context"," where"," I"," was"," asked"," to"," remember"," the"," cod","ew","ord"," \"","SA","FF","RON","\".\n\n","Now"," I"," reply"," with"," \"","PAR","ENT","_D","ONE","\""," as"," instructed","."]},{"type":"chunk","time":1792123814571,"chunk":{"type":"block-start","index":1,"blockType":"text"}},{"type":"text-chunks","time0":1792123814571,"index":1,"dt":[0,0,0],"texts":["PAR","ENT","_D","ONE"]},{"type":"chunk","time":1792123814571,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"Both subagents returned:\n1. First (fresh child): \"ALPHA\"\n2. Second (forked child): \"SAFFRON\" - correctly inherited the conversation context where I was asked to remember the codeword \"SAFFRON\".\n\nNow I reply with \"PARENT_DONE\" as instructed."}}},{"type":"chunk","time":1792123814571,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"PARENT_DONE"}}},{"type":"chunk","time":1792123814571,"chunk":{"type":"usage","usage":{"inputTokens":69,"outputTokens":69,"cacheReadTokens":3200,"reasoningTokens":64}}},{"type":"chunk","time":1792123814571,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":2,"step":3}} {"type":"turn/end","data":{"turn":2,"reason":{"kind":"completed"}}} diff --git a/snapshots/sdk/subagent-send-message/session.1.v4.jsonl b/snapshots/sdk/subagent-send-message/session.1.v4.jsonl index 51c465929f..63f87388a2 100644 --- a/snapshots/sdk/subagent-send-message/session.1.v4.jsonl +++ b/snapshots/sdk/subagent-send-message/session.1.v4.jsonl @@ -3,19 +3,19 @@ {"type":"sandbox/mode","data":{"mode":"danger-full-access","source":"delegation"}} {"type":"approval/policy","data":{"policy":"never","source":"delegation"}} {"type":"permission/preset","data":{"preset":"danger-full-access"}} -{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Send exactly CHILD_MESSAGE_OK to your parent with send_message, then stop."},{"type":"text","text":"Your parent agent id is \"{{session:1}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{session:1}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:12}}"}]}} +{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Send exactly CHILD_MESSAGE_OK to your parent with send_message, then stop."},{"type":"text","text":"Your name is \"worker-1\". Your parent agent name is \"lead\". Before you finish, send your result to that agent with send_message({ name: \"lead\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:12}}"}]}} {"type":"turn/start","data":{"turn":1}} {"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":1,"step":1}} {"type":"system/message","data":{"turn":1,"step":1,"message":{"role":"system","content":[{"type":"text","text":"{{system}}"}],"source":{"kind":"system-prompt"},"id":"{{message:13}}"}},"surfaceOp":"append"} -{"type":"user/message","data":{"content":[{"type":"text","text":"Send exactly CHILD_MESSAGE_OK to your parent with send_message, then stop."},{"type":"text","text":"Your parent agent id is \"{{session:1}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{session:1}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:12}}"},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Send exactly CHILD_MESSAGE_OK to your parent with send_message, then stop."},{"type":"text","text":"Your name is \"worker-1\". Your parent agent name is \"lead\". Before you finish, send your result to that agent with send_message({ name: \"lead\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:12}}"},"surfaceOp":"append"} {"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations.\n\nApproval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).\n\nDelegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly.\n\nDelegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly.\n\nYou are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations."},{"name":"approval:policy","text":"Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."},{"name":"tool:subagent:depth","text":"Delegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly."},{"name":"tool:subagent_fork:depth","text":"Delegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly."},{"name":"subagent:delegation","text":"You are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}]},"role":"user","id":"{{message:14}}"},"surfaceOp":"append"} {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} {"type":"session/title","data":{"title":"Send exactly CHILD_MESSAGE_OK to your","messageSeqs":[9],"source":{"kind":"fallback"}}} -{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_send_message_1","name":"send_message","arguments":"{\"agent_id\": \"{{session:1}}\", \"message\": \"CHILD_MESSAGE_OK\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:15}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1788699465535,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1788699465535,"index":0,"dt":[],"id":"call_send_message_1","name":"send_message","args":["{\"agent_id\": \"{{session:1}}\", \"message\": \"CHILD_MESSAGE_OK\"}"]},{"type":"chunk","time":1788699465535,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_send_message_1","name":"send_message","arguments":"{\"agent_id\": \"{{session:1}}\", \"message\": \"CHILD_MESSAGE_OK\"}"}}},{"type":"chunk","time":1788699465535,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1788699465535,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} -{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_send_message_1","name":"send_message","arguments":"{\"agent_id\": \"{{session:1}}\", \"message\": \"CHILD_MESSAGE_OK\"}"}} -{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_send_message_1"},"toolCallId":"call_send_message_1","content":[{"type":"text","text":"message delivered to agent {{session:1}}"}],"isError":false,"id":"{{message:16}}"}},"sourceEventSeqs":[15],"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_send_message_1","name":"send_message","arguments":"{\"message\":\"CHILD_MESSAGE_OK\",\"name\":\"lead\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:15}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1788699465535,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1788699465535,"index":0,"dt":[],"id":"call_send_message_1","name":"send_message","args":["{\"message\":\"CHILD_MESSAGE_OK\",\"name\":\"lead\"}"]},{"type":"chunk","time":1788699465535,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_send_message_1","name":"send_message","arguments":"{\"message\":\"CHILD_MESSAGE_OK\",\"name\":\"lead\"}"}}},{"type":"chunk","time":1788699465535,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1788699465535,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_send_message_1","name":"send_message","arguments":"{\"message\":\"CHILD_MESSAGE_OK\",\"name\":\"lead\"}"}} +{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_send_message_1"},"toolCallId":"call_send_message_1","content":[{"type":"text","text":"message delivered to agent lead"}],"isError":false,"id":"{{message:16}}"}},"sourceEventSeqs":[15],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":1}} {"type":"step/start","data":{"turn":1,"step":2}} {"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"text","text":"Message sent."}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:17}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1788699465557,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1788699465557,"index":0,"dt":[],"texts":["Message sent."]},{"type":"chunk","time":1788699465557,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"Message sent."}}},{"type":"chunk","time":1788699465557,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1788699465557,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} diff --git a/snapshots/sdk/subagent-send-message/session.v4.jsonl b/snapshots/sdk/subagent-send-message/session.v4.jsonl index b015fdd4ee..8a37df01d5 100644 --- a/snapshots/sdk/subagent-send-message/session.v4.jsonl +++ b/snapshots/sdk/subagent-send-message/session.v4.jsonl @@ -12,24 +12,25 @@ {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} {"type":"session/title","data":{"title":"Follow these steps exactly, then","messageSeqs":[8],"source":{"kind":"fallback"}}} -{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_bg_start","name":"subagent","arguments":"{\"description\": \"Send a finding\", \"prompt\": \"Send exactly CHILD_MESSAGE_OK to your parent with send_message, then stop.\", \"run_in_background\": true}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1788880390890,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1788880390890,"index":0,"dt":[],"id":"call_bg_start","name":"subagent","args":["{\"description\": \"Send a finding\", \"prompt\": \"Send exactly CHILD_MESSAGE_OK to your parent with send_message, then stop.\", \"run_in_background\": true}"]},{"type":"chunk","time":1788880390890,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_bg_start","name":"subagent","arguments":"{\"description\": \"Send a finding\", \"prompt\": \"Send exactly CHILD_MESSAGE_OK to your parent with send_message, then stop.\", \"run_in_background\": true}"}}},{"type":"chunk","time":1788880390890,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1788880390890,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} -{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_bg_start","name":"subagent","arguments":"{\"description\": \"Send a finding\", \"prompt\": \"Send exactly CHILD_MESSAGE_OK to your parent with send_message, then stop.\", \"run_in_background\": true}"}} +{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_bg_start","name":"subagent","arguments":"{\"description\":\"Send a finding\",\"prompt\":\"Send exactly CHILD_MESSAGE_OK to your parent with send_message, then stop.\",\"run_in_background\":true,\"name\":\"worker-1\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1792123815243,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792123815243,"index":0,"dt":[],"id":"call_bg_start","name":"subagent","args":["{\"description\":\"Send a finding\",\"prompt\":\"Send exactly CHILD_MESSAGE_OK to your parent with send_message, then stop.\",\"run_in_background\":true,\"name\":\"worker-1\"}"]},{"type":"chunk","time":1792123815243,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_bg_start","name":"subagent","arguments":"{\"description\":\"Send a finding\",\"prompt\":\"Send exactly CHILD_MESSAGE_OK to your parent with send_message, then stop.\",\"run_in_background\":true,\"name\":\"worker-1\"}"}}},{"type":"chunk","time":1792123815243,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1792123815243,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_bg_start","name":"subagent","arguments":"{\"description\":\"Send a finding\",\"prompt\":\"Send exactly CHILD_MESSAGE_OK to your parent with send_message, then stop.\",\"run_in_background\":true,\"name\":\"worker-1\"}"}} {"type":"subagent/catalog","data":{"version":0,"childId":"{{session:2}}","childCreatedAt":1789000001000,"mode":"continuable","label":"Send a finding"}} -{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_bg_start"},"toolCallId":"call_bg_start","content":[{"type":"text","text":"started subagent {{session:2}}"}],"isError":false,"id":"{{message:5}}"}},"sourceEventSeqs":[14],"surfaceOp":"append"} +{"type":"subagent/named","data":{"name":"worker-1","id":"{{session:2}}"}} +{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_bg_start"},"toolCallId":"call_bg_start","content":[{"type":"text","text":"started subagent worker-1"}],"isError":false,"id":"{{message:5}}"}},"sourceEventSeqs":[14],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":1}} {"type":"step/start","data":{"turn":1,"step":2}} -{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"text","text":"STARTED"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:6}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1788880390923,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1788880390923,"index":0,"dt":[],"texts":["STARTED"]},{"type":"chunk","time":1788880390923,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"STARTED"}}},{"type":"chunk","time":1788880390923,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1788880390923,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"text","text":"STARTED"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:6}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1792123815284,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1792123815284,"index":0,"dt":[],"texts":["STARTED"]},{"type":"chunk","time":1792123815284,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"STARTED"}}},{"type":"chunk","time":1792123815284,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1792123815284,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":2}} {"type":"turn/end","data":{"turn":1,"reason":{"kind":"completed"}}} -{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Agent {{session:2}} sent a message: "},{"type":"text","text":"CHILD_MESSAGE_OK"}],"source":{"kind":"agent-message","form":"relay","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:7}}"}]}} -{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent {{session:2}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"Message sent."}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{session:2}} finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:8}}"}]}} +{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Agent worker-1 sent a message: "},{"type":"text","text":"CHILD_MESSAGE_OK"}],"source":{"kind":"agent-message","form":"relay","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:7}}"}]}} +{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent worker-1 finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"Message sent."}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:8}}"}]}} {"type":"turn/start","data":{"turn":2}} {"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"removedCount":1,"inserted":[]}} {"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":2,"step":1}} -{"type":"user/message","data":{"content":[{"type":"text","text":"Agent {{session:2}} sent a message: "},{"type":"text","text":"CHILD_MESSAGE_OK"}],"source":{"kind":"agent-message","form":"relay","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:7}}"},"surfaceOp":"append"} -{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent {{session:2}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"Message sent."}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{session:2}} finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:8}}"},"surfaceOp":"append"} -{"type":"assistant/message","data":{"turn":2,"step":1,"message":{"role":"assistant","content":[{"type":"text","text":"SUBAGENT_SETTLED_NOTED"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:9}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1788880390979,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1788880390979,"index":0,"dt":[],"texts":["SUBAGENT_SETTLED_NOTED"]},{"type":"chunk","time":1788880390979,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"SUBAGENT_SETTLED_NOTED"}}},{"type":"chunk","time":1788880390979,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1788880390979,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Agent worker-1 sent a message: "},{"type":"text","text":"CHILD_MESSAGE_OK"}],"source":{"kind":"agent-message","form":"relay","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:7}}"},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent worker-1 finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"Message sent."}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:8}}"},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":2,"step":1,"message":{"role":"assistant","content":[{"type":"text","text":"SUBAGENT_SETTLED_NOTED"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:9}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1792123815345,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1792123815345,"index":0,"dt":[],"texts":["SUBAGENT_SETTLED_NOTED"]},{"type":"chunk","time":1792123815345,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"SUBAGENT_SETTLED_NOTED"}}},{"type":"chunk","time":1792123815345,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1792123815345,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":2,"step":1}} {"type":"turn/end","data":{"turn":2,"reason":{"kind":"completed"}}} {"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Repeat back, verbatim, the exact message the background subagent sent you. Reply with only that text. Do not use any tools."}],"source":{"kind":"user"},"role":"user","id":"{{message:10}}"}]}} @@ -37,6 +38,6 @@ {"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":3,"step":1}} {"type":"user/message","data":{"content":[{"type":"text","text":"Repeat back, verbatim, the exact message the background subagent sent you. Reply with only that text. Do not use any tools."}],"source":{"kind":"user"},"role":"user","id":"{{message:10}}"},"surfaceOp":"append"} -{"type":"assistant/message","data":{"turn":3,"step":1,"message":{"role":"assistant","content":[{"type":"text","text":"CHILD_MESSAGE_OK"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:11}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1788880390997,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1788880390997,"index":0,"dt":[],"texts":["CHILD_MESSAGE_OK"]},{"type":"chunk","time":1788880390997,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"CHILD_MESSAGE_OK"}}},{"type":"chunk","time":1788880390997,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1788880390997,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":3,"step":1,"message":{"role":"assistant","content":[{"type":"text","text":"CHILD_MESSAGE_OK"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:11}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1792123815365,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1792123815365,"index":0,"dt":[],"texts":["CHILD_MESSAGE_OK"]},{"type":"chunk","time":1792123815365,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"CHILD_MESSAGE_OK"}}},{"type":"chunk","time":1792123815365,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1792123815365,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":3,"step":1}} {"type":"turn/end","data":{"turn":3,"reason":{"kind":"completed"}}} diff --git a/snapshots/sdk/subagent-send-message/tool-schemas.1.expected.json b/snapshots/sdk/subagent-send-message/tool-schemas.1.expected.json index b546a748a7..99b37246de 100644 --- a/snapshots/sdk/subagent-send-message/tool-schemas.1.expected.json +++ b/snapshots/sdk/subagent-send-message/tool-schemas.1.expected.json @@ -181,13 +181,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -245,7 +245,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -297,9 +297,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -307,7 +307,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -330,10 +330,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -348,6 +352,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -355,10 +360,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -373,6 +382,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/sdk/subagent-spawn-in-process/notifications.expected.jsonl b/snapshots/sdk/subagent-spawn-in-process/notifications.expected.jsonl index e2c0f02413..67b4f4d598 100644 --- a/snapshots/sdk/subagent-spawn-in-process/notifications.expected.jsonl +++ b/snapshots/sdk/subagent-spawn-in-process/notifications.expected.jsonl @@ -9,17 +9,18 @@ {"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"request/header","seq":10,"time":0,"data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}}}} {"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"request/context","seq":11,"time":0,"data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}}}} {"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"session/title","seq":12,"time":0,"data":{"title":"Use the subagent tool exactly","messageSeqs":[8],"source":{"kind":"fallback"}}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/message","seq":13,"time":0,"data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"reasoning","text":"The user wants me to:\n1. Use the subagent tool exactly once with description 'echo probe' and prompt 'Reply with exactly: child answer 42.'\n2. Then reply with the subagent's final answer verbatim.\n\nLet me do this step by step."},{"type":"tool-call","id":"call_00_oHPNQ1nLoakoaAGXIxCM7404","name":"subagent","arguments":"{\"description\": \"echo probe\", \"prompt\": \"Reply with exactly: child answer 42.\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{sessionId}}"},"usage":{"inputTokens":135,"outputTokens":124,"cacheReadTokens":1664,"reasoningTokens":55},"stream":[{"type":"chunk","time":0,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":0,"index":0,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"texts":["The"," user"," wants"," me"," to",":\n","1","."," Use"," the"," sub","agent"," tool"," exactly"," once"," with"," description"," '","echo"," probe","'"," and"," prompt"," '","Reply"," with"," exactly",":"," child"," answer"," ","42",".'\n","2","."," Then"," reply"," with"," the"," sub","agent","'s"," final"," answer"," verb","atim",".\n\n","Let"," me"," do"," this"," step"," by"," step","."]},{"type":"chunk","time":0,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":0,"index":1,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"id":"call_00_oHPNQ1nLoakoaAGXIxCM7404","name":"subagent","args":["","{","\"","description","\"",": ","\"","echo"," probe","\"",", ","\"","prom","pt","\"",": ","\"","Reply"," with"," exactly",":"," child"," answer"," ","42",".","\"","}"]},{"type":"chunk","time":0,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The user wants me to:\n1. Use the subagent tool exactly once with description 'echo probe' and prompt 'Reply with exactly: child answer 42.'\n2. Then reply with the subagent's final answer verbatim.\n\nLet me do this step by step."}}},{"type":"chunk","time":0,"chunk":{"type":"block-end","index":1,"block":{"type":"tool-call","id":"call_00_oHPNQ1nLoakoaAGXIxCM7404","name":"subagent","arguments":"{\"description\": \"echo probe\", \"prompt\": \"Reply with exactly: child answer 42.\"}"}}},{"type":"chunk","time":0,"chunk":{"type":"usage","usage":{"inputTokens":135,"outputTokens":124,"cacheReadTokens":1664,"reasoningTokens":55}}},{"type":"chunk","time":0,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"tool/call","seq":14,"time":0,"data":{"turn":1,"step":1,"callId":"call_00_oHPNQ1nLoakoaAGXIxCM7404","name":"subagent","arguments":"{\"description\": \"echo probe\", \"prompt\": \"Reply with exactly: child answer 42.\"}"}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/message","seq":13,"time":0,"data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"reasoning","text":"The user wants me to:\n1. Use the subagent tool exactly once with description 'echo probe' and prompt 'Reply with exactly: child answer 42.'\n2. Then reply with the subagent's final answer verbatim.\n\nLet me do this step by step."},{"type":"tool-call","id":"call_00_oHPNQ1nLoakoaAGXIxCM7404","name":"subagent","arguments":"{\"description\":\"echo probe\",\"prompt\":\"Reply with exactly: child answer 42.\",\"name\":\"worker-1\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{sessionId}}"},"usage":{"inputTokens":135,"outputTokens":124,"cacheReadTokens":1664,"reasoningTokens":55},"stream":[{"type":"chunk","time":0,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":0,"index":0,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"texts":["The"," user"," wants"," me"," to",":\n","1","."," Use"," the"," sub","agent"," tool"," exactly"," once"," with"," description"," '","echo"," probe","'"," and"," prompt"," '","Reply"," with"," exactly",":"," child"," answer"," ","42",".'\n","2","."," Then"," reply"," with"," the"," sub","agent","'s"," final"," answer"," verb","atim",".\n\n","Let"," me"," do"," this"," step"," by"," step","."]},{"type":"chunk","time":0,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":0,"index":1,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"id":"call_00_oHPNQ1nLoakoaAGXIxCM7404","name":"subagent","args":["{\"description\":\"echo probe\",\"prompt\":\"Reply with exactly: child answer 42.\",\"name\":\"worker-1\"}","","","","","","","","","","","","","","","","","","","","","","","","","","",""]},{"type":"chunk","time":0,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The user wants me to:\n1. Use the subagent tool exactly once with description 'echo probe' and prompt 'Reply with exactly: child answer 42.'\n2. Then reply with the subagent's final answer verbatim.\n\nLet me do this step by step."}}},{"type":"chunk","time":0,"chunk":{"type":"block-end","index":1,"block":{"type":"tool-call","id":"call_00_oHPNQ1nLoakoaAGXIxCM7404","name":"subagent","arguments":"{\"description\":\"echo probe\",\"prompt\":\"Reply with exactly: child answer 42.\",\"name\":\"worker-1\"}"}}},{"type":"chunk","time":0,"chunk":{"type":"usage","usage":{"inputTokens":135,"outputTokens":124,"cacheReadTokens":1664,"reasoningTokens":55}}},{"type":"chunk","time":0,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"tool/call","seq":14,"time":0,"data":{"turn":1,"step":1,"callId":"call_00_oHPNQ1nLoakoaAGXIxCM7404","name":"subagent","arguments":"{\"description\":\"echo probe\",\"prompt\":\"Reply with exactly: child answer 42.\",\"name\":\"worker-1\"}"}}}} {"method":"subagent.started","params":{"parentSessionId":"{{sessionId}}","childSessionId":"{{sessionId}}"}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"agent/inbox/spliced","seq":3,"time":0,"data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Reply with exactly: child answer 42."},{"type":"text","text":"Your parent agent id is \"{{sessionId}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{sessionId}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{sessionId}}"}]}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"agent/inbox/spliced","seq":3,"time":0,"data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Reply with exactly: child answer 42."},{"type":"text","text":"Your name is \"worker-1\". Your parent agent name is \"lead\". Before you finish, send your result to that agent with send_message({ name: \"lead\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{sessionId}}"}]}}}} {"method":"session.status","params":{"sessionId":"{{sessionId}}","status":"running"}} {"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"turn/start","seq":4,"time":0,"data":{"turn":1}}}} {"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"agent/inbox/spliced","seq":5,"time":0,"data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}}}} {"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"subagent/catalog","seq":15,"time":0,"data":{"version":0,"childId":"{{sessionId}}","childCreatedAt":0,"mode":"continuable","label":"echo probe"}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"subagent/named","seq":16,"time":0,"data":{"name":"worker-1","id":"{{sessionId}}"}}}} {"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/start","seq":6,"time":0,"data":{"turn":1,"step":1}}}} {"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"system/message","seq":7,"time":0,"data":{"turn":1,"step":1,"message":{"role":"system","content":[{"type":"text","text":"{{system}}"}],"source":{"kind":"system-prompt"},"id":"{{sessionId}}"}},"surfaceOp":"append"}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"user/message","seq":8,"time":0,"data":{"content":[{"type":"text","text":"Reply with exactly: child answer 42."},{"type":"text","text":"Your parent agent id is \"{{sessionId}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{sessionId}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"user/message","seq":8,"time":0,"data":{"content":[{"type":"text","text":"Reply with exactly: child answer 42."},{"type":"text","text":"Your name is \"worker-1\". Your parent agent name is \"lead\". Before you finish, send your result to that agent with send_message({ name: \"lead\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}}} {"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"user/message","seq":9,"time":0,"data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: workspace-write. Any available operation enforced by the DSH file sandbox may modify files under the session workspace: \"{{cwd}}\". Some platform temporary areas may also be writable.\n\nApproval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).\n\nDelegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly.\n\nDelegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly.\n\nYou are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: workspace-write. Any available operation enforced by the DSH file sandbox may modify files under the session workspace: \"{{cwd}}\". Some platform temporary areas may also be writable."},{"name":"approval:policy","text":"Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."},{"name":"tool:subagent:depth","text":"Delegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly."},{"name":"tool:subagent_fork:depth","text":"Delegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly."},{"name":"subagent:delegation","text":"You are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}]},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}}} {"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"request/header","seq":10,"time":0,"data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}}}} {"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"request/context","seq":11,"time":0,"data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}}}} @@ -28,14 +29,14 @@ {"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/end","seq":14,"time":0,"data":{"turn":1,"step":1}}}} {"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"turn/end","seq":15,"time":0,"data":{"turn":1,"reason":{"kind":"completed"}}}}} {"method":"session.status","params":{"sessionId":"{{sessionId}}","status":"idle"}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"agent/inbox/spliced","seq":16,"time":0,"data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent {{sessionId}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"child answer 42."}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{sessionId}} finished and will do no further work unless you send it more.","senderSessionId":"{{sessionId}}"},"role":"user","id":"{{sessionId}}"}]}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"agent/inbox/spliced","seq":17,"time":0,"data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent worker-1 finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"child answer 42."}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 finished and will do no further work unless you send it more.","senderSessionId":"{{sessionId}}"},"role":"user","id":"{{sessionId}}"}]}}}} {"method":"subagent.finished","params":{"provider":"spawn","agentId":"{{sessionId}}","parentSessionId":"{{sessionId}}","childSessionId":"{{sessionId}}","status":"ok","stopReason":"completed","lastAssistantMessage":[{"type":"text","text":"child answer 42."}]}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"tool/result","seq":17,"time":0,"data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_00_oHPNQ1nLoakoaAGXIxCM7404"},"toolCallId":"call_00_oHPNQ1nLoakoaAGXIxCM7404","content":[{"type":"text","text":"started subagent {{sessionId}}"}],"isError":false,"id":"{{sessionId}}"}},"sourceEventSeqs":[14],"surfaceOp":"append"}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/end","seq":18,"time":0,"data":{"turn":1,"step":1}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"agent/inbox/spliced","seq":19,"time":0,"data":{"target":"next-step","start":0,"removedCount":1,"inserted":[]}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/start","seq":20,"time":0,"data":{"turn":1,"step":2}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"user/message","seq":21,"time":0,"data":{"content":[{"type":"text","text":"Background subagent {{sessionId}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"child answer 42."}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{sessionId}} finished and will do no further work unless you send it more.","senderSessionId":"{{sessionId}}"},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/message","seq":22,"time":0,"data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"reasoning","text":"The subagent replied with \"child answer 42.\" Now I need to reply with the subagent's final answer verbatim."},{"type":"text","text":"child answer 42."}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{sessionId}}"},"usage":{"inputTokens":19,"outputTokens":32,"cacheReadTokens":1920,"reasoningTokens":26},"stream":[{"type":"chunk","time":0,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":0,"index":0,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"texts":["The"," sub","agent"," replied"," with"," \"","child"," answer"," ","42",".\""," Now"," I"," need"," to"," reply"," with"," the"," sub","agent","'s"," final"," answer"," verb","atim","."]},{"type":"chunk","time":0,"chunk":{"type":"block-start","index":1,"blockType":"text"}},{"type":"text-chunks","time0":0,"index":1,"dt":[0,0,0,0],"texts":["child"," answer"," ","42","."]},{"type":"chunk","time":0,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The subagent replied with \"child answer 42.\" Now I need to reply with the subagent's final answer verbatim."}}},{"type":"chunk","time":0,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"child answer 42."}}},{"type":"chunk","time":0,"chunk":{"type":"usage","usage":{"inputTokens":19,"outputTokens":32,"cacheReadTokens":1920,"reasoningTokens":26}}},{"type":"chunk","time":0,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/end","seq":23,"time":0,"data":{"turn":1,"step":2}}}} -{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"turn/end","seq":24,"time":0,"data":{"turn":1,"reason":{"kind":"completed"}}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"tool/result","seq":18,"time":0,"data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_00_oHPNQ1nLoakoaAGXIxCM7404"},"toolCallId":"call_00_oHPNQ1nLoakoaAGXIxCM7404","content":[{"type":"text","text":"started subagent worker-1"}],"isError":false,"id":"{{sessionId}}"}},"sourceEventSeqs":[14],"surfaceOp":"append"}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/end","seq":19,"time":0,"data":{"turn":1,"step":1}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"agent/inbox/spliced","seq":20,"time":0,"data":{"target":"next-step","start":0,"removedCount":1,"inserted":[]}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/start","seq":21,"time":0,"data":{"turn":1,"step":2}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"user/message","seq":22,"time":0,"data":{"content":[{"type":"text","text":"Background subagent worker-1 finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"child answer 42."}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 finished and will do no further work unless you send it more.","senderSessionId":"{{sessionId}}"},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/message","seq":23,"time":0,"data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"reasoning","text":"The subagent replied with \"child answer 42.\" Now I need to reply with the subagent's final answer verbatim."},{"type":"text","text":"child answer 42."}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{sessionId}}"},"usage":{"inputTokens":19,"outputTokens":32,"cacheReadTokens":1920,"reasoningTokens":26},"stream":[{"type":"chunk","time":0,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":0,"index":0,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"texts":["The"," sub","agent"," replied"," with"," \"","child"," answer"," ","42",".\""," Now"," I"," need"," to"," reply"," with"," the"," sub","agent","'s"," final"," answer"," verb","atim","."]},{"type":"chunk","time":0,"chunk":{"type":"block-start","index":1,"blockType":"text"}},{"type":"text-chunks","time0":0,"index":1,"dt":[0,0,0,0],"texts":["child"," answer"," ","42","."]},{"type":"chunk","time":0,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The subagent replied with \"child answer 42.\" Now I need to reply with the subagent's final answer verbatim."}}},{"type":"chunk","time":0,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"child answer 42."}}},{"type":"chunk","time":0,"chunk":{"type":"usage","usage":{"inputTokens":19,"outputTokens":32,"cacheReadTokens":1920,"reasoningTokens":26}}},{"type":"chunk","time":0,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/end","seq":24,"time":0,"data":{"turn":1,"step":2}}}} +{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"turn/end","seq":25,"time":0,"data":{"turn":1,"reason":{"kind":"completed"}}}}} {"method":"session.status","params":{"sessionId":"{{sessionId}}","status":"idle"}} diff --git a/snapshots/sdk/subagent-spawn-in-process/session.1.v4.jsonl b/snapshots/sdk/subagent-spawn-in-process/session.1.v4.jsonl index 16ba615cac..e474491d1c 100644 --- a/snapshots/sdk/subagent-spawn-in-process/session.1.v4.jsonl +++ b/snapshots/sdk/subagent-spawn-in-process/session.1.v4.jsonl @@ -2,12 +2,12 @@ {"type":"subagent/descriptor","data":{"version":3,"mode":"continuable","provider":"spawn","label":"echo probe","agentProvider":"deepseek-official","agentModel":"deepseek-v4-flash"}} {"type":"sandbox/mode","data":{"mode":"workspace-write","source":"delegation"}} {"type":"approval/policy","data":{"policy":"never","source":"delegation"}} -{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Reply with exactly: child answer 42."},{"type":"text","text":"Your parent agent id is \"{{session:1}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{session:1}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:8}}"}]}} +{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Reply with exactly: child answer 42."},{"type":"text","text":"Your name is \"worker-1\". Your parent agent name is \"lead\". Before you finish, send your result to that agent with send_message({ name: \"lead\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:8}}"}]}} {"type":"turn/start","data":{"turn":1}} {"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":1,"step":1}} {"type":"system/message","data":{"turn":1,"step":1,"message":{"role":"system","content":[{"type":"text","text":"{{system}}"}],"source":{"kind":"system-prompt"},"id":"{{message:9}}"}},"surfaceOp":"append"} -{"type":"user/message","data":{"content":[{"type":"text","text":"Reply with exactly: child answer 42."},{"type":"text","text":"Your parent agent id is \"{{session:1}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{session:1}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:8}}"},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Reply with exactly: child answer 42."},{"type":"text","text":"Your name is \"worker-1\". Your parent agent name is \"lead\". Before you finish, send your result to that agent with send_message({ name: \"lead\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:8}}"},"surfaceOp":"append"} {"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: workspace-write. Any available operation enforced by the DSH file sandbox may modify files under the session workspace: \"{{cwd}}\". Some platform temporary areas may also be writable.\n\nApproval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).\n\nDelegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly.\n\nDelegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly.\n\nYou are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: workspace-write. Any available operation enforced by the DSH file sandbox may modify files under the session workspace: \"{{cwd}}\". Some platform temporary areas may also be writable."},{"name":"approval:policy","text":"Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."},{"name":"tool:subagent:depth","text":"Delegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly."},{"name":"tool:subagent_fork:depth","text":"Delegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly."},{"name":"subagent:delegation","text":"You are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}]},"role":"user","id":"{{message:10}}"},"surfaceOp":"append"} {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} diff --git a/snapshots/sdk/subagent-spawn-in-process/session.v4.jsonl b/snapshots/sdk/subagent-spawn-in-process/session.v4.jsonl index a30a5fc3ea..f752667d7a 100644 --- a/snapshots/sdk/subagent-spawn-in-process/session.v4.jsonl +++ b/snapshots/sdk/subagent-spawn-in-process/session.v4.jsonl @@ -12,15 +12,16 @@ {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} {"type":"session/title","data":{"title":"Use the subagent tool exactly","messageSeqs":[8],"source":{"kind":"fallback"}}} -{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"reasoning","text":"The user wants me to:\n1. Use the subagent tool exactly once with description 'echo probe' and prompt 'Reply with exactly: child answer 42.'\n2. Then reply with the subagent's final answer verbatim.\n\nLet me do this step by step."},{"type":"tool-call","id":"call_00_oHPNQ1nLoakoaAGXIxCM7404","name":"subagent","arguments":"{\"description\": \"echo probe\", \"prompt\": \"Reply with exactly: child answer 42.\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":135,"outputTokens":124,"cacheReadTokens":1664,"reasoningTokens":55},"stream":[{"type":"chunk","time":1789626545603,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1789626545603,"index":0,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"texts":["The"," user"," wants"," me"," to",":\n","1","."," Use"," the"," sub","agent"," tool"," exactly"," once"," with"," description"," '","echo"," probe","'"," and"," prompt"," '","Reply"," with"," exactly",":"," child"," answer"," ","42",".'\n","2","."," Then"," reply"," with"," the"," sub","agent","'s"," final"," answer"," verb","atim",".\n\n","Let"," me"," do"," this"," step"," by"," step","."]},{"type":"chunk","time":1789626545604,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1789626545604,"index":1,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"id":"call_00_oHPNQ1nLoakoaAGXIxCM7404","name":"subagent","args":["","{","\"","description","\"",": ","\"","echo"," probe","\"",", ","\"","prom","pt","\"",": ","\"","Reply"," with"," exactly",":"," child"," answer"," ","42",".","\"","}"]},{"type":"chunk","time":1789626545604,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The user wants me to:\n1. Use the subagent tool exactly once with description 'echo probe' and prompt 'Reply with exactly: child answer 42.'\n2. Then reply with the subagent's final answer verbatim.\n\nLet me do this step by step."}}},{"type":"chunk","time":1789626545604,"chunk":{"type":"block-end","index":1,"block":{"type":"tool-call","id":"call_00_oHPNQ1nLoakoaAGXIxCM7404","name":"subagent","arguments":"{\"description\": \"echo probe\", \"prompt\": \"Reply with exactly: child answer 42.\"}"}}},{"type":"chunk","time":1789626545604,"chunk":{"type":"usage","usage":{"inputTokens":135,"outputTokens":124,"cacheReadTokens":1664,"reasoningTokens":55}}},{"type":"chunk","time":1789626545604,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} -{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_00_oHPNQ1nLoakoaAGXIxCM7404","name":"subagent","arguments":"{\"description\": \"echo probe\", \"prompt\": \"Reply with exactly: child answer 42.\"}"}} +{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"reasoning","text":"The user wants me to:\n1. Use the subagent tool exactly once with description 'echo probe' and prompt 'Reply with exactly: child answer 42.'\n2. Then reply with the subagent's final answer verbatim.\n\nLet me do this step by step."},{"type":"tool-call","id":"call_00_oHPNQ1nLoakoaAGXIxCM7404","name":"subagent","arguments":"{\"description\":\"echo probe\",\"prompt\":\"Reply with exactly: child answer 42.\",\"name\":\"worker-1\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":135,"outputTokens":124,"cacheReadTokens":1664,"reasoningTokens":55},"stream":[{"type":"chunk","time":1792123815926,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1792123815926,"index":0,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"texts":["The"," user"," wants"," me"," to",":\n","1","."," Use"," the"," sub","agent"," tool"," exactly"," once"," with"," description"," '","echo"," probe","'"," and"," prompt"," '","Reply"," with"," exactly",":"," child"," answer"," ","42",".'\n","2","."," Then"," reply"," with"," the"," sub","agent","'s"," final"," answer"," verb","atim",".\n\n","Let"," me"," do"," this"," step"," by"," step","."]},{"type":"chunk","time":1792123815926,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792123815926,"index":1,"dt":[0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"id":"call_00_oHPNQ1nLoakoaAGXIxCM7404","name":"subagent","args":["{\"description\":\"echo probe\",\"prompt\":\"Reply with exactly: child answer 42.\",\"name\":\"worker-1\"}","","","","","","","","","","","","","","","","","","","","","","","","","","",""]},{"type":"chunk","time":1792123815927,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The user wants me to:\n1. Use the subagent tool exactly once with description 'echo probe' and prompt 'Reply with exactly: child answer 42.'\n2. Then reply with the subagent's final answer verbatim.\n\nLet me do this step by step."}}},{"type":"chunk","time":1792123815927,"chunk":{"type":"block-end","index":1,"block":{"type":"tool-call","id":"call_00_oHPNQ1nLoakoaAGXIxCM7404","name":"subagent","arguments":"{\"description\":\"echo probe\",\"prompt\":\"Reply with exactly: child answer 42.\",\"name\":\"worker-1\"}"}}},{"type":"chunk","time":1792123815927,"chunk":{"type":"usage","usage":{"inputTokens":135,"outputTokens":124,"cacheReadTokens":1664,"reasoningTokens":55}}},{"type":"chunk","time":1792123815927,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_00_oHPNQ1nLoakoaAGXIxCM7404","name":"subagent","arguments":"{\"description\":\"echo probe\",\"prompt\":\"Reply with exactly: child answer 42.\",\"name\":\"worker-1\"}"}} {"type":"subagent/catalog","data":{"version":0,"childId":"{{session:2}}","childCreatedAt":1789626545611,"mode":"continuable","label":"echo probe"}} -{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent {{session:2}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"child answer 42."}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{session:2}} finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:5}}"}]}} -{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_00_oHPNQ1nLoakoaAGXIxCM7404"},"toolCallId":"call_00_oHPNQ1nLoakoaAGXIxCM7404","content":[{"type":"text","text":"started subagent {{session:2}}"}],"isError":false,"id":"{{message:6}}"}},"sourceEventSeqs":[14],"surfaceOp":"append"} +{"type":"subagent/named","data":{"name":"worker-1","id":"{{session:2}}"}} +{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent worker-1 finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"child answer 42."}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:5}}"}]}} +{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_00_oHPNQ1nLoakoaAGXIxCM7404"},"toolCallId":"call_00_oHPNQ1nLoakoaAGXIxCM7404","content":[{"type":"text","text":"started subagent worker-1"}],"isError":false,"id":"{{message:6}}"}},"sourceEventSeqs":[14],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":1}} {"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":1,"step":2}} -{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent {{session:2}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"child answer 42."}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{session:2}} finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:5}}"},"surfaceOp":"append"} -{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"reasoning","text":"The subagent replied with \"child answer 42.\" Now I need to reply with the subagent's final answer verbatim."},{"type":"text","text":"child answer 42."}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:7}}"},"usage":{"inputTokens":19,"outputTokens":32,"cacheReadTokens":1920,"reasoningTokens":26},"stream":[{"type":"chunk","time":1789626545667,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1789626545667,"index":0,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"texts":["The"," sub","agent"," replied"," with"," \"","child"," answer"," ","42",".\""," Now"," I"," need"," to"," reply"," with"," the"," sub","agent","'s"," final"," answer"," verb","atim","."]},{"type":"chunk","time":1789626545667,"chunk":{"type":"block-start","index":1,"blockType":"text"}},{"type":"text-chunks","time0":1789626545667,"index":1,"dt":[0,0,0,0],"texts":["child"," answer"," ","42","."]},{"type":"chunk","time":1789626545667,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The subagent replied with \"child answer 42.\" Now I need to reply with the subagent's final answer verbatim."}}},{"type":"chunk","time":1789626545667,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"child answer 42."}}},{"type":"chunk","time":1789626545667,"chunk":{"type":"usage","usage":{"inputTokens":19,"outputTokens":32,"cacheReadTokens":1920,"reasoningTokens":26}}},{"type":"chunk","time":1789626545667,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent worker-1 finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"child answer 42."}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:5}}"},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"reasoning","text":"The subagent replied with \"child answer 42.\" Now I need to reply with the subagent's final answer verbatim."},{"type":"text","text":"child answer 42."}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:7}}"},"usage":{"inputTokens":19,"outputTokens":32,"cacheReadTokens":1920,"reasoningTokens":26},"stream":[{"type":"chunk","time":1792123815987,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1792123815987,"index":0,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"texts":["The"," sub","agent"," replied"," with"," \"","child"," answer"," ","42",".\""," Now"," I"," need"," to"," reply"," with"," the"," sub","agent","'s"," final"," answer"," verb","atim","."]},{"type":"chunk","time":1792123815987,"chunk":{"type":"block-start","index":1,"blockType":"text"}},{"type":"text-chunks","time0":1792123815987,"index":1,"dt":[0,0,0,0],"texts":["child"," answer"," ","42","."]},{"type":"chunk","time":1792123815987,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The subagent replied with \"child answer 42.\" Now I need to reply with the subagent's final answer verbatim."}}},{"type":"chunk","time":1792123815987,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"child answer 42."}}},{"type":"chunk","time":1792123815987,"chunk":{"type":"usage","usage":{"inputTokens":19,"outputTokens":32,"cacheReadTokens":1920,"reasoningTokens":26}}},{"type":"chunk","time":1792123815987,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":2}} {"type":"turn/end","data":{"turn":1,"reason":{"kind":"completed"}}} diff --git a/snapshots/sdk/text-turn/tool-schemas.expected.json b/snapshots/sdk/text-turn/tool-schemas.expected.json index b546a748a7..99b37246de 100644 --- a/snapshots/sdk/text-turn/tool-schemas.expected.json +++ b/snapshots/sdk/text-turn/tool-schemas.expected.json @@ -181,13 +181,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -245,7 +245,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -297,9 +297,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -307,7 +307,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -330,10 +330,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -348,6 +352,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -355,10 +360,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -373,6 +382,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/sdk/tool-error-details/system-prompt.expected.md b/snapshots/sdk/tool-error-details/system-prompt.expected.md index fd8dc5b49a..d295be2619 100644 --- a/snapshots/sdk/tool-error-details/system-prompt.expected.md +++ b/snapshots/sdk/tool-error-details/system-prompt.expected.md @@ -147,8 +147,8 @@ interface ToolArgsMap { } & Record; /** Ask a subagent to stop its current work. This call returns without waiting for it to stop. You can continue a local direct child's conversation later with send_message. External executions stop permanently and cannot receive follow-ups. Subagents it started will keep running. */ interrupt_agent: { - /** The id of an agent created under you: your direct child or a deeper descendant. */ - agent_id: string; + /** The name of an agent created under you: your direct child or a deeper descendant. */ + name: string; } & Record; /** Request cancellation of a running background job. */ job_kill: { @@ -168,7 +168,7 @@ interface ToolArgsMap { /** Max wait in milliseconds with wait: true. Defaults to and is capped by configuration. */ timeout_ms?: number; } & Record; - /** List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation. */ + /** List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation. */ list_agents: Record; /** Read a UTF-8 text file and return line-numbered content. */ read: { @@ -186,8 +186,8 @@ interface ToolArgsMap { } & Record; /** Send a message to an agent. A working agent receives it at its next step; an idle agent starts a new turn with it. Returns delivery confirmation, not the agent's answer. */ send_message: { - /** The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child. */ - agent_id: string; + /** The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child. */ + name: string; /** The message to deliver to the agent. */ message: string; } & Record; @@ -196,8 +196,10 @@ interface ToolArgsMap { /** The exact skill name from the available skills list. */ name: string; } & Record; - /** Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ + /** Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ subagent: { + /** Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish. */ + name: string; /** Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent. */ cwd?: string; /** A short (3-5 word) description of the delegated task, for display. */ @@ -205,8 +207,10 @@ interface ToolArgsMap { /** The complete, self-contained task for the subagent. It does not share this conversation's context, so include everything it needs. */ prompt: string; } & Record; - /** Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ + /** Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ subagent_fork: { + /** Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish. */ + name: string; /** Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent. */ cwd?: string; /** A short (3-5 word) description of the delegated task, for display. */ @@ -425,18 +429,18 @@ interface ToolOutputMap { }; list_agents: ({ kind: "parent"; - id: string; + name: string; status: "running" | "inactive"; } | { kind: "child" | "sibling"; - id: string; + name: string; label: string; status: "running" | "inactive"; parent?: string; depth?: number; } | { kind: "diagnostic"; - id: string; + name: string; reason: "corrupt" | "unsupported" | "unavailable"; parent?: string; depth?: number; @@ -487,11 +491,11 @@ interface ToolOutputMap { }; subagent: { kind: "activation"; - subagentId: string; + name: string; }; subagent_fork: { kind: "activation"; - subagentId: string; + name: string; }; todo_write: { todos: ({ diff --git a/snapshots/sdk/tool-error-details/tool-schemas.expected.json b/snapshots/sdk/tool-error-details/tool-schemas.expected.json index 5c039e7d30..63d8c20766 100644 --- a/snapshots/sdk/tool-error-details/tool-schemas.expected.json +++ b/snapshots/sdk/tool-error-details/tool-schemas.expected.json @@ -181,13 +181,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -245,7 +245,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -297,9 +297,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -307,7 +307,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -330,10 +330,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -348,6 +352,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -355,10 +360,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -373,6 +382,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/session/advanced-toolchain-runtime/session.1.v4.jsonl b/snapshots/session/advanced-toolchain-runtime/session.1.v4.jsonl index 1574a70735..d0ae525ef9 100644 --- a/snapshots/session/advanced-toolchain-runtime/session.1.v4.jsonl +++ b/snapshots/session/advanced-toolchain-runtime/session.1.v4.jsonl @@ -3,12 +3,12 @@ {"type":"sandbox/mode","data":{"mode":"danger-full-access","source":"delegation"}} {"type":"approval/policy","data":{"policy":"never","source":"delegation"}} {"type":"permission/preset","data":{"preset":"danger-full-access"}} -{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Reply with exactly DIRECT_CHILD_OK and nothing else."},{"type":"text","text":"Your parent agent id is \"{{session:1}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{session:1}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:14}}"}]}} +{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Reply with exactly DIRECT_CHILD_OK and nothing else."},{"type":"text","text":"Your name is \"worker-1\". Your parent agent name is \"lead\". Before you finish, send your result to that agent with send_message({ name: \"lead\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:14}}"}]}} {"type":"turn/start","data":{"turn":1}} {"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":1,"step":1}} {"type":"system/message","data":{"turn":1,"step":1,"message":{"role":"system","content":[{"type":"text","text":"{{system}}"}],"source":{"kind":"system-prompt"},"id":"{{message:15}}"}},"surfaceOp":"append"} -{"type":"user/message","data":{"content":[{"type":"text","text":"Reply with exactly DIRECT_CHILD_OK and nothing else."},{"type":"text","text":"Your parent agent id is \"{{session:1}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{session:1}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:14}}"},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Reply with exactly DIRECT_CHILD_OK and nothing else."},{"type":"text","text":"Your name is \"worker-1\". Your parent agent name is \"lead\". Before you finish, send your result to that agent with send_message({ name: \"lead\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:14}}"},"surfaceOp":"append"} {"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations.\n\nApproval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).\n\nDelegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly.\n\nDelegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly.\n\nYou are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations."},{"name":"approval:policy","text":"Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."},{"name":"tool:subagent:depth","text":"Delegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly."},{"name":"tool:subagent_fork:depth","text":"Delegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly."},{"name":"subagent:delegation","text":"You are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}]},"role":"user","id":"{{message:16}}"},"surfaceOp":"append"} {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} diff --git a/snapshots/session/advanced-toolchain-runtime/session.v4.jsonl b/snapshots/session/advanced-toolchain-runtime/session.v4.jsonl index f3d8b119f5..9bfa19d349 100644 --- a/snapshots/session/advanced-toolchain-runtime/session.v4.jsonl +++ b/snapshots/session/advanced-toolchain-runtime/session.v4.jsonl @@ -12,35 +12,37 @@ {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} {"type":"session/title","data":{"title":"Run this advanced flow exactly","messageSeqs":[8],"source":{"kind":"fallback"}}} -{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"advanced-inspect-before","name":"cordis_inspect_list","arguments":"{}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":3,"outputTokens":3},"stream":[{"type":"chunk","time":1790493376576,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1790493376576,"index":0,"dt":[],"id":"advanced-inspect-before","name":"cordis_inspect_list","args":["{}"]},{"type":"chunk","time":1790493376577,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"advanced-inspect-before","name":"cordis_inspect_list","arguments":"{}"}}},{"type":"chunk","time":1790493376577,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}},{"type":"chunk","time":1790493376577,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"advanced-inspect-before","name":"cordis_inspect_list","arguments":"{}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":3,"outputTokens":3},"stream":[{"type":"chunk","time":1792123791668,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792123791668,"index":0,"dt":[],"id":"advanced-inspect-before","name":"cordis_inspect_list","args":["{}"]},{"type":"chunk","time":1792123791668,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"advanced-inspect-before","name":"cordis_inspect_list","arguments":"{}"}}},{"type":"chunk","time":1792123791668,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}},{"type":"chunk","time":1792123791668,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} {"type":"tool/call","data":{"turn":1,"step":1,"callId":"advanced-inspect-before","name":"cordis_inspect_list","arguments":"{}"}} {"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"advanced-inspect-before"},"toolCallId":"advanced-inspect-before","content":[{"type":"text","text":"{\n \"providers\": [\n {\n \"platform\": \"host\",\n \"id\": \"Service\",\n \"description\": \"Progressive Host Service discovery: compact capability/signature directory, then one exact coding contract.\",\n \"methods\": [\n {\n \"name\": \"listService\",\n \"description\": \"Progressive Host Service discovery: compact capability/signature directory, then one exact coding contract.\",\n \"inputSchema\": {\n \"type\": \"object\",\n \"properties\": {\n \"service\": {\n \"type\": \"string\",\n \"description\": \"Exact Service key. Omit it for the compact Service and method-signature directory.\"\n }\n },\n \"additionalProperties\": false\n },\n \"outputSchema\": {\n \"description\": \"Compact Service directory, or one exact Service contract with only its referenced type declarations.\"\n }\n }\n ]\n },\n {\n \"platform\": \"host\",\n \"id\": \"Event\",\n \"description\": \"Progressive Host Event discovery: compact listener directory, then one exact event contract.\",\n \"methods\": [\n {\n \"name\": \"listEvents\",\n \"description\": \"Progressive Host Event discovery: compact listener directory, then one exact event contract.\",\n \"inputSchema\": {\n \"type\": \"object\",\n \"properties\": {\n \"event\": {\n \"type\": \"string\",\n \"description\": \"Exact Event name. Omit it for the compact Event and listener-signature directory.\"\n }\n },\n \"additionalProperties\": false\n },\n \"outputSchema\": {\n \"description\": \"Compact Event directory, or one exact Event contract with only its referenced type declarations.\"\n }\n }\n ]\n },\n {\n \"platform\": \"host\",\n \"id\": \"Config\",\n \"description\": \"Progressive live plugin Config discovery: paged entry directory with schema status, then one entry's exact JSON Schema.\",\n \"methods\": [\n {\n \"name\": \"listConfigs\",\n \"description\": \"Progressive live plugin Config discovery: paged entry directory with schema status, then one entry's exact JSON Schema.\",\n \"inputSchema\": {\n \"type\": \"object\",\n \"properties\": {\n \"entry\": {\n \"type\": \"string\",\n \"description\": \"Exact Loader entry id from the directory; returns that entry's projected Config schema.\"\n },\n \"name\": {\n \"type\": \"string\",\n \"description\": \"Exact plugin package name; limits the directory to its entries.\"\n },\n \"offset\": {\n \"type\": \"number\",\n \"description\": \"Zero-based directory offset; defaults to 0.\"\n },\n \"limit\": {\n \"type\": \"number\",\n \"description\": \"Directory page size, from 1 to 100; defaults to 25.\"\n }\n },\n \"additionalProperties\": false\n },\n \"outputSchema\": {\n \"description\": \"One directory page of live entries with patch ids, Config status, total, and nextOffset, or one entry's projected JSON Schema with shared definitions, omission acceptance, and projection limitations.\"\n }\n }\n ]\n },\n {\n \"platform\": \"host\",\n \"id\": \"Tool\",\n \"description\": \"Tools visible to the requesting Agent, including scoped and dynamic registrations.\",\n \"methods\": [\n {\n \"name\": \"listTools\",\n \"description\": \"Return every Tool schema currently callable by this Agent.\",\n \"inputSchema\": {\n \"type\": \"object\",\n \"properties\": {},\n \"additionalProperties\": false\n },\n \"outputSchema\": {\n \"description\": \"JSON data owned by this inspect provider.\"\n }\n }\n ]\n }\n ]\n}"}],"isError":false,"id":"{{message:5}}"}},"sourceEventSeqs":[14],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":1}} {"type":"step/start","data":{"turn":1,"step":2}} -{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"tool-call","id":"advanced-direct-child","name":"subagent","arguments":"{\"description\":\"Check direct child\",\"prompt\":\"Reply with exactly DIRECT_CHILD_OK and nothing else.\",\"run_in_background\":false}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:6}}"},"usage":{"inputTokens":3,"outputTokens":3},"stream":[{"type":"chunk","time":1790493376601,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1790493376601,"index":0,"dt":[],"id":"advanced-direct-child","name":"subagent","args":["{\"description\":\"Check direct child\",\"prompt\":\"Reply with exactly DIRECT_CHILD_OK and nothing else.\",\"run_in_background\":false}"]},{"type":"chunk","time":1790493376601,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"advanced-direct-child","name":"subagent","arguments":"{\"description\":\"Check direct child\",\"prompt\":\"Reply with exactly DIRECT_CHILD_OK and nothing else.\",\"run_in_background\":false}"}}},{"type":"chunk","time":1790493376602,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}},{"type":"chunk","time":1790493376602,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} -{"type":"tool/call","data":{"turn":1,"step":2,"callId":"advanced-direct-child","name":"subagent","arguments":"{\"description\":\"Check direct child\",\"prompt\":\"Reply with exactly DIRECT_CHILD_OK and nothing else.\",\"run_in_background\":false}"}} -{"type":"subagent/catalog","data":{"version":0,"childId":"{{session:2}}","childCreatedAt":1790493376609,"mode":"continuable","label":"Check direct child"}} -{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent {{session:2}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"DIRECT_CHILD_OK"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{session:2}} finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:7}}"}]}} -{"type":"tool/result","data":{"turn":1,"step":2,"message":{"role":"tool","source":{"kind":"tool","callId":"advanced-direct-child"},"toolCallId":"advanced-direct-child","content":[{"type":"text","text":"started subagent {{session:2}}"}],"isError":false,"id":"{{message:8}}"}},"sourceEventSeqs":[19],"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"tool-call","id":"advanced-direct-child","name":"subagent","arguments":"{\"description\":\"Check direct child\",\"prompt\":\"Reply with exactly DIRECT_CHILD_OK and nothing else.\",\"run_in_background\":false,\"name\":\"worker-1\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:6}}"},"usage":{"inputTokens":3,"outputTokens":3},"stream":[{"type":"chunk","time":1792123791687,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792123791687,"index":0,"dt":[],"id":"advanced-direct-child","name":"subagent","args":["{\"description\":\"Check direct child\",\"prompt\":\"Reply with exactly DIRECT_CHILD_OK and nothing else.\",\"run_in_background\":false,\"name\":\"worker-1\"}"]},{"type":"chunk","time":1792123791687,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"advanced-direct-child","name":"subagent","arguments":"{\"description\":\"Check direct child\",\"prompt\":\"Reply with exactly DIRECT_CHILD_OK and nothing else.\",\"run_in_background\":false,\"name\":\"worker-1\"}"}}},{"type":"chunk","time":1792123791687,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}},{"type":"chunk","time":1792123791687,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":2,"callId":"advanced-direct-child","name":"subagent","arguments":"{\"description\":\"Check direct child\",\"prompt\":\"Reply with exactly DIRECT_CHILD_OK and nothing else.\",\"run_in_background\":false,\"name\":\"worker-1\"}"}} +{"type":"subagent/catalog","data":{"version":0,"childId":"{{session:2}}","childCreatedAt":1792123791692,"mode":"continuable","label":"Check direct child"}} +{"type":"subagent/named","data":{"name":"worker-1","id":"{{session:2}}"}} +{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent worker-1 finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"DIRECT_CHILD_OK"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:7}}"}]}} +{"type":"tool/result","data":{"turn":1,"step":2,"message":{"role":"tool","source":{"kind":"tool","callId":"advanced-direct-child"},"toolCallId":"advanced-direct-child","content":[{"type":"text","text":"started subagent worker-1"}],"isError":false,"id":"{{message:8}}"}},"sourceEventSeqs":[19],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":2}} {"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":1,"step":3}} -{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent {{session:2}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"DIRECT_CHILD_OK"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{session:2}} finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:7}}"},"surfaceOp":"append"} -{"type":"assistant/message","data":{"turn":1,"step":3,"message":{"role":"assistant","content":[{"type":"tool-call","id":"advanced-workflow","name":"workflow","arguments":"{\"script\":\"phase('Delegate')\\nconst reply = await agent('Reply with exactly WORKFLOW_CHILD_OK and nothing else.', { label: 'workflow-child' })\\nreturn { reply }\",\"meta\":{\"name\":\"advanced-acp-snapshot\",\"description\":\"exercise one workflow child through ACP\"}}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:9}}"},"usage":{"inputTokens":3,"outputTokens":3},"stream":[{"type":"chunk","time":1790493376676,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1790493376676,"index":0,"dt":[],"id":"advanced-workflow","name":"workflow","args":["{\"script\":\"phase('Delegate')\\nconst reply = await agent('Reply with exactly WORKFLOW_CHILD_OK and nothing else.', { label: 'workflow-child' })\\nreturn { reply }\",\"meta\":{\"name\":\"advanced-acp-snapshot\",\"description\":\"exercise one workflow child through ACP\"}}"]},{"type":"chunk","time":1790493376676,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"advanced-workflow","name":"workflow","arguments":"{\"script\":\"phase('Delegate')\\nconst reply = await agent('Reply with exactly WORKFLOW_CHILD_OK and nothing else.', { label: 'workflow-child' })\\nreturn { reply }\",\"meta\":{\"name\":\"advanced-acp-snapshot\",\"description\":\"exercise one workflow child through ACP\"}}"}}},{"type":"chunk","time":1790493376676,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}},{"type":"chunk","time":1790493376676,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent worker-1 finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"DIRECT_CHILD_OK"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:7}}"},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":3,"message":{"role":"assistant","content":[{"type":"tool-call","id":"advanced-workflow","name":"workflow","arguments":"{\"script\":\"phase('Delegate')\\nconst reply = await agent('Reply with exactly WORKFLOW_CHILD_OK and nothing else.', { label: 'workflow-child' })\\nreturn { reply }\",\"meta\":{\"name\":\"advanced-acp-snapshot\",\"description\":\"exercise one workflow child through ACP\"}}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:9}}"},"usage":{"inputTokens":3,"outputTokens":3},"stream":[{"type":"chunk","time":1792123791744,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792123791744,"index":0,"dt":[],"id":"advanced-workflow","name":"workflow","args":["{\"script\":\"phase('Delegate')\\nconst reply = await agent('Reply with exactly WORKFLOW_CHILD_OK and nothing else.', { label: 'workflow-child' })\\nreturn { reply }\",\"meta\":{\"name\":\"advanced-acp-snapshot\",\"description\":\"exercise one workflow child through ACP\"}}"]},{"type":"chunk","time":1792123791744,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"advanced-workflow","name":"workflow","arguments":"{\"script\":\"phase('Delegate')\\nconst reply = await agent('Reply with exactly WORKFLOW_CHILD_OK and nothing else.', { label: 'workflow-child' })\\nreturn { reply }\",\"meta\":{\"name\":\"advanced-acp-snapshot\",\"description\":\"exercise one workflow child through ACP\"}}"}}},{"type":"chunk","time":1792123791744,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}},{"type":"chunk","time":1792123791744,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} {"type":"tool/call","data":{"turn":1,"step":3,"callId":"advanced-workflow","name":"workflow","arguments":"{\"script\":\"phase('Delegate')\\nconst reply = await agent('Reply with exactly WORKFLOW_CHILD_OK and nothing else.', { label: 'workflow-child' })\\nreturn { reply }\",\"meta\":{\"name\":\"advanced-acp-snapshot\",\"description\":\"exercise one workflow child through ACP\"}}"}} {"type":"tool-workflow/run-start","data":{"runId":"{{workflow:1}}","name":"advanced-acp-snapshot"}} -{"type":"subagent/catalog","data":{"version":0,"childId":"{{session:3}}","childCreatedAt":1783950002000,"mode":"continuable","label":"advanced-acp-snapshot child 1"}} +{"type":"subagent/catalog","data":{"version":0,"childId":"{{session:3}}","childCreatedAt":1792123791857,"mode":"continuable","label":"advanced-acp-snapshot child 1"}} +{"type":"subagent/named","data":{"name":"workflow-{{workflow:1}}-1","id":"{{session:3}}"}} {"type":"tool-workflow/agent-start","data":{"runId":"{{workflow:1}}","seq":1,"label":"workflow-child","phase":"Delegate","childId":"{{session:3}}"}} {"type":"tool-workflow/agent-end","data":{"runId":"{{workflow:1}}","seq":1,"outcome":"completed"}} {"type":"tool-workflow/run-end","data":{"runId":"{{workflow:1}}","stopReason":"completed"}} -{"type":"tool/result","data":{"turn":1,"step":3,"message":{"role":"tool","source":{"kind":"tool","callId":"advanced-workflow"},"toolCallId":"advanced-workflow","content":[{"type":"text","text":"workflow \"advanced-acp-snapshot\" completed (1 agent).\nReturn value:\n{\n \"reply\": \"WORKFLOW_CHILD_OK\"\n}"}],"isError":false,"id":"{{message:10}}"}},"sourceEventSeqs":[28],"surfaceOp":"append"} +{"type":"tool/result","data":{"turn":1,"step":3,"message":{"role":"tool","source":{"kind":"tool","callId":"advanced-workflow"},"toolCallId":"advanced-workflow","content":[{"type":"text","text":"workflow \"advanced-acp-snapshot\" completed (1 agent).\nReturn value:\n{\n \"reply\": \"WORKFLOW_CHILD_OK\"\n}"}],"isError":false,"id":"{{message:10}}"}},"sourceEventSeqs":[29],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":3}} {"type":"step/start","data":{"turn":1,"step":4}} -{"type":"assistant/message","data":{"turn":1,"step":4,"message":{"role":"assistant","content":[{"type":"tool-call","id":"advanced-inspect-after","name":"cordis_inspect_list","arguments":"{}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:11}}"},"usage":{"inputTokens":3,"outputTokens":3},"stream":[{"type":"chunk","time":1790493376863,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1790493376864,"index":0,"dt":[],"id":"advanced-inspect-after","name":"cordis_inspect_list","args":["{}"]},{"type":"chunk","time":1790493376864,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"advanced-inspect-after","name":"cordis_inspect_list","arguments":"{}"}}},{"type":"chunk","time":1790493376864,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}},{"type":"chunk","time":1790493376864,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":4,"message":{"role":"assistant","content":[{"type":"tool-call","id":"advanced-inspect-after","name":"cordis_inspect_list","arguments":"{}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:11}}"},"usage":{"inputTokens":3,"outputTokens":3},"stream":[{"type":"chunk","time":1792123791929,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792123791929,"index":0,"dt":[],"id":"advanced-inspect-after","name":"cordis_inspect_list","args":["{}"]},{"type":"chunk","time":1792123791929,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"advanced-inspect-after","name":"cordis_inspect_list","arguments":"{}"}}},{"type":"chunk","time":1792123791929,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}},{"type":"chunk","time":1792123791929,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} {"type":"tool/call","data":{"turn":1,"step":4,"callId":"advanced-inspect-after","name":"cordis_inspect_list","arguments":"{}"}} -{"type":"tool/result","data":{"turn":1,"step":4,"message":{"role":"tool","source":{"kind":"tool","callId":"advanced-inspect-after"},"toolCallId":"advanced-inspect-after","content":[{"type":"text","text":"{\n \"providers\": [\n {\n \"platform\": \"host\",\n \"id\": \"Service\",\n \"description\": \"Progressive Host Service discovery: compact capability/signature directory, then one exact coding contract.\",\n \"methods\": [\n {\n \"name\": \"listService\",\n \"description\": \"Progressive Host Service discovery: compact capability/signature directory, then one exact coding contract.\",\n \"inputSchema\": {\n \"type\": \"object\",\n \"properties\": {\n \"service\": {\n \"type\": \"string\",\n \"description\": \"Exact Service key. Omit it for the compact Service and method-signature directory.\"\n }\n },\n \"additionalProperties\": false\n },\n \"outputSchema\": {\n \"description\": \"Compact Service directory, or one exact Service contract with only its referenced type declarations.\"\n }\n }\n ]\n },\n {\n \"platform\": \"host\",\n \"id\": \"Event\",\n \"description\": \"Progressive Host Event discovery: compact listener directory, then one exact event contract.\",\n \"methods\": [\n {\n \"name\": \"listEvents\",\n \"description\": \"Progressive Host Event discovery: compact listener directory, then one exact event contract.\",\n \"inputSchema\": {\n \"type\": \"object\",\n \"properties\": {\n \"event\": {\n \"type\": \"string\",\n \"description\": \"Exact Event name. Omit it for the compact Event and listener-signature directory.\"\n }\n },\n \"additionalProperties\": false\n },\n \"outputSchema\": {\n \"description\": \"Compact Event directory, or one exact Event contract with only its referenced type declarations.\"\n }\n }\n ]\n },\n {\n \"platform\": \"host\",\n \"id\": \"Config\",\n \"description\": \"Progressive live plugin Config discovery: paged entry directory with schema status, then one entry's exact JSON Schema.\",\n \"methods\": [\n {\n \"name\": \"listConfigs\",\n \"description\": \"Progressive live plugin Config discovery: paged entry directory with schema status, then one entry's exact JSON Schema.\",\n \"inputSchema\": {\n \"type\": \"object\",\n \"properties\": {\n \"entry\": {\n \"type\": \"string\",\n \"description\": \"Exact Loader entry id from the directory; returns that entry's projected Config schema.\"\n },\n \"name\": {\n \"type\": \"string\",\n \"description\": \"Exact plugin package name; limits the directory to its entries.\"\n },\n \"offset\": {\n \"type\": \"number\",\n \"description\": \"Zero-based directory offset; defaults to 0.\"\n },\n \"limit\": {\n \"type\": \"number\",\n \"description\": \"Directory page size, from 1 to 100; defaults to 25.\"\n }\n },\n \"additionalProperties\": false\n },\n \"outputSchema\": {\n \"description\": \"One directory page of live entries with patch ids, Config status, total, and nextOffset, or one entry's projected JSON Schema with shared definitions, omission acceptance, and projection limitations.\"\n }\n }\n ]\n },\n {\n \"platform\": \"host\",\n \"id\": \"Tool\",\n \"description\": \"Tools visible to the requesting Agent, including scoped and dynamic registrations.\",\n \"methods\": [\n {\n \"name\": \"listTools\",\n \"description\": \"Return every Tool schema currently callable by this Agent.\",\n \"inputSchema\": {\n \"type\": \"object\",\n \"properties\": {},\n \"additionalProperties\": false\n },\n \"outputSchema\": {\n \"description\": \"JSON data owned by this inspect provider.\"\n }\n }\n ]\n }\n ]\n}"}],"isError":false,"id":"{{message:12}}"}},"sourceEventSeqs":[38],"surfaceOp":"append"} +{"type":"tool/result","data":{"turn":1,"step":4,"message":{"role":"tool","source":{"kind":"tool","callId":"advanced-inspect-after"},"toolCallId":"advanced-inspect-after","content":[{"type":"text","text":"{\n \"providers\": [\n {\n \"platform\": \"host\",\n \"id\": \"Service\",\n \"description\": \"Progressive Host Service discovery: compact capability/signature directory, then one exact coding contract.\",\n \"methods\": [\n {\n \"name\": \"listService\",\n \"description\": \"Progressive Host Service discovery: compact capability/signature directory, then one exact coding contract.\",\n \"inputSchema\": {\n \"type\": \"object\",\n \"properties\": {\n \"service\": {\n \"type\": \"string\",\n \"description\": \"Exact Service key. Omit it for the compact Service and method-signature directory.\"\n }\n },\n \"additionalProperties\": false\n },\n \"outputSchema\": {\n \"description\": \"Compact Service directory, or one exact Service contract with only its referenced type declarations.\"\n }\n }\n ]\n },\n {\n \"platform\": \"host\",\n \"id\": \"Event\",\n \"description\": \"Progressive Host Event discovery: compact listener directory, then one exact event contract.\",\n \"methods\": [\n {\n \"name\": \"listEvents\",\n \"description\": \"Progressive Host Event discovery: compact listener directory, then one exact event contract.\",\n \"inputSchema\": {\n \"type\": \"object\",\n \"properties\": {\n \"event\": {\n \"type\": \"string\",\n \"description\": \"Exact Event name. Omit it for the compact Event and listener-signature directory.\"\n }\n },\n \"additionalProperties\": false\n },\n \"outputSchema\": {\n \"description\": \"Compact Event directory, or one exact Event contract with only its referenced type declarations.\"\n }\n }\n ]\n },\n {\n \"platform\": \"host\",\n \"id\": \"Config\",\n \"description\": \"Progressive live plugin Config discovery: paged entry directory with schema status, then one entry's exact JSON Schema.\",\n \"methods\": [\n {\n \"name\": \"listConfigs\",\n \"description\": \"Progressive live plugin Config discovery: paged entry directory with schema status, then one entry's exact JSON Schema.\",\n \"inputSchema\": {\n \"type\": \"object\",\n \"properties\": {\n \"entry\": {\n \"type\": \"string\",\n \"description\": \"Exact Loader entry id from the directory; returns that entry's projected Config schema.\"\n },\n \"name\": {\n \"type\": \"string\",\n \"description\": \"Exact plugin package name; limits the directory to its entries.\"\n },\n \"offset\": {\n \"type\": \"number\",\n \"description\": \"Zero-based directory offset; defaults to 0.\"\n },\n \"limit\": {\n \"type\": \"number\",\n \"description\": \"Directory page size, from 1 to 100; defaults to 25.\"\n }\n },\n \"additionalProperties\": false\n },\n \"outputSchema\": {\n \"description\": \"One directory page of live entries with patch ids, Config status, total, and nextOffset, or one entry's projected JSON Schema with shared definitions, omission acceptance, and projection limitations.\"\n }\n }\n ]\n },\n {\n \"platform\": \"host\",\n \"id\": \"Tool\",\n \"description\": \"Tools visible to the requesting Agent, including scoped and dynamic registrations.\",\n \"methods\": [\n {\n \"name\": \"listTools\",\n \"description\": \"Return every Tool schema currently callable by this Agent.\",\n \"inputSchema\": {\n \"type\": \"object\",\n \"properties\": {},\n \"additionalProperties\": false\n },\n \"outputSchema\": {\n \"description\": \"JSON data owned by this inspect provider.\"\n }\n }\n ]\n }\n ]\n}"}],"isError":false,"id":"{{message:12}}"}},"sourceEventSeqs":[40],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":4}} {"type":"step/start","data":{"turn":1,"step":5}} -{"type":"assistant/message","data":{"turn":1,"step":5,"message":{"role":"assistant","content":[{"type":"text","text":"ADVANCED_ACP_OK"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:13}}"},"usage":{"inputTokens":3,"outputTokens":3},"stream":[{"type":"chunk","time":1790493376883,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1790493376883,"index":0,"dt":[],"texts":["ADVANCED_ACP_OK"]},{"type":"chunk","time":1790493376883,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"ADVANCED_ACP_OK"}}},{"type":"chunk","time":1790493376883,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}},{"type":"chunk","time":1790493376884,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":5,"message":{"role":"assistant","content":[{"type":"text","text":"ADVANCED_ACP_OK"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:13}}"},"usage":{"inputTokens":3,"outputTokens":3},"stream":[{"type":"chunk","time":1792123791945,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1792123791945,"index":0,"dt":[],"texts":["ADVANCED_ACP_OK"]},{"type":"chunk","time":1792123791945,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"ADVANCED_ACP_OK"}}},{"type":"chunk","time":1792123791945,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}},{"type":"chunk","time":1792123791945,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":5}} {"type":"turn/end","data":{"turn":1,"reason":{"kind":"completed"}}} diff --git a/snapshots/session/advanced-toolchain/session.1.v4.jsonl b/snapshots/session/advanced-toolchain/session.1.v4.jsonl index cdce994743..71b749931e 100644 --- a/snapshots/session/advanced-toolchain/session.1.v4.jsonl +++ b/snapshots/session/advanced-toolchain/session.1.v4.jsonl @@ -3,12 +3,12 @@ {"type":"sandbox/mode","data":{"mode":"danger-full-access","source":"delegation"}} {"type":"approval/policy","data":{"policy":"never","source":"delegation"}} {"type":"permission/preset","data":{"preset":"danger-full-access"}} -{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Reply with exactly DIRECT_CHILD_OK and nothing else."},{"type":"text","text":"Your parent agent id is \"{{session:1}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{session:1}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:20}}"}]}} +{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Reply with exactly DIRECT_CHILD_OK and nothing else."},{"type":"text","text":"Your name is \"worker-1\". Your parent agent name is \"lead\". Before you finish, send your result to that agent with send_message({ name: \"lead\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:20}}"}]}} {"type":"turn/start","data":{"turn":1}} {"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":1,"step":1}} {"type":"system/message","data":{"turn":1,"step":1,"message":{"role":"system","content":[{"type":"text","text":"{{system}}"}],"source":{"kind":"system-prompt"},"id":"{{message:21}}"}},"surfaceOp":"append"} -{"type":"user/message","data":{"content":[{"type":"text","text":"Reply with exactly DIRECT_CHILD_OK and nothing else."},{"type":"text","text":"Your parent agent id is \"{{session:1}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{session:1}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:20}}"},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Reply with exactly DIRECT_CHILD_OK and nothing else."},{"type":"text","text":"Your name is \"worker-1\". Your parent agent name is \"lead\". Before you finish, send your result to that agent with send_message({ name: \"lead\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:20}}"},"surfaceOp":"append"} {"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations.\n\nApproval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).\n\nDelegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly.\n\nDelegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly.\n\nYou are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations."},{"name":"approval:policy","text":"Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."},{"name":"tool:subagent:depth","text":"Delegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly."},{"name":"tool:subagent_fork:depth","text":"Delegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly."},{"name":"subagent:delegation","text":"You are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}]},"role":"user","id":"{{message:22}}"},"surfaceOp":"append"} {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} diff --git a/snapshots/session/advanced-toolchain/session.v4.jsonl b/snapshots/session/advanced-toolchain/session.v4.jsonl index c0f1a22b8d..6259b5167b 100644 --- a/snapshots/session/advanced-toolchain/session.v4.jsonl +++ b/snapshots/session/advanced-toolchain/session.v4.jsonl @@ -12,7 +12,7 @@ {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":["bash","cordis_inspect_list","cordis_inspect_query","create_goal","edit","exit_plan_mode","get_goal","glob","grep","interrupt_agent","job_kill","job_list","job_output","list_agents","read","read_image","send_message","skill","subagent","subagent_fork","todo_write","update_goal","web_fetch","web_search","workflow","working_directory","write"]},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} {"type":"session/title","data":{"title":"Run this advanced flow exactly","messageSeqs":[8],"source":{"kind":"fallback"}}} -{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"advanced-inspect-before","name":"cordis_inspect_list","arguments":"{}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":3,"outputTokens":3},"stream":[{"type":"chunk","time":1791315715021,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1791315715022,"index":0,"dt":[],"id":"advanced-inspect-before","name":"cordis_inspect_list","args":["{}"]},{"type":"chunk","time":1791315715022,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"advanced-inspect-before","name":"cordis_inspect_list","arguments":"{}"}}},{"type":"chunk","time":1791315715022,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}},{"type":"chunk","time":1791315715022,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"advanced-inspect-before","name":"cordis_inspect_list","arguments":"{}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":3,"outputTokens":3},"stream":[{"type":"chunk","time":1792123960954,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792123960954,"index":0,"dt":[],"id":"advanced-inspect-before","name":"cordis_inspect_list","args":["{}"]},{"type":"chunk","time":1792123960954,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"advanced-inspect-before","name":"cordis_inspect_list","arguments":"{}"}}},{"type":"chunk","time":1792123960954,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}},{"type":"chunk","time":1792123960954,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} {"type":"tool/call","data":{"turn":1,"step":1,"callId":"advanced-inspect-before","name":"cordis_inspect_list","arguments":"{}"}} {"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"advanced-inspect-before"},"toolCallId":"advanced-inspect-before","content":[{"type":"text","text":"{\n \"providers\": [\n {\n \"platform\": \"host\",\n \"id\": \"Service\",\n \"description\": \"Progressive Host Service discovery: compact capability/signature directory, then one exact coding contract.\",\n \"methods\": [\n {\n \"name\": \"listService\",\n \"description\": \"Progressive Host Service discovery: compact capability/signature directory, then one exact coding contract.\",\n \"inputSchema\": {\n \"type\": \"object\",\n \"properties\": {\n \"service\": {\n \"type\": \"string\",\n \"description\": \"Exact Service key. Omit it for the compact Service and method-signature directory.\"\n }\n },\n \"additionalProperties\": false\n },\n \"outputSchema\": {\n \"description\": \"Compact Service directory, or one exact Service contract with only its referenced type declarations.\"\n }\n }\n ]\n },\n {\n \"platform\": \"host\",\n \"id\": \"Event\",\n \"description\": \"Progressive Host Event discovery: compact listener directory, then one exact event contract.\",\n \"methods\": [\n {\n \"name\": \"listEvents\",\n \"description\": \"Progressive Host Event discovery: compact listener directory, then one exact event contract.\",\n \"inputSchema\": {\n \"type\": \"object\",\n \"properties\": {\n \"event\": {\n \"type\": \"string\",\n \"description\": \"Exact Event name. Omit it for the compact Event and listener-signature directory.\"\n }\n },\n \"additionalProperties\": false\n },\n \"outputSchema\": {\n \"description\": \"Compact Event directory, or one exact Event contract with only its referenced type declarations.\"\n }\n }\n ]\n },\n {\n \"platform\": \"host\",\n \"id\": \"Config\",\n \"description\": \"Progressive live plugin Config discovery: paged entry directory with schema status, then one entry's exact JSON Schema.\",\n \"methods\": [\n {\n \"name\": \"listConfigs\",\n \"description\": \"Progressive live plugin Config discovery: paged entry directory with schema status, then one entry's exact JSON Schema.\",\n \"inputSchema\": {\n \"type\": \"object\",\n \"properties\": {\n \"entry\": {\n \"type\": \"string\",\n \"description\": \"Exact Loader entry id from the directory; returns that entry's projected Config schema.\"\n },\n \"name\": {\n \"type\": \"string\",\n \"description\": \"Exact plugin package name; limits the directory to its entries.\"\n },\n \"offset\": {\n \"type\": \"number\",\n \"description\": \"Zero-based directory offset; defaults to 0.\"\n },\n \"limit\": {\n \"type\": \"number\",\n \"description\": \"Directory page size, from 1 to 100; defaults to 25.\"\n }\n },\n \"additionalProperties\": false\n },\n \"outputSchema\": {\n \"description\": \"One directory page of live entries with patch ids, Config status, total, and nextOffset, or one entry's projected JSON Schema with shared definitions, omission acceptance, and projection limitations.\"\n }\n }\n ]\n },\n {\n \"platform\": \"host\",\n \"id\": \"Tool\",\n \"description\": \"Tools visible to the requesting Agent, including scoped and dynamic registrations.\",\n \"methods\": [\n {\n \"name\": \"listTools\",\n \"description\": \"Return every Tool schema currently callable by this Agent.\",\n \"inputSchema\": {\n \"type\": \"object\",\n \"properties\": {},\n \"additionalProperties\": false\n },\n \"outputSchema\": {\n \"description\": \"JSON data owned by this inspect provider.\"\n }\n }\n ]\n }\n ]\n}"}],"isError":false,"id":"{{message:5}}"}},"sourceEventSeqs":[14],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":1}} @@ -20,7 +20,7 @@ {"type":"system/message","data":{"turn":1,"step":2,"message":{"role":"system","content":[{"type":"text","text":"{{system}}"}],"source":{"kind":"system-prompt"},"id":"{{message:6}}"}},"sourceEventSeqs":[7],"surfaceOp":{"op":"replace","startSeq":7,"endSeq":7}} {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":["run_code"]},"reason":"change","startsSeries":true}} {"type":"developer/message","data":{"turn":1,"step":2,"message":{"source":{"kind":"tool-registry"},"content":[{"type":"tool-addition","toolName":"run_code"},{"type":"tool-removal","toolName":"bash"},{"type":"tool-removal","toolName":"cordis_inspect_list"},{"type":"tool-removal","toolName":"cordis_inspect_query"},{"type":"tool-removal","toolName":"create_goal"},{"type":"tool-removal","toolName":"edit"},{"type":"tool-removal","toolName":"exit_plan_mode"},{"type":"tool-removal","toolName":"get_goal"},{"type":"tool-removal","toolName":"glob"},{"type":"tool-removal","toolName":"grep"},{"type":"tool-removal","toolName":"interrupt_agent"},{"type":"tool-removal","toolName":"job_kill"},{"type":"tool-removal","toolName":"job_list"},{"type":"tool-removal","toolName":"job_output"},{"type":"tool-removal","toolName":"list_agents"},{"type":"tool-removal","toolName":"read"},{"type":"tool-removal","toolName":"read_image"},{"type":"tool-removal","toolName":"send_message"},{"type":"tool-removal","toolName":"skill"},{"type":"tool-removal","toolName":"subagent"},{"type":"tool-removal","toolName":"subagent_fork"},{"type":"tool-removal","toolName":"todo_write"},{"type":"tool-removal","toolName":"update_goal"},{"type":"tool-removal","toolName":"web_fetch"},{"type":"tool-removal","toolName":"web_search"},{"type":"tool-removal","toolName":"workflow"},{"type":"tool-removal","toolName":"working_directory"},{"type":"tool-removal","toolName":"write"}],"role":"developer","id":"{{message:7}}"},"headerSeq":19},"surfaceOp":"append"} -{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"tool-call","id":"advanced-code","name":"run_code","arguments":"{\"code\":\"const inspected = await tools.cordis_inspect_list({}); return inspected.providers.map(provider => provider.id);\",\"description\":\"Discover runtime APIs through PTC\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:8}}"},"usage":{"inputTokens":3,"outputTokens":3},"stream":[{"type":"chunk","time":1791315715055,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1791315715055,"index":0,"dt":[],"id":"advanced-code","name":"run_code","args":["{\"code\":\"const inspected = await tools.cordis_inspect_list({}); return inspected.providers.map(provider => provider.id);\",\"description\":\"Discover runtime APIs through PTC\"}"]},{"type":"chunk","time":1791315715055,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"advanced-code","name":"run_code","arguments":"{\"code\":\"const inspected = await tools.cordis_inspect_list({}); return inspected.providers.map(provider => provider.id);\",\"description\":\"Discover runtime APIs through PTC\"}"}}},{"type":"chunk","time":1791315715055,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}},{"type":"chunk","time":1791315715055,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"tool-call","id":"advanced-code","name":"run_code","arguments":"{\"code\":\"const inspected = await tools.cordis_inspect_list({}); return inspected.providers.map(provider => provider.id);\",\"description\":\"Discover runtime APIs through PTC\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:8}}"},"usage":{"inputTokens":3,"outputTokens":3},"stream":[{"type":"chunk","time":1792123960977,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792123960977,"index":0,"dt":[],"id":"advanced-code","name":"run_code","args":["{\"code\":\"const inspected = await tools.cordis_inspect_list({}); return inspected.providers.map(provider => provider.id);\",\"description\":\"Discover runtime APIs through PTC\"}"]},{"type":"chunk","time":1792123960977,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"advanced-code","name":"run_code","arguments":"{\"code\":\"const inspected = await tools.cordis_inspect_list({}); return inspected.providers.map(provider => provider.id);\",\"description\":\"Discover runtime APIs through PTC\"}"}}},{"type":"chunk","time":1792123960977,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}},{"type":"chunk","time":1792123960977,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} {"type":"tool/call","data":{"turn":1,"step":2,"callId":"advanced-code","name":"run_code","arguments":"{\"code\":\"const inspected = await tools.cordis_inspect_list({}); return inspected.providers.map(provider => provider.id);\",\"description\":\"Discover runtime APIs through PTC\"}"}} {"type":"tool/ptc-dispatch-start","data":{"rootCallId":"advanced-code","parentCallId":"advanced-code","subCallId":"advanced-code:ptc:1","name":"cordis_inspect_list","arguments":{}}} {"type":"tool/ptc-dispatch","data":{"rootCallId":"advanced-code","parentCallId":"advanced-code","subCallId":"advanced-code:ptc:1","name":"cordis_inspect_list","arguments":{},"isError":false,"content":[{"type":"text","text":"{\n \"providers\": [\n {\n \"platform\": \"host\",\n \"id\": \"Service\",\n \"description\": \"Progressive Host Service discovery: compact capability/signature directory, then one exact coding contract.\",\n \"methods\": [\n {\n \"name\": \"listService\",\n \"description\": \"Progressive Host Service discovery: compact capability/signature directory, then one exact coding contract.\",\n \"inputSchema\": {\n \"type\": \"object\",\n \"properties\": {\n \"service\": {\n \"type\": \"string\",\n \"description\": \"Exact Service key. Omit it for the compact Service and method-signature directory.\"\n }\n },\n \"additionalProperties\": false\n },\n \"outputSchema\": {\n \"description\": \"Compact Service directory, or one exact Service contract with only its referenced type declarations.\"\n }\n }\n ]\n },\n {\n \"platform\": \"host\",\n \"id\": \"Event\",\n \"description\": \"Progressive Host Event discovery: compact listener directory, then one exact event contract.\",\n \"methods\": [\n {\n \"name\": \"listEvents\",\n \"description\": \"Progressive Host Event discovery: compact listener directory, then one exact event contract.\",\n \"inputSchema\": {\n \"type\": \"object\",\n \"properties\": {\n \"event\": {\n \"type\": \"string\",\n \"description\": \"Exact Event name. Omit it for the compact Event and listener-signature directory.\"\n }\n },\n \"additionalProperties\": false\n },\n \"outputSchema\": {\n \"description\": \"Compact Event directory, or one exact Event contract with only its referenced type declarations.\"\n }\n }\n ]\n },\n {\n \"platform\": \"host\",\n \"id\": \"Config\",\n \"description\": \"Progressive live plugin Config discovery: paged entry directory with schema status, then one entry's exact JSON Schema.\",\n \"methods\": [\n {\n \"name\": \"listConfigs\",\n \"description\": \"Progressive live plugin Config discovery: paged entry directory with schema status, then one entry's exact JSON Schema.\",\n \"inputSchema\": {\n \"type\": \"object\",\n \"properties\": {\n \"entry\": {\n \"type\": \"string\",\n \"description\": \"Exact Loader entry id from the directory; returns that entry's projected Config schema.\"\n },\n \"name\": {\n \"type\": \"string\",\n \"description\": \"Exact plugin package name; limits the directory to its entries.\"\n },\n \"offset\": {\n \"type\": \"number\",\n \"description\": \"Zero-based directory offset; defaults to 0.\"\n },\n \"limit\": {\n \"type\": \"number\",\n \"description\": \"Directory page size, from 1 to 100; defaults to 25.\"\n }\n },\n \"additionalProperties\": false\n },\n \"outputSchema\": {\n \"description\": \"One directory page of live entries with patch ids, Config status, total, and nextOffset, or one entry's projected JSON Schema with shared definitions, omission acceptance, and projection limitations.\"\n }\n }\n ]\n },\n {\n \"platform\": \"host\",\n \"id\": \"Tool\",\n \"description\": \"Tools visible to the requesting Agent, including scoped and dynamic registrations.\",\n \"methods\": [\n {\n \"name\": \"listTools\",\n \"description\": \"Return every Tool schema currently callable by this Agent.\",\n \"inputSchema\": {\n \"type\": \"object\",\n \"properties\": {},\n \"additionalProperties\": false\n },\n \"outputSchema\": {\n \"description\": \"JSON data owned by this inspect provider.\"\n }\n }\n ]\n }\n ]\n}"}]}} @@ -30,30 +30,32 @@ {"type":"system/message","data":{"turn":1,"step":3,"message":{"role":"system","content":[{"type":"text","text":"{{system}}"}],"source":{"kind":"system-prompt"},"id":"{{message:10}}"}},"sourceEventSeqs":[18],"surfaceOp":{"op":"replace","startSeq":18,"endSeq":18}} {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":["bash","cordis_inspect_list","cordis_inspect_query","create_goal","edit","exit_plan_mode","get_goal","glob","grep","interrupt_agent","job_kill","job_list","job_output","list_agents","read","read_image","send_message","skill","subagent","subagent_fork","todo_write","update_goal","web_fetch","web_search","workflow","working_directory","write"]},"reason":"change","startsSeries":true}} {"type":"developer/message","data":{"turn":1,"step":3,"message":{"source":{"kind":"tool-registry"},"content":[{"type":"tool-addition","toolName":"bash"},{"type":"tool-addition","toolName":"cordis_inspect_list"},{"type":"tool-addition","toolName":"cordis_inspect_query"},{"type":"tool-addition","toolName":"create_goal"},{"type":"tool-addition","toolName":"edit"},{"type":"tool-addition","toolName":"exit_plan_mode"},{"type":"tool-addition","toolName":"get_goal"},{"type":"tool-addition","toolName":"glob"},{"type":"tool-addition","toolName":"grep"},{"type":"tool-addition","toolName":"interrupt_agent"},{"type":"tool-addition","toolName":"job_kill"},{"type":"tool-addition","toolName":"job_list"},{"type":"tool-addition","toolName":"job_output"},{"type":"tool-addition","toolName":"list_agents"},{"type":"tool-addition","toolName":"read"},{"type":"tool-addition","toolName":"read_image"},{"type":"tool-addition","toolName":"send_message"},{"type":"tool-addition","toolName":"skill"},{"type":"tool-addition","toolName":"subagent"},{"type":"tool-addition","toolName":"subagent_fork"},{"type":"tool-addition","toolName":"todo_write"},{"type":"tool-addition","toolName":"update_goal"},{"type":"tool-addition","toolName":"web_fetch"},{"type":"tool-addition","toolName":"web_search"},{"type":"tool-addition","toolName":"workflow"},{"type":"tool-addition","toolName":"working_directory"},{"type":"tool-addition","toolName":"write"},{"type":"tool-removal","toolName":"run_code"}],"role":"developer","id":"{{message:11}}"},"headerSeq":29},"surfaceOp":"append"} -{"type":"assistant/message","data":{"turn":1,"step":3,"message":{"role":"assistant","content":[{"type":"tool-call","id":"advanced-direct-child","name":"subagent","arguments":"{\"description\":\"Check direct child\",\"prompt\":\"Reply with exactly DIRECT_CHILD_OK and nothing else.\",\"run_in_background\":false}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:12}}"},"usage":{"inputTokens":3,"outputTokens":3},"stream":[{"type":"chunk","time":1791315715200,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1791315715200,"index":0,"dt":[],"id":"advanced-direct-child","name":"subagent","args":["{\"description\":\"Check direct child\",\"prompt\":\"Reply with exactly DIRECT_CHILD_OK and nothing else.\",\"run_in_background\":false}"]},{"type":"chunk","time":1791315715200,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"advanced-direct-child","name":"subagent","arguments":"{\"description\":\"Check direct child\",\"prompt\":\"Reply with exactly DIRECT_CHILD_OK and nothing else.\",\"run_in_background\":false}"}}},{"type":"chunk","time":1791315715200,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}},{"type":"chunk","time":1791315715200,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} -{"type":"tool/call","data":{"turn":1,"step":3,"callId":"advanced-direct-child","name":"subagent","arguments":"{\"description\":\"Check direct child\",\"prompt\":\"Reply with exactly DIRECT_CHILD_OK and nothing else.\",\"run_in_background\":false}"}} -{"type":"subagent/catalog","data":{"version":0,"childId":"{{session:2}}","childCreatedAt":1791315715221,"mode":"continuable","label":"Check direct child"}} -{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent {{session:2}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"DIRECT_CHILD_OK"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{session:2}} finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:13}}"}]}} -{"type":"tool/result","data":{"turn":1,"step":3,"message":{"role":"tool","source":{"kind":"tool","callId":"advanced-direct-child"},"toolCallId":"advanced-direct-child","content":[{"type":"text","text":"started subagent {{session:2}}"}],"isError":false,"id":"{{message:14}}"}},"sourceEventSeqs":[32],"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":3,"message":{"role":"assistant","content":[{"type":"tool-call","id":"advanced-direct-child","name":"subagent","arguments":"{\"description\":\"Check direct child\",\"prompt\":\"Reply with exactly DIRECT_CHILD_OK and nothing else.\",\"run_in_background\":false,\"name\":\"worker-1\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:12}}"},"usage":{"inputTokens":3,"outputTokens":3},"stream":[{"type":"chunk","time":1792123961121,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792123961121,"index":0,"dt":[],"id":"advanced-direct-child","name":"subagent","args":["{\"description\":\"Check direct child\",\"prompt\":\"Reply with exactly DIRECT_CHILD_OK and nothing else.\",\"run_in_background\":false,\"name\":\"worker-1\"}"]},{"type":"chunk","time":1792123961121,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"advanced-direct-child","name":"subagent","arguments":"{\"description\":\"Check direct child\",\"prompt\":\"Reply with exactly DIRECT_CHILD_OK and nothing else.\",\"run_in_background\":false,\"name\":\"worker-1\"}"}}},{"type":"chunk","time":1792123961121,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}},{"type":"chunk","time":1792123961121,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":3,"callId":"advanced-direct-child","name":"subagent","arguments":"{\"description\":\"Check direct child\",\"prompt\":\"Reply with exactly DIRECT_CHILD_OK and nothing else.\",\"run_in_background\":false,\"name\":\"worker-1\"}"}} +{"type":"subagent/catalog","data":{"version":0,"childId":"{{session:2}}","childCreatedAt":1792123961127,"mode":"continuable","label":"Check direct child"}} +{"type":"subagent/named","data":{"name":"worker-1","id":"{{session:2}}"}} +{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent worker-1 finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"DIRECT_CHILD_OK"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:13}}"}]}} +{"type":"tool/result","data":{"turn":1,"step":3,"message":{"role":"tool","source":{"kind":"tool","callId":"advanced-direct-child"},"toolCallId":"advanced-direct-child","content":[{"type":"text","text":"started subagent worker-1"}],"isError":false,"id":"{{message:14}}"}},"sourceEventSeqs":[32],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":3}} {"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":1,"step":4}} -{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent {{session:2}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"DIRECT_CHILD_OK"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{session:2}} finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:13}}"},"surfaceOp":"append"} -{"type":"assistant/message","data":{"turn":1,"step":4,"message":{"role":"assistant","content":[{"type":"tool-call","id":"advanced-workflow","name":"workflow","arguments":"{\"script\":\"phase('Delegate')\\nconst reply = await agent('Reply with exactly WORKFLOW_CHILD_OK and nothing else.', { label: 'workflow-child' })\\nreturn { reply }\",\"meta\":{\"name\":\"advanced-headless-snapshot\",\"description\":\"exercise one workflow child through the headless agent\"}}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:15}}"},"usage":{"inputTokens":3,"outputTokens":3},"stream":[{"type":"chunk","time":1791315715326,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1791315715326,"index":0,"dt":[],"id":"advanced-workflow","name":"workflow","args":["{\"script\":\"phase('Delegate')\\nconst reply = await agent('Reply with exactly WORKFLOW_CHILD_OK and nothing else.', { label: 'workflow-child' })\\nreturn { reply }\",\"meta\":{\"name\":\"advanced-headless-snapshot\",\"description\":\"exercise one workflow child through the headless agent\"}}"]},{"type":"chunk","time":1791315715326,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"advanced-workflow","name":"workflow","arguments":"{\"script\":\"phase('Delegate')\\nconst reply = await agent('Reply with exactly WORKFLOW_CHILD_OK and nothing else.', { label: 'workflow-child' })\\nreturn { reply }\",\"meta\":{\"name\":\"advanced-headless-snapshot\",\"description\":\"exercise one workflow child through the headless agent\"}}"}}},{"type":"chunk","time":1791315715326,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}},{"type":"chunk","time":1791315715326,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent worker-1 finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"DIRECT_CHILD_OK"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:13}}"},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":4,"message":{"role":"assistant","content":[{"type":"tool-call","id":"advanced-workflow","name":"workflow","arguments":"{\"script\":\"phase('Delegate')\\nconst reply = await agent('Reply with exactly WORKFLOW_CHILD_OK and nothing else.', { label: 'workflow-child' })\\nreturn { reply }\",\"meta\":{\"name\":\"advanced-headless-snapshot\",\"description\":\"exercise one workflow child through the headless agent\"}}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:15}}"},"usage":{"inputTokens":3,"outputTokens":3},"stream":[{"type":"chunk","time":1792123961192,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792123961192,"index":0,"dt":[],"id":"advanced-workflow","name":"workflow","args":["{\"script\":\"phase('Delegate')\\nconst reply = await agent('Reply with exactly WORKFLOW_CHILD_OK and nothing else.', { label: 'workflow-child' })\\nreturn { reply }\",\"meta\":{\"name\":\"advanced-headless-snapshot\",\"description\":\"exercise one workflow child through the headless agent\"}}"]},{"type":"chunk","time":1792123961192,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"advanced-workflow","name":"workflow","arguments":"{\"script\":\"phase('Delegate')\\nconst reply = await agent('Reply with exactly WORKFLOW_CHILD_OK and nothing else.', { label: 'workflow-child' })\\nreturn { reply }\",\"meta\":{\"name\":\"advanced-headless-snapshot\",\"description\":\"exercise one workflow child through the headless agent\"}}"}}},{"type":"chunk","time":1792123961192,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}},{"type":"chunk","time":1792123961192,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} {"type":"tool/call","data":{"turn":1,"step":4,"callId":"advanced-workflow","name":"workflow","arguments":"{\"script\":\"phase('Delegate')\\nconst reply = await agent('Reply with exactly WORKFLOW_CHILD_OK and nothing else.', { label: 'workflow-child' })\\nreturn { reply }\",\"meta\":{\"name\":\"advanced-headless-snapshot\",\"description\":\"exercise one workflow child through the headless agent\"}}"}} {"type":"tool-workflow/run-start","data":{"runId":"{{workflow:1}}","name":"advanced-headless-snapshot"}} -{"type":"subagent/catalog","data":{"version":0,"childId":"{{session:3}}","childCreatedAt":1791315715414,"mode":"continuable","label":"advanced-headless-snapshot child 1"}} +{"type":"subagent/catalog","data":{"version":0,"childId":"{{session:3}}","childCreatedAt":1792123961283,"mode":"continuable","label":"advanced-headless-snapshot child 1"}} +{"type":"subagent/named","data":{"name":"workflow-{{workflow:1}}-1","id":"{{session:3}}"}} {"type":"tool-workflow/agent-start","data":{"runId":"{{workflow:1}}","seq":1,"label":"workflow-child","phase":"Delegate","childId":"{{session:3}}"}} {"type":"tool-workflow/agent-end","data":{"runId":"{{workflow:1}}","seq":1,"outcome":"completed"}} {"type":"tool-workflow/run-end","data":{"runId":"{{workflow:1}}","stopReason":"completed"}} -{"type":"tool/result","data":{"turn":1,"step":4,"message":{"role":"tool","source":{"kind":"tool","callId":"advanced-workflow"},"toolCallId":"advanced-workflow","content":[{"type":"text","text":"workflow \"advanced-headless-snapshot\" completed (1 agent).\nReturn value:\n{\n \"reply\": \"WORKFLOW_CHILD_OK\"\n}"}],"isError":false,"id":"{{message:16}}"}},"sourceEventSeqs":[41],"surfaceOp":"append"} +{"type":"tool/result","data":{"turn":1,"step":4,"message":{"role":"tool","source":{"kind":"tool","callId":"advanced-workflow"},"toolCallId":"advanced-workflow","content":[{"type":"text","text":"workflow \"advanced-headless-snapshot\" completed (1 agent).\nReturn value:\n{\n \"reply\": \"WORKFLOW_CHILD_OK\"\n}"}],"isError":false,"id":"{{message:16}}"}},"sourceEventSeqs":[42],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":4}} {"type":"step/start","data":{"turn":1,"step":5}} -{"type":"assistant/message","data":{"turn":1,"step":5,"message":{"role":"assistant","content":[{"type":"tool-call","id":"advanced-inspect-after","name":"cordis_inspect_list","arguments":"{}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:17}}"},"usage":{"inputTokens":3,"outputTokens":3},"stream":[{"type":"chunk","time":1791315715551,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1791315715551,"index":0,"dt":[],"id":"advanced-inspect-after","name":"cordis_inspect_list","args":["{}"]},{"type":"chunk","time":1791315715551,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"advanced-inspect-after","name":"cordis_inspect_list","arguments":"{}"}}},{"type":"chunk","time":1791315715551,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}},{"type":"chunk","time":1791315715551,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":5,"message":{"role":"assistant","content":[{"type":"tool-call","id":"advanced-inspect-after","name":"cordis_inspect_list","arguments":"{}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:17}}"},"usage":{"inputTokens":3,"outputTokens":3},"stream":[{"type":"chunk","time":1792123961354,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792123961354,"index":0,"dt":[],"id":"advanced-inspect-after","name":"cordis_inspect_list","args":["{}"]},{"type":"chunk","time":1792123961354,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"advanced-inspect-after","name":"cordis_inspect_list","arguments":"{}"}}},{"type":"chunk","time":1792123961354,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}},{"type":"chunk","time":1792123961354,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} {"type":"tool/call","data":{"turn":1,"step":5,"callId":"advanced-inspect-after","name":"cordis_inspect_list","arguments":"{}"}} -{"type":"tool/result","data":{"turn":1,"step":5,"message":{"role":"tool","source":{"kind":"tool","callId":"advanced-inspect-after"},"toolCallId":"advanced-inspect-after","content":[{"type":"text","text":"{\n \"providers\": [\n {\n \"platform\": \"host\",\n \"id\": \"Service\",\n \"description\": \"Progressive Host Service discovery: compact capability/signature directory, then one exact coding contract.\",\n \"methods\": [\n {\n \"name\": \"listService\",\n \"description\": \"Progressive Host Service discovery: compact capability/signature directory, then one exact coding contract.\",\n \"inputSchema\": {\n \"type\": \"object\",\n \"properties\": {\n \"service\": {\n \"type\": \"string\",\n \"description\": \"Exact Service key. Omit it for the compact Service and method-signature directory.\"\n }\n },\n \"additionalProperties\": false\n },\n \"outputSchema\": {\n \"description\": \"Compact Service directory, or one exact Service contract with only its referenced type declarations.\"\n }\n }\n ]\n },\n {\n \"platform\": \"host\",\n \"id\": \"Event\",\n \"description\": \"Progressive Host Event discovery: compact listener directory, then one exact event contract.\",\n \"methods\": [\n {\n \"name\": \"listEvents\",\n \"description\": \"Progressive Host Event discovery: compact listener directory, then one exact event contract.\",\n \"inputSchema\": {\n \"type\": \"object\",\n \"properties\": {\n \"event\": {\n \"type\": \"string\",\n \"description\": \"Exact Event name. Omit it for the compact Event and listener-signature directory.\"\n }\n },\n \"additionalProperties\": false\n },\n \"outputSchema\": {\n \"description\": \"Compact Event directory, or one exact Event contract with only its referenced type declarations.\"\n }\n }\n ]\n },\n {\n \"platform\": \"host\",\n \"id\": \"Config\",\n \"description\": \"Progressive live plugin Config discovery: paged entry directory with schema status, then one entry's exact JSON Schema.\",\n \"methods\": [\n {\n \"name\": \"listConfigs\",\n \"description\": \"Progressive live plugin Config discovery: paged entry directory with schema status, then one entry's exact JSON Schema.\",\n \"inputSchema\": {\n \"type\": \"object\",\n \"properties\": {\n \"entry\": {\n \"type\": \"string\",\n \"description\": \"Exact Loader entry id from the directory; returns that entry's projected Config schema.\"\n },\n \"name\": {\n \"type\": \"string\",\n \"description\": \"Exact plugin package name; limits the directory to its entries.\"\n },\n \"offset\": {\n \"type\": \"number\",\n \"description\": \"Zero-based directory offset; defaults to 0.\"\n },\n \"limit\": {\n \"type\": \"number\",\n \"description\": \"Directory page size, from 1 to 100; defaults to 25.\"\n }\n },\n \"additionalProperties\": false\n },\n \"outputSchema\": {\n \"description\": \"One directory page of live entries with patch ids, Config status, total, and nextOffset, or one entry's projected JSON Schema with shared definitions, omission acceptance, and projection limitations.\"\n }\n }\n ]\n },\n {\n \"platform\": \"host\",\n \"id\": \"Tool\",\n \"description\": \"Tools visible to the requesting Agent, including scoped and dynamic registrations.\",\n \"methods\": [\n {\n \"name\": \"listTools\",\n \"description\": \"Return every Tool schema currently callable by this Agent.\",\n \"inputSchema\": {\n \"type\": \"object\",\n \"properties\": {},\n \"additionalProperties\": false\n },\n \"outputSchema\": {\n \"description\": \"JSON data owned by this inspect provider.\"\n }\n }\n ]\n }\n ]\n}"}],"isError":false,"id":"{{message:18}}"}},"sourceEventSeqs":[51],"surfaceOp":"append"} +{"type":"tool/result","data":{"turn":1,"step":5,"message":{"role":"tool","source":{"kind":"tool","callId":"advanced-inspect-after"},"toolCallId":"advanced-inspect-after","content":[{"type":"text","text":"{\n \"providers\": [\n {\n \"platform\": \"host\",\n \"id\": \"Service\",\n \"description\": \"Progressive Host Service discovery: compact capability/signature directory, then one exact coding contract.\",\n \"methods\": [\n {\n \"name\": \"listService\",\n \"description\": \"Progressive Host Service discovery: compact capability/signature directory, then one exact coding contract.\",\n \"inputSchema\": {\n \"type\": \"object\",\n \"properties\": {\n \"service\": {\n \"type\": \"string\",\n \"description\": \"Exact Service key. Omit it for the compact Service and method-signature directory.\"\n }\n },\n \"additionalProperties\": false\n },\n \"outputSchema\": {\n \"description\": \"Compact Service directory, or one exact Service contract with only its referenced type declarations.\"\n }\n }\n ]\n },\n {\n \"platform\": \"host\",\n \"id\": \"Event\",\n \"description\": \"Progressive Host Event discovery: compact listener directory, then one exact event contract.\",\n \"methods\": [\n {\n \"name\": \"listEvents\",\n \"description\": \"Progressive Host Event discovery: compact listener directory, then one exact event contract.\",\n \"inputSchema\": {\n \"type\": \"object\",\n \"properties\": {\n \"event\": {\n \"type\": \"string\",\n \"description\": \"Exact Event name. Omit it for the compact Event and listener-signature directory.\"\n }\n },\n \"additionalProperties\": false\n },\n \"outputSchema\": {\n \"description\": \"Compact Event directory, or one exact Event contract with only its referenced type declarations.\"\n }\n }\n ]\n },\n {\n \"platform\": \"host\",\n \"id\": \"Config\",\n \"description\": \"Progressive live plugin Config discovery: paged entry directory with schema status, then one entry's exact JSON Schema.\",\n \"methods\": [\n {\n \"name\": \"listConfigs\",\n \"description\": \"Progressive live plugin Config discovery: paged entry directory with schema status, then one entry's exact JSON Schema.\",\n \"inputSchema\": {\n \"type\": \"object\",\n \"properties\": {\n \"entry\": {\n \"type\": \"string\",\n \"description\": \"Exact Loader entry id from the directory; returns that entry's projected Config schema.\"\n },\n \"name\": {\n \"type\": \"string\",\n \"description\": \"Exact plugin package name; limits the directory to its entries.\"\n },\n \"offset\": {\n \"type\": \"number\",\n \"description\": \"Zero-based directory offset; defaults to 0.\"\n },\n \"limit\": {\n \"type\": \"number\",\n \"description\": \"Directory page size, from 1 to 100; defaults to 25.\"\n }\n },\n \"additionalProperties\": false\n },\n \"outputSchema\": {\n \"description\": \"One directory page of live entries with patch ids, Config status, total, and nextOffset, or one entry's projected JSON Schema with shared definitions, omission acceptance, and projection limitations.\"\n }\n }\n ]\n },\n {\n \"platform\": \"host\",\n \"id\": \"Tool\",\n \"description\": \"Tools visible to the requesting Agent, including scoped and dynamic registrations.\",\n \"methods\": [\n {\n \"name\": \"listTools\",\n \"description\": \"Return every Tool schema currently callable by this Agent.\",\n \"inputSchema\": {\n \"type\": \"object\",\n \"properties\": {},\n \"additionalProperties\": false\n },\n \"outputSchema\": {\n \"description\": \"JSON data owned by this inspect provider.\"\n }\n }\n ]\n }\n ]\n}"}],"isError":false,"id":"{{message:18}}"}},"sourceEventSeqs":[53],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":5}} {"type":"step/start","data":{"turn":1,"step":6}} -{"type":"assistant/message","data":{"turn":1,"step":6,"message":{"role":"assistant","content":[{"type":"text","text":"ADVANCED_HEADLESS_OK"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:19}}"},"usage":{"inputTokens":3,"outputTokens":3},"stream":[{"type":"chunk","time":1791315715575,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1791315715575,"index":0,"dt":[],"texts":["ADVANCED_HEADLESS_OK"]},{"type":"chunk","time":1791315715575,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"ADVANCED_HEADLESS_OK"}}},{"type":"chunk","time":1791315715575,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}},{"type":"chunk","time":1791315715575,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":6,"message":{"role":"assistant","content":[{"type":"text","text":"ADVANCED_HEADLESS_OK"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:19}}"},"usage":{"inputTokens":3,"outputTokens":3},"stream":[{"type":"chunk","time":1792123961371,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1792123961371,"index":0,"dt":[],"texts":["ADVANCED_HEADLESS_OK"]},{"type":"chunk","time":1792123961371,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"ADVANCED_HEADLESS_OK"}}},{"type":"chunk","time":1792123961371,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}},{"type":"chunk","time":1792123961371,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":6}} {"type":"turn/end","data":{"turn":1,"reason":{"kind":"completed"}}} diff --git a/snapshots/session/advanced-toolchain/system-prompt.expected.md b/snapshots/session/advanced-toolchain/system-prompt.expected.md index 5b2ad2c326..c85e732095 100644 --- a/snapshots/session/advanced-toolchain/system-prompt.expected.md +++ b/snapshots/session/advanced-toolchain/system-prompt.expected.md @@ -160,8 +160,8 @@ interface ToolArgsMap { } & Record; /** Ask a subagent to stop its current work. This call returns without waiting for it to stop. You can continue a local direct child's conversation later with send_message. External executions stop permanently and cannot receive follow-ups. Subagents it started will keep running. */ interrupt_agent: { - /** The id of an agent created under you: your direct child or a deeper descendant. */ - agent_id: string; + /** The name of an agent created under you: your direct child or a deeper descendant. */ + name: string; } & Record; /** Request cancellation of a running background job. */ job_kill: { @@ -181,7 +181,7 @@ interface ToolArgsMap { /** Max wait in milliseconds with wait: true. Defaults to and is capped by configuration. */ timeout_ms?: number; } & Record; - /** List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation. */ + /** List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation. */ list_agents: Record; /** Read a UTF-8 text file and return line-numbered content. */ read: { @@ -199,8 +199,8 @@ interface ToolArgsMap { } & Record; /** Send a message to an agent. A working agent receives it at its next step; an idle agent starts a new turn with it. Returns delivery confirmation, not the agent's answer. */ send_message: { - /** The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child. */ - agent_id: string; + /** The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child. */ + name: string; /** The message to deliver to the agent. */ message: string; } & Record; @@ -209,8 +209,10 @@ interface ToolArgsMap { /** The exact skill name from the available skills list. */ name: string; } & Record; - /** Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ + /** Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ subagent: { + /** Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish. */ + name: string; /** Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent. */ cwd?: string; /** A short (3-5 word) description of the delegated task, for display. */ @@ -218,8 +220,10 @@ interface ToolArgsMap { /** The complete, self-contained task for the subagent. It does not share this conversation's context, so include everything it needs. */ prompt: string; } & Record; - /** Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ + /** Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ subagent_fork: { + /** Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish. */ + name: string; /** Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent. */ cwd?: string; /** A short (3-5 word) description of the delegated task, for display. */ @@ -440,18 +444,18 @@ interface ToolOutputMap { }; list_agents: ({ kind: "parent"; - id: string; + name: string; status: "running" | "inactive"; } | { kind: "child" | "sibling"; - id: string; + name: string; label: string; status: "running" | "inactive"; parent?: string; depth?: number; } | { kind: "diagnostic"; - id: string; + name: string; reason: "corrupt" | "unsupported" | "unavailable"; parent?: string; depth?: number; @@ -502,11 +506,11 @@ interface ToolOutputMap { }; subagent: { kind: "activation"; - subagentId: string; + name: string; }; subagent_fork: { kind: "activation"; - subagentId: string; + name: string; }; todo_write: { todos: ({ diff --git a/snapshots/session/advanced-toolchain/tool-schemas.expected.json b/snapshots/session/advanced-toolchain/tool-schemas.expected.json index 8f95aafff2..574b9b8e27 100644 --- a/snapshots/session/advanced-toolchain/tool-schemas.expected.json +++ b/snapshots/session/advanced-toolchain/tool-schemas.expected.json @@ -222,13 +222,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -286,7 +286,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -338,9 +338,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -348,7 +348,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -371,10 +371,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -389,6 +393,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -396,10 +401,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -414,6 +423,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -926,13 +936,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -990,7 +1000,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -1042,9 +1052,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -1052,7 +1062,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -1075,10 +1085,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -1093,6 +1107,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -1100,10 +1115,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -1118,6 +1137,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/session/agent-instructions/tool-schemas.expected.json b/snapshots/session/agent-instructions/tool-schemas.expected.json index e08573c1ef..417fb5621d 100644 --- a/snapshots/session/agent-instructions/tool-schemas.expected.json +++ b/snapshots/session/agent-instructions/tool-schemas.expected.json @@ -181,13 +181,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -245,7 +245,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -297,9 +297,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -307,7 +307,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -330,10 +330,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -348,6 +352,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -355,10 +360,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -373,6 +382,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -805,13 +815,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -869,7 +879,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -921,9 +931,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -931,7 +941,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -954,10 +964,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -972,6 +986,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -979,10 +994,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -997,6 +1016,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/session/background-confinement-failure/tool-schemas.expected.json b/snapshots/session/background-confinement-failure/tool-schemas.expected.json index b546a748a7..99b37246de 100644 --- a/snapshots/session/background-confinement-failure/tool-schemas.expected.json +++ b/snapshots/session/background-confinement-failure/tool-schemas.expected.json @@ -181,13 +181,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -245,7 +245,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -297,9 +297,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -307,7 +307,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -330,10 +330,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -348,6 +352,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -355,10 +360,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -373,6 +382,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/session/both-mode-turn/system-prompt.expected.md b/snapshots/session/both-mode-turn/system-prompt.expected.md index b6cc6f95b1..03e52cb89f 100644 --- a/snapshots/session/both-mode-turn/system-prompt.expected.md +++ b/snapshots/session/both-mode-turn/system-prompt.expected.md @@ -114,8 +114,8 @@ interface ToolArgsMap { } & Record; /** Ask a subagent to stop its current work. This call returns without waiting for it to stop. You can continue a local direct child's conversation later with send_message. External executions stop permanently and cannot receive follow-ups. Subagents it started will keep running. */ interrupt_agent: { - /** The id of an agent created under you: your direct child or a deeper descendant. */ - agent_id: string; + /** The name of an agent created under you: your direct child or a deeper descendant. */ + name: string; } & Record; /** Request cancellation of a running background job. */ job_kill: { @@ -135,7 +135,7 @@ interface ToolArgsMap { /** Max wait in milliseconds with wait: true. Defaults to and is capped by configuration. */ timeout_ms?: number; } & Record; - /** List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation. */ + /** List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation. */ list_agents: Record; /** Read a UTF-8 text file and return line-numbered content. */ read: { @@ -153,8 +153,8 @@ interface ToolArgsMap { } & Record; /** Send a message to an agent. A working agent receives it at its next step; an idle agent starts a new turn with it. Returns delivery confirmation, not the agent's answer. */ send_message: { - /** The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child. */ - agent_id: string; + /** The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child. */ + name: string; /** The message to deliver to the agent. */ message: string; } & Record; @@ -163,8 +163,10 @@ interface ToolArgsMap { /** The exact skill name from the available skills list. */ name: string; } & Record; - /** Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ + /** Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ subagent: { + /** Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish. */ + name: string; /** Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent. */ cwd?: string; /** A short (3-5 word) description of the delegated task, for display. */ @@ -172,8 +174,10 @@ interface ToolArgsMap { /** The complete, self-contained task for the subagent. It does not share this conversation's context, so include everything it needs. */ prompt: string; } & Record; - /** Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ + /** Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ subagent_fork: { + /** Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish. */ + name: string; /** Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent. */ cwd?: string; /** A short (3-5 word) description of the delegated task, for display. */ @@ -392,18 +396,18 @@ interface ToolOutputMap { }; list_agents: ({ kind: "parent"; - id: string; + name: string; status: "running" | "inactive"; } | { kind: "child" | "sibling"; - id: string; + name: string; label: string; status: "running" | "inactive"; parent?: string; depth?: number; } | { kind: "diagnostic"; - id: string; + name: string; reason: "corrupt" | "unsupported" | "unavailable"; parent?: string; depth?: number; @@ -454,11 +458,11 @@ interface ToolOutputMap { }; subagent: { kind: "activation"; - subagentId: string; + name: string; }; subagent_fork: { kind: "activation"; - subagentId: string; + name: string; }; todo_write: { todos: ({ diff --git a/snapshots/session/browser-use-chrome-devtools-mcp/tool-schemas.expected.json b/snapshots/session/browser-use-chrome-devtools-mcp/tool-schemas.expected.json index 5cae3dc33a..c88191b408 100644 --- a/snapshots/session/browser-use-chrome-devtools-mcp/tool-schemas.expected.json +++ b/snapshots/session/browser-use-chrome-devtools-mcp/tool-schemas.expected.json @@ -181,13 +181,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -245,7 +245,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -404,9 +404,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -414,7 +414,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -437,10 +437,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -455,6 +459,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -462,10 +467,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -480,6 +489,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/session/browser-use-playwright-mcp/tool-schemas.expected.json b/snapshots/session/browser-use-playwright-mcp/tool-schemas.expected.json index 847dfbd5e4..5869d66110 100644 --- a/snapshots/session/browser-use-playwright-mcp/tool-schemas.expected.json +++ b/snapshots/session/browser-use-playwright-mcp/tool-schemas.expected.json @@ -181,13 +181,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -245,7 +245,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -406,9 +406,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -416,7 +416,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -439,10 +439,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -457,6 +461,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -464,10 +469,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -482,6 +491,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/session/browser-use-stagehand-native/tool-schemas.expected.json b/snapshots/session/browser-use-stagehand-native/tool-schemas.expected.json index 0a0285ca47..14d88d2fb8 100644 --- a/snapshots/session/browser-use-stagehand-native/tool-schemas.expected.json +++ b/snapshots/session/browser-use-stagehand-native/tool-schemas.expected.json @@ -181,13 +181,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -245,7 +245,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -297,9 +297,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -307,7 +307,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -543,10 +543,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -561,6 +565,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -568,10 +573,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -586,6 +595,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/session/claude-code-mods/tool-schemas.expected.json b/snapshots/session/claude-code-mods/tool-schemas.expected.json index b546a748a7..99b37246de 100644 --- a/snapshots/session/claude-code-mods/tool-schemas.expected.json +++ b/snapshots/session/claude-code-mods/tool-schemas.expected.json @@ -181,13 +181,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -245,7 +245,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -297,9 +297,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -307,7 +307,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -330,10 +330,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -348,6 +352,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -355,10 +360,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -373,6 +382,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/session/compaction-recovery/tool-schemas.expected.json b/snapshots/session/compaction-recovery/tool-schemas.expected.json index e08573c1ef..417fb5621d 100644 --- a/snapshots/session/compaction-recovery/tool-schemas.expected.json +++ b/snapshots/session/compaction-recovery/tool-schemas.expected.json @@ -181,13 +181,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -245,7 +245,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -297,9 +297,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -307,7 +307,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -330,10 +330,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -348,6 +352,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -355,10 +360,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -373,6 +382,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -805,13 +815,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -869,7 +879,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -921,9 +931,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -931,7 +941,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -954,10 +964,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -972,6 +986,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -979,10 +994,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -997,6 +1016,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/session/computer-use-cua-driver-mcp/tool-schemas.expected.json b/snapshots/session/computer-use-cua-driver-mcp/tool-schemas.expected.json index 2d60121149..17f4f32e4b 100644 --- a/snapshots/session/computer-use-cua-driver-mcp/tool-schemas.expected.json +++ b/snapshots/session/computer-use-cua-driver-mcp/tool-schemas.expected.json @@ -181,13 +181,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -245,7 +245,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -383,9 +383,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -393,7 +393,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -416,10 +416,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -434,6 +438,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -441,10 +446,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -459,6 +468,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/session/computer-use-cua-driver-native/tool-schemas.expected.json b/snapshots/session/computer-use-cua-driver-native/tool-schemas.expected.json index ae92347dfa..ab1397dcec 100644 --- a/snapshots/session/computer-use-cua-driver-native/tool-schemas.expected.json +++ b/snapshots/session/computer-use-cua-driver-native/tool-schemas.expected.json @@ -227,13 +227,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -291,7 +291,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -343,9 +343,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -353,7 +353,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -376,10 +376,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -394,6 +398,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -401,10 +406,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -419,6 +428,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/session/cordis-inspect-jsdoc/tool-schemas.expected.json b/snapshots/session/cordis-inspect-jsdoc/tool-schemas.expected.json index 79c1ac3351..59a87c02cf 100644 --- a/snapshots/session/cordis-inspect-jsdoc/tool-schemas.expected.json +++ b/snapshots/session/cordis-inspect-jsdoc/tool-schemas.expected.json @@ -222,13 +222,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -286,7 +286,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -338,9 +338,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -348,7 +348,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -371,10 +371,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -389,6 +393,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -396,10 +401,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -414,6 +423,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/session/cua-native/tool-schemas.expected.json b/snapshots/session/cua-native/tool-schemas.expected.json index 42971bf07a..8ed8fa7592 100644 --- a/snapshots/session/cua-native/tool-schemas.expected.json +++ b/snapshots/session/cua-native/tool-schemas.expected.json @@ -1320,13 +1320,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -1384,7 +1384,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -1436,9 +1436,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -1446,7 +1446,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -1469,10 +1469,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -1487,6 +1491,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -1494,10 +1499,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -1512,6 +1521,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/session/cua-ptc/system-prompt.expected.md b/snapshots/session/cua-ptc/system-prompt.expected.md index de34254453..92758a858e 100644 --- a/snapshots/session/cua-ptc/system-prompt.expected.md +++ b/snapshots/session/cua-ptc/system-prompt.expected.md @@ -159,8 +159,8 @@ interface ToolArgsMap { } & Record; /** Ask a subagent to stop its current work. This call returns without waiting for it to stop. You can continue a local direct child's conversation later with send_message. External executions stop permanently and cannot receive follow-ups. Subagents it started will keep running. */ interrupt_agent: { - /** The id of an agent created under you: your direct child or a deeper descendant. */ - agent_id: string; + /** The name of an agent created under you: your direct child or a deeper descendant. */ + name: string; } & Record; /** Request cancellation of a running background job. */ job_kill: { @@ -180,7 +180,7 @@ interface ToolArgsMap { /** Max wait in milliseconds with wait: true. Defaults to and is capped by configuration. */ timeout_ms?: number; } & Record; - /** List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation. */ + /** List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation. */ list_agents: Record; /** Read a UTF-8 text file and return line-numbered content. */ read: { @@ -198,8 +198,8 @@ interface ToolArgsMap { } & Record; /** Send a message to an agent. A working agent receives it at its next step; an idle agent starts a new turn with it. Returns delivery confirmation, not the agent's answer. */ send_message: { - /** The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child. */ - agent_id: string; + /** The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child. */ + name: string; /** The message to deliver to the agent. */ message: string; } & Record; @@ -208,8 +208,10 @@ interface ToolArgsMap { /** The exact skill name from the available skills list. */ name: string; } & Record; - /** Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ + /** Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ subagent: { + /** Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish. */ + name: string; /** Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent. */ cwd?: string; /** A short (3-5 word) description of the delegated task, for display. */ @@ -217,8 +219,10 @@ interface ToolArgsMap { /** The complete, self-contained task for the subagent. It does not share this conversation's context, so include everything it needs. */ prompt: string; } & Record; - /** Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ + /** Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ subagent_fork: { + /** Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish. */ + name: string; /** Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent. */ cwd?: string; /** A short (3-5 word) description of the delegated task, for display. */ @@ -438,18 +442,18 @@ interface ToolOutputMap { }; list_agents: ({ kind: "parent"; - id: string; + name: string; status: "running" | "inactive"; } | { kind: "child" | "sibling"; - id: string; + name: string; label: string; status: "running" | "inactive"; parent?: string; depth?: number; } | { kind: "diagnostic"; - id: string; + name: string; reason: "corrupt" | "unsupported" | "unavailable"; parent?: string; depth?: number; @@ -500,11 +504,11 @@ interface ToolOutputMap { }; subagent: { kind: "activation"; - subagentId: string; + name: string; }; subagent_fork: { kind: "activation"; - subagentId: string; + name: string; }; todo_write: { todos: ({ diff --git a/snapshots/session/deepseek-messages-system-prompt/tool-schemas.expected.json b/snapshots/session/deepseek-messages-system-prompt/tool-schemas.expected.json index b546a748a7..99b37246de 100644 --- a/snapshots/session/deepseek-messages-system-prompt/tool-schemas.expected.json +++ b/snapshots/session/deepseek-messages-system-prompt/tool-schemas.expected.json @@ -181,13 +181,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -245,7 +245,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -297,9 +297,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -307,7 +307,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -330,10 +330,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -348,6 +352,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -355,10 +360,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -373,6 +382,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/session/deepseek-protocol-system-prompt/tool-schemas.expected.json b/snapshots/session/deepseek-protocol-system-prompt/tool-schemas.expected.json index b546a748a7..99b37246de 100644 --- a/snapshots/session/deepseek-protocol-system-prompt/tool-schemas.expected.json +++ b/snapshots/session/deepseek-protocol-system-prompt/tool-schemas.expected.json @@ -181,13 +181,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -245,7 +245,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -297,9 +297,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -307,7 +307,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -330,10 +330,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -348,6 +352,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -355,10 +360,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -373,6 +382,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/session/dynamic-tool-updates/tool-schemas.expected.json b/snapshots/session/dynamic-tool-updates/tool-schemas.expected.json index 99cb26ac26..c167f22812 100644 --- a/snapshots/session/dynamic-tool-updates/tool-schemas.expected.json +++ b/snapshots/session/dynamic-tool-updates/tool-schemas.expected.json @@ -181,13 +181,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -245,7 +245,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -297,9 +297,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -307,7 +307,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -330,10 +330,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -348,6 +352,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -355,10 +360,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -373,6 +382,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -805,13 +815,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -869,7 +879,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -921,9 +931,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -931,7 +941,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -962,10 +972,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -980,6 +994,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -987,10 +1002,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -1005,6 +1024,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -1436,13 +1456,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -1500,7 +1520,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -1552,9 +1572,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -1562,7 +1582,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -1585,10 +1605,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -1603,6 +1627,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -1610,10 +1635,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -1628,6 +1657,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/session/foreground-confinement-timeout/tool-schemas.expected.json b/snapshots/session/foreground-confinement-timeout/tool-schemas.expected.json index b546a748a7..99b37246de 100644 --- a/snapshots/session/foreground-confinement-timeout/tool-schemas.expected.json +++ b/snapshots/session/foreground-confinement-timeout/tool-schemas.expected.json @@ -181,13 +181,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -245,7 +245,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -297,9 +297,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -307,7 +307,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -330,10 +330,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -348,6 +352,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -355,10 +360,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -373,6 +382,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/session/fs-glob-sampling/tool-schemas.expected.json b/snapshots/session/fs-glob-sampling/tool-schemas.expected.json index 5a272e965a..f030bf525f 100644 --- a/snapshots/session/fs-glob-sampling/tool-schemas.expected.json +++ b/snapshots/session/fs-glob-sampling/tool-schemas.expected.json @@ -153,19 +153,19 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -217,9 +217,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -227,17 +227,21 @@ } }, "required": [ - "agent_id", + "name", "message" ] } }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -252,6 +256,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -259,10 +264,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -277,6 +286,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/session/headless.snapshot.ts b/snapshots/session/headless.snapshot.ts index 1952f98898..230437fe91 100644 --- a/snapshots/session/headless.snapshot.ts +++ b/snapshots/session/headless.snapshot.ts @@ -680,7 +680,7 @@ function verifyAdvancedToolchain(logs: readonly SessionLog[]): void { const textOf = (index: number) => results[index]!.content .flatMap(block => block.type === 'text' ? [block.text] : []).join('') expect(JSON.parse(textOf(1))).toEqual(['Service', 'Event', 'Config', 'Tool']) - expect(textOf(2)).toBe(`started subagent ${logs[1]!.header.id}`) + expect(textOf(2)).toBe('started subagent worker-1') const completions = events.flatMap(event => event.type === 'user/message' && event.data.source.kind === 'subagent-settled' ? [{ sender: event.data.source.senderSessionId, diff --git a/snapshots/session/lsp-definition/tool-schemas.expected.json b/snapshots/session/lsp-definition/tool-schemas.expected.json index 4b13981451..6d3068991a 100644 --- a/snapshots/session/lsp-definition/tool-schemas.expected.json +++ b/snapshots/session/lsp-definition/tool-schemas.expected.json @@ -181,13 +181,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -245,7 +245,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -334,9 +334,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -344,7 +344,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -367,10 +367,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -385,6 +389,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -392,10 +397,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -410,6 +419,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/session/mcp-resources-ptc/system-prompt.expected.md b/snapshots/session/mcp-resources-ptc/system-prompt.expected.md index fff9e5fe63..d48990692d 100644 --- a/snapshots/session/mcp-resources-ptc/system-prompt.expected.md +++ b/snapshots/session/mcp-resources-ptc/system-prompt.expected.md @@ -122,8 +122,8 @@ interface ToolArgsMap { } & Record; /** Ask a subagent to stop its current work. This call returns without waiting for it to stop. You can continue a local direct child's conversation later with send_message. External executions stop permanently and cannot receive follow-ups. Subagents it started will keep running. */ interrupt_agent: { - /** The id of an agent created under you: your direct child or a deeper descendant. */ - agent_id: string; + /** The name of an agent created under you: your direct child or a deeper descendant. */ + name: string; } & Record; /** Request cancellation of a running background job. */ job_kill: { @@ -143,7 +143,7 @@ interface ToolArgsMap { /** Max wait in milliseconds with wait: true. Defaults to and is capped by configuration. */ timeout_ms?: number; } & Record; - /** List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation. */ + /** List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation. */ list_agents: Record; /** List parameterized resource URI templates from an MCP server. */ list_mcp_resource_templates: { @@ -182,8 +182,8 @@ interface ToolArgsMap { } & Record; /** Send a message to an agent. A working agent receives it at its next step; an idle agent starts a new turn with it. Returns delivery confirmation, not the agent's answer. */ send_message: { - /** The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child. */ - agent_id: string; + /** The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child. */ + name: string; /** The message to deliver to the agent. */ message: string; } & Record; @@ -192,8 +192,10 @@ interface ToolArgsMap { /** The exact skill name from the available skills list. */ name: string; } & Record; - /** Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ + /** Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ subagent: { + /** Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish. */ + name: string; /** Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent. */ cwd?: string; /** A short (3-5 word) description of the delegated task, for display. */ @@ -201,8 +203,10 @@ interface ToolArgsMap { /** The complete, self-contained task for the subagent. It does not share this conversation's context, so include everything it needs. */ prompt: string; } & Record; - /** Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ + /** Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ subagent_fork: { + /** Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish. */ + name: string; /** Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent. */ cwd?: string; /** A short (3-5 word) description of the delegated task, for display. */ @@ -421,18 +425,18 @@ interface ToolOutputMap { }; list_agents: ({ kind: "parent"; - id: string; + name: string; status: "running" | "inactive"; } | { kind: "child" | "sibling"; - id: string; + name: string; label: string; status: "running" | "inactive"; parent?: string; depth?: number; } | { kind: "diagnostic"; - id: string; + name: string; reason: "corrupt" | "unsupported" | "unavailable"; parent?: string; depth?: number; @@ -486,11 +490,11 @@ interface ToolOutputMap { }; subagent: { kind: "activation"; - subagentId: string; + name: string; }; subagent_fork: { kind: "activation"; - subagentId: string; + name: string; }; todo_write: { todos: ({ diff --git a/snapshots/session/mcp-resources/tool-schemas.expected.json b/snapshots/session/mcp-resources/tool-schemas.expected.json index 8fe57329b1..5cb03a9064 100644 --- a/snapshots/session/mcp-resources/tool-schemas.expected.json +++ b/snapshots/session/mcp-resources/tool-schemas.expected.json @@ -181,13 +181,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -245,7 +245,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -358,9 +358,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -368,7 +368,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -391,10 +391,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -409,6 +413,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -416,10 +421,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -434,6 +443,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/session/multimodal-spill-ends/tool-schemas.expected.json b/snapshots/session/multimodal-spill-ends/tool-schemas.expected.json index 8643290037..51ed3bcca7 100644 --- a/snapshots/session/multimodal-spill-ends/tool-schemas.expected.json +++ b/snapshots/session/multimodal-spill-ends/tool-schemas.expected.json @@ -181,13 +181,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -245,7 +245,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -316,9 +316,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -326,7 +326,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -349,10 +349,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -367,6 +371,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -374,10 +379,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -392,6 +401,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/session/office-progressive-native/tool-schemas.expected.json b/snapshots/session/office-progressive-native/tool-schemas.expected.json index f0e844ff6d..a0c73b2a71 100644 --- a/snapshots/session/office-progressive-native/tool-schemas.expected.json +++ b/snapshots/session/office-progressive-native/tool-schemas.expected.json @@ -136,13 +136,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -200,7 +200,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -252,9 +252,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -262,7 +262,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -285,10 +285,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -303,6 +307,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -310,10 +315,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -328,6 +337,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/session/office-progressive-ptc/system-prompt.expected.md b/snapshots/session/office-progressive-ptc/system-prompt.expected.md index 7e945a9b48..326fd8370f 100644 --- a/snapshots/session/office-progressive-ptc/system-prompt.expected.md +++ b/snapshots/session/office-progressive-ptc/system-prompt.expected.md @@ -93,8 +93,8 @@ interface ToolArgsMap { } & Record; /** Ask a subagent to stop its current work. This call returns without waiting for it to stop. You can continue a local direct child's conversation later with send_message. External executions stop permanently and cannot receive follow-ups. Subagents it started will keep running. */ interrupt_agent: { - /** The id of an agent created under you: your direct child or a deeper descendant. */ - agent_id: string; + /** The name of an agent created under you: your direct child or a deeper descendant. */ + name: string; } & Record; /** Request cancellation of a running background job. */ job_kill: { @@ -114,7 +114,7 @@ interface ToolArgsMap { /** Max wait in milliseconds with wait: true. Defaults to and is capped by configuration. */ timeout_ms?: number; } & Record; - /** List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation. */ + /** List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation. */ list_agents: Record; /** Read a UTF-8 text file and return line-numbered content. */ read: { @@ -132,8 +132,8 @@ interface ToolArgsMap { } & Record; /** Send a message to an agent. A working agent receives it at its next step; an idle agent starts a new turn with it. Returns delivery confirmation, not the agent's answer. */ send_message: { - /** The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child. */ - agent_id: string; + /** The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child. */ + name: string; /** The message to deliver to the agent. */ message: string; } & Record; @@ -142,8 +142,10 @@ interface ToolArgsMap { /** The exact skill name from the available skills list. */ name: string; } & Record; - /** Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ + /** Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ subagent: { + /** Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish. */ + name: string; /** Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent. */ cwd?: string; /** A short (3-5 word) description of the delegated task, for display. */ @@ -151,8 +153,10 @@ interface ToolArgsMap { /** The complete, self-contained task for the subagent. It does not share this conversation's context, so include everything it needs. */ prompt: string; } & Record; - /** Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ + /** Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ subagent_fork: { + /** Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish. */ + name: string; /** Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent. */ cwd?: string; /** A short (3-5 word) description of the delegated task, for display. */ @@ -335,18 +339,18 @@ interface ToolOutputMap { }; list_agents: ({ kind: "parent"; - id: string; + name: string; status: "running" | "inactive"; } | { kind: "child" | "sibling"; - id: string; + name: string; label: string; status: "running" | "inactive"; parent?: string; depth?: number; } | { kind: "diagnostic"; - id: string; + name: string; reason: "corrupt" | "unsupported" | "unavailable"; parent?: string; depth?: number; @@ -397,11 +401,11 @@ interface ToolOutputMap { }; subagent: { kind: "activation"; - subagentId: string; + name: string; }; subagent_fork: { kind: "activation"; - subagentId: string; + name: string; }; todo_write: { todos: ({ diff --git a/snapshots/session/office-skills/tool-schemas.expected.json b/snapshots/session/office-skills/tool-schemas.expected.json index f0e844ff6d..a0c73b2a71 100644 --- a/snapshots/session/office-skills/tool-schemas.expected.json +++ b/snapshots/session/office-skills/tool-schemas.expected.json @@ -136,13 +136,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -200,7 +200,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -252,9 +252,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -262,7 +262,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -285,10 +285,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -303,6 +307,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -310,10 +315,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -328,6 +337,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/session/persistent-pwsh-tool-turn/tool-schemas.expected.json b/snapshots/session/persistent-pwsh-tool-turn/tool-schemas.expected.json index 5e76c9627d..55db1639eb 100644 --- a/snapshots/session/persistent-pwsh-tool-turn/tool-schemas.expected.json +++ b/snapshots/session/persistent-pwsh-tool-turn/tool-schemas.expected.json @@ -108,19 +108,19 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -188,9 +188,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -198,17 +198,21 @@ } }, "required": [ - "agent_id", + "name", "message" ] } }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -223,6 +227,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -230,10 +235,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -248,6 +257,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/session/plugin-manager-mcp/tool-schemas.expected.json b/snapshots/session/plugin-manager-mcp/tool-schemas.expected.json index a5770e6380..22ab658556 100644 --- a/snapshots/session/plugin-manager-mcp/tool-schemas.expected.json +++ b/snapshots/session/plugin-manager-mcp/tool-schemas.expected.json @@ -181,13 +181,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -245,7 +245,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -358,9 +358,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -368,7 +368,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -391,10 +391,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -409,6 +413,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -416,10 +421,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -434,6 +443,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -866,13 +876,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -930,7 +940,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -1113,9 +1123,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -1123,7 +1133,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -1146,10 +1156,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -1164,6 +1178,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -1171,10 +1186,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -1189,6 +1208,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/session/plugin-manager/tool-schemas.expected.json b/snapshots/session/plugin-manager/tool-schemas.expected.json index aac330649c..699c24bd38 100644 --- a/snapshots/session/plugin-manager/tool-schemas.expected.json +++ b/snapshots/session/plugin-manager/tool-schemas.expected.json @@ -181,13 +181,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -245,7 +245,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -358,9 +358,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -368,7 +368,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -391,10 +391,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -409,6 +413,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -416,10 +421,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -434,6 +443,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/session/product-subagent-both/tool-schemas.expected.json b/snapshots/session/product-subagent-both/tool-schemas.expected.json index e9778f1492..18d9a9c7c0 100644 --- a/snapshots/session/product-subagent-both/tool-schemas.expected.json +++ b/snapshots/session/product-subagent-both/tool-schemas.expected.json @@ -181,13 +181,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -245,7 +245,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -297,9 +297,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -307,7 +307,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -330,10 +330,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -348,6 +352,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -355,10 +360,14 @@ }, { "name": "subagent_claude_primary", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The completion notice includes its final answer. This backend does not accept follow-up messages.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The completion notice includes its final answer. This backend does not accept follow-up messages.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -373,6 +382,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -380,10 +390,14 @@ }, { "name": "subagent_claude_secondary", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The completion notice includes its final answer. This backend does not accept follow-up messages.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The completion notice includes its final answer. This backend does not accept follow-up messages.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -398,6 +412,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -405,10 +420,14 @@ }, { "name": "subagent_codex_primary", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The completion notice includes its final answer. This backend does not accept follow-up messages.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The completion notice includes its final answer. This backend does not accept follow-up messages.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -423,6 +442,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -430,10 +450,14 @@ }, { "name": "subagent_codex_secondary", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The completion notice includes its final answer. This backend does not accept follow-up messages.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The completion notice includes its final answer. This backend does not accept follow-up messages.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -448,6 +472,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -455,10 +480,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -473,6 +502,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/session/product-subagent-codex/tool-schemas.expected.json b/snapshots/session/product-subagent-codex/tool-schemas.expected.json index bf02723253..93dd763728 100644 --- a/snapshots/session/product-subagent-codex/tool-schemas.expected.json +++ b/snapshots/session/product-subagent-codex/tool-schemas.expected.json @@ -181,13 +181,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -245,7 +245,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -297,9 +297,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -307,7 +307,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -330,10 +330,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -348,6 +352,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -355,10 +360,14 @@ }, { "name": "subagent_codex_primary", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The completion notice includes its final answer. This backend does not accept follow-up messages.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The completion notice includes its final answer. This backend does not accept follow-up messages.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -373,6 +382,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -380,10 +390,14 @@ }, { "name": "subagent_codex_secondary", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The completion notice includes its final answer. This backend does not accept follow-up messages.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The completion notice includes its final answer. This backend does not accept follow-up messages.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -398,6 +412,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -405,10 +420,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -423,6 +442,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/session/product-subagent-result-diagnostic/replay.override.json b/snapshots/session/product-subagent-result-diagnostic/replay.override.json index 5a46080b58..f4781967a6 100644 --- a/snapshots/session/product-subagent-result-diagnostic/replay.override.json +++ b/snapshots/session/product-subagent-result-diagnostic/replay.override.json @@ -12,7 +12,7 @@ "index": 0, "id": "call_claude_foreground", "name": "subagent_codex", - "argumentsDelta": "{\"description\":\"Observe Claude foreground diagnostic\",\"prompt\":\"Return the Claude diagnostic failure.\"}" + "argumentsDelta": "{\"description\":\"Observe Claude foreground diagnostic\",\"prompt\":\"Return the Claude diagnostic failure.\",\"name\":\"worker-1\"}" }, { "type": "block-end", @@ -21,7 +21,7 @@ "type": "tool-call", "id": "call_claude_foreground", "name": "subagent_codex", - "arguments": "{\"description\":\"Observe Claude foreground diagnostic\",\"prompt\":\"Return the Claude diagnostic failure.\"}" + "arguments": "{\"description\":\"Observe Claude foreground diagnostic\",\"prompt\":\"Return the Claude diagnostic failure.\",\"name\":\"worker-1\"}" } }, { @@ -52,7 +52,7 @@ "index": 0, "id": "call_claude_background", "name": "subagent_codex", - "argumentsDelta": "{\"description\":\"Observe Claude background diagnostic\",\"prompt\":\"Return the Claude diagnostic failure.\"}" + "argumentsDelta": "{\"description\":\"Observe Claude background diagnostic\",\"prompt\":\"Return the Claude diagnostic failure.\",\"name\":\"worker-2\"}" }, { "type": "block-end", @@ -61,7 +61,7 @@ "type": "tool-call", "id": "call_claude_background", "name": "subagent_codex", - "arguments": "{\"description\":\"Observe Claude background diagnostic\",\"prompt\":\"Return the Claude diagnostic failure.\"}" + "arguments": "{\"description\":\"Observe Claude background diagnostic\",\"prompt\":\"Return the Claude diagnostic failure.\",\"name\":\"worker-2\"}" } }, { @@ -92,7 +92,7 @@ "index": 0, "id": "call_codex_foreground", "name": "subagent_codex", - "argumentsDelta": "{\"description\":\"Observe Codex foreground diagnostic\",\"prompt\":\"Return the Codex diagnostic failure.\"}" + "argumentsDelta": "{\"description\":\"Observe Codex foreground diagnostic\",\"prompt\":\"Return the Codex diagnostic failure.\",\"name\":\"worker-3\"}" }, { "type": "block-end", @@ -101,7 +101,7 @@ "type": "tool-call", "id": "call_codex_foreground", "name": "subagent_codex", - "arguments": "{\"description\":\"Observe Codex foreground diagnostic\",\"prompt\":\"Return the Codex diagnostic failure.\"}" + "arguments": "{\"description\":\"Observe Codex foreground diagnostic\",\"prompt\":\"Return the Codex diagnostic failure.\",\"name\":\"worker-3\"}" } }, { @@ -132,7 +132,7 @@ "index": 0, "id": "call_codex_background", "name": "subagent_codex", - "argumentsDelta": "{\"description\":\"Observe Codex background diagnostic\",\"prompt\":\"Return the Codex diagnostic failure.\"}" + "argumentsDelta": "{\"description\":\"Observe Codex background diagnostic\",\"prompt\":\"Return the Codex diagnostic failure.\",\"name\":\"worker-4\"}" }, { "type": "block-end", @@ -141,7 +141,7 @@ "type": "tool-call", "id": "call_codex_background", "name": "subagent_codex", - "arguments": "{\"description\":\"Observe Codex background diagnostic\",\"prompt\":\"Return the Codex diagnostic failure.\"}" + "arguments": "{\"description\":\"Observe Codex background diagnostic\",\"prompt\":\"Return the Codex diagnostic failure.\",\"name\":\"worker-4\"}" } }, { @@ -172,7 +172,7 @@ "index": 0, "id": "call_cleanup_failure", "name": "subagent_codex", - "argumentsDelta": "{\"description\":\"Observe completed output after cleanup failure\",\"prompt\":\"Complete the task, then fail cleanup.\"}" + "argumentsDelta": "{\"description\":\"Observe completed output after cleanup failure\",\"prompt\":\"Complete the task, then fail cleanup.\",\"name\":\"worker-5\"}" }, { "type": "block-end", @@ -181,7 +181,7 @@ "type": "tool-call", "id": "call_cleanup_failure", "name": "subagent_codex", - "arguments": "{\"description\":\"Observe completed output after cleanup failure\",\"prompt\":\"Complete the task, then fail cleanup.\"}" + "arguments": "{\"description\":\"Observe completed output after cleanup failure\",\"prompt\":\"Complete the task, then fail cleanup.\",\"name\":\"worker-5\"}" } }, { diff --git a/snapshots/session/product-subagent-result-diagnostic/session.v4.jsonl b/snapshots/session/product-subagent-result-diagnostic/session.v4.jsonl index ad62979297..bf49f142fb 100644 --- a/snapshots/session/product-subagent-result-diagnostic/session.v4.jsonl +++ b/snapshots/session/product-subagent-result-diagnostic/session.v4.jsonl @@ -12,51 +12,56 @@ {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-pro"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-pro"}} {"type":"session/title","data":{"title":"Observe four diagnostic failures with","messageSeqs":[8],"source":{"kind":"fallback"}}} -{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_claude_foreground","name":"subagent_codex","arguments":"{\"description\":\"Observe Claude foreground diagnostic\",\"prompt\":\"Return the Claude diagnostic failure.\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-pro"},"id":"{{message:4}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1789975216473,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1789975216474,"index":0,"dt":[],"id":"call_claude_foreground","name":"subagent_codex","args":["{\"description\":\"Observe Claude foreground diagnostic\",\"prompt\":\"Return the Claude diagnostic failure.\"}"]},{"type":"chunk","time":1789975216474,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_claude_foreground","name":"subagent_codex","arguments":"{\"description\":\"Observe Claude foreground diagnostic\",\"prompt\":\"Return the Claude diagnostic failure.\"}"}}},{"type":"chunk","time":1789975216474,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1789975216474,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} -{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_claude_foreground","name":"subagent_codex","arguments":"{\"description\":\"Observe Claude foreground diagnostic\",\"prompt\":\"Return the Claude diagnostic failure.\"}"}} -{"type":"subagent/catalog","data":{"version":2,"childId":"{{id:1}}","childCreatedAt":1789975216482,"mode":"external","label":"Observe Claude foreground diagnostic"}} -{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent {{id:1}} failed before it finished."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"partial assistant text"},{"type":"text","text":"Product subagent failure (product: Claude Code; stage: query-run; category: limit)"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{id:1}} failed before it finished.","senderSessionId":"{{id:1}}"},"role":"user","id":"{{message:5}}"}]}} -{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_claude_foreground"},"toolCallId":"call_claude_foreground","content":[{"type":"text","text":"started subagent {{id:1}}"}],"isError":false,"id":"{{message:6}}"}},"sourceEventSeqs":[14],"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_claude_foreground","name":"subagent_codex","arguments":"{\"description\":\"Observe Claude foreground diagnostic\",\"prompt\":\"Return the Claude diagnostic failure.\",\"name\":\"worker-1\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-pro"},"id":"{{message:4}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1792123794519,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792123794519,"index":0,"dt":[],"id":"call_claude_foreground","name":"subagent_codex","args":["{\"description\":\"Observe Claude foreground diagnostic\",\"prompt\":\"Return the Claude diagnostic failure.\",\"name\":\"worker-1\"}"]},{"type":"chunk","time":1792123794519,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_claude_foreground","name":"subagent_codex","arguments":"{\"description\":\"Observe Claude foreground diagnostic\",\"prompt\":\"Return the Claude diagnostic failure.\",\"name\":\"worker-1\"}"}}},{"type":"chunk","time":1792123794519,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1792123794519,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_claude_foreground","name":"subagent_codex","arguments":"{\"description\":\"Observe Claude foreground diagnostic\",\"prompt\":\"Return the Claude diagnostic failure.\",\"name\":\"worker-1\"}"}} +{"type":"subagent/catalog","data":{"version":2,"childId":"{{id:1}}","childCreatedAt":1792123794525,"mode":"external","label":"Observe Claude foreground diagnostic"}} +{"type":"subagent/named","data":{"name":"worker-1","id":"{{id:1}}"}} +{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent worker-1 failed before it finished."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"partial assistant text"},{"type":"text","text":"Product subagent failure (product: Claude Code; stage: query-run; category: limit)"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 failed before it finished.","senderSessionId":"{{id:1}}"},"role":"user","id":"{{message:5}}"}]}} +{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_claude_foreground"},"toolCallId":"call_claude_foreground","content":[{"type":"text","text":"started subagent worker-1"}],"isError":false,"id":"{{message:6}}"}},"sourceEventSeqs":[14],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":1}} {"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":1,"step":2}} -{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent {{id:1}} failed before it finished."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"partial assistant text"},{"type":"text","text":"Product subagent failure (product: Claude Code; stage: query-run; category: limit)"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{id:1}} failed before it finished.","senderSessionId":"{{id:1}}"},"role":"user","id":"{{message:5}}"},"surfaceOp":"append"} -{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_claude_background","name":"subagent_codex","arguments":"{\"description\":\"Observe Claude background diagnostic\",\"prompt\":\"Return the Claude diagnostic failure.\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-pro"},"id":"{{message:7}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1789975216501,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1789975216501,"index":0,"dt":[],"id":"call_claude_background","name":"subagent_codex","args":["{\"description\":\"Observe Claude background diagnostic\",\"prompt\":\"Return the Claude diagnostic failure.\"}"]},{"type":"chunk","time":1789975216501,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_claude_background","name":"subagent_codex","arguments":"{\"description\":\"Observe Claude background diagnostic\",\"prompt\":\"Return the Claude diagnostic failure.\"}"}}},{"type":"chunk","time":1789975216501,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1789975216502,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} -{"type":"tool/call","data":{"turn":1,"step":2,"callId":"call_claude_background","name":"subagent_codex","arguments":"{\"description\":\"Observe Claude background diagnostic\",\"prompt\":\"Return the Claude diagnostic failure.\"}"}} -{"type":"subagent/catalog","data":{"version":2,"childId":"{{id:2}}","childCreatedAt":1789975216507,"mode":"external","label":"Observe Claude background diagnostic"}} -{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent {{id:2}} failed before it finished."},{"type":"text","text":"It left no closing message."},{"type":"text","text":"Product subagent failure (product: Claude Code; stage: query-run; category: limit)"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{id:2}} failed before it finished.","senderSessionId":"{{id:2}}"},"role":"user","id":"{{message:8}}"}]}} -{"type":"tool/result","data":{"turn":1,"step":2,"message":{"role":"tool","source":{"kind":"tool","callId":"call_claude_background"},"toolCallId":"call_claude_background","content":[{"type":"text","text":"started subagent {{id:2}}"}],"isError":false,"id":"{{message:9}}"}},"sourceEventSeqs":[23],"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent worker-1 failed before it finished."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"partial assistant text"},{"type":"text","text":"Product subagent failure (product: Claude Code; stage: query-run; category: limit)"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 failed before it finished.","senderSessionId":"{{id:1}}"},"role":"user","id":"{{message:5}}"},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_claude_background","name":"subagent_codex","arguments":"{\"description\":\"Observe Claude background diagnostic\",\"prompt\":\"Return the Claude diagnostic failure.\",\"name\":\"worker-2\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-pro"},"id":"{{message:7}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1792123794539,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792123794539,"index":0,"dt":[],"id":"call_claude_background","name":"subagent_codex","args":["{\"description\":\"Observe Claude background diagnostic\",\"prompt\":\"Return the Claude diagnostic failure.\",\"name\":\"worker-2\"}"]},{"type":"chunk","time":1792123794539,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_claude_background","name":"subagent_codex","arguments":"{\"description\":\"Observe Claude background diagnostic\",\"prompt\":\"Return the Claude diagnostic failure.\",\"name\":\"worker-2\"}"}}},{"type":"chunk","time":1792123794539,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1792123794539,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":2,"callId":"call_claude_background","name":"subagent_codex","arguments":"{\"description\":\"Observe Claude background diagnostic\",\"prompt\":\"Return the Claude diagnostic failure.\",\"name\":\"worker-2\"}"}} +{"type":"subagent/catalog","data":{"version":2,"childId":"{{id:2}}","childCreatedAt":1792123794544,"mode":"external","label":"Observe Claude background diagnostic"}} +{"type":"subagent/named","data":{"name":"worker-2","id":"{{id:2}}"}} +{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent worker-2 failed before it finished."},{"type":"text","text":"It left no closing message."},{"type":"text","text":"Product subagent failure (product: Claude Code; stage: query-run; category: limit)"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-2 failed before it finished.","senderSessionId":"{{id:2}}"},"role":"user","id":"{{message:8}}"}]}} +{"type":"tool/result","data":{"turn":1,"step":2,"message":{"role":"tool","source":{"kind":"tool","callId":"call_claude_background"},"toolCallId":"call_claude_background","content":[{"type":"text","text":"started subagent worker-2"}],"isError":false,"id":"{{message:9}}"}},"sourceEventSeqs":[24],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":2}} {"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":1,"step":3}} -{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent {{id:2}} failed before it finished."},{"type":"text","text":"It left no closing message."},{"type":"text","text":"Product subagent failure (product: Claude Code; stage: query-run; category: limit)"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{id:2}} failed before it finished.","senderSessionId":"{{id:2}}"},"role":"user","id":"{{message:8}}"},"surfaceOp":"append"} -{"type":"assistant/message","data":{"turn":1,"step":3,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_codex_foreground","name":"subagent_codex","arguments":"{\"description\":\"Observe Codex foreground diagnostic\",\"prompt\":\"Return the Codex diagnostic failure.\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-pro"},"id":"{{message:10}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1789975216521,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1789975216521,"index":0,"dt":[],"id":"call_codex_foreground","name":"subagent_codex","args":["{\"description\":\"Observe Codex foreground diagnostic\",\"prompt\":\"Return the Codex diagnostic failure.\"}"]},{"type":"chunk","time":1789975216521,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_codex_foreground","name":"subagent_codex","arguments":"{\"description\":\"Observe Codex foreground diagnostic\",\"prompt\":\"Return the Codex diagnostic failure.\"}"}}},{"type":"chunk","time":1789975216521,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1789975216521,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} -{"type":"tool/call","data":{"turn":1,"step":3,"callId":"call_codex_foreground","name":"subagent_codex","arguments":"{\"description\":\"Observe Codex foreground diagnostic\",\"prompt\":\"Return the Codex diagnostic failure.\"}"}} -{"type":"subagent/catalog","data":{"version":2,"childId":"{{id:3}}","childCreatedAt":1789975216526,"mode":"external","label":"Observe Codex foreground diagnostic"}} -{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent {{id:3}} failed before it finished."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"partial assistant text"},{"type":"text","text":"Product subagent failure (product: Codex; stage: turn; category: transport; HTTP status: 503)"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{id:3}} failed before it finished.","senderSessionId":"{{id:3}}"},"role":"user","id":"{{message:11}}"}]}} -{"type":"tool/result","data":{"turn":1,"step":3,"message":{"role":"tool","source":{"kind":"tool","callId":"call_codex_foreground"},"toolCallId":"call_codex_foreground","content":[{"type":"text","text":"started subagent {{id:3}}"}],"isError":false,"id":"{{message:12}}"}},"sourceEventSeqs":[32],"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent worker-2 failed before it finished."},{"type":"text","text":"It left no closing message."},{"type":"text","text":"Product subagent failure (product: Claude Code; stage: query-run; category: limit)"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-2 failed before it finished.","senderSessionId":"{{id:2}}"},"role":"user","id":"{{message:8}}"},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":3,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_codex_foreground","name":"subagent_codex","arguments":"{\"description\":\"Observe Codex foreground diagnostic\",\"prompt\":\"Return the Codex diagnostic failure.\",\"name\":\"worker-3\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-pro"},"id":"{{message:10}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1792123794555,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792123794556,"index":0,"dt":[],"id":"call_codex_foreground","name":"subagent_codex","args":["{\"description\":\"Observe Codex foreground diagnostic\",\"prompt\":\"Return the Codex diagnostic failure.\",\"name\":\"worker-3\"}"]},{"type":"chunk","time":1792123794556,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_codex_foreground","name":"subagent_codex","arguments":"{\"description\":\"Observe Codex foreground diagnostic\",\"prompt\":\"Return the Codex diagnostic failure.\",\"name\":\"worker-3\"}"}}},{"type":"chunk","time":1792123794556,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1792123794556,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":3,"callId":"call_codex_foreground","name":"subagent_codex","arguments":"{\"description\":\"Observe Codex foreground diagnostic\",\"prompt\":\"Return the Codex diagnostic failure.\",\"name\":\"worker-3\"}"}} +{"type":"subagent/catalog","data":{"version":2,"childId":"{{id:3}}","childCreatedAt":1792123794560,"mode":"external","label":"Observe Codex foreground diagnostic"}} +{"type":"subagent/named","data":{"name":"worker-3","id":"{{id:3}}"}} +{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent worker-3 failed before it finished."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"partial assistant text"},{"type":"text","text":"Product subagent failure (product: Codex; stage: turn; category: transport; HTTP status: 503)"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-3 failed before it finished.","senderSessionId":"{{id:3}}"},"role":"user","id":"{{message:11}}"}]}} +{"type":"tool/result","data":{"turn":1,"step":3,"message":{"role":"tool","source":{"kind":"tool","callId":"call_codex_foreground"},"toolCallId":"call_codex_foreground","content":[{"type":"text","text":"started subagent worker-3"}],"isError":false,"id":"{{message:12}}"}},"sourceEventSeqs":[34],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":3}} {"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":1,"step":4}} -{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent {{id:3}} failed before it finished."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"partial assistant text"},{"type":"text","text":"Product subagent failure (product: Codex; stage: turn; category: transport; HTTP status: 503)"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{id:3}} failed before it finished.","senderSessionId":"{{id:3}}"},"role":"user","id":"{{message:11}}"},"surfaceOp":"append"} -{"type":"assistant/message","data":{"turn":1,"step":4,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_codex_background","name":"subagent_codex","arguments":"{\"description\":\"Observe Codex background diagnostic\",\"prompt\":\"Return the Codex diagnostic failure.\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-pro"},"id":"{{message:13}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1789975216540,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1789975216541,"index":0,"dt":[],"id":"call_codex_background","name":"subagent_codex","args":["{\"description\":\"Observe Codex background diagnostic\",\"prompt\":\"Return the Codex diagnostic failure.\"}"]},{"type":"chunk","time":1789975216541,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_codex_background","name":"subagent_codex","arguments":"{\"description\":\"Observe Codex background diagnostic\",\"prompt\":\"Return the Codex diagnostic failure.\"}"}}},{"type":"chunk","time":1789975216541,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1789975216541,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} -{"type":"tool/call","data":{"turn":1,"step":4,"callId":"call_codex_background","name":"subagent_codex","arguments":"{\"description\":\"Observe Codex background diagnostic\",\"prompt\":\"Return the Codex diagnostic failure.\"}"}} -{"type":"subagent/catalog","data":{"version":2,"childId":"{{id:4}}","childCreatedAt":1789975216546,"mode":"external","label":"Observe Codex background diagnostic"}} -{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent {{id:4}} failed before it finished."},{"type":"text","text":"It left no closing message."},{"type":"text","text":"Product subagent failure (product: Codex; stage: turn; category: transport; HTTP status: 503)"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{id:4}} failed before it finished.","senderSessionId":"{{id:4}}"},"role":"user","id":"{{message:14}}"}]}} -{"type":"tool/result","data":{"turn":1,"step":4,"message":{"role":"tool","source":{"kind":"tool","callId":"call_codex_background"},"toolCallId":"call_codex_background","content":[{"type":"text","text":"started subagent {{id:4}}"}],"isError":false,"id":"{{message:15}}"}},"sourceEventSeqs":[41],"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent worker-3 failed before it finished."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"partial assistant text"},{"type":"text","text":"Product subagent failure (product: Codex; stage: turn; category: transport; HTTP status: 503)"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-3 failed before it finished.","senderSessionId":"{{id:3}}"},"role":"user","id":"{{message:11}}"},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":4,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_codex_background","name":"subagent_codex","arguments":"{\"description\":\"Observe Codex background diagnostic\",\"prompt\":\"Return the Codex diagnostic failure.\",\"name\":\"worker-4\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-pro"},"id":"{{message:13}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1792123794572,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792123794572,"index":0,"dt":[],"id":"call_codex_background","name":"subagent_codex","args":["{\"description\":\"Observe Codex background diagnostic\",\"prompt\":\"Return the Codex diagnostic failure.\",\"name\":\"worker-4\"}"]},{"type":"chunk","time":1792123794572,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_codex_background","name":"subagent_codex","arguments":"{\"description\":\"Observe Codex background diagnostic\",\"prompt\":\"Return the Codex diagnostic failure.\",\"name\":\"worker-4\"}"}}},{"type":"chunk","time":1792123794572,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1792123794572,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":4,"callId":"call_codex_background","name":"subagent_codex","arguments":"{\"description\":\"Observe Codex background diagnostic\",\"prompt\":\"Return the Codex diagnostic failure.\",\"name\":\"worker-4\"}"}} +{"type":"subagent/catalog","data":{"version":2,"childId":"{{id:4}}","childCreatedAt":1792123794577,"mode":"external","label":"Observe Codex background diagnostic"}} +{"type":"subagent/named","data":{"name":"worker-4","id":"{{id:4}}"}} +{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent worker-4 failed before it finished."},{"type":"text","text":"It left no closing message."},{"type":"text","text":"Product subagent failure (product: Codex; stage: turn; category: transport; HTTP status: 503)"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-4 failed before it finished.","senderSessionId":"{{id:4}}"},"role":"user","id":"{{message:14}}"}]}} +{"type":"tool/result","data":{"turn":1,"step":4,"message":{"role":"tool","source":{"kind":"tool","callId":"call_codex_background"},"toolCallId":"call_codex_background","content":[{"type":"text","text":"started subagent worker-4"}],"isError":false,"id":"{{message:15}}"}},"sourceEventSeqs":[44],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":4}} {"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":1,"step":5}} -{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent {{id:4}} failed before it finished."},{"type":"text","text":"It left no closing message."},{"type":"text","text":"Product subagent failure (product: Codex; stage: turn; category: transport; HTTP status: 503)"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{id:4}} failed before it finished.","senderSessionId":"{{id:4}}"},"role":"user","id":"{{message:14}}"},"surfaceOp":"append"} -{"type":"assistant/message","data":{"turn":1,"step":5,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_cleanup_failure","name":"subagent_codex","arguments":"{\"description\":\"Observe completed output after cleanup failure\",\"prompt\":\"Complete the task, then fail cleanup.\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-pro"},"id":"{{message:16}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1789975216564,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1789975216564,"index":0,"dt":[],"id":"call_cleanup_failure","name":"subagent_codex","args":["{\"description\":\"Observe completed output after cleanup failure\",\"prompt\":\"Complete the task, then fail cleanup.\"}"]},{"type":"chunk","time":1789975216565,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_cleanup_failure","name":"subagent_codex","arguments":"{\"description\":\"Observe completed output after cleanup failure\",\"prompt\":\"Complete the task, then fail cleanup.\"}"}}},{"type":"chunk","time":1789975216565,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1789975216565,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} -{"type":"tool/call","data":{"turn":1,"step":5,"callId":"call_cleanup_failure","name":"subagent_codex","arguments":"{\"description\":\"Observe completed output after cleanup failure\",\"prompt\":\"Complete the task, then fail cleanup.\"}"}} -{"type":"subagent/catalog","data":{"version":2,"childId":"{{id:5}}","childCreatedAt":1789975216569,"mode":"external","label":"Observe completed output after cleanup failure"}} -{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent {{id:5}} finished. It cannot receive follow-up messages."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"ANSWER_SURVIVES_CLEANUP_FAILURE"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{id:5}} finished. It cannot receive follow-up messages.","senderSessionId":"{{id:5}}"},"role":"user","id":"{{message:17}}"}]}} -{"type":"tool/result","data":{"turn":1,"step":5,"message":{"role":"tool","source":{"kind":"tool","callId":"call_cleanup_failure"},"toolCallId":"call_cleanup_failure","content":[{"type":"text","text":"started subagent {{id:5}}"}],"isError":false,"id":"{{message:18}}"}},"sourceEventSeqs":[50],"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent worker-4 failed before it finished."},{"type":"text","text":"It left no closing message."},{"type":"text","text":"Product subagent failure (product: Codex; stage: turn; category: transport; HTTP status: 503)"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-4 failed before it finished.","senderSessionId":"{{id:4}}"},"role":"user","id":"{{message:14}}"},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":5,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_cleanup_failure","name":"subagent_codex","arguments":"{\"description\":\"Observe completed output after cleanup failure\",\"prompt\":\"Complete the task, then fail cleanup.\",\"name\":\"worker-5\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-pro"},"id":"{{message:16}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1792123794590,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792123794590,"index":0,"dt":[],"id":"call_cleanup_failure","name":"subagent_codex","args":["{\"description\":\"Observe completed output after cleanup failure\",\"prompt\":\"Complete the task, then fail cleanup.\",\"name\":\"worker-5\"}"]},{"type":"chunk","time":1792123794590,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_cleanup_failure","name":"subagent_codex","arguments":"{\"description\":\"Observe completed output after cleanup failure\",\"prompt\":\"Complete the task, then fail cleanup.\",\"name\":\"worker-5\"}"}}},{"type":"chunk","time":1792123794590,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1792123794590,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":5,"callId":"call_cleanup_failure","name":"subagent_codex","arguments":"{\"description\":\"Observe completed output after cleanup failure\",\"prompt\":\"Complete the task, then fail cleanup.\",\"name\":\"worker-5\"}"}} +{"type":"subagent/catalog","data":{"version":2,"childId":"{{id:5}}","childCreatedAt":1792123794594,"mode":"external","label":"Observe completed output after cleanup failure"}} +{"type":"subagent/named","data":{"name":"worker-5","id":"{{id:5}}"}} +{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent worker-5 finished. It cannot receive follow-up messages."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"ANSWER_SURVIVES_CLEANUP_FAILURE"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-5 finished. It cannot receive follow-up messages.","senderSessionId":"{{id:5}}"},"role":"user","id":"{{message:17}}"}]}} +{"type":"tool/result","data":{"turn":1,"step":5,"message":{"role":"tool","source":{"kind":"tool","callId":"call_cleanup_failure"},"toolCallId":"call_cleanup_failure","content":[{"type":"text","text":"started subagent worker-5"}],"isError":false,"id":"{{message:18}}"}},"sourceEventSeqs":[54],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":5}} {"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":1,"step":6}} -{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent {{id:5}} finished. It cannot receive follow-up messages."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"ANSWER_SURVIVES_CLEANUP_FAILURE"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{id:5}} finished. It cannot receive follow-up messages.","senderSessionId":"{{id:5}}"},"role":"user","id":"{{message:17}}"},"surfaceOp":"append"} -{"type":"assistant/message","data":{"turn":1,"step":6,"message":{"role":"assistant","content":[{"type":"text","text":"PARENT_OBSERVED_DIAGNOSTICS"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-pro"},"id":"{{message:19}}"},"usage":{"inputTokens":10,"outputTokens":2},"stream":[{"type":"chunk","time":1789975216584,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1789975216584,"index":0,"dt":[],"texts":["PARENT_OBSERVED_DIAGNOSTICS"]},{"type":"chunk","time":1789975216584,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"PARENT_OBSERVED_DIAGNOSTICS"}}},{"type":"chunk","time":1789975216584,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":2}}},{"type":"chunk","time":1789975216584,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent worker-5 finished. It cannot receive follow-up messages."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"ANSWER_SURVIVES_CLEANUP_FAILURE"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-5 finished. It cannot receive follow-up messages.","senderSessionId":"{{id:5}}"},"role":"user","id":"{{message:17}}"},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":6,"message":{"role":"assistant","content":[{"type":"text","text":"PARENT_OBSERVED_DIAGNOSTICS"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-pro"},"id":"{{message:19}}"},"usage":{"inputTokens":10,"outputTokens":2},"stream":[{"type":"chunk","time":1792123794607,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1792123794607,"index":0,"dt":[],"texts":["PARENT_OBSERVED_DIAGNOSTICS"]},{"type":"chunk","time":1792123794607,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"PARENT_OBSERVED_DIAGNOSTICS"}}},{"type":"chunk","time":1792123794607,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":2}}},{"type":"chunk","time":1792123794607,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":6}} {"type":"turn/end","data":{"turn":1,"reason":{"kind":"completed"}}} diff --git a/snapshots/session/product-subagent-result-diagnostic/tool-schemas.expected.json b/snapshots/session/product-subagent-result-diagnostic/tool-schemas.expected.json index 87df175ba4..1515f4be94 100644 --- a/snapshots/session/product-subagent-result-diagnostic/tool-schemas.expected.json +++ b/snapshots/session/product-subagent-result-diagnostic/tool-schemas.expected.json @@ -181,13 +181,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -245,7 +245,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -297,9 +297,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -307,7 +307,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -330,10 +330,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -348,6 +352,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -355,10 +360,14 @@ }, { "name": "subagent_codex", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The completion notice includes its final answer. This backend does not accept follow-up messages.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The completion notice includes its final answer. This backend does not accept follow-up messages.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -373,6 +382,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -380,10 +390,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -398,6 +412,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/session/provider-cwd/tool-schemas.expected.json b/snapshots/session/provider-cwd/tool-schemas.expected.json index b546a748a7..99b37246de 100644 --- a/snapshots/session/provider-cwd/tool-schemas.expected.json +++ b/snapshots/session/provider-cwd/tool-schemas.expected.json @@ -181,13 +181,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -245,7 +245,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -297,9 +297,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -307,7 +307,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -330,10 +330,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -348,6 +352,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -355,10 +360,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -373,6 +382,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/session/ptc-node-read-only/system-prompt.expected.md b/snapshots/session/ptc-node-read-only/system-prompt.expected.md index 80c671f372..ccb3ffc7da 100644 --- a/snapshots/session/ptc-node-read-only/system-prompt.expected.md +++ b/snapshots/session/ptc-node-read-only/system-prompt.expected.md @@ -114,8 +114,8 @@ interface ToolArgsMap { } & Record; /** Ask a subagent to stop its current work. This call returns without waiting for it to stop. You can continue a local direct child's conversation later with send_message. External executions stop permanently and cannot receive follow-ups. Subagents it started will keep running. */ interrupt_agent: { - /** The id of an agent created under you: your direct child or a deeper descendant. */ - agent_id: string; + /** The name of an agent created under you: your direct child or a deeper descendant. */ + name: string; } & Record; /** Request cancellation of a running background job. */ job_kill: { @@ -135,7 +135,7 @@ interface ToolArgsMap { /** Max wait in milliseconds with wait: true. Defaults to and is capped by configuration. */ timeout_ms?: number; } & Record; - /** List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation. */ + /** List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation. */ list_agents: Record; /** Read a UTF-8 text file and return line-numbered content. */ read: { @@ -153,8 +153,8 @@ interface ToolArgsMap { } & Record; /** Send a message to an agent. A working agent receives it at its next step; an idle agent starts a new turn with it. Returns delivery confirmation, not the agent's answer. */ send_message: { - /** The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child. */ - agent_id: string; + /** The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child. */ + name: string; /** The message to deliver to the agent. */ message: string; } & Record; @@ -163,8 +163,10 @@ interface ToolArgsMap { /** The exact skill name from the available skills list. */ name: string; } & Record; - /** Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ + /** Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ subagent: { + /** Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish. */ + name: string; /** Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent. */ cwd?: string; /** A short (3-5 word) description of the delegated task, for display. */ @@ -172,8 +174,10 @@ interface ToolArgsMap { /** The complete, self-contained task for the subagent. It does not share this conversation's context, so include everything it needs. */ prompt: string; } & Record; - /** Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ + /** Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ subagent_fork: { + /** Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish. */ + name: string; /** Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent. */ cwd?: string; /** A short (3-5 word) description of the delegated task, for display. */ @@ -396,18 +400,18 @@ interface ToolOutputMap { }; list_agents: ({ kind: "parent"; - id: string; + name: string; status: "running" | "inactive"; } | { kind: "child" | "sibling"; - id: string; + name: string; label: string; status: "running" | "inactive"; parent?: string; depth?: number; } | { kind: "diagnostic"; - id: string; + name: string; reason: "corrupt" | "unsupported" | "unavailable"; parent?: string; depth?: number; @@ -458,11 +462,11 @@ interface ToolOutputMap { }; subagent: { kind: "activation"; - subagentId: string; + name: string; }; subagent_fork: { kind: "activation"; - subagentId: string; + name: string; }; template_echo: string; todo_write: { diff --git a/snapshots/session/ptc-node-workspace/system-prompt.expected.md b/snapshots/session/ptc-node-workspace/system-prompt.expected.md index 80c671f372..ccb3ffc7da 100644 --- a/snapshots/session/ptc-node-workspace/system-prompt.expected.md +++ b/snapshots/session/ptc-node-workspace/system-prompt.expected.md @@ -114,8 +114,8 @@ interface ToolArgsMap { } & Record; /** Ask a subagent to stop its current work. This call returns without waiting for it to stop. You can continue a local direct child's conversation later with send_message. External executions stop permanently and cannot receive follow-ups. Subagents it started will keep running. */ interrupt_agent: { - /** The id of an agent created under you: your direct child or a deeper descendant. */ - agent_id: string; + /** The name of an agent created under you: your direct child or a deeper descendant. */ + name: string; } & Record; /** Request cancellation of a running background job. */ job_kill: { @@ -135,7 +135,7 @@ interface ToolArgsMap { /** Max wait in milliseconds with wait: true. Defaults to and is capped by configuration. */ timeout_ms?: number; } & Record; - /** List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation. */ + /** List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation. */ list_agents: Record; /** Read a UTF-8 text file and return line-numbered content. */ read: { @@ -153,8 +153,8 @@ interface ToolArgsMap { } & Record; /** Send a message to an agent. A working agent receives it at its next step; an idle agent starts a new turn with it. Returns delivery confirmation, not the agent's answer. */ send_message: { - /** The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child. */ - agent_id: string; + /** The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child. */ + name: string; /** The message to deliver to the agent. */ message: string; } & Record; @@ -163,8 +163,10 @@ interface ToolArgsMap { /** The exact skill name from the available skills list. */ name: string; } & Record; - /** Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ + /** Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ subagent: { + /** Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish. */ + name: string; /** Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent. */ cwd?: string; /** A short (3-5 word) description of the delegated task, for display. */ @@ -172,8 +174,10 @@ interface ToolArgsMap { /** The complete, self-contained task for the subagent. It does not share this conversation's context, so include everything it needs. */ prompt: string; } & Record; - /** Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ + /** Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ subagent_fork: { + /** Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish. */ + name: string; /** Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent. */ cwd?: string; /** A short (3-5 word) description of the delegated task, for display. */ @@ -396,18 +400,18 @@ interface ToolOutputMap { }; list_agents: ({ kind: "parent"; - id: string; + name: string; status: "running" | "inactive"; } | { kind: "child" | "sibling"; - id: string; + name: string; label: string; status: "running" | "inactive"; parent?: string; depth?: number; } | { kind: "diagnostic"; - id: string; + name: string; reason: "corrupt" | "unsupported" | "unavailable"; parent?: string; depth?: number; @@ -458,11 +462,11 @@ interface ToolOutputMap { }; subagent: { kind: "activation"; - subagentId: string; + name: string; }; subagent_fork: { kind: "activation"; - subagentId: string; + name: string; }; template_echo: string; todo_write: { diff --git a/snapshots/session/ptc-persistent/system-prompt.expected.md b/snapshots/session/ptc-persistent/system-prompt.expected.md index 80c671f372..ccb3ffc7da 100644 --- a/snapshots/session/ptc-persistent/system-prompt.expected.md +++ b/snapshots/session/ptc-persistent/system-prompt.expected.md @@ -114,8 +114,8 @@ interface ToolArgsMap { } & Record; /** Ask a subagent to stop its current work. This call returns without waiting for it to stop. You can continue a local direct child's conversation later with send_message. External executions stop permanently and cannot receive follow-ups. Subagents it started will keep running. */ interrupt_agent: { - /** The id of an agent created under you: your direct child or a deeper descendant. */ - agent_id: string; + /** The name of an agent created under you: your direct child or a deeper descendant. */ + name: string; } & Record; /** Request cancellation of a running background job. */ job_kill: { @@ -135,7 +135,7 @@ interface ToolArgsMap { /** Max wait in milliseconds with wait: true. Defaults to and is capped by configuration. */ timeout_ms?: number; } & Record; - /** List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation. */ + /** List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation. */ list_agents: Record; /** Read a UTF-8 text file and return line-numbered content. */ read: { @@ -153,8 +153,8 @@ interface ToolArgsMap { } & Record; /** Send a message to an agent. A working agent receives it at its next step; an idle agent starts a new turn with it. Returns delivery confirmation, not the agent's answer. */ send_message: { - /** The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child. */ - agent_id: string; + /** The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child. */ + name: string; /** The message to deliver to the agent. */ message: string; } & Record; @@ -163,8 +163,10 @@ interface ToolArgsMap { /** The exact skill name from the available skills list. */ name: string; } & Record; - /** Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ + /** Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ subagent: { + /** Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish. */ + name: string; /** Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent. */ cwd?: string; /** A short (3-5 word) description of the delegated task, for display. */ @@ -172,8 +174,10 @@ interface ToolArgsMap { /** The complete, self-contained task for the subagent. It does not share this conversation's context, so include everything it needs. */ prompt: string; } & Record; - /** Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ + /** Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ subagent_fork: { + /** Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish. */ + name: string; /** Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent. */ cwd?: string; /** A short (3-5 word) description of the delegated task, for display. */ @@ -396,18 +400,18 @@ interface ToolOutputMap { }; list_agents: ({ kind: "parent"; - id: string; + name: string; status: "running" | "inactive"; } | { kind: "child" | "sibling"; - id: string; + name: string; label: string; status: "running" | "inactive"; parent?: string; depth?: number; } | { kind: "diagnostic"; - id: string; + name: string; reason: "corrupt" | "unsupported" | "unavailable"; parent?: string; depth?: number; @@ -458,11 +462,11 @@ interface ToolOutputMap { }; subagent: { kind: "activation"; - subagentId: string; + name: string; }; subagent_fork: { kind: "activation"; - subagentId: string; + name: string; }; template_echo: string; todo_write: { diff --git a/snapshots/session/ptc-policy-change/system-prompt.expected.md b/snapshots/session/ptc-policy-change/system-prompt.expected.md index e2ae9d653d..52d6f3232d 100644 --- a/snapshots/session/ptc-policy-change/system-prompt.expected.md +++ b/snapshots/session/ptc-policy-change/system-prompt.expected.md @@ -114,8 +114,8 @@ interface ToolArgsMap { } & Record; /** Ask a subagent to stop its current work. This call returns without waiting for it to stop. You can continue a local direct child's conversation later with send_message. External executions stop permanently and cannot receive follow-ups. Subagents it started will keep running. */ interrupt_agent: { - /** The id of an agent created under you: your direct child or a deeper descendant. */ - agent_id: string; + /** The name of an agent created under you: your direct child or a deeper descendant. */ + name: string; } & Record; /** Request cancellation of a running background job. */ job_kill: { @@ -135,7 +135,7 @@ interface ToolArgsMap { /** Max wait in milliseconds with wait: true. Defaults to and is capped by configuration. */ timeout_ms?: number; } & Record; - /** List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation. */ + /** List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation. */ list_agents: Record; /** Read a UTF-8 text file and return line-numbered content. */ read: { @@ -153,8 +153,8 @@ interface ToolArgsMap { } & Record; /** Send a message to an agent. A working agent receives it at its next step; an idle agent starts a new turn with it. Returns delivery confirmation, not the agent's answer. */ send_message: { - /** The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child. */ - agent_id: string; + /** The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child. */ + name: string; /** The message to deliver to the agent. */ message: string; } & Record; @@ -163,8 +163,10 @@ interface ToolArgsMap { /** The exact skill name from the available skills list. */ name: string; } & Record; - /** Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ + /** Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ subagent: { + /** Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish. */ + name: string; /** Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent. */ cwd?: string; /** A short (3-5 word) description of the delegated task, for display. */ @@ -172,8 +174,10 @@ interface ToolArgsMap { /** The complete, self-contained task for the subagent. It does not share this conversation's context, so include everything it needs. */ prompt: string; } & Record; - /** Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ + /** Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ subagent_fork: { + /** Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish. */ + name: string; /** Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent. */ cwd?: string; /** A short (3-5 word) description of the delegated task, for display. */ @@ -394,18 +398,18 @@ interface ToolOutputMap { }; list_agents: ({ kind: "parent"; - id: string; + name: string; status: "running" | "inactive"; } | { kind: "child" | "sibling"; - id: string; + name: string; label: string; status: "running" | "inactive"; parent?: string; depth?: number; } | { kind: "diagnostic"; - id: string; + name: string; reason: "corrupt" | "unsupported" | "unavailable"; parent?: string; depth?: number; @@ -456,11 +460,11 @@ interface ToolOutputMap { }; subagent: { kind: "activation"; - subagentId: string; + name: string; }; subagent_fork: { kind: "activation"; - subagentId: string; + name: string; }; todo_write: { todos: ({ diff --git a/snapshots/session/ptc-python-turn/system-prompt.expected.md b/snapshots/session/ptc-python-turn/system-prompt.expected.md index 586a413269..4aa4cf67b6 100644 --- a/snapshots/session/ptc-python-turn/system-prompt.expected.md +++ b/snapshots/session/ptc-python-turn/system-prompt.expected.md @@ -209,8 +209,8 @@ class GrepOutput(TypedDict): matches: list[GrepOutputMatches] class InterruptAgentArgs(TypedDict): - # The id of an agent created under you: your direct child or a deeper descendant. - agent_id: str + # The name of an agent created under you: your direct child or a deeper descendant. + name: str # Additional keys beyond those declared are allowed. class InterruptAgentOutput(TypedDict): @@ -269,12 +269,12 @@ class JobOutputOutput(TypedDict): class ListAgentsOutput1(TypedDict): kind: Literal["parent"] - id: str + name: str status: Literal["running", "inactive"] class ListAgentsOutput2(TypedDict): kind: Literal["child", "sibling"] - id: str + name: str label: str status: Literal["running", "inactive"] parent: NotRequired[str] @@ -282,7 +282,7 @@ class ListAgentsOutput2(TypedDict): class ListAgentsOutput3(TypedDict): kind: Literal["diagnostic"] - id: str + name: str reason: Literal["corrupt", "unsupported", "unavailable"] parent: NotRequired[str] depth: NotRequired[float] @@ -331,8 +331,8 @@ class ReadImageOutput(TypedDict): image: ReadImageOutputImage class SendMessageArgs(TypedDict): - # The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child. - agent_id: str + # The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child. + name: str # The message to deliver to the agent. message: str # Additional keys beyond those declared are allowed. @@ -364,6 +364,8 @@ class SkillOutput(TypedDict): content: str class SubagentArgs(TypedDict): + # Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish. + name: str # Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent. cwd: NotRequired[str] # A short (3-5 word) description of the delegated task, for display. @@ -374,9 +376,11 @@ class SubagentArgs(TypedDict): class SubagentOutput(TypedDict): kind: Literal["activation"] - subagentId: str + name: str class SubagentForkArgs(TypedDict): + # Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish. + name: str # Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent. cwd: NotRequired[str] # A short (3-5 word) description of the delegated task, for display. @@ -387,7 +391,7 @@ class SubagentForkArgs(TypedDict): class SubagentForkOutput(TypedDict): kind: Literal["activation"] - subagentId: str + name: str class TodoWriteArgsTodos(TypedDict): # What the task is — a short imperative line. @@ -534,7 +538,7 @@ class Tools(Protocol): async def job_output(self, args: JobOutputArgs) -> JobOutputOutput: """Read a background job: output since the previous read for stream jobs, or the result of a finished final-output job.""" async def list_agents(self, args: dict[str, Any]) -> list[ListAgentsOutput1 | ListAgentsOutput2 | ListAgentsOutput3]: - """List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.""" + """List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.""" async def read(self, args: ReadArgs) -> ReadOutput: """Read a UTF-8 text file and return line-numbered content.""" async def read_image(self, args: ReadImageArgs) -> ReadImageOutput: @@ -544,9 +548,9 @@ class Tools(Protocol): async def skill(self, args: SkillArgs) -> SkillOutput: """Load the full instructions for a skill. Call it before acting on a task that names or clearly matches a skill in the session skill catalog.""" async def subagent(self, args: SubagentArgs) -> SubagentOutput: - """Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.""" + """Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.""" async def subagent_fork(self, args: SubagentForkArgs) -> SubagentForkOutput: - """Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.""" + """Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.""" async def todo_write(self, args: TodoWriteArgs) -> TodoWriteOutput: """Record and update a task list to plan multi-step work and show progress; skip it for trivial single-step tasks. Add one todo per concrete step before you start. While work remains, keep the todos being worked on `in_progress`, several only when work runs in parallel. Mark each todo `completed` as soon as it is done.""" async def update_goal(self, args: UpdateGoalArgs) -> UpdateGoalOutput1 | UpdateGoalOutput2: diff --git a/snapshots/session/ptc-read-image/system-prompt.expected.md b/snapshots/session/ptc-read-image/system-prompt.expected.md index dbb8204298..836c0a988e 100644 --- a/snapshots/session/ptc-read-image/system-prompt.expected.md +++ b/snapshots/session/ptc-read-image/system-prompt.expected.md @@ -114,8 +114,8 @@ interface ToolArgsMap { } & Record; /** Ask a subagent to stop its current work. This call returns without waiting for it to stop. You can continue a local direct child's conversation later with send_message. External executions stop permanently and cannot receive follow-ups. Subagents it started will keep running. */ interrupt_agent: { - /** The id of an agent created under you: your direct child or a deeper descendant. */ - agent_id: string; + /** The name of an agent created under you: your direct child or a deeper descendant. */ + name: string; } & Record; /** Request cancellation of a running background job. */ job_kill: { @@ -135,7 +135,7 @@ interface ToolArgsMap { /** Max wait in milliseconds with wait: true. Defaults to and is capped by configuration. */ timeout_ms?: number; } & Record; - /** List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation. */ + /** List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation. */ list_agents: Record; /** Read a UTF-8 text file and return line-numbered content. */ read: { @@ -153,8 +153,8 @@ interface ToolArgsMap { } & Record; /** Send a message to an agent. A working agent receives it at its next step; an idle agent starts a new turn with it. Returns delivery confirmation, not the agent's answer. */ send_message: { - /** The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child. */ - agent_id: string; + /** The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child. */ + name: string; /** The message to deliver to the agent. */ message: string; } & Record; @@ -163,8 +163,10 @@ interface ToolArgsMap { /** The exact skill name from the available skills list. */ name: string; } & Record; - /** Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ + /** Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ subagent: { + /** Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish. */ + name: string; /** Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent. */ cwd?: string; /** A short (3-5 word) description of the delegated task, for display. */ @@ -172,8 +174,10 @@ interface ToolArgsMap { /** The complete, self-contained task for the subagent. It does not share this conversation's context, so include everything it needs. */ prompt: string; } & Record; - /** Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ + /** Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ subagent_fork: { + /** Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish. */ + name: string; /** Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent. */ cwd?: string; /** A short (3-5 word) description of the delegated task, for display. */ @@ -392,18 +396,18 @@ interface ToolOutputMap { }; list_agents: ({ kind: "parent"; - id: string; + name: string; status: "running" | "inactive"; } | { kind: "child" | "sibling"; - id: string; + name: string; label: string; status: "running" | "inactive"; parent?: string; depth?: number; } | { kind: "diagnostic"; - id: string; + name: string; reason: "corrupt" | "unsupported" | "unavailable"; parent?: string; depth?: number; @@ -454,11 +458,11 @@ interface ToolOutputMap { }; subagent: { kind: "activation"; - subagentId: string; + name: string; }; subagent_fork: { kind: "activation"; - subagentId: string; + name: string; }; todo_write: { todos: ({ diff --git a/snapshots/session/ptc-turn/system-prompt.expected.md b/snapshots/session/ptc-turn/system-prompt.expected.md index 80c671f372..ccb3ffc7da 100644 --- a/snapshots/session/ptc-turn/system-prompt.expected.md +++ b/snapshots/session/ptc-turn/system-prompt.expected.md @@ -114,8 +114,8 @@ interface ToolArgsMap { } & Record; /** Ask a subagent to stop its current work. This call returns without waiting for it to stop. You can continue a local direct child's conversation later with send_message. External executions stop permanently and cannot receive follow-ups. Subagents it started will keep running. */ interrupt_agent: { - /** The id of an agent created under you: your direct child or a deeper descendant. */ - agent_id: string; + /** The name of an agent created under you: your direct child or a deeper descendant. */ + name: string; } & Record; /** Request cancellation of a running background job. */ job_kill: { @@ -135,7 +135,7 @@ interface ToolArgsMap { /** Max wait in milliseconds with wait: true. Defaults to and is capped by configuration. */ timeout_ms?: number; } & Record; - /** List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation. */ + /** List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation. */ list_agents: Record; /** Read a UTF-8 text file and return line-numbered content. */ read: { @@ -153,8 +153,8 @@ interface ToolArgsMap { } & Record; /** Send a message to an agent. A working agent receives it at its next step; an idle agent starts a new turn with it. Returns delivery confirmation, not the agent's answer. */ send_message: { - /** The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child. */ - agent_id: string; + /** The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child. */ + name: string; /** The message to deliver to the agent. */ message: string; } & Record; @@ -163,8 +163,10 @@ interface ToolArgsMap { /** The exact skill name from the available skills list. */ name: string; } & Record; - /** Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ + /** Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ subagent: { + /** Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish. */ + name: string; /** Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent. */ cwd?: string; /** A short (3-5 word) description of the delegated task, for display. */ @@ -172,8 +174,10 @@ interface ToolArgsMap { /** The complete, self-contained task for the subagent. It does not share this conversation's context, so include everything it needs. */ prompt: string; } & Record; - /** Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ + /** Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ subagent_fork: { + /** Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish. */ + name: string; /** Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent. */ cwd?: string; /** A short (3-5 word) description of the delegated task, for display. */ @@ -396,18 +400,18 @@ interface ToolOutputMap { }; list_agents: ({ kind: "parent"; - id: string; + name: string; status: "running" | "inactive"; } | { kind: "child" | "sibling"; - id: string; + name: string; label: string; status: "running" | "inactive"; parent?: string; depth?: number; } | { kind: "diagnostic"; - id: string; + name: string; reason: "corrupt" | "unsupported" | "unavailable"; parent?: string; depth?: number; @@ -458,11 +462,11 @@ interface ToolOutputMap { }; subagent: { kind: "activation"; - subagentId: string; + name: string; }; subagent_fork: { kind: "activation"; - subagentId: string; + name: string; }; template_echo: string; todo_write: { diff --git a/snapshots/session/pty-tools-sandbox-backend/tool-schemas.expected.json b/snapshots/session/pty-tools-sandbox-backend/tool-schemas.expected.json index 77611208ff..b65f4a1322 100644 --- a/snapshots/session/pty-tools-sandbox-backend/tool-schemas.expected.json +++ b/snapshots/session/pty-tools-sandbox-backend/tool-schemas.expected.json @@ -181,13 +181,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -245,7 +245,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -297,9 +297,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -307,7 +307,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -330,10 +330,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -348,6 +352,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -355,10 +360,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -373,6 +382,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/session/pwsh-tool-turn/tool-schemas.expected.json b/snapshots/session/pwsh-tool-turn/tool-schemas.expected.json index c92b5e720f..e60890ab26 100644 --- a/snapshots/session/pwsh-tool-turn/tool-schemas.expected.json +++ b/snapshots/session/pwsh-tool-turn/tool-schemas.expected.json @@ -108,13 +108,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -172,7 +172,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -269,9 +269,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -279,17 +279,21 @@ } }, "required": [ - "agent_id", + "name", "message" ] } }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -304,6 +308,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -311,10 +316,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -329,6 +338,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/session/ralph-loop/session.v4.jsonl b/snapshots/session/ralph-loop/session.v4.jsonl index 8ebcaebed2..9eb74aa7fe 100644 --- a/snapshots/session/ralph-loop/session.v4.jsonl +++ b/snapshots/session/ralph-loop/session.v4.jsonl @@ -12,13 +12,15 @@ {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} {"type":"session/title","data":{"title":"Run a two-round fresh-agent Ralph","messageSeqs":[8],"source":{"kind":"fallback"}}} -{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_ralph","name":"ralph","arguments":"{\"objective\":\"Prove two fresh Ralph rounds through the shipped headless app.\",\"maxRounds\":2}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":20,"outputTokens":8},"stream":[{"type":"chunk","time":1790156853942,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1790156853942,"index":0,"dt":[],"id":"call_ralph","name":"ralph","args":["{\"objective\":\"Prove two fresh Ralph rounds through the shipped headless app.\",\"maxRounds\":2}"]},{"type":"chunk","time":1790156853943,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_ralph","name":"ralph","arguments":"{\"objective\":\"Prove two fresh Ralph rounds through the shipped headless app.\",\"maxRounds\":2}"}}},{"type":"chunk","time":1790156853943,"chunk":{"type":"usage","usage":{"inputTokens":20,"outputTokens":8}}},{"type":"chunk","time":1790156853943,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_ralph","name":"ralph","arguments":"{\"objective\":\"Prove two fresh Ralph rounds through the shipped headless app.\",\"maxRounds\":2}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":20,"outputTokens":8},"stream":[{"type":"chunk","time":1792124598917,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792124598918,"index":0,"dt":[],"id":"call_ralph","name":"ralph","args":["{\"objective\":\"Prove two fresh Ralph rounds through the shipped headless app.\",\"maxRounds\":2}"]},{"type":"chunk","time":1792124598918,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_ralph","name":"ralph","arguments":"{\"objective\":\"Prove two fresh Ralph rounds through the shipped headless app.\",\"maxRounds\":2}"}}},{"type":"chunk","time":1792124598918,"chunk":{"type":"usage","usage":{"inputTokens":20,"outputTokens":8}}},{"type":"chunk","time":1792124598918,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} {"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_ralph","name":"ralph","arguments":"{\"objective\":\"Prove two fresh Ralph rounds through the shipped headless app.\",\"maxRounds\":2}"}} -{"type":"subagent/catalog","data":{"version":0,"childId":"{{session:2}}","childCreatedAt":1783951001000,"mode":"continuable","label":"ralph-loop child 1"}} -{"type":"subagent/catalog","data":{"version":0,"childId":"{{session:3}}","childCreatedAt":1783951002000,"mode":"continuable","label":"ralph-loop child 2"}} +{"type":"subagent/catalog","data":{"version":0,"childId":"{{session:2}}","childCreatedAt":1792124599036,"mode":"continuable","label":"ralph-loop child 1"}} +{"type":"subagent/named","data":{"name":"workflow-{{workflow:1}}-1","id":"{{session:2}}"}} +{"type":"subagent/catalog","data":{"version":0,"childId":"{{session:3}}","childCreatedAt":1792124599090,"mode":"continuable","label":"ralph-loop child 2"}} +{"type":"subagent/named","data":{"name":"workflow-{{workflow:1}}-2","id":"{{session:3}}"}} {"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_ralph"},"toolCallId":"call_ralph","content":[{"type":"text","text":"Ralph worker reported completion after 2 rounds.\nFinal report:\n{\n \"status\": \"complete\",\n \"summary\": \"The Ralph snapshot objective is complete.\",\n \"evidence\": [\n \"Two fresh rounds completed through the shipped app.\"\n ],\n \"nextSteps\": [],\n \"blocker\": \"\"\n}"}],"isError":false,"id":"{{message:5}}"}},"sourceEventSeqs":[14],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":1}} {"type":"step/start","data":{"turn":1,"step":2}} -{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"text","text":"RALPH SNAPSHOT COMPLETE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:6}}"},"usage":{"inputTokens":30,"outputTokens":4},"stream":[{"type":"chunk","time":1790156854728,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1790156854728,"index":0,"dt":[],"texts":["RALPH SNAPSHOT COMPLETE"]},{"type":"chunk","time":1790156854728,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"RALPH SNAPSHOT COMPLETE"}}},{"type":"chunk","time":1790156854728,"chunk":{"type":"usage","usage":{"inputTokens":30,"outputTokens":4}}},{"type":"chunk","time":1790156854728,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"text","text":"RALPH SNAPSHOT COMPLETE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:6}}"},"usage":{"inputTokens":30,"outputTokens":4},"stream":[{"type":"chunk","time":1792124599180,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1792124599180,"index":0,"dt":[],"texts":["RALPH SNAPSHOT COMPLETE"]},{"type":"chunk","time":1792124599180,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"RALPH SNAPSHOT COMPLETE"}}},{"type":"chunk","time":1792124599180,"chunk":{"type":"usage","usage":{"inputTokens":30,"outputTokens":4}}},{"type":"chunk","time":1792124599180,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":2}} {"type":"turn/end","data":{"turn":1,"reason":{"kind":"completed"}}} diff --git a/snapshots/session/ralph-loop/tool-schemas.1.expected.json b/snapshots/session/ralph-loop/tool-schemas.1.expected.json index dfd4c2dda6..3d5fe2433c 100644 --- a/snapshots/session/ralph-loop/tool-schemas.1.expected.json +++ b/snapshots/session/ralph-loop/tool-schemas.1.expected.json @@ -181,13 +181,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -245,7 +245,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -317,9 +317,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -327,7 +327,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -393,10 +393,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -411,6 +415,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -418,10 +423,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -436,6 +445,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/session/ralph-loop/tool-schemas.2.expected.json b/snapshots/session/ralph-loop/tool-schemas.2.expected.json index dfd4c2dda6..3d5fe2433c 100644 --- a/snapshots/session/ralph-loop/tool-schemas.2.expected.json +++ b/snapshots/session/ralph-loop/tool-schemas.2.expected.json @@ -181,13 +181,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -245,7 +245,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -317,9 +317,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -327,7 +327,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -393,10 +393,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -411,6 +415,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -418,10 +423,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -436,6 +445,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/session/ralph-loop/tool-schemas.expected.json b/snapshots/session/ralph-loop/tool-schemas.expected.json index dda5ee11cc..b910765a88 100644 --- a/snapshots/session/ralph-loop/tool-schemas.expected.json +++ b/snapshots/session/ralph-loop/tool-schemas.expected.json @@ -181,13 +181,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -245,7 +245,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -317,9 +317,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -327,7 +327,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -350,10 +350,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -368,6 +372,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -375,10 +380,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -393,6 +402,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/session/session-query-spill/tool-schemas.expected.json b/snapshots/session/session-query-spill/tool-schemas.expected.json index 3e25a6db8e..6dced30431 100644 --- a/snapshots/session/session-query-spill/tool-schemas.expected.json +++ b/snapshots/session/session-query-spill/tool-schemas.expected.json @@ -181,13 +181,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -245,7 +245,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -297,9 +297,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -307,7 +307,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -534,10 +534,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -552,6 +556,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -559,10 +564,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -577,6 +586,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/session/subagent-acp-diagnostic/replay.override.json b/snapshots/session/subagent-acp-diagnostic/replay.override.json index f6fcb394e3..21941ec7f9 100644 --- a/snapshots/session/subagent-acp-diagnostic/replay.override.json +++ b/snapshots/session/subagent-acp-diagnostic/replay.override.json @@ -12,7 +12,7 @@ "index": 0, "id": "call_acp_first", "name": "subagent_acp", - "argumentsDelta": "{\"description\":\"Observe first ACP failure\",\"prompt\":\"Return the scripted ACP failure.\"}" + "argumentsDelta": "{\"description\":\"Observe first ACP failure\",\"prompt\":\"Return the scripted ACP failure.\",\"name\":\"worker-1\"}" }, { "type": "block-end", @@ -21,7 +21,7 @@ "type": "tool-call", "id": "call_acp_first", "name": "subagent_acp", - "arguments": "{\"description\":\"Observe first ACP failure\",\"prompt\":\"Return the scripted ACP failure.\"}" + "arguments": "{\"description\":\"Observe first ACP failure\",\"prompt\":\"Return the scripted ACP failure.\",\"name\":\"worker-1\"}" } }, { @@ -52,7 +52,7 @@ "index": 0, "id": "call_acp_second", "name": "subagent_acp", - "argumentsDelta": "{\"description\":\"Observe second ACP failure\",\"prompt\":\"Return the scripted ACP failure.\"}" + "argumentsDelta": "{\"description\":\"Observe second ACP failure\",\"prompt\":\"Return the scripted ACP failure.\",\"name\":\"worker-2\"}" }, { "type": "block-end", @@ -61,7 +61,7 @@ "type": "tool-call", "id": "call_acp_second", "name": "subagent_acp", - "arguments": "{\"description\":\"Observe second ACP failure\",\"prompt\":\"Return the scripted ACP failure.\"}" + "arguments": "{\"description\":\"Observe second ACP failure\",\"prompt\":\"Return the scripted ACP failure.\",\"name\":\"worker-2\"}" } }, { diff --git a/snapshots/session/subagent-acp-diagnostic/session.v4.jsonl b/snapshots/session/subagent-acp-diagnostic/session.v4.jsonl index e2d7750566..bbe4971cf8 100644 --- a/snapshots/session/subagent-acp-diagnostic/session.v4.jsonl +++ b/snapshots/session/subagent-acp-diagnostic/session.v4.jsonl @@ -12,24 +12,26 @@ {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-pro"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-pro"}} {"type":"session/title","data":{"title":"Observe the ACP diagnostic twice","messageSeqs":[8],"source":{"kind":"fallback"}}} -{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_acp_first","name":"subagent_acp","arguments":"{\"description\":\"Observe first ACP failure\",\"prompt\":\"Return the scripted ACP failure.\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-pro"},"id":"{{message:4}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1789820717257,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1789820717257,"index":0,"dt":[],"id":"call_acp_first","name":"subagent_acp","args":["{\"description\":\"Observe first ACP failure\",\"prompt\":\"Return the scripted ACP failure.\"}"]},{"type":"chunk","time":1789820717257,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_acp_first","name":"subagent_acp","arguments":"{\"description\":\"Observe first ACP failure\",\"prompt\":\"Return the scripted ACP failure.\"}"}}},{"type":"chunk","time":1789820717257,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1789820717257,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} -{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_acp_first","name":"subagent_acp","arguments":"{\"description\":\"Observe first ACP failure\",\"prompt\":\"Return the scripted ACP failure.\"}"}} -{"type":"subagent/catalog","data":{"version":2,"childId":"{{id:1}}","childCreatedAt":1789820717386,"mode":"external","label":"Observe first ACP failure"}} -{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent {{id:1}} was stopped before it finished."},{"type":"text","text":"It left no closing message."},{"type":"text","text":"ACP unattended decision (policy: reject; request: execute; decision: denied)"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{id:1}} was stopped before it finished.","senderSessionId":"{{id:1}}"},"role":"user","id":"{{message:5}}"}]}} -{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_acp_first"},"toolCallId":"call_acp_first","content":[{"type":"text","text":"started subagent {{id:1}}"}],"isError":false,"id":"{{message:6}}"}},"sourceEventSeqs":[14],"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_acp_first","name":"subagent_acp","arguments":"{\"description\":\"Observe first ACP failure\",\"prompt\":\"Return the scripted ACP failure.\",\"name\":\"worker-1\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-pro"},"id":"{{message:4}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1792123795368,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792123795368,"index":0,"dt":[],"id":"call_acp_first","name":"subagent_acp","args":["{\"description\":\"Observe first ACP failure\",\"prompt\":\"Return the scripted ACP failure.\",\"name\":\"worker-1\"}"]},{"type":"chunk","time":1792123795368,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_acp_first","name":"subagent_acp","arguments":"{\"description\":\"Observe first ACP failure\",\"prompt\":\"Return the scripted ACP failure.\",\"name\":\"worker-1\"}"}}},{"type":"chunk","time":1792123795368,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1792123795368,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_acp_first","name":"subagent_acp","arguments":"{\"description\":\"Observe first ACP failure\",\"prompt\":\"Return the scripted ACP failure.\",\"name\":\"worker-1\"}"}} +{"type":"subagent/catalog","data":{"version":2,"childId":"{{id:1}}","childCreatedAt":1792123795489,"mode":"external","label":"Observe first ACP failure"}} +{"type":"subagent/named","data":{"name":"worker-1","id":"{{id:1}}"}} +{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent worker-1 was stopped before it finished."},{"type":"text","text":"It left no closing message."},{"type":"text","text":"ACP unattended decision (policy: reject; request: execute; decision: denied)"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 was stopped before it finished.","senderSessionId":"{{id:1}}"},"role":"user","id":"{{message:5}}"}]}} +{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_acp_first"},"toolCallId":"call_acp_first","content":[{"type":"text","text":"started subagent worker-1"}],"isError":false,"id":"{{message:6}}"}},"sourceEventSeqs":[14],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":1}} {"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":1,"step":2}} -{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent {{id:1}} was stopped before it finished."},{"type":"text","text":"It left no closing message."},{"type":"text","text":"ACP unattended decision (policy: reject; request: execute; decision: denied)"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{id:1}} was stopped before it finished.","senderSessionId":"{{id:1}}"},"role":"user","id":"{{message:5}}"},"surfaceOp":"append"} -{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_acp_second","name":"subagent_acp","arguments":"{\"description\":\"Observe second ACP failure\",\"prompt\":\"Return the scripted ACP failure.\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-pro"},"id":"{{message:7}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1789820717420,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1789820717420,"index":0,"dt":[],"id":"call_acp_second","name":"subagent_acp","args":["{\"description\":\"Observe second ACP failure\",\"prompt\":\"Return the scripted ACP failure.\"}"]},{"type":"chunk","time":1789820717420,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_acp_second","name":"subagent_acp","arguments":"{\"description\":\"Observe second ACP failure\",\"prompt\":\"Return the scripted ACP failure.\"}"}}},{"type":"chunk","time":1789820717420,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1789820717420,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} -{"type":"tool/call","data":{"turn":1,"step":2,"callId":"call_acp_second","name":"subagent_acp","arguments":"{\"description\":\"Observe second ACP failure\",\"prompt\":\"Return the scripted ACP failure.\"}"}} -{"type":"subagent/catalog","data":{"version":2,"childId":"{{id:2}}","childCreatedAt":1789820717542,"mode":"external","label":"Observe second ACP failure"}} -{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent {{id:2}} was stopped before it finished."},{"type":"text","text":"It left no closing message."},{"type":"text","text":"ACP unattended decision (policy: reject; request: execute; decision: denied)"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{id:2}} was stopped before it finished.","senderSessionId":"{{id:2}}"},"role":"user","id":"{{message:8}}"}]}} -{"type":"tool/result","data":{"turn":1,"step":2,"message":{"role":"tool","source":{"kind":"tool","callId":"call_acp_second"},"toolCallId":"call_acp_second","content":[{"type":"text","text":"started subagent {{id:2}}"}],"isError":false,"id":"{{message:9}}"}},"sourceEventSeqs":[23],"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent worker-1 was stopped before it finished."},{"type":"text","text":"It left no closing message."},{"type":"text","text":"ACP unattended decision (policy: reject; request: execute; decision: denied)"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 was stopped before it finished.","senderSessionId":"{{id:1}}"},"role":"user","id":"{{message:5}}"},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_acp_second","name":"subagent_acp","arguments":"{\"description\":\"Observe second ACP failure\",\"prompt\":\"Return the scripted ACP failure.\",\"name\":\"worker-2\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-pro"},"id":"{{message:7}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1792123795523,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792123795523,"index":0,"dt":[],"id":"call_acp_second","name":"subagent_acp","args":["{\"description\":\"Observe second ACP failure\",\"prompt\":\"Return the scripted ACP failure.\",\"name\":\"worker-2\"}"]},{"type":"chunk","time":1792123795523,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_acp_second","name":"subagent_acp","arguments":"{\"description\":\"Observe second ACP failure\",\"prompt\":\"Return the scripted ACP failure.\",\"name\":\"worker-2\"}"}}},{"type":"chunk","time":1792123795523,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1792123795523,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":2,"callId":"call_acp_second","name":"subagent_acp","arguments":"{\"description\":\"Observe second ACP failure\",\"prompt\":\"Return the scripted ACP failure.\",\"name\":\"worker-2\"}"}} +{"type":"subagent/catalog","data":{"version":2,"childId":"{{id:2}}","childCreatedAt":1792123795637,"mode":"external","label":"Observe second ACP failure"}} +{"type":"subagent/named","data":{"name":"worker-2","id":"{{id:2}}"}} +{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent worker-2 was stopped before it finished."},{"type":"text","text":"It left no closing message."},{"type":"text","text":"ACP unattended decision (policy: reject; request: execute; decision: denied)"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-2 was stopped before it finished.","senderSessionId":"{{id:2}}"},"role":"user","id":"{{message:8}}"}]}} +{"type":"tool/result","data":{"turn":1,"step":2,"message":{"role":"tool","source":{"kind":"tool","callId":"call_acp_second"},"toolCallId":"call_acp_second","content":[{"type":"text","text":"started subagent worker-2"}],"isError":false,"id":"{{message:9}}"}},"sourceEventSeqs":[24],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":2}} {"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":1,"step":3}} -{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent {{id:2}} was stopped before it finished."},{"type":"text","text":"It left no closing message."},{"type":"text","text":"ACP unattended decision (policy: reject; request: execute; decision: denied)"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{id:2}} was stopped before it finished.","senderSessionId":"{{id:2}}"},"role":"user","id":"{{message:8}}"},"surfaceOp":"append"} -{"type":"assistant/message","data":{"turn":1,"step":3,"message":{"role":"assistant","content":[{"type":"text","text":"PARENT_OBSERVED_ACP_DIAGNOSTIC"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-pro"},"id":"{{message:10}}"},"usage":{"inputTokens":10,"outputTokens":2},"stream":[{"type":"chunk","time":1789820717574,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1789820717574,"index":0,"dt":[],"texts":["PARENT_OBSERVED_ACP_DIAGNOSTIC"]},{"type":"chunk","time":1789820717574,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"PARENT_OBSERVED_ACP_DIAGNOSTIC"}}},{"type":"chunk","time":1789820717574,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":2}}},{"type":"chunk","time":1789820717574,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent worker-2 was stopped before it finished."},{"type":"text","text":"It left no closing message."},{"type":"text","text":"ACP unattended decision (policy: reject; request: execute; decision: denied)"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-2 was stopped before it finished.","senderSessionId":"{{id:2}}"},"role":"user","id":"{{message:8}}"},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":3,"message":{"role":"assistant","content":[{"type":"text","text":"PARENT_OBSERVED_ACP_DIAGNOSTIC"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-pro"},"id":"{{message:10}}"},"usage":{"inputTokens":10,"outputTokens":2},"stream":[{"type":"chunk","time":1792123795670,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1792123795670,"index":0,"dt":[],"texts":["PARENT_OBSERVED_ACP_DIAGNOSTIC"]},{"type":"chunk","time":1792123795670,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"PARENT_OBSERVED_ACP_DIAGNOSTIC"}}},{"type":"chunk","time":1792123795670,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":2}}},{"type":"chunk","time":1792123795670,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":3}} {"type":"turn/end","data":{"turn":1,"reason":{"kind":"completed"}}} diff --git a/snapshots/session/subagent-acp-diagnostic/tool-schemas.expected.json b/snapshots/session/subagent-acp-diagnostic/tool-schemas.expected.json index 93ff550d0f..0a1cde92c6 100644 --- a/snapshots/session/subagent-acp-diagnostic/tool-schemas.expected.json +++ b/snapshots/session/subagent-acp-diagnostic/tool-schemas.expected.json @@ -181,13 +181,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -245,7 +245,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -297,9 +297,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -307,7 +307,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -330,10 +330,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -348,6 +352,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -355,10 +360,14 @@ }, { "name": "subagent_acp", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The completion notice includes its final answer. This backend does not accept follow-up messages.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The completion notice includes its final answer. This backend does not accept follow-up messages.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -373,6 +382,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -380,10 +390,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -398,6 +412,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/session/subagent-agent-preset/session.1.v4.jsonl b/snapshots/session/subagent-agent-preset/session.1.v4.jsonl index e3849d3990..80a71bf2fd 100644 --- a/snapshots/session/subagent-agent-preset/session.1.v4.jsonl +++ b/snapshots/session/subagent-agent-preset/session.1.v4.jsonl @@ -4,12 +4,12 @@ {"type":"sandbox/mode","data":{"mode":"danger-full-access","source":"delegation"}} {"type":"approval/policy","data":{"policy":"never","source":"delegation"}} {"type":"permission/preset","data":{"preset":"danger-full-access"}} -{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Reply with exactly the word CHILD_OK and nothing else."},{"type":"text","text":"Your parent agent id is \"{{session:1}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{session:1}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:9}}"}]}} +{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Reply with exactly the word CHILD_OK and nothing else."},{"type":"text","text":"Your name is \"worker-1\". Your parent agent name is \"lead\". Before you finish, send your result to that agent with send_message({ name: \"lead\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:9}}"}]}} {"type":"turn/start","data":{"turn":1}} {"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":1,"step":1}} {"type":"system/message","data":{"turn":1,"step":1,"message":{"role":"system","content":[{"type":"text","text":"{{system}}"}],"source":{"kind":"system-prompt"},"id":"{{message:10}}"}},"surfaceOp":"append"} -{"type":"user/message","data":{"content":[{"type":"text","text":"Reply with exactly the word CHILD_OK and nothing else."},{"type":"text","text":"Your parent agent id is \"{{session:1}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{session:1}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:9}}"},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Reply with exactly the word CHILD_OK and nothing else."},{"type":"text","text":"Your name is \"worker-1\". Your parent agent name is \"lead\". Before you finish, send your result to that agent with send_message({ name: \"lead\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:9}}"},"surfaceOp":"append"} {"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations.\n\nApproval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).\n\nDelegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly.\n\nDelegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly.\n\nYou are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it.\n\nDelegation depth for `reviewer_delegate`: current 1, maximum 1, remaining levels 0. Do not call `reviewer_delegate` at this depth; carry out the work directly."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations."},{"name":"approval:policy","text":"Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."},{"name":"tool:subagent_fork:depth","text":"Delegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly."},{"name":"tool:subagent:depth","text":"Delegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly."},{"name":"subagent:delegation","text":"You are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."},{"name":"tool:reviewer_delegate:depth","text":"Delegation depth for `reviewer_delegate`: current 1, maximum 1, remaining levels 0. Do not call `reviewer_delegate` at this depth; carry out the work directly."}]},"role":"user","id":"{{message:11}}"},"surfaceOp":"append"} {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} diff --git a/snapshots/session/subagent-agent-preset/session.v4.jsonl b/snapshots/session/subagent-agent-preset/session.v4.jsonl index e5b3ff02d7..06fe6a9c81 100644 --- a/snapshots/session/subagent-agent-preset/session.v4.jsonl +++ b/snapshots/session/subagent-agent-preset/session.v4.jsonl @@ -13,20 +13,21 @@ {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} {"type":"session/title","data":{"title":"Use the subagent tool exactly","messageSeqs":[9],"source":{"kind":"fallback"}}} -{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"reasoning","text":"The user wants me to:\n1. Use the subagent tool exactly once to delegate the task: \"Reply with exactly the word CHILD_OK and nothing else.\"\n2. After the subagent returns, reply with the single word PARENT_DONE and stop.\n3. Do not use the bash tool.\n\nLet me do this."},{"type":"tool-call","id":"call_00_gVbLWC12Qu8JheZpVRRz8749","name":"subagent","arguments":"{\"description\":\"Reply with CHILD_OK\",\"prompt\":\"Reply with exactly the word CHILD_OK and nothing else.\",\"run_in_background\":false,\"agent_preset\":\"reviewer\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":2907,"outputTokens":142,"cacheReadTokens":0,"reasoningTokens":67},"stream":[{"type":"chunk","time":1790502918996,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1790502918997,"index":0,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0],"texts":["The"," user"," wants"," me"," to",":\n","1","."," Use"," the"," sub","agent"," tool"," exactly"," once"," to"," delegate"," the"," task",":"," \"","Reply"," with"," exactly"," the"," word"," CH","ILD","_OK"," and"," nothing"," else",".\"\n","2","."," After"," the"," sub","agent"," returns",","," reply"," with"," the"," single"," word"," PAR","ENT","_D","ONE"," and"," stop",".\n","3","."," Do"," not"," use"," the"," bash"," tool",".\n\n","Let"," me"," do"," this","."]},{"type":"chunk","time":1790502918998,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1790502918998,"index":1,"dt":[],"id":"call_00_gVbLWC12Qu8JheZpVRRz8749","name":"subagent","args":["{\"description\":\"Reply with CHILD_OK\",\"prompt\":\"Reply with exactly the word CHILD_OK and nothing else.\",\"run_in_background\":false,\"agent_preset\":\"reviewer\"}"]},{"type":"chunk","time":1790502918998,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The user wants me to:\n1. Use the subagent tool exactly once to delegate the task: \"Reply with exactly the word CHILD_OK and nothing else.\"\n2. After the subagent returns, reply with the single word PARENT_DONE and stop.\n3. Do not use the bash tool.\n\nLet me do this."}}},{"type":"chunk","time":1790502918998,"chunk":{"type":"block-end","index":1,"block":{"type":"tool-call","id":"call_00_gVbLWC12Qu8JheZpVRRz8749","name":"subagent","arguments":"{\"description\":\"Reply with CHILD_OK\",\"prompt\":\"Reply with exactly the word CHILD_OK and nothing else.\",\"run_in_background\":false,\"agent_preset\":\"reviewer\"}"}}},{"type":"chunk","time":1790502918998,"chunk":{"type":"usage","usage":{"inputTokens":2907,"outputTokens":142,"cacheReadTokens":0,"reasoningTokens":67}}},{"type":"chunk","time":1790502918998,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} -{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_00_gVbLWC12Qu8JheZpVRRz8749","name":"subagent","arguments":"{\"description\":\"Reply with CHILD_OK\",\"prompt\":\"Reply with exactly the word CHILD_OK and nothing else.\",\"run_in_background\":false,\"agent_preset\":\"reviewer\"}"}} -{"type":"subagent/catalog","data":{"version":0,"childId":"{{session:2}}","childCreatedAt":1790502919012,"mode":"continuable","label":"Reply with CHILD_OK"}} -{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_00_gVbLWC12Qu8JheZpVRRz8749"},"toolCallId":"call_00_gVbLWC12Qu8JheZpVRRz8749","content":[{"type":"text","text":"started subagent {{session:2}}"}],"isError":false,"id":"{{message:5}}"}},"sourceEventSeqs":[15],"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"reasoning","text":"The user wants me to:\n1. Use the subagent tool exactly once to delegate the task: \"Reply with exactly the word CHILD_OK and nothing else.\"\n2. After the subagent returns, reply with the single word PARENT_DONE and stop.\n3. Do not use the bash tool.\n\nLet me do this."},{"type":"tool-call","id":"call_00_gVbLWC12Qu8JheZpVRRz8749","name":"subagent","arguments":"{\"description\":\"Reply with CHILD_OK\",\"prompt\":\"Reply with exactly the word CHILD_OK and nothing else.\",\"run_in_background\":false,\"agent_preset\":\"reviewer\",\"name\":\"worker-1\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":2907,"outputTokens":142,"cacheReadTokens":0,"reasoningTokens":67},"stream":[{"type":"chunk","time":1792123796415,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1792123796415,"index":0,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"texts":["The"," user"," wants"," me"," to",":\n","1","."," Use"," the"," sub","agent"," tool"," exactly"," once"," to"," delegate"," the"," task",":"," \"","Reply"," with"," exactly"," the"," word"," CH","ILD","_OK"," and"," nothing"," else",".\"\n","2","."," After"," the"," sub","agent"," returns",","," reply"," with"," the"," single"," word"," PAR","ENT","_D","ONE"," and"," stop",".\n","3","."," Do"," not"," use"," the"," bash"," tool",".\n\n","Let"," me"," do"," this","."]},{"type":"chunk","time":1792123796416,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792123796416,"index":1,"dt":[],"id":"call_00_gVbLWC12Qu8JheZpVRRz8749","name":"subagent","args":["{\"description\":\"Reply with CHILD_OK\",\"prompt\":\"Reply with exactly the word CHILD_OK and nothing else.\",\"run_in_background\":false,\"agent_preset\":\"reviewer\",\"name\":\"worker-1\"}"]},{"type":"chunk","time":1792123796416,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The user wants me to:\n1. Use the subagent tool exactly once to delegate the task: \"Reply with exactly the word CHILD_OK and nothing else.\"\n2. After the subagent returns, reply with the single word PARENT_DONE and stop.\n3. Do not use the bash tool.\n\nLet me do this."}}},{"type":"chunk","time":1792123796416,"chunk":{"type":"block-end","index":1,"block":{"type":"tool-call","id":"call_00_gVbLWC12Qu8JheZpVRRz8749","name":"subagent","arguments":"{\"description\":\"Reply with CHILD_OK\",\"prompt\":\"Reply with exactly the word CHILD_OK and nothing else.\",\"run_in_background\":false,\"agent_preset\":\"reviewer\",\"name\":\"worker-1\"}"}}},{"type":"chunk","time":1792123796416,"chunk":{"type":"usage","usage":{"inputTokens":2907,"outputTokens":142,"cacheReadTokens":0,"reasoningTokens":67}}},{"type":"chunk","time":1792123796416,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_00_gVbLWC12Qu8JheZpVRRz8749","name":"subagent","arguments":"{\"description\":\"Reply with CHILD_OK\",\"prompt\":\"Reply with exactly the word CHILD_OK and nothing else.\",\"run_in_background\":false,\"agent_preset\":\"reviewer\",\"name\":\"worker-1\"}"}} +{"type":"subagent/catalog","data":{"version":0,"childId":"{{session:2}}","childCreatedAt":1792123796423,"mode":"continuable","label":"Reply with CHILD_OK"}} +{"type":"subagent/named","data":{"name":"worker-1","id":"{{session:2}}"}} +{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_00_gVbLWC12Qu8JheZpVRRz8749"},"toolCallId":"call_00_gVbLWC12Qu8JheZpVRRz8749","content":[{"type":"text","text":"started subagent worker-1"}],"isError":false,"id":"{{message:5}}"}},"sourceEventSeqs":[15],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":1}} {"type":"step/start","data":{"turn":1,"step":2}} -{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"reasoning","text":"The subagent returned \"CHILD_OK\" as expected. Now I need to reply with the single word \"PARENT_DONE\" and stop."},{"type":"text","text":"PARENT_DONE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:6}}"},"usage":{"inputTokens":120,"outputTokens":35,"cacheReadTokens":2944,"reasoningTokens":30},"stream":[{"type":"chunk","time":1790502919081,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1790502919081,"index":0,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"texts":["The"," sub","agent"," returned"," \"","CH","ILD","_OK","\""," as"," expected","."," Now"," I"," need"," to"," reply"," with"," the"," single"," word"," \"","PAR","ENT","_D","ONE","\""," and"," stop","."]},{"type":"chunk","time":1790502919082,"chunk":{"type":"block-start","index":1,"blockType":"text"}},{"type":"text-chunks","time0":1790502919082,"index":1,"dt":[0,0,0],"texts":["PAR","ENT","_D","ONE"]},{"type":"chunk","time":1790502919082,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The subagent returned \"CHILD_OK\" as expected. Now I need to reply with the single word \"PARENT_DONE\" and stop."}}},{"type":"chunk","time":1790502919082,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"PARENT_DONE"}}},{"type":"chunk","time":1790502919082,"chunk":{"type":"usage","usage":{"inputTokens":120,"outputTokens":35,"cacheReadTokens":2944,"reasoningTokens":30}}},{"type":"chunk","time":1790502919082,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"reasoning","text":"The subagent returned \"CHILD_OK\" as expected. Now I need to reply with the single word \"PARENT_DONE\" and stop."},{"type":"text","text":"PARENT_DONE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:6}}"},"usage":{"inputTokens":120,"outputTokens":35,"cacheReadTokens":2944,"reasoningTokens":30},"stream":[{"type":"chunk","time":1792123796459,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1792123796460,"index":0,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"texts":["The"," sub","agent"," returned"," \"","CH","ILD","_OK","\""," as"," expected","."," Now"," I"," need"," to"," reply"," with"," the"," single"," word"," \"","PAR","ENT","_D","ONE","\""," and"," stop","."]},{"type":"chunk","time":1792123796460,"chunk":{"type":"block-start","index":1,"blockType":"text"}},{"type":"text-chunks","time0":1792123796460,"index":1,"dt":[0,0,0],"texts":["PAR","ENT","_D","ONE"]},{"type":"chunk","time":1792123796460,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The subagent returned \"CHILD_OK\" as expected. Now I need to reply with the single word \"PARENT_DONE\" and stop."}}},{"type":"chunk","time":1792123796460,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"PARENT_DONE"}}},{"type":"chunk","time":1792123796460,"chunk":{"type":"usage","usage":{"inputTokens":120,"outputTokens":35,"cacheReadTokens":2944,"reasoningTokens":30}}},{"type":"chunk","time":1792123796460,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":2}} {"type":"turn/end","data":{"turn":1,"reason":{"kind":"completed"}}} -{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent {{session:2}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"CHILD_OK"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{session:2}} finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:7}}"}]}} +{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent worker-1 finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"CHILD_OK"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:7}}"}]}} {"type":"turn/start","data":{"turn":2}} {"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":2,"step":1}} -{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent {{session:2}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"CHILD_OK"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{session:2}} finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:7}}"},"surfaceOp":"append"} -{"type":"assistant/message","data":{"turn":2,"step":1,"message":{"role":"assistant","content":[{"type":"text","text":"PARENT_DONE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:8}}"},"usage":{"inputTokens":10,"outputTokens":4},"stream":[{"type":"chunk","time":1790502919186,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1790502919186,"index":0,"dt":[],"texts":["PARENT_DONE"]},{"type":"chunk","time":1790502919186,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"PARENT_DONE"}}},{"type":"chunk","time":1790502919186,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":4}}},{"type":"chunk","time":1790502919186,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent worker-1 finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"CHILD_OK"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:7}}"},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":2,"step":1,"message":{"role":"assistant","content":[{"type":"text","text":"PARENT_DONE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:8}}"},"usage":{"inputTokens":10,"outputTokens":4},"stream":[{"type":"chunk","time":1792123796485,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1792123796485,"index":0,"dt":[],"texts":["PARENT_DONE"]},{"type":"chunk","time":1792123796485,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"PARENT_DONE"}}},{"type":"chunk","time":1792123796485,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":4}}},{"type":"chunk","time":1792123796485,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":2,"step":1}} {"type":"turn/end","data":{"turn":2,"reason":{"kind":"completed"}}} diff --git a/snapshots/session/subagent-agent-preset/tool-schemas.1.expected.json b/snapshots/session/subagent-agent-preset/tool-schemas.1.expected.json index 65f758f5e2..44d498209e 100644 --- a/snapshots/session/subagent-agent-preset/tool-schemas.1.expected.json +++ b/snapshots/session/subagent-agent-preset/tool-schemas.1.expected.json @@ -181,13 +181,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -245,7 +245,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -293,10 +293,14 @@ }, { "name": "reviewer_delegate", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -311,6 +315,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -322,9 +327,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -332,7 +337,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -355,10 +360,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -380,6 +389,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -387,10 +397,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -405,6 +419,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/session/subagent-agent-preset/tool-schemas.expected.json b/snapshots/session/subagent-agent-preset/tool-schemas.expected.json index b973227972..97e5b75647 100644 --- a/snapshots/session/subagent-agent-preset/tool-schemas.expected.json +++ b/snapshots/session/subagent-agent-preset/tool-schemas.expected.json @@ -181,13 +181,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -245,7 +245,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -297,9 +297,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -307,7 +307,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -330,10 +330,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -355,6 +359,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -362,10 +367,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -380,6 +389,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/session/subagent-child-question-rejection/session.1.v4.jsonl b/snapshots/session/subagent-child-question-rejection/session.1.v4.jsonl index bce0ae2168..f0888ecb76 100644 --- a/snapshots/session/subagent-child-question-rejection/session.1.v4.jsonl +++ b/snapshots/session/subagent-child-question-rejection/session.1.v4.jsonl @@ -3,12 +3,12 @@ {"type":"sandbox/mode","data":{"mode":"danger-full-access","source":"delegation"}} {"type":"approval/policy","data":{"policy":"never","source":"delegation"}} {"type":"permission/preset","data":{"preset":"danger-full-access"}} -{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Call ask_user_question once to ask whether deployment should use the CUDA fallback. If the tool returns an error, include the unresolved question verbatim in your final result."},{"type":"text","text":"Your parent agent id is \"{{session:1}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{session:1}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:9}}"}]}} +{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Call ask_user_question once to ask whether deployment should use the CUDA fallback. If the tool returns an error, include the unresolved question verbatim in your final result."},{"type":"text","text":"Your name is \"worker-1\". Your parent agent name is \"lead\". Before you finish, send your result to that agent with send_message({ name: \"lead\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:9}}"}]}} {"type":"turn/start","data":{"turn":1}} {"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":1,"step":1}} {"type":"system/message","data":{"turn":1,"step":1,"message":{"role":"system","content":[{"type":"text","text":"{{system}}"}],"source":{"kind":"system-prompt"},"id":"{{message:10}}"}},"surfaceOp":"append"} -{"type":"user/message","data":{"content":[{"type":"text","text":"Call ask_user_question once to ask whether deployment should use the CUDA fallback. If the tool returns an error, include the unresolved question verbatim in your final result."},{"type":"text","text":"Your parent agent id is \"{{session:1}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{session:1}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:9}}"},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Call ask_user_question once to ask whether deployment should use the CUDA fallback. If the tool returns an error, include the unresolved question verbatim in your final result."},{"type":"text","text":"Your name is \"worker-1\". Your parent agent name is \"lead\". Before you finish, send your result to that agent with send_message({ name: \"lead\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:9}}"},"surfaceOp":"append"} {"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations.\n\nApproval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).\n\nDelegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly.\n\nDelegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly.\n\nYou are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations."},{"name":"approval:policy","text":"Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."},{"name":"tool:subagent:depth","text":"Delegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly."},{"name":"tool:subagent_fork:depth","text":"Delegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly."},{"name":"subagent:delegation","text":"You are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}]},"role":"user","id":"{{message:11}}"},"surfaceOp":"append"} {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} diff --git a/snapshots/session/subagent-child-question-rejection/session.v4.jsonl b/snapshots/session/subagent-child-question-rejection/session.v4.jsonl index 8a7528ce39..493dae149e 100644 --- a/snapshots/session/subagent-child-question-rejection/session.v4.jsonl +++ b/snapshots/session/subagent-child-question-rejection/session.v4.jsonl @@ -12,20 +12,21 @@ {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} {"type":"session/title","data":{"title":"Delegate one question check. Ask","messageSeqs":[8],"source":{"kind":"fallback"}}} -{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_question_child","name":"subagent","arguments":"{\"description\":\"Check deployment question\",\"prompt\":\"Call ask_user_question once to ask whether deployment should use the CUDA fallback. If the tool returns an error, include the unresolved question verbatim in your final result.\", \"run_in_background\":false}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1789625677664,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1789625677664,"index":0,"dt":[],"id":"call_question_child","name":"subagent","args":["{\"description\":\"Check deployment question\",\"prompt\":\"Call ask_user_question once to ask whether deployment should use the CUDA fallback. If the tool returns an error, include the unresolved question verbatim in your final result.\", \"run_in_background\":false}"]},{"type":"chunk","time":1789625677664,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_question_child","name":"subagent","arguments":"{\"description\":\"Check deployment question\",\"prompt\":\"Call ask_user_question once to ask whether deployment should use the CUDA fallback. If the tool returns an error, include the unresolved question verbatim in your final result.\", \"run_in_background\":false}"}}},{"type":"chunk","time":1789625677665,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1789625677665,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} -{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_question_child","name":"subagent","arguments":"{\"description\":\"Check deployment question\",\"prompt\":\"Call ask_user_question once to ask whether deployment should use the CUDA fallback. If the tool returns an error, include the unresolved question verbatim in your final result.\", \"run_in_background\":false}"}} -{"type":"subagent/catalog","data":{"version":0,"childId":"{{session:2}}","childCreatedAt":1789625677671,"mode":"continuable","label":"Check deployment question"}} -{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_question_child"},"toolCallId":"call_question_child","content":[{"type":"text","text":"started subagent {{session:2}}"}],"isError":false,"id":"{{message:5}}"}},"sourceEventSeqs":[14],"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_question_child","name":"subagent","arguments":"{\"description\":\"Check deployment question\",\"prompt\":\"Call ask_user_question once to ask whether deployment should use the CUDA fallback. If the tool returns an error, include the unresolved question verbatim in your final result.\",\"run_in_background\":false,\"name\":\"worker-1\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1792123797269,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792123797269,"index":0,"dt":[],"id":"call_question_child","name":"subagent","args":["{\"description\":\"Check deployment question\",\"prompt\":\"Call ask_user_question once to ask whether deployment should use the CUDA fallback. If the tool returns an error, include the unresolved question verbatim in your final result.\",\"run_in_background\":false,\"name\":\"worker-1\"}"]},{"type":"chunk","time":1792123797269,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_question_child","name":"subagent","arguments":"{\"description\":\"Check deployment question\",\"prompt\":\"Call ask_user_question once to ask whether deployment should use the CUDA fallback. If the tool returns an error, include the unresolved question verbatim in your final result.\",\"run_in_background\":false,\"name\":\"worker-1\"}"}}},{"type":"chunk","time":1792123797269,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1792123797269,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_question_child","name":"subagent","arguments":"{\"description\":\"Check deployment question\",\"prompt\":\"Call ask_user_question once to ask whether deployment should use the CUDA fallback. If the tool returns an error, include the unresolved question verbatim in your final result.\",\"run_in_background\":false,\"name\":\"worker-1\"}"}} +{"type":"subagent/catalog","data":{"version":0,"childId":"{{session:2}}","childCreatedAt":1792123797276,"mode":"continuable","label":"Check deployment question"}} +{"type":"subagent/named","data":{"name":"worker-1","id":"{{session:2}}"}} +{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_question_child"},"toolCallId":"call_question_child","content":[{"type":"text","text":"started subagent worker-1"}],"isError":false,"id":"{{message:5}}"}},"sourceEventSeqs":[14],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":1}} {"type":"step/start","data":{"turn":1,"step":2}} -{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"text","text":"PARENT_COMPLETED"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:6}}"},"usage":{"inputTokens":10,"outputTokens":2},"stream":[{"type":"chunk","time":1789625677718,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1789625677719,"index":0,"dt":[],"texts":["PARENT_COMPLETED"]},{"type":"chunk","time":1789625677719,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"PARENT_COMPLETED"}}},{"type":"chunk","time":1789625677719,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":2}}},{"type":"chunk","time":1789625677719,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"text","text":"PARENT_COMPLETED"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:6}}"},"usage":{"inputTokens":10,"outputTokens":2},"stream":[{"type":"chunk","time":1792123797314,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1792123797314,"index":0,"dt":[],"texts":["PARENT_COMPLETED"]},{"type":"chunk","time":1792123797314,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"PARENT_COMPLETED"}}},{"type":"chunk","time":1792123797314,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":2}}},{"type":"chunk","time":1792123797314,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":2}} {"type":"turn/end","data":{"turn":1,"reason":{"kind":"completed"}}} -{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent {{session:2}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"UNRESOLVED: Should deployment use the CUDA fallback?"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{session:2}} finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:7}}"}]}} +{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent worker-1 finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"UNRESOLVED: Should deployment use the CUDA fallback?"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:7}}"}]}} {"type":"turn/start","data":{"turn":2}} {"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":2,"step":1}} -{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent {{session:2}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"UNRESOLVED: Should deployment use the CUDA fallback?"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{session:2}} finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:7}}"},"surfaceOp":"append"} -{"type":"assistant/message","data":{"turn":2,"step":1,"message":{"role":"assistant","content":[{"type":"text","text":"PARENT_COMPLETED"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:8}}"},"usage":{"inputTokens":10,"outputTokens":4},"stream":[{"type":"chunk","time":1789625677771,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1789625677771,"index":0,"dt":[],"texts":["PARENT_COMPLETED"]},{"type":"chunk","time":1789625677771,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"PARENT_COMPLETED"}}},{"type":"chunk","time":1789625677771,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":4}}},{"type":"chunk","time":1789625677771,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent worker-1 finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"UNRESOLVED: Should deployment use the CUDA fallback?"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:7}}"},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":2,"step":1,"message":{"role":"assistant","content":[{"type":"text","text":"PARENT_COMPLETED"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:8}}"},"usage":{"inputTokens":10,"outputTokens":4},"stream":[{"type":"chunk","time":1792123797360,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1792123797360,"index":0,"dt":[],"texts":["PARENT_COMPLETED"]},{"type":"chunk","time":1792123797360,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"PARENT_COMPLETED"}}},{"type":"chunk","time":1792123797360,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":4}}},{"type":"chunk","time":1792123797360,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":2,"step":1}} {"type":"turn/end","data":{"turn":2,"reason":{"kind":"completed"}}} diff --git a/snapshots/session/subagent-child-question-rejection/tool-schemas.expected.json b/snapshots/session/subagent-child-question-rejection/tool-schemas.expected.json index 2fd4909bf1..4a34d7de16 100644 --- a/snapshots/session/subagent-child-question-rejection/tool-schemas.expected.json +++ b/snapshots/session/subagent-child-question-rejection/tool-schemas.expected.json @@ -244,13 +244,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -308,7 +308,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -360,9 +360,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -370,7 +370,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -393,10 +393,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -411,6 +415,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -418,10 +423,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -436,6 +445,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/session/subagent-depth-context-disabled/session.v4.jsonl b/snapshots/session/subagent-depth-context-disabled/session.v4.jsonl index c4830eb1db..26d3b51029 100644 --- a/snapshots/session/subagent-depth-context-disabled/session.v4.jsonl +++ b/snapshots/session/subagent-depth-context-disabled/session.v4.jsonl @@ -12,8 +12,8 @@ {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} {"type":"session/title","data":{"title":"Attempt one subagent call beyond","messageSeqs":[8],"source":{"kind":"fallback"}}} -{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_depth_one_rejected","name":"subagent","arguments":"{\"description\":\"Exceed depth cap\",\"prompt\":\"This child must never start.\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1789625678968,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1789625678968,"index":0,"dt":[],"id":"call_depth_one_rejected","name":"subagent","args":["{\"description\":\"Exceed depth cap\",\"prompt\":\"This child must never start.\"}"]},{"type":"chunk","time":1789625678968,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_depth_one_rejected","name":"subagent","arguments":"{\"description\":\"Exceed depth cap\",\"prompt\":\"This child must never start.\"}"}}},{"type":"chunk","time":1789625678968,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1789625678968,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} -{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_depth_one_rejected","name":"subagent","arguments":"{\"description\":\"Exceed depth cap\",\"prompt\":\"This child must never start.\"}"}} +{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_depth_one_rejected","name":"subagent","arguments":"{\"description\":\"Exceed depth cap\",\"prompt\":\"This child must never start.\",\"name\":\"worker-1\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1789625678968,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1789625678968,"index":0,"dt":[],"id":"call_depth_one_rejected","name":"subagent","args":["{\"description\":\"Exceed depth cap\",\"prompt\":\"This child must never start.\",\"name\":\"worker-1\"}"]},{"type":"chunk","time":1789625678968,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_depth_one_rejected","name":"subagent","arguments":"{\"description\":\"Exceed depth cap\",\"prompt\":\"This child must never start.\",\"name\":\"worker-1\"}"}}},{"type":"chunk","time":1789625678968,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1789625678968,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_depth_one_rejected","name":"subagent","arguments":"{\"description\":\"Exceed depth cap\",\"prompt\":\"This child must never start.\",\"name\":\"worker-1\"}"}} {"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_depth_one_rejected"},"toolCallId":"call_depth_one_rejected","content":[{"type":"text","text":"Error: subagent depth 1 exceeds maxDepth 0"}],"isError":true,"id":"{{message:5}}"}},"sourceEventSeqs":[14],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":1}} {"type":"step/start","data":{"turn":1,"step":2}} diff --git a/snapshots/session/subagent-depth-two-rejection/replay.override.json b/snapshots/session/subagent-depth-two-rejection/replay.override.json index b77d4786de..30fe4bbf30 100644 --- a/snapshots/session/subagent-depth-two-rejection/replay.override.json +++ b/snapshots/session/subagent-depth-two-rejection/replay.override.json @@ -12,7 +12,7 @@ "index": 0, "id": "call_root_child", "name": "subagent", - "argumentsDelta": "{\"description\":\"Start depth one\",\"prompt\":\"Call subagent once. Ask that child to attempt one further subagent call, then report the result.\"}" + "argumentsDelta": "{\"description\":\"Start depth one\",\"prompt\":\"Call subagent once. Ask that child to attempt one further subagent call, then report the result.\",\"name\":\"worker-1\"}" }, { "type": "block-end", @@ -21,7 +21,7 @@ "type": "tool-call", "id": "call_root_child", "name": "subagent", - "arguments": "{\"description\":\"Start depth one\",\"prompt\":\"Call subagent once. Ask that child to attempt one further subagent call, then report the result.\"}" + "arguments": "{\"description\":\"Start depth one\",\"prompt\":\"Call subagent once. Ask that child to attempt one further subagent call, then report the result.\",\"name\":\"worker-1\"}" } }, { diff --git a/snapshots/session/subagent-depth-two-rejection/session.1.v4.jsonl b/snapshots/session/subagent-depth-two-rejection/session.1.v4.jsonl index c660da747b..7fd83e68c4 100644 --- a/snapshots/session/subagent-depth-two-rejection/session.1.v4.jsonl +++ b/snapshots/session/subagent-depth-two-rejection/session.1.v4.jsonl @@ -3,30 +3,30 @@ {"type":"sandbox/mode","data":{"mode":"danger-full-access","source":"delegation"}} {"type":"approval/policy","data":{"policy":"never","source":"delegation"}} {"type":"permission/preset","data":{"preset":"danger-full-access"}} -{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Call subagent once. Ask that child to attempt one further subagent call, then report the result."},{"type":"text","text":"Your parent agent id is \"{{session:1}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{session:1}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:9}}"}]}} +{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Call subagent once. Ask that child to attempt one further subagent call, then report the result."},{"type":"text","text":"Your name is \"worker-1\". Your parent agent name is \"lead\". Before you finish, send your result to that agent with send_message({ name: \"lead\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:9}}"}]}} {"type":"turn/start","data":{"turn":1}} {"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":1,"step":1}} {"type":"system/message","data":{"turn":1,"step":1,"message":{"role":"system","content":[{"type":"text","text":"{{system}}"}],"source":{"kind":"system-prompt"},"id":"{{message:10}}"}},"surfaceOp":"append"} -{"type":"user/message","data":{"content":[{"type":"text","text":"Call subagent once. Ask that child to attempt one further subagent call, then report the result."},{"type":"text","text":"Your parent agent id is \"{{session:1}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{session:1}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:9}}"},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Call subagent once. Ask that child to attempt one further subagent call, then report the result."},{"type":"text","text":"Your name is \"worker-1\". Your parent agent name is \"lead\". Before you finish, send your result to that agent with send_message({ name: \"lead\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:9}}"},"surfaceOp":"append"} {"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations.\n\nApproval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).\n\nDelegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly.\n\nYou are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations."},{"name":"approval:policy","text":"Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."},{"name":"tool:subagent_fork:depth","text":"Delegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly."},{"name":"subagent:delegation","text":"You are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}]},"role":"user","id":"{{message:11}}"},"surfaceOp":"append"} {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} {"type":"session/title","data":{"title":"Call subagent once. Ask that","messageSeqs":[9],"source":{"kind":"fallback"}}} -{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_depth_one_child","name":"subagent","arguments":"{\"description\":\"Start depth two\",\"prompt\":\"Attempt one subagent call beyond the configured cap, then report the rejection.\",\"run_in_background\":false}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:12}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1789625678920,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1789625678920,"index":0,"dt":[],"id":"call_depth_one_child","name":"subagent","args":["{\"description\":\"Start depth two\",\"prompt\":\"Attempt one subagent call beyond the configured cap, then report the rejection.\",\"run_in_background\":false}"]},{"type":"chunk","time":1789625678920,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_depth_one_child","name":"subagent","arguments":"{\"description\":\"Start depth two\",\"prompt\":\"Attempt one subagent call beyond the configured cap, then report the rejection.\",\"run_in_background\":false}"}}},{"type":"chunk","time":1789625678920,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1789625678920,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} -{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_depth_one_child","name":"subagent","arguments":"{\"description\":\"Start depth two\",\"prompt\":\"Attempt one subagent call beyond the configured cap, then report the rejection.\",\"run_in_background\":false}"}} +{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_depth_one_child","name":"subagent","arguments":"{\"description\":\"Start depth two\",\"prompt\":\"Attempt one subagent call beyond the configured cap, then report the rejection.\",\"run_in_background\":false,\"name\":\"worker-2\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:12}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1789625678920,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1789625678920,"index":0,"dt":[],"id":"call_depth_one_child","name":"subagent","args":["{\"description\":\"Start depth two\",\"prompt\":\"Attempt one subagent call beyond the configured cap, then report the rejection.\",\"run_in_background\":false,\"name\":\"worker-2\"}"]},{"type":"chunk","time":1789625678920,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_depth_one_child","name":"subagent","arguments":"{\"description\":\"Start depth two\",\"prompt\":\"Attempt one subagent call beyond the configured cap, then report the rejection.\",\"run_in_background\":false,\"name\":\"worker-2\"}"}}},{"type":"chunk","time":1789625678920,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1789625678920,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_depth_one_child","name":"subagent","arguments":"{\"description\":\"Start depth two\",\"prompt\":\"Attempt one subagent call beyond the configured cap, then report the rejection.\",\"run_in_background\":false,\"name\":\"worker-2\"}"}} {"type":"subagent/catalog","data":{"version":0,"childId":"{{session:3}}","childCreatedAt":1789625678926,"mode":"continuable","label":"Start depth two"}} -{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_depth_one_child"},"toolCallId":"call_depth_one_child","content":[{"type":"text","text":"started subagent {{session:3}}"}],"isError":false,"id":"{{message:13}}"}},"sourceEventSeqs":[15],"surfaceOp":"append"} +{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_depth_one_child"},"toolCallId":"call_depth_one_child","content":[{"type":"text","text":"started subagent worker-2"}],"isError":false,"id":"{{message:13}}"}},"sourceEventSeqs":[15],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":1}} {"type":"step/start","data":{"turn":1,"step":2}} {"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"text","text":"DEPTH_ONE_DONE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:14}}"},"usage":{"inputTokens":10,"outputTokens":2},"stream":[{"type":"chunk","time":1789625678959,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1789625678959,"index":0,"dt":[],"texts":["DEPTH_ONE_DONE"]},{"type":"chunk","time":1789625678959,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"DEPTH_ONE_DONE"}}},{"type":"chunk","time":1789625678959,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":2}}},{"type":"chunk","time":1789625678959,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":2}} {"type":"turn/end","data":{"turn":1,"reason":{"kind":"completed"}}} -{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent {{session:3}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"DEPTH_REJECTED"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{session:3}} finished and will do no further work unless you send it more.","senderSessionId":"{{session:3}}"},"role":"user","id":"{{message:15}}"}]}} +{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent worker-2 finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"DEPTH_REJECTED"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-2 finished and will do no further work unless you send it more.","senderSessionId":"{{session:3}}"},"role":"user","id":"{{message:15}}"}]}} {"type":"turn/start","data":{"turn":2}} {"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":2,"step":1}} -{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent {{session:3}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"DEPTH_REJECTED"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{session:3}} finished and will do no further work unless you send it more.","senderSessionId":"{{session:3}}"},"role":"user","id":"{{message:15}}"},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent worker-2 finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"DEPTH_REJECTED"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-2 finished and will do no further work unless you send it more.","senderSessionId":"{{session:3}}"},"role":"user","id":"{{message:15}}"},"surfaceOp":"append"} {"type":"assistant/attempt","data":{"turn":2,"step":1,"stream":[{"type":"chunk","time":1789625679010,"chunk":{"type":"finish","reason":{"kind":"error","failure":{"message":"llm-replay: script exhausted — session requested model call #3 but its script has only 2; re-record the scenario","code":"UNKNOWN"}}}}]}} {"type":"step/end","data":{"turn":2,"step":1}} {"type":"turn/end","data":{"turn":2,"reason":{"kind":"error","error":{"message":"llm-replay: script exhausted — session requested model call #3 but its script has only 2; re-record the scenario","code":"UNKNOWN"}}}} diff --git a/snapshots/session/subagent-depth-two-rejection/session.2.v4.jsonl b/snapshots/session/subagent-depth-two-rejection/session.2.v4.jsonl index 8e9c8a027d..eea3738b28 100644 --- a/snapshots/session/subagent-depth-two-rejection/session.2.v4.jsonl +++ b/snapshots/session/subagent-depth-two-rejection/session.2.v4.jsonl @@ -3,18 +3,18 @@ {"type":"sandbox/mode","data":{"mode":"danger-full-access","source":"delegation"}} {"type":"approval/policy","data":{"policy":"never","source":"delegation"}} {"type":"permission/preset","data":{"preset":"danger-full-access"}} -{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Attempt one subagent call beyond the configured cap, then report the rejection."},{"type":"text","text":"Your parent agent id is \"{{session:2}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{session:2}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:16}}"}]}} +{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Attempt one subagent call beyond the configured cap, then report the rejection."},{"type":"text","text":"Your name is \"worker-2\". Your parent agent name is \"worker-1\". Before you finish, send your result to that agent with send_message({ name: \"worker-1\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:16}}"}]}} {"type":"turn/start","data":{"turn":1}} {"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":1,"step":1}} {"type":"system/message","data":{"turn":1,"step":1,"message":{"role":"system","content":[{"type":"text","text":"{{system}}"}],"source":{"kind":"system-prompt"},"id":"{{message:17}}"}},"surfaceOp":"append"} -{"type":"user/message","data":{"content":[{"type":"text","text":"Attempt one subagent call beyond the configured cap, then report the rejection."},{"type":"text","text":"Your parent agent id is \"{{session:2}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{session:2}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:16}}"},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Attempt one subagent call beyond the configured cap, then report the rejection."},{"type":"text","text":"Your name is \"worker-2\". Your parent agent name is \"worker-1\". Before you finish, send your result to that agent with send_message({ name: \"worker-1\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:16}}"},"surfaceOp":"append"} {"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations.\n\nApproval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).\n\nDelegation depth for `subagent`: current 2, maximum 2, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly.\n\nDelegation depth for `subagent_fork`: current 2, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly.\n\nYou are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations."},{"name":"approval:policy","text":"Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."},{"name":"tool:subagent:depth","text":"Delegation depth for `subagent`: current 2, maximum 2, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly."},{"name":"tool:subagent_fork:depth","text":"Delegation depth for `subagent_fork`: current 2, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly."},{"name":"subagent:delegation","text":"You are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}]},"role":"user","id":"{{message:18}}"},"surfaceOp":"append"} {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} {"type":"session/title","data":{"title":"Attempt one subagent call beyond","messageSeqs":[9],"source":{"kind":"fallback"}}} -{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_depth_three_rejected","name":"subagent","arguments":"{\"description\":\"Exceed depth cap\",\"prompt\":\"This child must never start.\",\"run_in_background\":false}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:19}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1789625678968,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1789625678968,"index":0,"dt":[],"id":"call_depth_three_rejected","name":"subagent","args":["{\"description\":\"Exceed depth cap\",\"prompt\":\"This child must never start.\",\"run_in_background\":false}"]},{"type":"chunk","time":1789625678968,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_depth_three_rejected","name":"subagent","arguments":"{\"description\":\"Exceed depth cap\",\"prompt\":\"This child must never start.\",\"run_in_background\":false}"}}},{"type":"chunk","time":1789625678968,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1789625678968,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} -{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_depth_three_rejected","name":"subagent","arguments":"{\"description\":\"Exceed depth cap\",\"prompt\":\"This child must never start.\",\"run_in_background\":false}"}} +{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_depth_three_rejected","name":"subagent","arguments":"{\"description\":\"Exceed depth cap\",\"prompt\":\"This child must never start.\",\"run_in_background\":false,\"name\":\"worker-3\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:19}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1789625678968,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1789625678968,"index":0,"dt":[],"id":"call_depth_three_rejected","name":"subagent","args":["{\"description\":\"Exceed depth cap\",\"prompt\":\"This child must never start.\",\"run_in_background\":false,\"name\":\"worker-3\"}"]},{"type":"chunk","time":1789625678968,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_depth_three_rejected","name":"subagent","arguments":"{\"description\":\"Exceed depth cap\",\"prompt\":\"This child must never start.\",\"run_in_background\":false,\"name\":\"worker-3\"}"}}},{"type":"chunk","time":1789625678968,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1789625678968,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_depth_three_rejected","name":"subagent","arguments":"{\"description\":\"Exceed depth cap\",\"prompt\":\"This child must never start.\",\"run_in_background\":false,\"name\":\"worker-3\"}"}} {"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_depth_three_rejected"},"toolCallId":"call_depth_three_rejected","content":[{"type":"text","text":"Error: subagent depth 3 exceeds maxDepth 2"}],"isError":true,"id":"{{message:20}}"}},"sourceEventSeqs":[15],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":1}} {"type":"step/start","data":{"turn":1,"step":2}} diff --git a/snapshots/session/subagent-depth-two-rejection/session.v4.jsonl b/snapshots/session/subagent-depth-two-rejection/session.v4.jsonl index 52b59f8585..00f6748b9b 100644 --- a/snapshots/session/subagent-depth-two-rejection/session.v4.jsonl +++ b/snapshots/session/subagent-depth-two-rejection/session.v4.jsonl @@ -12,20 +12,22 @@ {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} {"type":"session/title","data":{"title":"Delegate through two child generations.","messageSeqs":[8],"source":{"kind":"fallback"}}} -{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_root_child","name":"subagent","arguments":"{\"description\":\"Start depth one\",\"prompt\":\"Call subagent once. Ask that child to attempt one further subagent call, then report the result.\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1789625678872,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1789625678872,"index":0,"dt":[],"id":"call_root_child","name":"subagent","args":["{\"description\":\"Start depth one\",\"prompt\":\"Call subagent once. Ask that child to attempt one further subagent call, then report the result.\"}"]},{"type":"chunk","time":1789625678872,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_root_child","name":"subagent","arguments":"{\"description\":\"Start depth one\",\"prompt\":\"Call subagent once. Ask that child to attempt one further subagent call, then report the result.\"}"}}},{"type":"chunk","time":1789625678872,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1789625678872,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} -{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_root_child","name":"subagent","arguments":"{\"description\":\"Start depth one\",\"prompt\":\"Call subagent once. Ask that child to attempt one further subagent call, then report the result.\"}"}} -{"type":"subagent/catalog","data":{"version":0,"childId":"{{session:2}}","childCreatedAt":1789625678879,"mode":"continuable","label":"Start depth one"}} -{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_root_child"},"toolCallId":"call_root_child","content":[{"type":"text","text":"started subagent {{session:2}}"}],"isError":false,"id":"{{message:5}}"}},"sourceEventSeqs":[14],"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_root_child","name":"subagent","arguments":"{\"description\":\"Start depth one\",\"prompt\":\"Call subagent once. Ask that child to attempt one further subagent call, then report the result.\",\"name\":\"worker-1\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1792123798869,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792123798869,"index":0,"dt":[],"id":"call_root_child","name":"subagent","args":["{\"description\":\"Start depth one\",\"prompt\":\"Call subagent once. Ask that child to attempt one further subagent call, then report the result.\",\"name\":\"worker-1\"}"]},{"type":"chunk","time":1792123798869,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_root_child","name":"subagent","arguments":"{\"description\":\"Start depth one\",\"prompt\":\"Call subagent once. Ask that child to attempt one further subagent call, then report the result.\",\"name\":\"worker-1\"}"}}},{"type":"chunk","time":1792123798869,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1792123798869,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_root_child","name":"subagent","arguments":"{\"description\":\"Start depth one\",\"prompt\":\"Call subagent once. Ask that child to attempt one further subagent call, then report the result.\",\"name\":\"worker-1\"}"}} +{"type":"subagent/catalog","data":{"version":0,"childId":"{{session:2}}","childCreatedAt":1792123798877,"mode":"continuable","label":"Start depth one"}} +{"type":"subagent/named","data":{"name":"worker-1","id":"{{session:2}}"}} +{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_root_child"},"toolCallId":"call_root_child","content":[{"type":"text","text":"started subagent worker-1"}],"isError":false,"id":"{{message:5}}"}},"sourceEventSeqs":[14],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":1}} {"type":"step/start","data":{"turn":1,"step":2}} -{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"text","text":"ROOT_DONE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:6}}"},"usage":{"inputTokens":10,"outputTokens":2},"stream":[{"type":"chunk","time":1789625678917,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1789625678917,"index":0,"dt":[],"texts":["ROOT_DONE"]},{"type":"chunk","time":1789625678917,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"ROOT_DONE"}}},{"type":"chunk","time":1789625678917,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":2}}},{"type":"chunk","time":1789625678917,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"text","text":"ROOT_DONE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:6}}"},"usage":{"inputTokens":10,"outputTokens":2},"stream":[{"type":"chunk","time":1792123798916,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1792123798916,"index":0,"dt":[],"texts":["ROOT_DONE"]},{"type":"chunk","time":1792123798916,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"ROOT_DONE"}}},{"type":"chunk","time":1792123798916,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":2}}},{"type":"chunk","time":1792123798916,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":2}} {"type":"turn/end","data":{"turn":1,"reason":{"kind":"completed"}}} -{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent {{session:2}} failed before it finished."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"DEPTH_ONE_DONE"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{session:2}} failed before it finished.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:7}}"}]}} +{"type":"subagent/named","data":{"name":"worker-2","id":"{{session:3}}"}} +{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent worker-1 failed before it finished."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"DEPTH_ONE_DONE"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 failed before it finished.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:7}}"}]}} {"type":"turn/start","data":{"turn":2}} {"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":2,"step":1}} -{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent {{session:2}} failed before it finished."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"DEPTH_ONE_DONE"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{session:2}} failed before it finished.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:7}}"},"surfaceOp":"append"} -{"type":"assistant/message","data":{"turn":2,"step":1,"message":{"role":"assistant","content":[{"type":"text","text":"ROOT_DONE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:8}}"},"usage":{"inputTokens":10,"outputTokens":4},"stream":[{"type":"chunk","time":1789625679032,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1789625679032,"index":0,"dt":[],"texts":["ROOT_DONE"]},{"type":"chunk","time":1789625679032,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"ROOT_DONE"}}},{"type":"chunk","time":1789625679032,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":4}}},{"type":"chunk","time":1789625679032,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent worker-1 failed before it finished."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"DEPTH_ONE_DONE"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 failed before it finished.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:7}}"},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":2,"step":1,"message":{"role":"assistant","content":[{"type":"text","text":"ROOT_DONE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:8}}"},"usage":{"inputTokens":10,"outputTokens":4},"stream":[{"type":"chunk","time":1792123799031,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1792123799031,"index":0,"dt":[],"texts":["ROOT_DONE"]},{"type":"chunk","time":1792123799031,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"ROOT_DONE"}}},{"type":"chunk","time":1792123799031,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":4}}},{"type":"chunk","time":1792123799031,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":2,"step":1}} {"type":"turn/end","data":{"turn":2,"reason":{"kind":"completed"}}} diff --git a/snapshots/session/subagent-max-tokens-partial/session.1.v4.jsonl b/snapshots/session/subagent-max-tokens-partial/session.1.v4.jsonl index 10b2c028bf..72d231f68f 100644 --- a/snapshots/session/subagent-max-tokens-partial/session.1.v4.jsonl +++ b/snapshots/session/subagent-max-tokens-partial/session.1.v4.jsonl @@ -3,22 +3,22 @@ {"type":"sandbox/mode","data":{"mode":"danger-full-access","source":"delegation"}} {"type":"approval/policy","data":{"policy":"never","source":"delegation"}} {"type":"permission/preset","data":{"preset":"danger-full-access"}} -{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Write the words 'partial one', call todo_write once, then keep going until you are cut off."},{"type":"text","text":"Your parent agent id is \"{{session:1}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{session:1}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:9}}"}]}} +{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Write the words 'partial one', call todo_write once, then keep going until you are cut off."},{"type":"text","text":"Your name is \"worker-1\". Your parent agent name is \"lead\". Before you finish, send your result to that agent with send_message({ name: \"lead\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:9}}"}]}} {"type":"turn/start","data":{"turn":1}} {"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":1,"step":1}} {"type":"system/message","data":{"turn":1,"step":1,"message":{"role":"system","content":[{"type":"text","text":"{{system}}"}],"source":{"kind":"system-prompt"},"id":"{{message:10}}"}},"surfaceOp":"append"} -{"type":"user/message","data":{"content":[{"type":"text","text":"Write the words 'partial one', call todo_write once, then keep going until you are cut off."},{"type":"text","text":"Your parent agent id is \"{{session:1}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{session:1}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:9}}"},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Write the words 'partial one', call todo_write once, then keep going until you are cut off."},{"type":"text","text":"Your name is \"worker-1\". Your parent agent name is \"lead\". Before you finish, send your result to that agent with send_message({ name: \"lead\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:9}}"},"surfaceOp":"append"} {"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations.\n\nApproval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).\n\nDelegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly.\n\nDelegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly.\n\nYou are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations."},{"name":"approval:policy","text":"Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."},{"name":"tool:subagent:depth","text":"Delegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly."},{"name":"tool:subagent_fork:depth","text":"Delegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly."},{"name":"subagent:delegation","text":"You are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}]},"role":"user","id":"{{message:11}}"},"surfaceOp":"append"} {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} {"type":"session/title","data":{"title":"Write the words 'partial one',","messageSeqs":[9],"source":{"kind":"fallback"}}} -{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"text","text":"partial one"},{"type":"tool-call","id":"call_child_1","name":"todo_write","arguments":"{\"todos\": [{\"content\": \"keep going\", \"status\": \"in_progress\"}]}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:12}}"},"usage":{"inputTokens":20,"outputTokens":9},"stream":[{"type":"chunk","time":1789625680223,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"chunk","time":1789625680223,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"partial one"}}},{"type":"chunk","time":1789625680223,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}},{"type":"chunk","time":1789625680223,"chunk":{"type":"block-end","index":1,"block":{"type":"tool-call","id":"call_child_1","name":"todo_write","arguments":"{\"todos\": [{\"content\": \"keep going\", \"status\": \"in_progress\"}]}"}}},{"type":"chunk","time":1789625680223,"chunk":{"type":"usage","usage":{"inputTokens":20,"outputTokens":9}}},{"type":"chunk","time":1789625680223,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} -{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_child_1","name":"todo_write","arguments":"{\"todos\": [{\"content\": \"keep going\", \"status\": \"in_progress\"}]}"}} +{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"text","text":"partial one"},{"type":"tool-call","id":"call_child_1","name":"todo_write","arguments":"{\"todos\":[{\"content\":\"keep going\",\"status\":\"in_progress\"}]}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:12}}"},"usage":{"inputTokens":20,"outputTokens":9},"stream":[{"type":"chunk","time":1789625680223,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"chunk","time":1789625680223,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"partial one"}}},{"type":"chunk","time":1789625680223,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}},{"type":"chunk","time":1789625680223,"chunk":{"type":"block-end","index":1,"block":{"type":"tool-call","id":"call_child_1","name":"todo_write","arguments":"{\"todos\":[{\"content\":\"keep going\",\"status\":\"in_progress\"}]}"}}},{"type":"chunk","time":1789625680223,"chunk":{"type":"usage","usage":{"inputTokens":20,"outputTokens":9}}},{"type":"chunk","time":1789625680223,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_child_1","name":"todo_write","arguments":"{\"todos\":[{\"content\":\"keep going\",\"status\":\"in_progress\"}]}"}} {"type":"todo/write","data":{"todos":[{"content":"keep going","status":"in_progress"}]}} {"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_child_1"},"toolCallId":"call_child_1","content":[{"type":"text","text":"Updated todo list: 0 pending, 1 in progress, 0 completed."}],"isError":false,"id":"{{message:13}}"}},"sourceEventSeqs":[15],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":1}} {"type":"step/start","data":{"turn":1,"step":2}} -{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:14}}"},"usage":{"inputTokens":30,"outputTokens":4},"stream":[{"type":"chunk","time":1789625680241,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"chunk","time":1789625680241,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_child_2","name":"todo_write","arguments":"{\"todos\": [{\"content\": \"keep going\", \"status\": \"completed\"}]}"}}},{"type":"chunk","time":1789625680241,"chunk":{"type":"usage","usage":{"inputTokens":30,"outputTokens":4}}},{"type":"chunk","time":1789625680241,"chunk":{"type":"finish","reason":{"kind":"max-tokens"}}}]},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:14}}"},"usage":{"inputTokens":30,"outputTokens":4},"stream":[{"type":"chunk","time":1789625680241,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"chunk","time":1789625680241,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_child_2","name":"todo_write","arguments":"{\"todos\":[{\"content\":\"keep going\",\"status\":\"completed\"}]}"}}},{"type":"chunk","time":1789625680241,"chunk":{"type":"usage","usage":{"inputTokens":30,"outputTokens":4}}},{"type":"chunk","time":1789625680241,"chunk":{"type":"finish","reason":{"kind":"max-tokens"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":2}} {"type":"turn/end","data":{"turn":1,"reason":{"kind":"max-tokens"}}} diff --git a/snapshots/session/subagent-max-tokens-partial/session.v4.jsonl b/snapshots/session/subagent-max-tokens-partial/session.v4.jsonl index 2b326fc02c..65339edbfc 100644 --- a/snapshots/session/subagent-max-tokens-partial/session.v4.jsonl +++ b/snapshots/session/subagent-max-tokens-partial/session.v4.jsonl @@ -12,20 +12,21 @@ {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} {"type":"session/title","data":{"title":"Use the subagent tool exactly","messageSeqs":[8],"source":{"kind":"fallback"}}} -{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_parent_1","name":"subagent","arguments":"{\"description\": \"Truncated child\", \"prompt\": \"Write the words 'partial one', call todo_write once, then keep going until you are cut off.\", \"run_in_background\":false}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1789625680177,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"chunk","time":1789625680178,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_parent_1","name":"subagent","arguments":"{\"description\": \"Truncated child\", \"prompt\": \"Write the words 'partial one', call todo_write once, then keep going until you are cut off.\", \"run_in_background\":false}"}}},{"type":"chunk","time":1789625680178,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1789625680178,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} -{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_parent_1","name":"subagent","arguments":"{\"description\": \"Truncated child\", \"prompt\": \"Write the words 'partial one', call todo_write once, then keep going until you are cut off.\", \"run_in_background\":false}"}} -{"type":"subagent/catalog","data":{"version":0,"childId":"{{session:2}}","childCreatedAt":1789625680183,"mode":"continuable","label":"Truncated child"}} -{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_parent_1"},"toolCallId":"call_parent_1","content":[{"type":"text","text":"started subagent {{session:2}}"}],"isError":false,"id":"{{message:5}}"}},"sourceEventSeqs":[14],"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_parent_1","name":"subagent","arguments":"{\"description\":\"Truncated child\",\"prompt\":\"Write the words 'partial one', call todo_write once, then keep going until you are cut off.\",\"run_in_background\":false,\"name\":\"worker-1\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1792123799764,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"chunk","time":1792123799764,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_parent_1","name":"subagent","arguments":"{\"description\":\"Truncated child\",\"prompt\":\"Write the words 'partial one', call todo_write once, then keep going until you are cut off.\",\"run_in_background\":false,\"name\":\"worker-1\"}"}}},{"type":"chunk","time":1792123799764,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1792123799764,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_parent_1","name":"subagent","arguments":"{\"description\":\"Truncated child\",\"prompt\":\"Write the words 'partial one', call todo_write once, then keep going until you are cut off.\",\"run_in_background\":false,\"name\":\"worker-1\"}"}} +{"type":"subagent/catalog","data":{"version":0,"childId":"{{session:2}}","childCreatedAt":1792123799770,"mode":"continuable","label":"Truncated child"}} +{"type":"subagent/named","data":{"name":"worker-1","id":"{{session:2}}"}} +{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_parent_1"},"toolCallId":"call_parent_1","content":[{"type":"text","text":"started subagent worker-1"}],"isError":false,"id":"{{message:5}}"}},"sourceEventSeqs":[14],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":1}} {"type":"step/start","data":{"turn":1,"step":2}} -{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"text","text":"PARENT_DONE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:6}}"},"usage":{"inputTokens":12,"outputTokens":2},"stream":[{"type":"chunk","time":1789625680211,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"chunk","time":1789625680211,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"PARENT_DONE"}}},{"type":"chunk","time":1789625680211,"chunk":{"type":"usage","usage":{"inputTokens":12,"outputTokens":2}}},{"type":"chunk","time":1789625680211,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"text","text":"PARENT_DONE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:6}}"},"usage":{"inputTokens":12,"outputTokens":2},"stream":[{"type":"chunk","time":1792123799807,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"chunk","time":1792123799807,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"PARENT_DONE"}}},{"type":"chunk","time":1792123799807,"chunk":{"type":"usage","usage":{"inputTokens":12,"outputTokens":2}}},{"type":"chunk","time":1792123799807,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":2}} {"type":"turn/end","data":{"turn":1,"reason":{"kind":"completed"}}} -{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent {{session:2}} ran out of room before it finished."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"partial one"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{session:2}} ran out of room before it finished.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:7}}"}]}} +{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent worker-1 ran out of room before it finished."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"partial one"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 ran out of room before it finished.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:7}}"}]}} {"type":"turn/start","data":{"turn":2}} {"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":2,"step":1}} -{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent {{session:2}} ran out of room before it finished."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"partial one"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{session:2}} ran out of room before it finished.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:7}}"},"surfaceOp":"append"} -{"type":"assistant/message","data":{"turn":2,"step":1,"message":{"role":"assistant","content":[{"type":"text","text":"PARENT_DONE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:8}}"},"usage":{"inputTokens":10,"outputTokens":4},"stream":[{"type":"chunk","time":1789625680259,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1789625680259,"index":0,"dt":[],"texts":["PARENT_DONE"]},{"type":"chunk","time":1789625680259,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"PARENT_DONE"}}},{"type":"chunk","time":1789625680259,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":4}}},{"type":"chunk","time":1789625680259,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent worker-1 ran out of room before it finished."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"partial one"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 ran out of room before it finished.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:7}}"},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":2,"step":1,"message":{"role":"assistant","content":[{"type":"text","text":"PARENT_DONE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:8}}"},"usage":{"inputTokens":10,"outputTokens":4},"stream":[{"type":"chunk","time":1792123799857,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1792123799857,"index":0,"dt":[],"texts":["PARENT_DONE"]},{"type":"chunk","time":1792123799857,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"PARENT_DONE"}}},{"type":"chunk","time":1792123799857,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":4}}},{"type":"chunk","time":1792123799857,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":2,"step":1}} {"type":"turn/end","data":{"turn":2,"reason":{"kind":"completed"}}} diff --git a/snapshots/session/subagent-multi/replay.override.json b/snapshots/session/subagent-multi/replay.override.json new file mode 100644 index 0000000000..de2aa048fe --- /dev/null +++ b/snapshots/session/subagent-multi/replay.override.json @@ -0,0 +1,1136 @@ +[ + { + "kind": "chunks", + "chunks": [ + { + "type": "block-start", + "index": 0, + "blockType": "reasoning" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": "The" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " user" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " wants" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " me" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " to" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " use" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " the" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " sub" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": "agent" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " tool" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " twice" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": "," + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " sequentially" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " (" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": "one" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " at" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " a" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " time" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": ")." + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " First" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " sub" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": "agent" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " should" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " reply" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " with" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " \"" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": "AL" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": "P" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": "HA" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": "\"," + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " second" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " with" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " \"" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": "B" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": "ETA" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": "\"." + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " After" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " both" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " return" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": "," + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " I" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " reply" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " with" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " \"" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": "PAR" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": "ENT" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": "_D" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": "ONE" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": "\"." + }, + { + "type": "block-start", + "index": 1, + "blockType": "tool-call" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_7zDCCjdsQgrk5LR2bAEQ1010", + "name": "subagent", + "argumentsDelta": "{\"description\":\"Return ALPHA only\",\"prompt\":\"Reply with exactly the word ALPHA and nothing else.\",\"run_in_background\":false,\"name\":\"worker-1\"}" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_7zDCCjdsQgrk5LR2bAEQ1010", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_7zDCCjdsQgrk5LR2bAEQ1010", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_7zDCCjdsQgrk5LR2bAEQ1010", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_7zDCCjdsQgrk5LR2bAEQ1010", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_7zDCCjdsQgrk5LR2bAEQ1010", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_7zDCCjdsQgrk5LR2bAEQ1010", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_7zDCCjdsQgrk5LR2bAEQ1010", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_7zDCCjdsQgrk5LR2bAEQ1010", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_7zDCCjdsQgrk5LR2bAEQ1010", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_7zDCCjdsQgrk5LR2bAEQ1010", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_7zDCCjdsQgrk5LR2bAEQ1010", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_7zDCCjdsQgrk5LR2bAEQ1010", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_7zDCCjdsQgrk5LR2bAEQ1010", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_7zDCCjdsQgrk5LR2bAEQ1010", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_7zDCCjdsQgrk5LR2bAEQ1010", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_7zDCCjdsQgrk5LR2bAEQ1010", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_7zDCCjdsQgrk5LR2bAEQ1010", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_7zDCCjdsQgrk5LR2bAEQ1010", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_7zDCCjdsQgrk5LR2bAEQ1010", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_7zDCCjdsQgrk5LR2bAEQ1010", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_7zDCCjdsQgrk5LR2bAEQ1010", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_7zDCCjdsQgrk5LR2bAEQ1010", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_7zDCCjdsQgrk5LR2bAEQ1010", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_7zDCCjdsQgrk5LR2bAEQ1010", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_7zDCCjdsQgrk5LR2bAEQ1010", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_7zDCCjdsQgrk5LR2bAEQ1010", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_7zDCCjdsQgrk5LR2bAEQ1010", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_7zDCCjdsQgrk5LR2bAEQ1010", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_7zDCCjdsQgrk5LR2bAEQ1010", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_7zDCCjdsQgrk5LR2bAEQ1010", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_7zDCCjdsQgrk5LR2bAEQ1010", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_7zDCCjdsQgrk5LR2bAEQ1010", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_7zDCCjdsQgrk5LR2bAEQ1010", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "block-end", + "index": 0, + "block": { + "type": "reasoning", + "text": "The user wants me to use the subagent tool twice, sequentially (one at a time). First subagent should reply with \"ALPHA\", second with \"BETA\". After both return, I reply with \"PARENT_DONE\"." + } + }, + { + "type": "block-end", + "index": 1, + "block": { + "type": "tool-call", + "id": "call_00_7zDCCjdsQgrk5LR2bAEQ1010", + "name": "subagent", + "arguments": "{\"description\":\"Return ALPHA only\",\"prompt\":\"Reply with exactly the word ALPHA and nothing else.\",\"run_in_background\":false,\"name\":\"worker-1\"}" + } + }, + { + "type": "usage", + "usage": { + "inputTokens": 2938, + "outputTokens": 124, + "cacheReadTokens": 0, + "reasoningTokens": 49 + } + }, + { + "type": "finish", + "reason": { + "kind": "tool-calls" + } + } + ] + }, + { + "kind": "chunks", + "chunks": [ + { + "type": "block-start", + "index": 0, + "blockType": "reasoning" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": "First" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " sub" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": "agent" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " returned" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " \"" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": "AL" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": "P" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": "HA" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": "\"." + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " Now" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " I" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": "'ll" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " call" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " the" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " second" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " sub" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": "agent" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " to" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " return" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " \"" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": "B" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": "ETA" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": "\"." + }, + { + "type": "block-start", + "index": 1, + "blockType": "tool-call" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_FudNKuJ0fchSptGy3Scw1411", + "name": "subagent", + "argumentsDelta": "{\"description\":\"Return BETA only\",\"prompt\":\"Reply with exactly the word BETA and nothing else.\",\"run_in_background\":false,\"name\":\"worker-2\"}" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_FudNKuJ0fchSptGy3Scw1411", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_FudNKuJ0fchSptGy3Scw1411", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_FudNKuJ0fchSptGy3Scw1411", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_FudNKuJ0fchSptGy3Scw1411", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_FudNKuJ0fchSptGy3Scw1411", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_FudNKuJ0fchSptGy3Scw1411", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_FudNKuJ0fchSptGy3Scw1411", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_FudNKuJ0fchSptGy3Scw1411", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_FudNKuJ0fchSptGy3Scw1411", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_FudNKuJ0fchSptGy3Scw1411", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_FudNKuJ0fchSptGy3Scw1411", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_FudNKuJ0fchSptGy3Scw1411", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_FudNKuJ0fchSptGy3Scw1411", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_FudNKuJ0fchSptGy3Scw1411", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_FudNKuJ0fchSptGy3Scw1411", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_FudNKuJ0fchSptGy3Scw1411", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_FudNKuJ0fchSptGy3Scw1411", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_FudNKuJ0fchSptGy3Scw1411", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_FudNKuJ0fchSptGy3Scw1411", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_FudNKuJ0fchSptGy3Scw1411", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_FudNKuJ0fchSptGy3Scw1411", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_FudNKuJ0fchSptGy3Scw1411", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_FudNKuJ0fchSptGy3Scw1411", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_FudNKuJ0fchSptGy3Scw1411", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_FudNKuJ0fchSptGy3Scw1411", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_FudNKuJ0fchSptGy3Scw1411", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_FudNKuJ0fchSptGy3Scw1411", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_FudNKuJ0fchSptGy3Scw1411", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_FudNKuJ0fchSptGy3Scw1411", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_FudNKuJ0fchSptGy3Scw1411", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_FudNKuJ0fchSptGy3Scw1411", + "name": "subagent", + "argumentsDelta": "" + }, + { + "type": "block-end", + "index": 0, + "block": { + "type": "reasoning", + "text": "First subagent returned \"ALPHA\". Now I'll call the second subagent to return \"BETA\"." + } + }, + { + "type": "block-end", + "index": 1, + "block": { + "type": "tool-call", + "id": "call_00_FudNKuJ0fchSptGy3Scw1411", + "name": "subagent", + "arguments": "{\"description\":\"Return BETA only\",\"prompt\":\"Reply with exactly the word BETA and nothing else.\",\"run_in_background\":false,\"name\":\"worker-2\"}" + } + }, + { + "type": "usage", + "usage": { + "inputTokens": 133, + "outputTokens": 96, + "cacheReadTokens": 2944, + "reasoningTokens": 23 + } + }, + { + "type": "finish", + "reason": { + "kind": "tool-calls" + } + } + ] + }, + { + "kind": "chunks", + "chunks": [ + { + "type": "block-start", + "index": 0, + "blockType": "reasoning" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": "Both" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " sub" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": "agents" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " have" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " returned" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": ":" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " first" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " with" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " \"" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": "AL" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": "P" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": "HA" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": "\"," + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " second" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " with" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " \"" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": "B" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": "ETA" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": "\"." + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " Now" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " I" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " should" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " reply" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " with" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": " \"" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": "PAR" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": "ENT" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": "_D" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": "ONE" + }, + { + "type": "reasoning-delta", + "index": 0, + "text": "\"." + }, + { + "type": "block-start", + "index": 1, + "blockType": "text" + }, + { + "type": "text-delta", + "index": 1, + "text": "PAR" + }, + { + "type": "text-delta", + "index": 1, + "text": "ENT" + }, + { + "type": "text-delta", + "index": 1, + "text": "_D" + }, + { + "type": "text-delta", + "index": 1, + "text": "ONE" + }, + { + "type": "block-end", + "index": 0, + "block": { + "type": "reasoning", + "text": "Both subagents have returned: first with \"ALPHA\", second with \"BETA\". Now I should reply with \"PARENT_DONE\"." + } + }, + { + "type": "block-end", + "index": 1, + "block": { + "type": "text", + "text": "PARENT_DONE" + } + }, + { + "type": "usage", + "usage": { + "inputTokens": 115, + "outputTokens": 35, + "cacheReadTokens": 3072, + "reasoningTokens": 30 + } + }, + { + "type": "finish", + "reason": { + "kind": "stop" + } + } + ] + } +] diff --git a/snapshots/session/subagent-multi/snapshot.yml b/snapshots/session/subagent-multi/snapshot.yml index a0d6fbf93e..3b0d237553 100644 --- a/snapshots/session/subagent-multi/snapshot.yml +++ b/snapshots/session/subagent-multi/snapshot.yml @@ -3,6 +3,8 @@ scenario: subagent-multi profile: headless composition: default recording: live +replay: + override: true sessionFormat: version: 0 coverage: [multi-hop, shipped-profile] diff --git a/snapshots/session/subagent-multi/writer.1.expected.jsonl b/snapshots/session/subagent-multi/writer.1.expected.jsonl index 9666f25ef7..b89c6aabfc 100644 --- a/snapshots/session/subagent-multi/writer.1.expected.jsonl +++ b/snapshots/session/subagent-multi/writer.1.expected.jsonl @@ -3,16 +3,16 @@ {"type":"sandbox/mode","data":{"mode":"danger-full-access","source":"delegation"}} {"type":"approval/policy","data":{"policy":"never","source":"delegation"}} {"type":"permission/preset","data":{"preset":"danger-full-access"}} -{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Reply with exactly the word ALPHA and nothing else."},{"type":"text","text":"Your parent agent id is \"{{session:1}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{session:1}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:11}}"}]}} +{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Reply with exactly the word ALPHA and nothing else."},{"type":"text","text":"Your name is \"worker-1\". Your parent agent name is \"lead\". Before you finish, send your result to that agent with send_message({ name: \"lead\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:11}}"}]}} {"type":"turn/start","data":{"turn":1}} {"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":1,"step":1}} {"type":"system/message","data":{"turn":1,"step":1,"message":{"role":"system","content":[{"type":"text","text":"{{system}}"}],"source":{"kind":"system-prompt"},"id":"{{message:12}}"}},"surfaceOp":"append"} -{"type":"user/message","data":{"content":[{"type":"text","text":"Reply with exactly the word ALPHA and nothing else."},{"type":"text","text":"Your parent agent id is \"{{session:1}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{session:1}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:11}}"},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Reply with exactly the word ALPHA and nothing else."},{"type":"text","text":"Your name is \"worker-1\". Your parent agent name is \"lead\". Before you finish, send your result to that agent with send_message({ name: \"lead\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:11}}"},"surfaceOp":"append"} {"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations.\n\nApproval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).\n\nDelegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly.\n\nDelegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly.\n\nYou are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations."},{"name":"approval:policy","text":"Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."},{"name":"tool:subagent:depth","text":"Delegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly."},{"name":"tool:subagent_fork:depth","text":"Delegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly."},{"name":"subagent:delegation","text":"You are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}]},"role":"user","id":"{{message:13}}"},"surfaceOp":"append"} {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} {"type":"session/title","data":{"title":"Reply with exactly the word","messageSeqs":[9],"source":{"kind":"fallback"}}} -{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"reasoning","text":"The user wants me to reply with exactly the word \"ALPHA\" and nothing else."},{"type":"text","text":"ALPHA"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:14}}"},"usage":{"inputTokens":49,"outputTokens":23,"cacheReadTokens":2816,"reasoningTokens":19},"stream":[{"type":"chunk","time":1791789326845,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1791789326846,"index":0,"dt":[1,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,4,0],"texts":["The"," user"," wants"," me"," to"," reply"," with"," exactly"," the"," word"," \"","AL","P","HA","\""," and"," nothing"," else","."]},{"type":"chunk","time":1791789326853,"chunk":{"type":"block-start","index":1,"blockType":"text"}},{"type":"text-chunks","time0":1791789326853,"index":1,"dt":[0,0],"texts":["AL","P","HA"]},{"type":"chunk","time":1791789326854,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The user wants me to reply with exactly the word \"ALPHA\" and nothing else."}}},{"type":"chunk","time":1791789326854,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"ALPHA"}}},{"type":"chunk","time":1791789326854,"chunk":{"type":"usage","usage":{"inputTokens":49,"outputTokens":23,"cacheReadTokens":2816,"reasoningTokens":19}}},{"type":"chunk","time":1791789326854,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"reasoning","text":"The user wants me to reply with exactly the word \"ALPHA\" and nothing else."},{"type":"text","text":"ALPHA"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:14}}"},"usage":{"inputTokens":49,"outputTokens":23,"cacheReadTokens":2816,"reasoningTokens":19},"stream":[{"type":"chunk","time":1792123971273,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1792123971274,"index":0,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"texts":["The"," user"," wants"," me"," to"," reply"," with"," exactly"," the"," word"," \"","AL","P","HA","\""," and"," nothing"," else","."]},{"type":"chunk","time":1792123971274,"chunk":{"type":"block-start","index":1,"blockType":"text"}},{"type":"text-chunks","time0":1792123971274,"index":1,"dt":[0,0],"texts":["AL","P","HA"]},{"type":"chunk","time":1792123971274,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The user wants me to reply with exactly the word \"ALPHA\" and nothing else."}}},{"type":"chunk","time":1792123971274,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"ALPHA"}}},{"type":"chunk","time":1792123971274,"chunk":{"type":"usage","usage":{"inputTokens":49,"outputTokens":23,"cacheReadTokens":2816,"reasoningTokens":19}}},{"type":"chunk","time":1792123971274,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":1}} {"type":"turn/end","data":{"turn":1,"reason":{"kind":"completed"}}} diff --git a/snapshots/session/subagent-multi/writer.2.expected.jsonl b/snapshots/session/subagent-multi/writer.2.expected.jsonl index 674fa2ce2e..1af5c9f873 100644 --- a/snapshots/session/subagent-multi/writer.2.expected.jsonl +++ b/snapshots/session/subagent-multi/writer.2.expected.jsonl @@ -3,16 +3,16 @@ {"type":"sandbox/mode","data":{"mode":"danger-full-access","source":"delegation"}} {"type":"approval/policy","data":{"policy":"never","source":"delegation"}} {"type":"permission/preset","data":{"preset":"danger-full-access"}} -{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Reply with exactly the word BETA and nothing else."},{"type":"text","text":"Your parent agent id is \"{{session:1}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{session:1}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:15}}"}]}} +{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Reply with exactly the word BETA and nothing else."},{"type":"text","text":"Your name is \"worker-2\". Your parent agent name is \"lead\". Before you finish, send your result to that agent with send_message({ name: \"lead\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:15}}"}]}} {"type":"turn/start","data":{"turn":1}} {"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":1,"step":1}} {"type":"system/message","data":{"turn":1,"step":1,"message":{"role":"system","content":[{"type":"text","text":"{{system}}"}],"source":{"kind":"system-prompt"},"id":"{{message:16}}"}},"surfaceOp":"append"} -{"type":"user/message","data":{"content":[{"type":"text","text":"Reply with exactly the word BETA and nothing else."},{"type":"text","text":"Your parent agent id is \"{{session:1}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{session:1}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:15}}"},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Reply with exactly the word BETA and nothing else."},{"type":"text","text":"Your name is \"worker-2\". Your parent agent name is \"lead\". Before you finish, send your result to that agent with send_message({ name: \"lead\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:15}}"},"surfaceOp":"append"} {"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations.\n\nApproval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).\n\nDelegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly.\n\nDelegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly.\n\nYou are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations."},{"name":"approval:policy","text":"Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."},{"name":"tool:subagent:depth","text":"Delegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly."},{"name":"tool:subagent_fork:depth","text":"Delegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly."},{"name":"subagent:delegation","text":"You are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}]},"role":"user","id":"{{message:17}}"},"surfaceOp":"append"} {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} {"type":"session/title","data":{"title":"Reply with exactly the word","messageSeqs":[9],"source":{"kind":"fallback"}}} -{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"reasoning","text":"The user wants me to reply with exactly the word \"BETA\" and nothing else."},{"type":"text","text":"BETA"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:18}}"},"usage":{"inputTokens":48,"outputTokens":21,"cacheReadTokens":2816,"reasoningTokens":18},"stream":[{"type":"chunk","time":1791789328017,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1791789328018,"index":0,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0],"texts":["The"," user"," wants"," me"," to"," reply"," with"," exactly"," the"," word"," \"","B","ETA","\""," and"," nothing"," else","."]},{"type":"chunk","time":1791789328019,"chunk":{"type":"block-start","index":1,"blockType":"text"}},{"type":"text-chunks","time0":1791789328019,"index":1,"dt":[0],"texts":["B","ETA"]},{"type":"chunk","time":1791789328019,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The user wants me to reply with exactly the word \"BETA\" and nothing else."}}},{"type":"chunk","time":1791789328019,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"BETA"}}},{"type":"chunk","time":1791789328019,"chunk":{"type":"usage","usage":{"inputTokens":48,"outputTokens":21,"cacheReadTokens":2816,"reasoningTokens":18}}},{"type":"chunk","time":1791789328019,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"reasoning","text":"The user wants me to reply with exactly the word \"BETA\" and nothing else."},{"type":"text","text":"BETA"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:18}}"},"usage":{"inputTokens":48,"outputTokens":21,"cacheReadTokens":2816,"reasoningTokens":18},"stream":[{"type":"chunk","time":1792123971346,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1792123971346,"index":0,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"texts":["The"," user"," wants"," me"," to"," reply"," with"," exactly"," the"," word"," \"","B","ETA","\""," and"," nothing"," else","."]},{"type":"chunk","time":1792123971346,"chunk":{"type":"block-start","index":1,"blockType":"text"}},{"type":"text-chunks","time0":1792123971346,"index":1,"dt":[0],"texts":["B","ETA"]},{"type":"chunk","time":1792123971346,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The user wants me to reply with exactly the word \"BETA\" and nothing else."}}},{"type":"chunk","time":1792123971346,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"BETA"}}},{"type":"chunk","time":1792123971346,"chunk":{"type":"usage","usage":{"inputTokens":48,"outputTokens":21,"cacheReadTokens":2816,"reasoningTokens":18}}},{"type":"chunk","time":1792123971346,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":1}} {"type":"turn/end","data":{"turn":1,"reason":{"kind":"completed"}}} diff --git a/snapshots/session/subagent-multi/writer.expected.jsonl b/snapshots/session/subagent-multi/writer.expected.jsonl index 519727be11..b11b237434 100644 --- a/snapshots/session/subagent-multi/writer.expected.jsonl +++ b/snapshots/session/subagent-multi/writer.expected.jsonl @@ -12,24 +12,26 @@ {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} {"type":"session/title","data":{"title":"Use the subagent tool TWICE,","messageSeqs":[8],"source":{"kind":"fallback"}}} -{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"reasoning","text":"The user wants me to use the subagent tool twice, sequentially (one at a time). First subagent should reply with \"ALPHA\", second with \"BETA\". After both return, I reply with \"PARENT_DONE\"."},{"type":"tool-call","id":"call_00_7zDCCjdsQgrk5LR2bAEQ1010","name":"subagent","arguments":"{\"description\": \"Return ALPHA only\", \"prompt\": \"Reply with exactly the word ALPHA and nothing else.\", \"run_in_background\": false}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":2938,"outputTokens":124,"cacheReadTokens":0,"reasoningTokens":49},"stream":[{"type":"chunk","time":1791444968802,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1791444968803,"index":0,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"texts":["The"," user"," wants"," me"," to"," use"," the"," sub","agent"," tool"," twice",","," sequentially"," (","one"," at"," a"," time",")."," First"," sub","agent"," should"," reply"," with"," \"","AL","P","HA","\","," second"," with"," \"","B","ETA","\"."," After"," both"," return",","," I"," reply"," with"," \"","PAR","ENT","_D","ONE","\"."]},{"type":"chunk","time":1791444968804,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1791444968804,"index":1,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"id":"call_00_7zDCCjdsQgrk5LR2bAEQ1010","name":"subagent","args":["","{","\"","description","\"",": ","\"","Return"," AL","P","HA"," only","\"",", ","\"","prom","pt","\"",": ","\"","Reply"," with"," exactly"," the"," word"," AL","P","HA"," and"," nothing"," else",".","\"",", \"run_in_background\": false}"]},{"type":"chunk","time":1791444968804,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The user wants me to use the subagent tool twice, sequentially (one at a time). First subagent should reply with \"ALPHA\", second with \"BETA\". After both return, I reply with \"PARENT_DONE\"."}}},{"type":"chunk","time":1791444968804,"chunk":{"type":"block-end","index":1,"block":{"type":"tool-call","id":"call_00_7zDCCjdsQgrk5LR2bAEQ1010","name":"subagent","arguments":"{\"description\": \"Return ALPHA only\", \"prompt\": \"Reply with exactly the word ALPHA and nothing else.\", \"run_in_background\": false}"}}},{"type":"chunk","time":1791444968804,"chunk":{"type":"usage","usage":{"inputTokens":2938,"outputTokens":124,"cacheReadTokens":0,"reasoningTokens":49}}},{"type":"chunk","time":1791444968804,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} -{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_00_7zDCCjdsQgrk5LR2bAEQ1010","name":"subagent","arguments":"{\"description\": \"Return ALPHA only\", \"prompt\": \"Reply with exactly the word ALPHA and nothing else.\", \"run_in_background\": false}"}} -{"type":"subagent/catalog","data":{"version":0,"childId":"{{session:2}}","childCreatedAt":1791444968811,"mode":"continuable","label":"Return ALPHA only"}} -{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent {{session:2}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"ALPHA"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{session:2}} finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:5}}"}]}} -{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_00_7zDCCjdsQgrk5LR2bAEQ1010"},"toolCallId":"call_00_7zDCCjdsQgrk5LR2bAEQ1010","content":[{"type":"text","text":"started subagent {{session:2}}"}],"isError":false,"id":"{{message:6}}"}},"sourceEventSeqs":[14],"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"reasoning","text":"The user wants me to use the subagent tool twice, sequentially (one at a time). First subagent should reply with \"ALPHA\", second with \"BETA\". After both return, I reply with \"PARENT_DONE\"."},{"type":"tool-call","id":"call_00_7zDCCjdsQgrk5LR2bAEQ1010","name":"subagent","arguments":"{\"description\":\"Return ALPHA only\",\"prompt\":\"Reply with exactly the word ALPHA and nothing else.\",\"run_in_background\":false,\"name\":\"worker-1\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":2938,"outputTokens":124,"cacheReadTokens":0,"reasoningTokens":49},"stream":[{"type":"chunk","time":1792123971226,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1792123971226,"index":0,"dt":[0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"texts":["The"," user"," wants"," me"," to"," use"," the"," sub","agent"," tool"," twice",","," sequentially"," (","one"," at"," a"," time",")."," First"," sub","agent"," should"," reply"," with"," \"","AL","P","HA","\","," second"," with"," \"","B","ETA","\"."," After"," both"," return",","," I"," reply"," with"," \"","PAR","ENT","_D","ONE","\"."]},{"type":"chunk","time":1792123971227,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792123971227,"index":1,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"id":"call_00_7zDCCjdsQgrk5LR2bAEQ1010","name":"subagent","args":["{\"description\":\"Return ALPHA only\",\"prompt\":\"Reply with exactly the word ALPHA and nothing else.\",\"run_in_background\":false,\"name\":\"worker-1\"}","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""]},{"type":"chunk","time":1792123971228,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The user wants me to use the subagent tool twice, sequentially (one at a time). First subagent should reply with \"ALPHA\", second with \"BETA\". After both return, I reply with \"PARENT_DONE\"."}}},{"type":"chunk","time":1792123971228,"chunk":{"type":"block-end","index":1,"block":{"type":"tool-call","id":"call_00_7zDCCjdsQgrk5LR2bAEQ1010","name":"subagent","arguments":"{\"description\":\"Return ALPHA only\",\"prompt\":\"Reply with exactly the word ALPHA and nothing else.\",\"run_in_background\":false,\"name\":\"worker-1\"}"}}},{"type":"chunk","time":1792123971228,"chunk":{"type":"usage","usage":{"inputTokens":2938,"outputTokens":124,"cacheReadTokens":0,"reasoningTokens":49}}},{"type":"chunk","time":1792123971228,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_00_7zDCCjdsQgrk5LR2bAEQ1010","name":"subagent","arguments":"{\"description\":\"Return ALPHA only\",\"prompt\":\"Reply with exactly the word ALPHA and nothing else.\",\"run_in_background\":false,\"name\":\"worker-1\"}"}} +{"type":"subagent/catalog","data":{"version":0,"childId":"{{session:2}}","childCreatedAt":1792123971235,"mode":"continuable","label":"Return ALPHA only"}} +{"type":"subagent/named","data":{"name":"worker-1","id":"{{session:2}}"}} +{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent worker-1 finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"ALPHA"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:5}}"}]}} +{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_00_7zDCCjdsQgrk5LR2bAEQ1010"},"toolCallId":"call_00_7zDCCjdsQgrk5LR2bAEQ1010","content":[{"type":"text","text":"started subagent worker-1"}],"isError":false,"id":"{{message:6}}"}},"sourceEventSeqs":[14],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":1}} {"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":1,"step":2}} -{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent {{session:2}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"ALPHA"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{session:2}} finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:5}}"},"surfaceOp":"append"} -{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"reasoning","text":"First subagent returned \"ALPHA\". Now I'll call the second subagent to return \"BETA\"."},{"type":"tool-call","id":"call_00_FudNKuJ0fchSptGy3Scw1411","name":"subagent","arguments":"{\"description\": \"Return BETA only\", \"prompt\": \"Reply with exactly the word BETA and nothing else.\", \"run_in_background\": false}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:7}}"},"usage":{"inputTokens":133,"outputTokens":96,"cacheReadTokens":2944,"reasoningTokens":23},"stream":[{"type":"chunk","time":1791444968872,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1791444968872,"index":0,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"texts":["First"," sub","agent"," returned"," \"","AL","P","HA","\"."," Now"," I","'ll"," call"," the"," second"," sub","agent"," to"," return"," \"","B","ETA","\"."]},{"type":"chunk","time":1791444968872,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1791444968872,"index":1,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"id":"call_00_FudNKuJ0fchSptGy3Scw1411","name":"subagent","args":["","{","\"","description","\"",": ","\"","Return"," B","ETA"," only","\"",", ","\"","prom","pt","\"",": ","\"","Reply"," with"," exactly"," the"," word"," B","ETA"," and"," nothing"," else",".","\"",", \"run_in_background\": false}"]},{"type":"chunk","time":1791444968872,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"First subagent returned \"ALPHA\". Now I'll call the second subagent to return \"BETA\"."}}},{"type":"chunk","time":1791444968872,"chunk":{"type":"block-end","index":1,"block":{"type":"tool-call","id":"call_00_FudNKuJ0fchSptGy3Scw1411","name":"subagent","arguments":"{\"description\": \"Return BETA only\", \"prompt\": \"Reply with exactly the word BETA and nothing else.\", \"run_in_background\": false}"}}},{"type":"chunk","time":1791444968872,"chunk":{"type":"usage","usage":{"inputTokens":133,"outputTokens":96,"cacheReadTokens":2944,"reasoningTokens":23}}},{"type":"chunk","time":1791444968872,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} -{"type":"tool/call","data":{"turn":1,"step":2,"callId":"call_00_FudNKuJ0fchSptGy3Scw1411","name":"subagent","arguments":"{\"description\": \"Return BETA only\", \"prompt\": \"Reply with exactly the word BETA and nothing else.\", \"run_in_background\": false}"}} -{"type":"subagent/catalog","data":{"version":0,"childId":"{{session:3}}","childCreatedAt":1791444968878,"mode":"continuable","label":"Return BETA only"}} -{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent {{session:3}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"BETA"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{session:3}} finished and will do no further work unless you send it more.","senderSessionId":"{{session:3}}"},"role":"user","id":"{{message:8}}"}]}} -{"type":"tool/result","data":{"turn":1,"step":2,"message":{"role":"tool","source":{"kind":"tool","callId":"call_00_FudNKuJ0fchSptGy3Scw1411"},"toolCallId":"call_00_FudNKuJ0fchSptGy3Scw1411","content":[{"type":"text","text":"started subagent {{session:3}}"}],"isError":false,"id":"{{message:9}}"}},"sourceEventSeqs":[23],"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent worker-1 finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"ALPHA"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:5}}"},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"reasoning","text":"First subagent returned \"ALPHA\". Now I'll call the second subagent to return \"BETA\"."},{"type":"tool-call","id":"call_00_FudNKuJ0fchSptGy3Scw1411","name":"subagent","arguments":"{\"description\":\"Return BETA only\",\"prompt\":\"Reply with exactly the word BETA and nothing else.\",\"run_in_background\":false,\"name\":\"worker-2\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:7}}"},"usage":{"inputTokens":133,"outputTokens":96,"cacheReadTokens":2944,"reasoningTokens":23},"stream":[{"type":"chunk","time":1792123971302,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1792123971302,"index":0,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"texts":["First"," sub","agent"," returned"," \"","AL","P","HA","\"."," Now"," I","'ll"," call"," the"," second"," sub","agent"," to"," return"," \"","B","ETA","\"."]},{"type":"chunk","time":1792123971302,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792123971302,"index":1,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"id":"call_00_FudNKuJ0fchSptGy3Scw1411","name":"subagent","args":["{\"description\":\"Return BETA only\",\"prompt\":\"Reply with exactly the word BETA and nothing else.\",\"run_in_background\":false,\"name\":\"worker-2\"}","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""]},{"type":"chunk","time":1792123971302,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"First subagent returned \"ALPHA\". Now I'll call the second subagent to return \"BETA\"."}}},{"type":"chunk","time":1792123971302,"chunk":{"type":"block-end","index":1,"block":{"type":"tool-call","id":"call_00_FudNKuJ0fchSptGy3Scw1411","name":"subagent","arguments":"{\"description\":\"Return BETA only\",\"prompt\":\"Reply with exactly the word BETA and nothing else.\",\"run_in_background\":false,\"name\":\"worker-2\"}"}}},{"type":"chunk","time":1792123971302,"chunk":{"type":"usage","usage":{"inputTokens":133,"outputTokens":96,"cacheReadTokens":2944,"reasoningTokens":23}}},{"type":"chunk","time":1792123971302,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":2,"callId":"call_00_FudNKuJ0fchSptGy3Scw1411","name":"subagent","arguments":"{\"description\":\"Return BETA only\",\"prompt\":\"Reply with exactly the word BETA and nothing else.\",\"run_in_background\":false,\"name\":\"worker-2\"}"}} +{"type":"subagent/catalog","data":{"version":0,"childId":"{{session:3}}","childCreatedAt":1792123971309,"mode":"continuable","label":"Return BETA only"}} +{"type":"subagent/named","data":{"name":"worker-2","id":"{{session:3}}"}} +{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent worker-2 finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"BETA"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-2 finished and will do no further work unless you send it more.","senderSessionId":"{{session:3}}"},"role":"user","id":"{{message:8}}"}]}} +{"type":"tool/result","data":{"turn":1,"step":2,"message":{"role":"tool","source":{"kind":"tool","callId":"call_00_FudNKuJ0fchSptGy3Scw1411"},"toolCallId":"call_00_FudNKuJ0fchSptGy3Scw1411","content":[{"type":"text","text":"started subagent worker-2"}],"isError":false,"id":"{{message:9}}"}},"sourceEventSeqs":[24],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":2}} {"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":1,"step":3}} -{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent {{session:3}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"BETA"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{session:3}} finished and will do no further work unless you send it more.","senderSessionId":"{{session:3}}"},"role":"user","id":"{{message:8}}"},"surfaceOp":"append"} -{"type":"assistant/message","data":{"turn":1,"step":3,"message":{"role":"assistant","content":[{"type":"reasoning","text":"Both subagents have returned: first with \"ALPHA\", second with \"BETA\". Now I should reply with \"PARENT_DONE\"."},{"type":"text","text":"PARENT_DONE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:10}}"},"usage":{"inputTokens":115,"outputTokens":35,"cacheReadTokens":3072,"reasoningTokens":30},"stream":[{"type":"chunk","time":1791444968937,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1791444968937,"index":0,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"texts":["Both"," sub","agents"," have"," returned",":"," first"," with"," \"","AL","P","HA","\","," second"," with"," \"","B","ETA","\"."," Now"," I"," should"," reply"," with"," \"","PAR","ENT","_D","ONE","\"."]},{"type":"chunk","time":1791444968937,"chunk":{"type":"block-start","index":1,"blockType":"text"}},{"type":"text-chunks","time0":1791444968937,"index":1,"dt":[0,0,0],"texts":["PAR","ENT","_D","ONE"]},{"type":"chunk","time":1791444968937,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"Both subagents have returned: first with \"ALPHA\", second with \"BETA\". Now I should reply with \"PARENT_DONE\"."}}},{"type":"chunk","time":1791444968937,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"PARENT_DONE"}}},{"type":"chunk","time":1791444968937,"chunk":{"type":"usage","usage":{"inputTokens":115,"outputTokens":35,"cacheReadTokens":3072,"reasoningTokens":30}}},{"type":"chunk","time":1791444968937,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent worker-2 finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"BETA"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-2 finished and will do no further work unless you send it more.","senderSessionId":"{{session:3}}"},"role":"user","id":"{{message:8}}"},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":3,"message":{"role":"assistant","content":[{"type":"reasoning","text":"Both subagents have returned: first with \"ALPHA\", second with \"BETA\". Now I should reply with \"PARENT_DONE\"."},{"type":"text","text":"PARENT_DONE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:10}}"},"usage":{"inputTokens":115,"outputTokens":35,"cacheReadTokens":3072,"reasoningTokens":30},"stream":[{"type":"chunk","time":1792123971367,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1792123971367,"index":0,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"texts":["Both"," sub","agents"," have"," returned",":"," first"," with"," \"","AL","P","HA","\","," second"," with"," \"","B","ETA","\"."," Now"," I"," should"," reply"," with"," \"","PAR","ENT","_D","ONE","\"."]},{"type":"chunk","time":1792123971367,"chunk":{"type":"block-start","index":1,"blockType":"text"}},{"type":"text-chunks","time0":1792123971367,"index":1,"dt":[0,0,0],"texts":["PAR","ENT","_D","ONE"]},{"type":"chunk","time":1792123971367,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"Both subagents have returned: first with \"ALPHA\", second with \"BETA\". Now I should reply with \"PARENT_DONE\"."}}},{"type":"chunk","time":1792123971367,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"PARENT_DONE"}}},{"type":"chunk","time":1792123971367,"chunk":{"type":"usage","usage":{"inputTokens":115,"outputTokens":35,"cacheReadTokens":3072,"reasoningTokens":30}}},{"type":"chunk","time":1792123971367,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":3}} {"type":"turn/end","data":{"turn":1,"reason":{"kind":"completed"}}} diff --git a/snapshots/session/subagent-no-message-tool/session.v4.jsonl b/snapshots/session/subagent-no-message-tool/session.v4.jsonl index a45a0eed8b..d09af9fe31 100644 --- a/snapshots/session/subagent-no-message-tool/session.v4.jsonl +++ b/snapshots/session/subagent-no-message-tool/session.v4.jsonl @@ -13,20 +13,21 @@ {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} {"type":"session/title","data":{"title":"Use the subagent tool exactly","messageSeqs":[9],"source":{"kind":"fallback"}}} -{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"reasoning","text":"The user wants me to:\n1. Use the subagent tool exactly once to delegate the task: \"Reply with exactly the word CHILD_OK and nothing else.\"\n2. After the subagent returns, reply with the single word PARENT_DONE and stop.\n3. Do not use the bash tool.\n\nLet me do this."},{"type":"tool-call","id":"call_00_gVbLWC12Qu8JheZpVRRz8749","name":"subagent","arguments":"{\"description\": \"Reply with CHILD_OK\", \"prompt\": \"Reply with exactly the word CHILD_OK and nothing else.\", \"run_in_background\":false}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":2907,"outputTokens":142,"cacheReadTokens":0,"reasoningTokens":67},"stream":[{"type":"chunk","time":1791518803373,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1791518803373,"index":0,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0],"texts":["The"," user"," wants"," me"," to",":\n","1","."," Use"," the"," sub","agent"," tool"," exactly"," once"," to"," delegate"," the"," task",":"," \"","Reply"," with"," exactly"," the"," word"," CH","ILD","_OK"," and"," nothing"," else",".\"\n","2","."," After"," the"," sub","agent"," returns",","," reply"," with"," the"," single"," word"," PAR","ENT","_D","ONE"," and"," stop",".\n","3","."," Do"," not"," use"," the"," bash"," tool",".\n\n","Let"," me"," do"," this","."]},{"type":"chunk","time":1791518803374,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1791518803374,"index":1,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"id":"call_00_gVbLWC12Qu8JheZpVRRz8749","name":"subagent","args":["","{","\"","description","\"",": ","\"","Reply"," with"," CH","ILD","_OK","\"",", ","\"","prom","pt","\"",": ","\"","Reply"," with"," exactly"," the"," word"," CH","ILD","_OK"," and"," nothing"," else",".","\"",", \"run_in_background\":false}"]},{"type":"chunk","time":1791518803374,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The user wants me to:\n1. Use the subagent tool exactly once to delegate the task: \"Reply with exactly the word CHILD_OK and nothing else.\"\n2. After the subagent returns, reply with the single word PARENT_DONE and stop.\n3. Do not use the bash tool.\n\nLet me do this."}}},{"type":"chunk","time":1791518803374,"chunk":{"type":"block-end","index":1,"block":{"type":"tool-call","id":"call_00_gVbLWC12Qu8JheZpVRRz8749","name":"subagent","arguments":"{\"description\": \"Reply with CHILD_OK\", \"prompt\": \"Reply with exactly the word CHILD_OK and nothing else.\", \"run_in_background\":false}"}}},{"type":"chunk","time":1791518803374,"chunk":{"type":"usage","usage":{"inputTokens":2907,"outputTokens":142,"cacheReadTokens":0,"reasoningTokens":67}}},{"type":"chunk","time":1791518803374,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} -{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_00_gVbLWC12Qu8JheZpVRRz8749","name":"subagent","arguments":"{\"description\": \"Reply with CHILD_OK\", \"prompt\": \"Reply with exactly the word CHILD_OK and nothing else.\", \"run_in_background\":false}"}} -{"type":"subagent/catalog","data":{"version":0,"childId":"{{session:2}}","childCreatedAt":1791518803380,"mode":"continuable","label":"Reply with CHILD_OK"}} -{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_00_gVbLWC12Qu8JheZpVRRz8749"},"toolCallId":"call_00_gVbLWC12Qu8JheZpVRRz8749","content":[{"type":"text","text":"started subagent {{session:2}}"}],"isError":false,"id":"{{message:5}}"}},"sourceEventSeqs":[15],"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"reasoning","text":"The user wants me to:\n1. Use the subagent tool exactly once to delegate the task: \"Reply with exactly the word CHILD_OK and nothing else.\"\n2. After the subagent returns, reply with the single word PARENT_DONE and stop.\n3. Do not use the bash tool.\n\nLet me do this."},{"type":"tool-call","id":"call_00_gVbLWC12Qu8JheZpVRRz8749","name":"subagent","arguments":"{\"description\":\"Reply with CHILD_OK\",\"prompt\":\"Reply with exactly the word CHILD_OK and nothing else.\",\"run_in_background\":false,\"name\":\"worker-1\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":2907,"outputTokens":142,"cacheReadTokens":0,"reasoningTokens":67},"stream":[{"type":"chunk","time":1792123801388,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1792123801389,"index":0,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"texts":["The"," user"," wants"," me"," to",":\n","1","."," Use"," the"," sub","agent"," tool"," exactly"," once"," to"," delegate"," the"," task",":"," \"","Reply"," with"," exactly"," the"," word"," CH","ILD","_OK"," and"," nothing"," else",".\"\n","2","."," After"," the"," sub","agent"," returns",","," reply"," with"," the"," single"," word"," PAR","ENT","_D","ONE"," and"," stop",".\n","3","."," Do"," not"," use"," the"," bash"," tool",".\n\n","Let"," me"," do"," this","."]},{"type":"chunk","time":1792123801389,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792123801389,"index":1,"dt":[0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"id":"call_00_gVbLWC12Qu8JheZpVRRz8749","name":"subagent","args":["{\"description\":\"Reply with CHILD_OK\",\"prompt\":\"Reply with exactly the word CHILD_OK and nothing else.\",\"run_in_background\":false,\"name\":\"worker-1\"}","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""]},{"type":"chunk","time":1792123801390,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The user wants me to:\n1. Use the subagent tool exactly once to delegate the task: \"Reply with exactly the word CHILD_OK and nothing else.\"\n2. After the subagent returns, reply with the single word PARENT_DONE and stop.\n3. Do not use the bash tool.\n\nLet me do this."}}},{"type":"chunk","time":1792123801390,"chunk":{"type":"block-end","index":1,"block":{"type":"tool-call","id":"call_00_gVbLWC12Qu8JheZpVRRz8749","name":"subagent","arguments":"{\"description\":\"Reply with CHILD_OK\",\"prompt\":\"Reply with exactly the word CHILD_OK and nothing else.\",\"run_in_background\":false,\"name\":\"worker-1\"}"}}},{"type":"chunk","time":1792123801390,"chunk":{"type":"usage","usage":{"inputTokens":2907,"outputTokens":142,"cacheReadTokens":0,"reasoningTokens":67}}},{"type":"chunk","time":1792123801390,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_00_gVbLWC12Qu8JheZpVRRz8749","name":"subagent","arguments":"{\"description\":\"Reply with CHILD_OK\",\"prompt\":\"Reply with exactly the word CHILD_OK and nothing else.\",\"run_in_background\":false,\"name\":\"worker-1\"}"}} +{"type":"subagent/catalog","data":{"version":0,"childId":"{{session:2}}","childCreatedAt":1792123801397,"mode":"continuable","label":"Reply with CHILD_OK"}} +{"type":"subagent/named","data":{"name":"worker-1","id":"{{session:2}}"}} +{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_00_gVbLWC12Qu8JheZpVRRz8749"},"toolCallId":"call_00_gVbLWC12Qu8JheZpVRRz8749","content":[{"type":"text","text":"started subagent worker-1"}],"isError":false,"id":"{{message:5}}"}},"sourceEventSeqs":[15],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":1}} {"type":"step/start","data":{"turn":1,"step":2}} -{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"reasoning","text":"The subagent returned \"CHILD_OK\" as expected. Now I need to reply with the single word \"PARENT_DONE\" and stop."},{"type":"text","text":"PARENT_DONE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:6}}"},"usage":{"inputTokens":120,"outputTokens":35,"cacheReadTokens":2944,"reasoningTokens":30},"stream":[{"type":"chunk","time":1791518803411,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1791518803411,"index":0,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"texts":["The"," sub","agent"," returned"," \"","CH","ILD","_OK","\""," as"," expected","."," Now"," I"," need"," to"," reply"," with"," the"," single"," word"," \"","PAR","ENT","_D","ONE","\""," and"," stop","."]},{"type":"chunk","time":1791518803411,"chunk":{"type":"block-start","index":1,"blockType":"text"}},{"type":"text-chunks","time0":1791518803411,"index":1,"dt":[0,0,0],"texts":["PAR","ENT","_D","ONE"]},{"type":"chunk","time":1791518803411,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The subagent returned \"CHILD_OK\" as expected. Now I need to reply with the single word \"PARENT_DONE\" and stop."}}},{"type":"chunk","time":1791518803411,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"PARENT_DONE"}}},{"type":"chunk","time":1791518803411,"chunk":{"type":"usage","usage":{"inputTokens":120,"outputTokens":35,"cacheReadTokens":2944,"reasoningTokens":30}}},{"type":"chunk","time":1791518803411,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"reasoning","text":"The subagent returned \"CHILD_OK\" as expected. Now I need to reply with the single word \"PARENT_DONE\" and stop."},{"type":"text","text":"PARENT_DONE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:6}}"},"usage":{"inputTokens":120,"outputTokens":35,"cacheReadTokens":2944,"reasoningTokens":30},"stream":[{"type":"chunk","time":1792123801434,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1792123801434,"index":0,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"texts":["The"," sub","agent"," returned"," \"","CH","ILD","_OK","\""," as"," expected","."," Now"," I"," need"," to"," reply"," with"," the"," single"," word"," \"","PAR","ENT","_D","ONE","\""," and"," stop","."]},{"type":"chunk","time":1792123801434,"chunk":{"type":"block-start","index":1,"blockType":"text"}},{"type":"text-chunks","time0":1792123801434,"index":1,"dt":[0,0,0],"texts":["PAR","ENT","_D","ONE"]},{"type":"chunk","time":1792123801434,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The subagent returned \"CHILD_OK\" as expected. Now I need to reply with the single word \"PARENT_DONE\" and stop."}}},{"type":"chunk","time":1792123801434,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"PARENT_DONE"}}},{"type":"chunk","time":1792123801434,"chunk":{"type":"usage","usage":{"inputTokens":120,"outputTokens":35,"cacheReadTokens":2944,"reasoningTokens":30}}},{"type":"chunk","time":1792123801434,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":2}} {"type":"turn/end","data":{"turn":1,"reason":{"kind":"completed"}}} -{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent {{session:2}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"CHILD_OK"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{session:2}} finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:7}}"}]}} +{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent worker-1 finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"CHILD_OK"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:7}}"}]}} {"type":"turn/start","data":{"turn":2}} {"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":2,"step":1}} -{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent {{session:2}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"CHILD_OK"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{session:2}} finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:7}}"},"surfaceOp":"append"} -{"type":"assistant/message","data":{"turn":2,"step":1,"message":{"role":"assistant","content":[{"type":"text","text":"PARENT_DONE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:8}}"},"usage":{"inputTokens":10,"outputTokens":4},"stream":[{"type":"chunk","time":1791518803462,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1791518803462,"index":0,"dt":[],"texts":["PARENT_DONE"]},{"type":"chunk","time":1791518803462,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"PARENT_DONE"}}},{"type":"chunk","time":1791518803462,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":4}}},{"type":"chunk","time":1791518803462,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent worker-1 finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"CHILD_OK"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:7}}"},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":2,"step":1,"message":{"role":"assistant","content":[{"type":"text","text":"PARENT_DONE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:8}}"},"usage":{"inputTokens":10,"outputTokens":4},"stream":[{"type":"chunk","time":1792123801492,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1792123801492,"index":0,"dt":[],"texts":["PARENT_DONE"]},{"type":"chunk","time":1792123801492,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"PARENT_DONE"}}},{"type":"chunk","time":1792123801492,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":4}}},{"type":"chunk","time":1792123801492,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":2,"step":1}} {"type":"turn/end","data":{"turn":2,"reason":{"kind":"completed"}}} diff --git a/snapshots/session/subagent-no-message-tool/tool-schemas.1.expected.json b/snapshots/session/subagent-no-message-tool/tool-schemas.1.expected.json index 82664f63b2..f5492eaf89 100644 --- a/snapshots/session/subagent-no-message-tool/tool-schemas.1.expected.json +++ b/snapshots/session/subagent-no-message-tool/tool-schemas.1.expected.json @@ -143,7 +143,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -167,10 +167,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -185,6 +189,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -192,10 +197,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -210,6 +219,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/session/subagent-parallel/session.1.v4.jsonl b/snapshots/session/subagent-parallel/session.1.v4.jsonl index 5c1f90f3b7..32303e9175 100644 --- a/snapshots/session/subagent-parallel/session.1.v4.jsonl +++ b/snapshots/session/subagent-parallel/session.1.v4.jsonl @@ -3,12 +3,12 @@ {"type":"sandbox/mode","data":{"mode":"danger-full-access","source":"delegation"}} {"type":"approval/policy","data":{"policy":"never","source":"delegation"}} {"type":"permission/preset","data":{"preset":"danger-full-access"}} -{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Reply with exactly the word ALPHA and nothing else."},{"type":"text","text":"Your parent agent id is \"{{session:1}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{session:1}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:10}}"}]}} +{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Reply with exactly the word ALPHA and nothing else."},{"type":"text","text":"Your name is \"worker-1\". Your parent agent name is \"lead\". Before you finish, send your result to that agent with send_message({ name: \"lead\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:10}}"}]}} {"type":"turn/start","data":{"turn":1}} {"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":1,"step":1}} {"type":"system/message","data":{"turn":1,"step":1,"message":{"role":"system","content":[{"type":"text","text":"{{system}}"}],"source":{"kind":"system-prompt"},"id":"{{message:11}}"}},"surfaceOp":"append"} -{"type":"user/message","data":{"content":[{"type":"text","text":"Reply with exactly the word ALPHA and nothing else."},{"type":"text","text":"Your parent agent id is \"{{session:1}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{session:1}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:10}}"},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Reply with exactly the word ALPHA and nothing else."},{"type":"text","text":"Your name is \"worker-1\". Your parent agent name is \"lead\". Before you finish, send your result to that agent with send_message({ name: \"lead\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:10}}"},"surfaceOp":"append"} {"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations.\n\nApproval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).\n\nDelegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly.\n\nDelegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly.\n\nYou are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations."},{"name":"approval:policy","text":"Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."},{"name":"tool:subagent:depth","text":"Delegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly."},{"name":"tool:subagent_fork:depth","text":"Delegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly."},{"name":"subagent:delegation","text":"You are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}]},"role":"user","id":"{{message:12}}"},"surfaceOp":"append"} {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} diff --git a/snapshots/session/subagent-parallel/session.2.v4.jsonl b/snapshots/session/subagent-parallel/session.2.v4.jsonl index 41f7181dd5..20bfacf1ff 100644 --- a/snapshots/session/subagent-parallel/session.2.v4.jsonl +++ b/snapshots/session/subagent-parallel/session.2.v4.jsonl @@ -3,12 +3,12 @@ {"type":"sandbox/mode","data":{"mode":"danger-full-access","source":"delegation"}} {"type":"approval/policy","data":{"policy":"never","source":"delegation"}} {"type":"permission/preset","data":{"preset":"danger-full-access"}} -{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Reply with exactly the word ALPHA and nothing else."},{"type":"text","text":"Your parent agent id is \"{{session:1}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{session:1}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:14}}"}]}} +{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Reply with exactly the word ALPHA and nothing else."},{"type":"text","text":"Your name is \"worker-2\". Your parent agent name is \"lead\". Before you finish, send your result to that agent with send_message({ name: \"lead\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:14}}"}]}} {"type":"turn/start","data":{"turn":1}} {"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":1,"step":1}} {"type":"system/message","data":{"turn":1,"step":1,"message":{"role":"system","content":[{"type":"text","text":"{{system}}"}],"source":{"kind":"system-prompt"},"id":"{{message:15}}"}},"surfaceOp":"append"} -{"type":"user/message","data":{"content":[{"type":"text","text":"Reply with exactly the word ALPHA and nothing else."},{"type":"text","text":"Your parent agent id is \"{{session:1}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{session:1}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:14}}"},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Reply with exactly the word ALPHA and nothing else."},{"type":"text","text":"Your name is \"worker-2\". Your parent agent name is \"lead\". Before you finish, send your result to that agent with send_message({ name: \"lead\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:14}}"},"surfaceOp":"append"} {"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations.\n\nApproval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).\n\nDelegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly.\n\nDelegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly.\n\nYou are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations."},{"name":"approval:policy","text":"Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."},{"name":"tool:subagent:depth","text":"Delegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly."},{"name":"tool:subagent_fork:depth","text":"Delegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly."},{"name":"subagent:delegation","text":"You are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}]},"role":"user","id":"{{message:16}}"},"surfaceOp":"append"} {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} diff --git a/snapshots/session/subagent-parallel/session.v4.jsonl b/snapshots/session/subagent-parallel/session.v4.jsonl index c1a03460a0..bca9cb6361 100644 --- a/snapshots/session/subagent-parallel/session.v4.jsonl +++ b/snapshots/session/subagent-parallel/session.v4.jsonl @@ -12,20 +12,22 @@ {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} {"type":"session/title","data":{"title":"Use the subagent tool TWICE","messageSeqs":[8],"source":{"kind":"fallback"}}} -{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_parallel_alpha_1","name":"subagent","arguments":"{\"description\": \"Say the word ALPHA\", \"prompt\": \"Reply with exactly the word ALPHA and nothing else.\"}"},{"type":"tool-call","id":"call_parallel_alpha_2","name":"subagent","arguments":"{\"description\": \"Say the word ALPHA\", \"prompt\": \"Reply with exactly the word ALPHA and nothing else.\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"stream":[{"type":"chunk","time":1789627835748,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"chunk","time":1789627835748,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_parallel_alpha_1","name":"subagent","arguments":"{\"description\": \"Say the word ALPHA\", \"prompt\": \"Reply with exactly the word ALPHA and nothing else.\"}"}}},{"type":"chunk","time":1789627835748,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}},{"type":"chunk","time":1789627835749,"chunk":{"type":"block-end","index":1,"block":{"type":"tool-call","id":"call_parallel_alpha_2","name":"subagent","arguments":"{\"description\": \"Say the word ALPHA\", \"prompt\": \"Reply with exactly the word ALPHA and nothing else.\"}"}}},{"type":"chunk","time":1789627835749,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} -{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_parallel_alpha_1","name":"subagent","arguments":"{\"description\": \"Say the word ALPHA\", \"prompt\": \"Reply with exactly the word ALPHA and nothing else.\"}"}} -{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_parallel_alpha_2","name":"subagent","arguments":"{\"description\": \"Say the word ALPHA\", \"prompt\": \"Reply with exactly the word ALPHA and nothing else.\"}"}} -{"type":"subagent/catalog","data":{"version":0,"childId":"{{session:2}}","childCreatedAt":1789627835758,"mode":"continuable","label":"Say the word ALPHA"}} -{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_parallel_alpha_1"},"toolCallId":"call_parallel_alpha_1","content":[{"type":"text","text":"started subagent {{session:2}}"}],"isError":false,"id":"{{message:5}}"}},"sourceEventSeqs":[14],"surfaceOp":"append"} -{"type":"subagent/catalog","data":{"version":0,"childId":"{{session:3}}","childCreatedAt":1789627835779,"mode":"continuable","label":"Say the word ALPHA"}} -{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent {{session:2}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"ALPHA"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{session:2}} finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:6}}"}]}} -{"type":"agent/inbox/spliced","data":{"target":"next-step","start":1,"inserted":[{"content":[{"type":"text","text":"Background subagent {{session:3}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"ALPHA"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{session:3}} finished and will do no further work unless you send it more.","senderSessionId":"{{session:3}}"},"role":"user","id":"{{message:7}}"}]}} -{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_parallel_alpha_2"},"toolCallId":"call_parallel_alpha_2","content":[{"type":"text","text":"started subagent {{session:3}}"}],"isError":false,"id":"{{message:8}}"}},"sourceEventSeqs":[15],"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_parallel_alpha_1","name":"subagent","arguments":"{\"description\":\"Say the word ALPHA\",\"prompt\":\"Reply with exactly the word ALPHA and nothing else.\",\"name\":\"worker-1\"}"},{"type":"tool-call","id":"call_parallel_alpha_2","name":"subagent","arguments":"{\"description\":\"Say the word ALPHA\",\"prompt\":\"Reply with exactly the word ALPHA and nothing else.\",\"name\":\"worker-2\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"stream":[{"type":"chunk","time":1792123802229,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"chunk","time":1792123802229,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_parallel_alpha_1","name":"subagent","arguments":"{\"description\":\"Say the word ALPHA\",\"prompt\":\"Reply with exactly the word ALPHA and nothing else.\",\"name\":\"worker-1\"}"}}},{"type":"chunk","time":1792123802229,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}},{"type":"chunk","time":1792123802229,"chunk":{"type":"block-end","index":1,"block":{"type":"tool-call","id":"call_parallel_alpha_2","name":"subagent","arguments":"{\"description\":\"Say the word ALPHA\",\"prompt\":\"Reply with exactly the word ALPHA and nothing else.\",\"name\":\"worker-2\"}"}}},{"type":"chunk","time":1792123802229,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_parallel_alpha_1","name":"subagent","arguments":"{\"description\":\"Say the word ALPHA\",\"prompt\":\"Reply with exactly the word ALPHA and nothing else.\",\"name\":\"worker-1\"}"}} +{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_parallel_alpha_2","name":"subagent","arguments":"{\"description\":\"Say the word ALPHA\",\"prompt\":\"Reply with exactly the word ALPHA and nothing else.\",\"name\":\"worker-2\"}"}} +{"type":"subagent/catalog","data":{"version":0,"childId":"{{session:2}}","childCreatedAt":1792123802240,"mode":"continuable","label":"Say the word ALPHA"}} +{"type":"subagent/named","data":{"name":"worker-1","id":"{{session:2}}"}} +{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_parallel_alpha_1"},"toolCallId":"call_parallel_alpha_1","content":[{"type":"text","text":"started subagent worker-1"}],"isError":false,"id":"{{message:5}}"}},"sourceEventSeqs":[14],"surfaceOp":"append"} +{"type":"subagent/catalog","data":{"version":0,"childId":"{{session:3}}","childCreatedAt":1792123802259,"mode":"continuable","label":"Say the word ALPHA"}} +{"type":"subagent/named","data":{"name":"worker-2","id":"{{session:3}}"}} +{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent worker-1 finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"ALPHA"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:6}}"}]}} +{"type":"agent/inbox/spliced","data":{"target":"next-step","start":1,"inserted":[{"content":[{"type":"text","text":"Background subagent worker-2 finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"ALPHA"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-2 finished and will do no further work unless you send it more.","senderSessionId":"{{session:3}}"},"role":"user","id":"{{message:7}}"}]}} +{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_parallel_alpha_2"},"toolCallId":"call_parallel_alpha_2","content":[{"type":"text","text":"started subagent worker-2"}],"isError":false,"id":"{{message:8}}"}},"sourceEventSeqs":[15],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":1}} {"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"removedCount":2,"inserted":[]}} {"type":"step/start","data":{"turn":1,"step":2}} -{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent {{session:2}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"ALPHA"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{session:2}} finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:6}}"},"surfaceOp":"append"} -{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent {{session:3}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"ALPHA"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{session:3}} finished and will do no further work unless you send it more.","senderSessionId":"{{session:3}}"},"role":"user","id":"{{message:7}}"},"surfaceOp":"append"} -{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"text","text":"PARENT_DONE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:9}}"},"stream":[{"type":"chunk","time":1789627835863,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"chunk","time":1789627835863,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"PARENT_DONE"}}},{"type":"chunk","time":1789627835863,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent worker-1 finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"ALPHA"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:6}}"},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent worker-2 finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"ALPHA"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-2 finished and will do no further work unless you send it more.","senderSessionId":"{{session:3}}"},"role":"user","id":"{{message:7}}"},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"text","text":"PARENT_DONE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:9}}"},"stream":[{"type":"chunk","time":1792123802350,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"chunk","time":1792123802350,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"PARENT_DONE"}}},{"type":"chunk","time":1792123802350,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":2}} {"type":"turn/end","data":{"turn":1,"reason":{"kind":"completed"}}} diff --git a/snapshots/session/subagent-published-run-failure/replay.override.json b/snapshots/session/subagent-published-run-failure/replay.override.json index 9fd259ea95..8ff1b97295 100644 --- a/snapshots/session/subagent-published-run-failure/replay.override.json +++ b/snapshots/session/subagent-published-run-failure/replay.override.json @@ -2,21 +2,77 @@ { "kind": "chunks", "chunks": [ - { "type": "block-start", "index": 0, "blockType": "tool-call" }, - { "type": "tool-call-delta", "index": 0, "id": "call_published_failure", "name": "subagent", "argumentsDelta": "{\"description\":\"Fail published run\",\"prompt\":\"This child prompt must never run.\",\"run_in_background\":false}" }, - { "type": "block-end", "index": 0, "block": { "type": "tool-call", "id": "call_published_failure", "name": "subagent", "arguments": "{\"description\":\"Fail published run\",\"prompt\":\"This child prompt must never run.\",\"run_in_background\":false}" } }, - { "type": "usage", "usage": { "inputTokens": 10, "outputTokens": 5 } }, - { "type": "finish", "reason": { "kind": "tool-calls" } } + { + "type": "block-start", + "index": 0, + "blockType": "tool-call" + }, + { + "type": "tool-call-delta", + "index": 0, + "id": "call_published_failure", + "name": "subagent", + "argumentsDelta": "{\"description\":\"Fail published run\",\"prompt\":\"This child prompt must never run.\",\"run_in_background\":false,\"name\":\"worker-1\"}" + }, + { + "type": "block-end", + "index": 0, + "block": { + "type": "tool-call", + "id": "call_published_failure", + "name": "subagent", + "arguments": "{\"description\":\"Fail published run\",\"prompt\":\"This child prompt must never run.\",\"run_in_background\":false,\"name\":\"worker-1\"}" + } + }, + { + "type": "usage", + "usage": { + "inputTokens": 10, + "outputTokens": 5 + } + }, + { + "type": "finish", + "reason": { + "kind": "tool-calls" + } + } ] }, { "kind": "chunks", "chunks": [ - { "type": "block-start", "index": 0, "blockType": "text" }, - { "type": "text-delta", "index": 0, "text": "PARENT_OBSERVED_ERROR" }, - { "type": "block-end", "index": 0, "block": { "type": "text", "text": "PARENT_OBSERVED_ERROR" } }, - { "type": "usage", "usage": { "inputTokens": 10, "outputTokens": 2 } }, - { "type": "finish", "reason": { "kind": "stop" } } + { + "type": "block-start", + "index": 0, + "blockType": "text" + }, + { + "type": "text-delta", + "index": 0, + "text": "PARENT_OBSERVED_ERROR" + }, + { + "type": "block-end", + "index": 0, + "block": { + "type": "text", + "text": "PARENT_OBSERVED_ERROR" + } + }, + { + "type": "usage", + "usage": { + "inputTokens": 10, + "outputTokens": 2 + } + }, + { + "type": "finish", + "reason": { + "kind": "stop" + } + } ] } ] diff --git a/snapshots/session/subagent-published-run-failure/session.v4.jsonl b/snapshots/session/subagent-published-run-failure/session.v4.jsonl index 0ab0984a95..b347dcd49e 100644 --- a/snapshots/session/subagent-published-run-failure/session.v4.jsonl +++ b/snapshots/session/subagent-published-run-failure/session.v4.jsonl @@ -12,8 +12,8 @@ {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} {"type":"session/title","data":{"title":"Delegate one foreground subagent. Its","messageSeqs":[8],"source":{"kind":"fallback"}}} -{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_published_failure","name":"subagent","arguments":"{\"description\":\"Fail published run\",\"prompt\":\"This child prompt must never run.\",\"run_in_background\":false}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1789820433594,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1789820433594,"index":0,"dt":[],"id":"call_published_failure","name":"subagent","args":["{\"description\":\"Fail published run\",\"prompt\":\"This child prompt must never run.\",\"run_in_background\":false}"]},{"type":"chunk","time":1789820433594,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_published_failure","name":"subagent","arguments":"{\"description\":\"Fail published run\",\"prompt\":\"This child prompt must never run.\",\"run_in_background\":false}"}}},{"type":"chunk","time":1789820433594,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1789820433594,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} -{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_published_failure","name":"subagent","arguments":"{\"description\":\"Fail published run\",\"prompt\":\"This child prompt must never run.\",\"run_in_background\":false}"}} +{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_published_failure","name":"subagent","arguments":"{\"description\":\"Fail published run\",\"prompt\":\"This child prompt must never run.\",\"run_in_background\":false,\"name\":\"worker-1\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1789820433594,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1789820433594,"index":0,"dt":[],"id":"call_published_failure","name":"subagent","args":["{\"description\":\"Fail published run\",\"prompt\":\"This child prompt must never run.\",\"run_in_background\":false,\"name\":\"worker-1\"}"]},{"type":"chunk","time":1789820433594,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_published_failure","name":"subagent","arguments":"{\"description\":\"Fail published run\",\"prompt\":\"This child prompt must never run.\",\"run_in_background\":false,\"name\":\"worker-1\"}"}}},{"type":"chunk","time":1789820433594,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1789820433594,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_published_failure","name":"subagent","arguments":"{\"description\":\"Fail published run\",\"prompt\":\"This child prompt must never run.\",\"run_in_background\":false,\"name\":\"worker-1\"}"}} {"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_published_failure"},"toolCallId":"call_published_failure","content":[{"type":"text","text":"Error: snapshot published run failed"}],"isError":true,"id":"{{message:5}}"}},"sourceEventSeqs":[14],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":1}} {"type":"step/start","data":{"turn":1,"step":2}} diff --git a/snapshots/session/subagent-spawn-in-process/session.1.v4.jsonl b/snapshots/session/subagent-spawn-in-process/session.1.v4.jsonl index 26e4d68b88..081d0d91fd 100644 --- a/snapshots/session/subagent-spawn-in-process/session.1.v4.jsonl +++ b/snapshots/session/subagent-spawn-in-process/session.1.v4.jsonl @@ -3,12 +3,12 @@ {"type":"sandbox/mode","data":{"mode":"danger-full-access","source":"delegation"}} {"type":"approval/policy","data":{"policy":"never","source":"delegation"}} {"type":"permission/preset","data":{"preset":"danger-full-access"}} -{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Reply with exactly the word CHILD_OK and nothing else."},{"type":"text","text":"Your parent agent id is \"{{session:1}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{session:1}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:9}}"}]}} +{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Reply with exactly the word CHILD_OK and nothing else."},{"type":"text","text":"Your name is \"worker-1\". Your parent agent name is \"lead\". Before you finish, send your result to that agent with send_message({ name: \"lead\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:9}}"}]}} {"type":"turn/start","data":{"turn":1}} {"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":1,"step":1}} {"type":"system/message","data":{"turn":1,"step":1,"message":{"role":"system","content":[{"type":"text","text":"{{system}}"}],"source":{"kind":"system-prompt"},"id":"{{message:10}}"}},"surfaceOp":"append"} -{"type":"user/message","data":{"content":[{"type":"text","text":"Reply with exactly the word CHILD_OK and nothing else."},{"type":"text","text":"Your parent agent id is \"{{session:1}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{session:1}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:9}}"},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Reply with exactly the word CHILD_OK and nothing else."},{"type":"text","text":"Your name is \"worker-1\". Your parent agent name is \"lead\". Before you finish, send your result to that agent with send_message({ name: \"lead\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:9}}"},"surfaceOp":"append"} {"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations.\n\nApproval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).\n\nDelegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly.\n\nDelegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly.\n\nYou are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations."},{"name":"approval:policy","text":"Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."},{"name":"tool:subagent:depth","text":"Delegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly."},{"name":"tool:subagent_fork:depth","text":"Delegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly."},{"name":"subagent:delegation","text":"You are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}]},"role":"user","id":"{{message:11}}"},"surfaceOp":"append"} {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} diff --git a/snapshots/session/subagent-spawn-in-process/session.v4.jsonl b/snapshots/session/subagent-spawn-in-process/session.v4.jsonl index b15bf3470c..fa4afac93c 100644 --- a/snapshots/session/subagent-spawn-in-process/session.v4.jsonl +++ b/snapshots/session/subagent-spawn-in-process/session.v4.jsonl @@ -12,20 +12,21 @@ {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} {"type":"session/title","data":{"title":"Use the subagent tool exactly","messageSeqs":[8],"source":{"kind":"fallback"}}} -{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"reasoning","text":"The user wants me to:\n1. Use the subagent tool exactly once to delegate the task: \"Reply with exactly the word CHILD_OK and nothing else.\"\n2. After the subagent returns, reply with the single word PARENT_DONE and stop.\n3. Do not use the bash tool.\n\nLet me do this."},{"type":"tool-call","id":"call_00_gVbLWC12Qu8JheZpVRRz8749","name":"subagent","arguments":"{\"description\": \"Reply with CHILD_OK\", \"prompt\": \"Reply with exactly the word CHILD_OK and nothing else.\", \"run_in_background\":false}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":2907,"outputTokens":142,"cacheReadTokens":0,"reasoningTokens":67},"stream":[{"type":"chunk","time":1789625684752,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1789625684752,"index":0,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"texts":["The"," user"," wants"," me"," to",":\n","1","."," Use"," the"," sub","agent"," tool"," exactly"," once"," to"," delegate"," the"," task",":"," \"","Reply"," with"," exactly"," the"," word"," CH","ILD","_OK"," and"," nothing"," else",".\"\n","2","."," After"," the"," sub","agent"," returns",","," reply"," with"," the"," single"," word"," PAR","ENT","_D","ONE"," and"," stop",".\n","3","."," Do"," not"," use"," the"," bash"," tool",".\n\n","Let"," me"," do"," this","."]},{"type":"chunk","time":1789625684753,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1789625684753,"index":1,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"id":"call_00_gVbLWC12Qu8JheZpVRRz8749","name":"subagent","args":["","{","\"","description","\"",": ","\"","Reply"," with"," CH","ILD","_OK","\"",", ","\"","prom","pt","\"",": ","\"","Reply"," with"," exactly"," the"," word"," CH","ILD","_OK"," and"," nothing"," else",".","\"",", \"run_in_background\":false}"]},{"type":"chunk","time":1789625684753,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The user wants me to:\n1. Use the subagent tool exactly once to delegate the task: \"Reply with exactly the word CHILD_OK and nothing else.\"\n2. After the subagent returns, reply with the single word PARENT_DONE and stop.\n3. Do not use the bash tool.\n\nLet me do this."}}},{"type":"chunk","time":1789625684753,"chunk":{"type":"block-end","index":1,"block":{"type":"tool-call","id":"call_00_gVbLWC12Qu8JheZpVRRz8749","name":"subagent","arguments":"{\"description\": \"Reply with CHILD_OK\", \"prompt\": \"Reply with exactly the word CHILD_OK and nothing else.\", \"run_in_background\":false}"}}},{"type":"chunk","time":1789625684753,"chunk":{"type":"usage","usage":{"inputTokens":2907,"outputTokens":142,"cacheReadTokens":0,"reasoningTokens":67}}},{"type":"chunk","time":1789625684753,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} -{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_00_gVbLWC12Qu8JheZpVRRz8749","name":"subagent","arguments":"{\"description\": \"Reply with CHILD_OK\", \"prompt\": \"Reply with exactly the word CHILD_OK and nothing else.\", \"run_in_background\":false}"}} -{"type":"subagent/catalog","data":{"version":0,"childId":"{{session:2}}","childCreatedAt":1789625684760,"mode":"continuable","label":"Reply with CHILD_OK"}} -{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_00_gVbLWC12Qu8JheZpVRRz8749"},"toolCallId":"call_00_gVbLWC12Qu8JheZpVRRz8749","content":[{"type":"text","text":"started subagent {{session:2}}"}],"isError":false,"id":"{{message:5}}"}},"sourceEventSeqs":[14],"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"reasoning","text":"The user wants me to:\n1. Use the subagent tool exactly once to delegate the task: \"Reply with exactly the word CHILD_OK and nothing else.\"\n2. After the subagent returns, reply with the single word PARENT_DONE and stop.\n3. Do not use the bash tool.\n\nLet me do this."},{"type":"tool-call","id":"call_00_gVbLWC12Qu8JheZpVRRz8749","name":"subagent","arguments":"{\"description\":\"Reply with CHILD_OK\",\"prompt\":\"Reply with exactly the word CHILD_OK and nothing else.\",\"run_in_background\":false,\"name\":\"worker-1\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":2907,"outputTokens":142,"cacheReadTokens":0,"reasoningTokens":67},"stream":[{"type":"chunk","time":1792123803903,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1792123803903,"index":0,"dt":[0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"texts":["The"," user"," wants"," me"," to",":\n","1","."," Use"," the"," sub","agent"," tool"," exactly"," once"," to"," delegate"," the"," task",":"," \"","Reply"," with"," exactly"," the"," word"," CH","ILD","_OK"," and"," nothing"," else",".\"\n","2","."," After"," the"," sub","agent"," returns",","," reply"," with"," the"," single"," word"," PAR","ENT","_D","ONE"," and"," stop",".\n","3","."," Do"," not"," use"," the"," bash"," tool",".\n\n","Let"," me"," do"," this","."]},{"type":"chunk","time":1792123803904,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792123803904,"index":1,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"id":"call_00_gVbLWC12Qu8JheZpVRRz8749","name":"subagent","args":["{\"description\":\"Reply with CHILD_OK\",\"prompt\":\"Reply with exactly the word CHILD_OK and nothing else.\",\"run_in_background\":false,\"name\":\"worker-1\"}","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""]},{"type":"chunk","time":1792123803904,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The user wants me to:\n1. Use the subagent tool exactly once to delegate the task: \"Reply with exactly the word CHILD_OK and nothing else.\"\n2. After the subagent returns, reply with the single word PARENT_DONE and stop.\n3. Do not use the bash tool.\n\nLet me do this."}}},{"type":"chunk","time":1792123803904,"chunk":{"type":"block-end","index":1,"block":{"type":"tool-call","id":"call_00_gVbLWC12Qu8JheZpVRRz8749","name":"subagent","arguments":"{\"description\":\"Reply with CHILD_OK\",\"prompt\":\"Reply with exactly the word CHILD_OK and nothing else.\",\"run_in_background\":false,\"name\":\"worker-1\"}"}}},{"type":"chunk","time":1792123803904,"chunk":{"type":"usage","usage":{"inputTokens":2907,"outputTokens":142,"cacheReadTokens":0,"reasoningTokens":67}}},{"type":"chunk","time":1792123803904,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_00_gVbLWC12Qu8JheZpVRRz8749","name":"subagent","arguments":"{\"description\":\"Reply with CHILD_OK\",\"prompt\":\"Reply with exactly the word CHILD_OK and nothing else.\",\"run_in_background\":false,\"name\":\"worker-1\"}"}} +{"type":"subagent/catalog","data":{"version":0,"childId":"{{session:2}}","childCreatedAt":1792123803911,"mode":"continuable","label":"Reply with CHILD_OK"}} +{"type":"subagent/named","data":{"name":"worker-1","id":"{{session:2}}"}} +{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_00_gVbLWC12Qu8JheZpVRRz8749"},"toolCallId":"call_00_gVbLWC12Qu8JheZpVRRz8749","content":[{"type":"text","text":"started subagent worker-1"}],"isError":false,"id":"{{message:5}}"}},"sourceEventSeqs":[14],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":1}} {"type":"step/start","data":{"turn":1,"step":2}} -{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"reasoning","text":"The subagent returned \"CHILD_OK\" as expected. Now I need to reply with the single word \"PARENT_DONE\" and stop."},{"type":"text","text":"PARENT_DONE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:6}}"},"usage":{"inputTokens":120,"outputTokens":35,"cacheReadTokens":2944,"reasoningTokens":30},"stream":[{"type":"chunk","time":1789625684789,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1789625684789,"index":0,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"texts":["The"," sub","agent"," returned"," \"","CH","ILD","_OK","\""," as"," expected","."," Now"," I"," need"," to"," reply"," with"," the"," single"," word"," \"","PAR","ENT","_D","ONE","\""," and"," stop","."]},{"type":"chunk","time":1789625684789,"chunk":{"type":"block-start","index":1,"blockType":"text"}},{"type":"text-chunks","time0":1789625684789,"index":1,"dt":[0,0,0],"texts":["PAR","ENT","_D","ONE"]},{"type":"chunk","time":1789625684789,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The subagent returned \"CHILD_OK\" as expected. Now I need to reply with the single word \"PARENT_DONE\" and stop."}}},{"type":"chunk","time":1789625684789,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"PARENT_DONE"}}},{"type":"chunk","time":1789625684789,"chunk":{"type":"usage","usage":{"inputTokens":120,"outputTokens":35,"cacheReadTokens":2944,"reasoningTokens":30}}},{"type":"chunk","time":1789625684789,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"reasoning","text":"The subagent returned \"CHILD_OK\" as expected. Now I need to reply with the single word \"PARENT_DONE\" and stop."},{"type":"text","text":"PARENT_DONE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:6}}"},"usage":{"inputTokens":120,"outputTokens":35,"cacheReadTokens":2944,"reasoningTokens":30},"stream":[{"type":"chunk","time":1792123803950,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1792123803950,"index":0,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"texts":["The"," sub","agent"," returned"," \"","CH","ILD","_OK","\""," as"," expected","."," Now"," I"," need"," to"," reply"," with"," the"," single"," word"," \"","PAR","ENT","_D","ONE","\""," and"," stop","."]},{"type":"chunk","time":1792123803950,"chunk":{"type":"block-start","index":1,"blockType":"text"}},{"type":"text-chunks","time0":1792123803950,"index":1,"dt":[0,0,0],"texts":["PAR","ENT","_D","ONE"]},{"type":"chunk","time":1792123803950,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The subagent returned \"CHILD_OK\" as expected. Now I need to reply with the single word \"PARENT_DONE\" and stop."}}},{"type":"chunk","time":1792123803950,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"PARENT_DONE"}}},{"type":"chunk","time":1792123803950,"chunk":{"type":"usage","usage":{"inputTokens":120,"outputTokens":35,"cacheReadTokens":2944,"reasoningTokens":30}}},{"type":"chunk","time":1792123803950,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":2}} {"type":"turn/end","data":{"turn":1,"reason":{"kind":"completed"}}} -{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent {{session:2}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"CHILD_OK"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{session:2}} finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:7}}"}]}} +{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent worker-1 finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"CHILD_OK"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:7}}"}]}} {"type":"turn/start","data":{"turn":2}} {"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":2,"step":1}} -{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent {{session:2}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"CHILD_OK"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{session:2}} finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:7}}"},"surfaceOp":"append"} -{"type":"assistant/message","data":{"turn":2,"step":1,"message":{"role":"assistant","content":[{"type":"text","text":"PARENT_DONE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:8}}"},"usage":{"inputTokens":10,"outputTokens":4},"stream":[{"type":"chunk","time":1789625684823,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1789625684823,"index":0,"dt":[],"texts":["PARENT_DONE"]},{"type":"chunk","time":1789625684823,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"PARENT_DONE"}}},{"type":"chunk","time":1789625684823,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":4}}},{"type":"chunk","time":1789625684823,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent worker-1 finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"CHILD_OK"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:7}}"},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":2,"step":1,"message":{"role":"assistant","content":[{"type":"text","text":"PARENT_DONE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:8}}"},"usage":{"inputTokens":10,"outputTokens":4},"stream":[{"type":"chunk","time":1792123803974,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1792123803974,"index":0,"dt":[],"texts":["PARENT_DONE"]},{"type":"chunk","time":1792123803974,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"PARENT_DONE"}}},{"type":"chunk","time":1792123803974,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":4}}},{"type":"chunk","time":1792123803974,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":2,"step":1}} {"type":"turn/end","data":{"turn":2,"reason":{"kind":"completed"}}} diff --git a/snapshots/session/subagent-structured-parent/session.1.v4.jsonl b/snapshots/session/subagent-structured-parent/session.1.v4.jsonl index 5bb06dd525..1ed587993c 100644 --- a/snapshots/session/subagent-structured-parent/session.1.v4.jsonl +++ b/snapshots/session/subagent-structured-parent/session.1.v4.jsonl @@ -3,24 +3,24 @@ {"type":"sandbox/mode","data":{"mode":"danger-full-access","source":"delegation"}} {"type":"approval/policy","data":{"policy":"never","source":"delegation"}} {"type":"permission/preset","data":{"preset":"danger-full-access"}} -{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Submit answer 41 through structured_output."},{"type":"text","text":"Your parent agent id is \"{{session:1}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{session:1}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:8}}"}]}} +{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Submit answer 41 through structured_output."},{"type":"text","text":"Your name is \"structured-child\". Your parent agent name is \"lead\". Before you finish, send your result to that agent with send_message({ name: \"lead\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:8}}"}]}} {"type":"turn/start","data":{"turn":1}} {"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":1,"step":1}} {"type":"system/message","data":{"turn":1,"step":1,"message":{"role":"system","content":[{"type":"text","text":"{{system}}"}],"source":{"kind":"system-prompt"},"id":"{{message:9}}"}},"surfaceOp":"append"} -{"type":"user/message","data":{"content":[{"type":"text","text":"Submit answer 41 through structured_output."},{"type":"text","text":"Your parent agent id is \"{{session:1}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{session:1}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:8}}"},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Submit answer 41 through structured_output."},{"type":"text","text":"Your name is \"structured-child\". Your parent agent name is \"lead\". Before you finish, send your result to that agent with send_message({ name: \"lead\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:8}}"},"surfaceOp":"append"} {"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations.\n\nApproval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).\n\nDelegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly.\n\nDelegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly.\n\nYou are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations."},{"name":"approval:policy","text":"Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."},{"name":"tool:subagent:depth","text":"Delegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly."},{"name":"tool:subagent_fork:depth","text":"Delegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly."},{"name":"subagent:delegation","text":"You are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}]},"role":"user","id":"{{message:10}}"},"surfaceOp":"append"} {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} {"type":"session/title","data":{"title":"Submit answer 41 through structured_outp","messageSeqs":[9],"source":{"kind":"fallback"}}} {"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_structured_answer","name":"structured_output","arguments":"{\"answer\":41}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:11}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":0,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"chunk","time":0,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_structured_answer","name":"structured_output","arguments":"{\"answer\":41}"}}},{"type":"chunk","time":0,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":0,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} {"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_structured_answer","name":"structured_output","arguments":"{\"answer\":41}"}} -{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Agent {{session:1}} sent a message: "},{"type":"text","text":"Correction: submit answer 42 instead."}],"source":{"kind":"agent-message","form":"relay","senderSessionId":"{{session:1}}"},"role":"user","id":"{{message:12}}"}]}} +{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Agent lead sent a message: "},{"type":"text","text":"Correction: submit answer 42 instead."}],"source":{"kind":"agent-message","form":"relay","senderSessionId":"{{session:1}}"},"role":"user","id":"{{message:12}}"}]}} {"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_structured_answer"},"toolCallId":"call_structured_answer","content":[{"type":"text","text":"Error: Wait for all delegated child tasks to finish and process pending messages before submitting structured output."}],"isError":true,"id":"{{message:13}}"}},"sourceEventSeqs":[15],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":1}} {"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":1,"step":2}} -{"type":"user/message","data":{"content":[{"type":"text","text":"Agent {{session:1}} sent a message: "},{"type":"text","text":"Correction: submit answer 42 instead."}],"source":{"kind":"agent-message","form":"relay","senderSessionId":"{{session:1}}"},"role":"user","id":"{{message:12}}"},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Agent lead sent a message: "},{"type":"text","text":"Correction: submit answer 42 instead."}],"source":{"kind":"agent-message","form":"relay","senderSessionId":"{{session:1}}"},"role":"user","id":"{{message:12}}"},"surfaceOp":"append"} {"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_corrected_answer","name":"structured_output","arguments":"{\"answer\":42}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:14}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":0,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"chunk","time":0,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_corrected_answer","name":"structured_output","arguments":"{\"answer\":42}"}}},{"type":"chunk","time":0,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":0,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} {"type":"tool/call","data":{"turn":1,"step":2,"callId":"call_corrected_answer","name":"structured_output","arguments":"{\"answer\":42}"}} {"type":"tool/result","data":{"turn":1,"step":2,"message":{"role":"tool","source":{"kind":"tool","callId":"call_corrected_answer"},"toolCallId":"call_corrected_answer","content":[{"type":"text","text":"Structured output recorded."}],"isError":false,"id":"{{message:15}}"}},"sourceEventSeqs":[23],"surfaceOp":"append"} diff --git a/snapshots/session/subagent-structured-parent/session.v4.jsonl b/snapshots/session/subagent-structured-parent/session.v4.jsonl index 0b7112e2de..77876e3e2c 100644 --- a/snapshots/session/subagent-structured-parent/session.v4.jsonl +++ b/snapshots/session/subagent-structured-parent/session.v4.jsonl @@ -12,15 +12,16 @@ {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} {"type":"session/title","data":{"title":"Use the subagent tool exactly","messageSeqs":[8],"source":{"kind":"fallback"}}} -{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_structured_child","name":"subagent_structured","arguments":"{}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1789978499294,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"chunk","time":1789978499294,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_structured_child","name":"subagent_structured","arguments":"{}"}}},{"type":"chunk","time":1789978499294,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1789978499294,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call_structured_child","name":"subagent_structured","arguments":"{}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1792123804759,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"chunk","time":1792123804759,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call_structured_child","name":"subagent_structured","arguments":"{}"}}},{"type":"chunk","time":1792123804759,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1792123804759,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} {"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_structured_child","name":"subagent_structured","arguments":"{}"}} -{"type":"subagent/catalog","data":{"version":0,"childId":"{{session:2}}","childCreatedAt":1789978499299,"mode":"continuable","label":"Structured answer"}} -{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent {{session:2}} finished and will do no further work unless you send it more."},{"type":"text","text":"It left no closing message."},{"type":"text","text":"Structured result: {\"answer\":42}"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{session:2}} finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:5}}"}]}} +{"type":"subagent/catalog","data":{"version":0,"childId":"{{session:2}}","childCreatedAt":1792123804765,"mode":"continuable","label":"Structured answer"}} +{"type":"subagent/named","data":{"name":"structured-child","id":"{{session:2}}"}} +{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent structured-child finished and will do no further work unless you send it more."},{"type":"text","text":"It left no closing message."},{"type":"text","text":"Structured result: {\"answer\":42}"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent structured-child finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:5}}"}]}} {"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_structured_child"},"toolCallId":"call_structured_child","content":[{"type":"text","text":"Child {{session:2}} settled."}],"isError":false,"id":"{{message:6}}"}},"sourceEventSeqs":[14],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":1}} {"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":1,"step":2}} -{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent {{session:2}} finished and will do no further work unless you send it more."},{"type":"text","text":"It left no closing message."},{"type":"text","text":"Structured result: {\"answer\":42}"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{session:2}} finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:5}}"},"surfaceOp":"append"} -{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"text","text":"PARENT_RECEIVED_42"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:7}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1789978499358,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"chunk","time":1789978499358,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"PARENT_RECEIVED_42"}}},{"type":"chunk","time":1789978499358,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1789978499358,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent structured-child finished and will do no further work unless you send it more."},{"type":"text","text":"It left no closing message."},{"type":"text","text":"Structured result: {\"answer\":42}"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent structured-child finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:5}}"},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"text","text":"PARENT_RECEIVED_42"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:7}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":1792123804843,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"chunk","time":1792123804843,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"PARENT_RECEIVED_42"}}},{"type":"chunk","time":1792123804843,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":1792123804843,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":2}} {"type":"turn/end","data":{"turn":1,"reason":{"kind":"completed"}}} diff --git a/snapshots/session/subagent-structured-parent/tool-schemas.1.expected.json b/snapshots/session/subagent-structured-parent/tool-schemas.1.expected.json index 3ed127e8d8..9aaf7bb6d5 100644 --- a/snapshots/session/subagent-structured-parent/tool-schemas.1.expected.json +++ b/snapshots/session/subagent-structured-parent/tool-schemas.1.expected.json @@ -181,13 +181,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -245,7 +245,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -297,9 +297,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -307,7 +307,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -345,10 +345,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -363,6 +367,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -370,10 +375,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -388,6 +397,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/session/subagent-structured-parent/tool-schemas.expected.json b/snapshots/session/subagent-structured-parent/tool-schemas.expected.json index 15b0f8b29d..03c0bdef2a 100644 --- a/snapshots/session/subagent-structured-parent/tool-schemas.expected.json +++ b/snapshots/session/subagent-structured-parent/tool-schemas.expected.json @@ -181,13 +181,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -245,7 +245,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -297,9 +297,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -307,7 +307,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -330,10 +330,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -348,6 +352,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -355,10 +360,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -373,6 +382,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/session/subagent-tool-filter/session.1.v4.jsonl b/snapshots/session/subagent-tool-filter/session.1.v4.jsonl index 707ac3e55d..4c8b714d20 100644 --- a/snapshots/session/subagent-tool-filter/session.1.v4.jsonl +++ b/snapshots/session/subagent-tool-filter/session.1.v4.jsonl @@ -4,12 +4,12 @@ {"type":"sandbox/mode","data":{"mode":"danger-full-access","source":"delegation"}} {"type":"approval/policy","data":{"policy":"never","source":"delegation"}} {"type":"permission/preset","data":{"preset":"danger-full-access"}} -{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Reply with exactly the word CHILD_OK and nothing else."},{"type":"text","text":"Your parent agent id is \"{{session:1}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{session:1}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:9}}"}]}} +{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Reply with exactly the word CHILD_OK and nothing else."},{"type":"text","text":"Your name is \"worker-1\". Your parent agent name is \"lead\". Before you finish, send your result to that agent with send_message({ name: \"lead\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:9}}"}]}} {"type":"turn/start","data":{"turn":1}} {"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":1,"step":1}} {"type":"system/message","data":{"turn":1,"step":1,"message":{"role":"system","content":[{"type":"text","text":"{{system}}"}],"source":{"kind":"system-prompt"},"id":"{{message:10}}"}},"surfaceOp":"append"} -{"type":"user/message","data":{"content":[{"type":"text","text":"Reply with exactly the word CHILD_OK and nothing else."},{"type":"text","text":"Your parent agent id is \"{{session:1}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{session:1}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:9}}"},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Reply with exactly the word CHILD_OK and nothing else."},{"type":"text","text":"Your name is \"worker-1\". Your parent agent name is \"lead\". Before you finish, send your result to that agent with send_message({ name: \"lead\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:9}}"},"surfaceOp":"append"} {"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations.\n\nApproval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).\n\nDelegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly.\n\nDelegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly.\n\nYou are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations."},{"name":"approval:policy","text":"Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."},{"name":"tool:subagent_fork:depth","text":"Delegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly."},{"name":"tool:subagent:depth","text":"Delegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly."},{"name":"subagent:delegation","text":"You are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}]},"role":"user","id":"{{message:11}}"},"surfaceOp":"append"} {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} diff --git a/snapshots/session/subagent-tool-filter/session.v4.jsonl b/snapshots/session/subagent-tool-filter/session.v4.jsonl index 412aba1557..a901f0e6e6 100644 --- a/snapshots/session/subagent-tool-filter/session.v4.jsonl +++ b/snapshots/session/subagent-tool-filter/session.v4.jsonl @@ -13,20 +13,21 @@ {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} {"type":"session/title","data":{"title":"Use the subagent tool exactly","messageSeqs":[9],"source":{"kind":"fallback"}}} -{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"reasoning","text":"The user wants me to:\n1. Use the subagent tool exactly once to delegate the task: \"Reply with exactly the word CHILD_OK and nothing else.\"\n2. After the subagent returns, reply with the single word PARENT_DONE and stop.\n3. Do not use the bash tool.\n\nLet me do this."},{"type":"tool-call","id":"call_00_gVbLWC12Qu8JheZpVRRz8749","name":"subagent","arguments":"{\"description\": \"Reply with CHILD_OK\", \"prompt\": \"Reply with exactly the word CHILD_OK and nothing else.\", \"run_in_background\":false}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":2907,"outputTokens":142,"cacheReadTokens":0,"reasoningTokens":67},"stream":[{"type":"chunk","time":1791518804298,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1791518804298,"index":0,"dt":[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"texts":["The"," user"," wants"," me"," to",":\n","1","."," Use"," the"," sub","agent"," tool"," exactly"," once"," to"," delegate"," the"," task",":"," \"","Reply"," with"," exactly"," the"," word"," CH","ILD","_OK"," and"," nothing"," else",".\"\n","2","."," After"," the"," sub","agent"," returns",","," reply"," with"," the"," single"," word"," PAR","ENT","_D","ONE"," and"," stop",".\n","3","."," Do"," not"," use"," the"," bash"," tool",".\n\n","Let"," me"," do"," this","."]},{"type":"chunk","time":1791518804299,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1791518804299,"index":1,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],"id":"call_00_gVbLWC12Qu8JheZpVRRz8749","name":"subagent","args":["","{","\"","description","\"",": ","\"","Reply"," with"," CH","ILD","_OK","\"",", ","\"","prom","pt","\"",": ","\"","Reply"," with"," exactly"," the"," word"," CH","ILD","_OK"," and"," nothing"," else",".","\"",", \"run_in_background\":false}"]},{"type":"chunk","time":1791518804300,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The user wants me to:\n1. Use the subagent tool exactly once to delegate the task: \"Reply with exactly the word CHILD_OK and nothing else.\"\n2. After the subagent returns, reply with the single word PARENT_DONE and stop.\n3. Do not use the bash tool.\n\nLet me do this."}}},{"type":"chunk","time":1791518804300,"chunk":{"type":"block-end","index":1,"block":{"type":"tool-call","id":"call_00_gVbLWC12Qu8JheZpVRRz8749","name":"subagent","arguments":"{\"description\": \"Reply with CHILD_OK\", \"prompt\": \"Reply with exactly the word CHILD_OK and nothing else.\", \"run_in_background\":false}"}}},{"type":"chunk","time":1791518804300,"chunk":{"type":"usage","usage":{"inputTokens":2907,"outputTokens":142,"cacheReadTokens":0,"reasoningTokens":67}}},{"type":"chunk","time":1791518804300,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} -{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_00_gVbLWC12Qu8JheZpVRRz8749","name":"subagent","arguments":"{\"description\": \"Reply with CHILD_OK\", \"prompt\": \"Reply with exactly the word CHILD_OK and nothing else.\", \"run_in_background\":false}"}} -{"type":"subagent/catalog","data":{"version":0,"childId":"{{session:2}}","childCreatedAt":1791518804307,"mode":"continuable","label":"Reply with CHILD_OK"}} -{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_00_gVbLWC12Qu8JheZpVRRz8749"},"toolCallId":"call_00_gVbLWC12Qu8JheZpVRRz8749","content":[{"type":"text","text":"started subagent {{session:2}}"}],"isError":false,"id":"{{message:5}}"}},"sourceEventSeqs":[15],"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"reasoning","text":"The user wants me to:\n1. Use the subagent tool exactly once to delegate the task: \"Reply with exactly the word CHILD_OK and nothing else.\"\n2. After the subagent returns, reply with the single word PARENT_DONE and stop.\n3. Do not use the bash tool.\n\nLet me do this."},{"type":"tool-call","id":"call_00_gVbLWC12Qu8JheZpVRRz8749","name":"subagent","arguments":"{\"description\":\"Reply with CHILD_OK\",\"prompt\":\"Reply with exactly the word CHILD_OK and nothing else.\",\"run_in_background\":false,\"name\":\"worker-1\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":2907,"outputTokens":142,"cacheReadTokens":0,"reasoningTokens":67},"stream":[{"type":"chunk","time":1792123805603,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1792123805603,"index":0,"dt":[0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"texts":["The"," user"," wants"," me"," to",":\n","1","."," Use"," the"," sub","agent"," tool"," exactly"," once"," to"," delegate"," the"," task",":"," \"","Reply"," with"," exactly"," the"," word"," CH","ILD","_OK"," and"," nothing"," else",".\"\n","2","."," After"," the"," sub","agent"," returns",","," reply"," with"," the"," single"," word"," PAR","ENT","_D","ONE"," and"," stop",".\n","3","."," Do"," not"," use"," the"," bash"," tool",".\n\n","Let"," me"," do"," this","."]},{"type":"chunk","time":1792123805604,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792123805604,"index":1,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"id":"call_00_gVbLWC12Qu8JheZpVRRz8749","name":"subagent","args":["{\"description\":\"Reply with CHILD_OK\",\"prompt\":\"Reply with exactly the word CHILD_OK and nothing else.\",\"run_in_background\":false,\"name\":\"worker-1\"}","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""]},{"type":"chunk","time":1792123805604,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The user wants me to:\n1. Use the subagent tool exactly once to delegate the task: \"Reply with exactly the word CHILD_OK and nothing else.\"\n2. After the subagent returns, reply with the single word PARENT_DONE and stop.\n3. Do not use the bash tool.\n\nLet me do this."}}},{"type":"chunk","time":1792123805604,"chunk":{"type":"block-end","index":1,"block":{"type":"tool-call","id":"call_00_gVbLWC12Qu8JheZpVRRz8749","name":"subagent","arguments":"{\"description\":\"Reply with CHILD_OK\",\"prompt\":\"Reply with exactly the word CHILD_OK and nothing else.\",\"run_in_background\":false,\"name\":\"worker-1\"}"}}},{"type":"chunk","time":1792123805604,"chunk":{"type":"usage","usage":{"inputTokens":2907,"outputTokens":142,"cacheReadTokens":0,"reasoningTokens":67}}},{"type":"chunk","time":1792123805604,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":1,"callId":"call_00_gVbLWC12Qu8JheZpVRRz8749","name":"subagent","arguments":"{\"description\":\"Reply with CHILD_OK\",\"prompt\":\"Reply with exactly the word CHILD_OK and nothing else.\",\"run_in_background\":false,\"name\":\"worker-1\"}"}} +{"type":"subagent/catalog","data":{"version":0,"childId":"{{session:2}}","childCreatedAt":1792123805613,"mode":"continuable","label":"Reply with CHILD_OK"}} +{"type":"subagent/named","data":{"name":"worker-1","id":"{{session:2}}"}} +{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"call_00_gVbLWC12Qu8JheZpVRRz8749"},"toolCallId":"call_00_gVbLWC12Qu8JheZpVRRz8749","content":[{"type":"text","text":"started subagent worker-1"}],"isError":false,"id":"{{message:5}}"}},"sourceEventSeqs":[15],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":1}} {"type":"step/start","data":{"turn":1,"step":2}} -{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"reasoning","text":"The subagent returned \"CHILD_OK\" as expected. Now I need to reply with the single word \"PARENT_DONE\" and stop."},{"type":"text","text":"PARENT_DONE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:6}}"},"usage":{"inputTokens":120,"outputTokens":35,"cacheReadTokens":2944,"reasoningTokens":30},"stream":[{"type":"chunk","time":1791518804337,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1791518804337,"index":0,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"texts":["The"," sub","agent"," returned"," \"","CH","ILD","_OK","\""," as"," expected","."," Now"," I"," need"," to"," reply"," with"," the"," single"," word"," \"","PAR","ENT","_D","ONE","\""," and"," stop","."]},{"type":"chunk","time":1791518804337,"chunk":{"type":"block-start","index":1,"blockType":"text"}},{"type":"text-chunks","time0":1791518804337,"index":1,"dt":[0,0,0],"texts":["PAR","ENT","_D","ONE"]},{"type":"chunk","time":1791518804337,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The subagent returned \"CHILD_OK\" as expected. Now I need to reply with the single word \"PARENT_DONE\" and stop."}}},{"type":"chunk","time":1791518804337,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"PARENT_DONE"}}},{"type":"chunk","time":1791518804337,"chunk":{"type":"usage","usage":{"inputTokens":120,"outputTokens":35,"cacheReadTokens":2944,"reasoningTokens":30}}},{"type":"chunk","time":1791518804337,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"reasoning","text":"The subagent returned \"CHILD_OK\" as expected. Now I need to reply with the single word \"PARENT_DONE\" and stop."},{"type":"text","text":"PARENT_DONE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:6}}"},"usage":{"inputTokens":120,"outputTokens":35,"cacheReadTokens":2944,"reasoningTokens":30},"stream":[{"type":"chunk","time":1792123805651,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1792123805651,"index":0,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"texts":["The"," sub","agent"," returned"," \"","CH","ILD","_OK","\""," as"," expected","."," Now"," I"," need"," to"," reply"," with"," the"," single"," word"," \"","PAR","ENT","_D","ONE","\""," and"," stop","."]},{"type":"chunk","time":1792123805651,"chunk":{"type":"block-start","index":1,"blockType":"text"}},{"type":"text-chunks","time0":1792123805651,"index":1,"dt":[0,0,0],"texts":["PAR","ENT","_D","ONE"]},{"type":"chunk","time":1792123805651,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The subagent returned \"CHILD_OK\" as expected. Now I need to reply with the single word \"PARENT_DONE\" and stop."}}},{"type":"chunk","time":1792123805651,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"PARENT_DONE"}}},{"type":"chunk","time":1792123805651,"chunk":{"type":"usage","usage":{"inputTokens":120,"outputTokens":35,"cacheReadTokens":2944,"reasoningTokens":30}}},{"type":"chunk","time":1792123805651,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":2}} {"type":"turn/end","data":{"turn":1,"reason":{"kind":"completed"}}} -{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent {{session:2}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"CHILD_OK"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{session:2}} finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:7}}"}]}} +{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent worker-1 finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"CHILD_OK"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:7}}"}]}} {"type":"turn/start","data":{"turn":2}} {"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":2,"step":1}} -{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent {{session:2}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"CHILD_OK"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{session:2}} finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:7}}"},"surfaceOp":"append"} -{"type":"assistant/message","data":{"turn":2,"step":1,"message":{"role":"assistant","content":[{"type":"text","text":"PARENT_DONE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:8}}"},"usage":{"inputTokens":10,"outputTokens":4},"stream":[{"type":"chunk","time":1791518804391,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1791518804391,"index":0,"dt":[],"texts":["PARENT_DONE"]},{"type":"chunk","time":1791518804391,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"PARENT_DONE"}}},{"type":"chunk","time":1791518804391,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":4}}},{"type":"chunk","time":1791518804391,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent worker-1 finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"CHILD_OK"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent worker-1 finished and will do no further work unless you send it more.","senderSessionId":"{{session:2}}"},"role":"user","id":"{{message:7}}"},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":2,"step":1,"message":{"role":"assistant","content":[{"type":"text","text":"PARENT_DONE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:8}}"},"usage":{"inputTokens":10,"outputTokens":4},"stream":[{"type":"chunk","time":1792123805692,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1792123805692,"index":0,"dt":[],"texts":["PARENT_DONE"]},{"type":"chunk","time":1792123805692,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"PARENT_DONE"}}},{"type":"chunk","time":1792123805692,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":4}}},{"type":"chunk","time":1792123805692,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":2,"step":1}} {"type":"turn/end","data":{"turn":2,"reason":{"kind":"completed"}}} diff --git a/snapshots/session/subagent-tool-filter/tool-schemas.1.expected.json b/snapshots/session/subagent-tool-filter/tool-schemas.1.expected.json index 6a6e4dc947..36acbc4b98 100644 --- a/snapshots/session/subagent-tool-filter/tool-schemas.1.expected.json +++ b/snapshots/session/subagent-tool-filter/tool-schemas.1.expected.json @@ -95,13 +95,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -159,7 +159,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -171,9 +171,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -181,7 +181,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -204,10 +204,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -222,6 +226,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -229,10 +234,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -247,6 +256,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/session/system-prompt-in-history/tool-schemas.expected.json b/snapshots/session/system-prompt-in-history/tool-schemas.expected.json index b546a748a7..99b37246de 100644 --- a/snapshots/session/system-prompt-in-history/tool-schemas.expected.json +++ b/snapshots/session/system-prompt-in-history/tool-schemas.expected.json @@ -181,13 +181,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -245,7 +245,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -297,9 +297,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -307,7 +307,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -330,10 +330,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -348,6 +352,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -355,10 +360,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -373,6 +382,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/session/team-direct-inbox/session.1.v4.jsonl b/snapshots/session/team-direct-inbox/session.1.v4.jsonl index 1d63ab1c26..c7ab3d020e 100644 --- a/snapshots/session/team-direct-inbox/session.1.v4.jsonl +++ b/snapshots/session/team-direct-inbox/session.1.v4.jsonl @@ -3,20 +3,20 @@ {"type":"sandbox/mode","data":{"mode":"danger-full-access","source":"delegation"}} {"type":"approval/policy","data":{"policy":"never","source":"delegation"}} {"type":"permission/preset","data":{"preset":"danger-full-access"}} -{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Create the empty file team-ready, then wait in Bash until interrupted."},{"type":"text","text":"Your parent agent id is \"{{session:1}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{session:1}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:13}}"}]}} +{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Create the empty file team-ready, then wait in Bash until interrupted."},{"type":"text","text":"Your name is \"worker-1\". Your parent agent name is \"lead\". Before you finish, send your result to that agent with send_message({ name: \"lead\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:13}}"}]}} {"type":"turn/start","data":{"turn":1}} {"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":1,"step":1}} {"type":"system/message","data":{"turn":1,"step":1,"message":{"role":"system","content":[{"type":"text","text":"{{system}}"}],"source":{"kind":"system-prompt"},"id":"{{message:14}}"}},"surfaceOp":"append"} -{"type":"user/message","data":{"content":[{"type":"text","text":"Create the empty file team-ready, then wait in Bash until interrupted."},{"type":"text","text":"Your parent agent id is \"{{session:1}}\". Before you finish, send your result to that agent with send_message({ agent_id: \"{{session:1}}\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:13}}"},"surfaceOp":"append"} -{"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations.\n\nApproval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).\n\nDelegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly.\n\nDelegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly.\n\nYou are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it.\n\nYou are a teammate in the Team led by agent \"{{session:1}}\"."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations."},{"name":"approval:policy","text":"Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."},{"name":"tool:subagent:depth","text":"Delegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly."},{"name":"tool:subagent_fork:depth","text":"Delegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly."},{"name":"subagent:delegation","text":"You are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."},{"name":"team:identity","text":"You are a teammate in the Team led by agent \"{{session:1}}\"."}]},"role":"user","id":"{{message:15}}"},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Create the empty file team-ready, then wait in Bash until interrupted."},{"type":"text","text":"Your name is \"worker-1\". Your parent agent name is \"lead\". Before you finish, send your result to that agent with send_message({ name: \"lead\", message: \"\" }). The parent shares your workspace but does not automatically receive your transcript, tool output, or reasoning. Send earlier messages as well when a finding changes what the parent should do next; sending a message does not end your turn."}],"source":{"kind":"user"},"role":"user","id":"{{message:13}}"},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations.\n\nApproval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).\n\nDelegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly.\n\nDelegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly.\n\nYou are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it.\n\nYour name is \"worker-1\". You are a teammate in the Team led by \"lead\"."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations."},{"name":"approval:policy","text":"Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."},{"name":"tool:subagent:depth","text":"Delegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly."},{"name":"tool:subagent_fork:depth","text":"Delegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly."},{"name":"subagent:delegation","text":"You are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."},{"name":"team:identity","text":"Your name is \"worker-1\". You are a teammate in the Team led by \"lead\"."}]},"role":"user","id":"{{message:15}}"},"surfaceOp":"append"} {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} {"type":"session/title","data":{"title":"Create the empty file team-ready,","messageSeqs":[9],"source":{"kind":"fallback"}}} -{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"direct-1","name":"bash","arguments":"{\"command\":\"touch team-ready; while :; do sleep 1; done\",\"description\":\"Signal readiness and wait for interruption\",\"timeoutMs\":60000}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:16}}"},"usage":{"inputTokens":3,"outputTokens":3},"stream":[{"type":"chunk","time":1791450215117,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1791450215117,"index":0,"dt":[],"id":"direct-1","name":"bash","args":["{\"command\":\"touch team-ready; while :; do sleep 1; done\",\"description\":\"Signal readiness and wait for interruption\",\"timeoutMs\":60000}"]},{"type":"chunk","time":1791450215117,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"direct-1","name":"bash","arguments":"{\"command\":\"touch team-ready; while :; do sleep 1; done\",\"description\":\"Signal readiness and wait for interruption\",\"timeoutMs\":60000}"}}},{"type":"chunk","time":1791450215117,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}},{"type":"chunk","time":1791450215117,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} -{"type":"tool/call","data":{"turn":1,"step":1,"callId":"direct-1","name":"bash","arguments":"{\"command\":\"touch team-ready; while :; do sleep 1; done\",\"description\":\"Signal readiness and wait for interruption\",\"timeoutMs\":60000}"}} +{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"direct-1","name":"bash","arguments":"{\"command\":\"touch team-ready; while :; do sleep 1; done\",\"description\":\"Signal readiness and wait for interruption\",\"timeoutMs\":60000,\"name\":\"worker-1\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:16}}"},"usage":{"inputTokens":3,"outputTokens":3},"stream":[{"type":"chunk","time":1791450215117,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1791450215117,"index":0,"dt":[],"id":"direct-1","name":"bash","args":["{\"command\":\"touch team-ready; while :; do sleep 1; done\",\"description\":\"Signal readiness and wait for interruption\",\"timeoutMs\":60000,\"name\":\"worker-1\"}"]},{"type":"chunk","time":1791450215117,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"direct-1","name":"bash","arguments":"{\"command\":\"touch team-ready; while :; do sleep 1; done\",\"description\":\"Signal readiness and wait for interruption\",\"timeoutMs\":60000,\"name\":\"worker-1\"}"}}},{"type":"chunk","time":1791450215117,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}},{"type":"chunk","time":1791450215117,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":1,"callId":"direct-1","name":"bash","arguments":"{\"command\":\"touch team-ready; while :; do sleep 1; done\",\"description\":\"Signal readiness and wait for interruption\",\"timeoutMs\":60000,\"name\":\"worker-1\"}"}} {"type":"job/registered","data":{"jobId":"{{id:2}}","owner":"{{session:2}}","kind":"bash","label":"touch team-ready; while :; do sleep 1; done","startedAt":1791450215128,"toolCall":{"callId":"direct-1","rootCallId":"direct-1"}}} -{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Agent {{session:1}} sent a message: "},{"type":"text","text":"Review the direct inbox delivery."}],"source":{"kind":"agent-message","form":"relay","senderSessionId":"{{session:1}}"},"role":"user","id":"{{message:17}}"}]}} +{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Agent lead sent a message: "},{"type":"text","text":"Review the direct inbox delivery."}],"source":{"kind":"agent-message","form":"relay","senderSessionId":"{{session:1}}"},"role":"user","id":"{{message:17}}"}]}} {"type":"job/settled","data":{"jobId":"{{id:2}}","owner":"{{session:2}}","kind":"bash","label":"touch team-ready; while :; do sleep 1; done","startedAt":1791450215128,"toolCall":{"callId":"direct-1","rootCallId":"direct-1"},"finishedAt":1791450215194,"status":"killed","cause":"kill","producerReported":true,"detail":"signal: SIGTERM; tool call aborted"}} {"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"direct-1"},"toolCallId":"direct-1","content":[{"type":"text","text":"Error: tool call aborted"}],"isError":true,"id":"{{message:18}}"},"error":{"name":"AbortError","code":"ABORTED"}},"sourceEventSeqs":[15],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":1}} diff --git a/snapshots/session/team-direct-inbox/session.v4.jsonl b/snapshots/session/team-direct-inbox/session.v4.jsonl index 06d170e4cc..9c1f0cbf6d 100644 --- a/snapshots/session/team-direct-inbox/session.v4.jsonl +++ b/snapshots/session/team-direct-inbox/session.v4.jsonl @@ -8,33 +8,34 @@ {"type":"step/start","data":{"turn":1,"step":1}} {"type":"system/message","data":{"turn":1,"step":1,"message":{"role":"system","content":[{"type":"text","text":"{{system}}"}],"source":{"kind":"system-prompt"},"id":"{{message:2}}"}},"surfaceOp":"append"} {"type":"user/message","data":{"content":[{"type":"text","text":"Spawn teammate reviewer, wait for its team-ready file, send it the message Review the direct inbox delivery., interrupt its waiting turn, then reply TEAM_DIRECT_INBOX_OK."}],"source":{"kind":"user"},"role":"user","id":"{{message:1}}"},"surfaceOp":"append"} -{"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations.\n\nApproval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).\n\nYou are the Team Lead. Your agent id is \"{{session:1}}\"."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations."},{"name":"approval:policy","text":"Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."},{"name":"team:identity","text":"You are the Team Lead. Your agent id is \"{{session:1}}\"."}]},"role":"user","id":"{{message:3}}"},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations.\n\nApproval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).\n\nYou are the Team Lead. Your name is lead."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations."},{"name":"approval:policy","text":"Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."},{"name":"team:identity","text":"You are the Team Lead. Your name is lead."}]},"role":"user","id":"{{message:3}}"},"surfaceOp":"append"} {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} {"type":"session/title","data":{"title":"Spawn teammate reviewer, wait for","messageSeqs":[8],"source":{"kind":"fallback"}}} -{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"direct-1","name":"subagent","arguments":"{\"description\":\"Check direct inbox delivery\",\"prompt\":\"Create the empty file team-ready, then wait in Bash until interrupted.\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":3,"outputTokens":3},"stream":[{"type":"chunk","time":1792050720691,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792050720691,"index":0,"dt":[],"id":"direct-1","name":"subagent","args":["{\"name\":\"reviewer\",\"description\":\"Check direct inbox delivery\",\"prompt\":\"Create the empty file team-ready, then wait in Bash until interrupted.\"}"]},{"type":"chunk","time":1792050720691,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"direct-1","name":"subagent","arguments":"{\"description\":\"Check direct inbox delivery\",\"prompt\":\"Create the empty file team-ready, then wait in Bash until interrupted.\"}"}}},{"type":"chunk","time":1792050720691,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}},{"type":"chunk","time":1792050720691,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} -{"type":"tool/call","data":{"turn":1,"step":1,"callId":"direct-1","name":"subagent","arguments":"{\"description\":\"Check direct inbox delivery\",\"prompt\":\"Create the empty file team-ready, then wait in Bash until interrupted.\"}"}} -{"type":"subagent/catalog","data":{"version":0,"childId":"{{session:2}}","childCreatedAt":1792050720697,"mode":"continuable","label":"Check direct inbox delivery"}} -{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"direct-1"},"toolCallId":"direct-1","content":[{"type":"text","text":"started subagent {{session:2}}"}],"isError":false,"id":"{{message:5}}"}},"sourceEventSeqs":[14],"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"direct-1","name":"subagent","arguments":"{\"description\":\"Check direct inbox delivery\",\"prompt\":\"Create the empty file team-ready, then wait in Bash until interrupted.\",\"name\":\"worker-1\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":3,"outputTokens":3},"stream":[{"type":"chunk","time":1792123806482,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792123806482,"index":0,"dt":[],"id":"direct-1","name":"subagent","args":["{\"name\":\"worker-1\",\"description\":\"Check direct inbox delivery\",\"prompt\":\"Create the empty file team-ready, then wait in Bash until interrupted.\"}"]},{"type":"chunk","time":1792123806482,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"direct-1","name":"subagent","arguments":"{\"description\":\"Check direct inbox delivery\",\"prompt\":\"Create the empty file team-ready, then wait in Bash until interrupted.\",\"name\":\"worker-1\"}"}}},{"type":"chunk","time":1792123806482,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}},{"type":"chunk","time":1792123806482,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":1,"callId":"direct-1","name":"subagent","arguments":"{\"description\":\"Check direct inbox delivery\",\"prompt\":\"Create the empty file team-ready, then wait in Bash until interrupted.\",\"name\":\"worker-1\"}"}} +{"type":"subagent/catalog","data":{"version":0,"childId":"{{session:2}}","childCreatedAt":1792123806489,"mode":"continuable","label":"Check direct inbox delivery"}} +{"type":"subagent/named","data":{"name":"worker-1","id":"{{session:2}}"}} +{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"direct-1"},"toolCallId":"direct-1","content":[{"type":"text","text":"started subagent worker-1"}],"isError":false,"id":"{{message:5}}"}},"sourceEventSeqs":[14],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":1}} {"type":"step/start","data":{"turn":1,"step":2}} -{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"tool-call","id":"direct-2","name":"bash","arguments":"{\"command\":\"while [ ! -f team-ready ]; do sleep 0.01; done\",\"description\":\"Wait for the teammate to start\",\"timeoutMs\":60000}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:6}}"},"usage":{"inputTokens":3,"outputTokens":3},"stream":[{"type":"chunk","time":1792050720737,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792050720737,"index":0,"dt":[],"id":"direct-2","name":"bash","args":["{\"command\":\"while [ ! -f team-ready ]; do sleep 0.01; done\",\"description\":\"Wait for the teammate to start\",\"timeoutMs\":60000}"]},{"type":"chunk","time":1792050720737,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"direct-2","name":"bash","arguments":"{\"command\":\"while [ ! -f team-ready ]; do sleep 0.01; done\",\"description\":\"Wait for the teammate to start\",\"timeoutMs\":60000}"}}},{"type":"chunk","time":1792050720737,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}},{"type":"chunk","time":1792050720737,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"tool-call","id":"direct-2","name":"bash","arguments":"{\"command\":\"while [ ! -f team-ready ]; do sleep 0.01; done\",\"description\":\"Wait for the teammate to start\",\"timeoutMs\":60000}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:6}}"},"usage":{"inputTokens":3,"outputTokens":3},"stream":[{"type":"chunk","time":1792123806526,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792123806526,"index":0,"dt":[],"id":"direct-2","name":"bash","args":["{\"command\":\"while [ ! -f team-ready ]; do sleep 0.01; done\",\"description\":\"Wait for the teammate to start\",\"timeoutMs\":60000}"]},{"type":"chunk","time":1792123806526,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"direct-2","name":"bash","arguments":"{\"command\":\"while [ ! -f team-ready ]; do sleep 0.01; done\",\"description\":\"Wait for the teammate to start\",\"timeoutMs\":60000}"}}},{"type":"chunk","time":1792123806526,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}},{"type":"chunk","time":1792123806526,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} {"type":"tool/call","data":{"turn":1,"step":2,"callId":"direct-2","name":"bash","arguments":"{\"command\":\"while [ ! -f team-ready ]; do sleep 0.01; done\",\"description\":\"Wait for the teammate to start\",\"timeoutMs\":60000}"}} -{"type":"job/registered","data":{"jobId":"{{id:1}}","owner":"{{session:1}}","kind":"bash","label":"while [ ! -f team-ready ]; do sleep 0.01; done","startedAt":1792050720748,"toolCall":{"callId":"direct-2","rootCallId":"direct-2"}}} -{"type":"job/settled","data":{"jobId":"{{id:1}}","owner":"{{session:1}}","kind":"bash","label":"while [ ! -f team-ready ]; do sleep 0.01; done","startedAt":1792050720748,"toolCall":{"callId":"direct-2","rootCallId":"direct-2"},"finishedAt":1792050720763,"status":"completed","cause":"producer","producerReported":true,"detail":"exit code: 0"}} -{"type":"tool/result","data":{"turn":1,"step":2,"message":{"role":"tool","source":{"kind":"tool","callId":"direct-2"},"toolCallId":"direct-2","content":[{"type":"text","text":"(no output)"}],"isError":false,"id":"{{message:7}}"},"meta":{"cwd":"{{cwd}}"}},"sourceEventSeqs":[20],"surfaceOp":"append"} +{"type":"job/registered","data":{"jobId":"{{id:1}}","owner":"{{session:1}}","kind":"bash","label":"while [ ! -f team-ready ]; do sleep 0.01; done","startedAt":1792123806538,"toolCall":{"callId":"direct-2","rootCallId":"direct-2"}}} +{"type":"job/settled","data":{"jobId":"{{id:1}}","owner":"{{session:1}}","kind":"bash","label":"while [ ! -f team-ready ]; do sleep 0.01; done","startedAt":1792123806538,"toolCall":{"callId":"direct-2","rootCallId":"direct-2"},"finishedAt":1792123806553,"status":"completed","cause":"producer","producerReported":true,"detail":"exit code: 0"}} +{"type":"tool/result","data":{"turn":1,"step":2,"message":{"role":"tool","source":{"kind":"tool","callId":"direct-2"},"toolCallId":"direct-2","content":[{"type":"text","text":"(no output)"}],"isError":false,"id":"{{message:7}}"},"meta":{"cwd":"{{cwd}}"}},"sourceEventSeqs":[21],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":2}} {"type":"step/start","data":{"turn":1,"step":3}} -{"type":"assistant/message","data":{"turn":1,"step":3,"message":{"role":"assistant","content":[{"type":"tool-call","id":"direct-3","name":"send_message","arguments":"{\"agent_id\":\"{{session:2}}\",\"message\":\"Review the direct inbox delivery.\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:8}}"},"usage":{"inputTokens":3,"outputTokens":3},"stream":[{"type":"chunk","time":1792050720776,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792050720776,"index":0,"dt":[],"id":"direct-3","name":"send_message","args":["{\"agent_id\":\"reviewer\",\"message\":\"Review the direct inbox delivery.\"}"]},{"type":"chunk","time":1792050720776,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"direct-3","name":"send_message","arguments":"{\"agent_id\":\"{{session:2}}\",\"message\":\"Review the direct inbox delivery.\"}"}}},{"type":"chunk","time":1792050720776,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}},{"type":"chunk","time":1792050720776,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} -{"type":"tool/call","data":{"turn":1,"step":3,"callId":"direct-3","name":"send_message","arguments":"{\"agent_id\":\"{{session:2}}\",\"message\":\"Review the direct inbox delivery.\"}"}} -{"type":"tool/result","data":{"turn":1,"step":3,"message":{"role":"tool","source":{"kind":"tool","callId":"direct-3"},"toolCallId":"direct-3","content":[{"type":"text","text":"message delivered to agent {{session:2}}"}],"isError":false,"id":"{{message:9}}"}},"sourceEventSeqs":[27],"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":3,"message":{"role":"assistant","content":[{"type":"tool-call","id":"direct-3","name":"send_message","arguments":"{\"message\":\"Review the direct inbox delivery.\",\"name\":\"worker-1\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:8}}"},"usage":{"inputTokens":3,"outputTokens":3},"stream":[{"type":"chunk","time":1792123806565,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792123806565,"index":0,"dt":[],"id":"direct-3","name":"send_message","args":["{\"message\":\"Review the direct inbox delivery.\",\"name\":\"reviewer\"}"]},{"type":"chunk","time":1792123806565,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"direct-3","name":"send_message","arguments":"{\"message\":\"Review the direct inbox delivery.\",\"name\":\"worker-1\"}"}}},{"type":"chunk","time":1792123806565,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}},{"type":"chunk","time":1792123806565,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":3,"callId":"direct-3","name":"send_message","arguments":"{\"message\":\"Review the direct inbox delivery.\",\"name\":\"worker-1\"}"}} +{"type":"tool/result","data":{"turn":1,"step":3,"message":{"role":"tool","source":{"kind":"tool","callId":"direct-3"},"toolCallId":"direct-3","content":[{"type":"text","text":"message delivered to agent worker-1"}],"isError":false,"id":"{{message:9}}"}},"sourceEventSeqs":[28],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":3}} {"type":"step/start","data":{"turn":1,"step":4}} -{"type":"assistant/message","data":{"turn":1,"step":4,"message":{"role":"assistant","content":[{"type":"tool-call","id":"direct-4","name":"interrupt_agent","arguments":"{\"agent_id\":\"{{session:2}}\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:10}}"},"usage":{"inputTokens":3,"outputTokens":3},"stream":[{"type":"chunk","time":1792050720793,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792050720793,"index":0,"dt":[],"id":"direct-4","name":"interrupt_agent","args":["{\"agent_id\":\"reviewer\"}"]},{"type":"chunk","time":1792050720793,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"direct-4","name":"interrupt_agent","arguments":"{\"agent_id\":\"{{session:2}}\"}"}}},{"type":"chunk","time":1792050720793,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}},{"type":"chunk","time":1792050720793,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} -{"type":"tool/call","data":{"turn":1,"step":4,"callId":"direct-4","name":"interrupt_agent","arguments":"{\"agent_id\":\"{{session:2}}\"}"}} -{"type":"tool/result","data":{"turn":1,"step":4,"message":{"role":"tool","source":{"kind":"tool","callId":"direct-4"},"toolCallId":"direct-4","content":[{"type":"text","text":"interrupt requested for agent {{session:2}}"}],"isError":false,"id":"{{message:11}}"}},"sourceEventSeqs":[32],"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":4,"message":{"role":"assistant","content":[{"type":"tool-call","id":"direct-4","name":"interrupt_agent","arguments":"{\"name\":\"worker-1\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:10}}"},"usage":{"inputTokens":3,"outputTokens":3},"stream":[{"type":"chunk","time":1792123806582,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792123806582,"index":0,"dt":[],"id":"direct-4","name":"interrupt_agent","args":["{\"name\":\"reviewer\"}"]},{"type":"chunk","time":1792123806582,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"direct-4","name":"interrupt_agent","arguments":"{\"name\":\"worker-1\"}"}}},{"type":"chunk","time":1792123806582,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}},{"type":"chunk","time":1792123806582,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":4,"callId":"direct-4","name":"interrupt_agent","arguments":"{\"name\":\"worker-1\"}"}} +{"type":"tool/result","data":{"turn":1,"step":4,"message":{"role":"tool","source":{"kind":"tool","callId":"direct-4"},"toolCallId":"direct-4","content":[{"type":"text","text":"interrupt requested for agent worker-1"}],"isError":false,"id":"{{message:11}}"}},"sourceEventSeqs":[33],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":4}} {"type":"step/start","data":{"turn":1,"step":5}} -{"type":"assistant/message","data":{"turn":1,"step":5,"message":{"role":"assistant","content":[{"type":"text","text":"TEAM_DIRECT_INBOX_OK"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:12}}"},"usage":{"inputTokens":3,"outputTokens":3},"stream":[{"type":"chunk","time":1792050720817,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1792050720817,"index":0,"dt":[],"texts":["TEAM_DIRECT_INBOX_OK"]},{"type":"chunk","time":1792050720817,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"TEAM_DIRECT_INBOX_OK"}}},{"type":"chunk","time":1792050720817,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}},{"type":"chunk","time":1792050720817,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":5,"message":{"role":"assistant","content":[{"type":"text","text":"TEAM_DIRECT_INBOX_OK"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:12}}"},"usage":{"inputTokens":3,"outputTokens":3},"stream":[{"type":"chunk","time":1792123806602,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1792123806602,"index":0,"dt":[],"texts":["TEAM_DIRECT_INBOX_OK"]},{"type":"chunk","time":1792123806602,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"TEAM_DIRECT_INBOX_OK"}}},{"type":"chunk","time":1792123806602,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}},{"type":"chunk","time":1792123806602,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":5}} {"type":"turn/end","data":{"turn":1,"reason":{"kind":"completed"}}} diff --git a/snapshots/session/team-targets/session.v4.jsonl b/snapshots/session/team-targets/session.v4.jsonl index 3bd3f1ea98..b44959cc55 100644 --- a/snapshots/session/team-targets/session.v4.jsonl +++ b/snapshots/session/team-targets/session.v4.jsonl @@ -8,7 +8,7 @@ {"type":"step/start","data":{"turn":1,"step":1}} {"type":"system/message","data":{"turn":1,"step":1,"message":{"role":"system","content":[{"type":"text","text":"{{system}}"}],"source":{"kind":"system-prompt"},"id":"{{message:2}}"}},"surfaceOp":"append"} {"type":"user/message","data":{"content":[{"type":"text","text":"Use list_agents to inspect your agents, attempt to message an unknown teammate and observe its rejection, then reply TEAM_TARGETS_OK."}],"source":{"kind":"user"},"role":"user","id":"{{message:1}}"},"surfaceOp":"append"} -{"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations.\n\nApproval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).\n\nYou are the Team Lead. Your agent id is \"{{session:1}}\"."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations."},{"name":"approval:policy","text":"Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."},{"name":"team:identity","text":"You are the Team Lead. Your agent id is \"{{session:1}}\"."}]},"role":"user","id":"{{message:3}}"},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations.\n\nApproval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).\n\nYou are the Team Lead. Your name is lead."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations."},{"name":"approval:policy","text":"Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."},{"name":"team:identity","text":"You are the Team Lead. Your name is lead."}]},"role":"user","id":"{{message:3}}"},"surfaceOp":"append"} {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} {"type":"session/title","data":{"title":"Use list_agents to inspect your","messageSeqs":[8],"source":{"kind":"fallback"}}} @@ -17,9 +17,9 @@ {"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"team-list-1"},"toolCallId":"team-list-1","content":[{"type":"text","text":"(no subagents)"}],"isError":false,"id":"{{message:5}}"}},"sourceEventSeqs":[14],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":1}} {"type":"step/start","data":{"turn":1,"step":2}} -{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"tool-call","id":"team-list-2","name":"send_message","arguments":"{\"agent_id\":\"reviewer\",\"message\":\"unknown teammate must fail\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:6}}"},"usage":{"inputTokens":3,"outputTokens":3},"stream":[{"type":"chunk","time":1788778146017,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1788778146017,"index":0,"dt":[],"id":"team-list-2","name":"send_message","args":["{\"agent_id\":\"reviewer\",\"message\":\"unknown teammate must fail\"}"]},{"type":"chunk","time":1788778146017,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"team-list-2","name":"send_message","arguments":"{\"agent_id\":\"reviewer\",\"message\":\"unknown teammate must fail\"}"}}},{"type":"chunk","time":1788778146017,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}},{"type":"chunk","time":1788778146017,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} -{"type":"tool/call","data":{"turn":1,"step":2,"callId":"team-list-2","name":"send_message","arguments":"{\"agent_id\":\"reviewer\",\"message\":\"unknown teammate must fail\"}"}} -{"type":"tool/result","data":{"turn":1,"step":2,"message":{"role":"tool","source":{"kind":"tool","callId":"team-list-2"},"toolCallId":"team-list-2","content":[{"type":"text","text":"Error: subagent \"reviewer\" is unavailable"}],"isError":true,"id":"{{message:7}}"},"error":{"name":"SubagentError","code":"NOT_RESUMABLE"}},"sourceEventSeqs":[19],"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"tool-call","id":"team-list-2","name":"send_message","arguments":"{\"message\":\"unknown teammate must fail\",\"name\":\"reviewer\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:6}}"},"usage":{"inputTokens":3,"outputTokens":3},"stream":[{"type":"chunk","time":1788778146017,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1788778146017,"index":0,"dt":[],"id":"team-list-2","name":"send_message","args":["{\"message\":\"unknown teammate must fail\",\"name\":\"reviewer\"}"]},{"type":"chunk","time":1788778146017,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"team-list-2","name":"send_message","arguments":"{\"message\":\"unknown teammate must fail\",\"name\":\"reviewer\"}"}}},{"type":"chunk","time":1788778146017,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}},{"type":"chunk","time":1788778146017,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":2,"callId":"team-list-2","name":"send_message","arguments":"{\"message\":\"unknown teammate must fail\",\"name\":\"reviewer\"}"}} +{"type":"tool/result","data":{"turn":1,"step":2,"message":{"role":"tool","source":{"kind":"tool","callId":"team-list-2"},"toolCallId":"team-list-2","content":[{"type":"text","text":"Error: agent name \"reviewer\" was not found; use list_agents to discover available names"}],"isError":true,"id":"{{message:7}}"},"error":{"name":"SubagentError","code":"AGENT_NAME_NOT_FOUND"}},"sourceEventSeqs":[19],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":2}} {"type":"step/start","data":{"turn":1,"step":3}} {"type":"assistant/message","data":{"turn":1,"step":3,"message":{"role":"assistant","content":[{"type":"text","text":"TEAM_TARGETS_OK"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:8}}"},"usage":{"inputTokens":3,"outputTokens":3},"stream":[{"type":"chunk","time":1788778146037,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1788778146037,"index":0,"dt":[],"texts":["TEAM_TARGETS_OK"]},{"type":"chunk","time":1788778146037,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"TEAM_TARGETS_OK"}}},{"type":"chunk","time":1788778146037,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}},{"type":"chunk","time":1788778146037,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} diff --git a/snapshots/session/team-targets/system-prompt.expected.md b/snapshots/session/team-targets/system-prompt.expected.md index 707f784e52..d3d19dee8f 100644 --- a/snapshots/session/team-targets/system-prompt.expected.md +++ b/snapshots/session/team-targets/system-prompt.expected.md @@ -5,13 +5,13 @@ You are a coding assistant powered by the deepseek-v4-flash model. Your bash too Verify your work by running the code or tests. Keep answers brief and factual. -Agent Teams is available in this session. Teammates are subagents. Use agent ids with send_message to reach your direct continuable children or, as a continuable subagent, your parent and continuable siblings. Descriptions explain responsibilities and may repeat. +Agent Teams is available in this session. Teammates are subagents. Use agent names with send_message to reach your direct continuable children or, as a continuable subagent, your parent and continuable siblings. Descriptions explain responsibilities and may repeat. The Team Lead and all teammates share the same working directory and filesystem. Edits are immediately visible to every member. Split write work into disjoint scopes, record expected write scopes on shared tasks, and use task dependencies when work must be ordered. Write-scope overlap is advisory, not a lock. Prefer read/edit/write for file changes. If a file operation returns FS_STALE_VERSION, read the current file, rebase your intended change onto the new content, and retry. Bash, formatters, code generators, and scripts are not fully protected by the filesystem version guard; coordinate them explicitly and have the Lead review the final diff and run tests. -Use agent ids as task owners. The Lead can reassign to itself, its direct continuable children, or historical members; other descendants claim tasks themselves. list_agents shows direct contacts and all reachable continuable descendants; discovery does not grant message or assignment authority. inactive means no turn is executing; it does not describe task completion, success, failure, or waiting for other agents. A successful send does not mean the recipient has processed it. Shared-task workflow is list, get, claim with the current revision, perform the work, then complete. Task readiness never starts an owner. Before wait_agent, make sure another required member is running; use send_message first for an inactive direct contact, or coordinate through its parent for a deeper member. wait_agent observes only changes after that call starts, never wakes a member, and returns noProgress immediately when no other member is running. Re-list after wakeup or timeout. The Lead must wait for required teammates before giving the final answer. +Use agent names as task owners; the root agent is named lead. The Lead can reassign to itself, its direct continuable children, or historical members; other descendants claim tasks themselves. list_agents shows direct contacts and all reachable continuable descendants; discovery does not grant message or assignment authority. inactive means no turn is executing; it does not describe task completion, success, failure, or waiting for other agents. A successful send does not mean the recipient has processed it. Shared-task workflow is list, get, claim with the current revision, perform the work, then complete. Task readiness never starts an owner. Before wait_agent, make sure another required member is running; use send_message first for an inactive direct contact, or coordinate through its parent for a deeper member. wait_agent observes only changes after that call starts, never wakes a member, and returns noProgress immediately when no other member is running. Re-list after wakeup or timeout. The Lead must wait for required teammates before giving the final answer. Check the [exit code: N] marker on every bash result; investigate failures before moving on. diff --git a/snapshots/session/team-targets/tool-schemas.expected.json b/snapshots/session/team-targets/tool-schemas.expected.json index c260c0f74a..ed5290f277 100644 --- a/snapshots/session/team-targets/tool-schemas.expected.json +++ b/snapshots/session/team-targets/tool-schemas.expected.json @@ -181,13 +181,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -245,7 +245,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -297,9 +297,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -307,7 +307,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -330,10 +330,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -348,6 +352,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -355,10 +360,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -373,6 +382,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -446,7 +456,7 @@ }, "owner": { "type": "string", - "description": "Optional exact ownerId filter; use unowned for tasks without an owner." + "description": "Optional exact ownerName filter; use unowned for tasks without an owner." }, "ready": { "type": "boolean", @@ -515,7 +525,7 @@ }, "owner": { "type": "string", - "description": "Agent id of the Lead or one of its direct continuable children for Lead-only reassign; omit to unassign." + "description": "Agent name of the Lead or one of its direct continuable children for Lead-only reassign; omit to unassign." } }, "required": [ diff --git a/snapshots/session/text-turn/tool-schemas.expected.json b/snapshots/session/text-turn/tool-schemas.expected.json index b546a748a7..99b37246de 100644 --- a/snapshots/session/text-turn/tool-schemas.expected.json +++ b/snapshots/session/text-turn/tool-schemas.expected.json @@ -181,13 +181,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -245,7 +245,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -297,9 +297,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -307,7 +307,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -330,10 +330,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -348,6 +352,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -355,10 +360,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -373,6 +382,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/session/text-turn/writer.expected.jsonl b/snapshots/session/text-turn/writer.expected.jsonl index baab2ac720..2c2cf8dcc3 100644 --- a/snapshots/session/text-turn/writer.expected.jsonl +++ b/snapshots/session/text-turn/writer.expected.jsonl @@ -12,6 +12,6 @@ {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}} {"type":"session/title","data":{"title":"Reply with exactly the word:","messageSeqs":[8],"source":{"kind":"fallback"}}} -{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"reasoning","text":"The user wants me to reply with exactly the word \"PONG\" and not use any tools."},{"type":"text","text":"PONG"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":3091,"outputTokens":23,"cacheReadTokens":0,"reasoningTokens":20},"stream":[{"type":"chunk","time":1791444976519,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1791444976519,"index":0,"dt":[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"texts":["The"," user"," wants"," me"," to"," reply"," with"," exactly"," the"," word"," \"","P","ONG","\""," and"," not"," use"," any"," tools","."]},{"type":"chunk","time":1791444976520,"chunk":{"type":"block-start","index":1,"blockType":"text"}},{"type":"text-chunks","time0":1791444976520,"index":1,"dt":[0],"texts":["P","ONG"]},{"type":"chunk","time":1791444976520,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The user wants me to reply with exactly the word \"PONG\" and not use any tools."}}},{"type":"chunk","time":1791444976520,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"PONG"}}},{"type":"chunk","time":1791444976520,"chunk":{"type":"usage","usage":{"inputTokens":3091,"outputTokens":23,"cacheReadTokens":0,"reasoningTokens":20}}},{"type":"chunk","time":1791444976520,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"reasoning","text":"The user wants me to reply with exactly the word \"PONG\" and not use any tools."},{"type":"text","text":"PONG"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:4}}"},"usage":{"inputTokens":3091,"outputTokens":23,"cacheReadTokens":0,"reasoningTokens":20},"stream":[{"type":"chunk","time":1792124601609,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}},{"type":"reasoning-chunks","time0":1792124601609,"index":0,"dt":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],"texts":["The"," user"," wants"," me"," to"," reply"," with"," exactly"," the"," word"," \"","P","ONG","\""," and"," not"," use"," any"," tools","."]},{"type":"chunk","time":1792124601610,"chunk":{"type":"block-start","index":1,"blockType":"text"}},{"type":"text-chunks","time0":1792124601610,"index":1,"dt":[0],"texts":["P","ONG"]},{"type":"chunk","time":1792124601610,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The user wants me to reply with exactly the word \"PONG\" and not use any tools."}}},{"type":"chunk","time":1792124601610,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"PONG"}}},{"type":"chunk","time":1792124601610,"chunk":{"type":"usage","usage":{"inputTokens":3091,"outputTokens":23,"cacheReadTokens":0,"reasoningTokens":20}}},{"type":"chunk","time":1792124601610,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":1}} {"type":"turn/end","data":{"turn":1,"reason":{"kind":"completed"}}} diff --git a/snapshots/session/web-fetch/tool-schemas.expected.json b/snapshots/session/web-fetch/tool-schemas.expected.json index 1c7e8191a1..cf957f0331 100644 --- a/snapshots/session/web-fetch/tool-schemas.expected.json +++ b/snapshots/session/web-fetch/tool-schemas.expected.json @@ -181,13 +181,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -245,7 +245,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -297,9 +297,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -307,7 +307,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -330,10 +330,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -348,6 +352,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -355,10 +360,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -373,6 +382,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/session/workflow-confinement/tool-schemas.expected.json b/snapshots/session/workflow-confinement/tool-schemas.expected.json index b546a748a7..99b37246de 100644 --- a/snapshots/session/workflow-confinement/tool-schemas.expected.json +++ b/snapshots/session/workflow-confinement/tool-schemas.expected.json @@ -181,13 +181,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -245,7 +245,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -297,9 +297,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -307,7 +307,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -330,10 +330,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -348,6 +352,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -355,10 +360,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -373,6 +382,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/session/workspace-dependencies/tool-schemas.expected.json b/snapshots/session/workspace-dependencies/tool-schemas.expected.json index d2a760c296..d441d8dd4e 100644 --- a/snapshots/session/workspace-dependencies/tool-schemas.expected.json +++ b/snapshots/session/workspace-dependencies/tool-schemas.expected.json @@ -136,13 +136,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -200,7 +200,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -260,9 +260,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -270,7 +270,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -293,10 +293,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -311,6 +315,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -318,10 +323,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -336,6 +345,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/session/worktree/tool-schemas.expected.json b/snapshots/session/worktree/tool-schemas.expected.json index c03aa73317..afe8f8c8af 100644 --- a/snapshots/session/worktree/tool-schemas.expected.json +++ b/snapshots/session/worktree/tool-schemas.expected.json @@ -198,13 +198,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -262,7 +262,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -314,9 +314,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -324,7 +324,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -347,10 +347,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -365,6 +369,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -372,10 +377,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -390,6 +399,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/web/fresh-round-trip/tool-schemas.expected.json b/snapshots/web/fresh-round-trip/tool-schemas.expected.json index b591338416..5bebca44ec 100644 --- a/snapshots/web/fresh-round-trip/tool-schemas.expected.json +++ b/snapshots/web/fresh-round-trip/tool-schemas.expected.json @@ -244,13 +244,13 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The id of an agent created under you: your direct child or a deeper descendant." + "description": "The name of an agent created under you: your direct child or a deeper descendant." } }, "required": [ - "agent_id" + "name" ] } }, @@ -308,7 +308,7 @@ }, { "name": "list_agents", - "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", + "description": "List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.", "parameters": { "type": "object", "properties": {} @@ -660,9 +660,9 @@ "parameters": { "type": "object", "properties": { - "agent_id": { + "name": { "type": "string", - "description": "The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." + "description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child." }, "message": { "type": "string", @@ -670,7 +670,7 @@ } }, "required": [ - "agent_id", + "name", "message" ] } @@ -693,10 +693,14 @@ }, { "name": "subagent", - "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -711,6 +715,7 @@ } }, "required": [ + "name", "description", "prompt" ] @@ -718,10 +723,14 @@ }, { "name": "subagent_fork", - "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", + "description": "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes.", "parameters": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish." + }, "cwd": { "type": "string", "description": "Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent." @@ -736,6 +745,7 @@ } }, "required": [ + "name", "description", "prompt" ] diff --git a/snapshots/web/official-subagent-bundle/session.v4.jsonl b/snapshots/web/official-subagent-bundle/session.v4.jsonl index 80558e93fd..aefbeb49c1 100644 --- a/snapshots/web/official-subagent-bundle/session.v4.jsonl +++ b/snapshots/web/official-subagent-bundle/session.v4.jsonl @@ -14,22 +14,23 @@ {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash","contextWindow":128000}} {"type":"session/title","data":{"title":"Delegate a self-contained task to","messageSeqs":[9],"source":{"kind":"fallback"}}} -{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"official-subagent-code","name":"run_code","arguments":"{\"description\":\"Delegate through the official Claude bundle\",\"code\":\"const result = await tools.subagent_claude_code({ description: \\\"Read the fixture response\\\", prompt: \\\"Reply with OFFICIAL_SUBAGENT_OK exactly.\\\" });\\nif (result.kind !== \\\"activation\\\") throw new Error(\\\"Expected child activation\\\");\\nconsole.log(result.subagentId);\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:5}}"},"usage":{"inputTokens":10,"outputTokens":4},"stream":[{"type":"chunk","time":1791277983299,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1791277983299,"index":0,"dt":[],"id":"official-subagent-code","name":"run_code","args":["{\"description\":\"Delegate through the official Claude bundle\",\"code\":\"const result = await tools.subagent_claude_code({ description: \\\"Read the fixture response\\\", prompt: \\\"Reply with OFFICIAL_SUBAGENT_OK exactly.\\\" });\\nif (result.kind !== \\\"activation\\\") throw new Error(\\\"Expected child activation\\\");\\nconsole.log(result.subagentId);\"}"]},{"type":"chunk","time":1791277983299,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"official-subagent-code","name":"run_code","arguments":"{\"description\":\"Delegate through the official Claude bundle\",\"code\":\"const result = await tools.subagent_claude_code({ description: \\\"Read the fixture response\\\", prompt: \\\"Reply with OFFICIAL_SUBAGENT_OK exactly.\\\" });\\nif (result.kind !== \\\"activation\\\") throw new Error(\\\"Expected child activation\\\");\\nconsole.log(result.subagentId);\"}"}}},{"type":"chunk","time":1791277983299,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":4}}},{"type":"chunk","time":1791277983299,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} -{"type":"tool/call","data":{"turn":1,"step":1,"callId":"official-subagent-code","name":"run_code","arguments":"{\"description\":\"Delegate through the official Claude bundle\",\"code\":\"const result = await tools.subagent_claude_code({ description: \\\"Read the fixture response\\\", prompt: \\\"Reply with OFFICIAL_SUBAGENT_OK exactly.\\\" });\\nif (result.kind !== \\\"activation\\\") throw new Error(\\\"Expected child activation\\\");\\nconsole.log(result.subagentId);\"}"}} -{"type":"tool/ptc-dispatch-start","data":{"rootCallId":"official-subagent-code","parentCallId":"official-subagent-code","subCallId":"official-subagent-code:ptc:1","name":"subagent_claude_code","arguments":{"description":"Read the fixture response","prompt":"Reply with OFFICIAL_SUBAGENT_OK exactly."}}} -{"type":"subagent/catalog","data":{"version":2,"childId":"{{id:1}}","childCreatedAt":1791277983378,"mode":"external","label":"Read the fixture response"}} -{"type":"tool/ptc-dispatch","data":{"rootCallId":"official-subagent-code","parentCallId":"official-subagent-code","subCallId":"official-subagent-code:ptc:1","name":"subagent_claude_code","arguments":{"description":"Read the fixture response","prompt":"Reply with OFFICIAL_SUBAGENT_OK exactly."},"isError":false,"content":[{"type":"text","text":"started subagent {{id:1}}"}]}} -{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"official-subagent-code"},"toolCallId":"official-subagent-code","content":[{"type":"text","text":"{{id:1}}"}],"isError":false,"id":"{{message:6}}"}},"sourceEventSeqs":[16],"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"official-subagent-code","name":"run_code","arguments":"{\"description\":\"Delegate through the official Claude bundle\",\"code\":\"const result = await tools.subagent_claude_code({ name: \\\"native-worker\\\", description: \\\"Read the fixture response\\\", prompt: \\\"Reply with OFFICIAL_SUBAGENT_OK exactly.\\\" });\\nif (result.kind !== \\\"activation\\\") throw new Error(\\\"Expected child activation\\\");\\nconsole.log(result.name);\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:5}}"},"usage":{"inputTokens":10,"outputTokens":4},"stream":[{"type":"chunk","time":1792124856024,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":1792124856024,"index":0,"dt":[],"id":"official-subagent-code","name":"run_code","args":["{\"description\":\"Delegate through the official Claude bundle\",\"code\":\"const result = await tools.subagent_claude_code({ name: \\\"native-worker\\\", description: \\\"Read the fixture response\\\", prompt: \\\"Reply with OFFICIAL_SUBAGENT_OK exactly.\\\" });\\nif (result.kind !== \\\"activation\\\") throw new Error(\\\"Expected child activation\\\");\\nconsole.log(result.name);\"}"]},{"type":"chunk","time":1792124856024,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"official-subagent-code","name":"run_code","arguments":"{\"description\":\"Delegate through the official Claude bundle\",\"code\":\"const result = await tools.subagent_claude_code({ name: \\\"native-worker\\\", description: \\\"Read the fixture response\\\", prompt: \\\"Reply with OFFICIAL_SUBAGENT_OK exactly.\\\" });\\nif (result.kind !== \\\"activation\\\") throw new Error(\\\"Expected child activation\\\");\\nconsole.log(result.name);\"}"}}},{"type":"chunk","time":1792124856024,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":4}}},{"type":"chunk","time":1792124856024,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"} +{"type":"tool/call","data":{"turn":1,"step":1,"callId":"official-subagent-code","name":"run_code","arguments":"{\"description\":\"Delegate through the official Claude bundle\",\"code\":\"const result = await tools.subagent_claude_code({ name: \\\"native-worker\\\", description: \\\"Read the fixture response\\\", prompt: \\\"Reply with OFFICIAL_SUBAGENT_OK exactly.\\\" });\\nif (result.kind !== \\\"activation\\\") throw new Error(\\\"Expected child activation\\\");\\nconsole.log(result.name);\"}"}} +{"type":"tool/ptc-dispatch-start","data":{"rootCallId":"official-subagent-code","parentCallId":"official-subagent-code","subCallId":"official-subagent-code:ptc:1","name":"subagent_claude_code","arguments":{"name":"native-worker","description":"Read the fixture response","prompt":"Reply with OFFICIAL_SUBAGENT_OK exactly."}}} +{"type":"subagent/catalog","data":{"version":2,"childId":"{{id:1}}","childCreatedAt":1792124856165,"mode":"external","label":"Read the fixture response"}} +{"type":"subagent/named","data":{"name":"native-worker","id":"{{id:1}}"}} +{"type":"tool/ptc-dispatch","data":{"rootCallId":"official-subagent-code","parentCallId":"official-subagent-code","subCallId":"official-subagent-code:ptc:1","name":"subagent_claude_code","arguments":{"name":"native-worker","description":"Read the fixture response","prompt":"Reply with OFFICIAL_SUBAGENT_OK exactly."},"isError":false,"content":[{"type":"text","text":"started subagent native-worker"}]}} +{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"official-subagent-code"},"toolCallId":"official-subagent-code","content":[{"type":"text","text":"native-worker"}],"isError":false,"id":"{{message:6}}"}},"sourceEventSeqs":[16],"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":1}} {"type":"step/start","data":{"turn":1,"step":2}} -{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"text","text":"Waiting for the child result."}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:7}}"},"usage":{"inputTokens":10,"outputTokens":4},"stream":[{"type":"chunk","time":1791277983418,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1791277983419,"index":0,"dt":[],"texts":["Waiting for the child result."]},{"type":"chunk","time":1791277983419,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"Waiting for the child result."}}},{"type":"chunk","time":1791277983419,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":4}}},{"type":"chunk","time":1791277983419,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"text","text":"Waiting for the child result."}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:7}}"},"usage":{"inputTokens":10,"outputTokens":4},"stream":[{"type":"chunk","time":1792124856214,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1792124856214,"index":0,"dt":[],"texts":["Waiting for the child result."]},{"type":"chunk","time":1792124856215,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"Waiting for the child result."}}},{"type":"chunk","time":1792124856215,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":4}}},{"type":"chunk","time":1792124856215,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":2}} {"type":"turn/end","data":{"turn":1,"reason":{"kind":"completed"}}} -{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent {{id:1}} finished. It cannot receive follow-up messages."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"OFFICIAL_SUBAGENT_OK"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{id:1}} finished. It cannot receive follow-up messages.","senderSessionId":"{{id:1}}"},"role":"user","id":"{{message:8}}"}]}} +{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent native-worker finished. It cannot receive follow-up messages."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"OFFICIAL_SUBAGENT_OK"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent native-worker finished. It cannot receive follow-up messages.","senderSessionId":"{{id:1}}"},"role":"user","id":"{{message:8}}"}]}} {"type":"turn/start","data":{"turn":2}} {"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}} {"type":"step/start","data":{"turn":2,"step":1}} -{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent {{id:1}} finished. It cannot receive follow-up messages."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"OFFICIAL_SUBAGENT_OK"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{id:1}} finished. It cannot receive follow-up messages.","senderSessionId":"{{id:1}}"},"role":"user","id":"{{message:8}}"},"surfaceOp":"append"} -{"type":"assistant/message","data":{"turn":2,"step":1,"message":{"role":"assistant","content":[{"type":"text","text":"DONE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:9}}"},"usage":{"inputTokens":10,"outputTokens":4},"stream":[{"type":"chunk","time":1791277983885,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1791277983885,"index":0,"dt":[],"texts":["DONE"]},{"type":"chunk","time":1791277983885,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"DONE"}}},{"type":"chunk","time":1791277983885,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":4}}},{"type":"chunk","time":1791277983885,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent native-worker finished. It cannot receive follow-up messages."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"OFFICIAL_SUBAGENT_OK"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent native-worker finished. It cannot receive follow-up messages.","senderSessionId":"{{id:1}}"},"role":"user","id":"{{message:8}}"},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":2,"step":1,"message":{"role":"assistant","content":[{"type":"text","text":"DONE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:9}}"},"usage":{"inputTokens":10,"outputTokens":4},"stream":[{"type":"chunk","time":1792124856902,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1792124856902,"index":0,"dt":[],"texts":["DONE"]},{"type":"chunk","time":1792124856902,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"DONE"}}},{"type":"chunk","time":1792124856902,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":4}}},{"type":"chunk","time":1792124856902,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":2,"step":1}} {"type":"turn/end","data":{"turn":2,"reason":{"kind":"completed"}}} diff --git a/snapshots/web/official-subagent-bundle/system-prompt.expected.md b/snapshots/web/official-subagent-bundle/system-prompt.expected.md index 693d9cae1b..576fcd1273 100644 --- a/snapshots/web/official-subagent-bundle/system-prompt.expected.md +++ b/snapshots/web/official-subagent-bundle/system-prompt.expected.md @@ -132,8 +132,8 @@ interface ToolArgsMap { } & Record; /** Ask a subagent to stop its current work. This call returns without waiting for it to stop. You can continue a local direct child's conversation later with send_message. External executions stop permanently and cannot receive follow-ups. Subagents it started will keep running. */ interrupt_agent: { - /** The id of an agent created under you: your direct child or a deeper descendant. */ - agent_id: string; + /** The name of an agent created under you: your direct child or a deeper descendant. */ + name: string; } & Record; /** Request cancellation of a running background job. */ job_kill: { @@ -153,7 +153,7 @@ interface ToolArgsMap { /** Max wait in milliseconds with wait: true. Defaults to and is capped by configuration. */ timeout_ms?: number; } & Record; - /** List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation. */ + /** List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation. */ list_agents: Record; /** Declare existing files as final deliverables for the user. Use it when the user needs a separate file, especially Office documents, spreadsheets, and slide decks; prefer your final response when that suffices. The user opens the current files; their contents are not copied. */ present: { @@ -268,8 +268,8 @@ interface ToolArgsMap { } & Record; /** Send a message to an agent. A working agent receives it at its next step; an idle agent starts a new turn with it. Returns delivery confirmation, not the agent's answer. */ send_message: { - /** The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child. */ - agent_id: string; + /** The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child. */ + name: string; /** The message to deliver to the agent. */ message: string; } & Record; @@ -278,8 +278,10 @@ interface ToolArgsMap { /** The exact skill name from the available skills list. */ name: string; } & Record; - /** Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ + /** Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ subagent: { + /** Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish. */ + name: string; /** Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent. */ cwd?: string; /** A short (3-5 word) description of the delegated task, for display. */ @@ -287,8 +289,10 @@ interface ToolArgsMap { /** The complete, self-contained task for the subagent. It does not share this conversation's context, so include everything it needs. */ prompt: string; } & Record; - /** Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The completion notice includes its final answer. This backend does not accept follow-up messages. */ + /** Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The completion notice includes its final answer. This backend does not accept follow-up messages. */ subagent_claude_code: { + /** Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish. */ + name: string; /** Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent. */ cwd?: string; /** A short (3-5 word) description of the delegated task, for display. */ @@ -296,8 +300,10 @@ interface ToolArgsMap { /** The complete, self-contained task for the subagent. It does not share this conversation's context, so include everything it needs. */ prompt: string; } & Record; - /** Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ + /** Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ subagent_fork: { + /** Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish. */ + name: string; /** Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent. */ cwd?: string; /** A short (3-5 word) description of the delegated task, for display. */ @@ -494,18 +500,18 @@ interface ToolOutputMap { }; list_agents: ({ kind: "parent"; - id: string; + name: string; status: "running" | "inactive"; } | { kind: "child" | "sibling"; - id: string; + name: string; label: string; status: "running" | "inactive"; parent?: string; depth?: number; } | { kind: "diagnostic"; - id: string; + name: string; reason: "corrupt" | "unsupported" | "unavailable"; parent?: string; depth?: number; @@ -857,15 +863,15 @@ interface ToolOutputMap { }; subagent: { kind: "activation"; - subagentId: string; + name: string; }; subagent_claude_code: { kind: "activation"; - subagentId: string; + name: string; }; subagent_fork: { kind: "activation"; - subagentId: string; + name: string; }; todo_write: { todos: ({ diff --git a/snapshots/web/optional-string-editor/system-prompt.expected.md b/snapshots/web/optional-string-editor/system-prompt.expected.md index 58a7662e07..74a912722f 100644 --- a/snapshots/web/optional-string-editor/system-prompt.expected.md +++ b/snapshots/web/optional-string-editor/system-prompt.expected.md @@ -132,8 +132,8 @@ interface ToolArgsMap { } & Record; /** Ask a subagent to stop its current work. This call returns without waiting for it to stop. You can continue a local direct child's conversation later with send_message. External executions stop permanently and cannot receive follow-ups. Subagents it started will keep running. */ interrupt_agent: { - /** The id of an agent created under you: your direct child or a deeper descendant. */ - agent_id: string; + /** The name of an agent created under you: your direct child or a deeper descendant. */ + name: string; } & Record; /** Request cancellation of a running background job. */ job_kill: { @@ -153,7 +153,7 @@ interface ToolArgsMap { /** Max wait in milliseconds with wait: true. Defaults to and is capped by configuration. */ timeout_ms?: number; } & Record; - /** List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation. */ + /** List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation. */ list_agents: Record; /** Declare existing files as final deliverables for the user. Use it when the user needs a separate file, especially Office documents, spreadsheets, and slide decks; prefer your final response when that suffices. The user opens the current files; their contents are not copied. */ present: { @@ -268,8 +268,8 @@ interface ToolArgsMap { } & Record; /** Send a message to an agent. A working agent receives it at its next step; an idle agent starts a new turn with it. Returns delivery confirmation, not the agent's answer. */ send_message: { - /** The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child. */ - agent_id: string; + /** The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child. */ + name: string; /** The message to deliver to the agent. */ message: string; } & Record; @@ -295,8 +295,10 @@ interface ToolArgsMap { /** Optional parameter of `view` command when `path` points to a file. If omitted or null, the full file is shown. If provided, the file will be shown in the indicated line number range, e.g. [11, 12] will show lines 11 and 12. Indexing at 1 to start. Setting `[start_line, -1]` shows all lines from `start_line` to the end of the file. */ view_range?: number[] | null; } & Record; - /** Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ + /** Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ subagent: { + /** Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish. */ + name: string; /** Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent. */ cwd?: string; /** A short (3-5 word) description of the delegated task, for display. */ @@ -304,8 +306,10 @@ interface ToolArgsMap { /** The complete, self-contained task for the subagent. It does not share this conversation's context, so include everything it needs. */ prompt: string; } & Record; - /** Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ + /** Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ subagent_fork: { + /** Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish. */ + name: string; /** Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent. */ cwd?: string; /** A short (3-5 word) description of the delegated task, for display. */ @@ -502,18 +506,18 @@ interface ToolOutputMap { }; list_agents: ({ kind: "parent"; - id: string; + name: string; status: "running" | "inactive"; } | { kind: "child" | "sibling"; - id: string; + name: string; label: string; status: "running" | "inactive"; parent?: string; depth?: number; } | { kind: "diagnostic"; - id: string; + name: string; reason: "corrupt" | "unsupported" | "unavailable"; parent?: string; depth?: number; @@ -866,11 +870,11 @@ interface ToolOutputMap { str_replace_editor: string; subagent: { kind: "activation"; - subagentId: string; + name: string; }; subagent_fork: { kind: "activation"; - subagentId: string; + name: string; }; todo_write: { todos: ({ diff --git a/snapshots/web/ptc-round/system-prompt.expected.md b/snapshots/web/ptc-round/system-prompt.expected.md index 1abaf8becf..52d4ba6055 100644 --- a/snapshots/web/ptc-round/system-prompt.expected.md +++ b/snapshots/web/ptc-round/system-prompt.expected.md @@ -132,8 +132,8 @@ interface ToolArgsMap { } & Record; /** Ask a subagent to stop its current work. This call returns without waiting for it to stop. You can continue a local direct child's conversation later with send_message. External executions stop permanently and cannot receive follow-ups. Subagents it started will keep running. */ interrupt_agent: { - /** The id of an agent created under you: your direct child or a deeper descendant. */ - agent_id: string; + /** The name of an agent created under you: your direct child or a deeper descendant. */ + name: string; } & Record; /** Request cancellation of a running background job. */ job_kill: { @@ -153,7 +153,7 @@ interface ToolArgsMap { /** Max wait in milliseconds with wait: true. Defaults to and is capped by configuration. */ timeout_ms?: number; } & Record; - /** List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry ids, descriptions, and status; descendant rows also carry parent ids and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation. */ + /** List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation. */ list_agents: Record; /** Declare existing files as final deliverables for the user. Use it when the user needs a separate file, especially Office documents, spreadsheets, and slide decks; prefer your final response when that suffices. The user opens the current files; their contents are not copied. */ present: { @@ -268,8 +268,8 @@ interface ToolArgsMap { } & Record; /** Send a message to an agent. A working agent receives it at its next step; an idle agent starts a new turn with it. Returns delivery confirmation, not the agent's answer. */ send_message: { - /** The agent id of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child. */ - agent_id: string; + /** The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child. */ + name: string; /** The message to deliver to the agent. */ message: string; } & Record; @@ -278,8 +278,10 @@ interface ToolArgsMap { /** The exact skill name from the available skills list. */ name: string; } & Record; - /** Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ + /** Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ subagent: { + /** Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish. */ + name: string; /** Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent. */ cwd?: string; /** A short (3-5 word) description of the delegated task, for display. */ @@ -287,8 +289,10 @@ interface ToolArgsMap { /** The complete, self-contained task for the subagent. It does not share this conversation's context, so include everything it needs. */ prompt: string; } & Record; - /** Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ + /** Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. The runtime notifies you when it finishes. The child reports results with `send_message`; use `send_message` to steer it while running or continue its conversation after it finishes. */ subagent_fork: { + /** Unique name across this agent tree. Start with a lower-case letter; use only lower-case letters, digits, underscores, or hyphens. lead and unowned are reserved. Names remain taken after agents finish. */ + name: string; /** Initial child working directory. Relative paths use your current directory; omitted inherits it. Later directory changes in either agent are independent. */ cwd?: string; /** A short (3-5 word) description of the delegated task, for display. */ @@ -485,18 +489,18 @@ interface ToolOutputMap { }; list_agents: ({ kind: "parent"; - id: string; + name: string; status: "running" | "inactive"; } | { kind: "child" | "sibling"; - id: string; + name: string; label: string; status: "running" | "inactive"; parent?: string; depth?: number; } | { kind: "diagnostic"; - id: string; + name: string; reason: "corrupt" | "unsupported" | "unavailable"; parent?: string; depth?: number; @@ -848,11 +852,11 @@ interface ToolOutputMap { }; subagent: { kind: "activation"; - subagentId: string; + name: string; }; subagent_fork: { kind: "activation"; - subagentId: string; + name: string; }; todo_write: { todos: ({ diff --git a/snapshots/web/subagent-fork-schedule/session.v4.jsonl b/snapshots/web/subagent-fork-schedule/session.v4.jsonl index 710c5684d5..46eab30ed1 100644 --- a/snapshots/web/subagent-fork-schedule/session.v4.jsonl +++ b/snapshots/web/subagent-fork-schedule/session.v4.jsonl @@ -13,7 +13,8 @@ {"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}} {"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash","contextWindow":128000}} {"type":"session/title","data":{"title":"Reply PARENT_READY.","messageSeqs":[8],"source":{"kind":"fallback"}}} -{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"text","text":"PARENT_READY"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:5}}"},"stream":[{"type":"chunk","time":1791527273558,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1791527273558,"index":0,"dt":[],"texts":["PARENT_READY"]},{"type":"chunk","time":1791527273558,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"PARENT_READY"}}},{"type":"chunk","time":1791527273558,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} +{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"text","text":"PARENT_READY"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{message:5}}"},"stream":[{"type":"chunk","time":1792124858028,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":1792124858028,"index":0,"dt":[],"texts":["PARENT_READY"]},{"type":"chunk","time":1792124858028,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"PARENT_READY"}}},{"type":"chunk","time":1792124858028,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"} {"type":"step/end","data":{"turn":1,"step":1}} {"type":"turn/end","data":{"turn":1,"reason":{"kind":"completed"}}} -{"type":"subagent/catalog","data":{"version":0,"childId":"{{session:2}}","childCreatedAt":1791527273562,"mode":"continuable","label":"Check child reminder refusal"}} +{"type":"subagent/catalog","data":{"version":0,"childId":"{{session:2}}","childCreatedAt":1792124858036,"mode":"continuable","label":"Check child reminder refusal"}} +{"type":"subagent/named","data":{"name":"scheduled-child","id":"{{session:2}}"}} From d5ef28def11682983bb72f7fbc523a437bdb143d Mon Sep 17 00:00:00 2001 From: Dudu-0223 Date: Fri, 16 Oct 2026 12:48:20 +0800 Subject: [PATCH 04/17] Update remaining named-subagent test consumers --- .../agent-loop/tests/resource-lifecycle.spec.ts | 2 +- .../auto-review/tests/auto-review.spec.ts | 1 + .../sdk/server/tests/built-scope-carrier.e2e.ts | 1 + .../tests/loader-composition.e2e.ts | 16 ++++++++-------- .../tests/loader-composition.e2e.ts | 12 ++++++------ .../tool-subagent-control/README.i18n.yaml | 8 ++++---- .../subagent/tool-subagent-control/README.md | 4 ++-- .../subagent/tool-subagent-control/README.zh.md | 4 ++-- 8 files changed, 25 insertions(+), 23 deletions(-) diff --git a/packages/core/agent-loop/tests/resource-lifecycle.spec.ts b/packages/core/agent-loop/tests/resource-lifecycle.spec.ts index 8a0a66df12..43518c6ac4 100644 --- a/packages/core/agent-loop/tests/resource-lifecycle.spec.ts +++ b/packages/core/agent-loop/tests/resource-lifecycle.spec.ts @@ -120,7 +120,7 @@ it.each(['loop', 'root'] as const)('unloads %s while a background child is stopp const started = await ctx.tools.execute({ agent: parent, signal: new AbortController().signal, callId: ToolCallId('background-start'), name: 'subagent', - arguments: { description: 'child', prompt: 'wait' }, + arguments: { name: 'child', description: 'child', prompt: 'wait' }, }) expect(started.isError).toBe(false) const child = await requestEntered.promise diff --git a/packages/experimental/auto-review/tests/auto-review.spec.ts b/packages/experimental/auto-review/tests/auto-review.spec.ts index 096addd35b..e14d6c464a 100644 --- a/packages/experimental/auto-review/tests/auto-review.spec.ts +++ b/packages/experimental/auto-review/tests/auto-review.spec.ts @@ -1244,6 +1244,7 @@ describe('out-of-process delegation boundary', () => { if (schema === undefined) throw new Error('remote delegation tool schema is missing') appendHeader(session, [schema]) const args = { + name: 'remote-inspector', description: 'remote boundary', prompt: 'Inspect the child runtime permission boundary.', } diff --git a/packages/sdk/server/tests/built-scope-carrier.e2e.ts b/packages/sdk/server/tests/built-scope-carrier.e2e.ts index a9caf27ebf..e9f493fe8a 100644 --- a/packages/sdk/server/tests/built-scope-carrier.e2e.ts +++ b/packages/sdk/server/tests/built-scope-carrier.e2e.ts @@ -69,6 +69,7 @@ try { }); const run = await ctx.subagents.startActivation({ provider: "built-local", + name: "scope-child", childId: SessionId("built-child"), label: "built scope carrier", delivery: "caller", diff --git a/packages/subagent/subagent-claude-code/tests/loader-composition.e2e.ts b/packages/subagent/subagent-claude-code/tests/loader-composition.e2e.ts index 26543fb219..7784c19243 100644 --- a/packages/subagent/subagent-claude-code/tests/loader-composition.e2e.ts +++ b/packages/subagent/subagent-claude-code/tests/loader-composition.e2e.ts @@ -79,23 +79,23 @@ describe('product-provider public Loader composition', () => { tools: [ { name: 'subagent_codex', - parameterNames: ['cwd', 'description', 'prompt'], - required: ['description', 'prompt'], + parameterNames: ['cwd', 'description', 'name', 'prompt'], + required: ['name', 'description', 'prompt'], }, { name: 'subagent_claude_code', - parameterNames: ['cwd', 'description', 'prompt'], - required: ['description', 'prompt'], + parameterNames: ['cwd', 'description', 'name', 'prompt'], + required: ['name', 'description', 'prompt'], }, { name: 'subagent_claude_primary', - parameterNames: ['cwd', 'description', 'prompt'], - required: ['description', 'prompt'], + parameterNames: ['cwd', 'description', 'name', 'prompt'], + required: ['name', 'description', 'prompt'], }, { name: 'subagent_claude_secondary', - parameterNames: ['cwd', 'description', 'prompt'], - required: ['description', 'prompt'], + parameterNames: ['cwd', 'description', 'name', 'prompt'], + required: ['name', 'description', 'prompt'], }, ], jobTools: ['job_kill', 'job_list', 'job_output'], diff --git a/packages/subagent/subagent-codex/tests/loader-composition.e2e.ts b/packages/subagent/subagent-codex/tests/loader-composition.e2e.ts index a9972381ae..ad39873df1 100644 --- a/packages/subagent/subagent-codex/tests/loader-composition.e2e.ts +++ b/packages/subagent/subagent-codex/tests/loader-composition.e2e.ts @@ -69,18 +69,18 @@ describe('Codex provider public Loader composition', () => { tools: [ { name: 'subagent_codex', - parameterNames: ['cwd', 'description', 'prompt'], - required: ['description', 'prompt'], + parameterNames: ['cwd', 'description', 'name', 'prompt'], + required: ['name', 'description', 'prompt'], }, { name: 'subagent_codex_primary', - parameterNames: ['cwd', 'description', 'prompt'], - required: ['description', 'prompt'], + parameterNames: ['cwd', 'description', 'name', 'prompt'], + required: ['name', 'description', 'prompt'], }, { name: 'subagent_codex_secondary', - parameterNames: ['cwd', 'description', 'prompt'], - required: ['description', 'prompt'], + parameterNames: ['cwd', 'description', 'name', 'prompt'], + required: ['name', 'description', 'prompt'], }, ], jobTools: ['job_kill', 'job_list', 'job_output'], diff --git a/packages/subagent/tool-subagent-control/README.i18n.yaml b/packages/subagent/tool-subagent-control/README.i18n.yaml index 11ff64d4f0..6273f564ed 100644 --- a/packages/subagent/tool-subagent-control/README.i18n.yaml +++ b/packages/subagent/tool-subagent-control/README.i18n.yaml @@ -9,8 +9,8 @@ en: 465d36925c792167 zh: 269cac314f638827 /deepseek-ai-dsh-tool-subagent-control/summary: - en: b397bc87605b3dcc - zh: a97e97e30be53faa + en: 5b225b5c13d38808 + zh: 185508ceb2ad7d88 /deepseek-ai-dsh-tool-subagent-control/table-of-contents: en: d152484eb41ac6b4 zh: 09388d293f9be9cb @@ -90,8 +90,8 @@ en: 094e55d258f2ec2e zh: f364bc9046530bff /deepseek-ai-dsh-tool-subagent-control/model-experience/listing-result/what-the-model-sees: - en: a975a6e493671c84 - zh: a258b718855972ea + en: f888710beb3d325e + zh: 1869a221626dd2ce /deepseek-ai-dsh-tool-subagent-control/model-experience/listing-result/token-effect: en: d3ced2fbde9382ef zh: 8c7e904ed30f7353 diff --git a/packages/subagent/tool-subagent-control/README.md b/packages/subagent/tool-subagent-control/README.md index 8d7c17db78..9ece598020 100644 --- a/packages/subagent/tool-subagent-control/README.md +++ b/packages/subagent/tool-subagent-control/README.md @@ -9,7 +9,7 @@ English | [中文](README.zh.md) ## Summary -`dsh-tool-subagent-control` adds the global control tools for continuable children: `send_message` steers between a parent and child or between siblings, `interrupt_agent` stops a descendant’s current turn while keeping its inbox and descendants intact, and the separately loadable `list-agents` plugin discovers agents by id and description. Parents and continuable children inherit the same tool definitions and ordering. +`dsh-tool-subagent-control` adds the global control tools for continuable children: `send_message` steers between a parent and child or between siblings, `interrupt_agent` stops a descendant’s current turn while keeping its inbox and descendants intact, and the separately loadable `list-agents` plugin discovers agents by name and description. Parents and continuable children inherit the same tool definitions and ordering. ## Table of Contents @@ -148,7 +148,7 @@ Append-only; newly visible content follows the reusable request prefix and does #### What the model sees -One line per descendant in stable order: ` [] parent= depth= —