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
11 changes: 11 additions & 0 deletions .github/instructions/dotnet.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
applyTo: 'dotnet/**'
---

Before reviewing .NET changes, read and apply
[dotnet/AGENTS.md](../../dotnet/AGENTS.md). Use the task-specific skills under
`dotnet/.github/skills/` for build and test commands, project structure, pull
requests, and sample verification.

Do not duplicate purely mechanical findings that `dotnet format`, analyzers, or
other required CI checks will report.
18 changes: 18 additions & 0 deletions .github/instructions/python.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
applyTo: 'python/**'
---

Before reviewing Python changes, read and apply the canonical
[Python coding standards](../../python/CODING_STANDARD.md). Use
[python/AGENTS.md](../../python/AGENTS.md) and the nearest package or sample `AGENTS.md`
for task-specific architecture and workflow guidance.
Comment thread
eavanvalkenburg marked this conversation as resolved.

- Review new or materially edited code against the standards. Do not report unrelated legacy convention violations
elsewhere in a touched file.
- Independently report material correctness or security defects visible in affected files, even when they predate
the changed lines.
- Treat `MUST` and `MUST NOT` violations as review findings.
- Report `SHOULD` and `SHOULD NOT` violations when they have a material correctness, API, maintainability,
performance, or usability impact.
- Do not report `MAY` choices as violations.
- Do not duplicate purely mechanical findings that Ruff, Pyright, or another required CI check will report.
10 changes: 0 additions & 10 deletions python/.github/instructions/python.instructions.md

This file was deleted.

165 changes: 43 additions & 122 deletions python/.github/skills/python-development/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,127 +1,48 @@
---
name: python-development
description: >
Coding standards, conventions, and patterns for developing Python code in the
Agent Framework repository. Use this when writing or modifying Python source
files in the python/ directory.
Workflow guidance for developing Python code in the Agent Framework
repository. Use this when writing or modifying Python source files under
python/.
---

# Python Development Standards

## File Header

Every `.py` file must start with:

```python
# Copyright (c) Microsoft. All rights reserved.
```

## Type Annotations

- Always specify return types and parameter types
- Use `Type | None` instead of `Optional[Type]`
- Use `from __future__ import annotations` to enable postponed evaluation
- Use suffix `T` for TypeVar names: `ChatResponseT = TypeVar("ChatResponseT", bound=ChatResponse)`
- Use `Mapping` instead of `MutableMapping` for read-only input parameters
- Prefer `# type: ignore[...]` over unnecessary casts, or `isinstance` checks, when these are internally called and executed methods
But make sure the ignore is specific for both mypy and pyright so that we don't miss other mistakes
- Internal private helpers may be used across `agent_framework*` modules when intentional; use a targeted
`# pyright: ignore[reportPrivateUsage]` instead of making the helper public just to satisfy pyright.
- Do not add trivial pass-through or one-line helper functions solely to appease typing. Prefer targeted ignores,
casts, or clearer annotations over adding runtime overhead without a design benefit.

## Function Parameters

- Positional parameters: up to 3 fully expected parameters
- Use keyword-only arguments (after `*`) for optional parameters
- Provide string-based overrides to avoid requiring extra imports:

```python
def create_agent(name: str, tool_mode: Literal['auto', 'required', 'none'] | ChatToolMode) -> Agent:
if isinstance(tool_mode, str):
tool_mode = ChatToolMode(tool_mode)
```

- Avoid shadowing built-ins (use `next_handler` instead of `next`)
- Avoid `**kwargs` unless needed for subclass extensibility; prefer named parameters

## Docstrings

Use Google-style docstrings for all public APIs:

```python
def equal(arg1: str, arg2: str) -> bool:
"""Compares two strings and returns True if they are the same.

Args:
arg1: The first string to compare.
arg2: The second string to compare.

Returns:
True if the strings are the same, False otherwise.

Raises:
ValueError: If one of the strings is empty.
"""
```

- Always document Agent Framework specific exceptions
- Explicitly use `Keyword Args` when applicable
- Only document standard Python exceptions when the condition is non-obvious

## Import Structure

