# Retrieve knowledge

```json metadata
{
  "schema_version": 2,
  "title": "Retrieve knowledge",
  "description": "Search published knowledge, discover skills and answers together, and control relevance and result size.",
  "categories": ["docs","develop","ai"],
  "tableOfContents": {"sections":[{"id":"before-you-begin","title":"Before you begin"},{"children":[{"id":"how-discovery-selects-entries","title":"How discovery selects entries"},{"id":"configure-discovery","title":"Configure discovery"},{"id":"pin-required-knowledge","title":"Pin required knowledge"},{"id":"limit-discovery-previews","title":"Limit discovery previews"},{"id":"load-skills-with-progressive-disclosure","title":"Load skills with progressive disclosure"}],"id":"discovery","title":"Discovery"},{"children":[{"id":"control-relevance-and-result-count","title":"Control relevance and result count"},{"id":"select-an-audience-with-filters","title":"Select an audience with filters"}],"id":"search","title":"Search"}]}

,
  "codeExamples": [{"codetabsId":"iris_playbook_retrieval-stepplaybook-retrieval-discover","difficulty":"beginner","id":"playbook-retrieval-discover","languages":[{"clientId":"iris-python","clientName":"Python (Iris)","id":"Python (Iris)","langId":"python","panelId":"panel_Python (Iris)_iris_playbook_retrieval-stepplaybook-retrieval-discover"},{"clientId":"iris-cli","clientName":"CLI (Iris)","id":"CLI (Iris)","langId":"bash","panelId":"panel_CLI (Iris)_iris_playbook_retrieval-stepplaybook-retrieval-discover"},{"clientId":"iris-curl","clientName":"cURL (Iris)","id":"cURL (Iris)","langId":"bash","panelId":"panel_cURL (Iris)_iris_playbook_retrieval-stepplaybook-retrieval-discover"}]},{"codetabsId":"iris_playbook_retrieval-stepplaybook-retrieval-pin","difficulty":"beginner","id":"playbook-retrieval-pin","languages":[{"clientId":"iris-python","clientName":"Python (Iris)","id":"Python (Iris)","langId":"python","panelId":"panel_Python (Iris)_iris_playbook_retrieval-stepplaybook-retrieval-pin"},{"clientId":"iris-cli","clientName":"CLI (Iris)","id":"CLI (Iris)","langId":"bash","panelId":"panel_CLI (Iris)_iris_playbook_retrieval-stepplaybook-retrieval-pin"},{"clientId":"iris-curl","clientName":"cURL (Iris)","id":"cURL (Iris)","langId":"bash","panelId":"panel_cURL (Iris)_iris_playbook_retrieval-stepplaybook-retrieval-pin"}]},{"codetabsId":"iris_playbook_retrieval-stepplaybook-retrieval-budget","difficulty":"beginner","id":"playbook-retrieval-budget","languages":[{"clientId":"iris-python","clientName":"Python (Iris)","id":"Python (Iris)","langId":"python","panelId":"panel_Python (Iris)_iris_playbook_retrieval-stepplaybook-retrieval-budget"},{"clientId":"iris-cli","clientName":"CLI (Iris)","id":"CLI (Iris)","langId":"bash","panelId":"panel_CLI (Iris)_iris_playbook_retrieval-stepplaybook-retrieval-budget"},{"clientId":"iris-curl","clientName":"cURL (Iris)","id":"cURL (Iris)","langId":"bash","panelId":"panel_cURL (Iris)_iris_playbook_retrieval-stepplaybook-retrieval-budget"}]},{"codetabsId":"iris_playbook_retrieval-stepplaybook-retrieval-load","difficulty":"beginner","id":"playbook-retrieval-load","languages":[{"clientId":"iris-python","clientName":"Python (Iris)","id":"Python (Iris)","langId":"python","panelId":"panel_Python (Iris)_iris_playbook_retrieval-stepplaybook-retrieval-load"},{"clientId":"iris-curl","clientName":"cURL (Iris)","id":"cURL (Iris)","langId":"bash","panelId":"panel_cURL (Iris)_iris_playbook_retrieval-stepplaybook-retrieval-load"}]},{"codetabsId":"iris_playbook_retrieval-stepplaybook-retrieval-search","difficulty":"beginner","id":"playbook-retrieval-search","languages":[{"clientId":"iris-python","clientName":"Python (Iris)","id":"Python (Iris)","langId":"python","panelId":"panel_Python (Iris)_iris_playbook_retrieval-stepplaybook-retrieval-search"},{"clientId":"iris-cli","clientName":"CLI (Iris)","id":"CLI (Iris)","langId":"bash","panelId":"panel_CLI (Iris)_iris_playbook_retrieval-stepplaybook-retrieval-search"},{"clientId":"iris-curl","clientName":"cURL (Iris)","id":"cURL (Iris)","langId":"bash","panelId":"panel_cURL (Iris)_iris_playbook_retrieval-stepplaybook-retrieval-search"}]},{"codetabsId":"iris_playbook_retrieval-stepplaybook-retrieval-threshold","difficulty":"beginner","id":"playbook-retrieval-threshold","languages":[{"clientId":"iris-python","clientName":"Python (Iris)","id":"Python (Iris)","langId":"python","panelId":"panel_Python (Iris)_iris_playbook_retrieval-stepplaybook-retrieval-threshold"},{"clientId":"iris-cli","clientName":"CLI (Iris)","id":"CLI (Iris)","langId":"bash","panelId":"panel_CLI (Iris)_iris_playbook_retrieval-stepplaybook-retrieval-threshold"},{"clientId":"iris-curl","clientName":"cURL (Iris)","id":"cURL (Iris)","langId":"bash","panelId":"panel_cURL (Iris)_iris_playbook_retrieval-stepplaybook-retrieval-threshold"}]},{"codetabsId":"iris_playbook_retrieval-stepplaybook-retrieval-filter","difficulty":"beginner","id":"playbook-retrieval-filter","languages":[{"clientId":"iris-python","clientName":"Python (Iris)","id":"Python (Iris)","langId":"python","panelId":"panel_Python (Iris)_iris_playbook_retrieval-stepplaybook-retrieval-filter"},{"clientId":"iris-cli","clientName":"CLI (Iris)","id":"CLI (Iris)","langId":"bash","panelId":"panel_CLI (Iris)_iris_playbook_retrieval-stepplaybook-retrieval-filter"},{"clientId":"iris-curl","clientName":"cURL (Iris)","id":"cURL (Iris)","langId":"bash","panelId":"panel_cURL (Iris)_iris_playbook_retrieval-stepplaybook-retrieval-filter"}]}]
}
```

