---
title: "Set Datamate Skills"
method: PUT
path: "/datamates/{datamate_id}/skills"
tags: ["SKILLS"]
---

# Set Datamate Skills

`PUT /datamates/{datamate_id}/skills`

Replace the set of skills attached to one workspace.

The mirror of ``PUT /skills/{public_id}/datamates``, and it exists because
the two directions are not interchangeable. That one is scoped to a *skill*
and replaces its entire workspace set, so adding one skill to one workspace
through it means sending that skill's complete set — which the caller must
first read, one request per skill, or silently detach it from every workspace
the client did not know about. This one is scoped to the workspace: it only
ever touches rows carrying this ``datamate_id``, so it needs no knowledge of
where else any of these skills is attached.

Locks, in the order the whole feature uses — ``Datamate``, then
``CustomSkill`` by ascending id, then ``CustomSkillDatamate``:

1. **The workspace**, for update and requiring ownership. Attaching changes
   what that workspace's agent does, so it is a write against it; a
   tenant-visible workspace says who may look, never who may reconfigure.
2. **Every named skill**, for update and requiring the caller created it.
   The other direction already refuses a non-creator, and the two have to
   agree or the same attachment would be allowed from one side and refused
   from the other.
3. **The attachment rows**, in ``set_skills_for_datamate``.

Both misses report 404 rather than 403 — whether someone else's workspace or
skill exists is not this endpoint's to disclose, matching
``app/api/bindings/api.py``.

## Path parameters

- `datamate_id` integer, required

## Request body

- SetDatamateSkillsRequest — Replace the whole set of skills attached to one workspace. The mirror of ``SetCustomSkillWorkspacesRequest``. Scoped to the workspace, so it needs no knowledge of where else any of these skills is attached — which is exactly what the skill-scoped endpoint cannot offer, since its payload replaces one skill's *entire* workspace set.
  - `skill_public_ids` string[]

## Response `200`

Successful Response

- DatamateSkillsResponse — The result of replacing a workspace's skill attachments. Shaped like what changed, for the same reason ``SkillWorkspacesResponse`` is: the workspace's own fields are untouched by an attachment write, and returning them would invite a read this endpoint has no reason to make.
  - `datamate_id` integer, required
  - `attached_skill_public_ids` string[]

## Other responses

- `403` — Not the workspace's owner
- `404` — Workspace or skill not found
- `422` — Validation Error

## Changes

- **2026-09-02** `fcb62c79da95` — 1 info
  - endpoint added

[Change history](https://skmtc.dev/myaltimate/apis/fastapi/changes/datamates/:datamate_id/skills/put.md)

---

[API](https://skmtc.dev/myaltimate/apis/fastapi.md) · [All operations](https://skmtc.dev/myaltimate/apis/fastapi/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/myaltimate/fastapi/revisions/b8f442483dc9/schema)
