Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
8acfed1
python: replace pre-commit with prek, add PEP 723 script deps, clean …
eavanvalkenburg Feb 7, 2026
6aba4d5
updated lock
eavanvalkenburg Feb 7, 2026
7210652
python: fix prek config paths for local execution and CI workflow
eavanvalkenburg Feb 7, 2026
99974a4
python: move helper scripts to scripts/ folder and exclude from checks
eavanvalkenburg Feb 7, 2026
eaae69e
python: exclude AGENTS.md from prek markdown code lint
eavanvalkenburg Feb 7, 2026
37ec19a
python: exclude AGENTS.md and azure_ai_search sample from markdown lint
eavanvalkenburg Feb 7, 2026
7def4d6
fix m365 sample
eavanvalkenburg Feb 7, 2026
7141951
python: ignore CPY rule for samples with PEP 723 headers
eavanvalkenburg Feb 7, 2026
a4a3e3c
fix in dev_setup
eavanvalkenburg Feb 7, 2026
9429cd3
python: replace aiofiles with regular open in samples
eavanvalkenburg Feb 7, 2026
8288f99
python: suppress reportUnusedImport in markdown code block checker
eavanvalkenburg Feb 7, 2026
b6b4c48
python: use samples pyright config for markdown code block checker
eavanvalkenburg Feb 7, 2026
7a96ea2
python: use markdown-code-lint with fixed globs instead of prek file …
eavanvalkenburg Feb 7, 2026
8753412
python: exclude READMEs with pre-existing broken imports from markdow…
eavanvalkenburg Feb 7, 2026
63c2566
python: fix broken README code snippets instead of excluding them
eavanvalkenburg Feb 7, 2026
a9a247f
add revision to gaia download
eavanvalkenburg Feb 9, 2026
db0354a
feat(python): parallelize checks across packages
eavanvalkenburg Feb 9, 2026
2b9eb2a
feat(ci): split code quality into 4 parallel jobs
eavanvalkenburg Feb 9, 2026
8f7a5e0
feat(ci): use only Python 3.10 for code quality checks
eavanvalkenburg Feb 9, 2026
0a3494c
refactor(python): add future annotations and remove quoted types
eavanvalkenburg Feb 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 99 additions & 9 deletions .github/workflows/python-code-quality.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ env:
UV_CACHE_DIR: /tmp/.uv-cache

jobs:
pre-commit:
name: Checks
pre-commit-hooks:
name: Pre-commit Hooks
if: "!cancelled()"
strategy:
fail-fast: false
matrix:
python-version: ["3.10", "3.14"]
python-version: ["3.10"]
runs-on: ubuntu-latest
continue-on-error: true
defaults:
Expand All @@ -37,16 +37,106 @@ jobs:
python-version: ${{ matrix.python-version }}
os: ${{ runner.os }}
env:
# Configure a constant location for the uv cache
UV_CACHE_DIR: /tmp/.uv-cache
- uses: actions/cache@v5
with:
path: ~/.cache/pre-commit
key: pre-commit|${{ matrix.python-version }}|${{ hashFiles('python/.pre-commit-config.yaml') }}
- uses: pre-commit/action@v3.0.1
name: Run Pre-Commit Hooks
path: ~/.cache/prek
key: prek|${{ matrix.python-version }}|${{ hashFiles('python/.pre-commit-config.yaml') }}
- uses: j178/prek-action@v1
name: Run Pre-commit Hooks (excluding poe-check)
env:
SKIP: poe-check
with:
extra_args: --config python/.pre-commit-config.yaml --all-files
extra-args: --cd python --all-files

package-checks:
name: Package Checks
if: "!cancelled()"
strategy:
fail-fast: false
matrix:
python-version: ["3.10"]
runs-on: ubuntu-latest
continue-on-error: true
defaults:
run:
working-directory: ./python
env:
UV_PYTHON: ${{ matrix.python-version }}
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Set up python and install the project
id: python-setup
uses: ./.github/actions/python-setup
with:
python-version: ${{ matrix.python-version }}
os: ${{ runner.os }}
env:
UV_CACHE_DIR: /tmp/.uv-cache
- name: Run fmt, lint, pyright in parallel across packages
run: uv run poe check-packages

