Skip to content
Open
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
6 changes: 6 additions & 0 deletions python/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,12 @@ from agent_framework.azure import AzureOpenAIChatClient, AzureAIAgentClient

When modifying samples, update associated README files in the same or parent folders.

### Samples Syntax Checking

Run `uv run poe samples-syntax` to check samples for syntax errors and missing imports from `agent_framework`. This uses a relaxed pyright configuration that validates imports without strict type checking.

Some samples depend on external packages (e.g., `azure.ai.agentserver.agentframework`, `microsoft_agents`) that are not installed in the dev environment. These are excluded in `pyrightconfig.samples.json`. When adding or modifying these excluded samples, add them to the exclude list and manually verify they have no import errors from `agent_framework` packages by temporarily removing them from the exclude list and running the check.

## Package Documentation

### Core
Expand Down
6 changes: 4 additions & 2 deletions python/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
samples-syntax = "pyright -p pyrightconfig.samples.json --warnings"
typing = ["pyright", "mypy"]
# cleaning
clean-dist-packages = "python run_tasks_in_packages_if_exists.py clean-dist"
Expand All @@ -238,7 +239,7 @@ build-meta = "python -m flit build"
build = ["build-packages", "build-meta"]
publish = "uv publish"
# combined checks
check = ["fmt", "lint", "pyright", "mypy", "test", "markdown-code-lint"]
check = ["fmt", "lint", "pyright", "mypy", "samples-syntax", "test", "markdown-code-lint"]

[tool.poe.tasks.all-tests-cov]
cmd = """
Expand Down Expand Up @@ -323,7 +324,8 @@ sequence = [
{ ref = "fmt" },
{ ref = "lint" },
{ ref = "pre-commit-pyright ${files}" },
{ ref = "pre-commit-markdown-code-lint ${files}" }
{ ref = "pre-commit-markdown-code-lint ${files}" },
{ ref = "samples-syntax" }
]
args = [{ name = "files", default = ".", positional = true, multiple = true }]

Expand Down
13 changes: 13 additions & 0 deletions python/pyrightconfig.samples.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"include": ["samples"],
"exclude": [
"**/autogen/**",
"**/autogen-migration/**",
"**/semantic-kernel-migration/**",
"**/demos/**",
"**/agent_with_foundry_tracing.py"
],
"typeCheckingMode": "off",
"reportMissingImports": "error",
"reportAttributeAccessIssue": "error"
}
Comment on lines +1 to +13
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two sample files that are not excluded by this configuration still reference the nonexistent AgentRunUpdateEvent class and should have been updated to use ExecutorEvent instead:

  1. python/samples/getting_started/workflows/agents/azure_chat_agents_tool_calls_with_feedback.py (lines 12, 197, 294)
  2. python/samples/getting_started/workflows/orchestration/magentic_human_plan_review.py (lines 8, 94)

These files import AgentRunUpdateEvent from agent_framework, but this class no longer exists - it should be ExecutorEvent based on the changes made in python/samples/demos/workflow_evaluation/create_workflow.py.

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +13
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sample file imports several classes that have been moved to the agent_framework_orchestrations package but the imports have not been updated:

  1. MagenticBuilder - should be imported from agent_framework_orchestrations
  2. MagenticPlanReviewRequest - should be imported from agent_framework_orchestrations
  3. AgentRunUpdateEvent - no longer exists, should be changed to ExecutorEvent

The imports should be split into two statements similar to the pattern used in other updated samples.

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +13
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sample file has multiple issues that need to be fixed to align with the API changes:

  1. AgentRunUpdateEvent (line 12) - no longer exists, should be changed to ExecutorEvent
  2. FunctionCallContent and FunctionResultContent (lines 16-17) - these classes are no longer exported. The code should be updated to use content.type == "function_call" and content.type == "function_result" instead of isinstance() checks (lines 204-205)
  3. The display_agent_run_update function signature and isinstance checks need to be updated to use ExecutorEvent instead of AgentRunUpdateEvent

Copilot uses AI. Check for mistakes.
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ async def run_autogen() -> None:

async def run_agent_framework() -> None:
"""Agent Framework's SequentialBuilder for sequential agent orchestration."""
from agent_framework import SequentialBuilder
from agent_framework_orchestrations import SequentialBuilder
from agent_framework.openai import OpenAIChatClient