## Code examples

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


Retrieve published knowledge for the user's task. Choose a retrieval method:

- [**Discovery**](https://redis.io/docs/latest/develop/ai/context-engine/agent-playbooks/retrieval#discovery) combines FAQ answers and skill previews so the agent can choose what to use.
- [**Search**](https://redis.io/docs/latest/develop/ai/context-engine/agent-playbooks/retrieval#search) returns one entry type when your application needs answers or skill previews, with a relevance threshold and result count for each request.

Both methods serve current publications. They exclude drafts, historical versions, and proposals.

## Before you begin

Use a data-plane endpoint, playbook identifier, and API key with `read` permission. Publish the entries you want to retrieve before testing them.

Start with the quickstart's [client setup](https://redis.io/docs/latest/develop/ai/context-engine/agent-playbooks/quickstart#connect-to-the-playbook) with a reader key, then append this page's snippets in order. The examples use the published FAQ and skill from the task guides; keep them published until testing is complete.

## Discovery

Discovery returns answers and skill previews within a shared result limit. Pins include required entries; a preview budget limits returned content.

Use Python's `discover` helper, send an HTTP discovery request, or call `discover_entries` through [MCP](https://redis.io/docs/latest/develop/ai/context-engine/agent-playbooks/mcp). Load selected skill instructions and files with [progressive disclosure](https://redis.io/docs/latest/develop/ai/context-engine/agent-playbooks/retrieval#load-skills-with-progressive-disclosure).

Request up to five entries for the agent's task:

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

##### Python (Iris)

```python
discovery = playbook.discover(
    "Draft a reply for a customer whose refund shows Processing", limit=5
)
print(discovery.as_prompt())
```

##### cURL (Iris)

```bash
curl --fail-with-body --silent --show-error \
  -X POST "$PLAYBOOK_API/entries/discover" \
  -H "Authorization: Bearer $IRIS_AGENT_PLAYBOOKS_API_KEY" \
  -H 'Content-Type: application/json' \
  --data '{"query":"Draft a reply for a customer whose refund shows Processing","limit":5}' | jq .
```

##### CLI (Iris)

```bash
cat > discover.json <<'JSON'
{
  "query": "Draft a reply for a customer whose refund shows Processing",
  "limit": 5
}
JSON
iris --json agent-playbooks discover --input discover.json | jq .
```



Python's unified SDK exposes matches as `discovery.discovered` and pins as `discovery.pinned`. `as_prompt()` renders their context for an agent. The CLI accepts the same JSON discovery request as cURL through `--input FILE` and returns the API response with `--json`.

### How discovery selects entries

Discovery applies these steps:

1. Resolve each pin to its current published version, preserving request order.
1. Reserve result slots and preview budget for the pins.
1. Rank matching FAQs and skills together using the query, attribute filter, and each type's similarity threshold. Exclude pinned entries from these matches.
1. Fill the remaining slots in rank order. When a preview does not fit the remaining token budget, skip it and consider later candidates that may fit.
1. Return pins in `pinnedEntries` and ranked matches in `discoveredEntries`, with count and budget truncation signals.

If pins fill every result slot, discovery returns only the pins. An FAQ preview includes its question and answer. A skill preview includes its name, description, entry identifier, version, and file address.

### Configure discovery

Discovery accepts these HTTP or CLI JSON fields and Python `playbook.client.discover_entries` arguments:

| HTTP/CLI field | Python argument | Use it to |
|:---------------|:----------------|:----------|
| `query` | `query` | Describe the agent's task. Required even when supplying pins. |
| `filter` | `filter_` | Restrict semantic matches by attributes. Uses the same [filter expressions as search](https://redis.io/docs/latest/develop/ai/context-engine/agent-playbooks/retrieval#select-an-audience-with-filters); pins bypass it. |
| `limit` | `limit` | Reduce the combined result count. Omission uses `discovery.maxResults`, which also caps an explicit limit. |
| `pinnedEntries` | `pinned_entries` | Require published entries in request order. Each reference contains exactly one `entryId` or `entryKey` (`entry_id` or `entry_key` in Python). |

The unified `playbook.discover(question, pin=[...])` helper used in this page accepts entry identifiers or keys as strings. It sends a default `limit` of `5`, still bounded by `discovery.maxResults`. For MCP argument names, see [MCP tools](https://redis.io/docs/latest/develop/ai/context-engine/agent-playbooks/mcp#use-the-tools).

Your administrator sets the playbook controls:

| Setting | Default | Effect |
|:--------|:--------|:-------|
| `discovery.faqMinimumScore` | `0.7` | Minimum similarity for discovered FAQ matches. |
| `discovery.skillMinimumScore` | `0.7` | Minimum similarity for discovered skill matches. |
| `discovery.maxResults` | `10` | Combined result ceiling for pins and discovered matches. |
| `discovery.previewTokenBudgetEnabled` | `false` | Enable the discovery preview ceiling. |
| `discovery.previewTokenBudget` | Unset | Estimated token ceiling, at least `64`. It applies only when `discovery.previewTokenBudgetEnabled` is `true`. |

Discovery has no per-request similarity override. An administrator can adjust the playbook thresholds in its [discovery policy](https://redis.io/docs/latest/operate/iris/agent-playbook/manage-playbook#discovery-policy).

### Pin required knowledge

Use discovery pins when a task must include a known published entry. Supply exactly one entry identifier or entry key for each pin. Discovery returns pins in request order, separately from semantic matches.

Pins bypass similarity thresholds and the request filter. Choose pins for the intended audience yourself. They still consume result slots and preview budget.

A missing, unpublished, duplicate, or oversized pin fails the request. Use pins to test connectivity or include required content; evaluate semantic relevance without them.

Export the identifier of a published skill, such as the sample in [Manage skills](https://redis.io/docs/latest/develop/ai/context-engine/agent-playbooks/manage-skills), before cleanup:

```bash
export PLAYBOOK_SKILL_ID='<published-skill-entry-id>'
```

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

##### Python (Iris)

```python
import os

skill_id = os.environ["PLAYBOOK_SKILL_ID"]
pinned = playbook.discover(
    "Draft a reply for a customer whose refund shows Processing",
    pin=[skill_id],
)
selected_preview = pinned.pinned[0]
print(selected_preview.entry_id, selected_preview.version)
```

##### cURL (Iris)

```bash
curl --fail-with-body --silent --show-error \
  -X POST "$PLAYBOOK_API/entries/discover" \
  -H "Authorization: Bearer $IRIS_AGENT_PLAYBOOKS_API_KEY" \
  -H 'Content-Type: application/json' \
  --data "$(jq -n --arg id "$PLAYBOOK_SKILL_ID" '{query: "Draft a reply for a customer whose refund shows Processing", pinnedEntries: [{entryId: $id}], limit: 5}')" > discovery.json
jq '.pinnedEntries[0] | {entryId, version}' discovery.json
```

##### CLI (Iris)

```bash
jq -n --arg id "$PLAYBOOK_SKILL_ID" '{
  query: "Draft a reply for a customer whose refund shows Processing",
  pinnedEntries: [{entryId: $id}],
  limit: 5
}' > pinned-discover.json
iris --json agent-playbooks discover --input pinned-discover.json > pinned.json
jq '.pinnedEntries[0] | {entryId, version}' pinned.json
```



### Limit discovery previews

Use the preview budget to limit the knowledge returned in one discovery response. It excludes model framing, conversation history, loaded instructions, and fetched files. Your application still controls the model's total context.

| HTTP/CLI field | Unified Python property | Meaning when `true` |
|:---------------|:------------------------|:--------------------|
| `truncated` | `truncated` | Eligible fetched candidates exceed the slots left after pins. This does not count every match in the playbook. |
| `budgetTruncated` | `budget_truncated` | Matching previews were skipped to fit the token ceiling. |

Empty results with `budgetTruncated: true` can mean matches did not fit. Shorten FAQ answers or skill descriptions, or raise the ceiling through your administrator. Increasing the result count does not increase the token budget. Type-specific search does not use this budget.

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

##### Python (Iris)

```python
print("Result limit reached:", pinned.truncated)
print("Preview budget reached:", pinned.budget_truncated or False)
```

##### cURL (Iris)

```bash
jq '{truncated, budgetTruncated: (.budgetTruncated // false)}' discovery.json
```

##### CLI (Iris)

```bash
jq '{truncated, budgetTruncated: (.budgetTruncated // false)}' pinned.json
```



### Load skills with progressive disclosure

Progressive disclosure lets an agent select a skill from its description before loading instructions and files. Discovery and skill search support the same loading steps.

1. **Discover previews.** Retrieve names and descriptions so the agent can assess which skills match the task. FAQ answers are already included in the result.
1. **Select a skill.** Keep the entry identifier and version from the same preview together.
1. **Load instructions.** Retrieve that version's instructions and resource descriptors. With MCP, call `load_skill` using the selected `entry_id` and `version`.
1. **Fetch files as needed.** Retrieve only supporting files needed for the task. Use returned resource identifiers or URIs. With MCP, pass the returned `uri` to `fetch_resource`.
1. **Add content to context.** Your application chooses the instructions and files to give the model and controls any actions it takes.

The preview budget applies only to the first step, not loaded instructions, files, or total model context.

Reader keys can load only the current publication. MCP tools apply this restriction even to management keys. For example, discovery can return version `1`, then loading fails because version `2` was published in the meantime. Rediscover once, select again, and load instructions and files from the newly returned version. Keeping an identifier/version pair does not reserve access to an older publication.

The example loads the skill selected in [Pin required knowledge](https://redis.io/docs/latest/develop/ai/context-engine/agent-playbooks/retrieval#pin-required-knowledge), then fetches its reply template. For a complete MCP client example, see [Connect a client](https://redis.io/docs/latest/develop/ai/context-engine/agent-playbooks/mcp#connect-a-client).

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

##### Python (Iris)

```python
skill = playbook.skill(selected_preview)
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(selected_preview, resource.resource_id)
print(response.text)
```

##### cURL (Iris)

```bash
SKILL_ID=$(jq -er '.pinnedEntries[0].entryId' discovery.json)
SKILL_VERSION=$(jq -er '.pinnedEntries[0].version' discovery.json)
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"
```



Use an SDK or cURL for this reader-only operation. The published CLI's skill-loading commands perform management lookup, which requires `write` or `publish`. Discovery and search CLI examples work with the reader key.

## Search

Search returns ranked `items` of one entry type. Use it to find an answer, select a skill, or tune retrieval per request.

| Operation | Use it when | Result |
|:----------|:------------|:-------|
| `search_faqs` | Your application needs an answer. | Ranked FAQ matches with questions and answers. |
| `search_skills` | Your application needs a procedure. | Ranked skill previews with names, descriptions, and file addresses. |

Send a query that describes the task and relevant conditions. A support question such as “How can I check an existing refund?” is more useful than a query containing only “refund.”

Semantic matching compares your query with the FAQ question or the skill's name and description. Include the task and distinguishing conditions in those fields. FAQ answers, intents, metadata, skill instructions, and supporting files do not contribute to similarity scores. Attributes narrow the eligible matches through filters. These rules apply to both search and discovery.

Retain returned entry identifiers and versions with the content you select.

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

##### Python (Iris)

```python
faq_results = playbook.client.search_faqs(query="Where is my refund?", limit=5)
skill_results = playbook.client.search_skills(query="Draft a reply about a reported refund stage", limit=5)
print(faq_results.model_dump_json(by_alias=True, indent=2))
print(skill_results.model_dump_json(by_alias=True, indent=2))
```

##### cURL (Iris)

```bash
curl --fail-with-body --silent --show-error \
  -X POST "$PLAYBOOK_API/faqs/search" \
  -H "Authorization: Bearer $IRIS_AGENT_PLAYBOOKS_API_KEY" \
  -H 'Content-Type: application/json' \
  --data '{"query":"Where is my refund?","limit":5}' | jq .
curl --fail-with-body --silent --show-error \
  -X POST "$PLAYBOOK_API/skills/search" \
  -H "Authorization: Bearer $IRIS_AGENT_PLAYBOOKS_API_KEY" \
  -H 'Content-Type: application/json' \
  --data '{"query":"Draft a reply about a reported refund stage","limit":5}' | jq .
```

##### CLI (Iris)

```bash
iris --json agent-playbooks faqs search 'Where is my refund?' --limit 5 | jq .
iris --json agent-playbooks skills search 'Draft a reply about a reported refund stage' --limit 5 | jq .
```



### Control relevance and result count

Search accepts these HTTP fields and Python `playbook.client.search_faqs` or `playbook.client.search_skills` arguments:

| HTTP field | Python argument | Default | Use it to |
|:-----------|:----------------|:--------|:----------|
| `query` | `query` | Required | Describe the task to match semantically. |
| `filter` | `filter_` | None | Restrict matches by entry attributes, such as locale or topic. |
| `minScore` | `min_score` | The playbook's threshold for that entry type; initially `0.7` | Set a similarity floor from `0` to `1` for this request. |
| `limit` | `limit` | `discovery.maxResults`; initially `10` | Request 1–50 results. An explicit search limit is not capped by the playbook's discovery limit. |

The threshold defaults come from `discovery.faqMinimumScore` and `discovery.skillMinimumScore`. Your administrator can change them. Search does not use discovery pins or the discovery preview budget.

Similarity ranks matches; it does not measure answer correctness. Test “Where is my refund?” against “How do I request a refund?” The first needs the sample status answer; the second needs different guidance. Compare results across paraphrases before choosing a threshold. Higher thresholds can remove useful matches too. If no relevant match remains, ask for clarification or route to support.

For example, override the FAQ search threshold and result count for one request:

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

##### Python (Iris)

```python
tuned = playbook.client.search_faqs(query="Where is my refund?", min_score=0.75, limit=3)
print(tuned.items)
```

##### cURL (Iris)

```bash
curl --fail-with-body --silent --show-error \
  -X POST "$PLAYBOOK_API/faqs/search" \
  -H "Authorization: Bearer $IRIS_AGENT_PLAYBOOKS_API_KEY" \
  -H 'Content-Type: application/json' \
  --data '{"query":"Where is my refund?","minScore":0.75,"limit":3}' | jq .items
```

##### CLI (Iris)

```bash
iris --json agent-playbooks faqs search 'Where is my refund?' --min-score 0.75 --limit 3 | jq .items
```



### Select an audience with filters

Set attributes when [authoring FAQs](https://redis.io/docs/latest/develop/ai/context-engine/agent-playbooks/manage-faqs) or [uploading skills](https://redis.io/docs/latest/develop/ai/context-engine/agent-playbooks/manage-skills). Filter retrieval by those attributes to select a locale, product, or audience.

Filters use exact, typed comparisons. Each HTTP filter node has one operator: `eq`, `and`, or `or`. Python dictionaries use `and_` and `or_`; `eq` is unchanged.

An equality filter matches a scalar attribute or a member of a list-valued attribute. Boolean `true`, integer `1`, and string `"true"` are different values. Filters do not search metadata and do not replace playbook access grants.

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

##### Python (Iris)

```python
filtered = playbook.client.search_faqs(
    query="Where is my refund?",
    filter_={
        "and_": [
            {"eq": {"name": "locale", "value": "en-US"}},
            {"eq": {"name": "topic", "value": "refund"}},
        ]
    },
)
print(filtered.model_dump_json(by_alias=True, indent=2))
```

##### cURL (Iris)

```bash
curl --fail-with-body --silent --show-error \
  -X POST "$PLAYBOOK_API/faqs/search" \
  -H "Authorization: Bearer $IRIS_AGENT_PLAYBOOKS_API_KEY" \
  -H 'Content-Type: application/json' \
  --data '{"query":"Where is my refund?","filter":{"and":[{"eq":{"name":"locale","value":"en-US"}},{"eq":{"name":"topic","value":"refund"}}]}}' | jq .
```

##### CLI (Iris)

```bash
cat > filtered-search.json <<'JSON'
{
  "query": "Where is my refund?",
  "filter": {
    "and": [
      {"eq": {"name": "locale", "value": "en-US"}},
      {"eq": {"name": "topic", "value": "refund"}}
    ]
  }
}
JSON
iris --json agent-playbooks faqs search --input filtered-search.json | jq .
```



Use entry lookup or list operations for management state. Lists use pagination cursors; search and discovery use result limits. See [service limits and errors](https://redis.io/docs/latest/develop/ai/context-engine/agent-playbooks/limits) for request constraints and recovery.

