Skip to content

Python: Changed Skills Resources to Use Type-Safe Dependencies#4564

Draft
suneetnangia wants to merge 4 commits intomicrosoft:mainfrom
suneetnangia:typed-hinted-code-skills-di
Draft

Python: Changed Skills Resources to Use Type-Safe Dependencies#4564
suneetnangia wants to merge 4 commits intomicrosoft:mainfrom
suneetnangia:typed-hinted-code-skills-di

Conversation

@suneetnangia
Copy link

Motivation and Context

  1. Why is this change required? to provide type-safe dependencies for Skill Resources.
  2. What problem does it solve? avoid untyped dependencies which are prone to bugs.
  3. What scenario does it contribute to? Skills Resources DI scenarios.
  4. If it fixes an open issue, please link to the issue here.

Description

This pull request introduces a new, experimental SkillContext API for code-defined skill resources in the agent framework, enabling typed dependency injection into resource functions. It replaces the previous pattern of passing **kwargs to resource functions, offering a more robust and type-safe way to provide shared dependencies (such as database clients or configuration) to skill resources.

SkillContext API and Dependency Injection:

  • Introduced the SkillContext[DepsT] class in agent_framework._skills, allowing resource functions to declare a first parameter that receives a typed context with dependencies injected by the SkillsProvider. This is detected automatically and is mutable, enabling state sharing between resources. [1] [2] [3] [4]

  • Updated the SkillsProvider to accept a deps argument, which is passed to all resource functions that declare a SkillContext parameter. The provider now detects whether a resource expects a SkillContext and injects it accordingly. [1] [2] [3] [4]

Testing and Backward Compatibility:

  • Added extensive tests for the new SkillContext pattern, including sync and async resources, mutation of dependencies, and backward compatibility for resources that do not use SkillContext.

Documentation and Samples:

  • Updated the documentation and sample code (README.md, code_skill.py) to demonstrate the new typed dependency injection pattern using SkillContext, replacing references to the old **kwargs pattern. [1] [2] [3] [4] [5] [6]

These changes make skill resource functions more robust, type-safe, and easier to test.

Contribution Checklist

  • The code builds clean without any errors or warnings
  • The PR follows the Contribution Guidelines
  • All unit tests pass, and I have added new tests where possible
  • Is this a breaking change? If yes, add "[BREAKING]" prefix to the title of the PR.

Signed-off-by: Suneet Nangia <suneetnangia@gmail.com>
Copilot AI review requested due to automatic review settings March 9, 2026 17:02
@markwallace-microsoft markwallace-microsoft added documentation Improvements or additions to documentation python labels Mar 9, 2026
@github-actions github-actions bot changed the title Changed Skills Resources to Use Type-Safe Dependencies Python: Changed Skills Resources to Use Type-Safe Dependencies Mar 9, 2026
@markwallace-microsoft
Copy link
Member

markwallace-microsoft commented Mar 9, 2026

Python Test Coverage

Python Test Coverage Report •
FileStmtsMissCoverMissing
packages/core/agent_framework
   _skills.py310897%689, 728–729, 802, 807, 959–960, 1168
TOTAL22702258488% 

Python Unit Test Overview

Tests Skipped Failures Errors Time
4953 20 💤 0 ❌ 0 🔥 1m 20s ⏱️

Copy link
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 introduces an experimental SkillContext[DepsT] API to enable typed dependency injection into code-defined skill resource functions, and updates the skills provider/tests/samples/docs accordingly.

Changes:

  • Added SkillContext[DepsT] and detection logic so SkillsProvider can inject typed deps into resource functions.
  • Updated SkillsProvider to accept a deps object and pass it into resource functions that opt into SkillContext.
  • Updated tests and the code-defined skills sample/docs to demonstrate typed deps.

Reviewed changes

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

Show a summary per file
File Description
python/packages/core/agent_framework/_skills.py Adds SkillContext, detects whether a resource takes it, and injects provider deps into resource execution.
python/packages/core/agent_framework/init.py Re-exports SkillContext from the package root.
python/packages/core/tests/core/test_skills.py Adds tests for SkillContext injection/mutation and related detection behavior.
python/samples/02-agents/skills/code_skill/code_skill.py Updates sample to use SkillContext + provider-level deps instead of runtime kwargs.
python/samples/02-agents/skills/code_skill/README.md Updates sample documentation to describe the SkillContext pattern.

Comment on lines +524 to 525
self._deps = deps
self._skills = _load_skills(skill_paths, skills, resource_extensions or DEFAULT_RESOURCE_EXTENSIONS)
Copy link

Copilot AI Mar 9, 2026

Choose a reason for hiding this comment

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

deps is stored on the SkillsProvider instance and passed by reference into every SkillContext. Since the API explicitly allows mutating ctx.deps, this makes dependency/state mutations global to the provider and potentially shared across concurrent sessions/runs. If this is intended, it should be documented clearly; otherwise consider supporting per-session/per-run deps (e.g., a deps_factory or storing deps in state) to avoid cross-request state bleed.

Copilot uses AI. Check for mistakes.
Copy link
Author

Choose a reason for hiding this comment

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

This is intended, deps implementer will take care of concurrency using Double-Checked Locking pattern etc.

Copy link
Author

Choose a reason for hiding this comment

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

@copilot open a new pull request to apply changes based on this feedback. Document that this is intended, deps implementer must take care of concurrency using Double-Checked Locking pattern etc.

Comment on lines +638 to 646
async def _read_skill_resource(self, skill_name: str, resource_name: str) -> str:
"""Read a named resource from a skill.

Resolves the resource by case-insensitive name lookup. Static
``content`` is returned directly; callable resources are invoked
(awaited if async).
(awaited if async). Resource functions that declare a
:class:`SkillContext` first parameter receive a context carrying
the provider's ``deps``.

Copy link

Copilot AI Mar 9, 2026

Choose a reason for hiding this comment

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

Changing SkillsProvider._read_skill_resource to no longer accept **kwargs removes the mechanism by which agent.run(..., **kwargs) runtime kwargs are forwarded into the read_skill_resource tool (via FunctionTool’s runtime kwargs forwarding). This is a breaking behavioral change for existing code-defined resources that relied on request-scoped kwargs (even if the tool schema didn’t declare them). Consider keeping **kwargs on _read_skill_resource for backward compatibility (and optionally exposing them via SkillContext, e.g., ctx.kwargs), or mark/document this as a breaking change and provide a migration path.

Copilot uses AI. Check for mistakes.
Copy link
Author

Choose a reason for hiding this comment

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

Use of **kwargs is not released as a package yet, so we may not want to keep it?

@suneetnangia
Copy link
Author

CC: @SergeyMenshykh

@suneetnangia suneetnangia marked this pull request as draft March 9, 2026 22:51
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

None yet

Development

Successfully merging this pull request may close these issues.

3 participants