Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Guide for managing packages in the Agent Framework Python monorepo, including creating new connector packages, versioning, and the lazy-loading pattern. Use this when adding, modifying, or releasing packages.
.claude/skills/microsoft-python-package-management/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 99% | 0% |
| case-13 | ✗→✓ | ▲ Improved | 131% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 81% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 94% | 0% |
| case-04 | ✗→✓ | ▲ Improved | 188% | 0% |
python/
├── pyproject.toml # Root package (agent-framework)
├── packages/
│ ├── core/ # agent-framework-core (main package)
│ ├── foundry/ # agent-framework-foundry
│ ├── anthropic/ # agent-framework-anthropic
│ └── ... # Other connector packagesagent-framework-core contains core abstractions and OpenAI/Azure OpenAI built-inagent-framework depends on agent-framework-core[all]Uses uv for dependency management and poethepoet for task automation.
bash# Full setup (venv + install + prek hooks) uv run poe setup # Install dependencies from lockfile (frozen resolution with prerelease policy) uv run poe install # Create venv with specific Python version uv run poe venv --python 3.12 # Intentionally upgrade a specific dependency to reduce lockfile conflicts uv lock --upgrade-package <dependency-name> && uv run poe install # Refresh exact development dependency-group pins, lockfile, and validation in one run uv run poe upgrade-dev-dependencies # Release cuts: refresh uv.lock and probe changed packages at both bound extremes. # The release probe has a shared five-minute deadline. uv run poe validate-python-release --base-ref upstream/main # Exhaustive test+typing matrix (slow; use for deliberate dependency-range work or CI) uv run poe validate-dependency-bounds-test # Defaults to --package "*"; scope locally whenever possible. uv run poe validate-dependency-bounds-test --package core # Then expand bounds for one dependency in the target package uv run poe validate-dependency-bounds-project --mode both --package core --dependency "<dependency-name>" # Repo-wide automation can reuse the same task 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>"
>=1.0) should typically be bounded as >=<known-good>,<next-major>.dev/a/b/rc) and <1.0 dependencies should use hard bounds with an explicit upper cap (avoid open-ended ranges).<1.0 dependencies, prefer the broadest validated range the package can really support. That may be a patch line, a minor line, or multiple minor lines when checks/tests show the broader lane is compatible.validate-python-release. It refreshesuv.lock, finds changed package metadata relative to the selected main ref, and runs the changed packages' published runtime dependencies and non-development extras through lock-independent lowest-direct and highest import probes on the minimum Python minor supported by each package's internal editable closure. The probes run concurrently under one 300-second deadline; pass --python only when an explicit interpreter override is needed.
validate-dependency-bounds-project --mode both for the target package/dependency to find and validate the actual minimum and maximum constraints. Scope the exhaustive validate-dependency-bounds-test matrix to affected packages during local iteration; reserve the workspace-wide form for CI or an intentional full audit. The same project task can drive repo-wide upper-bound automation by using --package "*" and omitting --dependency.
uv lock --upgrade-package <dependency-name> to reduce uv.lock merge conflicts.add-dependency-and-validate-bounds for package-scoped dependency additions plus bound validation in one command.dev group. Put package-specific testfixtures in a test group, and use a feature-named group for local-only executable dependencies that cannot be expressed in published runtime metadata.
upgrade-dev-dependencies for repo-wide development dependency refreshes; it repins exact dependenciesacross development groups, refreshes uv.lock, and reruns check, typing, and test.
The root agent_framework package is a lazy public API surface:
packages/core/agent_framework/__init__.py.packages/core/agent_framework/__init__.pyi._LAZY_MODULE_EXPORTS, keep the explicit runtime __all__ in sync, and add the samesymbol to the .pyi file.
__getattr__ that warns and returnsthe deprecated alias). Do not add one-off deprecated-symbol branches to root __getattr__.
uv run poe syntax -P core, uv run poe pyright -P core, and import smoke testsfor both from agent_framework import <symbol> and from agent_framework import *.
Provider folders in core use __getattr__ to lazy load from connector packages:
python# In agent_framework/foundry/__init__.py _IMPORTS: dict[str, tuple[str, str]] = { "FoundryChatClient": ("agent_framework_foundry", "agent-framework-foundry"), } def __getattr__(name: str) -> Any: if name in _IMPORTS: import_path, package_name = _IMPORTS[name] try: return getattr(importlib.import_module(import_path), name) except ModuleNotFoundError as exc: raise ModuleNotFoundError( f"The package {package_name} is required to use `{name}`. " f"Install it with: pip install {package_name}" ) from exc
Important: Do not create a new package unless approved by the core team.
Every new package starts as alpha.
packages/ (e.g., packages/my-connector/)tool.uv.sources in root pyproject.toml1.0.0a<date>Development Status :: 3 - Alphapackages/my-connector/samples/)[all] extra in packages/core/pyproject.tomlpython/PACKAGE_STATUS.md and keep that file updated when packages are added,removed, renamed, or promoted. If the package exposes individually staged APIs, keep the feature list there current too.
Recommended dependency workflow during connector implementation:
uv run poe add-dependency-to-project --package core --dependency "<dependency-spec>"
uv run poe validate-dependency-bounds-project --mode both --package core --dependency "<dependency-name>"
uv run poe add-dependency-and-validate-bounds --package core --dependency "<dependency-spec>" If compatibility checks are not in place yet, add the dependency first, then implement tests before running bound validation.
Promotion work is not isolated to the package being promoted. If a promotion changes dependency metadata for downstream packages, also update the dependent packages' own versions so they publish new metadata alongside the promoted dependency bounds. Apply the internal package dependency update rules from the versioning section below during promotions as well as standalone version update work.
Move a package to beta when it is stable enough to be part of the main install surface.
1.0.0b<date>Development Status :: 4 - Beta[all] in packages/core/pyproject.tomlsamples/ tree and remove package-local samplespython/PACKAGE_STATUS.mdAfter alpha, there should be no samples left inside a package folder.
Move a package to rc when its API is close to the final released shape.
1.0.0rc<number>Development Status :: 4 - Beta because PyPI does not have a separaterelease-candidate classifier
core[all]samples/ treepython/PACKAGE_STATUS.md to show the package as rcMove a package to released when it no longer carries a prerelease qualifier.
1.0.0Development Status :: 5 - Production/Stablecore[all]samples/ treepython/PACKAGE_STATUS.md to show the package as releasedREADME.md files that install that package withpip install agent-framework-... --pre so they use pip install agent-framework-... without the --pre suffix
declaration when the work on package B actually affects package A.
declaration unchanged.
declaration to the version or versioning scheme that matches what package A now requires.
declaration to the new versioning scheme for package B even when the only change is the stage transition itself.
agent-framework-coredependent package's own version in the correct lifecycle pattern for its current stage
alpha: 1.0.0a<date> where <date> is the current Pacific (US west coast) YYMMDDbeta: 1.0.0b<date> where <date> is the current Pacific (US west coast) YYMMDDrc: 1.0.0rc<number> where <number> increments only when the package has changesreleased: X.Y.Z using semver per packagetimezone. Same-Pacific-day re-cuts use a .postN suffix. Honor an explicit user-provided date over this default.
Development Status classifier in pyproject.toml aligned with the lifecycle stage:alpha -> Development Status :: 3 - Alphabeta -> Development Status :: 4 - Betarc -> Development Status :: 4 - Betareleased -> Development Status :: 5 - Production/Stablehttps://pypi.org/classifiers/
bashpip install agent-framework-core # Core only pip install agent-framework-core[all] # Core + all connectors pip install agent-framework # Same as core[all] pip install agent-framework-foundry # Specific connector (pulls in core)
When changing a package, check if its AGENTS.md needs updates:
Keep python/PACKAGE_STATUS.md updated when:
When a package adds, removes, or renames environment variables, update the related documentation in the same change:
README.md for package-level configuration/env var guidancesamples/README.md if the package is included in packages/core/pyproject.toml [all] and the env var ispart of the consolidated package env-var inventory
.env.example, .env.template, or sample README files when sample setupchanges alongside the package
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→pass | 20,039 | 18,056 | -10% | 1 | 1 | 0% | 3,169 | 6,314 | +99% | 0 | 0 | — |
case-13 | fail→pass | 11,709 | 6,362 | -46% | 1 | 1 | 0% | 1,906 | 4,403 | +131% | 0 | 0 | — |
case-02 | fail→pass | 21,835 | 13,416 | -39% | 1 | 1 | 0% | 3,413 | 6,183 | +81% | 0 | 0 | — |
case-03 | fail→pass | 16,805 | 10,037 | -40% | 1 | 1 | 0% | 2,714 | 5,263 | +94% | 0 | 0 | — |
case-04 | fail→pass | 7,925 | 5,482 | -31% | 1 | 1 | 0% | 1,525 | 4,398 | +188% | 0 | 0 | — |
case-05 | fail→pass | 8,153 | 5,878 | -28% | 1 | 1 | 0% | 1,587 | 4,412 | +178% | 0 | 0 | — |
case-06 | pass→pass | 16,876 | 6,880 | -59% | 1 | 1 | 0% | 3,133 | 4,533 | +45% | 0 | 0 | — |
case-11 | pass→pass | 12,235 | 2,787 | -77% | 1 | 1 | 0% | 2,097 | 3,709 | +77% | 0 | 0 | — |
case-07 | fail→pass | 8,539 | 1,905 | -78% | 1 | 1 | 0% | 1,339 | 3,486 | +160% | 0 | 0 | — |
case-08 | fail→pass | 16,846 | 2,040 | -88% | 1 | 1 | 0% | 3,083 | 3,613 | +17% | 0 | 0 | — |
case-09 | fail→pass | 42,881 | 2,357 | -95% | 1 | 1 | 0% | 7,233 | 3,698 | -49% | 0 | 0 | — |
case-10 | fail→pass | 12,173 | 7,755 | -36% | 1 | 1 | 0% | 1,929 | 4,744 | +146% | 0 | 0 | — |
case-12 | pass→pass | 11,325 | 2,546 | -78% | 1 | 1 | 0% | 1,987 | 3,696 | +86% | 0 | 0 | — |
case-14 | fail→pass | 10,590 | 2,649 | -75% | 1 | 1 | 0% | 1,702 | 3,628 | +113% | 0 | 0 | — |
case-15 | fail→pass | 9,411 | 5,059 | -46% | 1 | 1 | 0% | 1,557 | 4,145 | +166% | 0 | 0 | — |
case-16 | fail→pass | 12,410 | 4,722 | -62% | 1 | 1 | 0% | 2,102 | 4,127 | +96% | 0 | 0 | — |
case-17 | fail→pass | 10,231 | 3,012 | -71% | 1 | 1 | 0% | 1,398 | 3,739 | +167% | 0 | 0 | — |
case-18 | fail→pass | 10,470 | 1,907 | -82% | 1 | 1 | 0% | 1,757 | 3,580 | +104% | 0 | 0 | — |
case-19 | fail→pass | 28,611 | 2,505 | -91% | 1 | 1 | 0% | 4,308 | 3,737 | -13% | 0 | 0 | — |
case-20 | pass→pass | 9,083 | 6,689 | -26% | 1 | 1 | 0% | 1,786 | 4,493 | +152% | 0 | 0 | — |
case-21 | pass→pass | 14,492 | 15,081 | +4% | 1 | 1 | 0% | 2,774 | 6,188 | +123% | 0 | 0 | — |
case-22 | pass→pass | 11,780 | 8,257 | -30% | 1 | 1 | 0% | 1,724 | 4,822 | +180% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +73 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.