Skip to content

Python: [Breaking] Restructure agent skills to use multi-source architecture#5584

Open
SergeyMenshykh wants to merge 8 commits intomicrosoft:mainfrom
SergeyMenshykh:agent-skills-refactoring-1
Open

Python: [Breaking] Restructure agent skills to use multi-source architecture#5584
SergeyMenshykh wants to merge 8 commits intomicrosoft:mainfrom
SergeyMenshykh:agent-skills-refactoring-1

Conversation

@SergeyMenshykh
Copy link
Copy Markdown
Member

@SergeyMenshykh SergeyMenshykh commented Apr 30, 2026

Motivation and Context

Restructures the Python agent skills system to use the new multi-source architecture as proposed in ADR-0021. This introduces composable abstractions for discovering, filtering, deduplicating, and combining skills from multiple origins (filesystem, inline code, or custom sources) — aligning the Python implementation with the .NET implementation.

Description

New abstractions

  • Skill — abstract base for all skill types, with frontmatter, instructions, resources, and scripts properties
  • SkillResource / SkillScript — abstract base types for resources and scripts
  • SkillsSource — abstract base for skill discovery from any origin (filesystem, in-memory, custom)

Skill implementations

  • InlineSkill — a skill defined entirely in code with a fluent API for adding resources and scripts (replaces the old Skill class used for code-defined skills)
  • InlineSkillResource — a resource wrapping static content or a callable
  • InlineSkillScript — a script backed by a callable
  • FileSkill — a filesystem-based skill discovered from SKILL.md files on disk (replaces the old Skill class used for file-based skills)
  • FileSkillScript — a file-based script that delegates execution to a configurable SkillScriptRunner

Source implementations

  • _FileSkillsSource — discovers file-based skills from SKILL.md files on disk
  • _InMemorySkillsSource — holds any Skill instances in memory (for inline/code-based skills)
  • _AggregatingSkillsSource — composes multiple sources into one

Source decorators

  • _DelegatingSkillsSource — abstract base for intercepting get_skills()
  • _FilteringSkillsSource — applies predicate-based skill filtering
  • _DeduplicatingSkillsSource — deduplicates by name (case-insensitive, first-wins)

Provider and builder

  • SkillsProvider — updated to accept a single SkillsSource (composed externally); retains SkillsProvider.from_paths() convenience factory for file-only use cases
  • SkillsProviderBuilder — fluent API for composing skills from multiple source types with add_file_skills(), add_skill(), filtering, deduplication, and a file script runner

Copilot AI review requested due to automatic review settings April 30, 2026 12:43
@moonbox3 moonbox3 added documentation Improvements or additions to documentation python labels Apr 30, 2026
@SergeyMenshykh SergeyMenshykh marked this pull request as draft April 30, 2026 12:43
@SergeyMenshykh SergeyMenshykh self-assigned this Apr 30, 2026
@SergeyMenshykh SergeyMenshykh moved this to In Review in Agent Framework Apr 30, 2026
@moonbox3
Copy link
Copy Markdown
Contributor

moonbox3 commented Apr 30, 2026

Python Test Coverage

Python Test Coverage Report •
FileStmtsMissCoverMissing
packages/core/agent_framework
   _skills.py6681398%195, 521, 531, 1825–1826, 1899, 1904, 1953, 1958, 2164–2165, 2550–2551
TOTAL30863355688% 

Python Unit Test Overview

Tests Skipped Failures Errors Time
6239 30 💤 0 ❌ 0 🔥 1m 39s ⏱️

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the Python Agent Skills system to the ADR-0021 multi-source architecture, introducing new skill/source abstractions and updating samples to use the new InlineSkill / FileSkill APIs and the builder-based composition flow.

Changes:

  • Refactors core skills models to abstract Skill/SkillResource/SkillScript types, plus concrete Inline* and File* implementations and SkillsSource composition.
  • Updates SkillsProvider to accept a composed source (or skill/skill list), adds SkillsProvider.from_paths(), and introduces SkillsProviderBuilder.
  • Refreshes skills samples/docs to use InlineSkill, SkillsProviderBuilder, and typed file-script runner signatures.

Reviewed changes

