Skip to content

Commit 017ee41

Browse files
committed
feat: add context agent tools
1 parent 1540956 commit 017ee41

File tree

4 files changed

+156
-6
lines changed

4 files changed

+156
-6
lines changed

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ description = "Python SDK that enables developers to build and deploy LangGraph
55
readme = { file = "README.md", content-type = "text/markdown" }
66
requires-python = ">=3.11"
77
dependencies = [
8-
"uipath>=2.2.41, <2.3.0",
8+
"uipath>=2.2.43",
99
"langgraph>=1.0.0, <2.0.0",
1010
"langchain-core>=1.0.0, <2.0.0",
1111
"aiosqlite==0.21.0",
@@ -124,3 +124,4 @@ name = "testpypi"
124124
url = "https://test.pypi.org/simple/"
125125
publish-url = "https://test.pypi.org/legacy/"
126126
explicit = true
127+

src/uipath_langchain/agent/tools/__init__.py

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

33
from .context_tool import create_context_tool
4+
from .escalation_tool import create_escalation_tool
45
from .integration_tool import create_integration_tool
56
from .mcp_tool import create_mcp_tools
67
from .process_tool import create_process_tool
@@ -15,6 +16,7 @@
1516
"create_context_tool",
1617
"create_process_tool",
1718
"create_integration_tool",
19+
"create_escalation_tool",
1820
"create_mcp_tools",
1921
"UiPathToolNode",
2022
"ToolWrapperMixin",

src/uipath_langchain/agent/tools/context_tool.py

Lines changed: 148 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,24 @@
11
"""Context tool creation for semantic index retrieval."""
22

3+
import uuid
34
from typing import Any
45

56
from langchain_core.documents import Document
67
from langchain_core.tools import StructuredTool
8+
from langgraph.types import interrupt
79
from pydantic import BaseModel, Field
8-
from uipath.agent.models.agent import AgentContextResourceConfig
10+
from uipath.agent.models.agent import (
11+
AgentContextResourceConfig,
12+
AgentContextRetrievalMode,
13+
)
914
from uipath.eval.mocks import mockable
15+
from uipath.platform.common import CreateBatchTransform, CreateDeepRag
16+
from uipath.platform.context_grounding import (
17+
BatchTransformOutputColumn,
18+
BatchTransformResponse,
19+
CitationMode,
20+
DeepRagResponse,
21+
)
1022

1123
from uipath_langchain.retrievers import ContextGroundingRetriever
1224

@@ -16,6 +28,18 @@
1628

1729
def create_context_tool(resource: AgentContextResourceConfig) -> StructuredTool:
1830
tool_name = sanitize_tool_name(resource.name)
31+
retrieval_mode = resource.settings.retrieval_mode.lower()
32+
if retrieval_mode == AgentContextRetrievalMode.DEEP_RAG.value.lower():
33+
return handle_deep_rag(tool_name, resource)
34+
elif retrieval_mode == AgentContextRetrievalMode.BATCH_TRANSFORM.value.lower():
35+
return handle_batch_transform(tool_name, resource)
36+
else:
37+
return handle_sematic_search(tool_name, resource)
38+
39+
40+
def handle_sematic_search(
41+
tool_name: str, resource: AgentContextResourceConfig
42+
) -> StructuredTool:
1943
retriever = ContextGroundingRetriever(
2044
index_name=resource.index_name,
2145
folder_path=resource.folder_path,
@@ -52,3 +76,126 @@ async def context_tool_fn(query: str) -> dict[str, Any]:
5276
coroutine=context_tool_fn,
5377
output_type=output_model,
5478
)
79+
80+
81+
def handle_deep_rag(
82+
tool_name: str, resource: AgentContextResourceConfig
83+
) -> StructuredTool:
84+
ensure_valid_fields(resource)
85+
# needed for type checking
86+
assert resource.settings.query is not None
87+
assert resource.settings.query.value is not None
88+
89+
index_name = resource.index_name
90+
prompt = resource.settings.query.value
91+
if not resource.settings.citation_mode:
92+
raise ValueError("Citation mode is required for Deep RAG")
93+
citation_mode = CitationMode(resource.settings.citation_mode.value)
94+
95+
input_model = None
96+
output_model = DeepRagResponse
97+
98+
@mockable(
99+
name=resource.name,
100+
description=resource.description,
101+
input_schema=input_model,
102+
output_schema=output_model.model_json_schema(),
103+
example_calls=[], # Examples cannot be provided for context.
104+
)
105+
async def context_tool_fn() -> dict[str, Any]:
106+
# TODO: add glob pattern support
107+
return interrupt(
108+
CreateDeepRag(
109+
name=f"task-{uuid.uuid4()}",
110+
index_name=index_name,
111+
prompt=prompt,
112+
citation_mode=citation_mode,
113+
)
114+
)
115+
116+
return StructuredToolWithOutputType(
117+
name=tool_name,
118+
description=resource.description,
119+
args_schema=input_model,
120+
coroutine=context_tool_fn,
121+
output_type=output_model,
122+
)
123+
124+
125+
def handle_batch_transform(
126+
tool_name: str, resource: AgentContextResourceConfig
127+
) -> StructuredTool:
128+
ensure_valid_fields(resource)
129+
130+
# needed for type checking
131+
assert resource.settings.query is not None
132+
assert resource.settings.query.value is not None
133+
134+
index_name = resource.index_name
135+
prompt = resource.settings.query.value
136+
137+
index_folder_path = resource.folder_path
138+
if not resource.settings.web_search_grounding:
139+
raise ValueError("Web search grounding field is required for Batch Transform")
140+
enable_web_search_grounding = (
141+
resource.settings.web_search_grounding.value.lower() == "enabled"
142+
)
143+
144+
batch_transform_output_columns: list[BatchTransformOutputColumn] = []
145+
if (output_columns := resource.settings.output_columns) is None or not len(
146+
output_columns
147+
):
148+
raise ValueError("Batch transform output columns were not provided")
149+
150+
for column in output_columns:
151+
batch_transform_output_columns.append(
152+
BatchTransformOutputColumn(
153+
name=column.name,
154+
description=column.description,
155+
)
156+
)
157+
158+
class BatchTransformSchemaModel(BaseModel):
159+
destination_path: str = Field(
160+
...,
161+
description="The relative file path destination for the modified csv file",
162+
)
163+
164+
input_model = BatchTransformSchemaModel
165+
output_model = BatchTransformResponse
166+
167+
@mockable(
168+
name=resource.name,
169+
description=resource.description,
170+
input_schema=input_model.model_json_schema(),
171+
output_schema=output_model.model_json_schema(),
172+
example_calls=[], # Examples cannot be provided for context.
173+
)
174+
async def context_tool_fn(destination_path: str) -> dict[str, Any]:
175+
# TODO: storage_bucket_folder_path_prefix support
176+
return interrupt(
177+
CreateBatchTransform(
178+
name=f"task-{uuid.uuid4()}",
179+
index_name=index_name,
180+
prompt=prompt,
181+
destination_path=destination_path,
182+
index_folder_path=index_folder_path,
183+
enable_web_search_grounding=enable_web_search_grounding,
184+
output_columns=batch_transform_output_columns,
185+
)
186+
)
187+
188+
return StructuredToolWithOutputType(
189+
name=tool_name,
190+
description=resource.description,
191+
args_schema=input_model,
192+
coroutine=context_tool_fn,
193+
output_type=output_model,
194+
)
195+
196+
197+
def ensure_valid_fields(resource_config: AgentContextResourceConfig):
198+
if not resource_config.settings.query:
199+
raise ValueError("Query object is required")
200+
if not resource_config.settings.query.value:
201+
raise ValueError("Query prompt is required")

uv.lock

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

0 commit comments

Comments
 (0)