From aaf39b330a5874bd4835e1e3ae61e9aa2a9fc18c Mon Sep 17 00:00:00 2001 From: tudormatei Date: Tue, 13 Oct 2026 12:13:38 +0300 Subject: [PATCH 1/4] feat(agenthub): opt into retired models on LLM model discovery LLM Gateway lists a model past its usage end date for the requested feature only when discovery is called with includeDeprecatedModels=true, flagged isDeprecated and described by the successor it serves the retired name on. The runtime resolves an agent's model through get_available_llm_models, so without the flag an agent still configured with a retired name fails at startup. get_available_llm_models and its async variant take a keyword-only include_deprecated_models, default False, so `uipath list-models` and the uipath-dev evaluator picker keep listing only offered models. The runtime callers opt in separately. --- packages/uipath-platform/pyproject.toml | 2 +- .../platform/agenthub/_agenthub_service.py | 37 ++++++++-- .../tests/services/test_agenthub_service.py | 74 +++++++++++++++++++ packages/uipath-platform/uv.lock | 2 +- 4 files changed, 108 insertions(+), 7 deletions(-) create mode 100644 packages/uipath-platform/tests/services/test_agenthub_service.py diff --git a/packages/uipath-platform/pyproject.toml b/packages/uipath-platform/pyproject.toml index 4699bfeeb..df2ba2732 100644 --- a/packages/uipath-platform/pyproject.toml +++ b/packages/uipath-platform/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "uipath-platform" -version = "0.2.36" +version = "0.2.37" description = "HTTP client library for programmatic access to UiPath Platform" readme = { file = "README.md", content-type = "text/markdown" } requires-python = ">=3.11" diff --git a/packages/uipath-platform/src/uipath/platform/agenthub/_agenthub_service.py b/packages/uipath-platform/src/uipath/platform/agenthub/_agenthub_service.py index 4119a433f..19a53166b 100644 --- a/packages/uipath-platform/src/uipath/platform/agenthub/_agenthub_service.py +++ b/packages/uipath-platform/src/uipath/platform/agenthub/_agenthub_service.py @@ -22,14 +22,25 @@ def __init__( super().__init__(config=config, execution_context=execution_context) def get_available_llm_models( - self, headers: dict[str, Any] | None = None + self, + headers: dict[str, Any] | None = None, + *, + include_deprecated_models: bool = False, ) -> list[LlmModel]: """Fetch available models from LLM Gateway discovery endpoint. + Args: + headers: Extra headers sent with the discovery request. + include_deprecated_models: Also return the models already retired for + the requested feature, flagged `isDeprecated` and described by the + successor LLM Gateway serves them on. + Returns: List of available models and their configurations. """ - spec = self._available_models_spec(headers=headers) + spec = self._available_models_spec( + headers=headers, include_deprecated_models=include_deprecated_models + ) response = self.request( spec.method, @@ -43,14 +54,25 @@ def get_available_llm_models( ] async def get_available_llm_models_async( - self, headers: dict[str, Any] | None = None + self, + headers: dict[str, Any] | None = None, + *, + include_deprecated_models: bool = False, ) -> list[LlmModel]: """Asynchronously fetch available models from LLM Gateway discovery endpoint. + Args: + headers: Extra headers sent with the discovery request. + include_deprecated_models: Also return the models already retired for + the requested feature, flagged `isDeprecated` and described by the + successor LLM Gateway serves them on. + Returns: List of available models and their configurations. """ - spec = self._available_models_spec(headers=headers) + spec = self._available_models_spec( + headers=headers, include_deprecated_models=include_deprecated_models + ) response = await self.request_async( spec.method, @@ -197,9 +219,14 @@ def _resolve_folder_key( return folder_key - def _available_models_spec(self, headers: dict[str, Any] | None) -> RequestSpec: + def _available_models_spec( + self, headers: dict[str, Any] | None, include_deprecated_models: bool + ) -> RequestSpec: return RequestSpec( method="GET", endpoint=Endpoint("/agenthub_/llm/api/discovery"), + params={"includeDeprecatedModels": "true"} + if include_deprecated_models + else {}, headers=headers or {}, ) diff --git a/packages/uipath-platform/tests/services/test_agenthub_service.py b/packages/uipath-platform/tests/services/test_agenthub_service.py new file mode 100644 index 000000000..2a1fb42b7 --- /dev/null +++ b/packages/uipath-platform/tests/services/test_agenthub_service.py @@ -0,0 +1,74 @@ +import pytest +from pytest_httpx import HTTPXMock + +from uipath.platform import UiPathApiConfig, UiPathExecutionContext +from uipath.platform.agenthub._agenthub_service import AgentHubService +from uipath.platform.orchestrator._folder_service import FolderService + +RETIRED_MODEL = { + "modelName": "gpt-4o-2024-05-13", + "vendor": "OpenAi", + "effectiveModel": "gpt-5.1-2025-11-13", + "isDeprecated": True, + "deprecationDetails": { + "usageEndDate": "2026-09-30", + "replacedBy": "gpt-5.1-2025-11-13", + }, +} + + +@pytest.fixture +def service( + config: UiPathApiConfig, execution_context: UiPathExecutionContext +) -> AgentHubService: + return AgentHubService( + config=config, + execution_context=execution_context, + folder_service=FolderService( + config=config, execution_context=execution_context + ), + ) + + +@pytest.fixture +def discovery_url(base_url: str, org: str, tenant: str) -> str: + return f"{base_url}{org}{tenant}/agenthub_/llm/api/discovery" + + +class TestGetAvailableLlmModels: + def test_does_not_request_deprecated_models_by_default( + self, httpx_mock: HTTPXMock, service: AgentHubService, discovery_url: str + ) -> None: + httpx_mock.add_response(url=discovery_url, json=[]) + + service.get_available_llm_models() + + request = httpx_mock.get_request() + assert request is not None + assert "includeDeprecatedModels" not in request.url.params + + def test_requests_deprecated_models_when_asked( + self, httpx_mock: HTTPXMock, service: AgentHubService, discovery_url: str + ) -> None: + httpx_mock.add_response( + url=f"{discovery_url}?includeDeprecatedModels=true", + json=[RETIRED_MODEL], + ) + + models = service.get_available_llm_models(include_deprecated_models=True) + + assert [m.model_dump(by_alias=True) for m in models] == [RETIRED_MODEL] + + async def test_async_requests_deprecated_models_when_asked( + self, httpx_mock: HTTPXMock, service: AgentHubService, discovery_url: str + ) -> None: + httpx_mock.add_response( + url=f"{discovery_url}?includeDeprecatedModels=true", + json=[RETIRED_MODEL], + ) + + models = await service.get_available_llm_models_async( + include_deprecated_models=True + ) + + assert [m.model_dump(by_alias=True) for m in models] == [RETIRED_MODEL] diff --git a/packages/uipath-platform/uv.lock b/packages/uipath-platform/uv.lock index 99070bbf4..9ada6c4ac 100644 --- a/packages/uipath-platform/uv.lock +++ b/packages/uipath-platform/uv.lock @@ -1095,7 +1095,7 @@ dev = [ [[package]] name = "uipath-platform" -version = "0.2.36" +version = "0.2.37" source = { editable = "." } dependencies = [ { name = "anyio" }, From 6e7a77137ae563e460a31d217046fad6c1c7a3a6 Mon Sep 17 00:00:00 2001 From: tudormatei Date: Tue, 13 Oct 2026 13:09:29 +0300 Subject: [PATCH 2/4] chore(uipath): lock the editable uipath-platform at 0.2.37 --- packages/uipath/uv.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/uipath/uv.lock b/packages/uipath/uv.lock index cede61da3..251d803e4 100644 --- a/packages/uipath/uv.lock +++ b/packages/uipath/uv.lock @@ -2762,7 +2762,7 @@ wheels = [ [[package]] name = "uipath-platform" -version = "0.2.36" +version = "0.2.37" source = { editable = "../uipath-platform" } dependencies = [ { name = "anyio" }, From 32e7f52650c583b29105312e32a514e8c4aaf272 Mon Sep 17 00:00:00 2001 From: tudormatei Date: Tue, 13 Oct 2026 15:17:15 +0300 Subject: [PATCH 3/4] docs(uipath): list include_deprecated_models in the SDK reference --- packages/uipath/pyproject.toml | 4 ++-- packages/uipath/src/uipath/_resources/SDK_REFERENCE.md | 4 ++-- packages/uipath/uv.lock | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/uipath/pyproject.toml b/packages/uipath/pyproject.toml index c8ae36006..03591f19e 100644 --- a/packages/uipath/pyproject.toml +++ b/packages/uipath/pyproject.toml @@ -1,13 +1,13 @@ [project] name = "uipath" -version = "2.14.37" +version = "2.14.38" description = "Python SDK and CLI for UiPath Platform, enabling programmatic interaction with automation services, process management, and deployment tools." readme = { file = "README.md", content-type = "text/markdown" } requires-python = ">=3.11" dependencies = [ "uipath-core>=0.5.33, <0.6.0", "uipath-runtime>=0.13.5, <0.14.0", - "uipath-platform>=0.2.34, <0.3.0", + "uipath-platform>=0.2.37, <0.3.0", "uipath-ipc>=2.5.1, <2.6.0", "click>=8.3.3, <9.0.0", "httpx>=0.28.1", diff --git a/packages/uipath/src/uipath/_resources/SDK_REFERENCE.md b/packages/uipath/src/uipath/_resources/SDK_REFERENCE.md index 35eb97606..f433f34db 100644 --- a/packages/uipath/src/uipath/_resources/SDK_REFERENCE.md +++ b/packages/uipath/src/uipath/_resources/SDK_REFERENCE.md @@ -22,10 +22,10 @@ Agenthub service ```python # Fetch available models from LLM Gateway discovery endpoint. -sdk.agenthub.get_available_llm_models(headers: dict[str, Any] | None=None) -> list[uipath.platform.agenthub.agenthub.LlmModel] +sdk.agenthub.get_available_llm_models(headers: dict[str, Any] | None=None, include_deprecated_models: bool=False) -> list[uipath.platform.agenthub.agenthub.LlmModel] # Asynchronously fetch available models from LLM Gateway discovery endpoint. -sdk.agenthub.get_available_llm_models_async(headers: dict[str, Any] | None=None) -> list[uipath.platform.agenthub.agenthub.LlmModel] +sdk.agenthub.get_available_llm_models_async(headers: dict[str, Any] | None=None, include_deprecated_models: bool=False) -> list[uipath.platform.agenthub.agenthub.LlmModel] # Start a system agent job. sdk.agenthub.invoke_system_agent(agent_name: str, entrypoint: str, input_arguments: dict[str, Any] | None=None, folder_key: str | None=None, folder_path: str | None=None, headers: dict[str, Any] | None=None) -> str diff --git a/packages/uipath/uv.lock b/packages/uipath/uv.lock index 251d803e4..1a9dc47af 100644 --- a/packages/uipath/uv.lock +++ b/packages/uipath/uv.lock @@ -2599,7 +2599,7 @@ wheels = [ [[package]] name = "uipath" -version = "2.14.37" +version = "2.14.38" source = { editable = "." } dependencies = [ { name = "applicationinsights" }, From dd300dbc8df2e0196e0a31427a7b59d8abe1a63b Mon Sep 17 00:00:00 2001 From: tudormatei Date: Wed, 14 Oct 2026 12:14:48 +0300 Subject: [PATCH 4/4] chore(agenthub): keep the discovery docstrings as they were on main --- .../uipath/platform/agenthub/_agenthub_service.py | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/packages/uipath-platform/src/uipath/platform/agenthub/_agenthub_service.py b/packages/uipath-platform/src/uipath/platform/agenthub/_agenthub_service.py index 19a53166b..f47cb5e4c 100644 --- a/packages/uipath-platform/src/uipath/platform/agenthub/_agenthub_service.py +++ b/packages/uipath-platform/src/uipath/platform/agenthub/_agenthub_service.py @@ -29,12 +29,6 @@ def get_available_llm_models( ) -> list[LlmModel]: """Fetch available models from LLM Gateway discovery endpoint. - Args: - headers: Extra headers sent with the discovery request. - include_deprecated_models: Also return the models already retired for - the requested feature, flagged `isDeprecated` and described by the - successor LLM Gateway serves them on. - Returns: List of available models and their configurations. """ @@ -61,12 +55,6 @@ async def get_available_llm_models_async( ) -> list[LlmModel]: """Asynchronously fetch available models from LLM Gateway discovery endpoint. - Args: - headers: Extra headers sent with the discovery request. - include_deprecated_models: Also return the models already retired for - the requested feature, flagged `isDeprecated` and described by the - successor LLM Gateway serves them on. - Returns: List of available models and their configurations. """