samples-markdown:
name: Samples & Markdown
if: "!cancelled()"
strategy:
fail-fast: false
matrix:
python-version: ["3.10"]
runs-on: ubuntu-latest
continue-on-error: true
defaults:
run:
working-directory: ./python
env:
UV_PYTHON: ${{ matrix.python-version }}
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Set up python and install the project
id: python-setup
uses: ./.github/actions/python-setup
with:
python-version: ${{ matrix.python-version }}
os: ${{ runner.os }}
env:
UV_CACHE_DIR: /tmp/.uv-cache
- name: Run samples lint
run: uv run poe samples-lint
- name: Run samples syntax check
run: uv run poe samples-syntax
- name: Run markdown code lint
run: uv run poe markdown-code-lint

mypy:
name: Mypy Checks
if: "!cancelled()"
strategy:
fail-fast: false
matrix:
python-version: ["3.10"]
runs-on: ubuntu-latest
continue-on-error: true
defaults:
run:
working-directory: ./python
env:
UV_PYTHON: ${{ matrix.python-version }}
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Set up python and install the project
id: python-setup
uses: ./.github/actions/python-setup
with:
python-version: ${{ matrix.python-version }}
os: ${{ runner.os }}
env:
UV_CACHE_DIR: /tmp/.uv-cache
- name: Run Mypy
env:
GITHUB_BASE_REF: ${{ github.event.pull_request.base.ref || github.base_ref || 'main' }}
Expand Down
43 changes: 26 additions & 17 deletions python/.pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,59 +1,68 @@
files: ^python/
fail_fast: true
exclude: ^scripts/
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
- repo: builtin
hooks:
- id: check-toml
name: Check TOML files
files: \.toml$
exclude: ^python/packages/lab/cookiecutter-agent-framework-lab/
exclude: ^packages/lab/cookiecutter-agent-framework-lab/
- id: check-yaml
name: Check YAML files
files: \.yaml$
- id: check-json
name: Check JSON files
files: \.json$
exclude: ^.*\.vscode\/.*|^python/demos/samples/chatkit-integration/frontend/(tsconfig.*\.json|package-lock\.json)$
exclude: ^.*\.vscode\/.*|^demos/samples/chatkit-integration/frontend/(tsconfig.*\.json|package-lock\.json)$
- id: end-of-file-fixer
name: Fix End of File
files: \.py$
exclude: ^python/packages/lab/cookiecutter-agent-framework-lab/
exclude: ^packages/lab/cookiecutter-agent-framework-lab/
- id: mixed-line-ending
name: Check Mixed Line Endings
files: \.py$
exclude: ^python/packages/lab/cookiecutter-agent-framework-lab/
exclude: ^packages/lab/cookiecutter-agent-framework-lab/
- id: trailing-whitespace
name: Trim Trailing Whitespace
exclude: ^packages/lab/cookiecutter-agent-framework-lab/
- id: check-merge-conflict
name: Check Merge Conflicts
- id: detect-private-key
name: Detect Private Keys
- id: check-added-large-files
name: Check Added Large Files
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
hooks:
- id: check-ast
name: Check Valid Python Samples
types: ["python"]
exclude: ^python/packages/lab/cookiecutter-agent-framework-lab/
exclude: ^packages/lab/cookiecutter-agent-framework-lab/
- repo: https://github.com/asottile/pyupgrade
rev: v3.20.0
rev: v3.21.2
hooks:
- id: pyupgrade
name: Upgrade Python syntax
args: [--py310-plus]
exclude: ^python/packages/lab/cookiecutter-agent-framework-lab/
exclude: ^packages/lab/cookiecutter-agent-framework-lab/
- repo: local
hooks:
- id: poe-check
name: Run checks through Poe
entry: uv --directory ./python run poe pre-commit-check
entry: uv run poe prek-check
language: system
files: ^python/
- repo: https://github.com/PyCQA/bandit
rev: 1.8.5
rev: 1.9.3
hooks:
- id: bandit
name: Bandit Security Checks
args: ["-c", "python/pyproject.toml"]
args: ["-c", "pyproject.toml"]
additional_dependencies: ["bandit[toml]"]
- repo: https://github.com/astral-sh/uv-pre-commit
# uv version.
rev: 0.7.18
rev: 0.10.0
hooks:
# Update the uv lockfile
- id: uv-lock
name: Update uv lockfile
files: python/pyproject.toml
args: [--project, python]
files: pyproject.toml
2 changes: 1 addition & 1 deletion python/.vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"command": "uv",
"args": [
"run",
"pre-commit",
"prek",
"run",
"-a"
],
Expand Down
17 changes: 2 additions & 15 deletions python/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,22 +61,9 @@ from agent_framework.azure import AzureOpenAIChatClient, AzureAIAgentClient
- **Comments**: Avoid excessive comments; prefer clear code
- **Formatting**: Format only files you changed, not the entire codebase

