# Contributing to Agent Framework You can contribute to Agent Framework with issues and pull requests (PRs). Simply filing issues for problems you encounter is a great way to contribute. Contributing code is greatly appreciated. This repository is dedicated to the canonical .NET and Python implementations of Microsoft Agent Framework. Microsoft contributors outside the product team should engage with the maintainers before submitting pull requests that add new language implementations or before starting a new Microsoft-owned repository for another language. Contributors outside Microsoft are welcome to start their own repositories to implement Microsoft Agent Framework in other languages, as long as they make it clear that the effort is not owned or maintained directly by Microsoft. ## Reporting Issues We always welcome bug reports, API proposals and overall feedback. Here are a few tips on how you can make reporting your issue as effective as possible. ### Where to Report New issues can be reported in our [list of issues](https://github.com/microsoft/agent-framework/issues). Before filing a new issue, please search the list of issues to make sure it does not already exist. If you do find an existing issue for what you wanted to report, please include your own feedback in the discussion. Do consider upvoting (👍 reaction) the original post, as this helps us prioritize popular issues in our backlog. ### Writing a Good Bug Report Good bug reports make it easier for maintainers to verify and root cause the underlying problem. The better a bug report, the faster the problem will be resolved. Ideally, a bug report should contain the following information: - A high-level description of the problem. - A _minimal reproduction_, i.e. the smallest size of code/configuration required to reproduce the wrong behavior. - A description of the _expected behavior_, contrasted with the _actual behavior_ observed. - Information on the environment: OS/distribution, CPU architecture, SDK version, etc. - Additional information, e.g. Is it a regression from previous versions? Are there any known workarounds? ## Contributing Changes Project maintainers will merge accepted code changes from contributors. We welcome contributions, but maintainers must prioritize their limited review time across issues and pull requests, so we may not be able to get to reviewing every contribution immediately. AI tooling has also made it easier for more people to submit contributions, which has increased the overall volume we receive. AI-assisted contributions are permitted, but contributors remain responsible for understanding, verifying, and supporting everything they submit. Review the [AI-Assisted Contributions Policy](./AI_CONTRIBUTIONS.md) before submitting materially AI-assisted work. Contributors should expect longer wait times for reviews. ### Before Opening a Pull Request Except for trivial changes, create or reuse an issue before starting implementation. A trivial change is an obvious correction whose desired result is not reasonably in dispute, such as fixing a typo or broken documentation link. A small code diff is not automatically trivial. Repository-maintained scheduled automation may open recurring maintenance pull requests without an issue when the pull request identifies the generating workflow. For non-trivial changes: 1. Search for an existing issue before creating a new one. 2. Describe the problem, supporting evidence or reproduction, desired outcome, and relevant scope or alternatives. 3. Wait for a maintainer to add the `ready-for-implementation` label or explicitly comment that the proposed direction is ready for implementation. Automated triage, issue assignment, reactions, and silence do not indicate approval. Maintainer agreement means that a contribution is welcome for review; it does not promise that a future pull request will be merged. Pull requests for non-trivial changes may be closed without detailed review when they are neither linked to an agreed issue nor generated by repository-maintained scheduled automation, or when they duplicate existing work. For a trivial change without an issue, explain why it qualifies as trivial in the pull request's **Related Issue** section. Note that your pull request may receive automated review comments from a bot; addressing or at least replying to those comments will help fast track the eventual human review. ### DOs and DON'Ts DO's: - **DO** follow the standard coding conventions - [.NET](https://learn.microsoft.com/dotnet/csharp/fundamentals/coding-style/coding-conventions) - [Python](https://pypi.org/project/black/) - **DO** give priority to the current style of the project or file you're changing if it diverges from the general guidelines. - **DO** use the pre-commit hooks for python to ensure proper formatting. - **DO** include tests when adding new features. When fixing bugs, start with adding a test that highlights how the current behavior is broken. - **DO** keep the discussions focused. When a new or related topic comes up it's often better to create new issue than to side track the discussion. - **DO** clearly state on an issue that you are going to take on implementing it. - **DO** wait for explicit maintainer agreement before implementing a non-trivial change. - **DO** blog and tweet (or whatever) about your contributions, frequently! DON'Ts: - **DON'T** surprise us with non-trivial pull requests. File an issue and agree on the problem and direction before investing in implementation. - **DON'T** submit code or content whose origin, behavior, or licensing you cannot verify. If you find third-party code that may fit Agent Framework, file an issue and start a discussion before proceeding. - **DON'T** submit PRs that alter licensing related files or headers. If you believe there's a problem with them, file an issue and we'll be happy to discuss it. - **DON'T** make new APIs without filing an issue and discussing with us first. ### Breaking Changes Contributions must maintain API signature and behavioral compatibility. Contributions that include breaking changes will be rejected. Please file an issue to discuss your idea or change if you believe that a breaking change is warranted. #### Python Public API Compatibility Python pull requests run a non-blocking [Griffe](https://mkdocstrings.github.io/griffe/) check that compares the pull request's public API with its base commit. The workflow only runs when Python files change, and reports potential breaking changes as annotations and in the job summary. The experimental `agent-framework-lab` package is excluded. The workflow checks out only trusted base-branch code, fetches GitHub's synthetic merge commit without checking it out, and statically parses its Python source from a temporary directory without importing it. This supports fork pull requests while keeping the comparison current when a pull request branch is behind `main`. If GitHub has not produced a current synthetic merge ref—typically while the pull request has merge conflicts—the advisory comparison is skipped and reruns when the pull request is updated. Only APIs from packages marked `released` in `python/PACKAGE_STATUS.md` are checked. Prerelease packages and APIs marked with `@experimental` or `@release_candidate`—including members of a staged class—are excluded. Package state and feature-stage markers are read from the base commit, so changing either in the same pull request cannot suppress a compatibility finding. The Griffe version is pinned with the other Python development dependencies in `python/pyproject.toml`; the workflow reads that pin from the trusted base commit. Instance-attribute initializer values are excluded because Griffe derives them from constructor control flow and can report implementation-only assignment changes; other Griffe-detected attribute value changes remain checked. If a breaking change is intentional, add the `breaking change` label to the pull request or add `[BREAKING]` to its title. Existing title/label automation keeps those signals synchronized. The label declares that the detected break is intentional; normal repository review and merge policies determine whether the change is approved. The compatibility workflow still reports acknowledged changes but succeeds. Without the label, the comparison step fails; the job is configured as non-blocking so it cannot prevent a merge while the workflow is being evaluated. #### Automated API Compatibility Validation The .NET projects use [Package Validation](https://learn.microsoft.com/dotnet/fundamentals/package-validation/overview) to automatically detect API breaking changes. This validation runs during `dotnet build` (Release configuration) and `dotnet pack`, comparing the current API surface against the latest published NuGet baseline version. **What gets validated:** By default, packable RC packages (`IsReleaseCandidate=true`) and GA packages (`IsGenerallyAvailable=true`) that have a published NuGet baseline and do not override validation settings are automatically validated. The shared baseline version and default validation settings are defined in `dotnet/nuget/nuget-package.props`, but individual projects may opt out (for example by setting `EnablePackageValidation=false`). **If the build fails with CP errors (e.g., CP0001, CP0002):** 1. **Unintentional breaking change** — Refactor your code to maintain backward compatibility. 2. **Intentional breaking change** (approved by maintainers) — Generate a suppression file: ```bash dotnet build .csproj -c Release /p:ApiCompatGenerateSuppressionFile=true ``` This creates or updates a `CompatibilitySuppressions.xml` in the project directory. Include this file in your PR with justification for the breaking change. **After each release:** 1. Delete all `CompatibilitySuppressions.xml` files from validated projects. 2. Update `PackageValidationBaselineVersion` in `dotnet/nuget/nuget-package.props` to the newly published version. For more details, see the [Package Validation diagnostic IDs](https://learn.microsoft.com/dotnet/fundamentals/package-validation/diagnostic-ids). #### Public API Baselines Released .NET packages also use `Microsoft.CodeAnalysis.PublicApiAnalyzers` to make source-level public API changes visible during builds. The `PublicAPI.*.txt` files use `#nullable enable` so nullability annotations are tracked as part of the public API surface. When adding, changing, or removing public APIs in a released package, update the package's `PublicAPI.Unshipped.txt` file with the analyzer-provided entries and include that change in your PR. The build will fail if public API changes are not reflected in the baseline files. If local or CI builds report Public API Analyzer warnings or errors, handle each diagnostic separately: - `RS0016` reports a newly exposed public API that is missing from the baseline. The preferred fix is to use the analyzer code fix on the affected code symbol to add the missing API entry automatically. Alternatively, run `dotnet format` for `RS0016` from the repository root: ```powershell dotnet format .\dotnet\agent-framework-dotnet.slnx analyzers --diagnostics RS0016 ``` - `RS0017` reports that a declared public API was deleted. Restore the API if the deletion was accidental; otherwise, record the removed signature in the package's `PublicAPI.Unshipped.txt` file with the `*REMOVED*` prefix by using the corresponding code fix, or the following dotnet format script: ```powershell dotnet format .\dotnet\agent-framework-dotnet.slnx analyzers --diagnostics RS0017 ``` After a release, the `Promote Shipped APIs` workflow moves entries from `PublicAPI.Unshipped.txt` to `PublicAPI.Shipped.txt` and opens or updates a promotion PR. Publish builds fail if released packages still contain unshipped public API entries. ### Suggested Workflow We use and recommend the following workflow: 1. Complete the [issue-first process](#before-opening-a-pull-request). - Skip the issue only for a trivial change as defined above. - Reuse an existing issue on the topic when possible. - Clearly state that you are going to take on implementing it, if that's the case. You can request that the issue be assigned to you. Note: The issue filer and the implementer don't have to be the same person. 2. Create a personal fork of the repository on GitHub (if you don't already have one). 3. In your fork, create a branch off of main (`git checkout -b mybranch`). - Name the branch so that it clearly communicates your intentions, such as "issue-123" or "githubhandle-issue". 4. Make and commit your changes to your branch. 5. Add new tests corresponding to your change, if applicable. 6. Run the relevant scripts in [the section below](#development-setup) to ensure that your build is clean and all tests are passing. 7. Create a PR against the repository's **main** branch. - Link the agreed issue with a closing keyword, or explain why the change is a trivial exception. - Complete the AI assistance disclosure in the pull request template. - Verify that all the Continuous Integration checks are passing. 8. Address feedback from the code maintainers. Reply to every review comment with the outcome and resolve each completed review conversation yourself before requesting another review. 9. When area owners have signed off, and all checks are green, your PR will be merged. ### Resolving PR Review Comments PR authors are responsible for closing out all review conversations on their pull requests, including conversations opened by reviewers. Do not wait for the reviewer or a maintainer to resolve completed conversations for you. For every review comment: - If the feedback was addressed, reply with a brief explanation and, preferably, the commit containing the change. - If the feedback was not addressed, reply with the reason why. After replying and completing any necessary discussion, **resolve the conversation yourself**. Leave a conversation open only while it has an unanswered question or active discussion. Reviewers may reopen a conversation if further changes or discussion are needed. ### Development Setup Each language has its own dev setup guide, coding standards, and build scripts: - **Python**: [Dev Setup](./python/DEV_SETUP.md) · [Coding Standard](./python/CODING_STANDARD.md) · [README](./python/README.md) - From the `./python` directory: - Build: `uv run poe build` - Unit tests: `uv run poe test -A -m "not integration"` - Integration tests: `uv run poe test -A -m integration` (requires API keys/endpoints) - Format + lint: `uv run poe syntax` - All checks: `uv run poe check` - **.NET**: [README](./dotnet/README.md) · [Agent Instructions](./dotnet/AGENTS.md) - From the `./dotnet` directory: - Build: `dotnet build` - Unit tests: `dotnet test --filter-query "/*UnitTests*/*/*/*"` - Integration tests: `dotnet test --filter-query "/*IntegrationTests*/*/*/*"` (requires API keys/endpoints) - Linting (auto-fix): `dotnet format` #### Microsoft Internal Feed Proxy for GitHub Copilot SDK (.NET) Microsoft contributors can route GitHub Copilot SDK npm downloads through the internal proxy without passing extra `dotnet` arguments: 1. Create `dotnet/Directory.Build.rsp` with: ```text -p:CopilotNpmRegistryUrl=https://packagefeedproxy.microsoft.io/npm/ ``` When running `dotnet build` (or other `dotnet` commands) from the `./dotnet` directory, this property is applied automatically. ### PR - CI Process The continuous integration (CI) system will automatically perform the required builds and run tests (including the ones you are expected to run) for PRs. Builds and test runs must be clean. If the CI build fails for any reason, the PR issue will be updated with a link that can be used to determine the cause of the failure.