Skip to content

feat(skills): add skills support to advanced agents with sandboxed cli tool - #989

Open
mariadhakalUipath wants to merge 1 commit into
mainfrom
feat/uipath-skills-for-advanced
Open

feat(skills): add skills support to advanced agents with sandboxed cli tool#989
mariadhakalUipath wants to merge 1 commit into
mainfrom
feat/uipath-skills-for-advanced

Conversation

@mariadhakalUipath

Copy link
Copy Markdown

Title: Uipath Skills with Cli tool for advanced agents.

Summary

Adds skills feature for advanced agents. Agent can act on it — run uip commands, review what it ran, and verify what it scaffolded.

Copilot AI review requested due to automatic review settings July 14, 2026 21:20

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds initial “skills” plumbing to advanced agents and introduces a sandbox-oriented internal tool for running uip commands inside an agent workspace.

Changes:

  • Introduces a new create_uipath_cli_tool() (uipath_cli) StructuredTool that runs one uip command per invocation with command validation.
  • Adds unit tests covering command parsing, validation, subprocess result mapping, and timeout behavior for the new tool.
  • Extends advanced-agent builders to accept and forward a skills parameter into the underlying deepagents agent construction.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

File Description
tests/agent/tools/internal_tools/test_uipath_cli_tool.py Adds test coverage for the new sandboxed CLI tool.
src/uipath_langchain/agent/tools/internal_tools/uipath_cli_tool.py Implements the sandboxed uipath_cli tool and its input/output schemas.
src/uipath_langchain/agent/tools/internal_tools/__init__.py Exports create_uipath_cli_tool from the internal tools package.
src/uipath_langchain/agent/advanced/agent.py Adds skills parameter propagation to deepagents agent creation/wrappers.

Comment thread src/uipath_langchain/agent/tools/internal_tools/uipath_cli_tool.py
Comment thread src/uipath_langchain/agent/tools/internal_tools/uipath_cli_tool.py
Comment thread src/uipath_langchain/agent/tools/internal_tools/uipath_cli_tool.py Outdated
Comment thread tests/agent/tools/internal_tools/test_uipath_cli_tool.py
@mariadhakalUipath
mariadhakalUipath force-pushed the feat/uipath-skills-for-advanced branch from d79b0c1 to 5b5dea8 Compare July 14, 2026 21:27
@mariadhakalUipath mariadhakalUipath changed the title feat: add skills support to advanced agents with sandboxed workspace tools feat: add skills support to advanced agents with sandboxed cli tool Jul 14, 2026
@mariadhakalUipath
mariadhakalUipath force-pushed the feat/uipath-skills-for-advanced branch from 5b5dea8 to 36f2b2c Compare July 14, 2026 21:32
@mariadhakalUipath mariadhakalUipath changed the title feat: add skills support to advanced agents with sandboxed cli tool feat(skills): add skills support to advanced agents with sandboxed cli tool Jul 14, 2026
@mariadhakalUipath
mariadhakalUipath force-pushed the feat/uipath-skills-for-advanced branch from 36f2b2c to 2f7b1c1 Compare July 14, 2026 21:38

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

Comments suppressed due to low confidence (1)

src/uipath_langchain/agent/advanced/agent.py:45

  • The create_advanced_agent docstring documents memory but not the newly added skills parameter, which is part of the public API. Update the docstring to describe what skills does and how an empty value is handled.
    """Create a deepagents agent with planning, filesystem, and sub-agent tools.

    ``memory`` is a list of file paths loaded via deepagents' ``MemoryMiddleware``:
    each is read from ``backend`` and injected into the system prompt every turn,
    and the model maintains them with ``edit_file``. Empty disables the middleware.
    """

