roboto.domain.skills#
Stored, versioned procedures the chat AI can apply during a conversation.
A skill is text instructions the model follows when invoked — either manually
via a chat-composer chip or automatically when the model selects it from the
load_skill tool’s registry. Skills are owned by a user, optionally shared
with the user’s organization, and versioned in place; each version is mutable
without lifecycle states. Visibility and edit rights follow the skill’s
accessibility: private (author-only), org (visible org-wide, author-only
to edit), or org-editable (visible org-wide and editable by any subscribed
member). Per-user subscriptions carry an ai_version pin that controls
whether — and which version — the AI auto-invoke registry exposes to the
subscriber.
Submodules#
Package Contents#
- class roboto.domain.skills.CreateSkillRequest(/, **data)#
Bases:
pydantic.BaseModelCreate a new skill plus its first version (
version=1) in one call.The author is auto-subscribed at creation time with
ai_versionset to1so the skill is immediately offered to the author’s AI.- Parameters:
data (Any)
- accessibility: roboto.domain.skills.record.SkillAccessibility#
Private(only the author),Org(visible to every org member, author-only to edit), orOrgEditable(visible to every org member, editable by any member who subscribes). The author can flip this later viaUpdateSkillMetadataRequest.- Type:
Visibility scope
- body: str#
Procedure text v1 — the instructions the model executes when this version is invoked. Bumping the version creates a new row; this field never re-edits v1’s body after the fact (use
UpdateSkillVersionRequestfor that).
- description: str = None#
“When to use” text for v1. Surfaces verbatim in the
load_skilltool’s description so the model can decide whether to invoke this skill. Bumping the version replaces this text on the new row; this field never re-edits v1’s description after the fact.
- model_config#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- name: str = None#
Skill name. Unique per org across every org-visible skill (
OrgandOrgEditableshare one name namespace); private skills are unique per(org_id, created_by). A user’s private skill and an org-shared skill may therefore share a name without conflict. Must matchSKILL_NAME_PATTERNso the name is parseable inside the chat composer’s/slugtoken (no whitespace, letters/digits/hyphens/underscores only).
- tags: list[str] = None#
Initial set of tags. Edits after creation flow through
UpdateSkillMetadataRequest.put_tags/.remove_tagsso concurrent updates merge cleanly — seeSkillRecord.tags.
- class roboto.domain.skills.CreateSkillVersionRequest(/, **data)#
Bases:
pydantic.BaseModelAdd a new version to an existing skill. The new version is assigned
MAX(version) + 1.- Parameters:
data (Any)
- body: str#
Procedure text the model executes when this version is invoked.
- description: str = None#
“When to use” text for this version. Surfaces verbatim in the
load_skilltool’s description on every turn this version is offered to the AI.
- model_config#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- roboto.domain.skills.MAX_SKILL_DESCRIPTION_LENGTH = 500#
- roboto.domain.skills.SKILL_NAME_PATTERN = '^[A-Za-z0-9_-]+$'#
- class roboto.domain.skills.SetSkillSubscriptionRequest(/, **data)#
Bases:
pydantic.BaseModelUpsert the caller’s subscription for a skill.
Idempotent: creates the subscription row if missing, otherwise updates
ai_versionin place. Visibility-gated only — the caller does not need to be the skill’s author. The server enforces thatai_version, if provided, references an existing version of the skill.- Parameters:
data (Any)
- ai_version: int | None = None#
Pinned AI-available version.
Nonemeans “subscribed, but not exposed to AI”.
- model_config#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class roboto.domain.skills.Skill(record, roboto_client)#
An AI skill — a versioned, accessibility-scoped procedure the chat AI can apply.
Use
create()to create a new skill,from_id()/from_name()to load existing ones, andlist_for_org()to iterate. The constructor is internal.- Parameters:
roboto_client (roboto.http.RobotoClient)
- property accessibility: roboto.domain.skills.record.SkillAccessibility#
- Return type:
- classmethod create(name, description, body, accessibility=SkillAccessibility.Private, tags=None, caller_org_id=None, roboto_client=None)#
Create a new skill plus its first version (version=1).
The skill is created in the caller’s organization. With the default
SkillAccessibility.Privateaccessibility only the caller can see, edit, or delete it.SkillAccessibility.Orgmakes it readable by all org members (author-only to edit);SkillAccessibility.OrgEditableadditionally 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 mustsubscribe()to see the skill in their AI auto-invoke registry. Passtagsto seed the skill’s tag list at creation time; later edits flow throughUpdateSkillMetadataRequest.Examples
>>> 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"], ... ) >>> skill.skill_id 'sk_...'
- Parameters:
name (str)
description (str)
body (str)
accessibility (roboto.domain.skills.record.SkillAccessibility)
tags (Optional[collections.abc.Sequence[str]])
caller_org_id (Optional[str])
roboto_client (Optional[roboto.http.RobotoClient])
- Return type:
- create_version(request)#
Add a new version to this skill. The server assigns
MAX(version) + 1.Permitted for the author and — on an
SkillAccessibility.OrgEditableskill — 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.Examples
>>> v2 = skill.create_version( ... CreateSkillVersionRequest( ... description="Run when ...", ... body="Updated procedure ...", ... ) ... ) >>> v2.version 2
- Parameters:
request (roboto.domain.skills.operations.CreateSkillVersionRequest)
- Return type:
- property created_by: str#
- Return type:
str
- delete()#
Hard-delete this skill. Author-only, including on
OrgEditableskills.Cascades to all versions and subscriptions. Existing chats keep any fabricated
load_skilltool_use / tool_result blocks they’ve already produced — the body is captured at invocation time and written into the transcript.Examples
>>> skill.delete()
- Return type:
None
- delete_version(version)#
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.OrgEditableskill — 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_versionnulled out via a server-side trigger; the subscription row survives.Examples
>>> skill.delete_version(1)
- Parameters:
version (int)
- Return type:
None
- classmethod from_id(skill_id, roboto_client=None)#
Load a skill by its skill_id.
- Raises:
RobotoNotFoundException – No skill with this id exists, or the caller cannot see it (visibility-gated).
- Parameters:
skill_id (str)
roboto_client (Optional[roboto.http.RobotoClient])
- Return type:
Examples
>>> skill = Skill.from_id("sk_abc123") >>> skill.name 'qa-review'
- classmethod from_name(name, caller_org_id=None, roboto_client=None)#
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 — seeSkillsRepo.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 – No skill with this name is visible to the caller in the target org.
- Return type:
Examples
>>> skill = Skill.from_name("qa-review") >>> skill.accessibility <SkillAccessibility.Org: 'org'>
- get_version(version)#
Load a specific version of this skill.
- Raises:
RobotoNotFoundException – No such version exists.
- Parameters:
version (int)
- Return type:
Examples
>>> v2 = skill.get_version(2) >>> print(v2.body)
- classmethod list_for_org(scope=None, caller_org_id=None, roboto_client=None)#
Yield
SkillSummaryitems 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
scopeis provided the result is restricted to eitherPersonal(authored or subscribed) orOrg(org-shared skills the caller did not author, regardless of subscription state). Omitscopeto receive every visible skill in one stream.Examples
List the caller’s Personal-tab skills:
>>> 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:
>>> 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])
- Return type:
collections.abc.Generator[roboto.domain.skills.record.SkillSummary, None, None]
- classmethod list_known_tags(caller_org_id=None, roboto_client=None)#
Return the distinct tags found on skills the caller can see in this org.
Visibility-filtered the same way
list_for_org()is — private skills owned by other users contribute no tags. Suitable for powering a tag-autocomplete UI.Examples
>>> Skill.list_known_tags() ['qa-review', 'triage', 'experiments']
- Parameters:
caller_org_id (Optional[str])
roboto_client (Optional[roboto.http.RobotoClient])
- Return type:
list[str]
- list_versions()#
List every version of this skill, newest first.
Examples
>>> for version in skill.list_versions(): ... print(version.version, version.description)
- Return type:
- property name: str#
- Return type:
str
- property org_id: str#
- Return type:
str
- property record: roboto.domain.skills.record.SkillRecord#
- Return type:
- refresh()#
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.
Examples
>>> skill.refresh() >>> skill.name # now reflects any server-side rename 'qa-review'
- Return type:
- set_ai_version(version)#
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
Noneto 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.Examples
Pin version 2 for AI auto-invoke:
>>> skill.set_ai_version(2)
Stop the AI from auto-invoking this skill, but stay subscribed so manual chip-invocation still works:
>>> skill.set_ai_version(None)
- Parameters:
version (Optional[int])
- Return type:
- property skill_id: str#
- Return type:
str
- subscribe()#
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). Useset_ai_version()to enable AI auto-invocation.Examples
>>> sub = skill.subscribe() >>> sub.ai_version is None True
- Return type:
- property tags: list[str]#
- Return type:
list[str]
- unsubscribe()#
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.
Examples
>>> skill.unsubscribe()
- Return type:
None
- update_metadata(request)#
Update skill-level metadata (name, accessibility, tags).
Editing the name and tags is permitted for the author and — on an
SkillAccessibility.OrgEditableskill — for any subscribed org member. Changingaccessibilityis always author-only.Updates apply in place; the local record is replaced with the server’s authoritative copy.
Examples
>>> skill.update_metadata( ... UpdateSkillMetadataRequest( ... accessibility=SkillAccessibility.Org, ... put_tags=["qa-review"], ... ) ... )
- Parameters:
request (roboto.domain.skills.operations.UpdateSkillMetadataRequest)
- Return type:
- update_version(version, request)#
Edit fields on an existing version in place.
Permitted for the author and — on an
SkillAccessibility.OrgEditableskill — 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()when callers should not be auto-migrated.Examples
>>> skill.update_version(2, UpdateSkillVersionRequest(body="..."))
- Parameters:
version (int)
request (roboto.domain.skills.operations.UpdateSkillVersionRequest)
- Return type:
- class roboto.domain.skills.SkillAccessibility#
Bases:
roboto.compat.StrEnumControls who can see and edit a skill.
- Org = 'org'#
All members of the owning org can see and invoke the skill. Only the author can edit.
- OrgEditable = 'org-editable'#
All members of the owning org can see and invoke the skill, and any member who has subscribed to it can also edit its versions, name, and tags. Changing the skill’s accessibility and deleting the whole skill remain author-only.
- Private = 'private'#
Only the author (
created_by) can see, edit, or invoke the skill.
- class roboto.domain.skills.SkillListScope#
Bases:
roboto.compat.StrEnumWhich caller-relative slice of the visible skills a list-skills query targets.
- Org = 'org'#
Org-shared skills authored by someone else, regardless of whether the caller has subscribed.
- Personal = 'personal'#
Skills the caller authored or has subscribed to — their personal set.
- class roboto.domain.skills.SkillRecord(/, **data)#
Bases:
pydantic.BaseModelTop-level skill identity, ownership, and visibility.
A skill on its own carries no procedure content — see
SkillVersionRecord.- Parameters:
data (Any)
- accessibility: SkillAccessibility#
- created: datetime.datetime#
- created_by: str#
- modified: datetime.datetime#
Last edit timestamp. Skill mutations are author-only, so the editor is always
created_by— no separatemodified_byfield is stored.
- name: str#
- org_id: str#
- skill_id: str#
- tags: list[str] = None#
Free-form labels for categorization (e.g.
"qa-review","experiments"). Skill-level metadata, not version-scoped — they describe what the skill is for, not how a specific version implements it. Edited via the changeset fields onUpdateSkillMetadataRequest(put_tags/remove_tags).
- class roboto.domain.skills.SkillSubscriptionRecord(/, **data)#
Bases:
pydantic.BaseModelPer-user state for a single skill.
Created when a user subscribes to a skill (or authors one — authors are auto-subscribed at create time). Carries the user’s choice of which version, if any, should be exposed to the AI auto-invoke registry.
ai_version=Nonemeans the user is subscribed but has not enabled the skill for AI auto-invoke; manual chip-invocation still works.- Parameters:
data (Any)
- ai_version: int | None = None#
If set, the AI’s
LoadSkillToolregistry surfaces this exact version of the skill to this user. IfNone, the skill is hidden from AI auto-invocation for this user. Manual invocation works regardless.
- skill_id: str#
- subscribed: datetime.datetime#
When the subscription was created.
- user_id: str#
- class roboto.domain.skills.SkillSummary(/, **data)#
Bases:
pydantic.BaseModelCompact projection of a skill plus its latest version (if any).
Also includes the caller’s personal subscription state for the skill, when one exists.
subscription=Nonemeans the caller has neither authored nor subscribed to the skill.- Parameters:
data (Any)
- latest_version: SkillVersionRecord | None = None#
The MAX(version) row for this skill. Always populated for summaries returned from the public API:
Skill.create()makes the skill row and v1 atomically, and deleting the last version cascades to delete the parent skill in the same transaction. TheOptionalis defense-in- depth for repo-direct callers (test fixtures, manual SQL) and should not be treated as a real branch by SDK consumers.
- skill: SkillRecord#
- subscription: SkillSubscriptionRecord | None = None#
The caller’s subscription row for this skill, if any. Populated by the server based on the caller’s identity; not used in INSERT or UPDATE payloads.
- class roboto.domain.skills.SkillVersionRecord(/, **data)#
Bases:
pydantic.BaseModelA single, mutable version of a skill’s content.
- Parameters:
data (Any)
- body: str#
The procedure text the model executes when the skill is invoked.
- created: datetime.datetime#
- description: str = None#
Short ``when to use’’ text. Surfaces verbatim in the LoadSkillTool description.
- modified: datetime.datetime#
- skill_id: str#
- version: int#
- class roboto.domain.skills.UpdateSkillMetadataRequest(/, **data)#
Bases:
pydantic.BaseModelUpdate top-level skill identity.
Editing
name/put_tags/remove_tagsis permitted for the author and — on anOrgEditableskill — for any subscribed org member. Changingaccessibilityis always author-only.- Parameters:
data (Any)
- accessibility: roboto.domain.skills.record.SkillAccessibility | roboto.sentinels.NotSetType#
New visibility scope. Omit to leave unchanged. Author-only — a subscribed non-author editor of an
OrgEditableskill cannot change it. FlippingPrivate→Org/OrgEditableimmediately exposes the skill to every org member; flipping toPrivateprunes every non-author subscription.
- model_config#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- name: str | roboto.sentinels.NotSetType = None#
New skill name. Omit (the
NotSetdefault) to leave unchanged. Must matchSKILL_NAME_PATTERNand stays unique per org (private skills per author).
- put_tags: list[str] = None#
Tags to add. Empty (the default) means “no change to tags.” Additive semantics — does not clear other tags.
- remove_tags: list[str] = None#
Tags to remove. Empty (the default) means “no change to tags.” Removing a tag the skill doesn’t have is a no-op.
- class roboto.domain.skills.UpdateSkillVersionRequest(/, **data)#
Bases:
pydantic.BaseModelEdit fields on an existing version (mutates in place).
- Parameters:
data (Any)
- body: str | roboto.sentinels.NotSetType#
New procedure text. Omit (the
NotSetdefault) to leave unchanged. The change applies in place to this version — subscribers pinned to it will see the new body on their next AI invocation; there is no per-edit revision.
- description: str | roboto.sentinels.NotSetType = None#
New “when to use” text. Omit (the
NotSetdefault) to leave unchanged.
- model_config#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].