# Manage skills

```json metadata
{
  "schema_version": 2,
  "title": "Manage skills",
  "description": "Package, validate, upload, version, and publish reusable agent skills.",
  "categories": ["docs","develop","ai"],
  "tableOfContents": {"sections":[{"id":"before-you-begin","title":"Before you begin"},{"id":"prepare-a-skill-package","title":"Prepare a skill package"},{"id":"upload-and-validate-a-skill","title":"Upload and validate a skill"},{"id":"review-and-publish-a-version","title":"Review and publish a version"},{"id":"update-a-skill","title":"Update a skill"},{"id":"load-instructions-and-files","title":"Load instructions and files"},{"id":"list-skills-and-inspect-history","title":"List skills and inspect history"},{"id":"withdraw-or-delete-a-skill","title":"Withdraw or delete a skill"}]}

,
  "codeExamples": [{"codetabsId":"iris_playbook_skills-stepplaybook-skill-package","difficulty":"beginner","id":"playbook-skill-package","languages":[{"clientId":"iris-curl","clientName":"cURL (Iris)","id":"cURL (Iris)","langId":"bash","panelId":"panel_cURL (Iris)_iris_playbook_skills-stepplaybook-skill-package"}]},{"codetabsId":"iris_playbook_skills-stepplaybook-skill-create","difficulty":"beginner","id":"playbook-skill-create","languages":[{"clientId":"iris-python","clientName":"Python (Iris)","id":"Python (Iris)","langId":"python","panelId":"panel_Python (Iris)_iris_playbook_skills-stepplaybook-skill-create"},{"clientId":"iris-cli","clientName":"CLI (Iris)","id":"CLI (Iris)","langId":"bash","panelId":"panel_CLI (Iris)_iris_playbook_skills-stepplaybook-skill-create"},{"clientId":"iris-curl","clientName":"cURL (Iris)","id":"cURL (Iris)","langId":"bash","panelId":"panel_cURL (Iris)_iris_playbook_skills-stepplaybook-skill-create"}]},{"codetabsId":"iris_playbook_skills-stepplaybook-skill-review","difficulty":"beginner","id":"playbook-skill-review","languages":[{"clientId":"iris-python","clientName":"Python (Iris)","id":"Python (Iris)","langId":"python","panelId":"panel_Python (Iris)_iris_playbook_skills-stepplaybook-skill-review"},{"clientId":"iris-cli","clientName":"CLI (Iris)","id":"CLI (Iris)","langId":"bash","panelId":"panel_CLI (Iris)_iris_playbook_skills-stepplaybook-skill-review"},{"clientId":"iris-curl","clientName":"cURL (Iris)","id":"cURL (Iris)","langId":"bash","panelId":"panel_cURL (Iris)_iris_playbook_skills-stepplaybook-skill-review"}]},{"codetabsId":"iris_playbook_skills-stepplaybook-skill-publish","difficulty":"beginner","id":"playbook-skill-publish","languages":[{"clientId":"iris-python","clientName":"Python (Iris)","id":"Python (Iris)","langId":"python","panelId":"panel_Python (Iris)_iris_playbook_skills-stepplaybook-skill-publish"},{"clientId":"iris-cli","clientName":"CLI (Iris)","id":"CLI (Iris)","langId":"bash","panelId":"panel_CLI (Iris)_iris_playbook_skills-stepplaybook-skill-publish"},{"clientId":"iris-curl","clientName":"cURL (Iris)","id":"cURL (Iris)","langId":"bash","panelId":"panel_cURL (Iris)_iris_playbook_skills-stepplaybook-skill-publish"}]},{"codetabsId":"iris_playbook_skills-stepplaybook-skill-append","difficulty":"beginner","id":"playbook-skill-append","languages":[{"clientId":"iris-python","clientName":"Python (Iris)","id":"Python (Iris)","langId":"python","panelId":"panel_Python (Iris)_iris_playbook_skills-stepplaybook-skill-append"},{"clientId":"iris-cli","clientName":"CLI (Iris)","id":"CLI (Iris)","langId":"bash","panelId":"panel_CLI (Iris)_iris_playbook_skills-stepplaybook-skill-append"},{"clientId":"iris-curl","clientName":"cURL (Iris)","id":"cURL (Iris)","langId":"bash","panelId":"panel_cURL (Iris)_iris_playbook_skills-stepplaybook-skill-append"}]},{"codetabsId":"iris_playbook_skills-stepplaybook-skill-load","difficulty":"beginner","id":"playbook-skill-load","languages":[{"clientId":"iris-python","clientName":"Python (Iris)","id":"Python (Iris)","langId":"python","panelId":"panel_Python (Iris)_iris_playbook_skills-stepplaybook-skill-load"},{"clientId":"iris-cli","clientName":"CLI (Iris)","id":"CLI (Iris)","langId":"bash","panelId":"panel_CLI (Iris)_iris_playbook_skills-stepplaybook-skill-load"},{"clientId":"iris-curl","clientName":"cURL (Iris)","id":"cURL (Iris)","langId":"bash","panelId":"panel_cURL (Iris)_iris_playbook_skills-stepplaybook-skill-load"}]},{"codetabsId":"iris_playbook_skills-stepplaybook-skill-list","difficulty":"beginner","id":"playbook-skill-list","languages":[{"clientId":"iris-python","clientName":"Python (Iris)","id":"Python (Iris)","langId":"python","panelId":"panel_Python (Iris)_iris_playbook_skills-stepplaybook-skill-list"},{"clientId":"iris-cli","clientName":"CLI (Iris)","id":"CLI (Iris)","langId":"bash","panelId":"panel_CLI (Iris)_iris_playbook_skills-stepplaybook-skill-list"},{"clientId":"iris-curl","clientName":"cURL (Iris)","id":"cURL (Iris)","langId":"bash","panelId":"panel_cURL (Iris)_iris_playbook_skills-stepplaybook-skill-list"}]},{"codetabsId":"iris_playbook_skills-stepplaybook-skill-state","difficulty":"beginner","id":"playbook-skill-state","languages":[{"clientId":"iris-python","clientName":"Python (Iris)","id":"Python (Iris)","langId":"python","panelId":"panel_Python (Iris)_iris_playbook_skills-stepplaybook-skill-state"},{"clientId":"iris-cli","clientName":"CLI (Iris)","id":"CLI (Iris)","langId":"bash","panelId":"panel_CLI (Iris)_iris_playbook_skills-stepplaybook-skill-state"},{"clientId":"iris-curl","clientName":"cURL (Iris)","id":"cURL (Iris)","langId":"bash","panelId":"panel_cURL (Iris)_iris_playbook_skills-stepplaybook-skill-state"}]},{"codetabsId":"iris_playbook_skills-stepplaybook-skill-history","difficulty":"beginner","id":"playbook-skill-history","languages":[{"clientId":"iris-python","clientName":"Python (Iris)","id":"Python (Iris)","langId":"python","panelId":"panel_Python (Iris)_iris_playbook_skills-stepplaybook-skill-history"},{"clientId":"iris-cli","clientName":"CLI (Iris)","id":"CLI (Iris)","langId":"bash","panelId":"panel_CLI (Iris)_iris_playbook_skills-stepplaybook-skill-history"},{"clientId":"iris-curl","clientName":"cURL (Iris)","id":"cURL (Iris)","langId":"bash","panelId":"panel_cURL (Iris)_iris_playbook_skills-stepplaybook-skill-history"}]},{"codetabsId":"iris_playbook_skills_withdraw-stepplaybook-skill-withdraw","difficulty":"beginner","id":"playbook-skill-withdraw","languages":[{"clientId":"iris-python","clientName":"Python (Iris)","id":"Python (Iris)","langId":"python","panelId":"panel_Python (Iris)_iris_playbook_skills_withdraw-stepplaybook-skill-withdraw"},{"clientId":"iris-cli","clientName":"CLI (Iris)","id":"CLI (Iris)","langId":"bash","panelId":"panel_CLI (Iris)_iris_playbook_skills_withdraw-stepplaybook-skill-withdraw"},{"clientId":"iris-curl","clientName":"cURL (Iris)","id":"cURL (Iris)","langId":"bash","panelId":"panel_cURL (Iris)_iris_playbook_skills_withdraw-stepplaybook-skill-withdraw"}]},{"codetabsId":"iris_playbook_skills_delete-stepplaybook-skill-delete","difficulty":"beginner","id":"playbook-skill-delete","languages":[{"clientId":"iris-python","clientName":"Python (Iris)","id":"Python (Iris)","langId":"python","panelId":"panel_Python (Iris)_iris_playbook_skills_delete-stepplaybook-skill-delete"},{"clientId":"iris-cli","clientName":"CLI (Iris)","id":"CLI (Iris)","langId":"bash","panelId":"panel_CLI (Iris)_iris_playbook_skills_delete-stepplaybook-skill-delete"},{"clientId":"iris-curl","clientName":"cURL (Iris)","id":"cURL (Iris)","langId":"bash","panelId":"panel_cURL (Iris)_iris_playbook_skills_delete-stepplaybook-skill-delete"}]}]
}
```

