Skip to content

Commit f536077

Browse files
fix: retrieve the routing context to be derived from folders_map and … (#749)
1 parent 1389d3a commit f536077

File tree

6 files changed

+38
-82
lines changed

6 files changed

+38
-82
lines changed

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
[project]
22
name = "uipath-langchain"
3-
version = "0.9.23"
3+
version = "0.9.24"
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 = [
88
"uipath>=2.10.29, <2.11.0",
99
"uipath-core>=0.5.2, <0.6.0",
10-
"uipath-platform>=0.1.23, <0.2.0",
10+
"uipath-platform>=0.1.24, <0.2.0",
1111
"uipath-runtime>=0.10.0, <0.11.0",
1212
"langgraph>=1.0.0, <2.0.0",
1313
"langchain-core>=1.2.11, <2.0.0",

src/uipath_langchain/agent/tools/__init__.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
"""Tool creation and management for LowCode agents."""
22

33
from .context_tool import create_context_tool
4-
from .datafabric_tool import (
5-
fetch_entity_schemas,
6-
)
74
from .escalation_tool import create_escalation_tool
85
from .extraction_tool import create_ixp_extraction_tool
96
from .integration_tool import create_integration_tool
@@ -30,7 +27,6 @@
3027
"create_escalation_tool",
3128
"create_ixp_extraction_tool",
3229
"create_ixp_escalation_tool",
33-
"fetch_entity_schemas",
3430
"UiPathToolNode",
3531
"ToolWrapperMixin",
3632
"wrap_tools_with_error_handling",

src/uipath_langchain/agent/tools/datafabric_tool/__init__.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@
22

33
from .datafabric_tool import (
44
create_datafabric_query_tool,
5-
fetch_entity_schemas,
65
)
76

87
__all__ = [
98
"create_datafabric_query_tool",
10-
"fetch_entity_schemas",
119
]

src/uipath_langchain/agent/tools/datafabric_tool/datafabric_subgraph.py

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
from langgraph.graph.message import add_messages
2424
from langgraph.graph.state import CompiledStateGraph
2525
from pydantic import BaseModel
26-
from uipath.platform.entities import Entity, QueryRoutingOverrideContext
26+
from uipath.platform.entities import EntitiesService, Entity
2727

2828
from ..datafabric_query_tool import DataFabricQueryTool
2929
from . import datafabric_prompt_builder
@@ -42,18 +42,14 @@ class DataFabricSubgraphState(BaseModel):
4242
class QueryExecutor:
4343
"""Executes SQL queries against Data Fabric."""
4444

45-
def __init__(self, routing_context: QueryRoutingOverrideContext) -> None:
46-
from uipath.platform import UiPath
47-
48-
self._sdk = UiPath()
49-
self._routing_context = routing_context
45+
def __init__(self, entities_service: EntitiesService) -> None:
46+
self._entities = entities_service
5047

5148
async def __call__(self, sql_query: str) -> dict[str, Any]:
5249
logger.debug("execute_sql called with SQL: %s", sql_query)
5350
try:
54-
records = await self._sdk.entities.query_entity_records_async(
51+
records = await self._entities.query_entity_records_async(
5552
sql_query=sql_query,
56-
routing_context=self._routing_context,
5753
)
5854
return {
5955
"records": records,
@@ -81,14 +77,14 @@ def __init__(
8177
self,
8278
llm: BaseChatModel,
8379
entities: list[Entity],
84-
routing_context: QueryRoutingOverrideContext,
80+
entities_service: EntitiesService,
8581
max_iterations: int = 25,
8682
resource_description: str = "",
8783
base_system_prompt: str = "",
8884
) -> None:
8985
self._max_iterations = max_iterations
9086
self._execute_sql_tool = self._create_execute_sql_tool(
91-
routing_context, entities
87+
entities_service, entities
9288
)
9389
self._system_message = SystemMessage(
9490
content=datafabric_prompt_builder.build(
@@ -175,7 +171,7 @@ def router(self, state: DataFabricSubgraphState) -> str:
175171

176172
def _create_execute_sql_tool(
177173
self,
178-
routing_context: QueryRoutingOverrideContext,
174+
entities_service: EntitiesService,
179175
entities: list[Entity],
180176
) -> BaseTool:
181177
"""Create the inner ``execute_sql`` tool."""
@@ -188,15 +184,15 @@ def _create_execute_sql_tool(
188184
"tables and columns. Retry with a corrected query on errors."
189185
),
190186
args_schema=DataFabricExecuteSqlInput,
191-
coroutine=QueryExecutor(routing_context),
187+
coroutine=QueryExecutor(entities_service),
192188
metadata={"tool_type": "datafabric_sql"},
193189
)
194190

195191
@staticmethod
196192
def create(
197193
llm: BaseChatModel,
198194
entities: list[Entity],
199-
routing_context: QueryRoutingOverrideContext,
195+
entities_service: EntitiesService,
200196
max_iterations: int = 25,
201197
resource_description: str = "",
202198
base_system_prompt: str = "",
@@ -205,7 +201,7 @@ def create(
205201
graph = DataFabricGraph(
206202
llm,
207203
entities,
208-
routing_context,
204+
entities_service,
209205
max_iterations,
210206
resource_description,
211207
base_system_prompt,

src/uipath_langchain/agent/tools/datafabric_tool/datafabric_tool.py

Lines changed: 21 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
"""Data Fabric tool creation and resource detection.
22
3-
This module provides:
4-
1. An agentic ``query_datafabric`` tool with inner LLM sub-graph
5-
2. Entity schema fetching from the Data Fabric API
3+
This module provides an agentic ``query_datafabric`` tool with an inner
4+
LLM sub-graph.
65
76
The tool accepts natural language queries, runs an inner LangGraph
87
sub-graph for SQL generation + execution + self-correction, and
@@ -21,7 +20,7 @@
2120
from langchain_core.tools import BaseTool
2221
from langgraph.graph.state import CompiledStateGraph
2322
from uipath.agent.models.agent import AgentContextResourceConfig
24-
from uipath.platform.entities import Entity, EntityRouting, QueryRoutingOverrideContext
23+
from uipath.platform.entities import DataFabricEntityItem
2524

2625
from ..base_uipath_structured_tool import BaseUiPathStructuredTool
2726
from .models import DataFabricQueryInput
@@ -34,28 +33,27 @@
3433
class DataFabricTextQueryHandler:
3534
"""Manages lazy initialization and invocation of the Data Fabric sub-graph.
3635
37-
On first call, fetches entity schemas from the DF API and compiles
38-
the inner LangGraph sub-graph. Subsequent calls reuse the cached graph.
36+
On first call, resolves entity schemas and routing via the platform
37+
layer and compiles the inner LangGraph sub-graph. Subsequent calls
38+
reuse the cached graph.
3939
"""
4040

4141
def __init__(
4242
self,
43-
entity_identifiers: list[str],
44-
routing_context: QueryRoutingOverrideContext,
43+
entity_set: list[DataFabricEntityItem],
4544
llm: BaseChatModel,
4645
resource_description: str = "",
4746
base_system_prompt: str = "",
4847
) -> None:
49-
self._entity_identifiers = entity_identifiers
50-
self._routing_context = routing_context
48+
self._entity_set = entity_set
5149
self._llm = llm
5250
self._resource_description = resource_description
5351
self._base_system_prompt = base_system_prompt
5452
self._compiled: CompiledStateGraph[Any] | None = None
5553
self._init_lock = asyncio.Lock()
5654

5755
async def _ensure_datafabric_graph(self) -> CompiledStateGraph[Any]:
58-
"""Lazy-init: fetch schemas + build sub-graph on first call.
56+
"""Lazy-init: resolve entities + build sub-graph on first call.
5957
6058
Uses asyncio.Lock because the outer agent supports parallel
6159
tool calls — two concurrent invocations could race on first call.
@@ -67,18 +65,21 @@ async def _ensure_datafabric_graph(self) -> CompiledStateGraph[Any]:
6765
if self._compiled is not None:
6866
return self._compiled
6967

68+
from uipath.platform import UiPath
69+
7070
from .datafabric_subgraph import DataFabricGraph
7171

72-
entities = await fetch_entity_schemas(self._entity_identifiers)
73-
if not entities:
72+
sdk = UiPath()
73+
resolution = await sdk.entities.resolve_entity_set_async(self._entity_set)
74+
if not resolution.entities:
7475
raise ValueError(
7576
"No Data Fabric entity schemas could be fetched. "
7677
"Check entity identifiers and permissions."
7778
)
7879
self._compiled = DataFabricGraph.create(
7980
llm=self._llm,
80-
entities=entities,
81-
routing_context=self._routing_context,
81+
entities=resolution.entities,
82+
entities_service=resolution.entities_service,
8283
resource_description=self._resource_description,
8384
base_system_prompt=self._base_system_prompt,
8485
)
@@ -98,44 +99,6 @@ async def __call__(self, user_query: str) -> str:
9899
return "Unable to generate an answer from the available data."
99100

100101

101-
async def _fetch_single_entity(sdk: Any, identifier: str) -> Entity | None:
102-
"""Fetch a single entity by identifier, returning None on failure."""
103-
try:
104-
entity = await sdk.entities.retrieve_async(identifier)
105-
logger.info("Fetched schema for entity '%s'", entity.display_name)
106-
return entity
107-
except Exception:
108-
logger.warning("Failed to fetch entity '%s'", identifier, exc_info=True)
109-
return None
110-
111-
112-
async def fetch_entity_schemas(entity_identifiers: list[str]) -> list[Entity]:
113-
"""Fetch entity metadata from Data Fabric concurrently."""
114-
from uipath.platform import UiPath
115-
116-
sdk = UiPath()
117-
results = await asyncio.gather(
118-
*[_fetch_single_entity(sdk, eid) for eid in entity_identifiers]
119-
)
120-
return [e for e in results if e is not None]
121-
122-
123-
def _build_routing_context(
124-
resource: AgentContextResourceConfig,
125-
) -> QueryRoutingOverrideContext:
126-
"""Build query routing context from entity set items.
127-
128-
Maps each entity to its folder so the backend resolves
129-
entities at folder level instead of tenant level.
130-
"""
131-
return QueryRoutingOverrideContext(
132-
entity_routings=[
133-
EntityRouting(entity_name=item.name, folder_id=item.folder_id)
134-
for item in (resource.entity_set or [])
135-
]
136-
)
137-
138-
139102
def create_datafabric_query_tool(
140103
resource: AgentContextResourceConfig,
141104
llm: BaseChatModel,
@@ -152,9 +115,12 @@ def create_datafabric_query_tool(
152115
Key ``base_system_prompt`` carries the outer agent's system prompt.
153116
"""
154117
config = agent_config or {}
118+
entity_set = [
119+
DataFabricEntityItem.model_validate(item.model_dump(by_alias=True))
120+
for item in (resource.entity_set or [])
121+
]
155122
handler = DataFabricTextQueryHandler(
156-
entity_identifiers=resource.datafabric_entity_identifiers,
157-
routing_context=_build_routing_context(resource),
123+
entity_set=entity_set,
158124
llm=llm,
159125
resource_description=resource.description or "",
160126
base_system_prompt=config.get(BASE_SYSTEM_PROMPT, ""),

uv.lock

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)