> ## Documentation Index
> Fetch the complete documentation index at: https://docs.wellapp.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Skill

> A `Skill` is a workspace-scoped markdown document the AI chat LLM consumes at query time

A `Skill` is a workspace-scoped markdown document the AI chat LLM consumes at query time. Two flavours coexist in the same table, discriminated by `kind`: `reference` skills are long-form procedure docs browsable in workspace settings, while `action` skills capture a specific AI action (filter, custom column, table setup) and can be shared via a public link whose URL can be dropped into any chat to replay the action. Skills are soft-deletable, carry optional authorship provenance (`created_by` membership) and optional derivation provenance (`source_thread` chat conversation), and control their own visibility (`private` vs `public`). The entity has no cascade-delete from its owning workspace, which is intentional to protect cross-workspace public-link sharing.

| Naming                          | Value                             |
| ------------------------------- | --------------------------------- |
| Object                          | Skill                             |
| Resource type (JSON:API `type`) | `skill`                           |
| Collection / records root       | — <sub>(not a records root)</sub> |
| REST base                       | `/v1/skills`                      |
| Entity class                    | `Skill`                           |

<Note>
  **Internal object.** Not currently exposed on the public REST API. The operations below describe the intended contract.
</Note>

## API operations

| Operation | Method & path            | Status     |
| --------- | ------------------------ | ---------- |
| List      | `GET /v1/skills`         | 🟡 Planned |
| Retrieve  | `GET /v1/skills/{id}`    | 🟡 Planned |
| Create    | `POST /v1/skills`        | 🟡 Planned |
| Update    | `PATCH /v1/skills/{id}`  | 🟡 Planned |
| Delete    | `DELETE /v1/skills/{id}` | 🟡 Planned |

## Data model

### Attributes

| Field       | Type                           | Required | Constraints                                                                                    | Allowed values          | Description                                                                                                                                                                                                                                            |
| ----------- | ------------------------------ | -------- | ---------------------------------------------------------------------------------------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| skill\_id   | 🔒 system — UUID string        | ✅ Yes    | UNIQUE; generated by `gen_random_uuid()` default; never client-supplied.                       | —                       | Public-facing stable identifier generated by `gen_random_uuid()` at insert time. This is the `id` exposed on the JSON:API envelope.                                                                                                                    |
| kind        | enum (skill\_kind\_enum)       | ✅ Yes    | NOT NULL; native Postgres enum `core_api.skill_kind_enum`.                                     | "reference" \| "action" | Discriminator that separates the two skill flavours. `reference` = long-form Claude-Code-style procedure; `action` = short body capturing a specific AI action shareable via public link.                                                              |
| name        | string (varchar 255)           | ✅ Yes    | NOT NULL; max length 255.                                                                      | —                       | Human-readable display name for the skill, shown in workspace settings and the chat capability surface.                                                                                                                                                |
| description | string (text) \| null          | ⚪ No     | Nullable.                                                                                      | —                       | Optional short summary of the skill's purpose. Supplements the name for settings browsability.                                                                                                                                                         |
| body        | string (text)                  | ✅ Yes    | NOT NULL.                                                                                      | —                       | Full markdown content of the skill that the LLM reads. For `reference` skills this is the complete procedure doc; for `action` skills it is the short action-capture body.                                                                             |
| visibility  | enum (skill\_visibility\_enum) | ✅ Yes    | NOT NULL; native Postgres enum `core_api.skill_visibility_enum`; database default `'private'`. | "private" \| "public"   | Controls who can read the skill row. `private` = only members of the owning workspace; `public` = any authenticated Well user (still requires auth — not internet-public). Action skills flip to `public` on Share; reference skills remain `private`. |
| created\_at | 🔒 system — datetime           | ✅ Yes    | NOT NULL; `TIMESTAMPTZ NOT NULL DEFAULT now()`.                                                | —                       | Timestamp when the row was created. Set by MikroORM `onCreate` hook; never written by callers.                                                                                                                                                         |
| updated\_at | 🔒 system — datetime           | ✅ Yes    | NOT NULL; `TIMESTAMPTZ NOT NULL DEFAULT now()`.                                                | —                       | Timestamp of the most recent update. Maintained by MikroORM `onCreate` and `onUpdate` hooks.                                                                                                                                                           |
| deleted\_at | 🔒 system — datetime \| null   | ⚪ No     | Nullable; `TIMESTAMPTZ`.                                                                       | —                       | Soft-delete timestamp. NULL means the skill is live. Set by the delete handler; never written directly by callers. All list queries filter `deleted_at IS NULL`.                                                                                       |