Comment thread src/uipath_langchain/agent/tools/internal_tools/uipath_cli_tool.py
Comment thread src/uipath_langchain/agent/tools/internal_tools/uipath_cli_tool.py Outdated
Comment thread tests/agent/tools/internal_tools/test_uipath_cli_tool.py
Comment thread src/uipath_langchain/agent/advanced/agent.py

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Comment thread src/uipath_langchain/agent/tools/internal_tools/uipath_cli_tool.py Outdated
Comment thread src/uipath_langchain/agent/tools/internal_tools/uipath_cli_tool.py Outdated
Comment thread src/uipath_langchain/agent/advanced/agent.py Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Comment thread src/uipath_langchain/agent/tools/internal_tools/uipath_cli_tool.py Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

src/uipath_langchain/agent/advanced/agent.py:42

  • create_advanced_agent now accepts skills, but the docstring only documents memory. Since empty skills collapses to None (disabling skills support), documenting this behavior would help callers understand how to enable/disable the feature.
    skills: Sequence[str] = (),
) -> CompiledStateGraph[Any, Any, Any, Any]:
    """Create a deepagents agent with planning, filesystem, and sub-agent tools.

    ``memory`` is a list of file paths loaded via deepagents' ``MemoryMiddleware``:

Comment thread src/uipath_langchain/agent/tools/internal_tools/uipath_cli_tool.py
Comment thread src/uipath_langchain/agent/tools/internal_tools/uipath_cli_tool.py Outdated
@mariadhakalUipath
mariadhakalUipath force-pushed the feat/uipath-skills-for-advanced branch 2 times, most recently from 9bbae6c to 850386e Compare July 15, 2026 18:11

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Comment thread src/uipath_langchain/agent/tools/internal_tools/uipath_cli_tool.py
@mariadhakalUipath
mariadhakalUipath force-pushed the feat/uipath-skills-for-advanced branch 2 times, most recently from 8fd9bf3 to 923cb66 Compare July 15, 2026 23:16

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Comment thread src/uipath_langchain/agent/advanced/agent.py
Comment thread src/uipath_langchain/agent/tools/internal_tools/uipath_cli_tool.py Outdated
Comment thread src/uipath_langchain/agent/tools/internal_tools/uipath_cli_tool.py Outdated
@mariadhakalUipath
mariadhakalUipath force-pushed the feat/uipath-skills-for-advanced branch 5 times, most recently from 7d9ca46 to b02dd2b Compare August 6, 2026 20:29

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.

Suppressed comments (3)

src/uipath_langchain/agent/tools/internal_tools/uipath_cli_tool.py:37

  • The tool description says “A negative exit_code means the command was refused”. That’s inaccurate because real subprocess exit codes can be negative on Unix when terminated by a signal. The contract in UiPathCliOutput/test cases is specifically “exit_code == -1000 indicates refusal”, so the description should match to avoid confusing the agent.
    "Run a single UiPath `uip` command in the agent workspace; returns "
    "exit_code/stdout/stderr. Only the uip/uipath binaries, one command per call; "
    "shell chaining is refused. A negative exit_code means the command was refused "
    "before it ran and stderr explains why. Use `subdir` to target a scaffolded "
    "project folder."

src/uipath_langchain/agent/tools/internal_tools/uipath_cli_tool.py:167

  • On timeout, proc.kill() can raise ProcessLookupError if the process exits between the timeout firing and the kill call. That would crash the tool instead of returning the recoverable _REJECTED_EXIT_CODE payload.
    except asyncio.TimeoutError:
        proc.kill()
        await proc.wait()
        return _rejected(
            echoed, f"Command timed out after {_COMMAND_TIMEOUT_SECONDS}s."

src/uipath_langchain/agent/advanced/agent.py:110

  • This PR introduces a sandboxed uipath_cli tool, but create_advanced_agent only forwards the skills list into deepagents and never registers the new tool. The new tool module’s docstring says it is “injected programmatically by the agent graph builder when UiPath skills are active”, but there is currently no call site for create_uipath_cli_tool in src/ (verified by repo search). If skills are expected to prescribe uip commands, the agent needs the tool added to its tool list when skills are enabled (and a FilesystemBackend workspace exists).
        memory=list(memory) or None,
        middleware=list(middleware),
        skills=list(skills) if skills else None,

@mariadhakalUipath
mariadhakalUipath deleted the feat/uipath-skills-for-advanced branch August 6, 2026 20:40
@mariadhakalUipath
mariadhakalUipath restored the feat/uipath-skills-for-advanced branch August 6, 2026 20:41
@mariadhakalUipath
mariadhakalUipath force-pushed the feat/uipath-skills-for-advanced branch from b02dd2b to 4083836 Compare August 10, 2026 16:14
"A single `uip` command without the binary prefix, e.g. `pack`, "
"`solution publish`. One command only; no shell operators."
),
examples=["pack", "solution publish", "codeagent init"],

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

codeagent init is not a valid command; the cli returns unknown command 'codeagent'. use codedagent init here, and add a schema assertion so the example stays aligned with the actual cli.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for correcting me. I have changed the example command and also added the schema assertion for the example commands.

response_format: ResponseFormat[Any] | None = None,
memory: Sequence[str] = (),
middleware: Sequence[AgentMiddleware[Any, Any]] = (),
skills: Sequence[str] | None = None,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a logic-changing public change, but the pr does not bump the package version. main is already at 0.16.2 while this branch still has 0.16.1. rebase and bump to the next version in pyproject.toml before merge.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay will do this before I merge.

echoed, f"Invalid subdir '{subdir}': escapes the workspace."
)

return await _run_uip_subprocess(binary, args, run_dir, echoed)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this still executes the cli arguments directly, without the cli owning and enforcing a safe mode. the parser currently accepts commands such as solution delete and admin tenants delete, so resolving the previous thread did not address the version-skew problem. let s add the safety flag in the cli and always append it here before shipping this tool.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is really good point we were thinking about this, the reason I don't have it implemented is:

  1. We are using the user's token to run these commands so it is already tenant and folder scoped, agent can only run the commands that user is allowed.
  2. This tool is used by both conversational and autonomous low-code agent, conversational agent uses the interactive mode to ask user to run the command and only the autonomous low-code agent is running the command by itself so I added prompt-based guardrail to end the execution if there is any destructive command.
  3. It is only attached to agent if the skills are enabled so it will only follow the instructions there and if the user is using this tool in coded agent then it becomes their responsibility to filter the commands.
    Please guide me if I am missing anything that I should have considered for this, and I can work through it.

proc.communicate(), timeout=_COMMAND_TIMEOUT_SECONDS
)
except asyncio.TimeoutError:
proc.kill()

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

proc.kill() can raise ProcessLookupError when the child exits in the timeout and kill race. i reproduced that path and the tool crashes instead of returning the recoverable timeout payload. catch that race and still await proc.wait().

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix:

except asyncio.TimeoutError:
    try:
        proc.kill()
    except ProcessLookupError:
        pass
    await proc.wait()

wait_for timing out only means the child hadn't finished when the timer fired it can
exit before kill() runs, and the transport teardown that nulls _proc makes kill()
raise. await proc.wait() stays outside the try so it runs on both paths (safe after
teardown: _wait() returns the cached returncode immediately). Catching only
ProcessLookupError so a real PermissionError still surfaces.

Added Regression test: test_run_times_out_when_child_exits_during_kill to verify it fails
with an uncaught ProcessLookupError against the unpatched code.

response_format=response_format,
memory=list(memory) or None,
middleware=list(middleware),
skills=list(skills) if skills else None,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this tool is still not wired into the advanced agent. with skills enabled, we only forward the skill paths and leave tools unchanged, so the agent has no way to call uipath_cli. let s add it here for the filesystem-backed skills path and cover the final tool list in a test.

@mariadhakalUipath mariadhakalUipath Aug 13, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have this tool behind feature flag and we wired it when creating advanced agent graph for low-code agents if skills are enabled instead of wiring it to advanced agent. The scope for now is to attach the tool for low-code agents.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@mariadhakalUipath
mariadhakalUipath force-pushed the feat/uipath-skills-for-advanced branch from 4083836 to b8d13be Compare August 13, 2026 18:20
@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants