Skip to content

Commit 5822294

Browse files
committed
Remove fallback to all registered vector stores when tool RAG is unconfigured
Previously, when neither rag.tool nor rag.inline were configured, prepare_tools would fetch and register all vector stores from llama-stack as a backward-compatibility fallback. This implicit behavior is removed — tool RAG now requires explicit configuration via rag.tool. Updated docs, config model, example YAML, and tests to reflect the new behavior.
1 parent 804688e commit 5822294

9 files changed

Lines changed: 30 additions & 142 deletions

File tree

docs/byok_guide.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ rag:
261261
- okp # include OKP context inline
262262
263263
# Tool RAG: the LLM can call file_search to retrieve context on demand
264-
# If omitted, tool RAG is disabled. If both tool and inline are omitted, all registered stores are used as fallback
264+
# If omitted, tool RAG is disabled
265265
tool:
266266
- my-docs # expose this BYOK store as the file_search tool
267267
- okp # expose OKP as the file_search tool

docs/config.md

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -606,18 +606,14 @@ Controls which RAG sources are used for inline and tool-based retrieval.
606606
Each strategy lists RAG IDs to include. The special ID ``"okp"`` defined in constants,
607607
activates the OKP provider; all other IDs refer to entries in ``byok_rag``.
608608

609-
Backward compatibility:
610-
- ``inline`` defaults to ``[]`` (no inline RAG).
611-
- ``tool`` defaults to ``[]`` (no tool RAG).
612-
613-
If no RAG strategy is defined (inline and tool are empty),
614-
the RAG tool will register all stores available to llama-stack.
609+
Both ``inline`` and ``tool`` default to ``[]`` (disabled).
610+
Each must be explicitly configured to activate its respective RAG strategy.
615611

616612

617613
| Field | Type | Description |
618614
|--------|-------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
619615
| inline | array | RAG IDs whose sources are injected as context before the LLM call. Use 'okp' to enable OKP inline RAG. Empty by default (no inline RAG). |
620-
| tool | array | RAG IDs made available to the LLM as a file_search tool. Use 'okp' to include the OKP vector store. When omitted, all registered BYOK vector stores are used (backward compatibility). |
616+
| tool | array | RAG IDs made available to the LLM as a file_search tool. Use 'okp' to include the OKP vector store. When omitted, tool RAG is disabled. |
621617

622618

623619
## RerankerConfiguration

docs/models/responses_succ.md

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1840,18 +1840,14 @@ Controls which RAG sources are used for inline and tool-based retrieval.
18401840
Each strategy lists RAG IDs to include. The special ID ``"okp"`` defined in constants,
18411841
activates the OKP provider; all other IDs refer to entries in ``byok_rag``.
18421842

1843-
Backward compatibility:
1844-
- ``inline`` defaults to ``[]`` (no inline RAG).
1845-
- ``tool`` defaults to ``[]`` (no tool RAG).
1846-
1847-
If no RAG strategy is defined (inline and tool are empty),
1848-
the RAG tool will register all stores available to llama-stack.
1843+
Both ``inline`` and ``tool`` default to ``[]`` (disabled).
1844+
Each must be explicitly configured to activate its respective RAG strategy.
18491845

18501846

18511847
| Field | Type | Description |
18521848
|-------|------|-------------|
18531849
| inline | array | RAG IDs whose sources are injected as context before the LLM call. Use 'okp' to enable OKP inline RAG. Empty by default (no inline RAG). |
1854-
| tool | array | RAG IDs made available to the LLM as a file_search tool. Use 'okp' to include the OKP vector store. When omitted, all registered BYOK vector stores are used (backward compatibility). |
1850+
| tool | array | RAG IDs made available to the LLM as a file_search tool. Use 'okp' to include the OKP vector store. When omitted, tool RAG is disabled. |
18551851

18561852

18571853
## ReadinessResponse