## Code examples

These examples connect to Iris services using SDKs or HTTP requests with curl. Follow one language throughout each walkthrough.


A skill tells an agent how to complete a task: what inputs or tools to use, which decisions to make, and what to return. This example drafts a customer reply by choosing and filling a refund template.

## Before you begin

Use an existing playbook and an API key with `write` permission to upload and maintain skills. Publishing and withdrawing require `publish`.

Follow the quickstart to [install a client and configure it](https://redis.io/docs/latest/develop/ai/context-engine/agent-playbooks/quickstart#before-you-begin). You also need Bash and the `zip` utility for the sample package.

Expand an example to copy the complete program. Run the package-preparation step before using a Python or CLI copy.

## Prepare a skill package

Package skills using the [Agent Skills specification](https://agentskills.io/specification). Each directory contains `SKILL.md` with frontmatter and Markdown instructions. The required `name` matches the directory name; the required `description` explains the task and when to use the skill.

Make the task and its conditions explicit in the description: semantic matching uses the skill's name and description. In the instructions, specify inputs, decisions, and expected output. Put tool requirements in `compatibility`. Reference supporting files by paths relative to the skill root, with a reason to read each one.

“Help with refunds” is too broad: it overlaps refund requests and status questions. “Draft a customer reply from a reported refund stage or a missing refund” identifies the task and its inputs.

To prepare an upload:

1. Validate the directory against the Agent Skills specification.
2. Check that every referenced file is included and each path is relative to the skill root.
3. Create a ZIP archive containing exactly one skill directory.
4. Encode the archive as base64 for the upload request.

Redis Agent Playbooks also enforce [package and content limits](https://redis.io/docs/latest/develop/ai/context-engine/agent-playbooks/limits#content-limits).

Run these commands in a new directory. The sample uses customer-provided information without accessing an order system. Adapt its guidance to your policy.

**Available in:** cURL (Iris)

##### cURL (Iris)

```bash
mkdir -p refund-support-reply/references
cat > refund-support-reply/SKILL.md <<'SKILL'
---
name: refund-support-reply
description: Draft a customer reply for an existing refund using a reported refund stage or a report that no refund is listed. Use the matching reply template. Do not use to request a new refund.
---

# Draft a refund support reply

1. Check whether the customer supplied a displayed refund stage or said no refund is listed. If neither is known, ask what their order history shows before drafting a reply.
2. Read references/reply-template.md for the listed and missing refund templates.
3. If a stage is supplied, choose the listed refund template and replace <displayed-stage> with that exact stage.
4. If no refund is listed, choose the missing refund template. Do not invent a stage.
5. Return only the completed customer reply. Do not leave placeholders in it.

Do not claim to have accessed the order system, claim a refund was issued, or promise a bank posting date.
SKILL
cat > refund-support-reply/references/reply-template.md <<'TEMPLATE'
Refund listed: Your order history shows "<displayed-stage>". Support can help if you need more information about that stage.

Refund missing: Contact support with your order number and explain that no refund appears in your order history.
TEMPLATE
zip -r refund-support-reply.zip refund-support-reply
```



Run this Bash preparation step for every language. SDK and cURL examples upload the ZIP. The CLI reads the `refund-support-reply` directory and packages it for you. Its `.iris-playbook.json` sidecar supplies intents, attributes, and metadata without changing `SKILL.md`.

## Upload and validate a skill

Create an entry with `create_skill`. Supply the base64-encoded archive with intents, attributes, and metadata.

Upload validation rejects invalid frontmatter, a mismatched root name, unsafe or duplicate paths, symbolic links, special files such as device files, and content exceeding its limits. Regular text and binary files are supported. Include only the skill directory in the archive.

Save the returned entry identifier so later uploads update the same skill.

Validation checks structure and limits, not whether the procedure suits its audience. Review its accuracy before publishing. Your application controls script execution and tool permissions.

**Available in:** Python (Iris), cURL (Iris), CLI (Iris)

##### Python (Iris)

```python
import base64
from pathlib import Path

package_base64 = base64.b64encode(Path("refund-support-reply.zip").read_bytes()).decode("ascii")
skill_context = {
    "intents": ["Draft a refund support reply", "Choose a refund reply template"],
    "attributes": {"locale": "en-US", "topic": "refund"},
}
skill_draft = playbook.client.create_skill(package_base64=package_base64, content=skill_context)
skill_id = skill_draft.entry.entry_id
skill_version = skill_draft.version.version
print(skill_id, skill_version)
```

##### cURL (Iris)

```bash
base64 < refund-support-reply.zip | tr -d '\r\n' > package.b64
jq -n --rawfile package package.b64 '{
  packageBase64: $package,
  content: {
    intents: ["Draft a refund support reply", "Choose a refund reply template"],
    attributes: {locale: "en-US", topic: "refund"}
  }
}' > skill.json
curl --fail-with-body --silent --show-error \
  -X POST "$PLAYBOOK_API/skills" \
  -H "Authorization: Bearer $IRIS_AGENT_PLAYBOOKS_API_KEY" \
  -H 'Content-Type: application/json' --data-binary @skill.json > skill-draft.json
SKILL_ID=$(jq -er '.entry.entryId' skill-draft.json)
SKILL_VERSION=$(jq -er '.version.version' skill-draft.json)
jq .version skill-draft.json
```

##### CLI (Iris)

```bash
cat > refund-support-reply/.iris-playbook.json <<'JSON'
{
  "intents": ["Draft a refund support reply", "Choose a refund reply template"],
  "attributes": {"locale": "en-US", "topic": "refund"}
}
JSON
iris agent-playbooks skills validate refund-support-reply
iris --json agent-playbooks skills push refund-support-reply > skill-draft.json
SKILL_ID=$(jq -er '.results[0].entryId' skill-draft.json)
SKILL_VERSION=$(jq -er '.results[0].version' skill-draft.json)
jq . skill-draft.json
```



The CLI uses the skill name as its stable entry key. `skills push` creates missing content, appends changed content, and skips unchanged content. It leaves publication unchanged unless you request publication.

## Review and publish a version

1. Retrieve the exact version returned by the upload.
2. Review its name, description, instructions, and resource descriptors.
3. Read the supporting files needed to assess the procedure.
4. Publish the reviewed version with `publish_skill`.
5. Test retrieval with a reader key, then test the agent's use of the skill.

Uploading a valid package does not publish it automatically. To review a suggestion before creating an entry, use a [skill proposal](https://redis.io/docs/latest/develop/ai/context-engine/agent-playbooks/proposals#review-skill-proposals).

**Available in:** Python (Iris), cURL (Iris), CLI (Iris)

##### Python (Iris)

```python
stored_skill = playbook.client.get_skill_version(skill_id=skill_id, version=skill_version)
print(stored_skill.content)
```

##### cURL (Iris)

```bash
curl --fail-with-body --silent --show-error \
  "$PLAYBOOK_API/skills/$SKILL_ID/versions/$SKILL_VERSION" \
  -H "Authorization: Bearer $IRIS_AGENT_PLAYBOOKS_API_KEY" | jq .content
```

##### CLI (Iris)

```bash
iris --json agent-playbooks skills show "$SKILL_ID" --version "$SKILL_VERSION" | jq .content
```



Publish after review. The [agent-integration examples](https://redis.io/docs/latest/develop/ai/context-engine/agent-playbooks/agent-integration) ask an agent to draft a reply for the stage “Processing.” Check that it loads this skill and template, preserves the stage, and leaves no placeholders or invented payment date. Also test a missing refund and missing input.

**Available in:** Python (Iris), cURL (Iris), CLI (Iris)

##### Python (Iris)

```python
playbook.client.publish_skill(skill_id=skill_id, version=skill_version)
```

##### cURL (Iris)

```bash
curl --fail-with-body --silent --show-error \
  -X PUT "$PLAYBOOK_API/skills/$SKILL_ID/publication" \
  -H "Authorization: Bearer $IRIS_AGENT_PLAYBOOKS_API_KEY" \
  -H 'Content-Type: application/json' \
  --data "$(jq -n --argjson version "$SKILL_VERSION" '{version: $version}')" | jq .publication
```

##### CLI (Iris)

```bash
iris agent-playbooks skills publish "$SKILL_ID" --version "$SKILL_VERSION"
```



## Update a skill

Use `append_skill_version` to update the existing entry. Supply the complete package and the intents, attributes, and metadata you want to retain.

The identifier stays the same. Agents use the previous publication until you review and publish the new version.

To roll back, publish an earlier version. Concurrent publication changes are last-write-wins, so coordinate publishers.

This example adds a `channel` attribute for chat retrieval and keeps the same instructions. To change the instructions or files, edit the directory and create a fresh ZIP archive before uploading.

**Available in:** Python (Iris), cURL (Iris), CLI (Iris)

##### Python (Iris)

```python
from copy import deepcopy

updated_context = deepcopy(skill_context)
updated_context["attributes"]["channel"] = "chat"
replacement = base64.b64encode(Path("refund-support-reply.zip").read_bytes()).decode("ascii")
skill_update = playbook.client.append_skill_version(
    skill_id=skill_id,
    package_base64=replacement,
    content=updated_context,
)
print("Review before publishing:", skill_update.version)
```

##### cURL (Iris)

```bash
base64 < refund-support-reply.zip | tr -d '\r\n' > package.b64
jq --rawfile package package.b64 \
  '.packageBase64 = $package | .content.attributes.channel = "chat"' \
  skill.json > skill-update.json
curl --fail-with-body --silent --show-error \
  -X POST "$PLAYBOOK_API/skills/$SKILL_ID/versions" \
  -H "Authorization: Bearer $IRIS_AGENT_PLAYBOOKS_API_KEY" \
  -H 'Content-Type: application/json' --data-binary @skill-update.json | jq .version
```

##### CLI (Iris)

```bash
jq '.attributes.channel = "chat"' refund-support-reply/.iris-playbook.json > skill-context.json
mv skill-context.json refund-support-reply/.iris-playbook.json
iris --json agent-playbooks skills push refund-support-reply > skill-updated.json
UPDATED_VERSION=$(jq -er '.results[0].version' skill-updated.json)
iris --json agent-playbooks skills show "$SKILL_ID" --version "$UPDATED_VERSION" | jq .content
```



Leave the update unpublished here so the loading example uses the first version. Publishing the update makes its new attributes available to filters.

## Load instructions and files

Search and discovery return previews: a name, description, entry identifier, version, and file address. Select a relevant skill before loading its instructions. Fetch supporting files when the instructions or task call for them.

Keep the returned identifier and version together, and use the returned resource addresses. If the skill is republished or withdrawn between discovery and loading, rediscover and reassess it. See [Retrieve knowledge](https://redis.io/docs/latest/develop/ai/context-engine/agent-playbooks/retrieval) and [Connect with MCP](https://redis.io/docs/latest/develop/ai/context-engine/agent-playbooks/mcp).

Resource descriptors identify the file's media type, size, and digest. Decode known text files as UTF-8 (Unicode Transformation Format, 8-bit); keep binary files as bytes. Python's unified helper reads the stream and exposes `data`, `mime_type`, and optional decoded `text`.

This example loads the first published version and reads its reply template.

**Available in:** Python (Iris), cURL (Iris), CLI (Iris)

##### Python (Iris)

```python
skill = playbook.skill(skill_id, version=skill_version)
print(skill.instructions)
resource = next((r for r in skill.resources if r.path == "references/reply-template.md"), None)
if resource is None:
    raise ValueError("Reply template is missing")
response = playbook.skill_resource(
    skill_id, resource.resource_id, version=skill_version
)
print(response.text)
```

##### cURL (Iris)

```bash
curl --fail-with-body --silent --show-error \
  "$PLAYBOOK_API/skills/$SKILL_ID/versions/$SKILL_VERSION" \
  -H "Authorization: Bearer $IRIS_AGENT_PLAYBOOKS_API_KEY" > selected-skill.json
jq -r '.content.payload.skill.instructions' selected-skill.json
RESOURCE_ID=$(jq -er '.content.payload.skill.resources[] | select(.path == "references/reply-template.md") | .resourceId' selected-skill.json)
curl --fail-with-body --silent --show-error \
  "$PLAYBOOK_API/skills/$SKILL_ID/versions/$SKILL_VERSION/resources/$RESOURCE_ID" \
  -H "Authorization: Bearer $IRIS_AGENT_PLAYBOOKS_API_KEY"
```

##### CLI (Iris)

```bash
iris --json agent-playbooks skills show "$SKILL_ID" --version "$SKILL_VERSION" > selected-skill.json
jq -r '.content.payload.skill.instructions' selected-skill.json
iris agent-playbooks skills resource get "$SKILL_ID" references/reply-template.md \
  --version "$SKILL_VERSION" --output reply-template.txt --force
cat reply-template.txt
```



This guide's CLI reads use the authoring key. The published CLI resolves the entry through management lookup, so these commands require `write` or `publish` even for a published version. For reader-only loading, use the [retrieval examples](https://redis.io/docs/latest/develop/ai/context-engine/agent-playbooks/retrieval#load-skills-with-progressive-disclosure).

To verify file content, compare the descriptor's SHA-256 (Secure Hash Algorithm 256-bit) digest with the downloaded bytes. It uses `sha256:<hex>`; the HTTP `Content-Digest` header represents the same hash as `sha-256=:<base64>:`. This differs from the normalized entry digest in [entry lookup](https://redis.io/docs/latest/develop/ai/context-engine/agent-playbooks/manage-faqs#look-up-entry-state).

## List skills and inspect history

Use `list_skills` to inventory entries and `get_skill` to inspect one entry's summary. These operations require `read`; draft content and full version history require `write` or `publish`. To resolve a skill by its entry key or compare latest and published content digests, use the shared [entry lookup operation](https://redis.io/docs/latest/develop/ai/context-engine/agent-playbooks/manage-faqs#look-up-entry-state).

Follow cursors even after empty pages, and keep filters and ordering unchanged. Responses return `items` and `nextCursor` and don't include a total count. See [pagination behavior](https://redis.io/docs/latest/develop/ai/context-engine/agent-playbooks/limits#retrieval-limits).

**Available in:** Python (Iris), cURL (Iris), CLI (Iris)

##### Python (Iris)

```python
cursor = None
while True:
    page = playbook.client.list_skills(sort_by="updatedAt", sort_order="DESC", limit=50, cursor=cursor)
    for entry in page.items:
        print(entry.entry_id, entry.latest_version, entry.publication)
    cursor = page.next_cursor
    if cursor is None:
        break
```

##### cURL (Iris)

```bash
CURSOR=''
while true; do
  PAGE_ARGS=(--data-urlencode sortBy=updatedAt --data-urlencode sortOrder=DESC --data-urlencode limit=50)
  if [[ -n "$CURSOR" ]]; then PAGE_ARGS+=(--data-urlencode "cursor=$CURSOR"); fi
  curl --fail-with-body --silent --show-error --get "$PLAYBOOK_API/skills" \
    -H "Authorization: Bearer $IRIS_AGENT_PLAYBOOKS_API_KEY" "${PAGE_ARGS[@]}" > skill-page.json
  jq '.items[] | {entryId, latestVersion, publication}' skill-page.json
  CURSOR=$(jq -r '.nextCursor // empty' skill-page.json)
  [[ -n "$CURSOR" ]] || break
done
```

##### CLI (Iris)

```bash
iris --json agent-playbooks skills list --sort-by updatedAt --sort-order desc --page-size 50 | jq .
```



**Available in:** Python (Iris), cURL (Iris), CLI (Iris)

##### Python (Iris)

```python
entry = playbook.client.get_skill(skill_id=skill_id)
print(entry.latest_version, entry.publication)
```

##### cURL (Iris)

```bash
curl --fail-with-body --silent --show-error "$PLAYBOOK_API/skills/$SKILL_ID" \
  -H "Authorization: Bearer $IRIS_AGENT_PLAYBOOKS_API_KEY" | jq '{latestVersion, publication}'
```

##### CLI (Iris)

```bash
iris --json agent-playbooks skills list --sort-by updatedAt --sort-order desc --page-size 50 \
  | jq --arg id "$SKILL_ID" '.[] | select(.entryId == $id)'
```



Read the complete versions newest first. Use a returned version number when reviewing or rolling back a publication:

**Available in:** Python (Iris), cURL (Iris), CLI (Iris)

##### Python (Iris)

```python
cursor = None
while True:
    page = playbook.client.list_skill_versions(skill_id=skill_id, limit=50, cursor=cursor)
    for item in page.items:
        print(item.version, item.content_digest, item.content)
    cursor = page.next_cursor
    if cursor is None:
        break
```

##### cURL (Iris)

```bash
CURSOR=''
while true; do
  PAGE_ARGS=(--data-urlencode limit=50)
  if [[ -n "$CURSOR" ]]; then PAGE_ARGS+=(--data-urlencode "cursor=$CURSOR"); fi
  curl --fail-with-body --silent --show-error --get "$PLAYBOOK_API/skills/$SKILL_ID/versions" \
    -H "Authorization: Bearer $IRIS_AGENT_PLAYBOOKS_API_KEY" "${PAGE_ARGS[@]}" > skill-versions.json
  jq '.items[] | {version, contentDigest, content}' skill-versions.json
  CURSOR=$(jq -r '.nextCursor // empty' skill-versions.json)
  [[ -n "$CURSOR" ]] || break
done
```

##### CLI (Iris)

```bash
iris --json agent-playbooks skills versions "$SKILL_ID" --page-size 50 | jq .
```



CLI lists and history follow cursors automatically. Use `--page` and `--cursor` to inspect individual pages. CLI version JSON currently omits `contentDigest`; use an SDK or cURL tab to inspect digests.

## Withdraw or delete a skill

Withdraw the publication with `withdraw_skill` to stop serving the procedure while keeping its history. Delete the entry with `delete_skill` when you want to remove all its versions and files permanently.

Complete-program copies retain the skill. For withdrawal or deletion, set `PLAYBOOK_SKILL_ID` to the printed identifier and run the selected example with the same connection values.

**Available in:** Python (Iris), cURL (Iris), CLI (Iris)

##### Python (Iris)

```python
playbook.client.withdraw_skill(skill_id=skill_id)
```

##### cURL (Iris)

```bash
curl --fail-with-body --silent --show-error \
  -X DELETE "$PLAYBOOK_API/skills/$SKILL_ID/publication" \
  -H "Authorization: Bearer $IRIS_AGENT_PLAYBOOKS_API_KEY" | jq .
```

##### CLI (Iris)

```bash
iris agent-playbooks skills withdraw "$PLAYBOOK_SKILL_ID"
```



To remove the sample and its files permanently:

**Available in:** Python (Iris), cURL (Iris), CLI (Iris)

##### Python (Iris)

```python
playbook.client.delete_skill(skill_id=skill_id)
```

##### cURL (Iris)

```bash
curl --fail-with-body --silent --show-error \
  -X DELETE "$PLAYBOOK_API/skills/$SKILL_ID" \
  -H "Authorization: Bearer $IRIS_AGENT_PLAYBOOKS_API_KEY"
```

##### CLI (Iris)

```bash
iris agent-playbooks skills delete "$PLAYBOOK_SKILL_ID" --yes
```