## Sample Structure
## Samples

1. Copyright header: `# Copyright (c) Microsoft. All rights reserved.`
2. Required imports
3. Module docstring: `"""This sample demonstrates..."""`
4. Helper functions
5. Main function(s) demonstrating functionality
6. Entry point: `if __name__ == "__main__": asyncio.run(main())`

When modifying samples, update associated README files in the same or parent folders.

### Samples Syntax Checking

Run `uv run poe samples-syntax` to check samples for syntax errors and missing imports from `agent_framework`. This uses a relaxed pyright configuration that validates imports without strict type checking.

Some samples depend on external packages (e.g., `azure.ai.agentserver.agentframework`, `microsoft_agents`) that are not installed in the dev environment. These are excluded in `pyrightconfig.samples.json`. When adding or modifying these excluded samples, add them to the exclude list and manually verify they have no import errors from `agent_framework` packages by temporarily removing them from the exclude list and running the check.
See [samples/SAMPLE_GUIDELINES.md](samples/SAMPLE_GUIDELINES.md) for sample structure, external dependency handling (PEP 723), and syntax checking instructions.

## Package Documentation

Expand Down
7 changes: 7 additions & 0 deletions python/CODING_STANDARD.md
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,13 @@ After the package has been released and gained a measure of confidence:
2. Add the package to the `[all]` extra in `packages/core/pyproject.toml`
3. Create a provider folder in `agent_framework/` with lazy loading `__init__.py`

### Versioning and Core Dependency

All non-core packages declare a lower bound on `agent-framework-core` (e.g., `"agent-framework-core>=1.0.0b260130"`). Follow these rules when bumping versions:

- **Core version changes**: When `agent-framework-core` is updated with breaking or significant changes and its version is bumped, update the `agent-framework-core>=...` lower bound in every other package's `pyproject.toml` to match the new core version.
- **Non-core version changes**: Non-core packages (connectors, extensions) can have their own versions incremented independently while keeping the existing core lower bound pinned. Only raise the core lower bound if the non-core package actually depends on new core APIs.

### Installation Options

Connectors are distributed as separate packages and are not imported by default in the core package. Users install the specific connectors they need:
Expand Down
44 changes: 25 additions & 19 deletions python/DEV_SETUP.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,11 @@ uv venv --python $PYTHON_VERSION
uv sync --dev
# Install all the tools and dependencies
uv run poe install
# Install pre-commit hooks
uv run poe pre-commit-install
# Install prek hooks
uv run poe prek-install
```

Alternatively, you can reinstall the venv, pacakges, dependencies and pre-commit hooks with a single command (but this requires poe in the current env), this is especially useful if you want to switch python versions:
Alternatively, you can reinstall the venv, pacakges, dependencies and prek hooks with a single command (but this requires poe in the current env), this is especially useful if you want to switch python versions:

```bash
uv run poe setup -p 3.13
Expand Down Expand Up @@ -144,7 +144,7 @@ To run the same checks that run during a commit and the GitHub Action `Python Co
uv run poe check
```

