# Agent Duplication

> Canonical path: `specs/agent/duplicate.md`
> Status: living-spec
> Scope: Managed-agent duplication, target runtime placement, server-resource boundaries, and web batch behavior.

## Terminology

The product action is **duplicate**, not clone. Duplication creates a new independent agent definition. It does not imply an exact copy of machine-local state.

User-facing labels may use the language-appropriate equivalent of “Duplicate agent” or “复制智能体”. API routes, DTOs, implementation symbols, tests, and agent-duplication i18n keys use `duplicate` consistently.

## Single-Duplicate API

A duplicate request creates exactly one agent:

```http
POST /api/v1/workspaces/:workspaceId/agents/:agentId/duplicate
```

The request accepts:

```json
{
  "mode": "config_only | with_resources",
  "name": "backend-copy-2",
  "displayName": "Backend Copy 2",
  "machineId": "mac_target",
  "runtime": "codex",
  "channelIds": ["chn_1"]
}
```

`machineId` and `runtime` are optional. A missing or blank field independently inherits the corresponding value from the source agent. Batch quantity is a client concern and must not be added to this endpoint.

## Target Eligibility

The server resolves and validates the target pair before creating an agent:

- the caller may manage the source agent;
- the target machine belongs to the workspace and is managed by the caller;
- the target machine has an active authenticated daemon connection;
- the target runtime is a globally supported agent runtime;
- the target runtime is present in the connected machine's live runtime catalog;
- a AgentTeam-hosted model is executable through the target runtime's wire family and the target machine's advertised MaaS capability;
- reasoning effort is normalized for the target runtime.

Machine online state and the live runtime catalog come from the connected daemon, as specified in [`../product/machines.md`](../product/machines.md). Persisted last-known machine metadata is not sufficient to authorize placement. Duplication itself changes only server-owned definitions and bindings; the Desktop materializes them through the existing catalog and reconciliation flow, with no duplicate-specific Desktop command.

A AgentTeam-hosted target compatibility failure must reject the request before creation. Duplication does not add a Desktop capability or provider preflight protocol. Local and custom provider configuration is preserved without silent rewriting and remains subject to the existing Desktop reconciliation/start validation, which owns explicit runtime-specific errors.

## Duplicated Data

Every duplicate inherits the source agent's server-owned definition fields, including display metadata, model/provider configuration, auto-wake policy, role binding, and requested channel membership.

`config_only` does not copy separately managed resources. `with_resources` additionally copies:

- Skill grants;
- knowledge-base grants when knowledge-base management is enabled;
- an independent Memory derived through the resource-copy service.

Duplication never copies machine-local or live execution state:

- working directory contents or path selection;
- runtime session identifiers;
- recovery points;
- daemon-local provider/runtime configuration;
- current process state or runtime files.

A post-create role/resource failure rolls back the newly created agent. When a forked Memory has already been bound successfully, agent deletion removes the binding and the Memory lifecycle owns later automatic reclamation; duplication must not introduce a second synchronous Memory-deletion owner. A fork that cannot be bound is deleted immediately by the resource-copy service. Cleanup, identity update, and catalog synchronization use the target machine associated with the created agent. Rollback also stops any target-side materialization and reconciles that target machine's catalog; a failed database cleanup or target reconciliation is surfaced as a rollback failure rather than hidden behind the original copy error.

## Web Dialog

The duplicate dialog presents, in order:

1. a compact source-agent summary;
2. target Machine and Runtime selectors;
3. equal `config_only` and `with_resources` choices without a recommendation badge;
4. a “batch duplicate” switch that is off by default.

Only caller-manageable online machines are selectable. Runtime choices come from the selected machine's live catalog. If the source pair is eligible, it is the initial selection; otherwise the first eligible pair is selected. The submit action remains disabled when no eligible pair exists.

Enabling batch duplication reveals a quantity control supporting direct integer entry plus increment/decrement actions. The valid range is 2 through 10. The dialog does not show generated-name previews.

## Sequential Batch Contract

The web client implements a batch as repeated calls to the single-duplicate endpoint. Calls are strictly sequential; the next request starts only after the previous request reaches a terminal success or failure.

Before starting, the client:

- checks current workspace/organization agent quota for the requested quantity;
- allocates deterministic unique technical and display names from the latest known agent list.

Only the stable `agent_name_conflict` error code may trigger one name recomputation and one retry for that item. Other HTTP 409 responses, including runtime or model incompatibility, are not name conflicts and are not retried. Other errors are not retried automatically. Network and timeout failures are never retried because the server may have committed before the response was lost.

One item failure does not cancel later items. The final result preserves input order and reports successful and failed items separately.

Route-scope changes suppress stale dialog progress and results but do not cancel
an already submitted duplicate request: the server may have committed it even
when the client no longer observes the response. In-flight requests therefore
finish through the normal cache/realtime reconciliation path.

## Progress Semantics

Overall progress is exact and equals terminal item count divided by requested item count. A failed item counts as completed progress.

The active item may show rotating descriptive phases such as preparing configuration, copying resources, or synchronizing the target machine. These phases are presentation hints, not server-reported stage completion or percentages.

The final state displays success and failure counts and the corresponding ordered items. Every successful item can open its created agent. The result remains visible until the user closes it or opens a successful agent.

## Regression Coverage

Backend tests protect target inheritance, explicit placement, authorization, daemon presence, live runtime membership, model/provider compatibility, target runtime normalization, target cleanup, and server-resource copy boundaries.

Frontend tests protect machine/runtime eligibility, dialog defaults, batch limits, deterministic naming, strict sequential execution, one-time conflict retry, no network retry, quota preflight, partial-failure ordering, progress semantics, complete i18n, and consistent duplicate terminology.
