Skip to content

feat(skills): skill bundles for coded LangGraph agents [PC-5187] - #1179

Draft
cristian-groza wants to merge 26 commits into
mainfrom
feat/skills-coded-agents
Draft

cristian-groza wants to merge 26 commits into
mainfrom
feat/skills-coded-agents

Conversation

@cristian-groza

@cristian-groza cristian-groza commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

PR stack (skills for coded agents and the advanced harness), merge in this order

  1. [1/2] feat(skills): skill bundles for coded agents [PC-5187] uipath-python#1962: sdk.skills in uipath-platform 0.2.42 and skillBundle overrides in uipath 2.14.45.
  2. [2/2] UiPath/uipath-langchain-python (this PR): kept as a draft until [1/2] is released. Then it raises uipath-platform / uipath to those versions here and in samples/skills-agent/pyproject.toml, refreshes uv.lock and stamps the release notes. Until then CI cannot import uipath.platform.skills.
  3. [3/3] UiPath/uipath-agents-python#829: the low-code advanced harness, which now imports the middleware and prompt from this PR instead of keeping its own copy.

Summary

The LangChain side of skill bundles for coded agents. uipath.platform.skills resolves and downloads the bundles; this PR wires them into a LangGraph agent.

  • UiPathSkills: declares an agent's bundles at import time and resolves them once per process, safely across threads and event loops. It then hands out:
    • load_skill_tool(): a load_skill(name) tool that returns a skill's SKILL.md. Its output is capped to fit the context budget, and unknown names get a helpful error.
    • prompt_section(): the ## Skills system-prompt block.
    • advanced_middleware(backend) for deepagents agents.
  • Building blocks for an already-resolved SkillSet: create_load_skill_tool, skills_prompt_section.
  • Advanced (deepagents) agents: UiPathSkillsMiddleware, SkillLoadTraceMiddleware and create_skills_middleware. These moved here from uipath-agents-python (UiPath/uipath-agents-python#829) so coded and low-code agents share one implementation. The prompt is word for word the harness text, including D15: skill scripts are stored but cannot be executed. The module is imported lazily, so deepagents is only needed by agents that use it.
  • Sample samples/skills-agent: a LangGraph agent that binds two bundles (finance pinned to v3, ops latest), with local skills and bindings.json. Its README covers the local source, the orchestrator placeholder, overrides and traces.
  • Docs: docs/skills.md. The mkdocs nav entry goes into uipath-python once this page is merged.
  • Version: uipath-langchain 0.18.52.

Test plan

  • pytest tests/skills (110 passed), ruff check, ruff format --check, mypy src/uipath_langchain/skills tests/skills. Run locally against [1/2] installed in editable mode.
  • commitlint (commitlint.config.mjs).
  • End to end on the staging tenant with the sample:
    • uipath init generated the graph with its tools node.
    • Both bundles resolved through UIPATH_SKILLS_SOURCE=local.
    • Claude Haiku 4.5 called load_skill("ops/escalation-policy") and followed its steps, and skills_used was ["ops/escalation-policy"].
    • The run succeeded, and trace.jsonl holds the Skill bundles resolved and Skill load - ops/escalation-policy spans.
  • CI is green once [1/2] is released and the floors are raised.

🤖 Generated with Claude Code

cristian-groza and others added 11 commits October 28, 2026 22:02
… [PC-5187]

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…budget [PC-5187]

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e per process [PC-5187]

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…5187]

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…hain [PC-5187]

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…older [PC-5187]

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…C-5187]

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-5187]

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-5187]

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
cristian-groza and others added 15 commits October 29, 2026 13:06
…rness does [PC-5187]

D15: scripts are stored, never run. The advanced-agent prompt now matches the
uipath-agents-python harness word for word, so both runtimes give the same rule.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ock` [PC-5187]

uipath-platform no longer ships the Skills API client or the `mock`
source, and `orchestrator` is a placeholder until the API exists. The
sample, its README and the docs use `local`; the sample's override test
retargets a binding instead of pinning a version the folder lacks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A skillBundle resource overwrite now replaces the whole binding, as for the
other bindings: name, folderPath and versionMode, plus version when pinned. The
sample's example override and the override test carry the full entry, and the
README says an incomplete entry is skipped with a warning.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-5187]

uipath_langchain.skills re-exported the four middleware names through a
module __getattr__, so the load_skill path would not import deepagents. The
names now come from uipath_langchain.skills.middleware directly: the package
init loses the lazy loader and still never imports deepagents.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
test_prompt.py mostly asserted the wording of the skills prompts. The
remaining skills tests still exercise skills_prompt_section and the
SkillsMiddleware template through UiPathSkills and the middleware.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The plain async call is covered by the async span test, the enum rejection by
pydantic and the ToolNode test, and "supporting files record no span" by the
SDK's SkillSet.read tests. The metadata test no longer pins the description
wording.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The rendered-section test duplicated the modify_request test through private
methods, the async missing-folder test the shared error path, and the empty
deepagents_sources test the empty case of advanced_middleware.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…C-5187]

The bundle-source check moves into the main run test, which already ran the
same script, and the unit test of the sample's own skills_used helper goes.
The four tests left run UiPathSkills on the real SDK and local source inside a
LangGraph graph: a skill load, a failed load, an override and no skills.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The runtime calls a graph factory once per entrypoint, on one event loop, so
UiPathSkills no longer coordinates loads across threads and loops. load_sync,
the lazy load_skill tool for module-level graphs and the machinery behind them
(the thread lock, futures, the cleanup generation and the same-loop fallback)
are gone; load is an asyncio.Lock around one cached resolution, and
load_skill_tool raises before load. The docs drop the module-level graph
section, and the tests keep the contract the factory path relies on.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
SkillLoadTraceMiddleware now decides from the call's arguments whether
read_file reads a bound SKILL.md, and runs the tool inside the SDK's
skill_load_span. The span is current while the tool runs, so the
read_file tool call nests under "Skill load - <bundle>/<skill>". A read
that returns an error, or a Command without a ToolMessage, leaves the
span with an error status; a Command carrying a ToolMessage counts as a
load. Tracing failures still never affect the tool call.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
main moved uipath-langchain to 0.18.55 and raised the uipath minimums.
Take main's dependencies and keep the skills bump on top: 0.18.56.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Main moved to uipath 2.15 / uipath-platform 0.3 and released 0.19.0;
the branch version becomes 0.19.1 in pyproject.toml and uv.lock.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…5187]

The skills code ships in uipath 2.15.1 and uipath-langchain 0.19.1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sonarqubecloud

sonarqubecloud Bot commented Nov 5, 2026

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
0.0% Coverage on New Code (required ≥ 90%)

See analysis details on SonarQube Cloud

This branch has not been deployed

No deployments
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.

1 participant