```python
# Core
from agent_framework import Agent, Message, tool

# Components
from agent_framework.observability import enable_sensitive_telemetry

# Connectors (lazy-loaded)
from agent_framework.openai import OpenAIChatClient
from agent_framework.foundry import FoundryChatClient
```

## Public API and Exports

In `__init__.py` files that define package-level public APIs, use direct re-export imports plus an explicit
`__all__`. Avoid identity aliases like `from ._agents import Agent as Agent`, and avoid
`from module import *`.

Do not define `__all__` in internal non-`__init__.py` modules. Exception: modules intentionally exposed as a
public import surface (for example, `agent_framework.observability`) should define `__all__`.

```python
__all__ = ["Agent", "Message", "ChatResponse"]

from ._agents import Agent
from ._types import Message, ChatResponse
```

Special case: the root `agent_framework/__init__.py` uses lazy runtime exports. For root public API changes:
- Add the symbol to `_LAZY_MODULE_EXPORTS` and keep `_LAZY_EXPORTS` derived from it.
- Keep the explicit runtime `__all__` synchronized; it is still required for `from agent_framework import *`.
- Add the same public symbol to `agent_framework/__init__.pyi` so pyright, mypy, and editors see the typed surface.
- Put runtime deprecation behavior in the owning module via that module's `__getattr__`; avoid root-level
special-case branches for individual deprecated exports.
- Identity aliases are appropriate in `.pyi` stubs because they mark re-exported names for type checkers; avoid them
in runtime `.py` modules unless there is a specific compatibility reason.

## Performance Guidelines

- Cache expensive computations (e.g., JSON schema generation)
- Prefer `match/case` on `.type` attribute over `isinstance()` in hot paths
- Avoid redundant serialization — compute once, reuse

## Style

- Line length: 120 characters
- Format only files you changed, not the entire codebase
- Prefer attributes over inheritance when parameters are mostly the same
- Async by default — assume everything is asynchronous

## Naming Conventions for Connectors

- `_prepare_<object>_for_<purpose>` for methods that prepare data for external services
- `_parse_<object>_from_<source>` for methods that process data from external services
# Python Development Workflow

The canonical engineering rules are in
[`python/CODING_STANDARD.md`](../../../CODING_STANDARD.md). Read and apply that
document before changing Python source. Do not create or maintain a competing
copy of the standards in this skill.

## Before Editing

1. Read `python/AGENTS.md` and the nearest package `AGENTS.md`.
2. Identify whether the change affects package source, tests, samples, public
exports, package governance, or more than one of those surfaces.
3. Read the task-specific skill when applicable:
- `python-testing` for test design, integration markers, and test commands.
- `python-code-quality` for formatting, linting, and type checking.
- `python-package-management` for package creation, dependencies, public
lazy exports, and package lifecycle.
- `python-feature-lifecycle` for staged API decorators and promotion.

## Implementing Changes

- Follow established patterns in the owning package unless they conflict with
`python/CODING_STANDARD.md`.
- Keep the common public path import-light and review public API changes for
compatibility and ergonomics.
- Update source, typing surfaces, tests, samples, and documentation together
when they represent the same contract.
- For root `agent_framework` export changes, follow the synchronized runtime,
`__all__`, and `.pyi` workflow in `python-package-management`.
- Do not broaden a change into unrelated cleanup solely because nearby code
predates the current standard.

## Validation

Run the smallest relevant commands from `python/`. Use
`python-code-quality` and `python-testing` to select package-scoped syntax,
typing, and test commands before escalating to broader checks.

