Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/uipath-platform/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "uipath-platform"
version = "0.0.25"
version = "0.0.26"
description = "HTTP client library for programmatic access to UiPath Platform"
readme = { file = "README.md", content-type = "text/markdown" }
requires-python = ">=3.11"
Expand Down
5 changes: 5 additions & 0 deletions packages/uipath-platform/src/uipath/platform/_uipath.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

from .action_center import TasksService
from .agenthub._agenthub_service import AgentHubService
from .agenthub._remote_a2a_service import RemoteA2aService
from .chat import ConversationsService, UiPathLlmChatService, UiPathOpenAIService
from .common import (
ApiClient,
Expand Down Expand Up @@ -162,6 +163,10 @@ def guardrails(self) -> GuardrailsService:
def agenthub(self) -> AgentHubService:
return AgentHubService(self._config, self._execution_context, self.folders)

@property
def remote_a2a(self) -> RemoteA2aService:
return RemoteA2aService(self._config, self._execution_context, self.folders)

@property
def orchestrator_setup(self) -> OrchestratorSetupService:
return OrchestratorSetupService(self._config, self._execution_context)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
"""UiPath AgentHub Models.
"""UiPath AgentHub Models and Services.

This module contains models related to UiPath AgentHub service.
This module contains models and services related to UiPath AgentHub.
"""

from uipath.platform.agenthub._remote_a2a_service import RemoteA2aService
from uipath.platform.agenthub.agenthub import LlmModel
from uipath.platform.agenthub.remote_a2a import RemoteA2aAgent, RemoteA2aAgentFolder

__all__ = ["LlmModel"]
__all__ = ["LlmModel", "RemoteA2aAgent", "RemoteA2aAgentFolder", "RemoteA2aService"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,283 @@
"""Service for managing Remote A2A agents in UiPath AgentHub.

.. warning::
This module is experimental and subject to change.
The Remote A2A feature is in preview and its API may change in future releases.
"""

import warnings
from typing import Any, List

from ..common._base_service import BaseService
from ..common._config import UiPathApiConfig
from ..common._execution_context import UiPathExecutionContext
from ..common._folder_context import FolderContext, header_folder
from ..common._models import Endpoint, RequestSpec
from ..orchestrator import FolderService
from .remote_a2a import RemoteA2aAgent


class RemoteA2aService(FolderContext, BaseService):
"""Service for managing Remote A2A agents in UiPath AgentHub.

.. warning::
This service is experimental and subject to change.
"""

def __init__(
self,
config: UiPathApiConfig,
execution_context: UiPathExecutionContext,
folders_service: FolderService,
) -> None:
super().__init__(config=config, execution_context=execution_context)
self._folders_service = folders_service

def list(
self,
*,
top: int | None = None,
skip: int | None = None,
search: str | None = None,
folder_path: str | None = None,
) -> List[RemoteA2aAgent]:
"""List Remote A2A agents.

.. warning::
This method is experimental and subject to change.

When called without folder_path, returns all agents across
the tenant that the user has access to. When called with a folder,
returns only agents in that folder.

Args:
top: Maximum number of agents to return.
skip: Number of agents to skip (for pagination).
search: Filter agents by name or slug.
folder_path: Optional folder path to scope the query.

Returns:
List[RemoteA2aAgent]: A list of Remote A2A agents.

Examples:
```python
from uipath import UiPath

client = UiPath()

# List all agents across tenant
agents = client.remote_a2a.list()
for agent in agents:
print(f"{agent.name} - {agent.slug}")

# List with folder scope
agents = client.remote_a2a.list(folder_path="MyFolder")
```
"""
warnings.warn(
"remote_a2a.list is experimental and subject to change.",
stacklevel=2,
)
spec = self._list_spec(
top=top,
skip=skip,
search=search,
folder_path=folder_path,
)
response = self.request(
spec.method,
url=spec.endpoint,
params=spec.params,
headers=spec.headers,
)
data = response.json()
return [RemoteA2aAgent.model_validate(agent) for agent in data.get("value", [])]

async def list_async(
self,
*,
top: int | None = None,
skip: int | None = None,
search: str | None = None,
folder_path: str | None = None,
) -> List[RemoteA2aAgent]:
"""Asynchronously list Remote A2A agents.

.. warning::
This method is experimental and subject to change.

Args:
top: Maximum number of agents to return.
skip: Number of agents to skip (for pagination).
search: Filter agents by name or slug.
folder_path: Optional folder path to scope the query.

Returns:
List[RemoteA2aAgent]: A list of Remote A2A agents.

Examples:
```python
import asyncio
from uipath import UiPath

sdk = UiPath()

async def main():
agents = await sdk.remote_a2a.list_async()
for agent in agents:
print(f"{agent.name} - {agent.slug}")

asyncio.run(main())
```
"""
warnings.warn(
"remote_a2a.list_async is experimental and subject to change.",
stacklevel=2,
)
spec = self._list_spec(
top=top,
skip=skip,
search=search,
folder_path=folder_path,
)
response = await self.request_async(
spec.method,
url=spec.endpoint,
params=spec.params,
headers=spec.headers,
)
data = response.json()
return [RemoteA2aAgent.model_validate(agent) for agent in data.get("value", [])]

def retrieve(
self,
slug: str,
*,
folder_path: str | None = None,
) -> RemoteA2aAgent:
"""Retrieve a specific Remote A2A agent by slug.

.. warning::
This method is experimental and subject to change.

Args:
slug: The unique slug identifier for the agent.
folder_path: The folder path where the agent is located.

Returns:
RemoteA2aAgent: The Remote A2A agent.

Examples:
```python
from uipath import UiPath

client = UiPath()

agent = client.remote_a2a.retrieve("weather", folder_path="MyFolder")
print(f"Agent: {agent.name}, URL: {agent.a2a_url}")
```
"""
warnings.warn(
"remote_a2a.retrieve is experimental and subject to change.",
stacklevel=2,
)
spec = self._retrieve_spec(slug=slug, folder_path=folder_path)
response = self.request(
spec.method,
url=spec.endpoint,
params=spec.params,
headers=spec.headers,
)
return RemoteA2aAgent.model_validate(response.json())

async def retrieve_async(
self,
slug: str,
*,
folder_path: str | None = None,
) -> RemoteA2aAgent:
"""Asynchronously retrieve a specific Remote A2A agent by slug.

.. warning::
This method is experimental and subject to change.

Args:
slug: The unique slug identifier for the agent.
folder_path: The folder path where the agent is located.

Returns:
RemoteA2aAgent: The Remote A2A agent.

Examples:
```python
import asyncio
from uipath import UiPath

sdk = UiPath()

async def main():
agent = await sdk.remote_a2a.retrieve_async("weather", folder_path="MyFolder")
print(f"Agent: {agent.name}, URL: {agent.a2a_url}")

asyncio.run(main())
```
"""
warnings.warn(
"remote_a2a.retrieve_async is experimental and subject to change.",
stacklevel=2,
)
spec = self._retrieve_spec(slug=slug, folder_path=folder_path)
response = await self.request_async(
spec.method,
url=spec.endpoint,
params=spec.params,
headers=spec.headers,
)
return RemoteA2aAgent.model_validate(response.json())

@property
def custom_headers(self) -> dict[str, str]:
return self.folder_headers

def _list_spec(
self,
*,
top: int | None,
skip: int | None,
search: str | None,
folder_path: str | None,
) -> RequestSpec:
headers = {}
if folder_path is not None:
folder_key = self._folders_service.retrieve_folder_key(folder_path)
headers = header_folder(folder_key, None)

params: dict[str, Any] = {}
if top is not None:
params["top"] = top
if skip is not None:
params["skip"] = skip
if search is not None:
params["search"] = search

return RequestSpec(
method="GET",
endpoint=Endpoint("/agenthub_/api/remote-a2a-agents"),
params=params,
headers=headers,
)

def _retrieve_spec(
self,
slug: str,
*,
folder_path: str | None,
) -> RequestSpec:
folder_key = self._folders_service.retrieve_folder_key(folder_path)
return RequestSpec(
method="GET",
endpoint=Endpoint(f"/agenthub_/api/remote-a2a-agents/{slug}"),
headers={
**header_folder(folder_key, None),
},
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
"""Models for Remote A2A Agents in UiPath AgentHub.

.. warning::
This module is experimental and subject to change.
The Remote A2A feature is in preview and its API may change in future releases.
"""

from datetime import datetime
from typing import Any, Optional

from pydantic import BaseModel, ConfigDict, Field
from pydantic.alias_generators import to_camel


class RemoteA2aAgentFolder(BaseModel):
"""Folder information for a Remote A2A agent."""

model_config = ConfigDict(
alias_generator=to_camel,
populate_by_name=True,
use_enum_values=True,
arbitrary_types_allowed=True,
extra="allow",
)

key: Optional[str] = None
display_name: Optional[str] = None
fully_qualified_name: Optional[str] = None


class RemoteA2aAgent(BaseModel):
"""Model representing a Remote A2A agent in UiPath AgentHub.

.. warning::
This model is experimental and subject to change.
"""

model_config = ConfigDict(
alias_generator=to_camel,
populate_by_name=True,
use_enum_values=True,
arbitrary_types_allowed=True,
extra="allow",
)

id: Optional[str] = None
name: Optional[str] = None
slug: Optional[str] = None
description: Optional[str] = None
agent_card_url: Optional[str] = None
a2a_url: Optional[str] = Field(None, alias="a2aUrl")
folder: Optional[RemoteA2aAgentFolder] = None
headers: Optional[str] = None
is_active: Optional[bool] = None
cached_agent_card: Optional[Any] = None
created_at: Optional[datetime] = None
created_by: Optional[str] = None
updated_at: Optional[datetime] = None
updated_by: Optional[str] = None
2 changes: 1 addition & 1 deletion packages/uipath-platform/uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading