Skip to content

Commit 10cf420

Browse files
committed
fix: add chat hitl for agent framework
1 parent 33b5d67 commit 10cf420

16 files changed

Lines changed: 818 additions & 63 deletions

File tree

packages/uipath-agent-framework/pyproject.toml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
[project]
22
name = "uipath-agent-framework"
3-
version = "0.0.5"
3+
version = "0.0.6"
44
description = "Python SDK that enables developers to build and deploy Microsoft Agent Framework agents to the UiPath Cloud Platform"
55
readme = "README.md"
66
requires-python = ">=3.11"
77
dependencies = [
8-
"agent-framework-core>=1.0.0b260212",
9-
"agent-framework-orchestrations>=1.0.0b260212",
8+
"agent-framework-core>=1.0.0rc1",
9+
"agent-framework-orchestrations>=1.0.0b260219",
1010
"aiosqlite>=0.20.0",
1111
"openinference-instrumentation-agent-framework>=0.1.0",
1212
"uipath>=2.8.41, <2.9.0",
@@ -24,7 +24,7 @@ maintainers = [
2424
]
2525

2626
[project.optional-dependencies]
27-
anthropic = ["anthropic>=0.43.0", "agent-framework-anthropic>=1.0.0b260212"]
27+
anthropic = ["anthropic>=0.43.0", "agent-framework-anthropic>=1.0.0b260219"]
2828

2929
[project.entry-points."uipath.middlewares"]
3030
register = "uipath_agent_framework.middlewares:register_middleware"

packages/uipath-agent-framework/samples/concurrent/pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ requires-python = ">=3.11"
88
dependencies = [
99
"uipath",
1010
"uipath-agent-framework",
11-
"agent-framework-core>=1.0.0b260212",
12-
"agent-framework-orchestrations>=1.0.0b260212",
11+
"agent-framework-core>=1.0.0rc1",
12+
"agent-framework-orchestrations>=1.0.0b260219",
1313
]
1414

1515
[dependency-groups]

packages/uipath-agent-framework/samples/group-chat/pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ requires-python = ">=3.11"
88
dependencies = [
99
"uipath",
1010
"uipath-agent-framework",
11-
"agent-framework-core>=1.0.0b260212",
12-
"agent-framework-orchestrations>=1.0.0b260212",
11+
"agent-framework-core>=1.0.0rc1",
12+
"agent-framework-orchestrations>=1.0.0b260219",
1313
]
1414

1515
[dependency-groups]

packages/uipath-agent-framework/samples/handoff/pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ requires-python = ">=3.11"
88
dependencies = [
99
"uipath",
1010
"uipath-agent-framework",
11-
"agent-framework-core>=1.0.0b260212",
12-
"agent-framework-orchestrations>=1.0.0b260212",
11+
"agent-framework-core>=1.0.0rc1",
12+
"agent-framework-orchestrations>=1.0.0b260219",
1313
]
1414

1515
[dependency-groups]

packages/uipath-agent-framework/samples/hitl-workflow/README.md

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,31 @@
11
# HITL Workflow
22

3-
A customer support workflow with human-in-the-loop approval for sensitive operations. A triage agent routes requests to billing or returns specialists. Both `transfer_funds` and `issue_refund` tools require human approval before executing.
3+
A customer support workflow with human-in-the-loop approval for sensitive operations. A triage agent routes requests to specialists: billing handles fund transfers, returns handles refunds. The `transfer_funds`, `get_customer_order`, and `issue_refund` tools all require human approval before executing.
44

55
## Agent Graph
66

77
```mermaid
88
flowchart TB
99
__start__(__start__)
1010
triage(triage)
11+
orders_agent(orders_agent)
1112
billing_agent(billing_agent)
1213
returns_agent(returns_agent)
1314
__end__(__end__)
1415
__start__ --> |input|triage
16+
triage --> orders_agent
1517
triage --> billing_agent
1618
triage --> returns_agent
19+
orders_agent --> billing_agent
20+
orders_agent --> returns_agent
21+
orders_agent --> triage
22+
billing_agent --> orders_agent
1723
billing_agent --> returns_agent
1824
billing_agent --> triage
25+
returns_agent --> orders_agent
1926
returns_agent --> billing_agent
2027
returns_agent --> triage
28+
orders_agent --> |output|__end__
2129
billing_agent --> |output|__end__
2230
returns_agent --> |output|__end__
2331
```
@@ -32,8 +40,16 @@ uipath auth
3240

3341
## Run
3442

43+
Try a refund request (triggers `get_customer_order` + `issue_refund`, both require approval):
44+
45+
```
46+
uipath run agent '{"messages": [{"contentParts": [{"data": {"inline": "I need a refund for order #12345, the item was defective"}}], "role": "user"}]}'
47+
```
48+
49+
Or a fund transfer (triggers `transfer_funds`, requires approval):
50+
3551
```
36-
uipath run agent '{"messages": [{"contentParts": [{"data": {"inline": "I need a refund for order #12345"}}], "role": "user"}]}'
52+
uipath run agent '{"messages": [{"contentParts": [{"data": {"inline": "Transfer $500 from account ACC-001 to account ACC-002"}}], "role": "user"}]}'
3753
```
3854

3955
## Debug

packages/uipath-agent-framework/samples/hitl-workflow/main.py

Lines changed: 51 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,26 @@ def transfer_funds(from_account: str, to_account: str, amount: float) -> str:
1818
return f"Transferred ${amount:.2f} from {from_account} to {to_account}"
1919

2020

21+
@requires_approval
22+
def get_customer_order(order_id: str) -> str:
23+
"""Retrieve customer info and order details by order ID. Requires human approval.
24+
25+
Args:
26+
order_id: The order ID to look up
27+
28+
Returns:
29+
Customer and order information
30+
"""
31+
return (
32+
f"Order {order_id}:\n"
33+
f" Customer: Jane Doe (jane.doe@example.com)\n"
34+
f" Product: Wireless Headphones (SKU-4521)\n"
35+
f" Amount: $79.99\n"
36+
f" Status: Delivered\n"
37+
f" Date: 2026-02-15"
38+
)
39+
40+
2141
@requires_approval
2242
def issue_refund(order_id: str, amount: float, reason: str) -> str:
2343
"""Issue a refund for an order. Requires human approval.
@@ -39,20 +59,34 @@ def issue_refund(order_id: str, amount: float, reason: str) -> str:
3959
name="triage",
4060
description="Routes customer requests to the right specialist.",
4161
instructions=(
42-
"You are a customer support triage agent. Determine what the "
43-
"customer needs help with and hand off to the right agent:\n"
62+
"You are a customer support triage agent. "
63+
"Route the customer to the right agent immediately without asking questions:\n"
64+
"- Order lookups and customer info -> orders_agent\n"
4465
"- Billing issues (payments, transfers) -> billing_agent\n"
4566
"- Returns and refunds -> returns_agent\n"
67+
"Hand off on the first message. Do not ask clarifying questions."
68+
),
69+
)
70+
71+
orders = client.as_agent(
72+
name="orders_agent",
73+
description="Looks up customer info and order details.",
74+
instructions=(
75+
"You are an order lookup specialist. "
76+
"When a customer asks about an order, immediately call get_customer_order "
77+
"with the order ID they provided. Do not ask for additional information."
4678
),
79+
tools=[get_customer_order],
4780
)
4881

4982
billing = client.as_agent(
5083
name="billing_agent",
5184
description="Handles billing, payments, and fund transfers.",
5285
instructions=(
53-
"You are a billing specialist. Help customers with payments "
54-
"and transfers. Use the transfer_funds tool when needed — "
55-
"it will require human approval before executing."
86+
"You are a billing specialist. "
87+
"When a customer requests a payment or transfer, immediately call "
88+
"transfer_funds with the details provided. Do not ask for confirmation "
89+
"or additional information — the tool has built-in human approval."
5690
),
5791
tools=[transfer_funds],
5892
)
@@ -61,22 +95,26 @@ def issue_refund(order_id: str, amount: float, reason: str) -> str:
6195
name="returns_agent",
6296
description="Handles product returns and refund requests.",
6397
instructions=(
64-
"You are a returns specialist. Help customers process returns "
65-
"and issue refunds. Use the issue_refund tool — it will "
66-
"require human approval before executing."
98+
"You are a returns specialist. "
99+
"When a customer requests a refund, first call get_customer_order to look up "
100+
"the order details, then immediately call issue_refund with the order ID, "
101+
"the full order amount, and the reason the customer gave. "
102+
"Do not ask the customer for information you can look up. "
103+
"The tools have built-in human approval so just call them directly."
67104
),
68-
tools=[issue_refund],
105+
tools=[get_customer_order, issue_refund],
69106
)
70107

71108
workflow = (
72109
HandoffBuilder(
73110
name="customer_support",
74-
participants=[triage, billing, returns],
111+
participants=[triage, orders, billing, returns],
75112
)
76113
.with_start_agent(triage)
77-
.add_handoff(triage, [billing, returns])
78-
.add_handoff(billing, [returns, triage])
79-
.add_handoff(returns, [billing, triage])
114+
.add_handoff(triage, [orders, billing, returns])
115+
.add_handoff(orders, [billing, returns, triage])
116+
.add_handoff(billing, [orders, returns, triage])
117+
.add_handoff(returns, [orders, billing, triage])
80118
.build()
81119
)
82120

packages/uipath-agent-framework/samples/hitl-workflow/pyproject.toml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ requires-python = ">=3.11"
88
dependencies = [
99
"uipath",
1010
"uipath-agent-framework",
11-
"agent-framework-core>=1.0.0b260212",
11+
"agent-framework-core>=1.0.0rc1",
1212
]
1313

1414
[dependency-groups]
@@ -18,3 +18,7 @@ dev = [
1818

1919
[tool.uv]
2020
prerelease = "allow"
21+
22+
[tool.uv.sources]
23+
uipath-dev = { path = "../../../../../uipath-dev-python", editable = true }
24+
uipath-agent-framework = { path = "../../", editable = true }

packages/uipath-agent-framework/samples/quickstart-workflow/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ requires-python = ">=3.11"
88
dependencies = [
99
"uipath",
1010
"uipath-agent-framework",
11-
"agent-framework-core>=1.0.0b260212",
11+
"agent-framework-core>=1.0.0rc1",
1212
]
1313

1414
[dependency-groups]

packages/uipath-agent-framework/src/uipath_agent_framework/chat/hitl.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,18 @@ def transfer_funds(from_account: str, to_account: str, amount: float) -> str:
2222

2323

2424
@overload
25-
def requires_approval(func: Callable[..., Any]) -> FunctionTool[Any]: ...
25+
def requires_approval(func: Callable[..., Any]) -> FunctionTool: ...
2626

2727

2828
@overload
2929
def requires_approval(
3030
func: None = None,
31-
) -> Callable[[Callable[..., Any]], FunctionTool[Any]]: ...
31+
) -> Callable[[Callable[..., Any]], FunctionTool]: ...
3232

3333

3434
def requires_approval(
3535
func: Callable[..., Any] | None = None,
36-
) -> FunctionTool[Any] | Callable[[Callable[..., Any]], FunctionTool[Any]]:
36+
) -> FunctionTool | Callable[[Callable[..., Any]], FunctionTool]:
3737
"""Decorator that marks a tool function as requiring human approval.
3838
3939
When the agent calls a tool decorated with ``@requires_approval``,
@@ -61,7 +61,7 @@ def my_tool(arg: str) -> str: ...
6161
if func is not None:
6262
return tool(func, approval_mode="always_require")
6363

64-
def decorator(fn: Callable[..., Any]) -> FunctionTool[Any]:
64+
def decorator(fn: Callable[..., Any]) -> FunctionTool:
6565
return tool(fn, approval_mode="always_require")
6666

6767
return decorator

packages/uipath-agent-framework/src/uipath_agent_framework/chat/openai.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
from __future__ import annotations
99

1010
import logging
11-
from collections.abc import Sequence
1211
from typing import Any
1312

1413
import httpx
@@ -103,7 +102,7 @@ def __init__(self, model: str = "gpt-4o-mini", **kwargs: Any):
103102
**kwargs,
104103
)
105104

106-
def _prepare_tools_for_openai(self, tools: Sequence[Any]) -> dict[str, Any]:
105+
def _prepare_tools_for_openai(self, tools: Any) -> dict[str, Any]:
107106
"""Prepare tools for the OpenAI Chat Completions API.
108107
109108
Extends the base implementation to convert plain callables to

0 commit comments

Comments
 (0)