Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,6 @@
# Bash scripts
*.sh text eol=lf
*.cmd text eol=crlf

# Dependency lockfiles are generated by uv.
**/uv.lock linguist-generated=true
4 changes: 2 additions & 2 deletions .github/actions/python-setup/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ runs:
version-file: "python/pyproject.toml"
enable-cache: true
cache-suffix: ${{ inputs.os }}-${{ inputs.python-version }}
cache-dependency-glob: "**/uv.lock"
cache-dependency-glob: "python/uv.lock"
- name: Exclude incompatible workspace packages
if: ${{ inputs.exclude-packages != '' }}
shell: bash
Expand All @@ -46,4 +46,4 @@ runs:
- name: Install the project
shell: bash
run: |
cd python && uv sync --all-packages --all-extras --all-groups --prerelease=if-necessary-or-explicit
cd python && uv sync --all-packages --all-extras --all-groups --prerelease=if-necessary
28 changes: 28 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,34 @@ updates:
cooldown:
default-days: 7

- package-ecosystem: "uv"
directory: "python/packages/lab/"
schedule:
interval: "weekly"
day: "thursday"
groups:
basics:
patterns:
- "uv"
- "ruff"
- "prek"
- "poethepoet"
- "tomli"
- "rich"
pytest:
patterns:
- "pytest*"
python-type-checkers:
patterns:
- "mypy"
- "pyright"
labels:
- "python"
- "lab"
- "dependencies"
cooldown:
default-days: 7

