Skip to content

Commit 288789c

Browse files
radugheojepadil23
authored andcommitted
fix(a2a-tool): resolve proxy url via remote_a2a.retrieve instead of resource field (#931)
1 parent a607e87 commit 288789c

4 files changed

Lines changed: 296 additions & 70 deletions

File tree

pyproject.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
[project]
22
name = "uipath-langchain"
3-
version = "0.13.5"
3+
version = "0.13.6"
44
description = "Python SDK that enables developers to build and deploy LangGraph agents to the UiPath Cloud Platform"
55
readme = { file = "README.md", content-type = "text/markdown" }
66
requires-python = ">=3.11"
77
dependencies = [
8-
"uipath>=2.11.10, <2.12.0",
8+
"uipath>=2.11.12, <2.12.0",
99
"uipath-core>=0.5.20, <0.6.0",
10-
"uipath-platform>=0.1.71, <0.2.0",
10+
"uipath-platform>=0.1.75, <0.2.0",
1111
"uipath-runtime>=0.11.2, <0.12.0",
1212
"langgraph>=1.1.8, <2.0.0",
1313
"langchain-core>=1.2.27, <2.0.0",

src/uipath_langchain/agent/tools/a2a/a2a_tool.py

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
from uipath._utils._ssl_context import get_httpx_client_kwargs
3535
from uipath.agent.models.agent import AgentA2aResourceConfig
3636

37+
from uipath_langchain._utils import get_execution_folder_path
3738
from uipath_langchain.agent.react.types import AgentGraphState
3839
from uipath_langchain.agent.tools.base_uipath_structured_tool import (
3940
BaseUiPathStructuredTool,
@@ -65,8 +66,9 @@ class A2aClient:
6566
pool when done.
6667
"""
6768

68-
def __init__(self, agent_card: AgentCard) -> None:
69+
def __init__(self, agent_card: AgentCard, slug: str) -> None:
6970
self._agent_card = agent_card
71+
self._slug = slug
7072
self._lock = asyncio.Lock()
7173
self._client: Client | None = None
7274
self._http_client: httpx.AsyncClient | None = None
@@ -80,6 +82,16 @@ async def get(self) -> Client:
8082
from uipath.platform import UiPath
8183

8284
sdk = UiPath()
85+
folder_path = get_execution_folder_path()
86+
agent = await sdk.remote_a2a.retrieve_async(
87+
slug=self._slug, folder_path=folder_path
88+
)
89+
if not agent.a2a_url:
90+
raise ValueError(
91+
f"Remote A2A agent '{self._slug}' has no a2a_url configured"
92+
)
93+
self._agent_card.url = agent.a2a_url
94+
8395
client_kwargs = get_httpx_client_kwargs(
8496
headers={"Authorization": f"Bearer {sdk._config.secret}"},
8597
)
@@ -152,19 +164,16 @@ def _build_description(card: AgentCard) -> str:
152164
skill_desc += f": {skill.description}"
153165
if skill_desc:
154166
parts.append(f"Skill: {skill_desc}")
155-
return " | ".join(parts) if parts else f"Remote A2A agent at {card.url}"
156-
157-
158-
def _resolve_a2a_url(config: AgentA2aResourceConfig) -> str:
159-
"""Resolve the A2A endpoint URL, using the UiPath-hosted proxy URL."""
160-
if config.a2a_url:
161-
return config.a2a_url
162-
raise ValueError(f"A2A resource '{config.name}' has no URL")
167+
if parts:
168+
return " | ".join(parts)
169+
# The card URL is resolved lazily at runtime, so it is empty or stale here;
170+
# fall back to the agent name rather than exposing an internal/blank URL.
171+
return f"Remote A2A agent: {card.name}" if card.name else "Remote A2A agent"
163172

164173

165174
async def _send_a2a_message(
166175
client: Client,
167-
a2a_url: str,
176+
agent_label: str,
168177
*,
169178
message: str,
170179
task_id: str | None,
@@ -177,10 +186,10 @@ async def _send_a2a_message(
177186
"""
178187
if task_id or context_id:
179188
logger.info(
180-
"A2A continue task=%s context=%s to %s", task_id, context_id, a2a_url
189+
"A2A continue task=%s context=%s to %s", task_id, context_id, agent_label
181190
)
182191
else:
183-
logger.info("A2A new message to %s", a2a_url)
192+
logger.info("A2A new message to %s", agent_label)
184193

185194
a2a_message = Message(
186195
role=Role.user,
@@ -218,7 +227,7 @@ async def _send_a2a_message(
218227
return (text or "No response received.", state, new_task_id, new_context_id)
219228

220229
except Exception as e:
221-
logger.exception("A2A request to %s failed", a2a_url)
230+
logger.exception("A2A request to %s failed", agent_label)
222231
return (f"Error: {e}", "error", task_id, context_id)
223232

224233

@@ -234,7 +243,7 @@ def _create_a2a_tool(
234243
raw_name = agent_card.name or config.name
235244
tool_name = sanitize_tool_name(raw_name)
236245
tool_description = _build_description(agent_card)
237-
a2a_url = _resolve_a2a_url(config)
246+
agent_label = config.slug
238247

239248
metadata = {
240249
"tool_type": "a2a",
@@ -245,7 +254,7 @@ def _create_a2a_tool(
245254
async def _send(*, message: str) -> str:
246255
client = await a2a_client.get()
247256
text, state, _, _ = await _send_a2a_message(
248-
client, a2a_url, message=message, task_id=None, context_id=None
257+
client, agent_label, message=message, task_id=None, context_id=None
249258
)
250259
return _format_response(text, state)
251260

@@ -261,7 +270,7 @@ async def _a2a_wrapper(
261270
client = await a2a_client.get()
262271
text, task_state, new_task_id, new_context_id = await _send_a2a_message(
263272
client,
264-
a2a_url,
273+
agent_label,
265274
message=call["args"]["message"],
266275
task_id=task_id,
267276
context_id=context_id,
@@ -341,10 +350,7 @@ def create_a2a_tools_and_clients(
341350
default_output_modes=["text/plain"],
342351
)
343352

344-
if resource.a2a_url:
345-
agent_card.url = resource.a2a_url
346-
347-
a2a_client = A2aClient(agent_card)
353+
a2a_client = A2aClient(agent_card, resource.slug)
348354
tool = _create_a2a_tool(resource, a2a_client, agent_card)
349355
tools.append(tool)
350356
clients.append(a2a_client)

0 commit comments

Comments
 (0)