client = OpenAIChatClient(model_id="gpt-4.1-mini")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ async def run_autogen() -> None:

async def run_agent_framework() -> None:
"""Agent Framework's GroupChatBuilder with LLM-based speaker selection."""
from agent_framework import GroupChatBuilder
from agent_framework_orchestrations import GroupChatBuilder
from agent_framework.openai import OpenAIChatClient

client = OpenAIChatClient(model_id="gpt-4.1-mini")
Expand Down
5 changes: 3 additions & 2 deletions python/samples/autogen-migration/orchestrations/03_swarm.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@

import asyncio

from agent_framework import AgentResponseUpdate, HandoffAgentUserRequest, WorkflowOutputEvent
from agent_framework import AgentResponseUpdate, WorkflowOutputEvent
from agent_framework_orchestrations import HandoffAgentUserRequest


async def run_autogen() -> None:
Expand Down Expand Up @@ -98,11 +99,11 @@ async def run_autogen() -> None:
async def run_agent_framework() -> None:
"""Agent Framework's HandoffBuilder for agent coordination."""
from agent_framework import (
HandoffBuilder,
RequestInfoEvent,
WorkflowRunState,
WorkflowStatusEvent,
)
from agent_framework_orchestrations import HandoffBuilder
from agent_framework.openai import OpenAIChatClient

client = OpenAIChatClient(model_id="gpt-4.1-mini")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,9 @@
from agent_framework import (
AgentResponseUpdate,
ChatMessage,
MagenticOrchestratorEvent,
MagenticProgressLedger,
WorkflowOutputEvent,
)
from agent_framework_orchestrations import MagenticOrchestratorEvent, MagenticProgressLedger


async def run_autogen() -> None:
Expand Down Expand Up @@ -67,7 +66,7 @@ async def run_autogen() -> None:

async def run_agent_framework() -> None:
"""Agent Framework's MagenticBuilder for orchestrated collaboration."""
from agent_framework import MagenticBuilder
from agent_framework_orchestrations import MagenticBuilder
from agent_framework.openai import OpenAIChatClient

client = OpenAIChatClient(model_id="gpt-4.1-mini")
Expand Down Expand Up @@ -123,7 +122,7 @@ async def run_agent_framework() -> None:
print(event.data, end="", flush=True)

elif isinstance(event, MagenticOrchestratorEvent):
print(f"\n[Magentic Orchestrator Event] Type: {event.event_type.name}")
print(f"\n[Magentic Orchestrator Event] Type: {event.event_type.name}") # type: ignore[union-attr]
if isinstance(event.data, ChatMessage):
print(f"Please review the plan:\n{event.data.text}")
elif isinstance(event.data, MagenticProgressLedger):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ async def run_autogen() -> None:

async def run_agent_framework() -> None:
"""Agent Framework's as_tool() for hierarchical agents with streaming."""
from agent_framework import FunctionCallContent, FunctionResultContent
from agent_framework import Content
from agent_framework.openai import OpenAIChatClient

client = OpenAIChatClient(model_id="gpt-4.1-mini")
Expand Down Expand Up @@ -78,7 +78,7 @@ async def run_agent_framework() -> None:
print("[Agent Framework]")

# Track accumulated function calls (they stream in incrementally)
accumulated_calls: dict[str, FunctionCallContent] = {}
accumulated_calls: dict[str, Content] = {}

