---
title: "Apply an atomic add/remove membership batch"
method: PUT
path: "/agents/groups:batch"
tags: ["Agent Groups"]
---

# Apply an atomic add/remove membership batch

`PUT /agents/groups:batch`

## Request

- Base URL: `https://api.mnemom.ai/v1`
- URL: `https://api.mnemom.ai/v1/agents/groups:batch`
- Auth: one of:
  - HTTP bearer
  - API key in header `X-Mnemom-Api-Key`

Apply a mixed set of add + remove operations across multiple agents and multiple groups in a single call, **all-or-nothing**. The whole batch executes inside one database transaction: if any id is invalid, inaccessible, or belongs to a foreign org, the entire batch is rejected and nothing is applied. Membership is a set — an add of an existing member and a remove of a non-member are idempotent no-ops (reported via the `*_noop_count` fields), so re-sending an identical batch changes nothing and returns 200. Duplicate operations within one request are deduped; the same (agent, group) pair appearing as both an add and a remove is contradictory and rejected. At most 50 operations per request.

## Request body

- object
  - `org_id` string, required: Organization that owns the targeted groups and agents
  - `ops` object[], required: The add/remove operations to apply atomically
    - `op` 'add' | 'remove', required: Whether to add the agent to, or remove it from, the group
    - `group_id` string, uuid, required: Target group (UUID)
    - `agent_id` string, required: Target agent

## Response `200`

Batch applied atomically. `added`/`removed` are the ids that actually CHANGED; the `*_noop_count` fields count operations that were already in the requested state; `ops_applied` (post-dedupe) may be less than `ops_received` (raw count) when duplicate operations were collapsed.

- object
  - `added` string[], required: Agent ids that were newly added (real changes only)
  - `removed` string[], required: Agent ids that were actually removed (real changes only)
  - `added_count` integer, required
  - `removed_count` integer, required
  - `add_noop_count` integer, required: Add ops whose agent was already a member (idempotent no-op)
  - `remove_noop_count` integer, required: Remove ops whose agent was already absent (idempotent no-op)
  - `ops_applied` integer, required: Distinct operations applied after dedupe
  - `ops_received` integer, required: Raw operation count as submitted (before dedupe)

## Other responses

- `400`: Bad request. Covers a malformed body / missing `org_id` / non-array or empty `ops` / over-limit (`> 50`); an invalid op value, group_id, or agent_id; a contradictory add+remove of the same (agent, group) pair (`error.code: "conflicting_ops"`); an archived target group (`error.code: "group_archived"`); and an inaccessible/foreign-org **agent** id. Note: an inaccessible or foreign-org agent is returned as **400** with `error.code: "agent_not_found"` — deliberately NOT a 404 — so a caller cannot distinguish a genuinely missing agent from one that exists in an organization they cannot see (no cross-org existence leakage), matching the single-agent membership endpoints.
- `401`: Authentication required
- `403`: Forbidden
- `404`: An inaccessible, invalid, or foreign-org **group** id (`error.code: "group_not_found"`) — the same signal a genuinely missing group returns, so group existence does not leak across org boundaries. The entire batch is rejected; nothing is applied.
- `429`: Rate-limit exceeded. The global per-IP limiter (100 requests/minute, applied to every `/v1/*` route) rejected this request. Back off until the window resets — `Retry-After` carries the cooldown in seconds and `X-RateLimit-Reset` the absolute reset time.
- `500`: Server error — request was well-formed but the server failed to fulfill it. Typically a downstream dependency (DB / RPC / external API) returned an unexpected error.
- `503`: An upstream dependency is currently unavailable. The request was not processed; retry after the cooldown window.

---

[API](https://skmtc.dev/mnemom/apis/mnemom-api.md) · [All operations](https://skmtc.dev/mnemom/apis/mnemom-api/llms.txt) · [OpenAPI document](https://skmtc.dev/mnemom/apis/mnemom-api/revisions/274b7a6ea182?raw)
