.NET: Python: Add AGENTS.md files and update coding standards (#3644)

* Add AGENTS.md files and update coding standards for Python

- Add root python/AGENTS.md with project structure and package links
- Add AGENTS.md for each package describing purpose and main classes
- Update .github/copilot-instructions.md with improved structure
- Update python/CODING_STANDARD.md with API review guidance:
  - Future annotations convention (#3578)
  - TypeVar naming convention (#3594)
  - Mapping vs MutableMapping (#3577)
  - Avoid shadowing built-ins (#3583)
  - Explicit exports (#3605)
  - Exception documentation guidelines (#3410)
- Simplify python/.github/instructions/python.instructions.md to reference AGENTS.md
- Remove AGENTS.md from .gitignore

* Fix purview import path in AGENTS.md

* Address PR review comments and restructure instructions

- Slim down .github/copilot-instructions.md to reference language-specific docs
- Add ADR section explaining templates and purpose
- Create dotnet/AGENTS.md with .NET-specific build commands, conventions, and sample guidance
- Update Python build/test instructions for core vs isolated changes
- Fix Microsoft.Extensions.AI package references
- Update kwargs guidance per issue #3642
- Fix Python sample helper placement (top, not bottom)
- Document new 'typing' poe task in DEV_SETUP.md

* Add 'typing' poe task to run both pyright and mypy

* Add kwargs guidelines from issue #3642 to CODING_STANDARD.md

* Clarify that connector packages pull in core as dependency
This commit is contained in:
Eduard van Valkenburg
2026-02-05 11:27:46 +01:00
committed by GitHub
Unverified
parent de80543302
commit eaad042241
30 changed files with 1026 additions and 201 deletions
+11 -61
View File
@@ -1,69 +1,19 @@
# GitHub Copilot Instructions
This repository contains both Python and C# code.
All python code resides under the `python/` directory.
All C# code resides under the `dotnet/` directory.
Microsoft Agent Framework - a multi-language framework for building, orchestrating, and deploying AI agents.
The purpose of the code is to provide a framework for building AI agents.
## Repository Structure
When contributing to this repository, please follow these guidelines:
- `python/` - Python implementation → see [python/AGENTS.md](../python/AGENTS.md)
- `dotnet/` - C#/.NET implementation → see [dotnet/AGENTS.md](../dotnet/AGENTS.md)
- `docs/` - Design documents and architectural decision records
## C# Code Guidelines
## Architectural Decision Records (ADRs)
Here are some general guidelines that apply to all code.
ADRs in `docs/decisions/` capture significant design decisions and their rationale. They document considered alternatives, trade-offs, and the reasoning behind choices.
- The top of all *.cs files should have a copyright notice: `// Copyright (c) Microsoft. All rights reserved.`
- All public methods and classes should have XML documentation comments.
- After adding, modifying or deleting code, run `dotnet build`, and then fix any reported build errors.
- After adding or modifying code, run `dotnet format` to automatically fix any formatting errors.
**Templates:**
- `adr-template.md` - Full template with detailed sections
- `adr-short-template.md` - Abbreviated template for simpler decisions
### C# Sample Code Guidelines
Sample code is located in the `dotnet/samples` directory.
When adding a new sample, follow these steps:
- The sample should be a standalone .net project in one of the subdirectories of the samples directory.
- The directory name should be the same as the project name.
- The directory should contain a README.md file that explains what the sample does and how to run it.
- The README.md file should follow the same format as other samples.
- The csproj file should match the directory name.
- The csproj file should be configured in the same way as other samples.
- The project should preferably contain a single Program.cs file that contains all the sample code.
- The sample should be added to the solution file in the samples directory.
- The sample should be tested to ensure it works as expected.
- A reference to the new samples should be added to the README.md file in the parent directory of the new sample.
The sample code should follow these guidelines:
- Configuration settings should be read from environment variables, e.g. `var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");`.
- Environment variables should use upper snake_case naming convention.
- Secrets should not be hardcoded in the code or committed to the repository.
- The code should be well-documented with comments explaining the purpose of each step.
- The code should be simple and to the point, avoiding unnecessary complexity.
- Prefer inline literals over constants for values that are not reused. For example, use `new ChatClientAgent(chatClient, instructions: "You are a helpful assistant.")` instead of defining a constant for "instructions".
- Ensure that all private classes are sealed
- Use the Async suffix on the name of all async methods that return a Task or ValueTask.
- Prefer defining variables using types rather than var, to help users understand the types involved.
- Follow the patterns in the samples in the same directories where new samples are being added.
- The structure of the sample should be as follows:
- The top of the Program.cs should have a copyright notice: `// Copyright (c) Microsoft. All rights reserved.`
- Then add a comment describing what the sample is demonstrating.
- Then add the necessary using statements.
- Then add the main code logic.
- Finally, add any helper methods or classes at the bottom of the file.
### C# Unit Test Guidelines
Unit tests are located in the `dotnet/tests` directory in projects with a `.UnitTests.csproj` suffix.
Unit tests should follow these guidelines:
- Use `this.` for accessing class members
- Add Arrange, Act and Assert comments for each test
- Ensure that all private classes, that are not subclassed, are sealed
- Use the Async suffix on the name of all async methods
- Use the Moq library for mocking objects where possible
- Validate that each test actually tests the target behavior, e.g. we should not have tests that creates a mock, calls the mock and then verifies that the mock was called, without the target code being involved. We also shouldn't have tests that test language features, e.g. something that the compiler would catch anyway.
- Avoid adding excessive comments to tests. Instead favour clear easy to understand code.
- Follow the patterns in the unit tests in the same project or classes to which new tests are being added
When proposing architectural changes, create an ADR to capture options considered and the decision rationale. See [docs/decisions/README.md](../docs/decisions/README.md) for the full process.
-2
View File
@@ -199,8 +199,6 @@ temp*/
.tmp/
.temp/
agents.md
# AI
.claude/
WARP.md
+66
View File
@@ -0,0 +1,66 @@
# AGENTS.md
Instructions for AI coding agents working in the .NET codebase.
## Build, Test, and Lint Commands
```bash
# From dotnet/ directory
dotnet build # Build all projects
dotnet test # Run all tests
dotnet format # Auto-fix formatting
# Build/test a specific project (preferred for isolated changes)
dotnet build src/Microsoft.Agents.AI.<Package>
dotnet test tests/Microsoft.Agents.AI.<Package>.UnitTests
# Run a single test
dotnet test --filter "FullyQualifiedName~TestClassName.TestMethodName"
```
**Note**: Changes to core packages (`Microsoft.Agents.AI`, `Microsoft.Agents.AI.Abstractions`) affect dependent projects - run checks across the entire solution. For isolated changes, build/test only the affected project to save time.
## Project Structure
```
dotnet/
├── src/
│ ├── Microsoft.Agents.AI/ # Core AI agent abstractions
│ ├── Microsoft.Agents.AI.Abstractions/ # Shared abstractions and interfaces
│ ├── Microsoft.Agents.AI.OpenAI/ # OpenAI provider
│ ├── Microsoft.Agents.AI.AzureAI/ # Azure AI provider
│ ├── Microsoft.Agents.AI.Anthropic/ # Anthropic provider
│ ├── Microsoft.Agents.AI.Workflows/ # Workflow orchestration
│ └── ... # Other packages
├── samples/ # Sample applications
└── tests/ # Unit and integration tests
```
### External Dependencies
The framework integrates with `Microsoft.Extensions.AI` and `Microsoft.Extensions.AI.Abstractions` (external NuGet packages) using types like `IChatClient`, `FunctionInvokingChatClient`, `AITool`, and `AIContent`.
## Key Conventions
- **Copyright header**: `// Copyright (c) Microsoft. All rights reserved.` at top of all `.cs` files
- **XML docs**: Required for all public methods and classes
- **Async**: Use `Async` suffix for methods returning `Task`/`ValueTask`
- **Private classes**: Should be `sealed` unless subclassed
- **Config**: Read from environment variables with `UPPER_SNAKE_CASE` naming
- **Tests**: Add Arrange/Act/Assert comments; use Moq for mocking
## Sample Structure
1. Copyright header: `// Copyright (c) Microsoft. All rights reserved.`
2. Description comment explaining what the sample demonstrates
3. Using statements
4. Main code logic
5. Helper methods at bottom
Configuration via environment variables (never hardcode secrets). Keep samples simple and focused.
When adding a new sample:
- Create a standalone project in `samples/` with matching directory and project names
- Include a README.md explaining what the sample does and how to run it
- Add the project to the solution file
- Reference the sample in the parent directory's README.md
+7 -22
View File
@@ -1,26 +1,11 @@
---
applyTo: '**/agent-framework/python/**'
---
- Use `uv run` as the main entrypoint for running Python commands with all packages available.
- Use `uv run poe <task>` for development tasks like formatting (`fmt`), linting (`lint`), type checking (`pyright`, `mypy`), and testing (`test`).
- Use `uv run --directory packages/<package> poe <task>` to run tasks for a specific package.
- Read [DEV_SETUP.md](../../DEV_SETUP.md) for detailed development environment setup and available poe tasks.
- Read [CODING_STANDARD.md](../../CODING_STANDARD.md) for the project's coding standards and best practices.
- When verifying logic with unit tests, run only the related tests, not the entire test suite.
- For new tests and samples, review existing ones to understand the coding style and reuse it.
- When generating new functions, always specify the function return type and parameter types.
- Do not use `Optional`; use `Type | None` instead.
- Before running any commands to execute or test the code, ensure that all problems, compilation errors, and warnings are resolved.
- When formatting files, format only the files you changed or are currently working on; do not format the entire codebase.
- Do not mark new tests with `@pytest.mark.asyncio`.
- If you need debug information to understand an issue, use print statements as needed and remove them when testing is complete.
- Avoid adding excessive comments.
- When working with samples, make sure to update the associated README files with the latest information. These files are usually located in the same folder as the sample or in one of its parent folders.
Sample structure:
1. Copyright header: `# Copyright (c) Microsoft. All rights reserved.`
2. Required imports.
3. Short description about the sample: `"""This sample demonstrates..."""`
4. Helper functions.
5. Main functions that demonstrate the functionality. If it is a single scenario, use a `main` function. If there are multiple scenarios, define separate functions and add a `main` function that invokes all scenarios.
6. Place `if __name__ == "__main__": asyncio.run(main())` at the end of the sample file to make the example executable.
See [AGENTS.md](../../AGENTS.md) for project structure, commands, and conventions.
Additional guidance:
- Review existing tests and samples to understand coding style before creating new ones
- When verifying logic, run only related tests, not the entire suite
- Resolve all errors and warnings before running code
- Use print statements for debugging, then remove them when done
+110
View File
@@ -0,0 +1,110 @@
# AGENTS.md
Instructions for AI coding agents working in the Python codebase.
**Key Documentation:**
- [DEV_SETUP.md](DEV_SETUP.md) - Development environment setup and available poe tasks
- [CODING_STANDARD.md](CODING_STANDARD.md) - Coding standards, docstring format, and performance guidelines
## Maintaining Documentation
When making changes to a package, check if the package's `AGENTS.md` file needs updates. This includes:
- Adding/removing/renaming public classes or functions
- Changing the package's purpose or architecture
- Modifying import paths or usage patterns
## Quick Reference
Run `uv run poe` from the `python/` directory to see available commands. See [DEV_SETUP.md](DEV_SETUP.md) for detailed usage.
## Project Structure
```
python/
├── packages/
│ ├── core/ # agent-framework-core (main package)
│ │ ├── agent_framework/ # Public API exports
│ │ └── tests/
│ ├── azure-ai/ # agent-framework-azure-ai
│ ├── anthropic/ # agent-framework-anthropic
│ ├── ollama/ # agent-framework-ollama
│ └── ... # Other provider packages
├── samples/ # Sample code and examples
└── tests/ # Integration tests
```
### Package Relationships
- `agent-framework-core` contains core abstractions and OpenAI/Azure OpenAI built-in
- Provider packages (`azure-ai`, `anthropic`, etc.) extend core with specific integrations
- Core uses lazy loading via `__getattr__` in provider folders (e.g., `agent_framework/azure/`)
### Import Patterns
```python
# Core imports
from agent_framework import ChatAgent, ChatMessage, tool
# Provider imports (lazy-loaded)
from agent_framework.openai import OpenAIChatClient
from agent_framework.azure import AzureOpenAIChatClient, AzureAIAgentClient
```
## Key Conventions
- **Copyright**: `# Copyright (c) Microsoft. All rights reserved.` at top of all `.py` files
- **Types**: Always specify return types and parameter types; use `Type | None` not `Optional`
- **Logging**: `from agent_framework import get_logger` (never `import logging`)
- **Docstrings**: Google-style for public APIs
- **Tests**: Do not use `@pytest.mark.asyncio` (auto mode enabled); run only related tests, not the entire suite
- **Line length**: 120 characters
- **Comments**: Avoid excessive comments; prefer clear code
- **Formatting**: Format only files you changed, not the entire codebase
## Sample Structure
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.
## Package Documentation
### Core
- [core](packages/core/AGENTS.md) - Core abstractions, types, and built-in OpenAI/Azure OpenAI support
### LLM Providers
- [anthropic](packages/anthropic/AGENTS.md) - Anthropic Claude API
- [bedrock](packages/bedrock/AGENTS.md) - AWS Bedrock
- [claude](packages/claude/AGENTS.md) - Claude Agent SDK
- [foundry_local](packages/foundry_local/AGENTS.md) - Azure AI Foundry Local
- [ollama](packages/ollama/AGENTS.md) - Local Ollama inference
### Azure Integrations
- [azure-ai](packages/azure-ai/AGENTS.md) - Azure AI Foundry agents
- [azure-ai-search](packages/azure-ai-search/AGENTS.md) - Azure AI Search RAG
- [azurefunctions](packages/azurefunctions/AGENTS.md) - Azure Functions hosting
### Protocols & UI
- [a2a](packages/a2a/AGENTS.md) - Agent-to-Agent protocol
- [ag-ui](packages/ag-ui/AGENTS.md) - AG-UI protocol
- [chatkit](packages/chatkit/AGENTS.md) - OpenAI ChatKit integration
- [devui](packages/devui/AGENTS.md) - Developer UI for testing
### Storage & Memory
- [mem0](packages/mem0/AGENTS.md) - Mem0 memory integration
- [redis](packages/redis/AGENTS.md) - Redis storage
### Infrastructure
- [copilotstudio](packages/copilotstudio/AGENTS.md) - Microsoft Copilot Studio
- [declarative](packages/declarative/AGENTS.md) - YAML/JSON agent definitions
- [durabletask](packages/durabletask/AGENTS.md) - Durable execution
- [github_copilot](packages/github_copilot/AGENTS.md) - GitHub Copilot extensions
- [purview](packages/purview/AGENTS.md) - Data governance
### Experimental
- [lab](packages/lab/AGENTS.md) - Experimental features
+93 -9
View File
@@ -10,12 +10,66 @@ We use [ruff](https://github.com/astral-sh/ruff) for both linting and formatting
- **Target Python version**: 3.10+
- **Google-style docstrings**: All public functions, classes, and modules should have docstrings following Google conventions
## Type Annotations
### Future Annotations
> **Note:** This convention is being adopted. See [#3578](https://github.com/microsoft/agent-framework/issues/3578) for progress.
Use `from __future__ import annotations` at the top of files to enable postponed evaluation of annotations. This prevents the need for string-based type hints for forward references:
```python
# ✅ Preferred - use future annotations
from __future__ import annotations
class Agent:
def create_child(self) -> Agent: # No quotes needed
...
# ❌ Avoid - string-based type hints
class Agent:
def create_child(self) -> "Agent": # Requires quotes without future annotations
...
```
### TypeVar Naming Convention
> **Note:** This convention is being adopted. See [#3594](https://github.com/microsoft/agent-framework/issues/3594) for progress.
Use the suffix `T` for TypeVar names instead of a prefix:
```python
# ✅ Preferred - suffix T
ChatResponseT = TypeVar("ChatResponseT", bound=ChatResponse)
AgentT = TypeVar("AgentT", bound=Agent)
# ❌ Avoid - prefix T
TChatResponse = TypeVar("TChatResponse", bound=ChatResponse)
TAgent = TypeVar("TAgent", bound=Agent)
```
### Mapping Types
> **Note:** This convention is being adopted. See [#3577](https://github.com/microsoft/agent-framework/issues/3577) for progress.
Use `Mapping` instead of `MutableMapping` for input parameters when mutation is not required:
```python
# ✅ Preferred - Mapping for read-only access
def process_config(config: Mapping[str, Any]) -> None:
...
# ❌ Avoid - MutableMapping when mutation isn't needed
def process_config(config: MutableMapping[str, Any]) -> None:
...
```
## Function Parameter Guidelines
To make the code easier to use and maintain:
- **Positional parameters**: Only use for up to 3 fully expected parameters
- **Keyword parameters**: Use for all other parameters, especially when there are multiple required parameters without obvious ordering
- **Positional parameters**: Only use for up to 3 fully expected parameters (this is not a hard rule, but a guideline there are instances where this does make sense to exceed)
- **Keyword-only parameters**: Arguments after `*` in function signatures are keyword-only; prefer these for optional parameters
- **Avoid additional imports**: Do not require the user to import additional modules to use the function, so provide string based overrides when applicable, for instance:
```python
def create_agent(name: str, tool_mode: ChatToolMode) -> Agent:
@@ -28,8 +82,19 @@ def create_agent(name: str, tool_mode: Literal['auto', 'required', 'none'] | Cha
if isinstance(tool_mode, str):
tool_mode = ChatToolMode(tool_mode)
```
- **Document kwargs**: Always document how `kwargs` are used, either by referencing external documentation or explaining their purpose
- **Separate kwargs**: When combining kwargs for multiple purposes, use specific parameters like `client_kwargs: dict[str, Any]` instead of mixing everything in `**kwargs`
- **Avoid shadowing built-ins**: Do not use parameter names that shadow Python built-ins (e.g., use `next_handler` instead of `next`). See [#3583](https://github.com/microsoft/agent-framework/issues/3583) for progress.
### Using `**kwargs`
> **Note:** This convention is being adopted. See [#3642](https://github.com/microsoft/agent-framework/issues/3642) for progress.
Avoid `**kwargs` unless absolutely necessary. It should only be used as an escape route, not for well-known flows of data:
- **Prefer named parameters**: If there are known extra arguments being passed, use explicit named parameters instead of kwargs
- **Subclassing support**: kwargs is acceptable in methods that are part of classes designed for subclassing, allowing subclass-defined kwargs to pass through without issues. In this case, clearly document that kwargs exists for subclass extensibility and not for passing arbitrary data
- **Remove when possible**: In other cases, removing kwargs is likely better than keeping it
- **Separate kwargs by purpose**: When combining kwargs for multiple purposes, use specific parameters like `client_kwargs: dict[str, Any]` instead of mixing everything in `**kwargs`
- **Always document**: If kwargs must be used, always document how it's used, either by referencing external documentation or explaining its purpose
## Method Naming Inside Connectors
@@ -212,7 +277,7 @@ pip install agent-framework-core[all]
# or (equivalently):
pip install agent-framework
# Install specific connector
# Install specific connector (pulls in core as dependency)
pip install agent-framework-azure-ai
```
@@ -234,10 +299,9 @@ They should contain:
- Type and default values do not have to be specified, they will be pulled from the definition.
- Returns are specified after a header called `Returns:` or `Yields:`, with the return type and explanation of the return value.
- Keyword arguments are specified after a header called `Keyword Args:`, with each argument being specified in the same format as `Args:`.
- A header for exceptions can be added, called `Raises:`, but should only be used for:
- Agent Framework specific exceptions (e.g., `ServiceInitializationError`)
- Base exceptions that might be unexpected in the context
- Obvious exceptions like `ValueError` or `TypeError` do not need to be documented
- A header for exceptions can be added, called `Raises:`, following these guidelines:
- **Always document** Agent Framework specific exceptions (e.g., `AgentInitializationError`, `AgentExecutionException`)
- **Only document** standard Python exceptions (TypeError, ValueError, KeyError, etc.) when the condition is non-obvious or provides value to API users
- Format: `ExceptionType`: Explanation of the exception.
- If a longer explanation is needed, it should be placed on the next line, indented by 4 spaces.
- Code examples can be added using the `Examples:` header followed by `.. code-block:: python` directive.
@@ -328,6 +392,26 @@ def create_agent(name: str, chat_client: ChatClientProtocol) -> Agent:
If in doubt, use the link above to read much more considerations of what to do and when, or use common sense.
## Public API and Exports
### Explicit Exports
> **Note:** This convention is being adopted. See [#3605](https://github.com/microsoft/agent-framework/issues/3605) for progress.
Define `__all__` in each module to explicitly declare the public API. Avoid using `from module import *` in `__init__.py` files as it can impact performance and makes the public API unclear:
```python
# ✅ Preferred - explicit __all__ and imports
__all__ = ["ChatAgent", "ChatMessage", "ChatResponse"]
from ._agents import ChatAgent
from ._types import ChatMessage, ChatResponse
# ❌ Avoid - star imports
from ._agents import *
from ._types import *
```
## Performance considerations
### Cache Expensive Computations
+6
View File
@@ -254,6 +254,12 @@ Run MyPy type checking:
uv run poe mypy
```
#### `typing`
Run both Pyright and MyPy type checking:
```bash
uv run poe typing
```
### Code Validation
#### `markdown-code-lint`
-107
View File
@@ -1,107 +0,0 @@
# Copyright (c) Microsoft. All rights reserved.
import debugpy
import asyncio
import json
import os
from pathlib import Path
from dotenv import load_dotenv
from py2docfx.__main__ import main as py2docfx_main
load_dotenv()
async def generate_af_docs(root_path: Path):
"""Generate documentation for the Agent Framework using py2docfx.
This function runs the py2docfx command with the specified parameters.
"""
package = {
"packages": [
{
"package_info": {
"name": "agent-framework-core",
"version": "1.0.0b251001",
"install_type": "pypi",
"extras": ["all"]
},
"sphinx_extensions": [
"sphinxcontrib.autodoc_pydantic",
"sphinx-pydantic",
"sphinx.ext.autosummary"
],
"extension_config": {
"napoleon_google_docstring": 1,
"napoleon_preprocess_types": 1,
"napoleon_use_param": 0,
"autodoc_pydantic_field_doc_policy": "both",
"autodoc_pydantic_model_show_json": 0,
"autodoc_pydantic_model_show_config_summary": 1,
"autodoc_pydantic_model_show_field_summary": 1,
"autodoc_pydantic_model_hide_paramlist": 0,
"autodoc_pydantic_model_show_json_error_strategy": "coerce",
"autodoc_pydantic_settings_show_config_summary": 1,
"autodoc_pydantic_settings_show_field_summary": 1,
"python_use_unqualified_type_names": 1,
"autodoc_preserve_defaults": 1,
"autodoc_class_signature": "separated",
"autodoc_typehints": "description",
"autodoc_typehints_format": "fully-qualified",
"autodoc_default_options": {
"members": 1,
"member-order": "alphabetical",
"undoc-members": 1,
"show-inheritance": 1,
"imported-members": 1,
},
},
}
],
"required_packages": [
{
"install_type": "pypi",
"name": "autodoc_pydantic",
"version": ">=2.0.0",
},
{
"install_type": "pypi",
"name": "sphinx-pydantic",
}
],
}
args = [
"-o",
str((root_path / "docs" / "build").absolute()),
"-j",
json.dumps(package),
"--verbose"
]
try:
await py2docfx_main(args)
except Exception as e:
print(f"Error generating documentation: {e}")
if __name__ == "__main__":
# Ensure the script is run from the correct directory
debug = False
if debug:
debugpy.listen(("localhost", 5678))
debugpy.wait_for_client()
debugpy.breakpoint()
current_path = Path(__file__).parent.parent.resolve()
print(f"Current path: {current_path}")
# ensure the dist folder exists
dist_path = current_path / "dist"
if not dist_path.exists():
print(" Please run `poe build` to generate the dist folder.")
exit(1)
if os.getenv("PIP_FIND_LINKS") != str(dist_path.absolute()):
print(f"Setting PIP_FIND_LINKS to {dist_path.absolute()}")
os.environ["PIP_FIND_LINKS"] = str(dist_path.absolute())
print(f"Generating documentation in: {current_path / 'docs' / 'build'}")
# Generate the documentation
asyncio.run(generate_af_docs(current_path))
+23
View File
@@ -0,0 +1,23 @@
# A2A Package (agent-framework-a2a)
Agent-to-Agent (A2A) protocol support for inter-agent communication.
## Main Classes
- **`A2AAgent`** - Agent wrapper that exposes an agent via the A2A protocol
## Usage
```python
from agent_framework.a2a import A2AAgent
a2a_agent = A2AAgent(agent=my_agent)
```
## Import Path
```python
from agent_framework.a2a import A2AAgent
# or directly:
from agent_framework_a2a import A2AAgent
```
+35
View File
@@ -0,0 +1,35 @@
# AG-UI Package (agent-framework-ag-ui)
AG-UI protocol integration for building agent UIs with the AG-UI standard.
## Main Classes
- **`AgentFrameworkAgent`** - Wraps agents for AG-UI compatibility
- **`AGUIChatClient`** - Chat client that speaks AG-UI protocol
- **`AGUIHttpService`** - HTTP service for AG-UI endpoints
- **`AGUIEventConverter`** - Converts between Agent Framework and AG-UI events
- **`add_agent_framework_fastapi_endpoint()`** - Add AG-UI endpoint to FastAPI app
## Types
- **`AGUIRequest`** / **`AGUIChatOptions`** - Request types
- **`AgentState`** / **`RunMetadata`** - State management types
- **`PredictStateConfig`** - Configuration for state prediction
## Usage
```python
from agent_framework.ag_ui import add_agent_framework_fastapi_endpoint
from fastapi import FastAPI
app = FastAPI()
add_agent_framework_fastapi_endpoint(app, agent)
```
## Import Path
```python
from agent_framework.ag_ui import AGUIChatClient, add_agent_framework_fastapi_endpoint
# or directly:
from agent_framework_ag_ui import AGUIChatClient
```
+25
View File
@@ -0,0 +1,25 @@
# Anthropic Package (agent-framework-anthropic)
Integration with Anthropic's Claude API.
## Main Classes
- **`AnthropicClient`** - Chat client for Anthropic Claude models
- **`AnthropicChatOptions`** - Options TypedDict for Anthropic-specific parameters
## Usage
```python
from agent_framework.anthropic import AnthropicClient
client = AnthropicClient(model_id="claude-sonnet-4-20250514")
response = await client.get_response("Hello")
```
## Import Path
```python
from agent_framework.anthropic import AnthropicClient
# or directly:
from agent_framework_anthropic import AnthropicClient
```
+28
View File
@@ -0,0 +1,28 @@
# Azure AI Search Package (agent-framework-azure-ai-search)
Integration with Azure AI Search for RAG (Retrieval-Augmented Generation).
## Main Classes
- **`AzureAISearchContextProvider`** - Context provider that retrieves relevant documents from Azure AI Search
- **`AzureAISearchSettings`** - Pydantic settings for Azure AI Search configuration
## Usage
```python
from agent_framework.azure import AzureAISearchContextProvider
provider = AzureAISearchContextProvider(
endpoint="https://your-search.search.windows.net",
index_name="your-index",
)
agent = ChatAgent(..., context_provider=provider)
```
## Import Path
```python
from agent_framework.azure import AzureAISearchContextProvider
# or directly:
from agent_framework_azure_ai_search import AzureAISearchContextProvider
```
+32
View File
@@ -0,0 +1,32 @@
# Azure AI Package (agent-framework-azure-ai)
Integration with Azure AI Foundry for persistent agents and project-based agent management.
## Main Classes
- **`AzureAIAgentClient`** - Chat client for Azure AI Agents (persistent agents with threads)
- **`AzureAIClient`** - Client for Azure AI Foundry project-based agents
- **`AzureAIAgentsProvider`** - Provider for listing/managing Azure AI agents
- **`AzureAIProjectAgentProvider`** - Provider for project-scoped agent management
- **`AzureAISettings`** - Pydantic settings for Azure AI configuration
- **`AzureAIAgentOptions`** / **`AzureAIProjectAgentOptions`** - Options TypedDicts
## Usage
```python
from agent_framework.azure import AzureAIAgentClient
client = AzureAIAgentClient(
endpoint="https://your-project.services.ai.azure.com",
agent_id="your-agent-id",
)
response = await client.get_response("Hello")
```
## Import Path
```python
from agent_framework.azure import AzureAIAgentClient, AzureAIClient
# or directly:
from agent_framework_azure_ai import AzureAIAgentClient
```
+23
View File
@@ -0,0 +1,23 @@
# Azure Functions Package (agent-framework-azurefunctions)
Hosting agents as Azure Functions.
## Main Classes
- **`AgentFunctionApp`** - Azure Functions app wrapper for agents
## Usage
```python
from agent_framework.azure import AgentFunctionApp
app = AgentFunctionApp(agent=my_agent)
```
## Import Path
```python
from agent_framework.azure import AgentFunctionApp
# or directly:
from agent_framework_azurefunctions import AgentFunctionApp
```
+25
View File
@@ -0,0 +1,25 @@
# Bedrock Package (agent-framework-bedrock)
Integration with AWS Bedrock for LLM inference.
## Main Classes
- **`BedrockChatClient`** - Chat client for AWS Bedrock models
- **`BedrockChatOptions`** - Options TypedDict for Bedrock-specific parameters
- **`BedrockGuardrailConfig`** - Configuration for Bedrock guardrails
- **`BedrockSettings`** - Pydantic settings for Bedrock configuration
## Usage
```python
from agent_framework_bedrock import BedrockChatClient
client = BedrockChatClient(model_id="anthropic.claude-3-sonnet-20240229-v1:0")
response = await client.get_response("Hello")
```
## Import Path
```python
from agent_framework_bedrock import BedrockChatClient
```
+27
View File
@@ -0,0 +1,27 @@
# ChatKit Package (agent-framework-chatkit)
Integration with OpenAI ChatKit (Python) for building chat UIs.
## Main Classes
- **`ThreadItemConverter`** - Converts between Agent Framework and ChatKit types
- **`stream_agent_response()`** - Stream agent responses to ChatKit
- **`simple_to_agent_input()`** - Convert simple input to agent input format
## Usage
```python
from agent_framework.chatkit import stream_agent_response, ThreadItemConverter
async for event in stream_agent_response(agent, messages):
# Handle ChatKit events
pass
```
## Import Path
```python
from agent_framework.chatkit import stream_agent_response
# or directly:
from agent_framework_chatkit import stream_agent_response
```
+28
View File
@@ -0,0 +1,28 @@
# Claude Package (agent-framework-claude)
Integration with Anthropic Claude as a managed agent (Claude Agent SDK).
## Main Classes
- **`ClaudeAgent`** - Agent using Claude's native agent capabilities
- **`ClaudeAgentOptions`** - Options for Claude agent configuration
- **`ClaudeAgentSettings`** - Pydantic settings for configuration
## Usage
```python
from agent_framework_claude import ClaudeAgent
agent = ClaudeAgent(...)
response = await agent.run("Hello")
```
## Import Path
```python
from agent_framework_claude import ClaudeAgent
```
## Note
This package is for Claude's managed agent functionality. For basic Claude chat, use `agent-framework-anthropic` instead.
+28
View File
@@ -0,0 +1,28 @@
# Copilot Studio Package (agent-framework-copilotstudio)
Integration with Microsoft Copilot Studio agents.
## Main Classes
- **`CopilotStudioAgent`** - Agent that connects to a Copilot Studio bot
- **`acquire_token`** - Helper function for authentication
## Usage
```python
from agent_framework.microsoft import CopilotStudioAgent
agent = CopilotStudioAgent(
bot_identifier="your-bot-id",
environment_id="your-env-id",
)
response = await agent.run("Hello")
```
## Import Path
```python
from agent_framework.microsoft import CopilotStudioAgent
# or directly:
from agent_framework_copilotstudio import CopilotStudioAgent
```
+141
View File
@@ -0,0 +1,141 @@
# Core Package (agent-framework-core)
The foundation package containing all core abstractions, types, and built-in OpenAI/Azure OpenAI support.
## Module Structure
```
agent_framework/
├── __init__.py # Public API exports
├── _agents.py # Agent implementations
├── _clients.py # Chat client base classes and protocols
├── _types.py # Core types (ChatMessage, ChatResponse, Content, etc.)
├── _tools.py # Tool definitions and function invocation
├── _middleware.py # Middleware system for request/response interception
├── _threads.py # AgentThread and message store abstractions
├── _memory.py # Context providers for memory/RAG
├── _mcp.py # Model Context Protocol support
├── _workflows/ # Workflow orchestration (sequential, concurrent, handoff, etc.)
├── openai/ # Built-in OpenAI client
├── azure/ # Lazy-loading entry point for Azure integrations
└── <provider>/ # Other lazy-loading provider folders
```
## Core Classes
### Agents (`_agents.py`)
- **`AgentProtocol`** - Protocol defining the agent interface
- **`BaseAgent`** - Abstract base class for agents
- **`ChatAgent`** - Main agent class wrapping a chat client with tools, instructions, and middleware
### Chat Clients (`_clients.py`)
- **`ChatClientProtocol`** - Protocol for chat client implementations
- **`BaseChatClient`** - Abstract base class with middleware support; subclasses implement `_inner_get_response()` and `_inner_get_streaming_response()`
### Types (`_types.py`)
- **`ChatMessage`** - Represents a chat message with role, content, and metadata
- **`ChatResponse`** - Response from a chat client containing messages and usage
- **`ChatResponseUpdate`** - Streaming response update
- **`AgentResponse`** / **`AgentResponseUpdate`** - Agent-level response wrappers
- **`Content`** - Base class for message content (text, function calls, images, etc.)
- **`ChatOptions`** - TypedDict for chat request options
### Tools (`_tools.py`)
- **`ToolProtocol`** - Protocol for tool definitions
- **`FunctionTool`** - Wraps Python functions as tools with JSON schema generation
- **`@tool`** decorator - Converts functions to tools
- **`use_function_invocation()`** - Decorator to add automatic function calling to chat clients
### Middleware (`_middleware.py`)
- **`AgentMiddleware`** - Intercepts agent `run()` calls
- **`ChatMiddleware`** - Intercepts chat client `get_response()` calls
- **`FunctionMiddleware`** - Intercepts function/tool invocations
- **`AgentRunContext`** / **`ChatContext`** / **`FunctionInvocationContext`** - Context objects passed through middleware
### Threads (`_threads.py`)
- **`AgentThread`** - Manages conversation history for an agent
- **`ChatMessageStoreProtocol`** - Protocol for persistent message storage
- **`ChatMessageStore`** - Default in-memory implementation
### Memory (`_memory.py`)
- **`ContextProvider`** - Protocol for providing additional context to agents (RAG, memory systems)
- **`Context`** - Container for context data
### Workflows (`_workflows/`)
- **`Workflow`** - Graph-based workflow definition
- **`WorkflowBuilder`** - Fluent API for building workflows
- **Orchestrators**: `SequentialOrchestrator`, `ConcurrentOrchestrator`, `GroupChatOrchestrator`, `MagenticOrchestrator`, `HandoffOrchestrator`
## Built-in Providers
### OpenAI (`openai/`)
- **`OpenAIChatClient`** - Chat client for OpenAI API
- **`OpenAIResponsesClient`** - Client for OpenAI Responses API
### Azure OpenAI (`azure/`)
- **`AzureOpenAIChatClient`** - Chat client for Azure OpenAI
- **`AzureOpenAIResponsesClient`** - Client for Azure OpenAI Responses API
## Key Patterns
### Creating an Agent
```python
from agent_framework import ChatAgent
from agent_framework.openai import OpenAIChatClient
agent = ChatAgent(
chat_client=OpenAIChatClient(),
instructions="You are helpful.",
tools=[my_function],
)
response = await agent.run("Hello")
```
### Using `as_agent()` Shorthand
```python
agent = OpenAIChatClient().as_agent(
name="Assistant",
instructions="You are helpful.",
)
```
### Middleware Pipeline
```python
from agent_framework import ChatAgent, AgentMiddleware, AgentRunContext
class LoggingMiddleware(AgentMiddleware):
async def invoke(self, context: AgentRunContext, next) -> AgentResponse:
print(f"Input: {context.messages}")
response = await next(context)
print(f"Output: {response}")
return response
agent = ChatAgent(..., middleware=[LoggingMiddleware()])
```
### Custom Chat Client
```python
from agent_framework import BaseChatClient, ChatResponse, ChatMessage
class MyClient(BaseChatClient):
async def _inner_get_response(self, *, messages, options, **kwargs) -> ChatResponse:
# Call your LLM here
return ChatResponse(messages=[ChatMessage(role="assistant", text="Hi!")])
async def _inner_get_streaming_response(self, *, messages, options, **kwargs):
yield ChatResponseUpdate(...)
```
+33
View File
@@ -0,0 +1,33 @@
# Declarative Package (agent-framework-declarative)
YAML/JSON-based declarative agent and workflow definitions.
## Main Classes
- **`AgentFactory`** - Creates agents from declarative definitions
- **`WorkflowFactory`** - Creates workflows from declarative definitions
- **`WorkflowState`** - State management for declarative workflows
- **`ProviderTypeMapping`** - Maps provider types to implementations
- **`DeclarativeLoaderError`** / **`ProviderLookupError`** - Error types
## External Input Handling
- **`ExternalInputRequest`** / **`ExternalInputResponse`** - Human-in-the-loop support
- **`AgentExternalInputRequest`** / **`AgentExternalInputResponse`** - Agent-level input requests
## Usage
```python
from agent_framework.declarative import AgentFactory, WorkflowFactory
agent = AgentFactory.create_from_file("agent.yaml")
workflow = WorkflowFactory.create_from_file("workflow.yaml")
```
## Import Path
```python
from agent_framework.declarative import AgentFactory, WorkflowFactory
# or directly:
from agent_framework_declarative import AgentFactory
```
+43
View File
@@ -0,0 +1,43 @@
# DevUI Package (agent-framework-devui)
Interactive developer UI for testing and debugging agents and workflows.
## Main Classes
- **`serve()`** - Launch the DevUI server
- **`DevServer`** - The FastAPI-based development server
- **`register_cleanup()`** - Register cleanup hooks for entities
- **`CheckpointConversationManager`** - Manages conversation checkpoints
## Models
- **`AgentFrameworkRequest`** - Request model for agent invocations
- **`OpenAIResponse`** / **`OpenAIError`** - OpenAI-compatible response models
- **`DiscoveryResponse`** / **`EntityInfo`** - Entity discovery models
## Usage
```python
from agent_framework.devui import serve
agent = ChatAgent(...)
serve(entities=[agent], port=8080, auto_open=True)
```
## CLI
```bash
# Run with auto-discovery
devui ./agents
# Run with specific entities
devui --entities my_agent.py
```
## Import Path
```python
from agent_framework.devui import serve, register_cleanup
# or directly:
from agent_framework_devui import serve
```
+46
View File
@@ -0,0 +1,46 @@
# Durable Task Package (agent-framework-durabletask)
Durable execution support for long-running agent workflows using Azure Durable Functions.
## Main Classes
### Client Side
- **`DurableAIAgentClient`** - Client for invoking durable agents
- **`DurableAIAgent`** - Shim for creating durable agents
### Worker Side
- **`DurableAIAgentWorker`** - Worker that executes durable agent tasks
- **`DurableAgentExecutor`** - Executes agent logic within durable context
- **`AgentEntity`** - Durable entity for agent state management
### State Management
- **`DurableAgentState`** - State container for durable agents
- **`DurableAgentThread`** - Thread management for durable agents
- **`DurableAIAgentOrchestrationContext`** - Orchestration context
### Callbacks
- **`AgentCallbackContext`** - Context for agent callbacks
- **`AgentResponseCallbackProtocol`** - Protocol for response callbacks
## Usage
```python
from agent_framework_durabletask import DurableAIAgentClient, DurableAIAgentWorker
# Client side
client = DurableAIAgentClient(endpoint="https://your-functions.azurewebsites.net")
response = await client.run("Hello")
# Worker side
worker = DurableAIAgentWorker(agent=my_agent)
```
## Import Path
```python
from agent_framework_durabletask import DurableAIAgentClient, DurableAIAgentWorker
```
+24
View File
@@ -0,0 +1,24 @@
# Foundry Local Package (agent-framework-foundry-local)
Integration with Azure AI Foundry Local for local model inference.
## Main Classes
- **`FoundryLocalClient`** - Chat client for Foundry Local models
- **`FoundryLocalChatOptions`** - Options TypedDict for Foundry Local parameters
- **`FoundryLocalSettings`** - Pydantic settings for configuration
## Usage
```python
from agent_framework_foundry_local import FoundryLocalClient
client = FoundryLocalClient(model_id="your-local-model")
response = await client.get_response("Hello")
```
## Import Path
```python
from agent_framework_foundry_local import FoundryLocalClient
```
+26
View File
@@ -0,0 +1,26 @@
# GitHub Copilot Package (agent-framework-github-copilot)
Integration with GitHub Copilot extensions.
## Main Classes
- **`GitHubCopilotAgent`** - Agent for GitHub Copilot extensions
- **`GitHubCopilotOptions`** - Options for Copilot agent configuration
- **`GitHubCopilotSettings`** - Pydantic settings for configuration
## Usage
```python
from agent_framework.github import GitHubCopilotAgent
agent = GitHubCopilotAgent(...)
response = await agent.run("Hello")
```
## Import Path
```python
from agent_framework.github import GitHubCopilotAgent
# or directly:
from agent_framework_github_copilot import GitHubCopilotAgent
```
+22
View File
@@ -0,0 +1,22 @@
# Lab Package (agent-framework-lab)
Experimental packages for cutting-edge features including benchmarking, reinforcement learning, and research initiatives.
## Structure
This package contains experimental sub-packages:
- `gaia/` - GAIA benchmark integration
- `lightning/` - Lightning-based training utilities
- `tau2/` - Tau-bench evaluation framework
- `namespace/` - Experimental namespace utilities
## Note
Lab packages are experimental and may change frequently. They are not included in the standard `agent-framework[all]` installation.
## Installation
```bash
pip install agent-framework-lab
```
+28
View File
@@ -0,0 +1,28 @@
# Mem0 Package (agent-framework-mem0)
Integration with Mem0 for agent memory management.
## Main Classes
- **`Mem0Provider`** - Context provider that integrates Mem0 memory into agents
## Usage
```python
from agent_framework.mem0 import Mem0Provider
provider = Mem0Provider(api_key="your-key")
agent = ChatAgent(..., context_provider=provider)
```
## Import Path
```python
from agent_framework.mem0 import Mem0Provider
# or directly:
from agent_framework_mem0 import Mem0Provider
```
## Notes
Mem0 telemetry is disabled by default. Set `MEM0_TELEMETRY=true` to enable.
+26
View File
@@ -0,0 +1,26 @@
# Ollama Package (agent-framework-ollama)
Integration with Ollama for local LLM inference.
## Main Classes
- **`OllamaChatClient`** - Chat client for Ollama models
- **`OllamaChatOptions`** - Options TypedDict for Ollama-specific parameters
- **`OllamaSettings`** - Pydantic settings for Ollama configuration
## Usage
```python
from agent_framework.ollama import OllamaChatClient
client = OllamaChatClient(model_id="llama3.2")
response = await client.get_response("Hello")
```
## Import Path
```python
from agent_framework.ollama import OllamaChatClient
# or directly:
from agent_framework_ollama import OllamaChatClient
```
+44
View File
@@ -0,0 +1,44 @@
# Purview Package (agent-framework-purview)
Integration with Microsoft Purview for data governance and policy enforcement.
## Main Classes
### Middleware
- **`PurviewPolicyMiddleware`** - Agent middleware for Purview policy enforcement
- **`PurviewChatPolicyMiddleware`** - Chat-level middleware for policy enforcement
### Configuration
- **`PurviewSettings`** - Pydantic settings for Purview configuration
- **`PurviewAppLocation`** / **`PurviewLocationType`** - Location configuration
### Caching
- **`CacheProvider`** - Cache provider for Purview policy caching
### Exceptions
- **`PurviewAuthenticationError`** - Authentication failures
- **`PurviewRateLimitError`** - Rate limit exceeded
- **`PurviewRequestError`** / **`PurviewServiceError`** - Request/service errors
- **`PurviewPaymentRequiredError`** - Payment required
## Usage
```python
from agent_framework.microsoft import PurviewPolicyMiddleware, PurviewSettings
settings = PurviewSettings(...)
middleware = PurviewPolicyMiddleware(settings=settings)
agent = ChatAgent(..., middleware=[middleware])
```
## Import Path
```python
from agent_framework.microsoft import PurviewPolicyMiddleware
# or directly:
from agent_framework_purview import PurviewPolicyMiddleware
```
+25
View File
@@ -0,0 +1,25 @@
# Redis Package (agent-framework-redis)
Redis-based storage for agent threads and context.
## Main Classes
- **`RedisChatMessageStore`** - Persistent message store using Redis
- **`RedisProvider`** - Context provider with Redis backing
## Usage
```python
from agent_framework.redis import RedisChatMessageStore
store = RedisChatMessageStore(redis_url="redis://localhost:6379")
agent = ChatAgent(..., chat_message_store_factory=lambda: store)
```
## Import Path
```python
from agent_framework.redis import RedisChatMessageStore, RedisProvider
# or directly:
from agent_framework_redis import RedisChatMessageStore
```
+1
View File
@@ -227,6 +227,7 @@ format.ref = "fmt"
lint = "python run_tasks_in_packages_if_exists.py lint"
pyright = "python run_tasks_in_packages_if_exists.py pyright"
mypy = "python run_tasks_in_packages_if_exists.py mypy"
typing = ["pyright", "mypy"]
# cleaning
clean-dist-packages = "python run_tasks_in_packages_if_exists.py clean-dist"
clean-dist-meta = "rm -rf dist"