async for chunk in coordinator.run("Create a tagline for a coffee shop", stream=True):
# Stream text tokens
Expand All @@ -88,7 +88,7 @@ async def run_agent_framework() -> None:
# Process streaming function calls and results
if chunk.contents:
for content in chunk.contents:
if isinstance(content, FunctionCallContent):
if content.type == "function_call":
# Accumulate function call content as it streams in
call_id = content.call_id
if call_id in accumulated_calls:
Expand All @@ -105,7 +105,7 @@ async def run_agent_framework() -> None:
current_args = accumulated_calls[call_id].arguments
print(f" Arguments: {current_args}", flush=True)

elif isinstance(content, FunctionResultContent):
elif content.type == "function_result":
# Tool result - shows writer's response
result_text = content.result if isinstance(content.result, str) else str(content.result)
if result_text.strip():
Expand Down
9 changes: 4 additions & 5 deletions python/samples/demos/chatkit-integration/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import uvicorn

# Agent Framework imports
from agent_framework import AgentResponseUpdate, ChatAgent, ChatMessage, FunctionResultContent, Role, tool
from agent_framework import AgentResponseUpdate, ChatAgent, ChatMessage, tool
from agent_framework.azure import AzureOpenAIChatClient

# Agent Framework ChatKit integration
Expand Down Expand Up @@ -332,7 +332,6 @@ async def respond(
runs the agent, converts the response back to ChatKit events using stream_agent_response,
and creates interactive weather widgets when weather data is queried.
"""
from agent_framework import FunctionResultContent

if input_user_message is None:
logger.debug("Received None user message, skipping")
Expand Down Expand Up @@ -375,7 +374,7 @@ async def intercept_stream() -> AsyncIterator[AgentResponseUpdate]:
# Check for function results in the update
if update.contents:
for content in update.contents:
if isinstance(content, FunctionResultContent):
if content.type == "function_result":
result = content.result

# Check if it's a WeatherResponse (string subclass with weather_data attribute)
Expand Down Expand Up @@ -472,7 +471,7 @@ async def intercept_stream() -> AsyncIterator[AgentResponseUpdate]:
# Check for function results in the update
if update.contents:
for content in update.contents:
if isinstance(content, FunctionResultContent):
if content.type == "function_result":
result = content.result

# Check if it's a WeatherResponse (string subclass with weather_data attribute)
Expand Down Expand Up @@ -585,7 +584,7 @@ async def upload_file(attachment_id: str, file: UploadFile = File(...)):
attachment = await data_store.load_attachment(attachment_id, {"user_id": DEFAULT_USER_ID})

# Clear the upload_url since upload is complete
attachment.upload_url = None
attachment.upload_url = None # type: ignore[union-attr]

# Save the updated attachment back to the store
await data_store.save_attachment(attachment, {"user_id": DEFAULT_USER_ID})
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Copyright (c) Microsoft. All rights reserved.

from agent_framework import ConcurrentBuilder
from agent_framework_orchestrations import ConcurrentBuilder
from agent_framework.azure import AzureOpenAIChatClient
from azure.ai.agentserver.agentframework import from_agent_framework
from azure.identity import DefaultAzureCredential # pyright: ignore[reportUnknownVariableType]
Expand Down
14 changes: 7 additions & 7 deletions python/samples/demos/workflow_evaluation/create_workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@
from agent_framework import (
AgentExecutorResponse,
AgentResponseUpdate,
AgentRunUpdateEvent,
ChatMessage,
Executor,
ExecutorEvent,
WorkflowBuilder,
WorkflowContext,
WorkflowOutputEvent,
Expand Down Expand Up @@ -364,7 +364,7 @@ async def _process_workflow_events(events, conversation_ids, response_ids):
output_str = str(event.data).encode("ascii", "replace").decode("ascii")
print(f"\nWorkflow Output: {output_str}\n")

elif isinstance(event, AgentRunUpdateEvent):
elif isinstance(event, ExecutorEvent):
_track_agent_ids(event, event.executor_id, response_ids, conversation_ids)

return workflow_output
Expand All @@ -379,14 +379,14 @@ def _track_agent_ids(event, agent, response_ids, conversation_ids):
raw = event.data.raw_representation

# Try conversation_id directly on raw representation
if hasattr(raw, "conversation_id") and raw.conversation_id:
if hasattr(raw, "conversation_id") and raw.conversation_id: # type: ignore[union-attr]
# Only add if not already in the list
if raw.conversation_id not in conversation_ids[agent]:
conversation_ids[agent].append(raw.conversation_id)
if raw.conversation_id not in conversation_ids[agent]: # type: ignore[union-attr]
conversation_ids[agent].append(raw.conversation_id) # type: ignore[union-attr]

# Extract response_id from the OpenAI event (available from first event)
if hasattr(raw, "raw_representation") and raw.raw_representation:
openai_event = raw.raw_representation
if hasattr(raw, "raw_representation") and raw.raw_representation: # type: ignore[union-attr]
openai_event = raw.raw_representation # type: ignore[union-attr]

# Check if event has response object with id
if hasattr(openai_event, "response") and hasattr(openai_event.response, "id"):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import asyncio

from agent_framework import HostedMCPTool, HostedWebSearchTool, TextReasoningContent, UsageContent
from agent_framework import Content, HostedMCPTool, HostedWebSearchTool
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import of 'Content' is not used.

Suggested change
from agent_framework import Content, HostedMCPTool, HostedWebSearchTool
from agent_framework import HostedMCPTool, HostedWebSearchTool

Copilot uses AI. Check for mistakes.
from agent_framework.anthropic import AnthropicChatOptions, AnthropicClient

"""
Expand Down Expand Up @@ -40,9 +40,9 @@ async def main() -> None:
print("Agent: ", end="", flush=True)
async for chunk in agent.run(query, stream=True):
for content in chunk.contents:
if isinstance(content, TextReasoningContent):
if content.type == "text_reasoning":
print(f"\033[32m{content.text}\033[0m", end="", flush=True)
if isinstance(content, UsageContent):
if content.type == "usage":
print(f"\n\033[34m[Usage so far: {content.usage_details}]\033[0m\n", end="", flush=True)
if chunk.text:
print(chunk.text, end="", flush=True)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import asyncio

from agent_framework import HostedMCPTool, HostedWebSearchTool, TextReasoningContent, UsageContent
from agent_framework import Content, HostedMCPTool, HostedWebSearchTool
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import of 'Content' is not used.

Suggested change
from agent_framework import Content, HostedMCPTool, HostedWebSearchTool
from agent_framework import HostedMCPTool, HostedWebSearchTool

Copilot uses AI. Check for mistakes.
from agent_framework.anthropic import AnthropicClient
from anthropic import AsyncAnthropicFoundry

Expand Down Expand Up @@ -51,9 +51,9 @@ async def main() -> None:
print("Agent: ", end="", flush=True)
async for chunk in agent.run(query, stream=True):
for content in chunk.contents:
if isinstance(content, TextReasoningContent):
if content.type == "text_reasoning":
print(f"\033[32m{content.text}\033[0m", end="", flush=True)
if isinstance(content, UsageContent):
if content.type == "usage":
print(f"\n\033[34m[Usage so far: {content.usage_details}]\033[0m\n", end="", flush=True)
if chunk.text:
print(chunk.text, end="", flush=True)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import logging
from pathlib import Path

from agent_framework import HostedCodeInterpreterTool, HostedFileContent
from agent_framework import Content, HostedCodeInterpreterTool
from agent_framework.anthropic import AnthropicChatOptions, AnthropicClient

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -52,7 +52,7 @@ async def main() -> None:
query = "Create a presentation about renewable energy with 5 slides"
print(f"User: {query}")
print("Agent: ", end="", flush=True)
files: list[HostedFileContent] = []
files: list[Content] = []
async for chunk in agent.run(query, stream=True):
for content in chunk.contents:
match content.type:
Expand Down
Loading
Loading