-
Notifications
You must be signed in to change notification settings - Fork 34
feat: support coded DeepAgents runtime workspaces #991
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
andreitava-uip
wants to merge
5
commits into
main
Choose a base branch
from
feat/coded-deepagents-runtime
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
a9136c7
feat: support coded DeepAgents
andreitava-uip 66a573c
refactor: tighten DeepAgents runtime contracts
andreitava-uip a278c74
refactor: narrow DeepAgents runtime configuration
andreitava-uip 79c2666
refactor: use runtime hydrator factory
andreitava-uip 3b3cf2c
test: fix DeepAgents static typing
andreitava-uip File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| # Coded DeepAgent | ||
|
|
||
| This sample demonstrates a task-mode coded agent built with | ||
| `uipath_langchain.deepagents.create_uipath_deep_agent`. | ||
|
|
||
| The API follows the authoring surface of `deepagents.create_deep_agent`. UiPath | ||
| owns compile-time configuration, including the filesystem backend and | ||
| checkpointer. It marks the graph for the UiPath runtime, which creates and | ||
| hydrates a disk-backed workspace through job attachments. | ||
|
|
||
| ## What It Shows | ||
|
|
||
| - Standard DeepAgents message input and structured output. | ||
| - A standard LangChain tool used by the main DeepAgent. | ||
| - A DeepAgents subagent used for risk review. | ||
| - Runtime-provided, attachment-hydrated filesystem workspace. | ||
|
|
||
| ## Files | ||
|
|
||
| - `graph.py`: task-mode coded DeepAgent graph. | ||
| - `input.json`: sample input payload. | ||
| - `langgraph.json`: LangGraph entrypoint. | ||
| - `uipath.json`: UiPath task-mode runtime configuration. | ||
| - `pyproject.toml`: sample dependencies. | ||
| - `agent.mermaid`: conceptual view of the agent workflow. | ||
|
|
||
| ## Requirements | ||
|
|
||
| - UiPath runtime credentials for `UiPathChat`. | ||
| - Access to the configured model, `gpt-5.4`. | ||
|
|
||
| ## Installation | ||
|
|
||
| ```bash | ||
| cd samples/coded-deepagent | ||
| uv sync | ||
| uv run uipath auth | ||
| ``` | ||
|
|
||
| ## Usage | ||
|
|
||
| ```bash | ||
| uv run uipath init | ||
| uv run uipath run agent "$(cat input.json)" | ||
| ``` | ||
|
|
||
| The agent uses the filesystem tools supplied by the DeepAgents harness for its | ||
| working files and returns a structured launch brief. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| flowchart TB | ||
| __start__(__start__) | ||
| deep_agent(deep_agent) | ||
| tools([agent tools]) | ||
| risk_reviewer([risk_reviewer subagent]) | ||
| workspace[(runtime workspace)] | ||
| structured_output(structured output) | ||
| __end__(__end__) | ||
|
|
||
| __start__ --> deep_agent | ||
| deep_agent <--> tools | ||
| deep_agent -. delegates review .-> risk_reviewer | ||
| deep_agent -. writes files .-> workspace | ||
| deep_agent --> structured_output | ||
| structured_output --> __end__ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| """Task-mode coded DeepAgent using the UiPath DeepAgents API.""" | ||
|
|
||
| from langchain_core.tools import tool | ||
| from pydantic import BaseModel | ||
|
|
||
| from uipath_langchain.chat import UiPathChat | ||
| from uipath_langchain.deepagents import create_uipath_deep_agent | ||
|
|
||
|
|
||
| class BriefOutput(BaseModel): | ||
| """Structured launch brief returned by the agent.""" | ||
|
|
||
| executive_summary: str | ||
| launch_plan: list[str] | ||
| risk_review: list[str] | ||
|
|
||
|
|
||
| @tool | ||
| def score_launch_readiness(audience: str, constraints: list[str]) -> str: | ||
| """Score launch readiness from simple deterministic planning signals.""" | ||
| score = 80 | ||
| if len(constraints) >= 3: | ||
| score -= 10 | ||
| if any("compliance" in item.lower() for item in constraints): | ||
| score -= 10 | ||
| if any("deadline" in item.lower() for item in constraints): | ||
| score -= 5 | ||
| return f"Launch readiness for {audience}: {max(score, 35)}/100" | ||
|
|
||
|
|
||
| MODEL = UiPathChat(model="gpt-5.4", temperature=0) | ||
|
|
||
| RISK_REVIEWER_PROMPT = """You are a launch risk reviewer. | ||
| Review the proposed launch plan for practical delivery risks, compliance gaps, | ||
| unclear ownership, and missing follow-up work. Return concise findings that the | ||
| main agent can incorporate into the final brief.""" | ||
|
|
||
| RISK_REVIEWER = { | ||
| "name": "risk_reviewer", | ||
| "description": "Reviews launch plans for execution risks and missing safeguards.", | ||
| "system_prompt": RISK_REVIEWER_PROMPT, | ||
| "model": MODEL, | ||
| } | ||
|
|
||
|
|
||
| SYSTEM_PROMPT = """You are a product launch planning agent. | ||
|
|
||
| Use the planning tools provided by DeepAgents. Use score_launch_readiness to get | ||
| a deterministic readiness signal. Delegate a plan review to risk_reviewer before | ||
| finalizing the answer. | ||
|
|
||
| Use the DeepAgents filesystem to write these working files before producing the | ||
| final answer: | ||
| - /launch/brief.md with the final launch brief | ||
| - /launch/risks.md with the risk review | ||
|
|
||
| Return structured output matching the schema.""" | ||
|
|
||
|
|
||
| graph = create_uipath_deep_agent( | ||
| model=MODEL, | ||
| system_prompt=SYSTEM_PROMPT, | ||
| response_format=BriefOutput, | ||
| tools=[score_launch_readiness], | ||
| subagents=[RISK_REVIEWER], | ||
| ) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| { | ||
| "messages": [ | ||
| { | ||
| "type": "human", | ||
| "content": "Create a pilot launch plan for Invoice Exception Copilot for accounts payable operations managers at three enterprise customers. The security review must complete before external rollout, the deadline is six weeks away, and the support team needs enablement material." | ||
| } | ||
| ] | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| { | ||
| "dependencies": ["."], | ||
| "graphs": { | ||
| "agent": "./graph.py:graph" | ||
| }, | ||
| "env": ".env" | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| [project] | ||
| name = "coded-deepagent" | ||
| version = "0.0.1" | ||
| description = "Task-mode coded DeepAgent using the UiPath runtime workspace contract" | ||
| authors = [{ name = "UiPath", email = "support@uipath.com" }] | ||
| requires-python = ">=3.11" | ||
| dependencies = [ | ||
| "uipath-langchain>=0.14.10, <0.15.0", | ||
| "uipath>=2.13.7, <2.14.0", | ||
| ] | ||
|
|
||
| [dependency-groups] | ||
| dev = [ | ||
| "uipath-dev", | ||
| ] | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| { | ||
| "runtimeOptions": { | ||
| "isConversational": false | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| """UiPath DeepAgents integration.""" | ||
|
|
||
| from typing import Any | ||
|
|
||
| __all__ = ["create_uipath_deep_agent"] | ||
|
|
||
|
|
||
| def __getattr__(name: str) -> Any: | ||
| if name == "create_uipath_deep_agent": | ||
| from .agent import create_uipath_deep_agent | ||
|
|
||
| return create_uipath_deep_agent | ||
| raise AttributeError(f"module {__name__!r} has no attribute {name!r}") |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| """UiPath-aware DeepAgents authoring API.""" | ||
|
|
||
| from collections.abc import Callable, Sequence | ||
| from typing import Any | ||
|
|
||
| from deepagents import ( | ||
| AsyncSubAgent, | ||
| CompiledSubAgent, | ||
| FilesystemPermission, | ||
| SubAgent, | ||
| ) | ||
| from deepagents import create_deep_agent as _create_deep_agent | ||
| from langchain.agents import AgentState | ||
| from langchain.agents.middleware import AgentMiddleware, InterruptOnConfig | ||
| from langchain.agents.middleware.types import ResponseT | ||
| from langchain.agents.structured_output import ResponseFormat | ||
| from langchain_core.language_models import BaseChatModel | ||
| from langchain_core.messages import SystemMessage | ||
| from langchain_core.tools import BaseTool | ||
| from langgraph.graph.state import CompiledStateGraph | ||
| from langgraph.typing import ContextT | ||
|
|
||
| from .backend import _UiPathWorkspaceBackendFactory | ||
| from .metadata import mark_uipath_deep_agent | ||
|
|
||
|
|
||
| # This API intentionally omits DeepAgents' compile-time arguments. | ||
| # UiPath-compatible DeepAgents use the runtime-managed filesystem backend and | ||
| # checkpointer. Other compile-time settings are currently unsupported. | ||
| def create_uipath_deep_agent( | ||
| model: str | BaseChatModel | None = None, | ||
| tools: Sequence[BaseTool | Callable[..., Any] | dict[str, Any]] | None = None, | ||
| *, | ||
| system_prompt: str | SystemMessage | None = None, | ||
| middleware: Sequence[AgentMiddleware] = (), | ||
| subagents: Sequence[SubAgent | CompiledSubAgent | AsyncSubAgent] | None = None, | ||
| skills: list[str] | None = None, | ||
| memory: list[str] | None = None, | ||
| permissions: list[FilesystemPermission] | None = None, | ||
| interrupt_on: dict[str, bool | InterruptOnConfig] | None = None, | ||
| response_format: ResponseFormat[ResponseT] | ||
| | type[ResponseT] | ||
| | dict[str, Any] | ||
| | None = None, | ||
| context_schema: type[ContextT] | None = None, | ||
| ) -> CompiledStateGraph[AgentState[ResponseT], ContextT, Any, Any]: | ||
| """Create a DeepAgent backed by the UiPath runtime workspace. | ||
|
|
||
| Parameters match ``deepagents.create_deep_agent`` and are forwarded unchanged, | ||
| except that UiPath owns compile-time configuration. | ||
| """ | ||
| graph = _create_deep_agent( | ||
| model=model, | ||
| tools=tools, | ||
| system_prompt=system_prompt, | ||
| middleware=middleware, | ||
| subagents=subagents, | ||
| skills=skills, | ||
| memory=memory, | ||
| permissions=permissions, | ||
| backend=_UiPathWorkspaceBackendFactory(), | ||
| interrupt_on=interrupt_on, | ||
| response_format=response_format, | ||
| context_schema=context_schema, | ||
| ) | ||
| return mark_uipath_deep_agent(graph) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| """Workspace backend helpers for UiPath DeepAgents.""" | ||
|
|
||
| from deepagents.backends import FilesystemBackend | ||
| from langchain.tools import ToolRuntime | ||
| from langchain_core.runnables import RunnableConfig | ||
| from langgraph.config import get_config | ||
|
|
||
| from uipath_langchain.runtime._workspace import get_workspace_path | ||
|
|
||
|
|
||
| class _UiPathWorkspaceBackendFactory: | ||
| """DeepAgents backend factory resolved from UiPath runtime config.""" | ||
|
|
||
| def __call__(self, runtime: ToolRuntime) -> FilesystemBackend: | ||
| config: RunnableConfig | None = getattr(runtime, "config", None) | ||
| if config is None: | ||
| try: | ||
| config = get_config() | ||
| except RuntimeError: | ||
| config = {} | ||
| return FilesystemBackend( | ||
| root_dir=get_workspace_path(config), | ||
| virtual_mode=True, | ||
| ) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| """Runtime marker for UiPath-created DeepAgents graphs.""" | ||
|
|
||
| from typing import Any, TypeVar | ||
|
|
||
| from langgraph.graph.state import CompiledStateGraph | ||
|
|
||
| _UIPATH_INTEGRATION_METADATA_KEY = "uipath_integration" | ||
| _UIPATH_DEEPAGENTS_INTEGRATION = "deepagents" | ||
|
|
||
| CompiledGraphT = TypeVar( | ||
| "CompiledGraphT", | ||
| bound=CompiledStateGraph[Any, Any, Any, Any], | ||
| ) | ||
|
|
||
|
|
||
| def mark_uipath_deep_agent( | ||
| graph: CompiledGraphT, | ||
| ) -> CompiledGraphT: | ||
| """Return a graph copy with explicit UiPath DeepAgents runtime metadata.""" | ||
| return graph.with_config( | ||
| { | ||
| "metadata": { | ||
| _UIPATH_INTEGRATION_METADATA_KEY: _UIPATH_DEEPAGENTS_INTEGRATION, | ||
| } | ||
| } | ||
| ) | ||
|
|
||
|
|
||
| def is_uipath_deep_agent( | ||
| graph: CompiledStateGraph[Any, Any, Any, Any], | ||
| ) -> bool: | ||
| """Return whether ``graph`` was built by the UiPath DeepAgents API.""" | ||
| config = getattr(graph, "config", None) or {} | ||
| metadata = config.get("metadata", {}) if isinstance(config, dict) else {} | ||
| if not isinstance(metadata, dict): | ||
| return False | ||
| return ( | ||
| metadata.get(_UIPATH_INTEGRATION_METADATA_KEY) == _UIPATH_DEEPAGENTS_INTEGRATION | ||
| ) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| """Internal workspace integration shared by runtime-backed agents.""" | ||
|
|
||
| from pathlib import Path | ||
| from typing import Any, NotRequired, TypedDict | ||
|
|
||
| from langchain_core.runnables import RunnableConfig | ||
|
|
||
| WORKSPACE_PATH_CONFIG_KEY = "uipath_workspace_path" | ||
|
|
||
|
|
||
| class _UiPathGraphConfigurable(TypedDict): | ||
| """UiPath-owned values injected into LangGraph's configurable payload.""" | ||
|
|
||
| thread_id: str | ||
| uipath_workspace_path: NotRequired[str] | ||
|
|
||
|
|
||
| def create_graph_configurable( | ||
| *, | ||
| thread_id: str, | ||
| workspace_path: Path | None, | ||
| ) -> dict[str, Any]: | ||
| """Create the UiPath-owned portion of LangGraph's configurable payload.""" | ||
| configurable: _UiPathGraphConfigurable = {"thread_id": thread_id} | ||
| if workspace_path is not None: | ||
| configurable["uipath_workspace_path"] = str(workspace_path) | ||
| return dict(configurable) | ||
|
|
||
|
|
||
| def get_workspace_path(config: RunnableConfig) -> Path: | ||
| """Decode and validate the UiPath-managed workspace path from graph config.""" | ||
| configurable = config.get("configurable") | ||
| workspace_path = ( | ||
| configurable.get(WORKSPACE_PATH_CONFIG_KEY) | ||
| if isinstance(configurable, dict) | ||
| else None | ||
| ) | ||
| if not isinstance(workspace_path, str) or not workspace_path: | ||
| raise RuntimeError( | ||
| "UiPath DeepAgents workspace path is unavailable. Run graphs created " | ||
| "by create_uipath_deep_agent through the UiPath runtime." | ||
| ) | ||
| return Path(workspace_path) |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.