Files
deepseek-harness/packages/team/agent-team

description, kind
description kind
Coordinate subagents through a durable shared task board in Team-enabled Sessions. package-reference

@deepseek-ai/dsh-agent-team

English | 中文

Summary

dsh-agent-team adds a durable shared task board to an existing subagent tree. Members use standard subagent tools to discover and contact one another. Team adds compare-and-set task ownership. Mount dsh-tool-agent-team for task tools. Members share one checkout.

Table of Contents


Use this package

New Sessions, including ordinary forks, default to Team mode off. See the Session-mode upgrade guide. Select Use Agent Teams in the root Session’s model and reasoning menu. Turning it off hides Team tools and guidance from subsequent steps throughout the tree while retaining tasks and subagents. The saved selection survives restart; a historical task board without a saved selection remains enabled.

Mode changes take effect without waiting for queued task mutations. Each mutation checks the current mode when it starts: an admitted operation finishes, while queued work is rejected if Team is still off when it starts. Enabling again permits subsequent operations. A failed save leaves an appended selection active; retrying the same selection saves without another mode record.

Add this package when subagents need durable shared task ownership and dependencies. Mount it with @deepseek-ai/dsh-tool-agent-team for model tools.

When to choose it

Choose it when delegated agents must divide and track shared work. Plain subagents suffice when no shared board is needed. Team does not create isolated working directories, coordinate across processes, or automatically release task owners.

Smallest working setup

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:

# smallest Team addition over a composition with continuable subagents
- name: '@deepseek-ai/dsh-agent-team'
- name: '@deepseek-ai/dsh-tool-agent-team'

For example, ask the model to start a subagent to review the diff and track its work on the task board. The one limit is optional and validated at startup:

Field Default Meaning
maxTasks 256 Maximum non-deleted tasks on the board

The generated configuration catalog is the exhaustive source for every accepted field and its JSDoc. A row that sets maxMembers, maxMessageBytes, or disposalTimeoutMs does not activate, and dsh names the key in its startup warning; the upgrade guide lists the replacements.

Teammates

Ask the Lead to start a subagent with a sibling-unique name and a description of its work: subagent starts fresh, while subagent_fork inherits completed turns. The returned full path addresses the teammate; descriptions may repeat.

Every root agent and its descendants form one Team. Task assignment accepts the root or any reachable continuable descendant discovered by the subagent runtime, at any depth. Historical roster records remain readable but grant no assignment authority.

Messages between teammates

Members use standard list_agents to discover the tree and send_message to contact another member by full agent path. The subagent runtime owns routing, sender attribution, and cold restoration.

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 root can reassign a task to itself or any reachable continuable descendant by full agent path. 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.

Waiting and interruption

The standard wait_agent tool waits for the exact caller’s next-step inbox and works without Team mode; see subagent controls. Task changes and Team mode changes do not end waits, add inbox input, or start idle Agents. Use send_message when an Agent needs to act on an update.

An ancestor stops a descendant’s current turn with the standard interrupt_agent tool. Interruption keeps unclaimed queued messages and leaves task ownership unchanged.

What success and failure look like

Success returns the committed task revision. Unknown owners, unready tasks, stale revisions, unauthorized mutations, and exhausted task limits report typed errors.


Understand the implementation

Implementation internals — click to expand

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.

Design philosophy

The service is built on four commitments:

  • One tree identity. The subagent runtime resolves the root and discovers descendants; Team maintains no second membership authority.
  • Durable log, derived state. The Lead log owns tasks and child catalog facts; each target Agent owns accepted messages.
  • Explicit authority. Every service method takes the exact live calling Agent; a task owner or the Lead mutates a task, and only the Lead reassigns one.
  • Bounds that fail loud. maxTasks is a validated deployment value, and exhaustion reports a typed error instead of reusing an id.

The inbox-only wait decision separates task commits from Agent input waiting.

Source map