Copilot reviewed 8 out of 9 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
python/packages/core/agent_framework/_skills.py Implements the new multi-source skills architecture, new skill/script/resource types, provider changes, and builder.
python/packages/core/agent_framework/init.py Exposes new public API symbols for the refactored skills system.
python/samples/02-agents/skills/subprocess_script_runner.py Updates subprocess runner typing/behavior for file-based scripts.
python/samples/02-agents/skills/script_approval/script_approval.py Updates sample to InlineSkill and the new provider constructor API.
python/samples/02-agents/skills/mixed_skills/mixed_skills.py Updates sample to compose file + inline skills via SkillsProviderBuilder.
python/samples/02-agents/skills/mixed_skills/README.md Updates documentation diagram to builder-based composition.
python/samples/02-agents/skills/file_based_skill/file_based_skill.py Updates sample to use SkillsProvider.from_paths().
python/samples/02-agents/skills/code_defined_skill/code_defined_skill.py Updates sample to InlineSkill / InlineSkillResource and new provider API.

Comment thread python/packages/core/agent_framework/_skills.py Outdated
Comment thread python/samples/02-agents/skills/subprocess_script_runner.py Outdated
Comment thread python/packages/core/agent_framework/_skills.py Outdated
Comment thread python/packages/core/agent_framework/_skills.py Outdated
Comment thread python/packages/core/agent_framework/_skills.py Outdated
Comment thread python/packages/core/agent_framework/_skills.py Outdated
Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

Automated Code Review

Reviewers: 2 | Confidence: 88% | Result: All clear

Reviewed: Correctness, Security Reliability


Automated review by SergeyMenshykh's agents

SergeyMenshykh and others added 6 commits April 30, 2026 14:17
- Use anyio.Path for async file I/O in _FileSkillResource.read()
- Use noqa: ASYNC240 for pure string os.path calls in async context
- Restore pre-commit if/else pattern in InlineSkillScript.run()
- Break long lines to fit 120-char limit in _skills.py and test_skills.py

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The pyright ignore comments only suppress errors on the same line, so
multi-line lambdas left arguments on continuation lines uncovered.
Collapse both lambdas to single lines matching the existing load_skill
lambda pattern.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…t errors

Python lambdas cannot have type annotations, so pyright reports
reportUnknownLambdaType and reportUnknownArgumentType errors that
cannot be suppressed with inline ignore comments. Replace the
lambdas for read_skill_resource and run_skill_script with typed
inner async functions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Update with_prompt_template() docstring to document the
  {resource_instructions} placeholder requirement
- Remove stray backslashes after {resource_instructions} and
  {runner_instructions} in DEFAULT_SKILLS_INSTRUCTION_PROMPT
- Update subprocess_script_runner docstring to reflect
  FileSkillScript.full_path usage

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ider

Replace internal dict-based skills storage with Sequence[Skill] to
eliminate silent duplicate overwrites and simplify the code. Add
_find_skill helper for case-insensitive linear lookup.

Also fix pyright errors in tests by adding isinstance assertions
before accessing .function on SkillResource/SkillScript base types.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Move security validation (path-traversal and symlink guards) for
file-based skill resources into _FileSkillsSource, restoring the
read-time checks that existed in main via _read_file_skill_resource.

- Add _get_validated_resource_path static method on _FileSkillsSource
  that validates containment, existence, and symlink safety
- _FileSkillsSource.get_skills() validates resource paths at discovery
  time via _get_validated_resource_path before passing to _FileSkillResource
- Move _normalize_resource_path, _is_path_within_directory, and
  _has_symlink_in_path from module-level into _FileSkillsSource as
  static methods (only used there)
- _FileSkillResource remains a simple path-to-content reader
- Add tests for _get_validated_resource_path security checks

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@SergeyMenshykh SergeyMenshykh marked this pull request as ready for review April 30, 2026 15:43
Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

Automated Code Review

Reviewers: 3 | Confidence: 83%

✓ Correctness

No actionable issues found in this dimension.

✓ Security Reliability

No actionable issues found in this dimension.

✓ Design Approach

The test updates largely track the new Inline/File skill split, but they also lock in one design regression: SkillsProvider now appears to initialize successfully for file-based skills that contain scripts even when no runner is configured. That shifts what used to be a clear configuration-time validation into a runtime/tool-call failure, so the provider can advertise an unusable script capability to the model and only fail after run_skill_script is invoked. The chunk mostly looks coherent with the new source/builder direction, but one sample now blurs the intended API boundary by passing a plain inline-skill list through the new source= abstraction. That works against the PR’s own design, which otherwise distinguishes SkillsSource composition from the simpler inline-skill constructor path.


Automated review by SergeyMenshykh's agents

Comment thread python/packages/core/agent_framework/_skills.py
…Sequence ambiguity

Since str is a Sequence, passing a path string to the source parameter
would silently be treated as a sequence of characters instead of a
file source. Add an explicit TypeError with a helpful message pointing
callers to SkillsProvider.from_paths().

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation python

Projects

Status: In Review

Development

Successfully merging this pull request may close these issues.

4 participants