---
sidebar:
  hidden: true
title: roboto.domain.skills.skill
---
## Module Contents

### Skill

```python
class roboto.domain.skills.skill.Skill(
    record: roboto.domain.skills.record.SkillRecord,
    roboto_client: roboto.http.RobotoClient,
)
```

`from roboto.domain.skills import Skill`

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/domain/skills/skill.py#L31-L474)

An AI skill — a versioned, accessibility-scoped procedure the chat AI can apply.

Use [`create()`](/reference/python-sdk/roboto/domain/skills/skill#roboto.domain.skills.skill.Skill.create) to create a new skill, [`from_id()`](/reference/python-sdk/roboto/domain/skills/skill#roboto.domain.skills.skill.Skill.from_id) / [`from_name()`](/reference/python-sdk/roboto/domain/skills/skill#roboto.domain.skills.skill.Skill.from_name) to load existing ones, and [`list_for_org()`](/reference/python-sdk/roboto/domain/skills/skill#roboto.domain.skills.skill.Skill.list_for_org) to iterate. The constructor is internal.

**Parameters**

- **record** (`roboto.domain.skills.record.SkillRecord`)
- **roboto_client** (`roboto.http.RobotoClient`)

**Properties**

- **Skill.accessibility** (`roboto.domain.skills.record.SkillAccessibility`)
- **Skill.created_by** (`str`)
- **Skill.name** (`str`)
- **Skill.org_id** (`str`)
- **Skill.record** (`roboto.domain.skills.record.SkillRecord`)
- **Skill.skill_id** (`str`)
- **Skill.tags** (`list[str]`)

#### Skill.create()

```python
@classmethod
def create(
    name: str,
    description: str,
    body: str,
    accessibility: roboto.domain.skills.record.SkillAccessibility = SkillAccessibility.Private,
    tags: Optional[collections.abc.Sequence[str]] = None,
    relevant_topics: Optional[collections.abc.Sequence[str]] = None,
    caller_org_id: Optional[str] = None,
    roboto_client: Optional[roboto.http.RobotoClient] = None,
) -> Skill
```

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/domain/skills/skill.py#L40-L93)

Create a new skill plus its first version (version=1).

The skill is created in the caller's organization. With the default [`SkillAccessibility.Private`](/reference/python-sdk/roboto/domain/skills/record#roboto.domain.skills.record.SkillAccessibility.Private) accessibility only the caller can see, edit, or delete it. [`SkillAccessibility.Org`](/reference/python-sdk/roboto/domain/skills/record#roboto.domain.skills.record.SkillAccessibility.Org) makes it readable by all org members (author-only to edit); [`SkillAccessibility.OrgEditable`](/reference/python-sdk/roboto/domain/skills/record#roboto.domain.skills.record.SkillAccessibility.OrgEditable) additionally lets any member who subscribes edit its versions, name, and tags. The author is auto-subscribed at creation time and the new version is pinned as Available to AI. Other org members must [`subscribe()`](/reference/python-sdk/roboto/domain/skills/skill#roboto.domain.skills.skill.Skill.subscribe) to see the skill in their AI auto-invoke registry. Pass `tags` to seed the skill's tag list at creation time; later edits flow through [`UpdateSkillMetadataRequest`](/reference/python-sdk/roboto/domain/skills/operations#roboto.domain.skills.operations.UpdateSkillMetadataRequest). Pass `relevant_topics` to record the topic names v1's procedure investigates; the chat AI resolves them to schemas when it loads the skill (see [`SkillVersionRecord.relevant_topics`](/reference/python-sdk/roboto/domain/skills/record#roboto.domain.skills.record.SkillVersionRecord.relevant_topics)).

**Usage**

```python
skill = Skill.create(
    name="qa-review",
    description="Run when the user asks for a QA review of a dataset.",
    body="Step 1: load the dataset summary...",
    accessibility=SkillAccessibility.Org,
    tags=["qa-review", "triage"],
    relevant_topics=["/imu/data", "/gps/fix"],
)
skill.skill_id
# 'sk_...'
```

**Parameters**

- **name** (`str`)
- **description** (`str`)
- **body** (`str`)
- **accessibility** (`roboto.domain.skills.record.SkillAccessibility`)
- **tags** (`Optional[collections.abc.Sequence[str]]`)
- **relevant_topics** (`Optional[collections.abc.Sequence[str]]`)
- **caller_org_id** (`Optional[str]`)
- **roboto_client** (`Optional[roboto.http.RobotoClient]`)

**Returns**

- `Skill`

#### Skill.create_version()

```python
def create_version(
    request: roboto.domain.skills.operations.CreateSkillVersionRequest,
) -> roboto.domain.skills.record.SkillVersionRecord
```

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/domain/skills/skill.py#L363-L389)

Add a new version to this skill. The server assigns `MAX(version) + 1`.

Permitted for the author and — on an [`SkillAccessibility.OrgEditable`](/reference/python-sdk/roboto/domain/skills/record#roboto.domain.skills.record.SkillAccessibility.OrgEditable) skill — for any subscribed org member. Subscribers who pinned the previous version stay on that pin until they explicitly re-pin — the new row does not auto-promote.

Pass `relevant_topics` to record the topic names this version's procedure investigates; the chat AI resolves them to schemas when it loads the skill (see [`SkillVersionRecord.relevant_topics`](/reference/python-sdk/roboto/domain/skills/record#roboto.domain.skills.record.SkillVersionRecord.relevant_topics)).

**Usage**

```python
v2 = skill.create_version(
    CreateSkillVersionRequest(
        description="Run when ...",
        body="Updated procedure ...",
        relevant_topics=["/imu/data", "/gps/fix"],
    )
)
v2.version
# 2
```

**Parameters**

- **request** (`roboto.domain.skills.operations.CreateSkillVersionRequest`)

**Returns**

- `roboto.domain.skills.record.SkillVersionRecord`

#### Skill.delete()

```python
def delete() -> None
```

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/domain/skills/skill.py#L325-L336)

Hard-delete this skill. Author-only, including on `OrgEditable` skills.

Cascades to all versions and subscriptions. Existing chats keep any fabricated `load_skill` tool_use / tool_result blocks they've already produced — the body is captured at invocation time and written into the transcript.

**Usage**

```python
skill.delete()
```

**Returns**

- `None`

#### Skill.delete_version()

```python
def delete_version(version: int) -> None
```

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/domain/skills/skill.py#L409-L423)

Delete a single version. If it's the last remaining version, the parent skill is removed too.

Permitted for the author and — on an [`SkillAccessibility.OrgEditable`](/reference/python-sdk/roboto/domain/skills/record#roboto.domain.skills.record.SkillAccessibility.OrgEditable) skill — for any subscribed org member. A subscribed non-author may not delete the *last* remaining version: that cascades into a full skill delete, which is author-only. The author has no such restriction.

Subscriptions pinned to the deleted version have their `ai_version` nulled out via a server-side trigger; the subscription row survives.

**Usage**

```python
skill.delete_version(1)
```

**Parameters**

- **version** (`int`)

**Returns**

- `None`

#### Skill.from_id()

```python
@classmethod
def from_id(
    skill_id: str,
    roboto_client: Optional[roboto.http.RobotoClient] = None,
) -> Skill
```

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/domain/skills/skill.py#L96-L114)

Load a skill by its skill_id.

**Parameters**

- **skill_id** (`str`)
- **roboto_client** (`Optional[roboto.http.RobotoClient]`)

**Raises**

- [`RobotoNotFoundException`](/reference/python-sdk/roboto/exceptions/domain#roboto.exceptions.domain.RobotoNotFoundException): No skill with this id exists, or the caller cannot see it (visibility-gated).

**Returns**

- `Skill`

**Usage**

```python
skill = Skill.from_id("sk_abc123")
skill.name
# 'qa-review'
```

#### Skill.from_name()

```python
@classmethod
def from_name(
    name: str,
    caller_org_id: Optional[str] = None,
    roboto_client: Optional[roboto.http.RobotoClient] = None,
) -> Skill
```

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/domain/skills/skill.py#L143-L179)

Load a skill by name in the caller's organization.

Skill names are unique within `(org_id, accessibility)`. When both a private and an org-shared skill share a name in the same org, this method returns the caller's private one (the manual-invocation tie-break — see `SkillsRepo.get_skill_by_name()`).

**Parameters**

- **name** (`str`): Skill name. URL-encoded by the SDK.
- **caller_org_id** (`Optional[str]`): Look up in this org. Defaults to the caller's current org.
- **roboto_client** (`Optional[roboto.http.RobotoClient]`)

**Raises**

- [`RobotoNotFoundException`](/reference/python-sdk/roboto/exceptions/domain#roboto.exceptions.domain.RobotoNotFoundException): No skill with this name is visible to the caller in the target org.

**Returns**

- `Skill`

**Usage**

```python
skill = Skill.from_name("qa-review")
skill.accessibility
# <SkillAccessibility.Org: 'org'>
```

#### Skill.get_summary()

```python
@classmethod
def get_summary(
    skill_id: str,
    roboto_client: Optional[roboto.http.RobotoClient] = None,
) -> roboto.domain.skills.record.SkillSummary
```

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/domain/skills/skill.py#L117-L140)

Load one skill's summary: the skill, its latest version, and your subscription.

The single-skill counterpart of [`list_for_org()`](/reference/python-sdk/roboto/domain/skills/skill#roboto.domain.skills.skill.Skill.list_for_org). Prefer it over filtering that listing when you already know the `skill_id` — it costs one row instead of the whole org's skills.

**Parameters**

- **skill_id** (`str`)
- **roboto_client** (`Optional[roboto.http.RobotoClient]`)

**Raises**

- [`RobotoNotFoundException`](/reference/python-sdk/roboto/exceptions/domain#roboto.exceptions.domain.RobotoNotFoundException): No skill with this id exists, or the caller cannot see it (visibility-gated, same as [`from_id()`](/reference/python-sdk/roboto/domain/skills/skill#roboto.domain.skills.skill.Skill.from_id)).

**Returns**

- `roboto.domain.skills.record.SkillSummary`

**Usage**

```python
summary = Skill.get_summary("sk_abc123")
summary.latest_version.version
# 3
summary.subscription is None  # not subscribed
# True
```

#### Skill.get_version()

```python
def get_version(version: int) -> roboto.domain.skills.record.SkillVersionRecord
```

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/domain/skills/skill.py#L349-L361)

Load a specific version of this skill.

**Parameters**

- **version** (`int`)

**Raises**

- [`RobotoNotFoundException`](/reference/python-sdk/roboto/exceptions/domain#roboto.exceptions.domain.RobotoNotFoundException): No such version exists.

**Returns**

- `roboto.domain.skills.record.SkillVersionRecord`

**Usage**

```python
v2 = skill.get_version(2)
print(v2.body)
```

#### Skill.list_for_org()

```python
@classmethod
def list_for_org(
    scope: Optional[roboto.domain.skills.operations.SkillListScope] = None,
    caller_org_id: Optional[str] = None,
    roboto_client: Optional[roboto.http.RobotoClient] = None,
) -> collections.abc.Generator[roboto.domain.skills.record.SkillSummary, None, None]
```

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/domain/skills/skill.py#L204-L245)

Yield [`SkillSummary`](/reference/python-sdk/roboto/domain/skills/record#roboto.domain.skills.record.SkillSummary) items for every skill the caller can see in their org.

The summary includes the latest version (MAX(version)) and the caller's own subscription row when one exists. When `scope` is provided the result is restricted to either `Personal` (authored or subscribed) or `Org` (org-shared skills the caller did not author, regardless of subscription state). Omit `scope` to receive every visible skill in one stream.

**Usage**

List the caller's Personal-tab skills:

```python
for summary in Skill.list_for_org(scope=SkillListScope.Personal):
    print(summary.skill.name, summary.subscription.ai_version if summary.subscription else None)
```

Iterate every visible skill (Personal + Org), in one pass:

```python
all_visible = list(Skill.list_for_org())
```

**Parameters**

- **scope** (`Optional[roboto.domain.skills.operations.SkillListScope]`)
- **caller_org_id** (`Optional[str]`)
- **roboto_client** (`Optional[roboto.http.RobotoClient]`)

**Returns**

- `collections.abc.Generator[roboto.domain.skills.record.SkillSummary, None, None]`

#### Skill.list_known_tags()

```python
@classmethod
def list_known_tags(
    caller_org_id: Optional[str] = None,
    roboto_client: Optional[roboto.http.RobotoClient] = None,
) -> list[str]
```

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/domain/skills/skill.py#L182-L201)

Return the distinct tags found on skills the caller can see in this org.

Visibility-filtered the same way [`list_for_org()`](/reference/python-sdk/roboto/domain/skills/skill#roboto.domain.skills.skill.Skill.list_for_org) is — private skills owned by other users contribute no tags. Suitable for powering a tag-autocomplete UI.

**Usage**

```python
Skill.list_known_tags()
# ['qa-review', 'triage', 'experiments']
```

**Parameters**

- **caller_org_id** (`Optional[str]`)
- **roboto_client** (`Optional[roboto.http.RobotoClient]`)

**Returns**

- `list[str]`

#### Skill.list_versions()

```python
def list_versions() -> list[roboto.domain.skills.record.SkillVersionRecord]
```

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/domain/skills/skill.py#L338-L347)

List every version of this skill, newest first.

**Usage**

```python
for version in skill.list_versions():
    print(version.version, version.description)
```

**Returns**

- `list[roboto.domain.skills.record.SkillVersionRecord]`

#### Skill.refresh()

```python
def refresh() -> Skill
```

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/domain/skills/skill.py#L287-L299)

Re-fetch this skill's record from the server and return self.

Useful after another caller may have updated the skill — bumps the local view past stale data.

**Usage**

```python
skill.refresh()
skill.name  # now reflects any server-side rename
# 'qa-review'
```

**Returns**

- `Skill`

#### Skill.set_ai_version()

```python
def set_ai_version(
    version: Optional[int],
) -> roboto.domain.skills.record.SkillSubscriptionRecord
```

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/domain/skills/skill.py#L453-L474)

Pin (or clear) which version of this skill the AI auto-invokes for the caller.

Pass an integer to expose that exact version to AI auto-invocation; pass `None` to disable AI auto-invocation while keeping the subscription. Implicitly subscribes the caller if no row exists yet. Visibility-gated; the caller does not have to be the author.

**Usage**

Pin version 2 for AI auto-invoke:

```python
skill.set_ai_version(2)
```

Stop the AI from auto-invoking this skill, but stay subscribed so manual chip-invocation still works:

```python
skill.set_ai_version(None)
```

**Parameters**

- **version** (`Optional[int]`)

**Returns**

- `roboto.domain.skills.record.SkillSubscriptionRecord`

#### Skill.subscribe()

```python
def subscribe() -> roboto.domain.skills.record.SkillSubscriptionRecord
```

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/domain/skills/skill.py#L425-L440)

Subscribe to this skill — adds it to the caller's Personal tab.

Idempotent: if the caller is already subscribed (or is the author), the existing row is returned unchanged. New subscriptions default to `ai_version=None` (not yet exposed to AI). Use [`set_ai_version()`](/reference/python-sdk/roboto/domain/skills/skill#roboto.domain.skills.skill.Skill.set_ai_version) to enable AI auto-invocation.

**Usage**

```python
sub = skill.subscribe()
sub.ai_version is None
# True
```

**Returns**

- `roboto.domain.skills.record.SkillSubscriptionRecord`

#### Skill.unsubscribe()

```python
def unsubscribe() -> None
```

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/domain/skills/skill.py#L442-L451)

Remove the caller's subscription row — removes the skill from their Personal tab.

No-op if there is no subscription. Authors who unsubscribe from their own skill can re-subscribe later; authorship is unchanged.

**Usage**

```python
skill.unsubscribe()
```

**Returns**

- `None`

#### Skill.update_metadata()

```python
def update_metadata(
    request: roboto.domain.skills.operations.UpdateSkillMetadataRequest,
) -> Skill
```

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/domain/skills/skill.py#L301-L323)

Update skill-level metadata (name, accessibility, tags).

Editing the name and tags is permitted for the author and — on an [`SkillAccessibility.OrgEditable`](/reference/python-sdk/roboto/domain/skills/record#roboto.domain.skills.record.SkillAccessibility.OrgEditable) skill — for any subscribed org member. Changing `accessibility` is always author-only.

Updates apply in place; the local record is replaced with the server's authoritative copy.

**Usage**

```python
skill.update_metadata(
    UpdateSkillMetadataRequest(
        accessibility=SkillAccessibility.Org,
        put_tags=["qa-review"],
    )
)
```

**Parameters**

- **request** (`roboto.domain.skills.operations.UpdateSkillMetadataRequest`)

**Returns**

- `Skill`

#### Skill.update_version()

```python
def update_version(
    version: int,
    request: roboto.domain.skills.operations.UpdateSkillVersionRequest,
) -> roboto.domain.skills.record.SkillVersionRecord
```

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/domain/skills/skill.py#L391-L407)

Edit fields on an existing version in place.

Permitted for the author and — on an [`SkillAccessibility.OrgEditable`](/reference/python-sdk/roboto/domain/skills/record#roboto.domain.skills.record.SkillAccessibility.OrgEditable) skill — for any subscribed org member.

Subscribers pinned to this version see the new body on their next AI invocation; there is no per-edit revision. Use [`create_version()`](/reference/python-sdk/roboto/domain/skills/skill#roboto.domain.skills.skill.Skill.create_version) when callers should not be auto-migrated.

**Usage**

```python
skill.update_version(2, UpdateSkillVersionRequest(body="..."))
```

**Parameters**

- **version** (`int`)
- **request** (`roboto.domain.skills.operations.UpdateSkillVersionRequest`)

**Returns**

- `roboto.domain.skills.record.SkillVersionRecord`
