@deepseek-ai/dsh-experimental-agent-team 0.1.5-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.i18n.yaml +6 -0
- package/README.md +220 -0
- package/README.zh.md +220 -0
- package/lib/index.js +1894 -0
- package/lib/invariant.js +361 -0
- package/lib/typert.host.d.ts +3 -0
- package/lib/typert.host.js +867 -0
- package/lib/typert.remote-client.d.ts +32 -0
- package/lib/typert.remote-client.js +210 -0
- package/lib/types/activity.d.ts +23 -0
- package/lib/types/activity.js +85 -0
- package/lib/types/client.d.ts +3 -0
- package/lib/types/client.js +3 -0
- package/lib/types/error.d.ts +13 -0
- package/lib/types/error.js +23 -0
- package/lib/types/index.d.ts +137 -0
- package/lib/types/index.js +313 -0
- package/lib/types/invariant.d.ts +9 -0
- package/lib/types/invariant.js +26 -0
- package/lib/types/journal.d.ts +39 -0
- package/lib/types/journal.js +63 -0
- package/lib/types/lifecycle.d.ts +33 -0
- package/lib/types/lifecycle.js +85 -0
- package/lib/types/mailbox.d.ts +78 -0
- package/lib/types/mailbox.js +292 -0
- package/lib/types/persisted.d.ts +20 -0
- package/lib/types/persisted.js +20 -0
- package/lib/types/projection.d.ts +48 -0
- package/lib/types/projection.js +260 -0
- package/lib/types/roster.d.ts +113 -0
- package/lib/types/roster.js +446 -0
- package/lib/types/session-message.d.ts +11 -0
- package/lib/types/session-message.js +23 -0
- package/lib/types/task-board.d.ts +62 -0
- package/lib/types/task-board.js +275 -0
- package/lib/types/task-graph.d.ts +21 -0
- package/lib/types/task-graph.js +62 -0
- package/lib/types/types.d.ts +206 -0
- package/lib/types/types.js +26 -0
- package/lib/types/validation.d.ts +16 -0
- package/lib/types/validation.js +33 -0
- package/package.json +88 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 DeepSeek
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.i18n.yaml
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
|
|
2
|
+
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
|
3
|
+
# after editing either side, bring the other along and re-record with:
|
|
4
|
+
# pnpm run verify-translation-pairing --write packages/experimental/agent-team/README.md
|
|
5
|
+
README.md: 3aa5f8606c76111dc2a85ce505f7989b15cf3b78
|
|
6
|
+
README.zh.md: 342e3be4f09c7987dc0770ad11dffc8fb5278f39
|
package/README.md
ADDED
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Run a small team of named agents in one session: durable messages between members and a shared task board, for deployments composing the experimental Team plugins."
|
|
3
|
+
kind: "package-reference"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# @deepseek-ai/dsh-experimental-agent-team
|
|
7
|
+
|
|
8
|
+
English | [中文](README.zh.md)
|
|
9
|
+
|
|
10
|
+
## Summary
|
|
11
|
+
|
|
12
|
+
`dsh-experimental-agent-team` turns one coding session into a small working team: the session's agent becomes the Lead, creates named teammates for delegated work, exchanges durable messages with them, and tracks shared tasks on a common board. Messages and task state survive crashes, reloads, and interruptions, so a teammate that was offline receives its queued messages when it resumes. It provides no tools of its own — mount the sibling `dsh-experimental-tool-agent-team` so the model can create teammates, message them, and use the task board. It is published under its experimental name, carries no stability promise, and needs durable session storage to activate.
|
|
13
|
+
|
|
14
|
+
## Table of Contents
|
|
15
|
+
|
|
16
|
+
- [Use this package](#use-this-package)
|
|
17
|
+
- [Understand the implementation](#understand-the-implementation)
|
|
18
|
+
- [Further Exploration](#further-exploration)
|
|
19
|
+
- [Model Experience](#model-experience)
|
|
20
|
+
- [Known Limitations and Deferred Work](#known-limitations-and-deferred-work)
|
|
21
|
+
- [Dev Note](#dev-note)
|
|
22
|
+
|
|
23
|
+
-----
|
|
24
|
+
|
|
25
|
+
<a id="use-this-package"></a>
|
|
26
|
+
## Use this package
|
|
27
|
+
|
|
28
|
+
Add this package to a composition when one agent should run a small team of named helpers in its own working directory, with messages and task state that survive crashes and restarts. It ships no tools of its own: mount it together with `@deepseek-ai/dsh-experimental-tool-agent-team` so the model can create teammates, message them, and use the task board.
|
|
29
|
+
|
|
30
|
+
### When to choose it
|
|
31
|
+
|
|
32
|
+
Choose it when several agents must cooperate on one shared workspace and their roster, messages, and task state must survive crashes and restarts. Avoid it when teammates need separate working directories, when several processes must coordinate over one team, or when a task owner should be released automatically — none of those are supported. The team features need durable session storage to activate.
|
|
33
|
+
|
|
34
|
+
### Smallest working setup
|
|
35
|
+
|
|
36
|
+
<a id="smallest-working-setup"></a>
|
|
37
|
+
|
|
38
|
+
The smallest addition to an existing composition is durable session storage plus both Team packages:
|
|
39
|
+
|
|
40
|
+
```yaml
|
|
41
|
+
# smallest team setup — durable storage plus both Team packages
|
|
42
|
+
- name: '@deepseek-ai/dsh-session-persistence-jsonl'
|
|
43
|
+
- name: '@deepseek-ai/dsh-experimental-agent-team'
|
|
44
|
+
- name: '@deepseek-ai/dsh-experimental-tool-agent-team'
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
With the tools installed, the model does the rest on request — for example, "create a teammate named reviewer to check the diff", then "send reviewer the change summary". All limits are optional and validated at startup:
|
|
48
|
+
|
|
49
|
+
| Field | Default | Meaning |
|
|
50
|
+
|---|---|---|
|
|
51
|
+
| `maxMembers` | `8` | Maximum teammates a team may ever create, including failed ones |
|
|
52
|
+
| `maxTasks` | `256` | Maximum active tasks on the board |
|
|
53
|
+
| `maxPendingMessagesPerMember` | `64` | Maximum queued messages for one member |
|
|
54
|
+
| `maxMessageBytes` | `65,536` | Maximum size of one sent message |
|
|
55
|
+
| `disposalTimeoutMs` | `5,000` | Time allowed for shutdown cleanup |
|
|
56
|
+
|
|
57
|
+
The generated [configuration catalog](../../../docs/config-catalog.md#deepseek-aidsh-experimental-agent-team) is the exhaustive source for every accepted field and its JSDoc.
|
|
58
|
+
|
|
59
|
+
### Teammates
|
|
60
|
+
|
|
61
|
+
Ask the Lead to create a teammate: give it a unique lowercase name such as `reviewer` and describe its job. A teammate starts fresh with no memory of the Lead's conversation, or as a fork that inherits the Lead's completed turns; the creation request chooses which. Teammate names are permanent — even a teammate whose creation failed keeps its name, and no name is ever reused.
|
|
62
|
+
|
|
63
|
+
The roster shows every member with its role (`lead` or `teammate`) and current status: `running`, `idle`, `inactive` (a member that exists but is not loaded), `provisioning`, or `failed`. A member that is not loaded receives its messages when it wakes.
|
|
64
|
+
|
|
65
|
+
Only the Lead can create teammates or interrupt them.
|
|
66
|
+
|
|
67
|
+
### Messages between teammates
|
|
68
|
+
|
|
69
|
+
Any member can send a message to any other member or to the Lead. A live member receives it immediately; an offline member's messages queue and arrive when it resumes. Messages are never lost and never delivered twice.
|
|
70
|
+
|
|
71
|
+
Every message uses Steer: a running target receives it at the nearest step boundary, an idle target starts a turn, and an inactive teammate cold-resumes. The sender always sees the outcome — accepted by the target inbox, or retained as queued when delivery is temporarily unavailable. A queued message is already safely stored, so it must not be resent.
|
|
72
|
+
|
|
73
|
+
### Shared task board
|
|
74
|
+
|
|
75
|
+
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.
|
|
76
|
+
|
|
77
|
+
Tasks have an owner: a member claims a task to start work, completes it when done, releases it back, or reopens it; the Lead can assign a task to any member. Every change is compare-and-set: an update based on an outdated copy is rejected, so two members cannot silently overwrite each other's work.
|
|
78
|
+
|
|
79
|
+
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.
|
|
80
|
+
|
|
81
|
+
### Waiting and interruption
|
|
82
|
+
|
|
83
|
+
A member can wait for the next team change — a teammate's status, an incoming message, or a task update — instead of polling repeatedly; the wait reports only whether it timed out, and the caller re-reads the current state afterward.
|
|
84
|
+
|
|
85
|
+
The Lead can stop a teammate's current turn without deleting its queued messages; task ownership is unchanged.
|
|
86
|
+
|
|
87
|
+
### What success and failure look like
|
|
88
|
+
|
|
89
|
+
Success looks like a teammate appearing in the roster, a message reporting `accepted` or `queued`, and task revisions advancing with each change. Likely failures are reported as specific errors instead of silently corrupting state: sending to a name that is not a member, claiming a task that is not ready, editing with an outdated revision, or creating a teammate beyond the member limit.
|
|
90
|
+
|
|
91
|
+
-----
|
|
92
|
+
|
|
93
|
+
<a id="understand-the-implementation"></a>
|
|
94
|
+
## Understand the implementation
|
|
95
|
+
|
|
96
|
+
<details>
|
|
97
|
+
<summary>Implementation internals — click to expand</summary>
|
|
98
|
+
|
|
99
|
+
This section explains the design decisions behind the service and points at the code that realizes them; the observable behavior is fully covered in [Use this package](#use-this-package).
|
|
100
|
+
|
|
101
|
+
### Design philosophy
|
|
102
|
+
|
|
103
|
+
The service is built on one separation and three commitments:
|
|
104
|
+
|
|
105
|
+
- **Durable log, derived state.** The Lead Session log is the single source of truth; roster, mailbox, and task state are replayed from it on every read.
|
|
106
|
+
- **Process-local ownership.** All coordination lives in one process; the guarantee is retry plus de-duplication, never cross-process consensus.
|
|
107
|
+
- **Explicit authority.** Every service method takes the exact live calling `Agent`; only the Lead spawns, reassigns, or interrupts.
|
|
108
|
+
- **Bounds that fail loud.** Every limit is a validated deployment value, and exhaustion reports a typed error instead of reusing an id or name.
|
|
109
|
+
|
|
110
|
+
The [Agent Teams Agent Note](../../../.agents/notes/implemented/feature/2026-08-05-agent-teams.md) owns the identity, mailbox, task, and shared-checkout decisions.
|
|
111
|
+
|
|
112
|
+
### Source map
|
|
113
|
+
|
|
114
|
+
| File | Role |
|
|
115
|
+
|---|---|
|
|
116
|
+
| [`src/index.ts`](src/index.ts) | Plugin entry: `Config` schema, service registration, recovery scheduling |
|
|
117
|
+
| [`src/roster.ts`](src/roster.ts) | Team identity, membership resolution, provisioning, and roster teardown |
|
|
118
|
+
| [`src/mailbox.ts`](src/mailbox.ts) | Durable queue, target-local dispatch, acknowledgement, and recovery |
|
|
119
|
+
| [`src/task-board.ts`](src/task-board.ts) | Task CAS commands, DAG validation, and derived views |
|
|
120
|
+
| [`src/journal.ts`](src/journal.ts) | Serialized Lead-log transactions and commit notification |
|
|
121
|
+
| [`src/projection.ts`](src/projection.ts) | Strict replay projection that decodes and validates Team events |
|
|
122
|
+
| [`src/activity.ts`](src/activity.ts) | One-shot change waiters and disposal release |
|
|
123
|
+
| [`src/lifecycle.ts`](src/lifecycle.ts) | Shared admission cutoff and bounded settlement |
|
|
124
|
+
| [`src/invariant.ts`](src/invariant.ts) | Invariant companion that replays candidate events before append |
|
|
125
|
+
|
|
126
|
+
### Team identity and roster
|
|
127
|
+
|
|
128
|
+
Every ordinary runtime root is the implicit Lead of a Team whose `TeamId` equals its `SessionId`; there is no creation event, and durable state begins with the first member, message, or task record. `spawnTeammate()` first appends and flushes a `provisioning` member record, then asks the configured provider to create the reserved child; a provider failure appends a durable `failed` member. A fresh child starts with no Lead history; a fork child captures the Lead's completed-turn prefix once. Recovery reconciles an unterminated provisioning record against the child's independently persisted Session: a matching direct-parent and continuable descriptor plus a recorded initial user message produces `active`, and anything else produces `failed`. If recovery wins a same-process race, the creator accepts the terminal state or reports `TEAM_PROVISIONING_CONFLICT` and drains the child. Names are reserved by the first provisioning record and never reused.
|
|
129
|
+
|
|
130
|
+
### Durable mailbox
|
|
131
|
+
|
|
132
|
+
`sendMessage()` validates peer membership, appends `team/message/queued`, and flushes before attempting delivery. The target message begins with `Team message <id> from <name>:` and keeps the same id and sender in `TeamMessageSource`. A target receipt is acknowledged with `team/message/delivered` only after the target Session durably holds the message identity in its pending inbox or recorded history. Immediate admissions are serialized per target in durable queue order; recovery dispatches queued-minus-delivered records in the same order. Delivery folds both live and persisted target inbox/history state before retrying, so a crash between inbox acceptance and model claim does not duplicate the message. The guarantee is process-local retry plus target-Session de-duplication, not cross-process exactly-once delivery.
|
|
133
|
+
|
|
134
|
+
Lead delivery calls `Agent.steer()` directly. Teammate delivery uses the continuation owner's host-only Steer path, which preserves the Team sender source while authorizing the Lead-to-child edge and cold-resuming inactive targets. Sibling messages never impersonate the Lead through the public adjacent-Agent messaging operation.
|
|
135
|
+
|
|
136
|
+
### Shared task board
|
|
137
|
+
|
|
138
|
+
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-<n>` 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.
|
|
139
|
+
|
|
140
|
+
### Waiting and interruption
|
|
141
|
+
|
|
142
|
+
`waitForChange()` waits for one roster, task, mailbox, or live-status edge that occurs after registration, from ten seconds through one hour, and reports only whether it timed out; runtime disposal releases current waits. Cancellation preserves an Error reason or reports a non-Error reason through `TEAM_WAIT_ABORTED`. `interrupt()` is Lead-only and delegates to the continuable-subagent interrupt path, which cancels only a live teammate's current turn with `keepInbox`; it neither releases task ownership nor deletes durable mail.
|
|
143
|
+
|
|
144
|
+
### Durability model
|
|
145
|
+
|
|
146
|
+
Team events are appended to the exact live Lead Session and flushed before the operation reports success or wakes waiters. `team/member`, `team/task`, `team/message/queued`, and `team/message/delivered` are log-only: they never enter the conversation surface, so derived model history is untouched by coordination records. Session event `seq` and `time` own ordering and timing; snapshots do not duplicate them. The `./invariant` companion replays each candidate Team event against its committed prefix and rejects invalid transitions before append.
|
|
147
|
+
|
|
148
|
+
### Disposal
|
|
149
|
+
|
|
150
|
+
Disposal closes admission, aborts and awaits admitted creation and mailbox-dispatch transactions, then asks the continuation owner to release the roster's exact live direct children and their descendants; non-Team continuable children of the Lead remain untouched. Cleanup failures make disposal fail visibly, bounded by `disposalTimeoutMs`.
|
|
151
|
+
|
|
152
|
+
</details>
|
|
153
|
+
|
|
154
|
+
-----
|
|
155
|
+
|
|
156
|
+
<a id="further-exploration"></a>
|
|
157
|
+
## Further Exploration
|
|
158
|
+
|
|
159
|
+
Read these pages when the package-level contract is not enough. They move from the shared subsystem types to the tool surface and the decisions behind the design.
|
|
160
|
+
|
|
161
|
+
- [Agent Teams subsystem](../../../docs/subsystems/agent-team.md) — durable Team types and the `ctx.agentTeams` service API.
|
|
162
|
+
- [tool-agent-team package](../tool-agent-team/README.md) — the tools that let the model create, message, and coordinate teammates.
|
|
163
|
+
- [Agent Teams Agent Note](../../../.agents/notes/implemented/feature/2026-08-05-agent-teams.md) — identity, mailbox, task, and shared-checkout decisions.
|
|
164
|
+
- [Experimental package decision](../../../.agents/notes/implemented/architecture/2026-08-18-experimental-agent-teams-packages.md) — placement, publication, and dependency isolation.
|
|
165
|
+
|
|
166
|
+
-----
|
|
167
|
+
|
|
168
|
+
<a id="model-experience"></a>
|
|
169
|
+
|
|
170
|
+
### Browser Remote
|
|
171
|
+
|
|
172
|
+
`TeamService` owns the generated `agentTeams/view`, `agentTeams/createTask`, and `agentTeams/updateTask` Remote methods beside the roster, mailbox, task, and lifecycle operations. The `./remote` export supplies the Client contribution mounted by the Web UI, while `./client` re-exports the request, view, and task-mutation result types that are safe in a browser compilation face. Typert retains transport failures in its outer `RemoteResult`; create and update rejections remain explicit domain results inside a successful transport response, with stale update revisions distinguished as task conflicts.
|
|
173
|
+
|
|
174
|
+
## Model Experience
|
|
175
|
+
|
|
176
|
+
### Peer messages
|
|
177
|
+
|
|
178
|
+
#### What the model sees
|
|
179
|
+
|
|
180
|
+
Each delivered peer message is a user-role message. A short first text block names its stable message id and sender; the sender's original content blocks follow unchanged. Roster, task, and mailbox records are log-only and never enter derived model history.
|
|
181
|
+
|
|
182
|
+
#### Token effect
|
|
183
|
+
|
|
184
|
+
Each peer delivery adds the sender prefix plus message content to the target history. Task and roster mutations add no model tokens; their model-facing representation belongs to `@deepseek-ai/dsh-experimental-tool-agent-team` results.
|
|
185
|
+
|
|
186
|
+
#### KV Cache effect
|
|
187
|
+
|
|
188
|
+
Peer messages append after the target's reusable history prefix. Cold resume reuses the persisted conversation before appending a previously undelivered item.
|
|
189
|
+
|
|
190
|
+
## Known Limitations and Deferred Work
|
|
191
|
+
|
|
192
|
+
<a id="known-limitations-and-deferred-work"></a>
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
These limits describe what a team cannot do yet or what needs special operational care. They are current package constraints, not a comparison with other coordination mechanisms.
|
|
196
|
+
|
|
197
|
+
- **Experimental prototype with no stability promise** — the package is public, but its contracts can change freely while it incubates.
|
|
198
|
+
- **One process and one shared checkout** — members share cwd and observe edits immediately; this package provides no worktree, remote member, merge, or filesystem lock.
|
|
199
|
+
- **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.
|
|
200
|
+
- **Flat immutable roster** — only the Lead creates direct teammates; there is no nested Team, rename, deletion, or name reuse.
|
|
201
|
+
- **No automatic ownership release** — idle, interruption, process exit, and failed work do not release a task owner.
|
|
202
|
+
- **Mailbox is not cross-process exactly-once** — concurrent harness processes over one Team are unsupported.
|
|
203
|
+
|
|
204
|
+
<a id="dev-note"></a>
|
|
205
|
+
### Dev Note
|
|
206
|
+
|
|
207
|
+
<details>
|
|
208
|
+
<summary>Working context for maintainers — click to expand</summary>
|
|
209
|
+
|
|
210
|
+
This Dev Note is working context for maintainers and is explicitly non-authoritative.
|
|
211
|
+
|
|
212
|
+
#### Promotion
|
|
213
|
+
|
|
214
|
+
Promotion to a product-role group requires reviewing the public contract, limitations, test evidence, release payload, runtime dependents, and a named stable owner, per the [experimental subtree rules](../AGENTS.md).
|
|
215
|
+
|
|
216
|
+
#### Future directions
|
|
217
|
+
|
|
218
|
+
Undecided directions include nested Teams, automatic ownership release policies, cross-process mailbox transactions, and filesystem isolation via worktrees; none of these are committed.
|
|
219
|
+
|
|
220
|
+
</details>
|
package/README.zh.md
ADDED
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "在一个会话中运行一个小型具名 agent 团队:成员之间的持久消息与共享任务板,供组合实验性 Team 插件的部署方阅读。"
|
|
3
|
+
kind: "package-reference"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# @deepseek-ai/dsh-experimental-agent-team
|
|
7
|
+
|
|
8
|
+
[English](README.md) | 中文
|
|
9
|
+
|
|
10
|
+
## 概述
|
|
11
|
+
|
|
12
|
+
`dsh-experimental-agent-team` 把一个编码会话变成一个小型工作团队:会话中的 agent 成为 Lead,创建具名 teammate 处理委派的工作,与它们交换持久消息,并在公共任务板上跟踪共享任务。消息与任务状态能挺过崩溃、reload 与中断,因此离线的 teammate 会在恢复后收到排队的消息。它本身不提供任何工具——请挂载兄弟包 `dsh-experimental-tool-agent-team`,让模型能够创建 teammate、给它们发消息并使用任务板。它以实验性名称公开发布、不承诺稳定性,并且需要持久会话存储才能激活。
|
|
13
|
+
|
|
14
|
+
## 目录
|
|
15
|
+
|
|
16
|
+
- [使用本包](#use-this-package)
|
|
17
|
+
- [理解实现](#understand-the-implementation)
|
|
18
|
+
- [进一步探索](#further-exploration)
|
|
19
|
+
- [模型体验](#model-experience)
|
|
20
|
+
- [已知限制与延期工作](#known-limitations-and-deferred-work)
|
|
21
|
+
- [开发备注](#dev-note)
|
|
22
|
+
|
|
23
|
+
-----
|
|
24
|
+
|
|
25
|
+
<a id="use-this-package"></a>
|
|
26
|
+
## 使用本包
|
|
27
|
+
|
|
28
|
+
当一个 agent 应该在自己的工作目录中运行一支小型具名助手团队、且消息与任务状态需要挺过崩溃与重启时,把本包加入组合。它本身不带工具:请与 `@deepseek-ai/dsh-experimental-tool-agent-team` 一起挂载,让模型能够创建 teammate、给它们发消息并使用任务板。
|
|
29
|
+
|
|
30
|
+
### 何时选择
|
|
31
|
+
|
|
32
|
+
当多个 agent 必须在同一个共享工作区协作、且 roster、消息与任务状态需要挺过崩溃与重启时,选择它。当 teammate 需要独立工作目录、多个进程需要协调同一支团队、或任务 owner 需要自动释放时,请不要选择——这些都不受支持。团队功能需要持久会话存储才能激活。
|
|
33
|
+
|
|
34
|
+
### 最小工作配置
|
|
35
|
+
|
|
36
|
+
<a id="smallest-working-setup"></a>
|
|
37
|
+
|
|
38
|
+
对现有组合的最小增量是持久会话存储加两个 Team 包:
|
|
39
|
+
|
|
40
|
+
```yaml
|
|
41
|
+
# smallest team setup — durable storage plus both Team packages
|
|
42
|
+
- name: '@deepseek-ai/dsh-session-persistence-jsonl'
|
|
43
|
+
- name: '@deepseek-ai/dsh-experimental-agent-team'
|
|
44
|
+
- name: '@deepseek-ai/dsh-experimental-tool-agent-team'
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
工具安装后,模型会按请求完成其余工作——例如先「创建一个名为 reviewer 的 teammate 检查 diff」,再「把变更摘要发给 reviewer」。所有限制都是可选的,并在启动时校验:
|
|
48
|
+
|
|
49
|
+
| 字段 | 默认值 | 含义 |
|
|
50
|
+
|---|---|---|
|
|
51
|
+
| `maxMembers` | `8` | 一支团队最多可创建的 teammate 数,包括失败的 |
|
|
52
|
+
| `maxTasks` | `256` | 任务板上最多的活动任务数 |
|
|
53
|
+
| `maxPendingMessagesPerMember` | `64` | 单个成员最多可排队的消息数 |
|
|
54
|
+
| `maxMessageBytes` | `65,536` | 单条发送消息的最大尺寸 |
|
|
55
|
+
| `disposalTimeoutMs` | `5,000` | 关闭清理允许的时间 |
|
|
56
|
+
|
|
57
|
+
生成的[配置目录](../../../docs/config-catalog.zh.md#deepseek-aidsh-experimental-agent-team)是每个受支持字段及其 JSDoc 的穷尽式真源。
|
|
58
|
+
|
|
59
|
+
### Teammate
|
|
60
|
+
|
|
61
|
+
请 Lead 创建 teammate:给它一个唯一的小写名字(例如 `reviewer`)并描述其职责。teammate 可以 fresh 启动(不携带 Lead 对话的任何记忆),也可以作为 fork 启动(继承 Lead 已完成的轮次);创建请求决定用哪种。teammate 名字是永久的——即使创建失败的 teammate 也保留其名字,任何名字都不会被复用。
|
|
62
|
+
|
|
63
|
+
roster 显示每个成员的职责(`lead` 或 `teammate`)与当前状态:`running`、`idle`、`inactive`(存在但未加载的成员)、`provisioning` 或 `failed`。未加载的成员会在唤醒后收到其消息。
|
|
64
|
+
|
|
65
|
+
只有 Lead 可以创建 teammate 或中断它们。
|
|
66
|
+
|
|
67
|
+
### teammate 之间的消息
|
|
68
|
+
|
|
69
|
+
任何成员都可以向任何其他成员或 Lead 发送消息。live 成员会立即收到;离线成员的消息会排队,并在其恢复后到达。消息不会丢失,也绝不会重复投递。
|
|
70
|
+
|
|
71
|
+
每条消息都使用 Steer:running target 在最近的步骤边界收到消息,idle target 启动一个轮次,inactive teammate 则冷恢复。发送方始终能看到结果——target inbox 已接受,或在投递暂时不可用时保留为 queued。排队的消息已经安全存储,因此绝不能重发。
|
|
72
|
+
|
|
73
|
+
### 共享任务板
|
|
74
|
+
|
|
75
|
+
任何成员都可以添加任务,包含标题、详情、对其他任务的可选依赖,以及可选的文件触及提示。只有其全部依赖完成后,任务才可 claim。
|
|
76
|
+
|
|
77
|
+
任务有 owner:成员 claim 任务开始工作,完成后标记完成、释放回板或重新打开;Lead 可以把任务分配给任意成员。每次变更都是 compare-and-set:基于过期副本的更新会被拒绝,因此两个成员不会悄悄覆盖彼此的成果。
|
|
78
|
+
|
|
79
|
+
当两个 in-progress 任务计划触及重叠路径时,文件提示会产生警告——它们绝不阻止任何操作。已删除任务保留在历史中,但从活动列表中消失。
|
|
80
|
+
|
|
81
|
+
### 等待与中断
|
|
82
|
+
|
|
83
|
+
成员可以等待下一次团队变化——teammate 的状态、新消息或任务更新——而不必反复轮询;等待只报告是否超时,调用方随后重新读取当前状态。
|
|
84
|
+
|
|
85
|
+
Lead 可以停止 teammate 的当前轮次,而不会删除其排队的消息;任务归属不变。
|
|
86
|
+
|
|
87
|
+
### 成功与失败的表现
|
|
88
|
+
|
|
89
|
+
成功的表现是:teammate 出现在 roster 中、消息报告 `accepted` 或 `queued`、任务 revision 随每次变更递增。可能的失败会以具体错误报告,而不会悄悄破坏状态:发给不存在的成员名字、claim 尚未就绪的任务、用过期 revision 编辑、或超出成员上限创建 teammate。
|
|
90
|
+
|
|
91
|
+
-----
|
|
92
|
+
|
|
93
|
+
<a id="understand-the-implementation"></a>
|
|
94
|
+
## 理解实现
|
|
95
|
+
|
|
96
|
+
<details>
|
|
97
|
+
<summary>实现细节——点击展开</summary>
|
|
98
|
+
|
|
99
|
+
本节解释服务背后的设计决策并指出实现它们的代码位置;可观察行为已在[使用本包](#use-this-package)中完整说明。
|
|
100
|
+
|
|
101
|
+
### 设计理念
|
|
102
|
+
|
|
103
|
+
本服务建立在一个分离与三项承诺之上:
|
|
104
|
+
|
|
105
|
+
- **持久日志,派生状态。** Lead Session 日志是唯一真源;roster、mailbox 与任务状态每次读取都从中回放。
|
|
106
|
+
- **进程内归属。** 所有协作都位于单一进程;保证是重试加去重,绝不是跨进程共识。
|
|
107
|
+
- **显式权限。** 每个服务方法都接收精确的 live 调用 `Agent`;只有 Lead 可以 spawn、reassign 或 interrupt。
|
|
108
|
+
- **边界大声失败。** 每个限制都是经过校验的部署值,耗尽时报告类型化错误,而不是复用 id 或名字。
|
|
109
|
+
|
|
110
|
+
[Agent Teams Agent Note](../../../.agents/notes/implemented/feature/2026-08-05-agent-teams.zh.md)负责身份、mailbox、任务与共享 checkout 决策。
|
|
111
|
+
|
|
112
|
+
### 源码地图
|
|
113
|
+
|
|
114
|
+
| 文件 | 职责 |
|
|
115
|
+
|---|---|
|
|
116
|
+
| [`src/index.ts`](src/index.ts) | 插件入口:`Config` schema、服务注册、恢复调度 |
|
|
117
|
+
| [`src/roster.ts`](src/roster.ts) | Team 身份、成员关系解析、provisioning 与 roster 拆除 |
|
|
118
|
+
| [`src/mailbox.ts`](src/mailbox.ts) | 持久队列、目标本地投递、确认与恢复 |
|
|
119
|
+
| [`src/task-board.ts`](src/task-board.ts) | 任务 CAS 命令、DAG 校验与派生视图 |
|
|
120
|
+
| [`src/journal.ts`](src/journal.ts) | 串行化的 Lead 日志事务与提交通知 |
|
|
121
|
+
| [`src/projection.ts`](src/projection.ts) | 解码并校验 Team 事件的严格回放投影 |
|
|
122
|
+
| [`src/activity.ts`](src/activity.ts) | 一次性变更等待者与 dispose 释放 |
|
|
123
|
+
| [`src/lifecycle.ts`](src/lifecycle.ts) | 共享准入截止与有界结算 |
|
|
124
|
+
| [`src/invariant.ts`](src/invariant.ts) | 在 append 前回放候选事件的不变式伴生插件 |
|
|
125
|
+
|
|
126
|
+
### Team 身份与 roster
|
|
127
|
+
|
|
128
|
+
每个普通运行时 root 都是一个隐式 Team 的 Lead,其 `TeamId` 等于 `SessionId`;不存在创建事件,持久状态从第一条成员、消息或任务记录开始。`spawnTeammate()` 先追加并 flush 一条 `provisioning` 成员记录,再要求配置的 provider 创建预留 child;provider 失败会追加一条持久的 `failed` 成员。fresh child 不携带 Lead 历史;fork child 只捕获一次 Lead 的已完成 turn 前缀。恢复把未终结的 provisioning 记录对照 child 独立持久化的 Session 进行对账:直接 parent 与 continuable descriptor 匹配、且初始用户消息已记录则产生 `active`,其他任何情况都产生 `failed`。如果恢复在同进程竞争中先完成,creator 会接受终态,或报告 `TEAM_PROVISIONING_CONFLICT` 并 drain 该 child。名字由第一条 provisioning 记录保留,且永不复用。
|
|
129
|
+
|
|
130
|
+
### 持久 mailbox
|
|
131
|
+
|
|
132
|
+
`sendMessage()` 校验 peer 成员关系,追加 `team/message/queued` 并在尝试投递前 flush。目标消息以 `Team message <id> from <name>:` 开头,并在 `TeamMessageSource` 中保留同一 id 与发送者。只有目标 Session 在 pending inbox 或已记录历史中持久持有消息身份后,才会以 `team/message/delivered` 确认投递。即时准入按目标与持久队列顺序串行化;恢复按同一顺序重新投递 queued-minus-delivered 记录。重试前会同时折叠 live 与持久目标 inbox/历史状态,因此 inbox 已接受但模型尚未 claim 时发生崩溃不会复制消息。该保证是进程内重试加 target Session 去重,而不是跨进程 exactly-once 投递。
|
|
133
|
+
|
|
134
|
+
投递给 Lead 时直接调用 `Agent.steer()`。投递给 teammate 时使用 continuation owner 的 host-only Steer 路径;该路径会保留 Team 发送者 source,同时授权 Lead-to-child edge 并冷恢复 inactive target。sibling 消息绝不会通过公开的相邻 Agent 消息操作伪装成 Lead。
|
|
135
|
+
|
|
136
|
+
### 共享任务板
|
|
137
|
+
|
|
138
|
+
任务是完整版本化快照;每次变更都携带 `expectedRevision`,陈旧调用方会收到 `TEAM_TASK_STALE_REVISION`,而不会覆盖更新的值。数字 `task-<n>` id 的后缀必须是安全整数,id 空间耗尽时报告 `TEAM_TASK_LIMIT`,而不是复用最后一个 id。已删除任务作为 tombstone 保留以供回放与维持 id 稳定,但不占用 `maxTasks`,也不出现在 `listTasks()` 中。`writeScopes` 是规范化后的 workspace 相对前缀;视图会对与 in-progress 任务的重叠发出警告,但绝不阻止 claim 或授予写权限。
|
|
139
|
+
|
|
140
|
+
### 等待与中断
|
|
141
|
+
|
|
142
|
+
`waitForChange()` 等待注册之后发生的下一条 roster、task、mailbox 或实时状态边,时长从 10 秒到 1 小时,并且只报告是否超时;运行时 dispose 会释放当前等待。取消会保留 Error reason;非 Error reason 则通过 `TEAM_WAIT_ABORTED` 报告。`interrupt()` 仅限 Lead,委托 continuable-subagent 的 interrupt 路径,以 `keepInbox` 只取消 live teammate 的当前 turn;它既不释放任务 owner,也不删除持久 mail。
|
|
143
|
+
|
|
144
|
+
### 持久性模型
|
|
145
|
+
|
|
146
|
+
Team 事件追加到精确的 live Lead Session,并在操作报告成功或唤醒等待者之前 flush。`team/member`、`team/task`、`team/message/queued` 与 `team/message/delivered` 仅存在于日志:它们从不进入会话表面,因此派生模型历史不受协作记录影响。顺序与时间由 Session event 的 `seq` 与 `time` 负责,快照不重复保存。`./invariant` 伴生插件把每条候选 Team event 对照已提交前缀回放,并在 append 前拒绝非法转换。
|
|
147
|
+
|
|
148
|
+
### Dispose
|
|
149
|
+
|
|
150
|
+
dispose 会关闭准入、中止并等待已获准的创建与 mailbox dispatch 事务,再让 continuation owner 释放 roster 中确切的 live direct child 及其后代;Lead 的非 Team continuable child 不受影响。cleanup 失败会让 dispose 明确失败,并以 `disposalTimeoutMs` 为上限。
|
|
151
|
+
|
|
152
|
+
</details>
|
|
153
|
+
|
|
154
|
+
-----
|
|
155
|
+
|
|
156
|
+
<a id="further-exploration"></a>
|
|
157
|
+
## 进一步探索
|
|
158
|
+
|
|
159
|
+
当包级约定不够用时阅读以下页面。它们从共享子系统类型逐步进入工具表面与设计背后的决策。
|
|
160
|
+
|
|
161
|
+
- [Agent Teams 子系统](../../../docs/subsystems/agent-team.zh.md)——持久 Team 类型与 `ctx.agentTeams` 服务 API。
|
|
162
|
+
- [tool-agent-team 包](../tool-agent-team/README.zh.md)——让模型创建、消息与协调 teammate 的工具。
|
|
163
|
+
- [Agent Teams Agent Note](../../../.agents/notes/implemented/feature/2026-08-05-agent-teams.zh.md)——身份、mailbox、任务与共享 checkout 决策。
|
|
164
|
+
- [实验包决策](../../../.agents/notes/implemented/architecture/2026-08-18-experimental-agent-teams-packages.zh.md)——位置、公开发布与依赖隔离。
|
|
165
|
+
|
|
166
|
+
-----
|
|
167
|
+
|
|
168
|
+
<a id="model-experience"></a>
|
|
169
|
+
|
|
170
|
+
### 浏览器 Remote
|
|
171
|
+
|
|
172
|
+
`TeamService` 除了 roster、mailbox、task 与 lifecycle operation,还直接负责生成式 `agentTeams/view`、`agentTeams/createTask` 与 `agentTeams/updateTask` Remote method。`./remote` 导出由 Web UI 挂载的 Client contribution,`./client` 则重新导出可在浏览器 compilation face 中安全使用的 request、view 与 task mutation result type。Typert 在外层 `RemoteResult` 中保留 transport failure;create 与 update rejection 则作为 transport 成功响应中的显式 domain result,其中过期的 update revision 会区分为 task conflict。
|
|
173
|
+
|
|
174
|
+
## 模型体验
|
|
175
|
+
|
|
176
|
+
### Peer 消息
|
|
177
|
+
|
|
178
|
+
#### 模型看到什么
|
|
179
|
+
|
|
180
|
+
每条已投递 peer 消息都是用户角色消息。第一个短文本块包含稳定消息 id 与发送者,之后原样附加发送者的内容块。roster、task 与 mailbox 记录仅存在于日志,绝不进入派生模型历史。
|
|
181
|
+
|
|
182
|
+
#### Token 影响
|
|
183
|
+
|
|
184
|
+
每次 peer 投递都会把发送者前缀与消息内容加入 target 历史。任务与 roster 变更不增加模型 token;其面向模型的呈现属于 `@deepseek-ai/dsh-experimental-tool-agent-team` 结果。
|
|
185
|
+
|
|
186
|
+
#### KV Cache 影响
|
|
187
|
+
|
|
188
|
+
Peer 消息追加在 target 可复用历史前缀之后。冷恢复会先复用持久对话,再追加尚未投递的消息。
|
|
189
|
+
|
|
190
|
+
## 已知限制与延期工作
|
|
191
|
+
|
|
192
|
+
<a id="known-limitations-and-deferred-work"></a>
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
这些限制说明一支团队目前不能做什么、或何时需要特别运维。它们是当前包约束,不是与其他协作机制的对比。
|
|
196
|
+
|
|
197
|
+
- **实验原型,无稳定性承诺**——本包公开发布,但孵化期间约定仍可自由变更。
|
|
198
|
+
- **单进程、共享 checkout**——成员共享 cwd,修改立即可见;本包不提供 worktree、远端成员、merge 或文件锁。
|
|
199
|
+
- **write scope 仅作提示**——Bash、formatter、代码生成器与直接外部写入可以绕过文件版本检查;Lead 必须协调 owner 并检查最终 diff。
|
|
200
|
+
- **扁平且不可变的 roster**——只有 Lead 可以创建直接 teammate;不支持嵌套 Team、重命名、删除或名字复用。
|
|
201
|
+
- **不会自动释放 owner**——idle、interrupt、进程退出与工作失败都不会释放任务 owner。
|
|
202
|
+
- **mailbox 不保证跨进程 exactly-once**——不支持多个 harness 进程并发操作同一 Team。
|
|
203
|
+
|
|
204
|
+
<a id="dev-note"></a>
|
|
205
|
+
### 开发备注
|
|
206
|
+
|
|
207
|
+
<details>
|
|
208
|
+
<summary>维护者的工作上下文——点击展开</summary>
|
|
209
|
+
|
|
210
|
+
本开发备注是维护者的工作上下文,明确不具权威性。
|
|
211
|
+
|
|
212
|
+
#### Promotion
|
|
213
|
+
|
|
214
|
+
promotion 到产品角色组需要按[实验子树规则](../AGENTS.md)审查公共约定、限制、测试证据、发布载荷、运行时依赖与具名稳定 owner。
|
|
215
|
+
|
|
216
|
+
#### 未来方向
|
|
217
|
+
|
|
218
|
+
尚未决定的探索方向包括嵌套 Team、自动释放 owner 的策略、跨进程 mailbox 事务,以及通过 worktree 实现文件系统隔离;这些都没有承诺。
|
|
219
|
+
|
|
220
|
+
</details>
|