### Relationships

| Name           | Type               | Required          | Description                                                                                                                                                                                                                                      |
| -------------- | ------------------ | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| workspace      | to-one (ManyToOne) | Yes — NOT NULL FK | The workspace that owns this skill. Deliberately has no `ON DELETE CASCADE` — a workspace hard-delete must not silently invalidate cross-workspace public-link action skills; callers must clean up skill rows first. FK column: `workspace_pk`. |
| source\_thread | to-one (ManyToOne) | No — nullable FK  | Originating chat conversation for action skills (provenance). Nullable; `ON DELETE SET NULL` so deleting a conversation does not break the skill. FK column: `source_thread_pk`. Points to `ChatConversation`.                                   |
| created\_by    | to-one (ManyToOne) | No — nullable FK  | Membership of the user who authored the skill. Nullable; `ON DELETE SET NULL` so the skill survives if the creator's membership is removed. FK column: `created_by_pk`. Points to `Membership`.                                                  |

### System-computed

* skill\_id — generated by gen\_random\_uuid() at insert; never client-supplied.
* created\_at — set by MikroORM onCreate hook (new Date()); maps to TIMESTAMPTZ NOT NULL DEFAULT now().
* updated\_at — set by MikroORM onCreate hook and refreshed on every flush via onUpdate hook.
* deleted\_at — soft-delete field; set by the delete handler to the current timestamp; never written by callers; live queries always filter deleted\_at IS NULL.
* visibility default — the ORM default and DB column default are both 'private'; callers may omit this field on create.
* Partial index idx\_skills\_workspace\_kind covers (workspace\_pk, kind, created\_at DESC) WHERE deleted\_at IS NULL — list-by-workspace-and-kind queries satisfy ORDER BY without a separate sort step.
* Partial index idx\_skills\_source\_thread covers (source\_thread\_pk) WHERE source\_thread\_pk IS NOT NULL AND deleted\_at IS NULL — reverse-lookup 'skills derived from this conversation' query.

## Example

```json theme={null}
{
  "data": {
    "id": "d4e7f1a2-3b8c-4e9d-a0f5-1c2b3d4e5f6a",
    "type": "skill",
    "attributes": {
      "skill_id": "d4e7f1a2-3b8c-4e9d-a0f5-1c2b3d4e5f6a",
      "kind": "reference",
      "name": "Invoice matching procedure",
      "description": "Step-by-step procedure for matching supplier invoices to PO lines.",
      "body": "# Invoice Matching Procedure\n\n## When to use\nUse this skill whenever a supplier invoice...",
      "visibility": "private",
      "created_at": "2026-04-10T09:23:14.000Z",
      "updated_at": "2026-05-18T14:05:07.000Z",
      "deleted_at": null
    },
    "relationships": {
      "workspace": {
        "data": { "id": "a1b2c3d4-e5f6-7890-ab12-cd34ef567890", "type": "workspace" }
      },
      "source_thread": {
        "data": null
      },
      "created_by": {
        "data": { "id": "f7e6d5c4-b3a2-1098-7654-321fedcba098", "type": "membership" }
      }
    }
  }
}
```

<sub>Source: `apps/api/src/database/entities/Skill.ts` · domain: automation · tier: Activity</sub>