# Maintain dependencies for github-actions
- package-ecosystem: "github-actions"
# Cover both the standard workflow location and our composite actions.
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/python-dependency-maintenance.yml
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ jobs:
const prBody = [
"### Motivation & Context",
"",
"This automated update keeps Python dependency metadata coherent across the uv workspace. Python dependencies can be declared in multiple `pyproject.toml` files, but the workspace has one shared `python/uv.lock`, so dependency maintenance should update and validate them together instead of through per-manifest Dependabot PRs.",
"This automated update keeps dependency metadata coherent across the released Python uv workspace. Its packages share `python/uv.lock`, so dependency maintenance updates and validates them together instead of through per-manifest Dependabot PRs. The standalone Lab project maintains its dependencies separately.",
"",
"### Description & Review Guide",
"",
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/python-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
version-file: "python/pyproject.toml"
enable-cache: true
cache-suffix: ${{ runner.os }}-${{ env.UV_PYTHON }}
cache-dependency-glob: "**/uv.lock"
cache-dependency-glob: "python/uv.lock"
- name: Install dependencies
run: uv sync --all-packages --dev --docs
- name: Build the docs
Expand Down
54 changes: 24 additions & 30 deletions .github/workflows/python-lab-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ on:
branches: ["main"]
paths:
- "python/packages/lab/**"
- ".github/workflows/python-lab-tests.yml"
merge_group:
branches: ["main"]
schedule:
Expand All @@ -22,32 +23,24 @@ jobs:
contents: read
pull-requests: read
outputs:
pythonChanges: ${{ steps.filter.outputs.python}}
labChanges: ${{ steps.filter.outputs.lab }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: dorny/paths-filter@ceb8a2b8f2d89434be7ff52d3de7ec3738c5cc9d # v4.0.3
id: filter
with:
filters: |
python:
- 'python/**'
- '!python/AGENTS.md'
- '!python/**/AGENTS.md'
- '!python/.github/skills/*'
- '!python/.github/skills/**'
# run only if 'python' files were changed
- name: python tests
if: steps.filter.outputs.python == 'true'
run: echo "Python file"
# run only if not 'python' files were changed
- name: not python tests
if: steps.filter.outputs.python != 'true'
run: echo "NOT python file"
lab:
- 'python/packages/lab/**'
- '.github/workflows/python-lab-tests.yml'

python-lab-tests:
name: Python Lab Tests
needs: paths-filter
if: needs.paths-filter.outputs.pythonChanges == 'true'
if: >
github.event_name == 'workflow_dispatch' ||
github.event_name == 'schedule' ||
needs.paths-filter.outputs.labChanges == 'true'
runs-on: ${{ matrix.os }}
strategy:
fail-fast: true
Expand All @@ -61,36 +54,37 @@ jobs:
contents: read
defaults:
run:
working-directory: python
working-directory: python/packages/lab
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Set up python and install the project
id: python-setup
uses: ./.github/actions/python-setup
- name: Set up uv
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
version-file: "python/packages/lab/pyproject.toml"
python-version: ${{ matrix.python-version }}
os: ${{ runner.os }}
exclude-packages: ${{ matrix.python-version == '3.10' && 'agent-framework-github-copilot agent-framework-azure-cosmos-memory' || '' }}
env:
# Configure a constant location for the uv cache
UV_CACHE_DIR: /tmp/.uv-cache
enable-cache: true
cache-suffix: ${{ runner.os }}-${{ matrix.python-version }}
cache-dependency-glob: "python/packages/lab/uv.lock"

- name: Install the Lab project
run: uv sync --all-extras --all-groups --frozen --prerelease=if-necessary

# Lab specific tests
- name: Run lab tests
run: cd packages/lab && uv run poe test
run: uv run poe test

- name: Run resource-intensive lab tests
run: cd packages/lab && uv run pytest -m "resource_intensive and not integration" --junitxml=test-results-resource-intensive.xml
run: uv run pytest -m "resource_intensive and not integration" --junitxml=test-results-resource-intensive.xml

- name: Run lab lint
run: cd packages/lab && uv run poe lint
run: uv run poe lint

- name: Run lab format check
run: cd packages/lab && uv run poe fmt --check
run: uv run poe fmt --check

- name: Run lab type checking
run: cd packages/lab && uv run poe pyright
run: uv run poe pyright

# Surface failing tests
- name: Surface failing tests
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ Python

```bash
pip install agent-framework
# This will install all sub-packages, see `python/packages` for individual packages.
# This installs the standard package set; install `agent-framework-lab` separately for experimental modules.
# It may take a minute on first install on Windows.
```

Expand Down
65 changes: 65 additions & 0 deletions docs/decisions/0040-isolate-python-lab-workspace.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
---
status: accepted
contact: eavanvalkenburg
date: 2026-09-09
deciders: eavanvalkenburg, moonbox3
informed: chetantoshniwal, giles17, TaoChenOSU, jpalvarezl
---

# Isolate Python Lab from the released package workspace

## Context and Problem Statement

The Python root uv workspace resolves released packages and experimental Lab features in one universal lockfile.
Lab extras depend on Agent Lightning and Tau2, which currently require LiteLLM and OpenAI 2.x. That constraint prevents
the released Foundry package from using Azure AI Projects versions that require OpenAI 3.x, even though Lab is
developed and tested independently.

## Decision Drivers

- Keep experimental Lab dependencies from constraining released provider packages.
- Preserve reproducible Lab development and CI with a committed lockfile.
- Resolve Lab against released Core and provider distributions without root-workspace source overrides.
- Keep the standard `agent-framework[all]` installation free of experimental Lab modules.
- Avoid artificial uv conflict groups in the released workspace.

## Considered Options

### Keep Lab in the root workspace and cap Foundry

- Good: one environment and one lockfile.
- Bad: experimental dependencies determine the supported dependency range of released providers.
- Bad: the root workspace cannot exercise Foundry with OpenAI 3.x.

### Add mutually exclusive uv dependency groups

- Good: one lockfile can contain separate OpenAI 2.x and 3.x forks.
- Bad: requires an artificial OpenAI 3 group and explicit group switching.
- Bad: makes ordinary setup behavior depend on selecting the correct conflict branch.

### Give Lab a standalone uv project

- Good: released and experimental dependency graphs resolve independently.
- Good: Lab retains a reproducible environment and can keep its current LiteLLM and OpenAI 2.x stack.
- Good: Lab already has dedicated CI and is documented as outside `agent-framework[all]`.
- Bad: contributors and automation must run a separate Lab sync.
- Bad: the repository maintains two Python lockfiles.

## Decision Outcome

Chosen option: "Give Lab a standalone uv project", because it creates a direct dependency boundary without adding
selection rules to the released workspace.

The root workspace excludes `packages/lab`, and `agent-framework-core[all]` no longer installs
`agent-framework-lab`. Lab uses its own lockfile, uv cache key, CI installation, and dependency updates. It resolves
released Core and provider distributions so root-workspace metadata changes cannot stale the Lab lock.

### Consequences

- Root dependency resolution can select OpenAI 3.x and Azure AI Projects 2.6 without considering Lab extras.
- Lab continues to resolve LiteLLM and OpenAI 2.x until those dependencies add OpenAI 3.x support.
- Cross-package changes that require unreleased Core or provider APIs must land and release those dependencies before
updating Lab.
- Users install Lab explicitly with `pip install agent-framework-lab`.
- Root workspace validation and dependency maintenance do not include Lab.
- Lab-only dependency changes update `python/packages/lab/uv.lock`.
13 changes: 13 additions & 0 deletions python/.github/skills/python-package-management/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,19 @@ python/
├── packages/
│ ├── core/ # agent-framework-core (main package)
│ ├── foundry/ # agent-framework-foundry
│ ├── lab/ # Standalone uv project, excluded from the root workspace
│ ├── anthropic/ # agent-framework-anthropic
│ └── ... # Other connector packages
```

- `agent-framework-core` contains core abstractions and OpenAI/Azure OpenAI built-in
- Provider packages extend core with specific integrations
- Root `agent-framework` depends on `agent-framework-core[all]`
- `packages/lab` is intentionally excluded from the root uv workspace. It has its own
`pyproject.toml`, `uv.lock`, environment, CI matrix, and dependency updates so experimental
dependencies cannot constrain released provider packages. Lab is also an explicit exception
to the lifecycle rule that beta packages belong in `agent-framework-core[all]`. Lab resolves
released Core and provider distributions rather than local root-workspace packages.

## Dependency Management

Expand Down Expand Up @@ -62,6 +68,11 @@ uv run poe validate-dependency-bounds-project --mode upper --package "*"

# Add a dependency to one project and run both validators for that project/dependency
uv run poe add-dependency-and-validate-bounds --package core --dependency "<dependency-spec>"

# Work on the standalone Lab project
cd packages/lab
uv sync --all-extras --all-groups
uv run poe test
```

### Dependency Bound Notes
Expand All @@ -87,6 +98,8 @@ uv run poe add-dependency-and-validate-bounds --package core --dependency "<depe
expressed in published runtime metadata.
- Use `upgrade-dev-dependencies` for repo-wide development dependency refreshes; it repins exact dependencies
across development groups, refreshes `uv.lock`, and reruns `check`, `typing`, and `test`.
- Run Lab dependency and validation commands from `packages/lab`; root workspace tasks deliberately do not
discover or update the Lab project.

## Lazy Loading Pattern

Expand Down
1 change: 1 addition & 0 deletions python/.pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ repos:
name: Detect Private Keys
- id: check-added-large-files
name: Check Added Large Files
exclude: ^packages/lab/uv\.lock$
- id: no-commit-to-branch
name: Protect main branch
args: [--branch, main]
Expand Down
3 changes: 2 additions & 1 deletion python/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ python/
│ │ ├── agent_framework/ # Public API exports
│ │ └── tests/
│ ├── foundry/ # agent-framework-foundry
│ ├── lab/ # Standalone experimental Lab project
│ ├── anthropic/ # agent-framework-anthropic
│ ├── ollama/ # agent-framework-ollama
│ └── ... # Other provider packages
Expand Down Expand Up @@ -134,5 +135,5 @@ Durable Task and Azure Functions integrations are maintained in the [Durable Age
- [purview](packages/purview/AGENTS.md) - Data governance

### Experimental
- [lab](packages/lab/AGENTS.md) - Experimental features
- [lab](packages/lab/AGENTS.md) - Experimental features; standalone uv project with its own lockfile
- [monty](packages/monty/AGENTS.md) - Monty-backed CodeAct integrations (alpha)
13 changes: 11 additions & 2 deletions python/DEV_SETUP.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,14 @@ uv run poe setup -p 3.13

You can then run different commands through Poe the Poet, use `uv run poe` to discover which ones.

The root setup excludes the experimental Lab package. Lab has a separate environment and lockfile:

```bash
cd packages/lab
uv sync --all-extras --all-groups
uv run poe test
```

## VSCode Setup

Install the [Python extension](https://marketplace.visualstudio.com/items?itemName=ms-python.python) for VSCode.
Expand Down Expand Up @@ -244,12 +252,13 @@ Install all dependencies (including extras and dependency groups) from the lockf
uv run poe install
```
The root `dev` group contains shared tooling and source/type-check support. Package-specific test fixtures use
`test` groups, while dependencies needed for a locally executable optional feature may use a feature-named group
such as the lab package's `tau2` group.
`test` groups. The standalone Lab project keeps its own development and feature groups, including `tau2`, under
`packages/lab/pyproject.toml`.
For intentional dependency upgrades, run `uv lock --upgrade-package <dependency-name>` and then run `uv run poe install`.

For repo-wide development dependency refreshes, run `uv run poe upgrade-dev-dependencies` to repin exact
dependencies in development groups, refresh `uv.lock`, and rerun validation, typing, and tests.
This root task does not update Lab; use `uv lock --upgrade` from `packages/lab` or its dedicated Dependabot updates.

#### `venv`
Create a virtual environment with specified Python version or switch python version:
Expand Down
5 changes: 3 additions & 2 deletions python/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@ We recommend two common installation paths depending on your use case.

### 1. Development mode

If you are exploring or developing locally, install the entire framework with all sub-packages:
If you are exploring or developing locally, install the standard framework package set:

```bash
pip install agent-framework
```

This installs the core and every integration package, making sure that all features are available without additional steps. This is the simplest way to get started.
This installs the core and the standard integration packages. Experimental Lab modules are installed separately
with `pip install agent-framework-lab`.

### 2. Selective install

Expand Down
2 changes: 1 addition & 1 deletion python/packages/a2a/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ dependencies = [
]

[tool.uv]
prerelease = "if-necessary-or-explicit"
prerelease = "if-necessary"
environments = [
"sys_platform == 'darwin'",
"sys_platform == 'linux'",
Expand Down
2 changes: 1 addition & 1 deletion python/packages/anthropic/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ dependencies = [
]

[tool.uv]
prerelease = "if-necessary-or-explicit"
prerelease = "if-necessary"
environments = [
"sys_platform == 'darwin'",
"sys_platform == 'linux'",
Expand Down
2 changes: 1 addition & 1 deletion python/packages/azure-ai-search/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ dependencies = [
]

[tool.uv]
prerelease = "if-necessary-or-explicit"
prerelease = "if-necessary"
environments = [
"sys_platform == 'darwin'",
"sys_platform == 'linux'",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ dependencies = [
]

[tool.uv]
prerelease = "if-necessary-or-explicit"
prerelease = "if-necessary"
environments = [
"sys_platform == 'darwin'",
"sys_platform == 'linux'",
Expand Down
Loading
Loading