Ideally you should run these checks before committing any changes, when you install using the instructions above the pre-commit hooks should be installed already.
Ideally you should run these checks before committing any changes, when you install using the instructions above the prek hooks should be installed already.

## Code Coverage

Expand Down Expand Up @@ -196,10 +196,10 @@ and then you can run the following tasks:
uv sync --all-extras --dev
```

After this initial setup, you can use the following tasks to manage your development environment. It is advised to use the following setup command since that also installs the pre-commit hooks.
After this initial setup, you can use the following tasks to manage your development environment. It is advised to use the following setup command since that also installs the prek hooks.

#### `setup`
Set up the development environment with a virtual environment, install dependencies and pre-commit hooks:
Set up the development environment with a virtual environment, install dependencies and prek hooks:
```bash
uv run poe setup
# or with specific Python version
Expand All @@ -220,36 +220,36 @@ uv run poe venv
uv run poe venv --python 3.12
```

#### `pre-commit-install`
Install pre-commit hooks:
#### `prek-install`
Install prek hooks:
```bash
uv run poe pre-commit-install
uv run poe prek-install
```

### Code Quality and Formatting

Each of the following tasks are designed to run against both the main `agent-framework` package and the extension packages, ensuring consistent code quality across the project.
Each of the following tasks run against both the main `agent-framework` package and the extension packages in parallel, ensuring consistent code quality across the project.

#### `fmt` (format)
Format code using ruff:
Format code using ruff (runs in parallel across all packages):
```bash
uv run poe fmt
```

#### `lint`
Run linting checks and fix issues:
Run linting checks and fix issues (runs in parallel across all packages):
```bash
uv run poe lint
```

#### `pyright`
Run Pyright type checking:
Run Pyright type checking (runs in parallel across all packages):
```bash
uv run poe pyright
```

#### `mypy`
Run MyPy type checking:
Run MyPy type checking (runs in parallel across all packages):
```bash
uv run poe mypy
```
Expand All @@ -270,16 +270,22 @@ uv run poe markdown-code-lint

### Comprehensive Checks

#### `check-packages`
Run all package-level quality checks (format, lint, pyright, mypy) in parallel across all packages. This runs the full cross-product of (package × check) concurrently:
```bash
uv run poe check-packages
```

#### `check`
Run all quality checks (format, lint, pyright, mypy, test, markdown lint):
Run all quality checks including package checks, samples, tests and markdown lint:
```bash
uv run poe check
```

### Testing

#### `test`
Run unit tests with coverage by invoking the `test` task in each package sequentially:
Run unit tests with coverage by invoking the `test` task in each package in parallel:
```bash
uv run poe test
```
Expand Down Expand Up @@ -325,10 +331,10 @@ Publish packages to PyPI:
uv run poe publish
```

## Pre-commit Hooks
## Prek Hooks

Pre-commit hooks run automatically on commit and execute a subset of the checks on changed files only. You can also run all checks using pre-commit directly:
Prek hooks run automatically on commit and execute a subset of the checks on changed files only. Package-level checks (fmt, lint, pyright) run in parallel but only for packages with changed files. Markdown and sample checks are skipped when no relevant files were changed. If the `core` package is changed, all packages are checked. You can also run all checks using prek directly:

```bash
uv run pre-commit run -a
uv run prek run -a
```
4 changes: 2 additions & 2 deletions python/devsetup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ uv venv --python $PYTHON_VERSION
uv sync --dev
# Install all the tools and dependencies
uv run poe install
# Install pre-commit hooks
uv run poe pre-commit-install
# Install prek hooks
uv run poe prek-install
Loading
Loading