mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
Python: [BREAKING] Support code-defined agent skills (#4387)
* support code skills * address pr review comments * address package and syntax checks * address pr review comments * address pr review comment * address failed check * rename agentskill and agetnskillprovider * move agent skills related assets to _skills.py * address pr review comments * address review comments
This commit is contained in:
committed by
GitHub
Unverified
parent
5fb0cc106a
commit
4dad26fcae
@@ -59,7 +59,7 @@ from ._sessions import (
|
||||
register_state_type,
|
||||
)
|
||||
from ._settings import SecretString, load_settings
|
||||
from ._skills import FileAgentSkillsProvider
|
||||
from ._skills import Skill, SkillResource, SkillsProvider
|
||||
from ._telemetry import (
|
||||
AGENT_FRAMEWORK_USER_AGENT,
|
||||
APP_INFO,
|
||||
@@ -205,6 +205,9 @@ __all__ = [
|
||||
"AgentResponseUpdate",
|
||||
"AgentRunInputs",
|
||||
"AgentSession",
|
||||
"Skill",
|
||||
"SkillResource",
|
||||
"SkillsProvider",
|
||||
"Annotation",
|
||||
"BaseAgent",
|
||||
"BaseChatClient",
|
||||
@@ -234,7 +237,6 @@ __all__ = [
|
||||
"Executor",
|
||||
"FanInEdgeGroup",
|
||||
"FanOutEdgeGroup",
|
||||
"FileAgentSkillsProvider",
|
||||
"FileCheckpointStorage",
|
||||
"FinalT",
|
||||
"FinishReason",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
# Agent Skills Sample
|
||||
|
||||
This sample demonstrates how to use **Agent Skills** with a `FileAgentSkillsProvider` in the Microsoft Agent Framework.
|
||||
This sample demonstrates how to use **Agent Skills** with a `SkillsProvider` in the Microsoft Agent Framework.
|
||||
|
||||
## What are Agent Skills?
|
||||
|
||||
@@ -20,8 +20,8 @@ Policy-based expense filing with spending limits, receipt requirements, and appr
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
basic_skills/
|
||||
├── basic_file_skills.py
|
||||
basic_skill/
|
||||
├── basic_skill.py
|
||||
├── README.md
|
||||
└── skills/
|
||||
└── expense-report/
|
||||
@@ -52,7 +52,7 @@ This sample uses `AzureCliCredential` for authentication. Run `az login` in your
|
||||
|
||||
```bash
|
||||
cd python
|
||||
uv run samples/02-agents/skills/basic_skills/basic_file_skills.py
|
||||
uv run samples/02-agents/skills/basic_skill/basic_skill.py
|
||||
```
|
||||
|
||||
### Examples
|
||||
|
||||
@@ -4,18 +4,15 @@ import asyncio
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
from agent_framework import Agent, FileAgentSkillsProvider
|
||||
from agent_framework import Agent, SkillsProvider
|
||||
from agent_framework.azure import AzureOpenAIResponsesClient
|
||||
from azure.identity import AzureCliCredential
|
||||
from dotenv import load_dotenv
|
||||
|
||||
# Load environment variables from .env file
|
||||
load_dotenv()
|
||||
|
||||
"""
|
||||
Agent Skills Sample
|
||||
|
||||
This sample demonstrates how to use file-based Agent Skills with a FileAgentSkillsProvider.
|
||||
This sample demonstrates how to use file-based Agent Skills with a SkillsProvider.
|
||||
Agent Skills are modular packages of instructions and resources that extend an agent's
|
||||
capabilities. They follow the progressive disclosure pattern:
|
||||
|
||||
@@ -27,6 +24,9 @@ This sample includes the expense-report skill:
|
||||
- Policy-based expense filing with references and assets
|
||||
"""
|
||||
|
||||
# Load environment variables from .env file
|
||||
load_dotenv()
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
"""Run the Agent Skills demo."""
|
||||
@@ -44,7 +44,7 @@ async def main() -> None:
|
||||
# --- 2. Create the skills provider ---
|
||||
# Discovers skills from the 'skills' directory and makes them available to the agent
|
||||
skills_dir = Path(__file__).parent / "skills"
|
||||
skills_provider = FileAgentSkillsProvider(skill_paths=str(skills_dir))
|
||||
skills_provider = SkillsProvider(skill_paths=str(skills_dir))
|
||||
|
||||
# --- 3. Create the agent with skills ---
|
||||
async with Agent(
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
# Code-Defined Agent Skills Sample
|
||||
|
||||
This sample demonstrates how to create **Agent Skills** in Python code, without needing `SKILL.md` files on disk.
|
||||
|
||||
## What are Code-Defined Skills?
|
||||
|
||||
While file-based skills use `SKILL.md` files discovered on disk, code-defined skills let you define skills entirely in Python using `Skill` and `SkillResource` classes. Two patterns are shown:
|
||||
|
||||
1. **Basic Code Skill** — Create a `Skill` directly with static resources (inline content)
|
||||
2. **Dynamic Resources** — Attach callable resources via the `@skill.resource` decorator that generate content at invocation time
|
||||
|
||||
Both patterns can be combined with file-based skills in a single `SkillsProvider`.
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
code_skill/
|
||||
├── code_skill.py
|
||||
└── README.md
|
||||
```
|
||||
|
||||
## Running the Sample
|
||||
|
||||
### Prerequisites
|
||||
- An [Azure AI Foundry](https://ai.azure.com/) project with a deployed model (e.g. `gpt-4o-mini`)
|
||||
|
||||
### Environment Variables
|
||||
|
||||
Set the required environment variables in a `.env` file (see `python/.env.example`):
|
||||
|
||||
- `AZURE_AI_PROJECT_ENDPOINT`: Your Azure AI Foundry project endpoint
|
||||
- `AZURE_OPENAI_RESPONSES_DEPLOYMENT_NAME`: The name of your model deployment (defaults to `gpt-4o-mini`)
|
||||
|
||||
### Authentication
|
||||
|
||||
This sample uses `AzureCliCredential` for authentication. Run `az login` in your terminal before running the sample.
|
||||
|
||||
### Run
|
||||
|
||||
```bash
|
||||
cd python
|
||||
uv run samples/02-agents/skills/code_skill/code_skill.py
|
||||
```
|
||||
|
||||
### Examples
|
||||
|
||||
The sample runs two examples:
|
||||
|
||||
1. **Code style question** — Uses Pattern 1 (static resources): the agent loads the `code-style` skill and reads the `style-guide` resource to answer naming convention questions
|
||||
2. **Project info question** — Uses Pattern 2 (dynamic resources): the agent reads dynamically generated `environment` and `team-roster` resources
|
||||
|
||||
## Learn More
|
||||
|
||||
- [Agent Skills Specification](https://agentskills.io/)
|
||||
- [File-based Skills Sample](../basic_skill/)
|
||||
- [Microsoft Agent Framework Documentation](../../../../../docs/)
|
||||
@@ -0,0 +1,151 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
import sys
|
||||
from textwrap import dedent
|
||||
|
||||
from agent_framework import Agent, Skill, SkillResource, SkillsProvider
|
||||
from agent_framework.azure import AzureOpenAIResponsesClient
|
||||
from azure.identity import AzureCliCredential
|
||||
from dotenv import load_dotenv
|
||||
|
||||
"""
|
||||
Code-Defined Agent Skills — Define skills in Python code
|
||||
|
||||
This sample demonstrates how to create Agent Skills in code,
|
||||
without needing SKILL.md files on disk. Two patterns are shown:
|
||||
|
||||
Pattern 1: Basic Code Skill
|
||||
Create a Skill instance directly with static resources (inline content).
|
||||
|
||||
Pattern 2: Dynamic Resources
|
||||
Create a Skill and attach callable resources via the @skill.resource
|
||||
decorator. Resources can be sync or async functions that generate content at
|
||||
invocation time.
|
||||
|
||||
Both patterns can be combined with file-based skills in a single SkillsProvider.
|
||||
"""
|
||||
|
||||
# Load environment variables from .env file
|
||||
load_dotenv()
|
||||
|
||||
# Pattern 1: Basic Code Skill — direct construction with static resources
|
||||
code_style_skill = Skill(
|
||||
name="code-style",
|
||||
description="Coding style guidelines and conventions for the team",
|
||||
content=dedent("""\
|
||||
Use this skill when answering questions about coding style, conventions,
|
||||
or best practices for the team.
|
||||
"""),
|
||||
resources=[
|
||||
SkillResource(
|
||||
name="style-guide",
|
||||
content=dedent("""\
|
||||
# Team Coding Style Guide
|
||||
|
||||
## General Rules
|
||||
- Use 4-space indentation (no tabs)
|
||||
- Maximum line length: 120 characters
|
||||
- Use type annotations on all public functions
|
||||
- Use Google-style docstrings
|
||||
|
||||
## Naming Conventions
|
||||
- Classes: PascalCase (e.g., UserAccount)
|
||||
- Functions/methods: snake_case (e.g., get_user_name)
|
||||
- Constants: UPPER_SNAKE_CASE (e.g., MAX_RETRIES)
|
||||
- Private members: prefix with underscore (e.g., _internal_state)
|
||||
"""),
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
# Pattern 2: Dynamic Resources — @skill.resource decorator
|
||||
project_info_skill = Skill(
|
||||
name="project-info",
|
||||
description="Project status and configuration information",
|
||||
content=dedent("""\
|
||||
Use this skill for questions about the current project status,
|
||||
environment configuration, or team structure.
|
||||
"""),
|
||||
)
|
||||
|
||||
|
||||
@project_info_skill.resource
|
||||
def environment() -> str:
|
||||
"""Get current environment configuration."""
|
||||
env = os.environ.get("APP_ENV", "development")
|
||||
region = os.environ.get("APP_REGION", "us-east-1")
|
||||
return f"""\
|
||||
# Environment Configuration
|
||||
- Environment: {env}
|
||||
- Region: {region}
|
||||
- Python: {sys.version}
|
||||
"""
|
||||
|
||||
|
||||
@project_info_skill.resource(name="team-roster", description="Current team members and roles")
|
||||
def get_team_roster() -> str:
|
||||
"""Return the team roster."""
|
||||
return """\
|
||||
# Team Roster
|
||||
| Name | Role |
|
||||
|--------------|-------------------|
|
||||
| Alice Chen | Tech Lead |
|
||||
| Bob Smith | Backend Engineer |
|
||||
| Carol Davis | Frontend Engineer |
|
||||
"""
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
"""Run the code-defined skills demo."""
|
||||
endpoint = os.environ["AZURE_AI_PROJECT_ENDPOINT"]
|
||||
deployment = os.environ.get("AZURE_OPENAI_RESPONSES_DEPLOYMENT_NAME", "gpt-4o-mini")
|
||||
|
||||
client = AzureOpenAIResponsesClient(
|
||||
project_endpoint=endpoint,
|
||||
deployment_name=deployment,
|
||||
credential=AzureCliCredential(),
|
||||
)
|
||||
|
||||
# Create the skills provider with both code-defined skills
|
||||
skills_provider = SkillsProvider(
|
||||
skills=[code_style_skill, project_info_skill],
|
||||
)
|
||||
|
||||
async with Agent(
|
||||
client=client,
|
||||
instructions="You are a helpful assistant for our development team.",
|
||||
context_providers=[skills_provider],
|
||||
) as agent:
|
||||
# Example 1: Code style question (Pattern 1 — static resources)
|
||||
print("Example 1: Code style question")
|
||||
print("-------------------------------")
|
||||
response = await agent.run("What naming convention should I use for class attributes?")
|
||||
print(f"Agent: {response}\n")
|
||||
|
||||
# Example 2: Project info question (Pattern 2 — dynamic resources)
|
||||
print("Example 2: Project info question")
|
||||
print("---------------------------------")
|
||||
response = await agent.run("What environment are we running in and who is on the team?")
|
||||
print(f"Agent: {response}\n")
|
||||
|
||||
"""
|
||||
Expected output:
|
||||
|
||||
Example 1: Code style question
|
||||
-------------------------------
|
||||
Agent: Based on our team's coding style guide, class attributes should follow
|
||||
snake_case naming. Private attributes use an underscore prefix (_internal_state).
|
||||
Constants use UPPER_SNAKE_CASE (MAX_RETRIES).
|
||||
|
||||
Example 2: Project info question
|
||||
---------------------------------
|
||||
Agent: We're running in the development environment in us-east-1.
|
||||
The team consists of Alice Chen (Tech Lead), Bob Smith (Backend Engineer),
|
||||
and Carol Davis (Frontend Engineer).
|
||||
"""
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
Reference in New Issue
Block a user