Skip to content

feat: add skills feature to advanced agent with workspace to load skills#977

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

feat: add skills feature to advanced agent with workspace to load skills#977
mariadhakalUipath wants to merge 1 commit into
mainfrom
feat/uipath-skills-for-advanced-agents

Conversation

@mariadhakalUipath

@mariadhakalUipath mariadhakalUipath commented Jul 8, 2026

Copy link
Copy Markdown

Title: feat: add skills support to advanced agents with sandboxed workspace tools

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 8, 2026 21:52

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 opt-in “skills” support to deepagents-backed advanced agents, including workspace-mounted skill sources and auto-injected sandboxed workspace tools (CLI runner, audit log reader, and scaffold verifier) when running on a FilesystemBackend.

Changes:

  • Adds a skills: Sequence[str] | None parameter to create_advanced_agent / create_advanced_agent_graph and wires it into deepagents’ SkillsMiddleware with workspace-source prepending/dedup.
  • Introduces three workspace-bound internal tools (uipath_cli, uipath_cli_usage, uipath_verify_files) plus timeout/audit/denylist and required-files validation logic.
  • Adds focused test coverage for skills opt-in behavior, tool injection gating, CLI sandboxing/audit behavior, usage reading, and file verification.

Reviewed changes

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

Show a summary per file
File Description
src/uipath_langchain/agent/advanced/agent.py Wires skills into deepagents and injects workspace tools when skills are active on a filesystem backend.
src/uipath_langchain/agent/advanced/utils.py Defines skills workspace layout constants (SKILLS_DIR_NAME, SKILLS_VIRTUAL_PATH).
src/uipath_langchain/agent/advanced/init.py Exports skills-related constants from the advanced agent package.
src/uipath_langchain/agent/tools/internal_tools/uipath_cli_tool.py Implements the sandboxed CLI runner, audit-log usage reader, and required-files verifier tools.
src/uipath_langchain/agent/tools/internal_tools/init.py Exposes the new internal tool constructors/utilities from the internal tools package.
tests/agent/advanced/test_skills_injection.py Tests skills opt-in gating and workspace source prepending/dedup behavior.
tests/agent/advanced/test_cli_tool_injection.py Tests conditional injection of the three workspace tools based on skills + filesystem backend.
tests/agent/tools/internal_tools/test_uipath_cli_tool.py Tests CLI sandboxing: binary allowlist, subdir jailing, timeout resolution, denylist, and auditing.
tests/agent/tools/internal_tools/test_cli_usage_tool.py Tests reading and summarizing CLI audit log records (including malformed line handling).
tests/agent/tools/internal_tools/test_verify_files_tool.py Tests file verification behavior including glob patterns, unknown types, and workspace escape prevention.

Comment thread src/uipath_langchain/agent/advanced/agent.py
Comment on lines +152 to +155
workspace_path = Path(workspace).expanduser().resolve()
workspace_path.mkdir(parents=True, exist_ok=True)
audit_path = Path(audit_log or (workspace_path / AUDIT_LOG_FILENAME)).expanduser()
denied = frozenset(
Comment on lines +264 to +272
return finish(
"ok" if proc.returncode == 0 else "nonzero_exit",
f"exit_code: {proc.returncode}\n--- stdout ---\n{proc.stdout}\n--- stderr ---\n{proc.stderr}",
exit_code=proc.returncode,
stdout=proc.stdout[:MAX_LOG_BYTES],
stderr=proc.stderr[:MAX_LOG_BYTES],
stdout_truncated=len(proc.stdout) > MAX_LOG_BYTES,
stderr_truncated=len(proc.stderr) > MAX_LOG_BYTES,
)
Comment on lines +281 to +294
def _read_audit_records(audit_path: Path) -> list[dict[str, Any]]:
"""Return audit records of cli commands execution in invocation order; empty if the log is absent."""
if not audit_path.is_file():
return []
records: list[dict[str, Any]] = []
for raw in audit_path.read_text(encoding="utf-8").splitlines():
line = raw.strip()
if not line:
continue
try:
records.append(json.loads(line))
except json.JSONDecodeError:
continue
return records
Comment on lines +331 to +335
def _file_matches(project_dir: Path, pattern: str) -> bool:
"""True if ``pattern`` (literal name or glob) matches a file in the dir root."""
if any(ch in pattern for ch in "*?["):
return any(project_dir.glob(pattern))
return (project_dir / pattern).is_file()
@mariadhakalUipath mariadhakalUipath force-pushed the feat/uipath-skills-for-advanced-agents branch 2 times, most recently from e5d2b48 to 5cee6e8 Compare July 10, 2026 03:58

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 7 out of 7 changed files in this pull request and generated 2 comments.

Comment on lines +118 to +123
binary = os.path.basename(argv[0])
if binary not in ALLOWED_BINARIES:
return (
f"ERROR: '{binary}' is not allowed. Only these binaries are "
f"permitted: {sorted(ALLOWED_BINARIES)}"
)
Comment on lines +59 to +60
memory=list(memory) or None,
skills=list(skills) if skills is not None else None,
backend=backend,
response_format=response_format,
memory=list(memory) or None,
skills=list(skills) if skills is not None else None,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

because of the default None in the function call this could be simply skills = list(skills)

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.

Changed skills = list(skills) or None instead to avoid triggering deepagents skillsmidleware when the skills list is passed empty.

@mariadhakalUipath mariadhakalUipath force-pushed the feat/uipath-skills-for-advanced-agents branch 3 times, most recently from ca05cf8 to 55a9031 Compare July 13, 2026 22:25

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 7 out of 7 changed files in this pull request and generated 2 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
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

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 7 out of 7 changed files in this pull request and generated 3 comments.

@@ -0,0 +1,210 @@
"""Workspace CLI tool injected when skills are active."""
Comment on lines +150 to +154
return (
f"exit_code: {proc.returncode}\n"
f"--- stdout ---\n{proc.stdout[:MAX_LOG_BYTES]}\n"
f"--- stderr ---\n{proc.stderr[:MAX_LOG_BYTES]}"
)
Comment on lines 73 to +76
With a ``FilesystemBackend``, attachment-shaped inputs are downloaded into the
workspace and given a ``FilePath`` before the user message is built. A
``FilesystemBackend`` also enables workspace memory: deepagents'
``MemoryMiddleware`` reads ``/memory/MEMORY.md`` from the backend each turn.
Memory stays disabled for non-filesystem backends, which carry no workspace.
workspace, memory (``/memory/MEMORY.md``) is enabled, and the workspace
``skills/`` dir is prepended to any declared ``skills``. Both stay disabled for
non-filesystem backends, which carry no workspace.
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.

3 participants