uipath-openai-agents 0.0.1__py3-none-any.whl → 0.0.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- uipath_openai_agents/__init__.py +24 -3
- uipath_openai_agents/_cli/_templates/AGENTS.md.template +1 -1
- uipath_openai_agents/_cli/_templates/main.py.template +13 -7
- uipath_openai_agents/_cli/cli_new.py +2 -6
- uipath_openai_agents/chat/__init__.py +30 -3
- uipath_openai_agents/chat/supported_models.py +42 -60
- uipath_openai_agents/runtime/__init__.py +34 -8
- uipath_openai_agents/runtime/_serialize.py +4 -4
- uipath_openai_agents/runtime/agent.py +0 -17
- uipath_openai_agents/runtime/factory.py +0 -120
- uipath_openai_agents/runtime/runtime.py +21 -205
- uipath_openai_agents/runtime/schema.py +11 -112
- uipath_openai_agents-0.0.2.dist-info/METADATA +146 -0
- uipath_openai_agents-0.0.2.dist-info/RECORD +23 -0
- uipath_openai_agents/runtime/_sqlite.py +0 -190
- uipath_openai_agents/runtime/_telemetry.py +0 -32
- uipath_openai_agents/runtime/storage.py +0 -357
- uipath_openai_agents-0.0.1.dist-info/METADATA +0 -53
- uipath_openai_agents-0.0.1.dist-info/RECORD +0 -26
- {uipath_openai_agents-0.0.1.dist-info → uipath_openai_agents-0.0.2.dist-info}/WHEEL +0 -0
- {uipath_openai_agents-0.0.1.dist-info → uipath_openai_agents-0.0.2.dist-info}/entry_points.txt +0 -0
|
@@ -1,15 +1,10 @@
|
|
|
1
1
|
"""Runtime class for executing OpenAI Agents within the UiPath framework."""
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
|
-
import os
|
|
5
4
|
from typing import Any, AsyncGenerator
|
|
6
5
|
from uuid import uuid4
|
|
7
6
|
|
|
8
|
-
from agents import
|
|
9
|
-
Agent,
|
|
10
|
-
Runner,
|
|
11
|
-
SQLiteSession,
|
|
12
|
-
)
|
|
7
|
+
from agents import Agent, Runner
|
|
13
8
|
from uipath.runtime import (
|
|
14
9
|
UiPathExecuteOptions,
|
|
15
10
|
UiPathRuntimeResult,
|
|
@@ -27,7 +22,6 @@ from uipath.runtime.schema import UiPathRuntimeSchema
|
|
|
27
22
|
from ._serialize import serialize_output
|
|
28
23
|
from .errors import UiPathOpenAIAgentsErrorCode, UiPathOpenAIAgentsRuntimeError
|
|
29
24
|
from .schema import get_agent_schema, get_entrypoints_schema
|
|
30
|
-
from .storage import SqliteAgentStorage
|
|
31
25
|
|
|
32
26
|
|
|
33
27
|
class UiPathOpenAIAgentRuntime:
|
|
@@ -40,9 +34,6 @@ class UiPathOpenAIAgentRuntime:
|
|
|
40
34
|
agent: Agent,
|
|
41
35
|
runtime_id: str | None = None,
|
|
42
36
|
entrypoint: str | None = None,
|
|
43
|
-
storage_path: str | None = None,
|
|
44
|
-
loaded_object: Any | None = None,
|
|
45
|
-
storage: SqliteAgentStorage | None = None,
|
|
46
37
|
):
|
|
47
38
|
"""
|
|
48
39
|
Initialize the runtime.
|
|
@@ -51,86 +42,10 @@ class UiPathOpenAIAgentRuntime:
|
|
|
51
42
|
agent: The OpenAI Agent to execute
|
|
52
43
|
runtime_id: Unique identifier for this runtime instance
|
|
53
44
|
entrypoint: Optional entrypoint name (for schema generation)
|
|
54
|
-
storage_path: Path to SQLite database for session persistence
|
|
55
|
-
loaded_object: Original loaded object (for schema inference)
|
|
56
|
-
storage: Optional storage instance for state persistence
|
|
57
45
|
"""
|
|
58
46
|
self.agent: Agent = agent
|
|
59
47
|
self.runtime_id: str = runtime_id or "default"
|
|
60
48
|
self.entrypoint: str | None = entrypoint
|
|
61
|
-
self.storage_path: str | None = storage_path
|
|
62
|
-
self.loaded_object: Any | None = loaded_object
|
|
63
|
-
self.storage: SqliteAgentStorage | None = storage
|
|
64
|
-
|
|
65
|
-
# Configure OpenAI Agents SDK to use Responses API
|
|
66
|
-
# UiPath supports both APIs via X-UiPath-LlmGateway-ApiFlavor header
|
|
67
|
-
# Using responses API for enhanced agent capabilities (conversation state, reasoning)
|
|
68
|
-
from agents import set_default_openai_api
|
|
69
|
-
|
|
70
|
-
set_default_openai_api("responses")
|
|
71
|
-
|
|
72
|
-
# Inject UiPath OpenAI client if UiPath credentials are available
|
|
73
|
-
self._setup_uipath_client()
|
|
74
|
-
|
|
75
|
-
def _setup_uipath_client(self) -> None:
|
|
76
|
-
"""Set up UiPath OpenAI client for agents to use UiPath gateway.
|
|
77
|
-
|
|
78
|
-
This injects the UiPath OpenAI client into the OpenAI Agents SDK
|
|
79
|
-
so all agents use the UiPath LLM Gateway instead of direct OpenAI.
|
|
80
|
-
|
|
81
|
-
The model is automatically extracted from the agent's `model` parameter.
|
|
82
|
-
If not specified in Agent(), the SDK uses agents.models.get_default_model().
|
|
83
|
-
|
|
84
|
-
If UiPath credentials are not available, falls back to default OpenAI client.
|
|
85
|
-
"""
|
|
86
|
-
try:
|
|
87
|
-
# Import here to avoid circular dependency
|
|
88
|
-
from uipath_openai_agents.chat import UiPathChatOpenAI
|
|
89
|
-
|
|
90
|
-
# Check if UiPath credentials are available
|
|
91
|
-
org_id = os.getenv("UIPATH_ORGANIZATION_ID")
|
|
92
|
-
tenant_id = os.getenv("UIPATH_TENANT_ID")
|
|
93
|
-
token = os.getenv("UIPATH_ACCESS_TOKEN")
|
|
94
|
-
uipath_url = os.getenv("UIPATH_URL")
|
|
95
|
-
|
|
96
|
-
if org_id and tenant_id and token and uipath_url:
|
|
97
|
-
# Extract model from agent definition
|
|
98
|
-
from agents.models import get_default_model
|
|
99
|
-
|
|
100
|
-
from uipath_openai_agents.chat.supported_models import OpenAIModels
|
|
101
|
-
|
|
102
|
-
if hasattr(self.agent, "model") and self.agent.model:
|
|
103
|
-
model_name = str(self.agent.model)
|
|
104
|
-
else:
|
|
105
|
-
model_name = get_default_model()
|
|
106
|
-
|
|
107
|
-
# Normalize generic model names to UiPath-specific versions
|
|
108
|
-
model_name = OpenAIModels.normalize_model_name(model_name)
|
|
109
|
-
|
|
110
|
-
# Update agent's model to normalized version so SDK sends correct model in body
|
|
111
|
-
self.agent.model = model_name
|
|
112
|
-
|
|
113
|
-
# Create UiPath OpenAI client
|
|
114
|
-
uipath_client = UiPathChatOpenAI(
|
|
115
|
-
token=token,
|
|
116
|
-
org_id=org_id,
|
|
117
|
-
tenant_id=tenant_id,
|
|
118
|
-
model_name=model_name,
|
|
119
|
-
)
|
|
120
|
-
|
|
121
|
-
# Inject into OpenAI Agents SDK
|
|
122
|
-
# This makes all agents use UiPath gateway
|
|
123
|
-
from agents.models import _openai_shared
|
|
124
|
-
|
|
125
|
-
_openai_shared.set_default_openai_client(uipath_client.async_client)
|
|
126
|
-
|
|
127
|
-
except ImportError:
|
|
128
|
-
# UiPath chat module not available, skip injection
|
|
129
|
-
pass
|
|
130
|
-
except Exception:
|
|
131
|
-
# If injection fails, fall back to default OpenAI client
|
|
132
|
-
# Agents will use OPENAI_API_KEY if set
|
|
133
|
-
pass
|
|
134
49
|
|
|
135
50
|
async def execute(
|
|
136
51
|
self,
|
|
@@ -207,54 +122,27 @@ class UiPathOpenAIAgentRuntime:
|
|
|
207
122
|
Runtime events if stream_events=True, then final result
|
|
208
123
|
"""
|
|
209
124
|
agent_input = self._prepare_agent_input(input)
|
|
210
|
-
is_resuming = bool(options and options.resume)
|
|
211
|
-
|
|
212
|
-
# Create session for state persistence (local to this run)
|
|
213
|
-
# SQLiteSession automatically loads existing data from the database when created
|
|
214
|
-
session: SQLiteSession | None = None
|
|
215
|
-
if self.storage_path:
|
|
216
|
-
session = SQLiteSession(self.runtime_id, self.storage_path)
|
|
217
125
|
|
|
218
126
|
# Run the agent with streaming if events requested
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
)
|
|
233
|
-
yield self._create_success_result(result.final_output)
|
|
234
|
-
|
|
235
|
-
except Exception:
|
|
236
|
-
# Clean up session on error
|
|
237
|
-
if session and self.storage_path and not is_resuming:
|
|
238
|
-
# Delete incomplete session
|
|
239
|
-
try:
|
|
240
|
-
import os
|
|
241
|
-
|
|
242
|
-
if os.path.exists(self.storage_path):
|
|
243
|
-
os.remove(self.storage_path)
|
|
244
|
-
except Exception:
|
|
245
|
-
pass # Best effort cleanup
|
|
246
|
-
raise
|
|
247
|
-
finally:
|
|
248
|
-
# Always close session after run completes with proper WAL checkpoint
|
|
249
|
-
if session:
|
|
250
|
-
self._close_session_with_checkpoint(session)
|
|
127
|
+
if stream_events:
|
|
128
|
+
# Use streaming for events
|
|
129
|
+
async for event_or_result in self._run_agent_streamed(
|
|
130
|
+
agent_input, options, stream_events
|
|
131
|
+
):
|
|
132
|
+
yield event_or_result
|
|
133
|
+
else:
|
|
134
|
+
# Use non-streaming for simple execution
|
|
135
|
+
result = await Runner.run(
|
|
136
|
+
starting_agent=self.agent,
|
|
137
|
+
input=agent_input,
|
|
138
|
+
)
|
|
139
|
+
yield self._create_success_result(result.final_output)
|
|
251
140
|
|
|
252
141
|
async def _run_agent_streamed(
|
|
253
142
|
self,
|
|
254
143
|
agent_input: str | list[Any],
|
|
255
144
|
options: UiPathExecuteOptions | UiPathStreamOptions | None,
|
|
256
145
|
stream_events: bool,
|
|
257
|
-
session: SQLiteSession | None,
|
|
258
146
|
) -> AsyncGenerator[UiPathRuntimeEvent | UiPathRuntimeResult, None]:
|
|
259
147
|
"""
|
|
260
148
|
Run agent using streaming API to enable event streaming.
|
|
@@ -272,7 +160,6 @@ class UiPathOpenAIAgentRuntime:
|
|
|
272
160
|
result = Runner.run_streamed(
|
|
273
161
|
starting_agent=self.agent,
|
|
274
162
|
input=agent_input,
|
|
275
|
-
session=session,
|
|
276
163
|
)
|
|
277
164
|
|
|
278
165
|
# Stream events from the agent
|
|
@@ -335,49 +222,17 @@ class UiPathOpenAIAgentRuntime:
|
|
|
335
222
|
"""
|
|
336
223
|
Prepare agent input from UiPath input dictionary.
|
|
337
224
|
|
|
338
|
-
Supports two input formats:
|
|
339
|
-
- {"message": "text"} → returns string for Runner.run()
|
|
340
|
-
- {"messages": [...]} → returns list of message dicts for Runner.run()
|
|
341
|
-
|
|
342
|
-
Note: When using sessions, string input is preferred as it doesn't
|
|
343
|
-
require a session_input_callback.
|
|
344
|
-
|
|
345
|
-
Args:
|
|
346
|
-
input: Input dictionary from UiPath
|
|
347
|
-
|
|
348
|
-
Returns:
|
|
349
|
-
String or list for Runner.run() input parameter
|
|
350
|
-
|
|
351
|
-
Raises:
|
|
352
|
-
ValueError: If input doesn't contain "message" or "messages" field
|
|
353
225
|
"""
|
|
354
226
|
if not input:
|
|
355
|
-
|
|
356
|
-
"Input is required. Provide either 'message' (string) or 'messages' (list of message dicts)"
|
|
357
|
-
)
|
|
227
|
+
return ""
|
|
358
228
|
|
|
359
|
-
|
|
360
|
-
if "messages" in input:
|
|
361
|
-
messages = input["messages"]
|
|
362
|
-
# Ensure it's a list
|
|
363
|
-
if isinstance(messages, list):
|
|
364
|
-
return messages
|
|
365
|
-
else:
|
|
366
|
-
raise ValueError(
|
|
367
|
-
"'messages' field must be a list of message dictionaries"
|
|
368
|
-
)
|
|
229
|
+
messages = input.get("messages", "")
|
|
369
230
|
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
message = input["message"]
|
|
373
|
-
# Return as string (OpenAI Agents SDK handles string → message conversion)
|
|
374
|
-
return str(message)
|
|
231
|
+
if isinstance(messages, (str, list)):
|
|
232
|
+
return messages
|
|
375
233
|
|
|
376
|
-
#
|
|
377
|
-
|
|
378
|
-
"Input must contain either 'message' (string) or 'messages' (list of message dicts). "
|
|
379
|
-
f"Got keys: {list(input.keys())}"
|
|
380
|
-
)
|
|
234
|
+
# Fallback to empty string for unexpected types
|
|
235
|
+
return ""
|
|
381
236
|
|
|
382
237
|
def _serialize_message(self, message: Any) -> dict[str, Any]:
|
|
383
238
|
"""
|
|
@@ -477,7 +332,7 @@ class UiPathOpenAIAgentRuntime:
|
|
|
477
332
|
Returns:
|
|
478
333
|
UiPathRuntimeSchema with input/output schemas and graph structure
|
|
479
334
|
"""
|
|
480
|
-
entrypoints_schema = get_entrypoints_schema(self.agent
|
|
335
|
+
entrypoints_schema = get_entrypoints_schema(self.agent)
|
|
481
336
|
|
|
482
337
|
return UiPathRuntimeSchema(
|
|
483
338
|
filePath=self.entrypoint,
|
|
@@ -488,45 +343,6 @@ class UiPathOpenAIAgentRuntime:
|
|
|
488
343
|
graph=get_agent_schema(self.agent),
|
|
489
344
|
)
|
|
490
345
|
|
|
491
|
-
def _close_session_with_checkpoint(self, session: SQLiteSession) -> None:
|
|
492
|
-
"""Close SQLite session with WAL checkpoint to release file locks.
|
|
493
|
-
|
|
494
|
-
OpenAI SDK uses sync sqlite3 which doesn't release file locks on Windows
|
|
495
|
-
without explicit WAL checkpoint. This is especially important for cleanup.
|
|
496
|
-
|
|
497
|
-
Args:
|
|
498
|
-
session: The SQLiteSession to close
|
|
499
|
-
"""
|
|
500
|
-
try:
|
|
501
|
-
# Get the underlying connection
|
|
502
|
-
conn = session._get_connection()
|
|
503
|
-
|
|
504
|
-
# Commit any pending transactions
|
|
505
|
-
try:
|
|
506
|
-
conn.commit()
|
|
507
|
-
except Exception:
|
|
508
|
-
pass # Best effort
|
|
509
|
-
|
|
510
|
-
# Force WAL checkpoint to release shared memory files
|
|
511
|
-
# This is especially important on Windows
|
|
512
|
-
try:
|
|
513
|
-
conn.execute("PRAGMA wal_checkpoint(TRUNCATE)")
|
|
514
|
-
conn.commit()
|
|
515
|
-
except Exception:
|
|
516
|
-
pass # Best effort
|
|
517
|
-
|
|
518
|
-
except Exception:
|
|
519
|
-
pass # Best effort cleanup
|
|
520
|
-
|
|
521
|
-
finally:
|
|
522
|
-
# Always call the session's close method
|
|
523
|
-
try:
|
|
524
|
-
session.close()
|
|
525
|
-
except Exception:
|
|
526
|
-
pass # Best effort
|
|
527
|
-
|
|
528
346
|
async def dispose(self) -> None:
|
|
529
347
|
"""Cleanup runtime resources."""
|
|
530
|
-
# Sessions are closed immediately after each run in _run_agent()
|
|
531
|
-
# Storage is shared across runtimes and managed by the factory
|
|
532
348
|
pass
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""Schema extraction utilities for OpenAI Agents."""
|
|
2
2
|
|
|
3
3
|
import inspect
|
|
4
|
-
from typing import Any, get_args, get_origin
|
|
4
|
+
from typing import Any, get_args, get_origin
|
|
5
5
|
|
|
6
6
|
from agents import Agent
|
|
7
7
|
from pydantic import BaseModel, TypeAdapter
|
|
@@ -41,106 +41,14 @@ def _is_pydantic_model(type_hint: Any) -> bool:
|
|
|
41
41
|
return False
|
|
42
42
|
|
|
43
43
|
|
|
44
|
-
def
|
|
45
|
-
"""
|
|
46
|
-
Extract input/output schemas from a callable's type annotations.
|
|
47
|
-
|
|
48
|
-
Args:
|
|
49
|
-
callable_obj: A callable object (function, async function, etc.)
|
|
50
|
-
|
|
51
|
-
Returns:
|
|
52
|
-
Dictionary with input and output schemas if type hints are found,
|
|
53
|
-
None otherwise
|
|
54
|
-
"""
|
|
55
|
-
if not callable(callable_obj):
|
|
56
|
-
return None
|
|
57
|
-
|
|
58
|
-
try:
|
|
59
|
-
# Get type hints from the callable
|
|
60
|
-
type_hints = get_type_hints(callable_obj)
|
|
61
|
-
|
|
62
|
-
if not type_hints:
|
|
63
|
-
return None
|
|
64
|
-
|
|
65
|
-
# Get function signature to identify parameters
|
|
66
|
-
sig = inspect.signature(callable_obj)
|
|
67
|
-
params = list(sig.parameters.values())
|
|
68
|
-
|
|
69
|
-
# Find the first parameter (usually the input)
|
|
70
|
-
input_type = None
|
|
71
|
-
|
|
72
|
-
for param in params:
|
|
73
|
-
if param.name in ("self", "cls"):
|
|
74
|
-
continue
|
|
75
|
-
if param.name in type_hints:
|
|
76
|
-
input_type = type_hints[param.name]
|
|
77
|
-
break
|
|
78
|
-
|
|
79
|
-
# Get return type
|
|
80
|
-
return_type = type_hints.get("return")
|
|
81
|
-
|
|
82
|
-
schema: dict[str, Any] = {
|
|
83
|
-
"input": {"type": "object", "properties": {}, "required": []},
|
|
84
|
-
"output": {"type": "object", "properties": {}, "required": []},
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
# Extract input schema from Pydantic model
|
|
88
|
-
if input_type and _is_pydantic_model(input_type):
|
|
89
|
-
adapter = TypeAdapter(input_type)
|
|
90
|
-
input_schema = adapter.json_schema()
|
|
91
|
-
unpacked_input = _resolve_refs(input_schema)
|
|
92
|
-
|
|
93
|
-
schema["input"]["properties"] = _process_nullable_types(
|
|
94
|
-
unpacked_input.get("properties", {})
|
|
95
|
-
)
|
|
96
|
-
schema["input"]["required"] = unpacked_input.get("required", [])
|
|
97
|
-
|
|
98
|
-
# Add title and description if available
|
|
99
|
-
if "title" in unpacked_input:
|
|
100
|
-
schema["input"]["title"] = unpacked_input["title"]
|
|
101
|
-
if "description" in unpacked_input:
|
|
102
|
-
schema["input"]["description"] = unpacked_input["description"]
|
|
103
|
-
|
|
104
|
-
# Extract output schema from Pydantic model
|
|
105
|
-
if return_type and _is_pydantic_model(return_type):
|
|
106
|
-
adapter = TypeAdapter(return_type)
|
|
107
|
-
output_schema = adapter.json_schema()
|
|
108
|
-
unpacked_output = _resolve_refs(output_schema)
|
|
109
|
-
|
|
110
|
-
schema["output"]["properties"] = _process_nullable_types(
|
|
111
|
-
unpacked_output.get("properties", {})
|
|
112
|
-
)
|
|
113
|
-
schema["output"]["required"] = unpacked_output.get("required", [])
|
|
114
|
-
|
|
115
|
-
# Add title and description if available
|
|
116
|
-
if "title" in unpacked_output:
|
|
117
|
-
schema["output"]["title"] = unpacked_output["title"]
|
|
118
|
-
if "description" in unpacked_output:
|
|
119
|
-
schema["output"]["description"] = unpacked_output["description"]
|
|
120
|
-
|
|
121
|
-
# Only return schema if we found at least one Pydantic model
|
|
122
|
-
if schema["input"]["properties"] or schema["output"]["properties"]:
|
|
123
|
-
return schema
|
|
124
|
-
|
|
125
|
-
except Exception:
|
|
126
|
-
# If schema extraction fails, return None to fall back to default
|
|
127
|
-
pass
|
|
128
|
-
|
|
129
|
-
return None
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
def get_entrypoints_schema(
|
|
133
|
-
agent: Agent, loaded_object: Any | None = None
|
|
134
|
-
) -> dict[str, Any]:
|
|
44
|
+
def get_entrypoints_schema(agent: Agent) -> dict[str, Any]:
|
|
135
45
|
"""
|
|
136
46
|
Extract input/output schema from an OpenAI Agent.
|
|
137
47
|
|
|
138
|
-
|
|
139
|
-
with optional fallback to wrapper function type hints (UiPath pattern).
|
|
48
|
+
Uses the agent's native output_type attribute for schema extraction.
|
|
140
49
|
|
|
141
50
|
Args:
|
|
142
51
|
agent: An OpenAI Agent instance
|
|
143
|
-
loaded_object: Optional original loaded object (function/callable) with type annotations
|
|
144
52
|
|
|
145
53
|
Returns:
|
|
146
54
|
Dictionary with input and output schemas
|
|
@@ -155,7 +63,7 @@ def get_entrypoints_schema(
|
|
|
155
63
|
schema["input"] = {
|
|
156
64
|
"type": "object",
|
|
157
65
|
"properties": {
|
|
158
|
-
"
|
|
66
|
+
"messages": {
|
|
159
67
|
"anyOf": [
|
|
160
68
|
{"type": "string"},
|
|
161
69
|
{
|
|
@@ -163,26 +71,26 @@ def get_entrypoints_schema(
|
|
|
163
71
|
"items": {"type": "object"},
|
|
164
72
|
},
|
|
165
73
|
],
|
|
166
|
-
"title": "
|
|
167
|
-
"description": "User
|
|
74
|
+
"title": "Messages",
|
|
75
|
+
"description": "User messages to send to the agent",
|
|
168
76
|
}
|
|
169
77
|
},
|
|
170
|
-
"required": ["
|
|
78
|
+
"required": ["messages"],
|
|
171
79
|
}
|
|
172
80
|
|
|
173
|
-
# Extract output schema -
|
|
81
|
+
# Extract output schema - Agent's output_type (native OpenAI Agents pattern)
|
|
174
82
|
output_type = getattr(agent, "output_type", None)
|
|
175
83
|
output_extracted = False
|
|
176
84
|
|
|
177
85
|
# Unwrap AgentOutputSchema if present (OpenAI Agents SDK wrapper)
|
|
178
|
-
#
|
|
86
|
+
# AgentOutputSchema wraps the actual Pydantic model in an 'output_type' attribute
|
|
179
87
|
if (
|
|
180
88
|
output_type is not None
|
|
181
|
-
and hasattr(output_type, "
|
|
89
|
+
and hasattr(output_type, "output_type")
|
|
182
90
|
and not isinstance(output_type, type)
|
|
183
91
|
):
|
|
184
92
|
# This is an AgentOutputSchema wrapper instance, extract the actual model
|
|
185
|
-
output_type = output_type.
|
|
93
|
+
output_type = output_type.output_type
|
|
186
94
|
|
|
187
95
|
if output_type is not None and _is_pydantic_model(output_type):
|
|
188
96
|
try:
|
|
@@ -207,15 +115,6 @@ def get_entrypoints_schema(
|
|
|
207
115
|
# Continue to fallback if extraction fails
|
|
208
116
|
pass
|
|
209
117
|
|
|
210
|
-
# Extract output schema - PRIORITY 2: Wrapper function type hints (UiPath pattern)
|
|
211
|
-
# This allows UiPath-specific patterns where agents are wrapped in typed functions
|
|
212
|
-
if not output_extracted and loaded_object is not None:
|
|
213
|
-
wrapper_schema = _extract_schema_from_callable(loaded_object)
|
|
214
|
-
if wrapper_schema is not None:
|
|
215
|
-
# Use the wrapper's output schema, but keep the default input (messages)
|
|
216
|
-
schema["output"] = wrapper_schema["output"]
|
|
217
|
-
output_extracted = True
|
|
218
|
-
|
|
219
118
|
# Fallback: Default output schema for agents without explicit output_type
|
|
220
119
|
if not output_extracted:
|
|
221
120
|
schema["output"] = {
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: uipath-openai-agents
|
|
3
|
+
Version: 0.0.2
|
|
4
|
+
Summary: UiPath OpenAI Agents SDK
|
|
5
|
+
Project-URL: Homepage, https://uipath.com
|
|
6
|
+
Project-URL: Repository, https://github.com/UiPath/uipath-llamaindex-python
|
|
7
|
+
Maintainer-email: Marius Cosareanu <marius.cosareanu@uipath.com>, Cristian Pufu <cristian.pufu@uipath.com>
|
|
8
|
+
Classifier: Intended Audience :: Developers
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
12
|
+
Classifier: Topic :: Software Development :: Build Tools
|
|
13
|
+
Requires-Python: >=3.11
|
|
14
|
+
Requires-Dist: aiosqlite>=0.20.0
|
|
15
|
+
Requires-Dist: openai-agents>=0.6.5
|
|
16
|
+
Requires-Dist: openai>=1.0.0
|
|
17
|
+
Requires-Dist: openinference-instrumentation-openai-agents>=1.4.0
|
|
18
|
+
Requires-Dist: uipath-runtime<0.6.0,>=0.5.0
|
|
19
|
+
Requires-Dist: uipath<2.6.0,>=2.5.0
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
|
|
22
|
+
# UiPath OpenAI Agents Python SDK
|
|
23
|
+
|
|
24
|
+
[](https://pypi.org/project/uipath-openai-agents/)
|
|
25
|
+
[](https://pypi.org/project/uipath-openai-agents/)
|
|
26
|
+
[](https://pypi.org/project/uipath-openai-agents/)
|
|
27
|
+
|
|
28
|
+
A Python SDK that enables developers to build and deploy OpenAI Agents to the UiPath Cloud Platform. It provides programmatic interaction with UiPath Cloud Platform services.
|
|
29
|
+
|
|
30
|
+
This package is an extension to the [UiPath Python SDK](https://github.com/UiPath/uipath-python) and implements the [UiPath Runtime Protocol](https://github.com/UiPath/uipath-runtime-python).
|
|
31
|
+
|
|
32
|
+
Check out these [sample projects](https://github.com/UiPath/uipath-integrations-python/tree/main/packages/uipath-openai-agents/samples) to see the SDK in action.
|
|
33
|
+
|
|
34
|
+
## Requirements
|
|
35
|
+
|
|
36
|
+
- Python 3.11 or higher
|
|
37
|
+
- UiPath Automation Cloud account
|
|
38
|
+
|
|
39
|
+
## Installation
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
pip install uipath-openai-agents
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
using `uv`:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
uv add uipath-openai-agents
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Configuration
|
|
52
|
+
|
|
53
|
+
### Environment Variables
|
|
54
|
+
|
|
55
|
+
Create a `.env` file in your project root with the following variables:
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
UIPATH_URL=https://cloud.uipath.com/ACCOUNT_NAME/TENANT_NAME
|
|
59
|
+
UIPATH_ACCESS_TOKEN=YOUR_TOKEN_HERE
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Command Line Interface (CLI)
|
|
63
|
+
|
|
64
|
+
The SDK provides a command-line interface for creating, packaging, and deploying OpenAI Agents:
|
|
65
|
+
|
|
66
|
+
### Authentication
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
uipath auth
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
This command opens a browser for authentication and creates/updates your `.env` file with the proper credentials.
|
|
73
|
+
|
|
74
|
+
### Initialize a Project
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
uipath init
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Running `uipath init` will process the agent definitions in the `openai_agents.json` file and create the corresponding `entry-points.json` file needed for deployment.
|
|
81
|
+
|
|
82
|
+
For more details on the configuration format, see the [UiPath configuration specifications](https://github.com/UiPath/uipath-python/blob/main/specs/README.md).
|
|
83
|
+
|
|
84
|
+
### Debug a Project
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
uipath run AGENT [INPUT]
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Executes the agent with the provided JSON input arguments.
|
|
91
|
+
|
|
92
|
+
### Package a Project
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
uipath pack
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Packages your project into a `.nupkg` file that can be deployed to UiPath.
|
|
99
|
+
|
|
100
|
+
**Note:** Your `pyproject.toml` must include:
|
|
101
|
+
|
|
102
|
+
- A description field (avoid characters: &, <, >, ", ', ;)
|
|
103
|
+
- Author information
|
|
104
|
+
|
|
105
|
+
Example:
|
|
106
|
+
|
|
107
|
+
```toml
|
|
108
|
+
description = "Your package description"
|
|
109
|
+
authors = [{name = "Your Name", email = "your.email@example.com"}]
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Publish a Package
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
uipath publish
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Publishes the most recently created package to your UiPath Orchestrator.
|
|
119
|
+
|
|
120
|
+
## Project Structure
|
|
121
|
+
|
|
122
|
+
To properly use the CLI for packaging and publishing, your project should include:
|
|
123
|
+
|
|
124
|
+
- A `pyproject.toml` file with project metadata
|
|
125
|
+
- A `openai_agents.json` file with your agent definitions (e.g., `"agents": {"agent": "main.py:agent"}`)
|
|
126
|
+
- A `entry-points.json` file (generated by `uipath init`)
|
|
127
|
+
- A `bindings.json` file (generated by `uipath init`) to configure resource overrides
|
|
128
|
+
- Any Python files needed for your automation
|
|
129
|
+
|
|
130
|
+
## Development
|
|
131
|
+
|
|
132
|
+
### Developer Tools
|
|
133
|
+
|
|
134
|
+
Check out [uipath-dev](https://github.com/uipath/uipath-dev-python) - an interactive terminal application for building, testing, and debugging UiPath Python runtimes, agents, and automation scripts.
|
|
135
|
+
|
|
136
|
+
### Setting Up a Development Environment
|
|
137
|
+
|
|
138
|
+
Please read our [contribution guidelines](https://github.com/UiPath/uipath-integrations-python/packages/uipath-openai-agents/blob/main/CONTRIBUTING.md) before submitting a pull request.
|
|
139
|
+
|
|
140
|
+
### Special Thanks
|
|
141
|
+
|
|
142
|
+
A huge thank-you to the open-source community and the maintainers of the libraries that make this project possible:
|
|
143
|
+
|
|
144
|
+
- [OpenAI](https://github.com/openai/openai-python) for providing a powerful framework for building AI agents.
|
|
145
|
+
- [OpenInference](https://github.com/Arize-ai/openinference) for observability and instrumentation support.
|
|
146
|
+
- [Pydantic](https://github.com/pydantic/pydantic) for reliable, typed configuration and validation.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
uipath_openai_agents/__init__.py,sha256=vCe5Vtfzg-19KYbm7vHVCH2fThuQPNvAPYez-7lZrrQ,794
|
|
2
|
+
uipath_openai_agents/middlewares.py,sha256=TMZAwdBh4gUMfgUZPhhxVDWf3pl-GBaeLlmCtipa-WM,299
|
|
3
|
+
uipath_openai_agents/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
uipath_openai_agents/_cli/__init__.py,sha256=juqd9PbXs4yg45zMJ7BHAOPQjb7sgEbWE9InBtGZhfo,24
|
|
5
|
+
uipath_openai_agents/_cli/cli_new.py,sha256=uWyxEh5CGKsKYbS9WQrp2cGTA90cGKUG_ijrV-Z71YQ,2794
|
|
6
|
+
uipath_openai_agents/_cli/_templates/AGENTS.md.template,sha256=9byz_03hXpD3EcUdXk9QgXjAKG-S-3z-sYGDWORBoic,1293
|
|
7
|
+
uipath_openai_agents/_cli/_templates/main.py.template,sha256=6YQ4PWMNt7ErVBMw28KGxcc87x040DmJYK5ztdzWcIM,1002
|
|
8
|
+
uipath_openai_agents/_cli/_templates/openai_agents.json.template,sha256=MH1nK-wZ-GMfFmCW5-pD8zUNFaEmlQUfZKiNXDqUgGM,51
|
|
9
|
+
uipath_openai_agents/chat/__init__.py,sha256=0snFcSmeuhI9F7IV4LZGfdJ265XMD2Wo8uq8tBbkmFI,855
|
|
10
|
+
uipath_openai_agents/chat/openai.py,sha256=KjbDKS_tUKYjuvjUYbouSsoJsOmzbtdHUzuDarDpFYM,8640
|
|
11
|
+
uipath_openai_agents/chat/supported_models.py,sha256=Y3DtpulywaKZ8_BIA1xxfStLPSoVsyzR2zufUJaHkrM,1837
|
|
12
|
+
uipath_openai_agents/runtime/__init__.py,sha256=lF58N6HDei6ntF34ke14hmvTSB-VE96TObLPNLem8oA,1916
|
|
13
|
+
uipath_openai_agents/runtime/_serialize.py,sha256=EyTy1I-BR1FxfsSDdju2AbxVEauHmmzeXbhxRDR-sn8,1594
|
|
14
|
+
uipath_openai_agents/runtime/agent.py,sha256=DxoT5SqeI0BEb3bVCs52e237muwtc9qt1Wr4SnNfUMo,6994
|
|
15
|
+
uipath_openai_agents/runtime/config.py,sha256=gtDCIMB1fcAry9Tj_xJSR1xVaARMNmrr5HmwSn4Nh-w,1808
|
|
16
|
+
uipath_openai_agents/runtime/errors.py,sha256=AgUmbikoM53O02CktbZAKVjVmK1ZCl9-EG0gWaYtrn0,1333
|
|
17
|
+
uipath_openai_agents/runtime/factory.py,sha256=rCw521lvUDGLtjrOYn2WwNQ05oxmWjuAxCmoJ_HTzkg,7595
|
|
18
|
+
uipath_openai_agents/runtime/runtime.py,sha256=NJIuIMKNaK3nraEZvYu_1Dkh1CZ0nfBfybEKVgNe090,11229
|
|
19
|
+
uipath_openai_agents/runtime/schema.py,sha256=hNpzMH0Y46HLGmTbqaP8Ez7_mhVSacgbwagUNtsQPJs,11664
|
|
20
|
+
uipath_openai_agents-0.0.2.dist-info/METADATA,sha256=XYN9io2WkhMS3DMollZJIGPw7s-2prJpFihiz6CsdhQ,4938
|
|
21
|
+
uipath_openai_agents-0.0.2.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
22
|
+
uipath_openai_agents-0.0.2.dist-info/entry_points.txt,sha256=2tY1wvop4ulDwWMUXFZzOREIKyIf5cFYsefLWNA2-9w,183
|
|
23
|
+
uipath_openai_agents-0.0.2.dist-info/RECORD,,
|