docs/openapi.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18084,13 +18084,13 @@
1808418084
},
1808518085
"type": "array",
1808618086
"title": "Tool RAG IDs",
18087-
"description": "RAG IDs made available to the LLM as a file_search tool. Use 'okp' to include the OKP vector store. When omitted, all registered BYOK vector stores are used (backward compatibility)."
18087+
"description": "RAG IDs made available to the LLM as a file_search tool. Use 'okp' to include the OKP vector store. When omitted, tool RAG is disabled."
1808818088
}
1808918089
},
1809018090
"additionalProperties": false,
1809118091
"type": "object",
1809218092
"title": "RagConfiguration",
18093-
"description": "RAG strategy configuration.\n\nControls which RAG sources are used for inline and tool-based retrieval.\n\nEach strategy lists RAG IDs to include. The special ID ``\"okp\"`` defined in constants,\nactivates the OKP provider; all other IDs refer to entries in ``byok_rag``.\n\nBackward compatibility:\n - ``inline`` defaults to ``[]`` (no inline RAG).\n - ``tool`` defaults to ``[]`` (no tool RAG).\n\nIf no RAG strategy is defined (inline and tool are empty),\nthe RAG tool will register all stores available to llama-stack."
18093+
"description": "RAG strategy configuration.\n\nControls which RAG sources are used for inline and tool-based retrieval.\n\nEach strategy lists RAG IDs to include. The special ID ``\"okp\"`` defined in constants,\nactivates the OKP provider; all other IDs refer to entries in ``byok_rag``.\n\nBoth ``inline`` and ``tool`` default to ``[]`` (disabled).\nEach must be explicitly configured to activate its respective RAG strategy."
1809418094
},
1809518095
"ReadinessResponse": {
1809618096
"properties": {

docs/openapi.md

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8155,18 +8155,14 @@ Controls which RAG sources are used for inline and tool-based retrieval.
81558155
Each strategy lists RAG IDs to include. The special ID ``"okp"`` defined in constants,
81568156
activates the OKP provider; all other IDs refer to entries in ``byok_rag``.
81578157

8158-
Backward compatibility:
8159-
- ``inline`` defaults to ``[]`` (no inline RAG).
8160-
- ``tool`` defaults to ``[]`` (no tool RAG).
8161-
8162-
If no RAG strategy is defined (inline and tool are empty),
8163-
the RAG tool will register all stores available to llama-stack.
8158+
Both ``inline`` and ``tool`` default to ``[]`` (disabled).
8159+
Each must be explicitly configured to activate its respective RAG strategy.
81648160

81658161

81668162
| Field | Type | Description |
81678163
|-------|------|-------------|
81688164
| inline | array | RAG IDs whose sources are injected as context before the LLM call. Use 'okp' to enable OKP inline RAG. Empty by default (no inline RAG). |
8169-
| tool | array | RAG IDs made available to the LLM as a file_search tool. Use 'okp' to include the OKP vector store. When omitted, all registered BYOK vector stores are used (backward compatibility). |
8165+
| tool | array | RAG IDs made available to the LLM as a file_search tool. Use 'okp' to include the OKP vector store. When omitted, tool RAG is disabled. |
81708166

81718167

81728168
## ReadinessResponse

examples/lightspeed-stack-byok-okp-rag.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ rag:
6060
- okp
6161
# Tool RAG: LLM can call file_search on demand to retrieve context
6262
# List rag_ids from byok_rag, or 'okp' to include OKP
63-
# Omit to use all registered BYOK stores (backward compatibility)
63+
# Omit to disable tool RAG
6464
tool:
6565
- ocp-docs
6666
- knowledge-base

src/models/config.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2258,12 +2258,8 @@ class RagConfiguration(ConfigurationBase):
22582258
Each strategy lists RAG IDs to include. The special ID ``"okp"`` defined in constants,
22592259
activates the OKP provider; all other IDs refer to entries in ``byok_rag``.
22602260
2261-
Backward compatibility:
2262-
- ``inline`` defaults to ``[]`` (no inline RAG).
2263-
- ``tool`` defaults to ``[]`` (no tool RAG).
2264-
2265-
If no RAG strategy is defined (inline and tool are empty),
2266-
the RAG tool will register all stores available to llama-stack.
2261+
Both ``inline`` and ``tool`` default to ``[]`` (disabled).
2262+
Each must be explicitly configured to activate its respective RAG strategy.
22672263
"""
22682264

22692265
inline: list[str] = Field(
@@ -2278,7 +2274,7 @@ class RagConfiguration(ConfigurationBase):
22782274
title="Tool RAG IDs",
22792275
description="RAG IDs made available to the LLM as a file_search tool. "
22802276
f"Use '{constants.OKP_RAG_ID}' to include the OKP vector store. "
2281-
"When omitted, all registered BYOK vector stores are used (backward compatibility).",
2277+
"When omitted, tool RAG is disabled.",
22822278
)
22832279

22842280

src/utils/responses.py

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@
130130
async def get_vector_store_ids(
131131
client: AsyncLlamaStackClient,
132132
) -> list[str]:
133-
"""Fetche all available vector stores from Llama Stack.
133+
"""Fetch all available vector stores from Llama Stack.
134134
135135
Args:
136136
client: The AsyncLlamaStackClient to use for fetching stores
@@ -219,7 +219,7 @@ async def maybe_get_topic_summary(
219219
return await get_topic_summary(input_text, client, model_id)
220220

221221

222-
async def prepare_tools( # pylint: disable=too-many-arguments,too-many-positional-arguments
222+
async def prepare_tools( # pylint: disable=too-many-arguments,too-many-positional-arguments,unused-argument
223223
client: AsyncLlamaStackClient,
224224
vector_store_ids: Optional[list[str]],
225225
no_tools: Optional[bool],
@@ -232,7 +232,7 @@ async def prepare_tools( # pylint: disable=too-many-arguments,too-many-position
232232
Args:
233233
client: The Llama Stack client instance
234234
vector_store_ids: The list of vector store IDs to use for RAG tools
235-
or None if all vector stores should be used
235+
or None to fall back to rag.tool configuration
236236
no_tools: Whether to skip tool preparation
237237
token: Authentication token for MCP tools
238238
mcp_headers: Per-request headers for MCP servers
@@ -250,22 +250,16 @@ async def prepare_tools( # pylint: disable=too-many-arguments,too-many-position
250250
# Vector store ID resolution priority:
251251
# 1. Per-request IDs: highest prio; customer-facing rag_ids are translated to vector_db_ids.
252252
# 2. rag.tool config IDs: used when no per-request IDs provided, and rag.tool is configured.
253-
# If rag.inline is configured, but not rag.tool, tool RAG is disabled.
254-
# 3. All registered vector DBs: fallback when neither rag.tool nor rag.inline are configured.
255-
# IDs fetched from llama-stack are already internal and need no translation.
256253
byok_rags = configuration.configuration.byok_rag
257254

258255
is_tool_rag_enabled = len(configuration.configuration.rag.tool) > 0
259-
is_inline_rag_enabled = len(configuration.configuration.rag.inline) > 0
260256

261257
if vector_store_ids is not None:
262258
effective_ids = resolve_vector_store_ids(vector_store_ids, byok_rags)
263259
elif is_tool_rag_enabled:
264260
effective_ids = resolve_vector_store_ids(
265261
configuration.configuration.rag.tool, byok_rags
266262
)
267-
elif not is_inline_rag_enabled:
268-
effective_ids = await get_vector_store_ids(client, None)
269263

270264
# Add RAG tools if vector stores are available
271265
rag_tools = get_rag_tools(effective_ids)

tests/unit/utils/test_responses.py

Lines changed: 11 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -1614,43 +1614,6 @@ async def test_prepare_tools_with_vector_store_ids(
16141614
assert result[0].type == "file_search"
16151615
assert result[0].vector_store_ids == ["vs1", "vs2"]
16161616

1617-
@pytest.mark.asyncio
1618-
async def test_prepare_tools_fetch_vector_stores(
1619-
self, mocker: MockerFixture
1620-
) -> None:
1621-
"""Test prepare_tools fetches vector stores when not specified."""
1622-
mock_client = mocker.AsyncMock()
1623-
mock_vector_store1 = mocker.Mock()
1624-
mock_vector_store1.id = "vs1"
1625-
mock_vector_store2 = mocker.Mock()
1626-
mock_vector_store2.id = "vs2"
1627-
mock_vector_stores = mocker.Mock()
1628-
mock_vector_stores.data = [mock_vector_store1, mock_vector_store2]
1629-
mock_client.vector_stores.list = mocker.AsyncMock(
1630-
return_value=mock_vector_stores
1631-
)
1632-
mocker.patch("utils.responses.get_mcp_tools", return_value=None)
1633-
1634-
result = await prepare_tools(mock_client, None, False, "token")
1635-
assert result is not None
1636-
assert len(result) == 1
1637-
assert isinstance(result[0], InputToolFileSearch)
1638-
assert result[0].vector_store_ids == ["vs1", "vs2"]
1639-
1640-
@pytest.mark.asyncio
1641-
async def test_prepare_tools_connection_error(self, mocker: MockerFixture) -> None:
1642-
"""Test prepare_tools raises HTTPException on connection error."""
1643-
mock_client = mocker.AsyncMock()
1644-
mock_client.vector_stores.list = mocker.AsyncMock(
1645-
side_effect=APIConnectionError(
1646-
message="Connection failed", request=mocker.Mock()
1647-
)
1648-
)
1649-
1650-
with pytest.raises(HTTPException) as exc_info:
1651-
await prepare_tools(mock_client, None, False, "token")
1652-
assert exc_info.value.status_code == 503
1653-
16541617
@pytest.mark.asyncio
16551618
async def test_prepare_tools_with_mcp_servers(self, mocker: MockerFixture) -> None:
16561619
"""Test prepare_tools includes MCP tools."""
@@ -1666,20 +1629,6 @@ async def test_prepare_tools_with_mcp_servers(self, mocker: MockerFixture) -> No
16661629
assert len(result) == 2 # RAG tool + MCP tool
16671630
assert any(tool.type == "mcp" for tool in result)
16681631

1669-
@pytest.mark.asyncio
1670-
async def test_prepare_tools_api_status_error(self, mocker: MockerFixture) -> None:
1671-
"""Test prepare_tools raises HTTPException on API status error when fetching vector stores."""
1672-
mock_client = mocker.AsyncMock()
1673-
mock_client.vector_stores.list = mocker.AsyncMock(
1674-
side_effect=APIStatusError(
1675-
message="API error", response=mocker.Mock(request=None), body=None
1676-
)
1677-
)
1678-
1679-
with pytest.raises(HTTPException) as exc_info:
1680-
await prepare_tools(mock_client, None, False, "token")
1681-
assert exc_info.value.status_code == 500
1682-
16831632
@pytest.mark.asyncio
16841633
async def test_prepare_tools_empty_toolgroups(self, mocker: MockerFixture) -> None:
16851634
"""Test prepare_tools returns None when no tools are available."""
@@ -1812,38 +1761,6 @@ async def test_passes_through_unknown_ids_in_prepare_tools(
18121761
assert isinstance(result[0], InputToolFileSearch)
18131762
assert result[0].vector_store_ids == ["raw-internal-id"]
18141763

1815-
@pytest.mark.asyncio
1816-
async def test_does_not_translate_when_ids_fetched_from_llama_stack(
1817-
self, mocker: MockerFixture
1818-
) -> None:
1819-
"""Test that IDs fetched from llama-stack (None path) are not translated."""
1820-
mock_client = mocker.AsyncMock()
1821-
mock_vector_store = mocker.Mock()
1822-
mock_vector_store.id = "vs-internal"
1823-
mock_vector_stores = mocker.Mock()
1824-
mock_vector_stores.data = [mock_vector_store]
1825-
mock_client.vector_stores.list = mocker.AsyncMock(
1826-
return_value=mock_vector_stores
1827-
)
1828-
mocker.patch("utils.responses.get_mcp_tools", return_value=None)
1829-
1830-
# Configure BYOK RAG whose rag_id matches the fetched ID so that
1831-
# accidental translation would change the result and fail the assertion
1832-
mock_byok_rag = mocker.Mock()
1833-
mock_byok_rag.rag_id = "vs-internal"
1834-
mock_byok_rag.vector_db_id = "vs-translated"
1835-
mock_config = mocker.Mock()
1836-
mock_config.configuration.byok_rag = [mock_byok_rag]
1837-
mock_config.configuration.rag.tool = []
1838-
mock_config.configuration.rag.inline = []
1839-
mocker.patch("utils.responses.configuration", mock_config)
1840-
1841-
result = await prepare_tools(mock_client, None, False, "token")
1842-
assert result is not None
1843-
# The IDs from llama-stack should be used as-is (no BYOK translation on None path)
1844-
assert isinstance(result[0], InputToolFileSearch)
1845-
assert result[0].vector_store_ids == ["vs-internal"]
1846-
18471764

18481765
class TestPrepareToolsVectorStoreResolution:
18491766
"""Tests for vector store ID resolution priority in prepare_tools."""
@@ -1895,8 +1812,10 @@ async def test_rag_tool_config_ids_are_translated(
18951812
mock_client.vector_stores.list.assert_not_called()
18961813

18971814
@pytest.mark.asyncio
1898-
async def test_inline_rag_disables_tool_rag(self, mocker: MockerFixture) -> None:
1899-
"""Test that configuring rag.inline without rag.tool disables tool RAG."""
1815+
async def test_inline_rag_config_does_not_affect_tool_rag(
1816+
self, mocker: MockerFixture
1817+
) -> None:
1818+
"""Test that configuring rag.inline have no effect on tool rag."""
19001819
mock_client = mocker.AsyncMock()
19011820
mocker.patch("utils.responses.get_mcp_tools", return_value=None)
19021821

@@ -1910,7 +1829,6 @@ async def test_inline_rag_disables_tool_rag(self, mocker: MockerFixture) -> None
19101829

19111830
result = await prepare_tools(mock_client, None, False, "token")
19121831

1913-
# Tool RAG should be disabled — no RAG tool in result, no llama-stack fetch
19141832
assert result is None
19151833
mock_client.vector_stores.list.assert_not_called()
19161834

@@ -1936,30 +1854,22 @@ async def test_per_request_ids_override_rag_tool_config(
19361854
mock_client.vector_stores.list.assert_not_called()
19371855

19381856
@pytest.mark.asyncio
1939-
async def test_all_registered_dbs_used_when_neither_tool_nor_inline_configured(
1857+
async def test_tool_rag_disabled_when_tool_not_configured(
19401858
self, mocker: MockerFixture
19411859
) -> None:
1942-
"""Test fallback to all registered vector DBs when neither rag.tool nor rag.inline are set."""
1860+
"""Test no rag tools is returned when rag.tool is not set and there is no per-request vector ids."""
19431861
mock_client = mocker.AsyncMock()
1944-
mock_vs = mocker.Mock()
1945-
mock_vs.id = "vs-registered"
1946-
mock_list = mocker.Mock()
1947-
mock_list.data = [mock_vs]
1948-
mock_client.vector_stores.list = mocker.AsyncMock(return_value=mock_list)
19491862
mocker.patch("utils.responses.get_mcp_tools", return_value=None)
19501863

19511864
mock_config = mocker.Mock()
19521865
mock_config.configuration.byok_rag = []
19531866
mock_config.configuration.rag.tool = []
1954-
mock_config.configuration.rag.inline = []
19551867
mocker.patch("utils.responses.configuration", mock_config)
19561868

19571869
result = await prepare_tools(mock_client, None, False, "token")
19581870

1959-
assert result is not None
1960-
assert isinstance(result[0], InputToolFileSearch)
1961-
assert result[0].vector_store_ids == ["vs-registered"]
1962-
mock_client.vector_stores.list.assert_called_once()
1871+
assert result is None
1872+
mock_client.vector_stores.list.assert_not_called()
19631873

19641874

19651875
class TestPrepareResponsesParams:
@@ -2150,9 +2060,9 @@ async def test_prepare_responses_params_includes_mcp_provider_data_headers(
21502060

21512061
# The result should contain extra_headers with x-llamastack-provider-data
21522062
dumped = result.model_dump()
2153-
assert dumped["extra_headers"] is not None, (
2154-
"extra_headers should not be None when MCP tools have headers"
2155-
)
2063+
assert (
2064+
dumped["extra_headers"] is not None
2065+
), "extra_headers should not be None when MCP tools have headers"
21562066
assert "x-llamastack-provider-data" in dumped["extra_headers"]
21572067

21582068
provider_data = json.loads(

0 commit comments

Comments
 (0)