File Role
src/index.ts Plugin entry, configuration validation, and task service registration
src/task-board.ts Task CAS commands, DAG validation, and derived views
src/journal.ts Serialized Lead-log transactions and commit notification
src/projection.ts Replay of saved mode and task records, publishing the agentTeam client view
src/task-view.ts Pure task readiness and write-overlap derivation shared by the task board and client view

Team identity and membership

The subagent service resolves the exact live caller’s root through subagents.rootOf(). Intermediate creators may be offline. An ordinary Session fork leads a new tree. Team uses that root Session as the board owner without a separate membership object.

Task assignees

Reassignment resolves the root or a continuable descendant through the same discovery used by list_agents. Historical team/member records remain in the Session log and cannot authorize assignment.

Messages and historical mailbox

Peer messaging, Steer delivery, cold resume, and sender framing belong to the subagent runtime. Historical team/message/queued and team/message/delivered records and team-message sources remain decodable but are never delivered or acknowledged.

Shared task board

Tasks are complete versioned snapshots. Mutations require expectedRevision; stale updates report TEAM_TASK_STALE_REVISION. Numeric task-<n> ids stay within the safe-integer range. Deleted tasks remain replay tombstones but do not consume maxTasks or appear in listTasks(). Normalized workspace-relative writeScopes warn about overlapping in-progress work without blocking claims or authorizing writes.

Durability model

Team requires sessionPersistence before activation. Service.init awaits registration of the agentTeam projection before publishing service readiness. The journal retains the returned handle and reads task state through stateOf(session); callers use the Team service rather than registering another reader.

Task mutations honor cancellation before appending team/task to the exact live root Session, then await the flush. Cancellation cannot retract an appended record. A failed flush or one with no participating listener raises TEAM_TASK_PERSISTENCE_UNCONFIRMED with the task id and revision: the task is already visible, but durability is unknown. Read that task before retrying. Task records remain log-only. No committed task or historical payload generation is rewritten.

The projection ignores historical roster and mailbox records without validating or retaining their payloads. It stores only the task board, saved mode, and recovery metadata. Incompatible projection checkpoints rebuild from the unchanged Session log; see the upgrade guide.

Disposal

Unloading the service unregisters the projection. The retained handle remains readable and folds Session events on demand while admitted work settles. Team owns no Agent: teammates remain under the subagent runtime, which owns their capacity, settlement, and teardown.

Browser projection

The agentTeam projection publishes non-deleted task views and any failure beside the last valid state. Historical roster and mailbox records cannot cause a task-board projection failure. A failed projection rejects task reads and mutations without appending task events. Mode selections can still be saved and applied, including disabling Team; the projection failure remains visible. Invalid mode payloads retain the last valid selection and publish a projection failure. The subsystem reference defines the wire types.

The Web UI displays tasks only. Ordinary subagent navigation owns the member list; task owner labels reuse Session and catalog data with an id fallback.


Further Exploration

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.


Model Experience

Task views and errors

What the model sees

The model reads task views through task-tool results. Model-facing and host views identify owners by ownerId; stale updates report the current revision. Task updates do not end wait_agent; send an explicit message when a member needs to act on an update.

Token effect

Each task result adds a compact task view. Task updates add no inbox messages.

KV Cache effect

Task records stay outside model history. Task results append after the reusable request prefix.

Known Limitations and Deferred Work

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.

  • Whole-view broadcasts — each task change sends the complete non-deleted board to connected browsers.

  • One process — members can observe shared filesystem edits; 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.

  • Notices reach live local members only — cold members are not restored, and idle members remain idle until explicitly resumed.

  • Communication stays within one tree — members cannot message unrelated Teams; only ancestors can interrupt descendants.

  • Membership needs a live Team root — members keep their Team role when an intermediate creator finishes or is released; a missing root leaves them without an active Team.

  • 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.

Dev Note

Working context for maintainers — click to expand

This Dev Note is working context for maintainers and is explicitly non-authoritative.

Future directions

Undecided directions include automatic ownership release and filesystem isolation via worktrees; neither is committed.