When a convention, command, or workflow changes, update the canonical document
or owning task-specific skill rather than duplicating the new guidance here.
25 changes: 18 additions & 7 deletions python/.github/skills/python-testing/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ description: >
CI enforces at least 85% line coverage for every package classified Beta or Production/Stable.
Alpha packages are report-only, and the DevUI and experimental Lab packages are excluded from
aggregate coverage enforcement. Tests should be fast, reliable, and maintainable.
When adding new code, check that the relevant sections of the codebase are covered by tests, and add new tests as needed. When modifying existing code, update or add tests to cover the changes.
Test observable behavior first, and use coverage as a backstop. Meaningful new branches, error paths,
and edge cases must be covered without coupling tests to implementation details.
Before writing new tests, inspect the existing tests and coverage for the affected behavior. For refactors and
behavior-preserving implementation changes, update existing tests when they already express the contract. Add new
tests for new behavior, regressions, or a meaningful coverage gap rather than by default for every production edit.
We run tests in two stages, for a PR each commit is tested with unit tests only (using `-m "not integration"`), and the full suite including integration tests is run when merging.

When an API is marked as deprecated, migrate ordinary tests to its replacement in the same change. Retain only
Expand Down Expand Up @@ -83,25 +87,30 @@ packages/core/

- Use `conftest.py` for shared fixtures within a test directory
- Before adding new fixtures, check if existing ones can be reused or extended
- For reusable setup that needs call-time parameters, use a fixture that returns a callable factory
- Consume fixtures through pytest injection; do not import fixtures or helpers from `conftest.py`
- Put non-fixture helpers in a normal helper module and import them explicitly
- Use descriptive names: `mapper`, `test_request`, `mock_client`

## File Naming

- Files starting with `test_` are test files — do not use this prefix for helpers
- Prefer extending an existing test file that already covers the same component or behavior; create a new file only for a distinct surface without an appropriate existing file
- Use `conftest.py` for shared utilities
- Use `conftest.py` for shared fixtures and normal helper modules for other shared utilities

## Integration Tests

Integration tests require external services (OpenAI, Azure, etc.) and are controlled by three markers:
Integration tests require external services (OpenAI, Azure, etc.) and must be selectable and safely skippable:

1. **`@pytest.mark.flaky`** — marks the test as potentially flaky since it depends on external services
2. **`@pytest.mark.integration`** — used for test selection, so integration tests can be included/excluded with `-m integration` / `-m "not integration"`
3. **`@skip_if_..._integration_tests_disabled`** decorator — skips the test when the required API keys or service endpoints are missing
1. **`@pytest.mark.integration`** — used for test selection, so integration tests can be included/excluded with `-m integration` / `-m "not integration"`
2. **`@skip_if_..._integration_tests_disabled`** decorator — skips the test when the required API keys or service endpoints are missing
3. **`@pytest.mark.flaky`** — add this only when the test is genuinely nondeterministic or service-sensitive

### Adding New Integration Tests

All three markers must be applied to every new integration test:
Every new integration test must have the integration marker and provider-specific skip condition. Add the flaky
marker when the scenario depends on timing, eventual consistency, a nondeterministic model response, or another
service-sensitive condition:

```python
@pytest.mark.flaky
Expand Down Expand Up @@ -160,5 +169,7 @@ The `python-tests-misc-integration` job is intended for small integration test s

- Run only related tests, not the entire suite
- Review existing tests to understand coding style before creating new ones
- Test through the public or observable contract
- Mock external boundaries rather than the internal unit whose behavior the test should prove
- Use print statements for debugging, then remove them when done
- Resolve all errors and warnings before committing
4 changes: 2 additions & 2 deletions python/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ 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
- [CODING_STANDARD.md](CODING_STANDARD.md) - Canonical Python engineering and API-design standards
- [samples/SAMPLE_GUIDELINES.md](samples/SAMPLE_GUIDELINES.md) - Sample structure and guidelines
- [Python function-calling loop specification](../docs/specs/004-python-function-calling-loop.md) - Required
behavior, scenario-to-test mapping, coverage gaps, and extra validation for function-loop changes

**Agent Skills** (`.github/skills/`) — detailed, task-specific instructions loaded on demand:
- `python-development` — coding standards, type annotations, docstrings, logging, performance
- `python-development` — Python development workflow and routing to the canonical standards and task-specific skills
- `python-testing` — test structure, fixtures, async mode, running tests
- `python-code-quality` — linting, formatting, type checking, prek hooks, CI workflow
- `python-feature-lifecycle` — package-stage meaning plus staged API decorators, enums, and feature promotion
Expand Down
Loading
Loading