diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 445c245f17..78bcaa7842 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -12,3 +12,6 @@ # .NET owners /dotnet/ @eavanvalkenburg @SergeyMenshykh @rogerbarreto @westey-m @moonbox3 @baywet @peibekwe + +# Public Python consumer skill +/skills/agent-framework-builder-python/ @eavanvalkenburg @SergeyMenshykh @rogerbarreto @westey-m @moonbox3 @jpalvarezl @sophia-ramsey @TaoChenOSU @giles17 diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 96d92f163f..5de768027a 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -7,6 +7,19 @@ Microsoft Agent Framework - a multi-language framework for building, orchestrati - `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 +- `skills/` - Public, installable Agent Skills for developers using Agent Framework + +## Public Consumer Skills + +The skills under `skills/` are distribution artifacts for developers building Agent Framework applications. They are +not project skills for contributors working in this repository: + +- Do not load or invoke them as instructions for normal Agent Framework repository work. +- Keep them outside `.github/skills`, `.agents/skills`, and `.claude/skills` so coding agents do not auto-discover them. +- When a change affects public APIs, packages, samples, configuration, evaluation, integrations, or hosting guidance, + review and update the corresponding consumer skill as maintained product documentation. +- Read a consumer skill during repository work only when that maintenance check is relevant; do not let its standalone + application defaults override repository-specific instructions. ## Architectural Decision Records (ADRs) diff --git a/.github/scripts/validate_agent_skill_links.py b/.github/scripts/validate_agent_skill_links.py new file mode 100644 index 0000000000..1c98614615 --- /dev/null +++ b/.github/scripts/validate_agent_skill_links.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python3 +# Copyright (c) Microsoft. All rights reserved. +"""Validate local Markdown resources bundled with public Agent Skills.""" + +from __future__ import annotations + +import re +import stat +import sys +from pathlib import Path + +LINK_PATTERN = re.compile(r"\[[^\]]+\]\(([^)]+)\)") + + +def validate_agent_skill_links(skills_directory: Path) -> list[str]: + """Return validation errors for local Markdown links in public Agent Skills.""" + errors: list[str] = [] + skill_roots = sorted(path.parent for path in skills_directory.rglob("SKILL.md")) + + if not skill_roots: + return [f"No Agent Skills found under {skills_directory}."] + + for skill_root in skill_roots: + resolved_root = skill_root.resolve(strict=True) + for markdown_path in skill_root.rglob("*.md"): + for target in LINK_PATTERN.findall(markdown_path.read_text(encoding="utf-8")): + if "://" in target or target.startswith(("#", "mailto:")): + continue + + relative_target = target.split("#", 1)[0] + if not relative_target: + continue + + target_path = Path(relative_target) + if target_path.is_absolute(): + errors.append(f"{markdown_path}: absolute local link is not allowed: {target}") + continue + + candidate = markdown_path.parent / target_path + try: + resolved_candidate = candidate.resolve(strict=True) + except FileNotFoundError: + errors.append(f"{markdown_path}: missing local resource: {target}") + continue + + try: + resolved_candidate.relative_to(resolved_root) + except ValueError: + errors.append(f"{markdown_path}: local resource escapes skill root: {target}") + continue + + if not stat.S_ISREG(candidate.lstat().st_mode): + errors.append(f"{markdown_path}: local resource is not a regular file: {target}") + + return errors + + +def main() -> None: + skills_directory = Path(sys.argv[1]) if len(sys.argv) > 1 else Path("skills") + errors = validate_agent_skill_links(skills_directory) + if errors: + raise SystemExit("\n".join(errors)) + + +if __name__ == "__main__": + main() diff --git a/.github/tests/test_validate_agent_skill_links.py b/.github/tests/test_validate_agent_skill_links.py new file mode 100644 index 0000000000..a309104b82 --- /dev/null +++ b/.github/tests/test_validate_agent_skill_links.py @@ -0,0 +1,82 @@ +# Copyright (c) Microsoft. All rights reserved. + +# ruff:file-ignore[implicit-namespace-package, undocumented-public-class, undocumented-public-method] + +from __future__ import annotations + +import sys +import tempfile +import unittest +from pathlib import Path + +sys.path.insert(0, str(Path(__file__).parents[1] / "scripts")) + +from validate_agent_skill_links import validate_agent_skill_links + + +class ValidateAgentSkillLinksTests(unittest.TestCase): + def setUp(self) -> None: + self.temp_dir = tempfile.TemporaryDirectory() + self.root = Path(self.temp_dir.name) + self.skills = self.root / "skills" + self.skill = self.skills / "example-skill" + self.skill.mkdir(parents=True) + + def tearDown(self) -> None: + self.temp_dir.cleanup() + + def write_skill(self, body: str) -> None: + (self.skill / "SKILL.md").write_text(body, encoding="utf-8") + + def test_accepts_regular_file_inside_skill(self) -> None: + (self.skill / "references").mkdir() + (self.skill / "references" / "details.md").write_text("# Details\n", encoding="utf-8") + self.write_skill("[Details](references/details.md)\n") + + self.assertEqual([], validate_agent_skill_links(self.skills)) + + def test_rejects_parent_traversal(self) -> None: + (self.skills / "outside.md").write_text("# Outside\n", encoding="utf-8") + self.write_skill("[Outside](../outside.md)\n") + + errors = validate_agent_skill_links(self.skills) + + self.assertTrue(any("escapes skill root" in error for error in errors)) + + def test_rejects_absolute_path(self) -> None: + absolute_file = self.root / "outside.md" + absolute_file.write_text("# Outside\n", encoding="utf-8") + self.write_skill(f"[Outside]({absolute_file})\n") + + errors = validate_agent_skill_links(self.skills) + + self.assertTrue(any("absolute local link" in error for error in errors)) + + def test_rejects_directory_target(self) -> None: + (self.skill / "references").mkdir() + self.write_skill("[References](references)\n") + + errors = validate_agent_skill_links(self.skills) + + self.assertTrue(any("not a regular file" in error for error in errors)) + + def test_rejects_symlink_target(self) -> None: + target = self.skill / "details.md" + target.write_text("# Details\n", encoding="utf-8") + (self.skill / "linked.md").symlink_to(target) + self.write_skill("[Details](linked.md)\n") + + errors = validate_agent_skill_links(self.skills) + + self.assertTrue(any("not a regular file" in error for error in errors)) + + def test_rejects_missing_target(self) -> None: + self.write_skill("[Missing](references/missing.md)\n") + + errors = validate_agent_skill_links(self.skills) + + self.assertTrue(any("missing local resource" in error for error in errors)) + + +if __name__ == "__main__": + unittest.main() diff --git a/.github/workflows/agent-skills.yml b/.github/workflows/agent-skills.yml new file mode 100644 index 0000000000..055b246010 --- /dev/null +++ b/.github/workflows/agent-skills.yml @@ -0,0 +1,62 @@ +name: Validate Agent Skills + +on: + workflow_dispatch: + pull_request: + paths: + - "skills/**" + - ".github/scripts/validate_agent_skill_links.py" + - ".github/tests/test_validate_agent_skill_links.py" + - ".github/workflows/agent-skills.yml" + push: + branches: ["main"] + paths: + - "skills/**" + - ".github/scripts/validate_agent_skill_links.py" + - ".github/tests/test_validate_agent_skill_links.py" + - ".github/workflows/agent-skills.yml" + +permissions: + contents: read + +jobs: + validate: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 + with: + python-version: "3.13" + + - uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0 + with: + version-file: "python/pyproject.toml" + + - name: Validate Agent Skills specification + shell: bash + run: | + set -euo pipefail + + found_skill=0 + while IFS= read -r skill_file; do + [[ -z "$skill_file" ]] && continue + found_skill=1 + uvx --from "skills-ref==0.1.1" agentskills validate "$(dirname "$skill_file")" + done < <(find skills -mindepth 2 -maxdepth 2 -name SKILL.md -print | sort) + + if (( found_skill == 0 )); then + echo "No public Agent Skills found under skills/." >&2 + exit 1 + fi + + - name: Validate relative resource links + run: | + python .github/tests/test_validate_agent_skill_links.py + python .github/scripts/validate_agent_skill_links.py skills + + - name: Validate GitHub skill publishing + env: + GH_TOKEN: ${{ github.token }} + run: gh skill publish skills --dry-run diff --git a/README.md b/README.md index c5b3b07d9b..5d20026ec9 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,7 @@ Explore new MAF capabilities and real implementation patterns on the [official b - [Quickstart](#quickstart) - [Basic Agent - Python](#basic-agent---python) - [Basic Agent - .NET](#basic-agent---net) +- [Agent Skills for Coding Agents](#agent-skills-for-coding-agents) - [More Examples & Samples](#more-examples--samples) - [Community & Feedback](#community--feedback) - [Troubleshooting](#troubleshooting) @@ -161,6 +162,23 @@ AIAgent agent = Console.WriteLine(await agent.RunAsync("Write a haiku about Microsoft Agent Framework.")); ``` +## Agent Skills for Coding Agents + +Install the Python Agent Framework builder skill to give a compatible coding agent current guidance for choosing and +building agents, harnesses, workflows, evaluations, integrations, and hosting: + +```bash +gh skill install microsoft/agent-framework agent-framework-builder-python +``` + +The cross-agent `skills` CLI is also supported: + +```bash +npx skills add microsoft/agent-framework --skill agent-framework-builder-python +``` + +See the [consumer skills catalog](./skills/) for details. + ## More Examples & Samples ### Python diff --git a/python/AGENTS.md b/python/AGENTS.md index 86f19e4571..c05ca07b00 100644 --- a/python/AGENTS.md +++ b/python/AGENTS.md @@ -18,11 +18,17 @@ Instructions for AI coding agents working in the Python codebase. - `pull-requests` — writing PR descriptions (template) and handling/resolving PR review comments - `agent-framework-py-release` — Python release PR workflow, CHANGELOG-driven package bumps, lifecycle version rules, and dependency-floor validation +**Public consumer skill** (`../skills/agent-framework-builder-python/`) — installable guidance for developers building +Python Agent Framework applications. It is a distribution artifact, not a repository skill: do not invoke it for +normal framework development. Review it as documentation when changes affect the public developer experience. + ## Maintaining Documentation When making changes to a package, check if the following need updates: - The package's `AGENTS.md` file (adding/removing/renaming public APIs, architecture changes, import path changes) - The agent skills in `.github/skills/` if conventions, commands, or workflows change +- The public Python consumer skill in `../skills/agent-framework-builder-python/` if public APIs, package names or + maturity, canonical samples, configuration, evaluation, integrations, or hosting guidance change At the end of every run, re-read `AGENTS.md` and the relevant skill files and update any guidance that the conversation revealed to be out of date, @@ -31,6 +37,9 @@ the user confirmed, etc.). **Before adding a new principle or rule, ask the user whether they want it captured as a durable principle** — do not invent team norms from a single conversation without explicit confirmation. +Only inspect the public consumer skill when the change falls into its maintenance scope. Do not load it as an active +skill or apply its standalone-project defaults to this monorepo. + ## Terminology - **Avoid "GA" for Agent Framework code.** Reserve *GA* for hosted services diff --git a/skills/README.md b/skills/README.md new file mode 100644 index 0000000000..da7d2406c4 --- /dev/null +++ b/skills/README.md @@ -0,0 +1,35 @@ +# Microsoft Agent Framework consumer skills + +This directory contains installable Agent Skills for developers building applications with Microsoft Agent Framework. +These are public distribution artifacts, not contributor instructions for working on the Agent Framework repository. + +## Available skills + +| Skill | Purpose | +| --- | --- | +| `agent-framework-builder-python` | Build, modify, evaluate, integrate, and host Python Agent Framework applications. | + +## Install + +Preview and install with GitHub CLI: + +```bash +gh skill preview microsoft/agent-framework agent-framework-builder-python +gh skill install microsoft/agent-framework agent-framework-builder-python +``` + +Or use the cross-agent skills CLI: + +```bash +npx skills add microsoft/agent-framework --skill agent-framework-builder-python +``` + +## Repository maintenance contract + +- Coding agents working on Agent Framework itself must not treat the skills in this directory as repository + instructions or automatically load them for normal framework development. +- Keep the skills outside `.github/skills`, `.agents/skills`, and `.claude/skills` so repository agents do not + discover them as project skills. +- Review the Python consumer skill whenever a change affects public APIs, package names or maturity, canonical samples, + configuration, evaluation, integrations, or hosting guidance. +- Update only the affected guidance. Do not copy internal contributor conventions into the consumer skill. diff --git a/skills/agent-framework-builder-python/SKILL.md b/skills/agent-framework-builder-python/SKILL.md new file mode 100644 index 0000000000..8a0d4508eb --- /dev/null +++ b/skills/agent-framework-builder-python/SKILL.md @@ -0,0 +1,104 @@ +--- +name: agent-framework-builder-python +description: Use this skill when building, modifying, reviewing, evaluating, integrating, or hosting Python applications with Microsoft Agent Framework. Use it for Agent Framework agents, harness agents, workflows, orchestrations, declarative definitions, tools, sessions, middleware, evaluation, observability, integrations, or hosting, even when the user has not yet chosen the correct framework pattern. +license: MIT +metadata: + version: "0.3" + project: agent-framework + language: python +--- + +# Agent Framework builder for Python + +Use this skill as the entry point for Python Agent Framework application work. Choose the smallest framework pattern +that preserves the required behavior, load only the relevant references, and validate against current APIs instead of +relying on remembered preview-era syntax. + +## Workflow + +1. Inspect the existing project, Python version, dependency manager, and installed Agent Framework packages. +2. Choose the simplest matching path from the table below. +3. Resolve design questions only when they materially change the implementation. +4. Read only the linked reference for the selected path. +5. Implement the smallest coherent change and run the narrowest validation that exercises it. + +## Core abstractions + +- A **chat client** implements the model-facing `SupportsChatGetResponse` protocol. It sends messages and options to a + model provider and returns chat responses or streaming updates. +- An **agent** implements the `SupportsAgentRun` protocol. The standard `Agent` implementation combines a chat client + with instructions, tools, middleware, context providers, and session handling behind one `run(...)` interface. +- A **harness agent** is a regular `Agent` assembled by `create_harness_agent`. It adds an opinionated set of context + providers and middleware; it does not introduce a separate agent abstraction. +- A **workflow** coordinates explicit execution paths. Graph workflows and most orchestration builders can use multiple + `SupportsAgentRun` implementations or executors. `HandoffBuilder` is the exception: its participants must be concrete + `Agent` instances. + +## User interface options + +- **DevUI** is a local development, testing, and debugging tool for interacting with agents and workflows. Never run + or deploy DevUI as a production application host. +- **AG-UI** is the application-facing protocol integration for connecting an agent or workflow to an AG-UI-compatible + frontend. Use the `agent-framework-ag-ui` package when the product needs streaming UI events, tool interactions, + shared state, interrupts, or resume behavior. + +## Choose the build path + +| Path | Choose it when | Details | +| --- | --- | --- | +| Plain agent | One model-driven actor owns the task and tools, sessions, context, and middleware are sufficient. | [Plain agents](references/agent-builder.md) | +| Harness agent | The product needs an operating loop with todos, modes, memory, approvals, skills, optional file access, background agents, shell, compaction, or repeated execution. | [Harness agents](references/harness-agent-builder.md) | +| Workflow or orchestration | Explicit stages, routing, parallelism, multiple participants, checkpointing, human input, or intermediate outputs are central to correctness. | [Workflows](references/workflow-builder.md) | +| Declarative definition | YAML or JSON should be the source of truth for a supported agent or workflow. | [Declarative definitions](references/declarative.md) | +| Evaluation | Expected outputs, tool calls, failed runs, or quality regressions are the main concern. | [Evaluation](references/evaluation.md) | +| Observability | The task is diagnosing or monitoring runtime behavior with traces, logs, and metrics. | [Observability](references/observability.md) | +| Extensibility | The application needs a custom provider, ContextProvider, or middleware component. | [Extensibility](references/extensibility.md) | +| Integration | The task is choosing or wiring a provider, protocol, memory store, tool service, UI, or platform extension. | [Integrations](references/integrations.md) | +| Hosting and deployment | Working Agent Framework code needs a process host, protocol endpoint, identity contract, or deployment shape. | [Hosting and deployment](references/hosting-and-deployment.md) | + +## Defaults + +- Agent Framework supports Python 3.11 and later. Build new environments with the latest supported Python release, or + at least the previous release (N-1), unless a required dependency has a narrower compatibility range. +- Install the narrow Agent Framework distribution needed by the application instead of defaulting to the + `agent-framework` meta-package. +- Agent Framework does not automatically read `.env` files. If the project uses one, call `load_dotenv()` explicitly + or use the selected API's documented `env_file_path` or equivalent initialization option. + +## Current documentation lookup + +Use local guidance for stable decisions and common patterns. For provider matrices, package maturity, hosted tools, +deployment details, or unfamiliar APIs, consult current sources before generating code: + +The reference pages intentionally describe selection rules, invariants, and non-obvious gotchas. Use public docstrings +or API reference pages for signatures and option details, and use Learn or maintained samples for end-to-end +procedures. + +When the coding agent supports MCP, configure the Microsoft Learn MCP Server as a Streamable HTTP server: + +```text +https://learn.microsoft.com/api/mcp +``` + +See [Microsoft Learn MCP Server setup](https://learn.microsoft.com/training/support/mcp-get-started) for client +configuration. The endpoint is for MCP clients and returns an error when opened directly in a browser. + +1. Search Microsoft Learn with `microsoft_docs_search`. +2. Fetch the relevant page with `microsoft_docs_fetch`. +3. Use `microsoft_code_sample_search` when a current implementation example is needed. +4. If Learn MCP is unavailable and a trusted `mslearn` CLI is already installed, use the equivalent command: + +| MCP tool | Preinstalled CLI | +| --- | --- | +| `microsoft_docs_search(query="...")` | `mslearn search "..."` | +| `microsoft_docs_fetch(url="...")` | `mslearn fetch "..."` | +| `microsoft_code_sample_search(query="...", language="python")` | `mslearn code-search "..." --language python` | + +Do not fetch and execute an unpinned CLI package during a coding session. Use the +[official Microsoft Learn MCP/CLI setup](https://github.com/MicrosoftDocs/mcp) to install or update it intentionally. + +Canonical starting points: + +- [Agent Framework overview](https://learn.microsoft.com/agent-framework/overview/) +- [Your first agent](https://learn.microsoft.com/agent-framework/get-started/your-first-agent) +- [Python samples](https://github.com/microsoft/agent-framework/tree/main/python/samples) diff --git a/skills/agent-framework-builder-python/references/agent-builder.md b/skills/agent-framework-builder-python/references/agent-builder.md new file mode 100644 index 0000000000..b90e83a99a --- /dev/null +++ b/skills/agent-framework-builder-python/references/agent-builder.md @@ -0,0 +1,120 @@ +# Plain agent builder + +Use this path for Python agents whose behavior can be expressed with one `Agent`, a model or remote-agent client, tools, +sessions, context providers, and middleware. + +## Requirement intake + +Capture: + +1. Goal and user-visible behavior. +2. Input and output shape, including streaming or structured output. +3. Model provider, authentication, and whether the definition is application-owned or service-managed. +4. Tools, hosted tools, and side effects that require approval. +5. Session, history, retrieval, memory, and compaction requirements. +6. Middleware, runtime context, observability, and evaluation criteria. +7. Local, self-hosted, protocol-hosted, durable, or Foundry-hosted deployment. + +Ask only about unknowns that materially affect the design. + +## Start from maintained examples + +For a new application, select the provider first and install only its required distribution and capabilities. Use the +current quickstart or maintained sample for package commands and runnable code rather than copying versions or setup +steps into the skill. + +- [Your first agent](https://learn.microsoft.com/agent-framework/get-started/your-first-agent) +- [Python getting-started samples](https://github.com/microsoft/agent-framework/tree/main/python/samples/01-get-started) + +The stable pattern is an `Agent` wrapping a chat client, instructions, tools, middleware, and ContextProviders. Agent +Framework does not automatically load `.env` files; configuration loading remains application-owned. + +## Provider selection + +| Need | Distribution and API | +| --- | --- | +| Foundry project model with application-owned instructions and tools | `agent-framework-foundry`, `FoundryChatClient` | +| Interact with an existing agent of any supported type already defined in Foundry | `agent-framework-foundry`, `FoundryAgent` | +| OpenAI and OpenAI-compatible endpoints with Responses semantics | `agent-framework-openai`, `OpenAIChatClient` | +| OpenAI and OpenAI-compatible endpoints with Chat Completions semantics | `agent-framework-openai`, `OpenAIChatCompletionClient` | +| Other model or agent service | Its current provider distribution and documented client or agent | + +`FoundryAgent` connects to and interacts with an agent that already exists in Foundry. It does not create, deploy, +version, update, or otherwise manage that agent definition; use the appropriate Foundry management APIs or deployment +tools for those operations. + +Use current provider documentation before assuming hosted-tool, storage, streaming, or structured-output parity. + +## Tools and approval + +- Prefer focused, typed, non-interactive tool functions. +- Use `@tool` or `FunctionTool` when explicit schema or approval behavior is needed. +- Tool approval defaults to `never_require`; set `approval_mode="always_require"` for side effects. +- Treat writes, sends, purchases, destructive operations, shell commands, and privileged external calls as side effects. +- Keep return values structured when downstream code or evaluation consumes them. +- Use hosted tools only with providers that document support. + +For parameter descriptions, use normal annotations and current schema guidance rather than inventing provider-specific +JSON schemas. + +## Sessions + +Create an `AgentSession` through the agent and pass the same session to each run in one logical conversation. + +- Do not reuse a session concurrently unless the provider and application explicitly support it. +- Treat persisted session state as sensitive data. +- Read [session documentation](https://learn.microsoft.com/agent-framework/concepts/agents/conversations/session) for + serialization and provider-specific continuation behavior. + +## History + +Choose one primary history owner: + +- **Application-managed history** uses a `HistoryProvider` to load prior messages and persist new messages in + `AgentSession` state or an external store. +- **Service-managed history** is available on clients that support a `store` option. With `store=True`, the provider + stores the conversation and returns a service continuation identifier that Agent Framework keeps in + `AgentSession.service_session_id`; later turns can send new input against that stored conversation instead of + resending the full transcript. +- With `store=False`, the provider does not retain the conversation. Use a `HistoryProvider` or supply the required + prior messages when multi-turn context is needed. +- When the chat client does not support service-managed storage and no configured `HistoryProvider` reads history, + `Agent` adds an `InMemoryHistoryProvider` by default so an `AgentSession` retains conversation history for the + current process. Replace it with a persistent history provider when history must survive process restarts or scale + across instances. + +- Not every provider supports `store`, and service-managed continuation and branching behavior varies by provider. +- Avoid combining service-managed storage with a load-enabled history provider unless the provider documentation + explicitly describes that combination; otherwise the model may receive duplicate history. +- Treat stored messages and service continuation identifiers as sensitive data. +- Add compaction when conversations or tool loops can exceed the model context window. + +## Context providers + +Use a `ContextProvider` when instructions, messages, tools, retrieval results, memory, or other context must be supplied +dynamically for a run or session. + +- Keep conversation history ownership in a `HistoryProvider`; context providers serve a different extension point. +- Prefer scoped context providers over concatenating changing data into static agent instructions. +- Define when the provider loads and persists data, and keep its session-state keys distinct from other providers. +- Treat retrieved and persisted context as sensitive and enforce tenant and user boundaries outside the model. + +For custom providers, ContextProviders, and middleware, read +[Extensibility](extensibility.md). + +## Validation + +1. Import and construct the client and agent without invoking the model where practical. +2. Check the selected client or provider documentation for its environment keys and tell the user to set them. Let the + framework classes resolve and validate those settings. If values come from a `.env` file, pass the documented + environment-file option or call `load_dotenv()` before construction; do not manually resolve each setting. +3. Unit-test deterministic tools, schemas, context providers, and middleware. +4. Add an opt-in live smoke test only when provider access is available. +5. Exercise a second turn when session behavior is required. +6. Check approval behavior with at least one side-effecting tool. + +Current examples: + +- [Minimal agent](https://github.com/microsoft/agent-framework/blob/main/python/samples/01-get-started/01_hello_agent.py) +- [Function tool](https://github.com/microsoft/agent-framework/blob/main/python/samples/01-get-started/02_add_tools.py) +- [Multi-turn session](https://github.com/microsoft/agent-framework/blob/main/python/samples/01-get-started/03_multi_turn.py) diff --git a/skills/agent-framework-builder-python/references/declarative.md b/skills/agent-framework-builder-python/references/declarative.md new file mode 100644 index 0000000000..b2adb87cb0 --- /dev/null +++ b/skills/agent-framework-builder-python/references/declarative.md @@ -0,0 +1,36 @@ +# Declarative agents and workflows + +Use declarative construction when YAML or JSON should be the source of truth for supported agent or workflow behavior. +Keep credentials, custom tools, transports, authorization, and application services in code. + +## Selection rules + +- Use `AgentFactory` for declarative agents and `WorkflowFactory` for declarative workflows. +- Prefer code-first construction when custom Python logic, strong typing, unsupported actions, or dynamic routing would + make the definition harder to validate than code. +- Do not invent schema kinds or parse definitions into ad hoc constructor calls; use the published schema and factory. + +The `agent-framework-declarative` distribution is released, but individual surfaces can have different feature +maturity. Check current package status and public docstrings before making compatibility commitments. + +## Host responsibilities + +- Supply provider clients, connections, bindings, tools, and external handlers explicitly. +- Provide an HTTP or MCP handler when a workflow uses those actions. +- Keep environment exposure restricted to intentional configuration. +- Treat definitions as executable configuration and load them only from trusted sources. +- Allowlist external destinations and register only resources the definition may invoke. +- Review the documented HTTP body limits and handler ownership rules; use a custom handler when host policy requires + different authentication, retries, SSRF controls, or transport behavior. + +## Validation + +Validate definitions at startup and fail clearly on unknown providers, actions, tools, variables, or resources. Apply +the same approval, evaluation, and telemetry policy used for code-first agents and workflows. + +## Learn more + +- [Declarative agents](https://learn.microsoft.com/agent-framework/agents/declarative) +- [Declarative workflows](https://learn.microsoft.com/agent-framework/workflows/declarative) +- [Declarative package README](https://github.com/microsoft/agent-framework/blob/main/python/packages/declarative/README.md) +- [Declarative samples](https://github.com/microsoft/agent-framework/tree/main/python/samples/02-agents/declarative) diff --git a/skills/agent-framework-builder-python/references/evaluation.md b/skills/agent-framework-builder-python/references/evaluation.md new file mode 100644 index 0000000000..3b50930074 --- /dev/null +++ b/skills/agent-framework-builder-python/references/evaluation.md @@ -0,0 +1,40 @@ +# Evaluation + +Use evaluation to turn expected behavior, failures, and feedback into repeatable evidence. Evaluation determines whether +behavior is acceptable; observability explains what happened during execution. + +Evaluation APIs are experimental. Check current feature maturity and API docstrings before making them a long-term +application contract. + +## Capture the case + +Record the input, current and expected output, expected tool calls, relevant session or workflow state, provider/model, +application version, and actionable user feedback. Express feedback as expected behavior or a custom evaluator instead +of inventing unsupported fields. + +## Diagnose before changing + +Classify the failure before modifying prompts or models: + +1. deterministic code, schema, or tool behavior; +2. tool selection or approval; +3. missing context, retrieval, memory, or history; +4. instructions or output contract; +5. workflow routing, state, checkpoint, or output selection; +6. provider, hosting, or environment configuration; +7. model limitation after application causes are excluded. + +Fix the lowest responsible layer. Prefer deterministic checks for tools, schemas, required facts, and output structure; +use model-based or Foundry evaluators only where they add signal. + +## Improvement loop + +Reproduce the failure, add a regression case, fix the responsible layer, run deterministic checks, add model-based +evaluation if needed, compare results, and retain the case. + +## Learn more + +- [Agent evaluation](https://learn.microsoft.com/agent-framework/agents/evaluation) +- [Local evaluation samples](https://github.com/microsoft/agent-framework/tree/main/python/samples/02-agents/evaluation) +- [Workflow evaluation sample](https://github.com/microsoft/agent-framework/blob/main/python/samples/03-workflows/evaluation/evaluate_workflow.py) +- [Foundry evaluation samples](https://github.com/microsoft/agent-framework/tree/main/python/samples/05-end-to-end/evaluation) diff --git a/skills/agent-framework-builder-python/references/extensibility.md b/skills/agent-framework-builder-python/references/extensibility.md new file mode 100644 index 0000000000..c1dcb16960 --- /dev/null +++ b/skills/agent-framework-builder-python/references/extensibility.md @@ -0,0 +1,121 @@ +# Extensibility + +Use this reference when an application needs framework behavior that is not provided by an existing model or agent +provider, ContextProvider, or middleware component. + +## Choose an extension point + +| Requirement | Extension point | +| --- | --- | +| Connect an unsupported model-style endpoint | Custom `BaseChatClient` | +| Connect a remote agent service or non-chat runtime | Custom `SupportsAgentRun`, usually a `BaseAgent` | +| Add retrieval, memory, dynamic instructions, per-run tools, or post-run extraction | Custom `ContextProvider` | +| Add cross-cutting execution policy, retries, caching, validation, or transforms | Agent, chat, or function middleware | + +Prefer composition through these public extension points over forking an existing provider or modifying framework +internals. + +## Custom providers + +Build a provider when the application must integrate a model endpoint or remote agent service that no existing Agent +Framework package supports, or when a private gateway requires custom authentication, transport, option mapping, or +protocol translation. + +Choose the provider shape that matches the backend: + +- Implement a chat client when the backend accepts messages and returns model-style chat responses. Subclass + `BaseChatClient` and implement `_inner_get_response(...)` for both regular and streaming execution. +- Implement an agent when the backend already owns agent behavior or does not fit chat-client semantics. Implement + `SupportsAgentRun`, usually by subclassing `BaseAgent`, and support both `stream=False` and `stream=True`. +- Use middleware instead of a provider when the underlying model protocol is already supported and the requirement is + cross-cutting policy, retries, routing, logging, or request transformation. + +A custom chat client is responsible for: + +- converting Agent Framework `Message` and `Content` values to the backend request; +- mapping backend responses, streaming updates, usage, identifiers, and finish information back to framework types; +- defining typed provider-specific options without discarding unknown application options unintentionally; +- mapping provider failures to actionable exceptions and preserving cancellation; +- declaring service-managed history behavior and persisting continuation identifiers through `AgentSession` when + supported; +- owning and cleaning up network clients or other context-managed resources it creates. + +If a custom client needs the standard tool loop, chat middleware, and telemetry, compose the public layers in this +order: function invocation, chat middleware, chat telemetry, then the raw or base client. Prefer an existing +fully-featured client when only configuration or middleware differs. + +Current references: + +- [BaseChatClient API](https://learn.microsoft.com/python/api/agent-framework-core/agent_framework.basechatclient?view=agent-framework-python-latest) +- [Custom chat client sample](https://github.com/microsoft/agent-framework/blob/main/python/samples/02-agents/chat_client/custom_chat_client.py) +- [Custom agent sample](https://github.com/microsoft/agent-framework/blob/main/python/samples/02-agents/providers/custom/custom_agent.py) + +## Custom ContextProviders + +Build a custom `ContextProvider` when an application needs reusable context engineering that runs with an agent, such +as retrieval, user or tenant memory, dynamic instructions, per-run tools, request-scoped data, or post-run extraction. +Use middleware instead when the requirement is primarily execution control around the agent, model, or tools. + +1. Subclass `ContextProvider` and give each provider instance a stable, unique `source_id`. +2. Override `before_run(...)` to add context through `SessionContext`: + - `extend_instructions(...)` for dynamic instructions; + - `extend_messages(...)` for retrieved or remembered messages; + - `extend_tools(...)` for tools available only to this invocation; + - `extend_middleware(...)` for invocation-scoped chat or function middleware. +3. Override `after_run(...)` to inspect the input and response, extract new information, or persist provider-owned + state. +4. Store mutable provider data in the supplied provider-scoped `state` dictionary. Use `session.state` directly only + when deliberate coordination across providers is required. +5. Register custom persisted classes with `register_state_type(...)` at module import time so restored sessions can + deserialize them before the application loads a session. + +Set `after_run_once_per_turn=True` when an `AgentLoopMiddleware` should defer `after_run` until the whole user turn is +complete. Context providers may add chat or function middleware, but not agent middleware. + +For cross-session memory, include origin session attribution and enforce authorization before injecting content. + +Current references: + +- [Context Provider concepts](https://learn.microsoft.com/agent-framework/concepts/agents/conversations/context-providers) +- [ContextProvider API](https://learn.microsoft.com/python/api/agent-framework-core/agent_framework.contextprovider) +- [Custom ContextProvider sample](https://github.com/microsoft/agent-framework/blob/main/python/samples/02-agents/context_providers/simple_context_provider.py) + +## Custom middleware + +Use middleware for reusable behavior that belongs around an execution boundary rather than in agent instructions, +business tools, or a provider implementation. Common cases include policy enforcement, retries, caching, routing, +dynamic tool exposure, validation, observability, result transformation, and shared runtime context. + +Choose the narrowest boundary: + +- **Agent middleware** runs around `Agent.run(...)`. Use it for run-level policy, caching, termination, result + overrides, or shared state. +- **Chat middleware** runs around each model call, including calls inside a tool loop. Use it for retries, request and + response transformation, model routing, or per-call usage behavior. +- **Function middleware** runs around each local tool invocation. Use it for validated-argument checks, authorization + context, logging, exception handling, or tool-result transformation. + +Create middleware either by subclassing `AgentMiddleware`, `ChatMiddleware`, or `FunctionMiddleware`, or by using the +matching decorator. The implementation receives a context and `call_next`: + +1. Inspect or update the context before execution. +2. Call `await call_next()` without passing the context again. +3. Inspect or transform the result after execution. + +Skip `call_next()` only when deliberately terminating the pipeline or returning a complete valid result. Keep state +scoped to the run or session unless cross-run sharing is intentional, and test both streaming and non-streaming paths. + +Current references: + +- [Middleware concepts](https://learn.microsoft.com/agent-framework/concepts/agents/middleware/) +- [Middleware samples](https://github.com/microsoft/agent-framework/tree/main/python/samples/02-agents/middleware) +- [Class-based middleware sample](https://github.com/microsoft/agent-framework/blob/main/python/samples/02-agents/middleware/class_based_middleware.py) + +## Validation + +- Custom providers: test regular and streaming parity, tools, structured output, usage, cancellation, session + continuation, resource cleanup, and layer ordering. +- Custom ContextProviders: test attribution, multiple sessions, serialization and restoration, provider ordering, + missing data, cross-session authorization, and failure behavior. +- Middleware: test the before/after paths, short-circuit behavior, exceptions, state scope, and both streaming and + non-streaming execution. diff --git a/skills/agent-framework-builder-python/references/harness-agent-builder.md b/skills/agent-framework-builder-python/references/harness-agent-builder.md new file mode 100644 index 0000000000..ad992ce0a4 --- /dev/null +++ b/skills/agent-framework-builder-python/references/harness-agent-builder.md @@ -0,0 +1,51 @@ +# Harness agent builder + +Use a harness when the product needs an opinionated operating loop around a normal `Agent`: planning, todos, memory, +approval handling, compaction, or optional autonomous capabilities. + +`create_harness_agent` is a convenience composition, not a separate agent abstraction. It returns an `Agent` +implementing `SupportsAgentRun`. Everything it assembles can also be composed manually from an `Agent`, middleware, +context providers, history, and instructions. + +## Choose the composition direction + +- Start with `create_harness_agent` and disable or replace features when the product wants most harness capabilities. +- Start with `Agent` and add individual components when the product needs only a few capabilities or exact ordering. +- Use a workflow instead when explicit graph topology, routing, checkpointed stages, or intermediate outputs define + correctness. + +## Important defaults and opt-ins + +Keep only the defaults that affect architecture or safety in working memory; read the +[harness documentation](https://learn.microsoft.com/agent-framework/concepts/harness) or the factory docstring for the +complete option list. + +- Todo, plan/execute mode, file memory, tool approval, history persistence, and telemetry are enabled by default. +- Compaction is active only when token budgets or custom strategies are supplied. +- Web search is added only when the client supports it and it is not disabled. +- File access, Agent Skills, background agents, shell execution, and looping are opt-in. +- Background agents, file access, looping, and shell tooling have experimental or prerelease constraints; check + current feature maturity before depending on them. + +## Operational gotchas + +- Use an `AgentSession` when standing approval state or multi-turn behavior matters. +- File memory and file access are separate. File access tools require approval by default; file-memory writes do not. +- For hosted or untrusted workloads, disable file memory or supply tenant-scoped storage with quotas, retention, and + server-owned cleanup. Do not rely on the shared default working-directory store. +- Load skills and background agents only from trusted sources; their content crosses the model and tool boundary. +- Bound autonomous loops and stop for unresolved approvals or user input. +- Treat shell command filters as a usability guard, not a security boundary. The host owns sandboxing and executor + lifecycle. + +## Validation + +- Exercise enabled modes, memory, skills, and file roots rather than testing factory construction alone. +- Verify approval behavior for side effects. +- Prove loop termination and resource cleanup for optional autonomous features. + +## Learn more + +- [Harness concepts](https://learn.microsoft.com/agent-framework/concepts/harness) +- [First harness sample](https://github.com/microsoft/agent-framework/blob/main/python/samples/01-get-started/06_agent_harness.py) +- [Harness samples](https://github.com/microsoft/agent-framework/tree/main/python/samples/02-agents/harness) diff --git a/skills/agent-framework-builder-python/references/hosting-and-deployment.md b/skills/agent-framework-builder-python/references/hosting-and-deployment.md new file mode 100644 index 0000000000..eac727bd81 --- /dev/null +++ b/skills/agent-framework-builder-python/references/hosting-and-deployment.md @@ -0,0 +1,51 @@ +# Hosting and deployment + +Use hosting after the agent or workflow works locally. Separate the runtime protocol from the deployment platform: +hosting libraries expose an application; infrastructure tooling deploys it. + +## Choose the hosting family + +| Need | Source of detail | +| --- | --- | +| Self-managed protocol endpoint | [Agent Framework hosting](https://learn.microsoft.com/agent-framework/hosting/) | +| Microsoft Foundry Agent Server | [Foundry hosted agents](https://learn.microsoft.com/agent-framework/hosting/foundry-hosted-agent) | +| Durable execution or Azure Functions | [Durable Agent Framework extension](https://github.com/microsoft/agent-framework-durable-extension) | + +General hosting packages target arbitrary environments and provide protocol adapters such as Responses, A2A, MCP, or +Telegram. `agent-framework-foundry-hosting` is specific to the Foundry Agent Server and supports Responses and +Invocations contracts. Check current package maturity and protocol documentation rather than copying option inventories +into application code. + +## Stable hosting rules + +- Treat translated request options as caller-controlled input and forward only an explicit allowlist. +- Choose one history owner; do not combine competing host, service, and agent history mechanisms. +- Reuse an agent instance only when all mutable state is session-scoped. Otherwise use a request-owned factory. +- Prefer native workflow hosting. A shared `workflow.as_agent()` instance can leak workflow state across requests. +- Build fresh workflows and request-owned resources while keeping workflow and executor identities stable for + checkpoint restoration. +- Make session, checkpoint, response, identity, approval, storage, and cleanup ownership explicit. + +Read the selected host's public docstrings and maintained sample for constructor options, parsers, history modes, +storage providers, and protocol details. + +## Deployment readiness + +Verify the entry point imports, required packages and external files are included, configuration fails clearly, history +and storage ownership are documented, request-owned resources are cleaned up, and no local credentials or caches enter +the deployment package. + +## Deploy to Microsoft Foundry + +Foundry deployment commands, manifests, prerequisites, and injected configuration change independently from Agent +Framework. Use current authoritative instructions: + +- [Agent Framework Foundry deployment guidance](https://learn.microsoft.com/agent-framework/hosting/foundry-hosted-agent#deploying-to-foundry) +- [Foundry hosted-agent quickstart](https://learn.microsoft.com/azure/foundry/agents/quickstarts/quickstart-hosted-agent) +- [Deploy a hosted agent](https://learn.microsoft.com/azure/foundry/agents/how-to/deploy-hosted-agent) +- [Deploy from source code](https://learn.microsoft.com/azure/foundry/agents/how-to/deploy-hosted-agent-code) +- [Manage hosted agents](https://learn.microsoft.com/azure/foundry/agents/how-to/manage-hosted-agent) +- [Agent Framework hosted-agent samples](https://github.com/microsoft/agent-framework/tree/main/python/samples/04-hosting/foundry-hosted-agents) + +Use those sources for `azd`, provisioning, manifests, environment variables, deployment, invocation, RBAC, quota, +monitoring, and troubleshooting. Do not reconstruct deployment files from memory. diff --git a/skills/agent-framework-builder-python/references/integrations.md b/skills/agent-framework-builder-python/references/integrations.md new file mode 100644 index 0000000000..2b298e0f10 --- /dev/null +++ b/skills/agent-framework-builder-python/references/integrations.md @@ -0,0 +1,47 @@ +# Providers and integrations + +Choose integrations only after the application contract is clear. Provider and connector capabilities, package +maturity, and Python compatibility change more frequently than core Agent Framework patterns. + +## Version and package selection + +- Check each selected distribution's `Requires-Python` metadata and the current + [Python package status](https://github.com/microsoft/agent-framework/blob/main/python/PACKAGE_STATUS.md). +- Read the [Python README compatibility notes](https://github.com/microsoft/agent-framework/blob/main/python/README.md) + for current boundary-version limitations rather than copying that matrix into application guidance. +- Install only the selected integrations and allow prerelease packages only when required. + +## Provider selection + +Start with the current +[model provider catalog](https://learn.microsoft.com/agent-framework/integrations/by-component/model-providers/) and +[agent service catalog](https://learn.microsoft.com/agent-framework/integrations/by-component/agent-services/). + +Verify authentication, streaming, structured output, hosted tools, history ownership, approval, and function-loop +support instead of assuming provider parity. If no provider matches, use +[Extensibility](extensibility.md#custom-providers). + +## Capability categories + +- Use function tools for application-owned code and MCP for external tool services. +- Use sessions and ContextProviders first; add memory, retrieval, or vector-store connectors when persistence, search, + scale, or an external data model requires them. +- A2A connects agents across services; AG-UI connects agents or workflows to compatible frontends; hosting adapters + expose protocols. None of these replace application authorization. +- Durable Task and Azure Functions integrations are maintained in the + [Durable Agent Framework extension](https://github.com/microsoft/agent-framework-durable-extension). + +For AG-UI, remember that thread and run IDs are correlation identifiers, not authentication boundaries. The +application owns authorization, durable snapshots, scaling, and rendering policy. + +## Selection checklist + +Confirm the provider/service, authentication model, required capabilities, package maturity, Python range, data and +tenant boundaries, approval policy, and required permissions. Add a focused integration test or opt-in live smoke test. + +## Learn more + +- [Agent Framework integrations](https://learn.microsoft.com/agent-framework/integrations/) +- [Python package status](https://github.com/microsoft/agent-framework/blob/main/python/PACKAGE_STATUS.md) +- [Python samples](https://github.com/microsoft/agent-framework/tree/main/python/samples) +- [AG-UI sample](https://github.com/microsoft/agent-framework/tree/main/python/samples/05-end-to-end/ag_ui_single_agent) diff --git a/skills/agent-framework-builder-python/references/observability.md b/skills/agent-framework-builder-python/references/observability.md new file mode 100644 index 0000000000..b3f7b3e1ab --- /dev/null +++ b/skills/agent-framework-builder-python/references/observability.md @@ -0,0 +1,24 @@ +# Observability + +Use observability to diagnose agent runs, model calls, tools, workflows, latency, errors, and token use. It provides +runtime evidence; it does not determine whether output is correct. + +## Stable setup rules + +- Agent Framework instrumentation is enabled by default, but applications must configure OpenTelemetry providers and + exporters. +- Narrow installations include `opentelemetry-api`, not the SDK. Install `opentelemetry-sdk` and the exporter required + by the chosen backend. +- Configure providers once during startup, or use application-owned OpenTelemetry setup and enable Agent Framework + instrumentation against it. +- Keep sensitive payload capture disabled unless the application explicitly accepts the exposure. +- Built-in redaction does not replace sanitization in custom telemetry, exporters, middleware, or exception messages. + +Inspect run boundaries, model calls, tool and MCP calls, workflow transitions, checkpoints, approvals, retries, usage, +and hosted-service continuations. Use stable agent, workflow, and service identifiers. + +## Learn more + +- [Agent observability](https://learn.microsoft.com/agent-framework/agents/observability) +- [Workflow observability](https://learn.microsoft.com/agent-framework/workflows/observability) +- [Observability samples](https://github.com/microsoft/agent-framework/tree/main/python/samples/02-agents/observability) diff --git a/skills/agent-framework-builder-python/references/workflow-builder.md b/skills/agent-framework-builder-python/references/workflow-builder.md new file mode 100644 index 0000000000..c121e97c66 --- /dev/null +++ b/skills/agent-framework-builder-python/references/workflow-builder.md @@ -0,0 +1,54 @@ +# Workflow and orchestration builder + +Use a workflow when execution order, routing, parallelism, multiple participants, checkpoints, human input, or +intermediate outputs are part of the product contract. + +## Choose the workflow API + +| Need | API | +| --- | --- | +| Native Python control flow | Experimental `@workflow` | +| Cached or checkpoint-replayable function calls | Experimental `@step` | +| Explicit typed graph and routing | `WorkflowBuilder` | +| Standard multi-agent collaboration | `agent-framework-orchestrations` builders | +| YAML-defined actions and routing | `WorkflowFactory`; read `declarative.md` | + +Read [workflow concepts](https://learn.microsoft.com/agent-framework/concepts/workflows/) and the relevant API +docstrings for signatures and execution options. + +## Stable design rules + +- A functional workflow definition must be built before running; each built workflow owns mutable execution state. +- Build fresh workflows when executors or wrapped agents hold run-specific state. +- Builders that accept `SupportsAgentRun` can use custom or remote agent implementations. `HandoffBuilder` accepts + concrete `Agent` participants only. +- Use standard sequential, concurrent, handoff, group-chat, or Magentic builders before recreating those patterns. +- Select caller-facing output separately from intermediate progress. +- Wrap a workflow as an agent only when callers require the agent contract. Prefer native workflow hosting when the + host supports it. + +## Agent-to-workflow migration + +Before splitting an agent into stages, record its input, response, tools, middleware, context, session, and hosting +contract. Split responsibilities only where the topology changes correctness or observability. Define the messages +between stages, final output, intermediate output, session ownership, and approval behavior explicitly. + +## Gotchas + +- Workflow instances are stateful and cannot run concurrently. +- Checkpoint resume requires stable workflow, executor, and participant identities. +- Sessions are not automatically interchangeable between participants. +- Tool approval and workflow human input are different suspension mechanisms. +- Workflow streams include framework events in addition to application output. + +## Validation + +Exercise every route with deterministic executors first. Test final and intermediate outputs separately, then test +streaming, suspension/resume, participant sessions, approvals, and error propagation where used. + +## Learn more + +- [Workflow concepts](https://learn.microsoft.com/agent-framework/concepts/workflows/) +- [Functional workflow sample](https://github.com/microsoft/agent-framework/blob/main/python/samples/01-get-started/05a_functional_workflow_basics.py) +- [Graph workflow sample](https://github.com/microsoft/agent-framework/blob/main/python/samples/01-get-started/05c_first_graph_workflow.py) +- [Workflow samples](https://github.com/microsoft/agent-framework/tree/main/python/samples/03-workflows)