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 3e2da6553f..119380327b 100644
--- a/apps/cli/tests/profiles/headless/tests/fixtures/team-llm.mjs
+++ b/apps/cli/tests/profiles/headless/tests/fixtures/team-llm.mjs
@@ -189,9 +189,9 @@ class TeamFixtureAdapter extends LlmAdapter {
}
const chunks = identity === 'TEAM_WORKFLOW_CHILD'
? textChunks('Fresh workflow child complete.')
- : identity === '\nYou are teammate "researcher".\n'
+ : identity === '\nYou are teammate "researcher".\nYour Team Lead is named "lead".\nUse list_agents({}) to find your teammates and their names.\nTo message your Team Lead, use send_message({ target: "lead", message: "..." }).\nTo message another teammate, use send_message({ target: "", message: "..." }).\n'
? researcher(options.messages)
- : identity === '\nYou are teammate "implementer".\n'
+ : identity === '\nYou are teammate "implementer".\nYour Team Lead is named "lead".\nUse list_agents({}) to find your teammates and their names.\nTo message your Team Lead, use send_message({ target: "lead", message: "..." }).\nTo message another teammate, use send_message({ target: "", message: "..." }).\n'
? implementer(options.messages)
: lead(options.messages)
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 93e6e27ad4..33752b7812 100644
--- a/apps/cli/tests/profiles/headless/tests/headless.expected.e2e.ts
+++ b/apps/cli/tests/profiles/headless/tests/headless.expected.e2e.ts
@@ -862,9 +862,17 @@ describe('headless stream-json snapshots', () => {
"identityReminders": [
"
You are teammate "implementer".
+ Your Team Lead is named "lead".
+ Use list_agents({}) to find your teammates and their names.
+ To message your Team Lead, use send_message({ target: "lead", message: "..." }).
+ To message another teammate, use send_message({ target: "", message: "..." }).
",
"
You are teammate "researcher".
+ Your Team Lead is named "lead".
+ Use list_agents({}) to find your teammates and their names.
+ To message your Team Lead, use send_message({ target: "lead", message: "..." }).
+ To message another teammate, use send_message({ target: "", message: "..." }).
",
],
"memberEdges": 4,
diff --git a/packages/experimental/tool-agent-team/README.i18n.yaml b/packages/experimental/tool-agent-team/README.i18n.yaml
index 2b30aa79fc..4e2ee828f7 100644
--- a/packages/experimental/tool-agent-team/README.i18n.yaml
+++ b/packages/experimental/tool-agent-team/README.i18n.yaml
@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write packages/experimental/tool-agent-team/README.md
-README.md: bfa3fc7f466d4b7f405231de3de4cf648fc690de
-README.zh.md: 990e786fd69877af17cef339a696bb5e93d5925c
+README.md: 0918686d28f7212558aafa988a4b968c18aa8664
+README.zh.md: 8243f8471a67fe55d5a5d368d98e20c5519f42f3
diff --git a/packages/experimental/tool-agent-team/README.md b/packages/experimental/tool-agent-team/README.md
index bfa3fc7f46..0918686d28 100644
--- a/packages/experimental/tool-agent-team/README.md
+++ b/packages/experimental/tool-agent-team/README.md
@@ -125,7 +125,7 @@ Read these pages when the package-level contract is not enough. They move from t
#### What the model sees
-One shared system policy states the explicit-delegation requirement, shared-cwd behavior, filesystem stale-version recovery, Bash/formatter/codegen risk, task and write-scope coordination, Steer delivery, the no-retry mailbox rule, and the Lead's duty to wait before answering. All nine Team schemas are identical for Leads and teammates; execution enforces Lead-only operations. `spawn_teammate` prefixes its initial user message with `\nYou are teammate "".\n`, followed by a blank line and the task. The prefix contains no Team id and works when runtime context is disabled. Forks inherit history without an additional Lead identity message.
+One shared system policy states the explicit-delegation requirement, shared-cwd behavior, filesystem stale-version recovery, Bash/formatter/codegen risk, task and write-scope coordination, Steer delivery, the no-retry mailbox rule, and the Lead's duty to wait before answering. All nine Team schemas are identical for Leads and teammates; execution enforces Lead-only operations. `spawn_teammate` prefixes its initial user message with `\nYou are teammate "".\nYour Team Lead is named "lead".\nUse list_agents({}) to find your teammates and their names.\nTo message your Team Lead, use send_message({ target: "lead", message: "..." }).\nTo message another teammate, use send_message({ target: "", message: "..." }).\n`, followed by a blank line and the task. The prefix contains no Team id and works when runtime context is disabled. Forks inherit history without an additional Lead identity message.
#### Token effect
diff --git a/packages/experimental/tool-agent-team/README.zh.md b/packages/experimental/tool-agent-team/README.zh.md
index 990e786fd6..8243f8471a 100644
--- a/packages/experimental/tool-agent-team/README.zh.md
+++ b/packages/experimental/tool-agent-team/README.zh.md
@@ -125,7 +125,7 @@ member scope 上的一个 `team:policy` 段落说明共享的协作规则;固
#### 模型看到什么
-一段共享 system 策略会说明显式 delegation 要求、共享 cwd 行为、文件陈旧版本恢复、Bash/formatter/codegen 风险、task/write-scope 协调、Steer 投递、mailbox 不重试规则,以及 Lead 必须在回答前等待。Lead 与 teammate 的全部九个 Team schema 相同;执行时检查仅限 Lead 的操作权限。`spawn_teammate` 在初始 user 消息前加上 `\nYou are teammate "".\n`,接着是一个空行和任务。该前缀不含 Team id,禁用运行时上下文时也能生效。fork 继承历史,不额外添加 Lead 身份消息。
+一段共享 system 策略会说明显式 delegation 要求、共享 cwd 行为、文件陈旧版本恢复、Bash/formatter/codegen 风险、task/write-scope 协调、Steer 投递、mailbox 不重试规则,以及 Lead 必须在回答前等待。Lead 与 teammate 的全部九个 Team schema 相同;执行时检查仅限 Lead 的操作权限。`spawn_teammate` 在初始 user 消息前加上 `\nYou are teammate "".\nYour Team Lead is named "lead".\nUse list_agents({}) to find your teammates and their names.\nTo message your Team Lead, use send_message({ target: "lead", message: "..." }).\nTo message another teammate, use send_message({ target: "", message: "..." }).\n`,接着是一个空行和任务。该前缀不含 Team id,禁用运行时上下文时也能生效。fork 继承历史,不额外添加 Lead 身份消息。
#### Token 影响
diff --git a/packages/experimental/tool-agent-team/src/index.ts b/packages/experimental/tool-agent-team/src/index.ts
index 3ab4b77235..75dee88c70 100644
--- a/packages/experimental/tool-agent-team/src/index.ts
+++ b/packages/experimental/tool-agent-team/src/index.ts
@@ -193,7 +193,15 @@ function install(agent: Agent, ctx: Context, config: Required): () => vo
name: args.name,
description: args.description,
prompt: [
- { type: 'text', text: `\nYou are teammate "${args.name.trim()}".\n\n\n` },
+ { type: 'text', text: `
+You are teammate "${args.name.trim()}".
+Your Team Lead is named "lead".
+Use list_agents({}) to find your teammates and their names.
+To message your Team Lead, use send_message({ target: "lead", message: "..." }).
+To message another teammate, use send_message({ target: "", message: "..." }).
+
+
+` },
{ type: 'text', text: args.prompt },
],
context,
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 198e39f35f..c1c98c19e2 100644
--- a/packages/experimental/tool-agent-team/tests/tool-team.spec.ts
+++ b/packages/experimental/tool-agent-team/tests/tool-team.spec.ts
@@ -238,12 +238,12 @@ describe('dsh-tool-team', () => {
expect(renderPrompt(childAssembly)).toBe(leadPrompt)
expect(renderContextSnapshot(childAssembly)).not.toContain('team:identity')
expect(child.session.deriveMessages().some(message => message.content.some(block =>
- block.type === 'text' && block.text === '\nYou are teammate "tool-worker".\n\n\n'))).toBe(true)
+ block.type === 'text' && block.text === '\nYou are teammate "tool-worker".\nYour Team Lead is named "lead".\nUse list_agents({}) to find your teammates and their names.\nTo message your Team Lead, use send_message({ target: "lead", message: "..." }).\nTo message another teammate, use send_message({ target: "", message: "..." }).\n\n\n'))).toBe(true)
const initialPrompt = child.session.snapshotEvents().find(event => event.type === 'user/message'
&& event.data.source.kind === 'user')
expect(initialPrompt?.type === 'user/message'
? initialPrompt.data.content.flatMap(block => block.type === 'text' ? [block.text] : [])
- : []).toEqual(['\nYou are teammate "tool-worker".\n\n\n', 'stay available'])
+ : []).toEqual(['\nYou are teammate "tool-worker".\nYour Team Lead is named "lead".\nUse list_agents({}) to find your teammates and their names.\nTo message your Team Lead, use send_message({ target: "lead", message: "..." }).\nTo message another teammate, use send_message({ target: "", message: "..." }).\n\n\n', 'stay available'])
const denied = await execute(ctx, child, 'spawn_teammate', {
name: 'nested', description: 'not allowed', prompt: 'no',
@@ -279,14 +279,14 @@ describe('dsh-tool-team', () => {
expect(JSON.stringify(childRequest.messages)).not.toContain('Parent task')
}
expect(childRequest.messages.at(-1)?.content.slice(0, 2)).toEqual([
- { type: 'text', text: '\nYou are teammate "reviewer".\n\n\n' },
+ { type: 'text', text: '\nYou are teammate "reviewer".\nYour Team Lead is named "lead".\nUse list_agents({}) to find your teammates and their names.\nTo message your Team Lead, use send_message({ target: "lead", message: "..." }).\nTo message another teammate, use send_message({ target: "", message: "..." }).\n\n\n' },
{ type: 'text', text: 'Review the work' },
])
await using persisted = await ctx.sessionPersistence.open(childId, 'read')
const { events } = await persisted.read()
const initial = events.findLast(event => event.type === 'user/message' && event.data.source.kind === 'user')
expect(initial?.type === 'user/message' ? initial.data.content : []).toEqual([
- { type: 'text', text: '\nYou are teammate "reviewer".\n\n\n' },
+ { type: 'text', text: '\nYou are teammate "reviewer".\nYour Team Lead is named "lead".\nUse list_agents({}) to find your teammates and their names.\nTo message your Team Lead, use send_message({ target: "lead", message: "..." }).\nTo message another teammate, use send_message({ target: "", message: "..." }).\n\n\n' },
{ type: 'text', text: 'Review the work' },
])
})
@@ -377,7 +377,7 @@ describe('dsh-tool-team', () => {
})
const childId = spawnedChildId(ctx, lead, spawned)
await waitNoAgent(ctx, childId)
- const reminder = '\nYou are teammate "reviewer".\n\n\n'
+ const reminder = '\nYou are teammate "reviewer".\nYour Team Lead is named "lead".\nUse list_agents({}) to find your teammates and their names.\nTo message your Team Lead, use send_message({ target: "lead", message: "..." }).\nTo message another teammate, use send_message({ target: "", message: "..." }).\n\n\n'
const first = serializeRequest(adapter.requests[0]!).messages
expect(first.at(-1)?.content.slice(0, 2)).toEqual([{ type: 'text', text: reminder }, { type: 'text', text: 'Review the work' }])
expect(adapter.requests[1]!.messages.filter(message => message.content.some(block =>
@@ -419,7 +419,7 @@ describe('dsh-tool-team', () => {
expect(spawned.isError, text(spawned)).toBe(false)
await waitNoAgent(ctx, spawnedChildId(ctx, lead, spawned))
expect(serializeRequest(adapter.requests[0]!).messages.at(-1)?.content).toEqual([
- { type: 'text', text: '\nYou are teammate "reviewer".\n\n\n' },
+ { type: 'text', text: '\nYou are teammate "reviewer".\nYour Team Lead is named "lead".\nUse list_agents({}) to find your teammates and their names.\nTo message your Team Lead, use send_message({ target: "lead", message: "..." }).\nTo message another teammate, use send_message({ target: "", message: "..." }).\n\n\n' },
{ type: 'text', text: 'Review the work' },
])
})