Commit Graph

192 Commits

  • Python: Fix Bedrock embedding test stub missing meta attribute (#4287)
    * Fix Bedrock embedding test stub missing meta attribute
    
    * Increase test coverage so gate passes
  • Update Python package versions to rc2 (#4258)
    - Bump core and azure-ai to 1.0.0rc2
    - Bump preview packages to 1.0.0b260225
    - Update dependencies to >=1.0.0rc2
    - Add CHANGELOG entries for changes since rc1
    - Update uv.lock
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: Phase 2: Embedding clients for Ollama, Bedrock, and Azure AI Inference (#4207)
    * Phase 2: Embedding clients for Ollama, Bedrock, and Azure AI Inference
    
    Add embedding client implementations to existing provider packages:
    
    - OllamaEmbeddingClient: Text embeddings via Ollama's embed API
    - BedrockEmbeddingClient: Text embeddings via Amazon Titan on Bedrock
    - AzureAIInferenceEmbeddingClient: Text and image embeddings via Azure AI
      Inference, supporting Content | str input with separate model IDs for
      text (AZURE_AI_INFERENCE_EMBEDDING_MODEL_ID) and image
      (AZURE_AI_INFERENCE_IMAGE_EMBEDDING_MODEL_ID) endpoints
    
    Additional changes:
    - Rename EmbeddingCoT -> EmbeddingT, EmbeddingOptionsCoT -> EmbeddingOptionsT
    - Add otel_provider_name passthrough to all embedding clients
    - Register integration pytest marker in all packages
    - Add lazy-loading namespace exports for Ollama and Bedrock embeddings
    - Add image embedding sample using Cohere-embed-v3-english
    - Add azure-ai-inference dependency to azure-ai package
    
    Part of #1188
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Fix mypy duplicate name and ruff lint issues
    
    - Rename second 'vector' variable to 'img_vector' in image embedding loop
    - Combine nested with statements in tests
    - Remove unused result assignments in tests
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * updates from feedback
    
    * Fix CI failures in embedding usage handling
    
    - Fix Azure AI embedding mypy issues by normalizing vectors to list[float],
      safely accumulating optional usage token fields, and filtering None entries
      before constructing GeneratedEmbeddings
    - Avoid Bandit false positive by initializing usage details as an empty dict
    - Update OpenAI embedding tests to assert canonical usage keys
      (input_token_count/total_token_count)
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: Support Agent Skills (#4210)
    * Python: Support Agent Skills
    
    Add FileAgentSkillsProvider, a context provider that discovers and exposes
    Agent Skills from filesystem directories following the Agent Skills
    specification (https://agentskills.io/) progressive disclosure pattern:
    advertise, load, read resources.
    
    Changes:
    - FileAgentSkillsProvider - discovers SKILL.md files from configured
      directories, advertises skills via system prompt injection, and provides
      load_skill / read_skill_resource tools for on-demand access.
    - Internal helpers for skill discovery, frontmatter parsing, and secure
      resource reading (path traversal / symlink guards).
    - Unit tests covering discovery, loading, resource reading, and security
      scenarios.
    - Sample (basic_file_skills) demonstrating usage with an expense-report skill.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Python: Move skills sample to samples/02-agents/basic_skills/
    
    Align sample directory name with .NET equivalent (Agent_Step01_BasicSkills).
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * fix code quality checks
    
    * address pr review comment and code quality check issue
    
    * address pr review comments
    
    * move the sample to the skills folder
    
    * update readme
    
    * reame consts and use types for them
    
    * leverage pathlib for working with files
    
    * refactor the test
    
    * supply schema to functions
    
    * update readme
    
    * update sample name
    
    * address pr review comments
    
    * fix failing lint check
    
    * address failing check
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: Fixing issue #1366 - Thread corruption when max_iterations is reached. (#4234)
    * Fix thread corruption when max_iterations exhausted (#1366)
    
    When the function invocation loop exhausts max_iterations while the model
    keeps requesting tools, the failsafe code path (calling the model with
    tool_choice='none' and prepending fcc_messages) was unreachable because
    'if response is not None: return response' short-circuited before it.
    
    The fix removes the premature return so the failsafe always runs after
    loop exhaustion, making a final model call with tool_choice='none' to
    produce a clean text answer and prepending accumulated fcc_messages from
    prior iterations. This matches the existing pattern used by the error
    threshold and max_function_calls paths.
    
    Also unskips test_max_iterations_limit and test_streaming_max_iterations_limit
    which were previously skipped with 'needs investigation in unified API'.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Add fix report for issue #1366
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Fix ruff formatting in _tools.py and test_issue_1366_thread_corruption.py
    
    Apply ruff format to fix multi-line string concatenation and function call
    formatting issues flagged by the linter.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Add quality review for issue #1366 fix
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Remove temporary investigation docs.
    
    * Address PR review: explicit enabled check in log condition, clarify mock behavior in test
    
    - Add explicit function_invocation_configuration['enabled'] check to the
      'Maximum iterations reached' log condition in both non-streaming and
      streaming paths, making intent clearer when function invocation is disabled.
    - Add comment in test_thread_safe_after_max_iterations_with_agent explaining
      that the failsafe response (tool_choice='none') is provided automatically
      by the mock client, not from run_responses.
    
    * Blend fix and tests into project without issue-specific callouts
    
    - Remove issue #1366 references from _tools.py comments
    - Move regression tests from standalone test_issue_1366_thread_corruption.py
      into test_function_invocation_logic.py alongside existing max_iterations tests
    - Clean up test docstrings to describe behavior generically
    - Delete the standalone issue-specific test file
    
    ---------
    
    Co-authored-by: alliscode <bentho@microsoft.com>
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: Fix workflow runner concurrent processing (#4143)
    * Fix workflow runner concurrent processing
    
    * Comments 1
    
    * Add test
  • Python: updated integration tests and guidance (#4181)
    * updated integration tests and guidance
    
    * fixed merge test
    
    * updated integration tests
    
    * fix: remove duplicate --dist loadfile flag from pytest-xdist config
    
    Only one --dist mode can be active at a time; the second value silently
    overrides the first. Keep --dist worksteal (dynamic load balancing) and
    remove the redundant --dist loadfile from all workflow files and
    pyproject.toml configs.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * docs: add keep-in-sync notes for merge and integration test workflows
    
    Both python-merge-tests.yml and python-integration-tests.yml share the
    same parallel job structure. Added sync reminders in workflow file
    comments, the python-testing SKILL.md, and CODING_STANDARD.md.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * refactor: remove RUN_INTEGRATION_TESTS flag
    
    Integration test gating now uses two mechanisms:
    - `@pytest.mark.integration` for test selection via `-m` filtering
    - `skip_if_*_disabled` for credential/service availability checks
    
    The RUN_INTEGRATION_TESTS env var was redundant since the marker handles
    selection and the skip decorators already check for actual credentials.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * fix: sync missing env vars from merge-tests to integration-tests
    
    Add OPENAI_EMBEDDINGS_MODEL_ID and AZURE_OPENAI_EMBEDDING_DEPLOYMENT_NAME
    to python-integration-tests.yml to match python-merge-tests.yml.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * fix: remove remaining RUN_INTEGRATION_TESTS from embedding tests and docs
    
    Missed test_openai_embedding_client.py and vector-stores README in the
    earlier cleanup.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * set functions tests to 3.10
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: feat(python): Add embedding abstractions and OpenAI implementation (Phase 1) (#4153)
    * feat(python): Add embedding abstractions and OpenAI implementation (Phase 1)
    
    This PR contains two parts:
    
    1. **Overall migration plan** for porting vector stores and embeddings from
       Semantic Kernel to Agent Framework (docs/features/vector-stores-and-embeddings/README.md)
       covering all 10 phases from core abstractions through connectors and TextSearch.
    
    2. **Phase 1 implementation** — core embedding abstractions and OpenAI/Azure OpenAI
       embedding clients:
    
       Core types (_types.py):
       - EmbeddingGenerationOptions TypedDict (total=False)
       - Embedding[EmbeddingT] generic class with model_id, dimensions, created_at
       - GeneratedEmbeddings[EmbeddingT, EmbeddingOptionsT] list container with options, usage
       - EmbeddingInputT (default str) and EmbeddingT (default list[float]) TypeVars
    
       Protocol + base class (_clients.py):
       - SupportsGetEmbeddings protocol — Generic[EmbeddingInputT, EmbeddingT, OptionsContraT]
       - BaseEmbeddingClient ABC — Generic[EmbeddingInputT, EmbeddingT, OptionsCoT]
    
       Telemetry (observability.py):
       - EmbeddingTelemetryLayer with gen_ai.operation.name = "embeddings"
    
       OpenAI implementation (openai/_embedding_client.py):
       - RawOpenAIEmbeddingClient, OpenAIEmbeddingClient, OpenAIEmbeddingOptions
       - Uses _ensure_client() factory pattern
    
       Azure OpenAI implementation (azure/_embedding_client.py):
       - AzureOpenAIEmbeddingClient following AzureOpenAIChatClient pattern
       - Supports API key, Entra ID credentials, env var configuration
    
       Tests:
       - 47 unit tests for types, protocol, base class, OpenAI, and Azure clients
       - 6 integration tests (gated behind RUN_INTEGRATION_TESTS + credentials)
    
       Samples:
       - samples/02-agents/embeddings/openai_embeddings.py
       - samples/02-agents/embeddings/azure_openai_embeddings.py
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * fix: Add AzureOpenAIEmbeddingClient to azure __init__.pyi stub
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * ci: Add embedding env vars to Python integration tests
    
    Map OPENAI_EMBEDDING_MODEL_ID and AZURE_OPENAI_EMBEDDING_DEPLOYMENT_NAME
    from GitHub vars to the integration test environment.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * fix: Handle base64 encoding_format in OpenAI embedding client
    
    When encoding_format='base64' is used, the OpenAI API returns base64-encoded
    floats instead of a JSON array. Decode these automatically to list[float]
    so the return type stays consistent regardless of encoding format.
    
    Also adds a unit test for base64 decoding and fixes minor docstring/import issues.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * fix: Only record INPUT_TOKENS for embedding telemetry
    
    Embeddings have no output/completion tokens. Remove OUTPUT_TOKENS recording
    which was double-counting prompt_tokens via the total_tokens fallback.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * fix: Resolve mypy variance error and lint warning
    
    Use contravariant/covariant TypeVars for SupportsGetEmbeddings Protocol.
    Combine nested if into single statement in telemetry layer.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * fix: Make EmbeddingCoT invariant for mypy compatibility
    
    GeneratedEmbeddings is invariant in its type param, so the Protocol
    TypeVar cannot be covariant.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * fix: Address PR review - empty values guard, service_url for telemetry
    
    - Add early return for empty values in get_embeddings to avoid unnecessary API calls
    - Add service_url() method to RawOpenAIEmbeddingClient for proper telemetry endpoint reporting
    - Add test for empty values behavior
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Python: Fix OpenAI chat client compatibility with third-party endpoints and OTel 0.4.14 (#4161)
    
    * Fix system message content sent as list instead of string
    
    Some OpenAI-compatible endpoints (e.g. NVIDIA NIM) reject system messages
    when content is a list of content parts. This change flattens system and
    developer message content to a plain string in the Chat Completions client.
    
    Fixes https://github.com/microsoft/agent-framework/issues/1407
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Fix compatibility with opentelemetry-semantic-conventions-ai 0.4.14
    
    Version 0.4.14 removed several LLM_* attributes from SpanAttributes
    (LLM_SYSTEM, LLM_REQUEST_MODEL, LLM_RESPONSE_MODEL, LLM_REQUEST_MAX_TOKENS,
    LLM_REQUEST_TEMPERATURE, LLM_REQUEST_TOP_P, LLM_TOKEN_TYPE).
    
    Move these to the OtelAttr enum with their well-known gen_ai.* string values
    and update all references in observability.py and tests.
    
    Fixes https://github.com/microsoft/agent-framework/issues/4160
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Flatten text-only message content to string for all roles
    
    Extend the system/developer fix to all message roles. Text-only content
    lists are now post-processed into plain strings, while multimodal content
    (text + images/audio) remains as a list. This fixes compatibility with
    OpenAI-like endpoints that cannot deserialize list content (e.g. Foundry
    Local's Neutron backend).
    
    Partially fixes https://github.com/microsoft/agent-framework/issues/4084
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Fix streaming text lost when usage data in same chunk
    
    Some providers (e.g. Gemini) include both usage data and text content
    in the same streaming chunk. The early return on chunk.usage caused
    text and tool call parsing to be skipped entirely. Remove the early
    return and process usage alongside text/tool calls.
    
    Fixes https://github.com/microsoft/agent-framework/issues/3434
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Fix mypy errors in _chat_client.py
    
    Rename shadowed variable 'args' in system/developer branch to 'sys_args'
    and rename loop variable 'content' to 'msg_content' to avoid type conflict.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * reorder imports
    
    * fix: Use OtelAttr.REQUEST_MODEL instead of removed SpanAttributes.LLM_REQUEST_MODEL
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * docs: Add score_threshold to vector store plan
    
    Reference SK .NET PR #13501 for score threshold filtering semantics.
    Include score_threshold in SearchOptions from Phase 3.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * docs: Add reference to roji's SK .NET MEVD work for SQL connectors
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * fix: Clear env vars in construction tests to avoid CI leakage
    
    Tests for missing API key / model ID now use monkeypatch.delenv to ensure
    env vars from the integration test environment don't prevent the expected
    ValueError from being raised.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: Add max_function_calls to FunctionInvocationConfiguration (#2329) (#4175)
    * Add max_function_calls to FunctionInvocationConfiguration (#2329)
    
    Add a new per-request max_function_calls setting to FunctionInvocationConfiguration
    that limits the total number of individual function invocations across all iterations
    within a single get_response call. This complements max_iterations (which limits LLM
    roundtrips) by providing a hard cap on actual tool executions regardless of parallelism.
    
    - Add max_function_calls field to FunctionInvocationConfiguration (default: None/unlimited)
    - Track cumulative function call count in both streaming and non-streaming tool loops
    - Force tool_choice='none' when the limit is reached
    - Add validation in normalize_function_invocation_configuration
    - Improve docstrings for FunctionInvocationConfiguration, FunctionTool, and @tool
      to clarify semantics of max_iterations vs max_function_calls vs max_invocations
    - Add tests for parallel calls, single calls, unlimited mode, and config validation
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Add sample for controlling total tool executions
    
    Showcases all three mechanisms for limiting tool executions:
    1. max_iterations — caps LLM roundtrips
    2. max_function_calls — caps total individual function invocations per request
    3. max_invocations — lifetime cap on a specific tool instance
    Plus a combined scenario demonstrating defense in depth.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Suppress ruff E305/fmt in hosting sample to preserve XML doc tags
    
    The XML snippet tags (# <create_agent> / # </create_agent>) are used for
    docs extraction and must stay adjacent to the code they wrap. Both ruff
    check (E305) and ruff format add blank lines after the function definition,
    pushing the closing tag away. Suppress with ruff: noqa: E305 and fmt: off.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Add per-agent tool wrapping scenario to control_total_tool_executions sample
    
    Show that wrapping the same callable with @tool multiple times creates
    independent FunctionTool instances with separate invocation counters,
    enabling per-agent max_invocations budgets for shared functions.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Clarify max_function_calls is a best-effort limit
    
    The limit is checked after each batch of parallel calls completes, so the
    current batch always runs to completion even if it overshoots the limit.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Address PR review: fix docstring reference, clarify best-effort in sample
    
    - Fix malformed Sphinx :attr: role in FunctionTool docstring — use plain
      backtick reference instead
    - Update sample to say 'best-effort cap' instead of 'hard cap' for
      max_function_calls, noting it's checked between iterations
    - Parametrize pattern is correct (fixture override, matching existing tests)
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * clarify max_invocations limits
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: (ag-ui): Add Workflow Support, Harden Streaming Semantics, and add Dynamic Handoff Demo (#3911)
    * fix Workflow.as_agent() streaming regression in ag-ui
    
    * Address PR feedback
    
    * workflows wip
    
    * wip
    
    * wip
    
    * Workflow AG-UI demo
    
    * Fixes for handoff workflow demo
    
    * Fixes to workflows support in AG-UI
    
    * Fixes
    
    * Add headers to some demo files
    
    * Fix comment
    
    * Fixes for store
    
    * Make _input_schema lazy-loaded
    
    * fix mypy
    
    * revert session change to handoff only for now
    
    ---------
    
    Co-authored-by: Eduard van Valkenburg <eavanvalkenburg@users.noreply.github.com>
  • Python: Fix OpenAI chat client compatibility with third-party endpoints and OTel 0.4.14 (#4161)
    * Fix system message content sent as list instead of string
    
    Some OpenAI-compatible endpoints (e.g. NVIDIA NIM) reject system messages
    when content is a list of content parts. This change flattens system and
    developer message content to a plain string in the Chat Completions client.
    
    Fixes https://github.com/microsoft/agent-framework/issues/1407
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Fix compatibility with opentelemetry-semantic-conventions-ai 0.4.14
    
    Version 0.4.14 removed several LLM_* attributes from SpanAttributes
    (LLM_SYSTEM, LLM_REQUEST_MODEL, LLM_RESPONSE_MODEL, LLM_REQUEST_MAX_TOKENS,
    LLM_REQUEST_TEMPERATURE, LLM_REQUEST_TOP_P, LLM_TOKEN_TYPE).
    
    Move these to the OtelAttr enum with their well-known gen_ai.* string values
    and update all references in observability.py and tests.
    
    Fixes https://github.com/microsoft/agent-framework/issues/4160
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Flatten text-only message content to string for all roles
    
    Extend the system/developer fix to all message roles. Text-only content
    lists are now post-processed into plain strings, while multimodal content
    (text + images/audio) remains as a list. This fixes compatibility with
    OpenAI-like endpoints that cannot deserialize list content (e.g. Foundry
    Local's Neutron backend).
    
    Partially fixes https://github.com/microsoft/agent-framework/issues/4084
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Fix streaming text lost when usage data in same chunk
    
    Some providers (e.g. Gemini) include both usage data and text content
    in the same streaming chunk. The early return on chunk.usage caused
    text and tool call parsing to be skipped entirely. Remove the early
    return and process usage alongside text/tool calls.
    
    Fixes https://github.com/microsoft/agent-framework/issues/3434
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Fix mypy errors in _chat_client.py
    
    Rename shadowed variable 'args' in system/developer branch to 'sys_args'
    and rename loop variable 'content' to 'msg_content' to avoid type conflict.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: fix reasoning model workflow handoff and history serialization (#4083)
    * fix: strip function_call and text_reasoning from cross-agent workflow handoff
    
    When a reasoning model (e.g. gpt-5-mini) runs as Agent 1 in a workflow, its
    response includes text_reasoning items (with server-scoped IDs like rs_XXXX)
    and function_call items. Forwarding these to Agent 2 in a fresh conversation
    caused API errors because the reasoning/call IDs are scoped to the original
    stored response context.
    
    Changes:
    - Strip 'function_call', 'text_reasoning', 'function_approval_request', and
      'function_approval_response' from handoff messages in _agent_executor.py
    - Keep 'function_result' so the actual tool output content is preserved for
      the next agent's context
    - Update unit tests to reflect that function_result messages survive handoff
      (messages grow from 2→3: user, tool(result), assistant(summary))
    - Fix incorrect test assertions in test_function_invocation_stop_clears_*
      that assumed the client layer updates session.service_session_id
    - Also fixed _extract_function_calls to search all messages with call_id
      deduplication, and the error-limit stop path to submit function_call_output
      items before halting (via tool_choice=none cleanup call)
    
    Relates to: https://github.com/microsoft/agent-framework/issues/4047
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * fix: reasoning model workflow handoff and history serialization
    
    Fixes multiple related issues when using reasoning models (gpt-5-mini,
    gpt-5.2) in multi-agent workflows that chain agents via from_response
    or replay full conversation history via AgentExecutorRequest.
    
    ## Reasoning items always emitted on output_item.added
    
    When a reasoning model produces encrypted or hidden reasoning (no
    visible text), the Responses API still fires a reasoning output item
    without any reasoning_text.delta events. Previously no text_reasoning
    Content was emitted in that case, making it invisible to downstream
    logic. Both the non-streaming (_parse_response_from_openai) and
    streaming (output_item.added) paths now always emit at least one
    text_reasoning Content — with empty text if no content is available —
    so co-occurrence detection and serialization guards work reliably.
    
    ## Reasoning items only serialized when paired with a function_call
    
    The Responses API only accepts reasoning items in input when they
    directly preceded a function_call in the original response. Sending a
    reasoning item that preceded a text response (no tool call) causes:
      "reasoning was provided without its required following item"
    _prepare_message_for_openai now checks has_function_call per message
    and skips text_reasoning serialization when there is no accompanying
    function_call.
    
    ## summary field is an array, not an object
    
    The reasoning item summary field sent to the Responses API must be an
    array of objects ([{"type": "summary_text", "text": ...}]), not a
    single object. Fixed _prepare_content_for_openai accordingly.
    
    ## service_session_id cleared when explicit history is provided
    
    When a workflow coordinator replays a full conversation (including
    function calls from a previous agent run) back to an executor via
    AgentExecutorRequest or from_response, the executor's session still
    held a service_session_id (previous_response_id) from the prior run.
    The API then received the same function-call items twice — once from
    previous_response_id (server-stored) and once from the explicit input —
    causing: "Duplicate item found with id fc_...".
    
    AgentExecutor.run (when should_respond=True) and from_response now
    reset self._session.service_session_id = None before running so that
    explicit input is the sole source of conversation context.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * small improvements in text reasoning
    
    * refactor: add reset_service_session to AgentExecutorRequest for explicit history replay
    
    Replace the implicit 'always clear service_session_id when should_respond=True'
    with an explicit opt-in field on AgentExecutorRequest.
    
    The old approach used should_respond=True as a proxy for 'full history replay',
    but that conflates two distinct intents:
    - Orchestrations group chat sends should_respond=True with an empty/single-message
      list (not a full replay) — unnecessarily clearing service_session_id.
    - HITL / feedback coordinators send the full prior conversation and truly need
      a fresh service session ID to avoid duplicate-item API errors.
    
    Changes:
    - Add AgentExecutorRequest.reset_service_session: bool = False
    - AgentExecutor.run only clears service_session_id when this flag is True
    - AgentExecutor.from_response unchanged (always clears; always full conversation)
    - Set reset_service_session=True in all full-history-replay call sites:
      agents_with_HITL.py, azure_chat_agents_tool_calls_with_feedback.py,
      autogen-migration round-robin coordinator, tau2 runner
    - Update _FullHistoryReplayCoordinator test helper to pass the flag
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * comment update
    
    * fixes from feedback
    
    * fix test
    
    * reverted changes to agent executor
    
    * fix: remove reset_service_session from tau2 runner
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * two other reverts
    
    * fix sample
    
    ---------
    
    Co-authored-by: Giles Odigwe <79032838+giles17@users.noreply.github.com>
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: [BREAKING] Redesign Python exception hierarchy (#4082)
    * [BREAKING] Redesign Python exception hierarchy
    
    Replace the flat ServiceException family with domain-scoped branches:
    - AgentException (with InvalidAuth, InvalidRequest, InvalidResponse, ContentFilter)
    - ChatClientException (same consistent suberrors)
    - IntegrationException (same + InitializationError)
    - WorkflowException (Runner, Convergence, Checkpoint, Validation, Action, Declarative)
    - ContentError (AdditionItemMismatch)
    - ToolException / ToolExecutionException (unchanged)
    - MiddlewareException / MiddlewareTermination (unchanged)
    
    Key changes:
    - All Service* exceptions removed (ServiceException, ServiceInitializationError, etc.)
    - AgentExecutionException split into AgentInvalidRequest/ResponseException
    - AgentInvocationError removed, split into AgentInvalidRequest/ResponseException
    - Workflow exceptions moved from _workflows/_exceptions.py into main exceptions.py
    - _workflows/__init__.py emptied; main __init__.py imports directly from submodules
    - Purview exceptions re-parented under IntegrationException hierarchy
    - Init validation errors use built-in ValueError/TypeError instead of custom exceptions
    - CODING_STANDARD.md updated with hierarchy design and rationale
    
    Fixes microsoft/agent-framework#3410
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Clarify ToolException vs ToolExecutionException docstrings
    
    ToolException: base class for all tool-related exceptions (preconditions,
    connection/init failures).
    ToolExecutionException: runtime call failures (tool call failed, reconnect
    failed, MCP errors).
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Fix remaining stale imports from agent_framework._workflows
    
    - azurefunctions: _context.py, _app.py, _serialization.py, test_func_utils.py
      used 'from agent_framework._workflows import X' which broke after
      emptying _workflows/__init__.py; changed to direct submodule imports
    - azure-ai-search: test still referenced ServiceInitializationError;
      updated to ValueError to match production code
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Unify Azure credential handling across all Python packages (#4088)
    Replace ad_token, ad_token_provider, and get_entra_auth_token with a
    unified credential parameter across all Azure-related packages.
    
    Core changes:
    - Add AzureCredentialTypes (TokenCredential | AsyncTokenCredential) and
      AzureTokenProvider (Callable[[], str | Awaitable[str]]) type aliases
    - Add resolve_credential_to_token_provider() using azure.identity's
      get_bearer_token_provider for automatic token caching/refresh
    - Update AzureOpenAIChatClient, AzureOpenAIResponsesClient, and
      AzureOpenAIAssistantsClient to accept credential: AzureCredentialTypes |
      AzureTokenProvider
    - Remove ad_token, ad_token_provider params and get_entra_auth_token helpers
    
    Package updates:
    - azure-ai: Accept AzureCredentialTypes on AzureAIClient,
      AzureAIAgentClient, AzureAIProjectAgentProvider, AzureAIAgentsProvider
    - azure-ai-search: Accept AzureCredentialTypes on
      AzureAISearchContextProvider
    - purview: Accept AzureCredentialTypes | AzureTokenProvider on
      PurviewClient, PurviewPolicyMiddleware, PurviewChatPolicyMiddleware
    
    Fixes #3449
    Fixes #3500
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: Fix hosted MCP tool approval flow for all session/streaming combinations (#4054)
    * fix openai hosted mcp samples
    
    * addressed copilot comments
    
    * Update python/samples/02-agents/providers/azure_openai/azure_responses_client_with_hosted_mcp.py
    
    Co-authored-by: Dmytro Struk <13853051+dmytrostruk@users.noreply.github.com>
    
    ---------
    
    Co-authored-by: Dmytro Struk <13853051+dmytrostruk@users.noreply.github.com>
  • Python: Fix Eval samples (#4033)
    * fix red team sample
    
    * Updated self-reflection
    
    * fix for workflow eval sample
    
    * fix test
  • Python: improve .env handling and observability samples (#4032)
    * Python: improve .env precedence and observability samples
    
    - Switch load_settings to explicit precedence: overrides -> explicit .env -> environment -> defaults\n- Raise when env_file_path is provided but missing\n- Update settings docs and tests for new behavior\n- Refresh observability samples and README guidance for env loading options\n\nCloses #3864\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * fixed some imports
    
    * Fix load_settings CI regressions
    
    Allow explicit env_file_path values that exist but are not regular files (for example /dev/null) by checking path existence before dotenv parsing, and restore a dict accumulator with typed return cast to satisfy mypy.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Avoid implicit dotenv in observability
    
    Only load dotenv in observability helpers when env_file_path is explicitly provided, and remove test os.devnull workarounds that are no longer necessary.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: Fixed middleware and multimodal input samples (#4022)
    * Fix streaming branch in weather override middleware sample
    
    The streaming branch of weather_override_middleware only prefixed the
    original weather data via a transform hook instead of replacing the
    content with the 'perfect weather' override like the non-streaming
    branch does. Replace with a new ResponseStream that yields the override
    content as ChatResponseUpdate chunks.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Fixed exception handling middleware sample
    
    * Fixed runtime context delegation middleware example
    
    * Fixed multimodal input examples
    
    * Small update
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: Add missing system instruction attr to invoke_agent span (#4012)
    * Add missing sysmte instruction attr to invoke_agent span
    
    * Temp remove azure search gate
    
    * fix pipeline error
  • Python: [BREAKING] Scope provider state by source_id and standardize source IDs (#3995)
    * Initial plan
    
    * Add FoundryMemoryProvider and tests
    
    Co-authored-by: eavanvalkenburg <13749212+eavanvalkenburg@users.noreply.github.com>
    
    * Add sample and documentation for FoundryMemoryProvider
    
    Co-authored-by: eavanvalkenburg <13749212+eavanvalkenburg@users.noreply.github.com>
    
    * Address code review feedback for FoundryMemoryProvider
    
    Co-authored-by: eavanvalkenburg <13749212+eavanvalkenburg@users.noreply.github.com>
    
    * Address PR review comments: Add DEFAULT_SOURCE_ID, use logging.getLogger, move state to session.state
    
    Co-authored-by: eavanvalkenburg <13749212+eavanvalkenburg@users.noreply.github.com>
    
    * Fix Foundry memory ItemParam usage and exports
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Refactor provider hook state and standardize source IDs
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Support endpoint-based Foundry memory init
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Fix core README workflows link
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * updated implementation and sample
    
    * Split out Foundry memory provider changes
    
    Remove FoundryMemoryProvider implementation/tests/sample plus export and docs mentions from this branch so only non-Foundry changes remain.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Trigger CI rerun for PR #3995
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    ---------
    
    Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
    Co-authored-by: eavanvalkenburg <13749212+eavanvalkenburg@users.noreply.github.com>
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: feature: Inject OpenTelemetry trace context into MCP requests and update… (#3780)
    * feat: Inject OpenTelemetry trace context into MCP requests and update documentation
    
    * Update python/samples/getting_started/observability/README.md
    
    Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
    
    * Update python/packages/core/tests/core/test_mcp.py
    
    Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
    
    * refactor: move opentelemetry import to module level
    
    OpenTelemetry is a hard dependency of agent-framework-core (per
    pyproject.toml), so the try/except ImportError guard was dead code.
    Move the import to the top of the file to fail fast on missing
    dependencies instead of silently hiding installation issues.
    
    ---------
    
    Co-authored-by: Pete Roden <Pete.Roden@microsoft.com>
    Co-authored-by: Mark Wallace <127216156+markwallace-microsoft@users.noreply.github.com>
    Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
  • Python: Fix tool normalization and provider sample consolidation (#3953)
    * Fix tool normalization and provider samples
    
    - restore callable/single-tool normalization paths and unset tool-choice behavior\n- consolidate and expand chat/provider samples (OpenAI/Azure/Anthropic/Ollama/Bedrock)\n- migrate Bedrock lazy import surface to agent_framework.amazon and move provider samples
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * small fix in sample
    
    * Finalize provider, samples, and core cleanup
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Fix CopilotTool passthrough in agent
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * fix link
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • Python: [BREAKING] Fix #3613 chat/agent message typing alignment (#3920)
    * Fix #3613 message typing across chat and agents
    
    * Address #3613 review feedback and sample input style
    
    * refactor: use shared AgentRunMessages aliases (#3613)
    
    * refactor: rename agent run input aliases for #3613
    
    * samples: inline image content in run calls
    
    * core: export AgentRunInputs from package init
    
    * core: use explicit init re-exports without __all__
    
    * updated logging and inits
    
    * Fix core mypy export and samples XML note
    
    * Remove AgentRunInputsOrNone and dedupe loggers
    
    * Remove prepare_messages helper
    
    * fix integration tests
  • Python: [BREAKING] Remove FunctionTool[Any] compatibility shim for schema passthrough (#3600) (#3907)
    * Fix #3600: Pass JSON schemas through without Pydantic conversion
    
    This change optimizes FunctionTool and MCP flows by passing JSON schemas
    directly to providers without converting them to Pydantic models first.
    
    Key changes:
    - Store JSON schema as-is when supplied to FunctionTool
    - Skip Pydantic model_validate for schema-supplied tools in invoke()
    - Return MCP tool schemas directly without conversion
    - Add comprehensive tests for schema passthrough behavior
    
    Performance benefits:
    - Eliminates expensive Pydantic model creation for supplied schemas
    - Preserves exact schema structure (additionalProperties, custom fields, etc.)
    - Reduces memory overhead and initialization time
    
    Maintains backward compatibility:
    - Function signature inference still uses Pydantic models
    - Explicit Pydantic models passed as input_model work as before
    - All existing tests pass
    
    * Fix schema passthrough validation and remove helper
    
    * Simplify FunctionTool without generic model dependency
    
    * Fix FunctionTool typing fallout in 3600
    
    * Remove FunctionTool[Any] compatibility shim
    
    * Use serializable kwargs in OTEL tool args
  • Python: fix: prevent repeating instructions in continued Responses API conversations (#3909)
    * fix: prevent repeating instructions in continued Responses API conversations
    
    - Instructions are now only prepended to messages on the first turn
    - When conversation_id/response_id exists (continuation), instructions are skipped
    - Covers OpenAI and Azure Responses API paths
    - Adds regression tests for all continuation scenarios
    
    Fixes #3498
    
    * Apply lint fixes to continuation tests
    
    * Consolidate responses continuation tests
  • Python: Fix non-ascii chars in span attributes (#3894)
    * Fix non-ascii chars in span attributes
    
    * Comments
  • Python: Fix streamed workflow agent continuation context by finalizing AgentExecutor streams (#3882)
    * Fix streamed workflow agent continuation context by finalizing AgentExecutor streams
    
    * Fix stream handling
    
    * Fixes
    
    * Fix DevUI and tests
  • Python: [BREAKING] PR2 — Wire context provider pipeline, remove old types, update all consumers (#3850)
    * PR2: Wire context provider pipeline and update all internal consumers
    
    - Replace AgentThread with AgentSession across all packages
    - Replace ContextProvider with BaseContextProvider across all packages
    - Replace context_provider param with context_providers (Sequence)
    - Replace thread= with session= in run() signatures
    - Replace get_new_thread() with create_session()
    - Add get_session(service_session_id) to agent interface
    - DurableAgentThread -> DurableAgentSession
    - Remove _notify_thread_of_new_messages from WorkflowAgent
    - Wire before_run/after_run context provider pipeline in RawAgent
    - Auto-inject InMemoryHistoryProvider when no providers configured
    
    * fix: update all tests for context provider pipeline, fix lazy-loaders, remove old test files
    
    * refactor: update all sample files for context provider pipeline (AgentThread→AgentSession, ContextProvider→BaseContextProvider)
    
    * fix: update remaining ag-ui references (client docstring, getting_started sample)
    
    * fix: make get_session service_session_id keyword-only to avoid confusion with session_id
    
    * refactor: rename _RunContext.thread_messages to session_messages
    
    * refactor: remove _threads.py, _memory.py, and old provider files; migrate devui to use plain message lists
    
    * rename: remove _new_ prefix from test files
    
    * refactor: rewrite SlidingWindowChatMessageStore as SlidingWindowHistoryProvider(InMemoryHistoryProvider)
    
    * fix: read full history from session state directly instead of reaching into provider internals
    
    * fix: update stale .pyi stubs, sample imports, and README references for new provider types
    
    * fix: remove stale message_store, _notify_thread_of_new_messages, and session_id.key references in samples
    
    * refactor: merge context_providers and sessions sample folders into sessions, remove aggregate_context_provider
    
    * refactor: UserInfoMemory stores state in session.state instead of instance attributes
    
    * feat: add Pydantic BaseModel support to session state serialization
    
    Pydantic models stored in session.state are now automatically serialized
    via model_dump() and restored via model_validate() during to_dict()/from_dict()
    round-trips. Models are auto-registered on first serialization; use
    register_state_type() for cold-start deserialization.
    
    Also export register_state_type as a public API.
    
    * fix mem0
    
    * Update sample README links and descriptions for session terminology
    
    - Replace 'thread' with 'session' in sample descriptions across all READMEs
    - Update file links for renamed samples (mem0_sessions, redis_sessions, etc.)
    - Fix Threads section → Sessions section in main samples/README.md
    - Update tools, middleware, workflows, durabletask, azure_functions READMEs
    - Update architecture diagrams in concepts/tools/README.md
    - Update migration guides (autogen, semantic-kernel)
    
    * Fix broken Redis README link to renamed sample
    
    * Fix Mem0 OSS client search: pass scoping params as direct kwargs
    
    AsyncMemory (OSS) expects user_id/agent_id/run_id as direct kwargs,
    while AsyncMemoryClient (Platform) expects them in a filters dict.
    Adds tests for both client types.
    
    Port of fix from #3844 to new Mem0ContextProvider.
    
    * Fix rebase issues: restore missing _conversation_state.py and checkpoint decode logic
    
    - Add back _conversation_state.py (encode/decode_chat_messages) lost in rebase
    - Fix on_checkpoint_restore to decode cache/conversation with decode_chat_messages
    - Fix on_checkpoint_restore to use decode_checkpoint_value for pending requests
    - Add tests/workflow/__init__.py for relative import support
    - Fix test_agent_executor checkpoint selection (checkpoints[1] not superstep)
    
    * Add STORES_BY_DEFAULT ClassVar to skip redundant InMemoryHistoryProvider injection
    
    Chat clients that store history server-side by default (OpenAI Responses API,
    Azure AI Agent) now declare STORES_BY_DEFAULT = True. The agent checks this
    during auto-injection and skips InMemoryHistoryProvider unless the user
    explicitly sets store=False.
    
    * Fix broken markdown links in azure_ai and redis READMEs
    
    * Fix getting-started samples to use session API instead of removed thread/ContextProvider API
    
    * updates to workflow as agent
    
    * fix group chat import
    
    * Rename Thread→Session throughout, fix service_session_id propagation, remove stale AGUIThread
    
    - Fix: Propagate conversation_id from ChatResponse back to session.service_session_id
      in both streaming and non-streaming paths in _agents.py
    - Rename AgentThreadException → AgentSessionException
    - Remove stale AGUIThread from ag_ui lazy-loader
    - Rename use_service_thread → use_service_session in ag-ui package
    - Rename test functions from *_thread_* to *_session_*
    - Rename sample files from *_thread* to *_session*
    - Update docstrings and comments: thread → session
    - Update _mcp.py kwargs filter: add 'session' alongside 'thread'
    - Fix ContinuationToken docstring example: thread=thread → session=session
    - Fix _clients.py docstring: 'Agent threads' → 'Agent sessions'
    
    * Fix broken markdown links after thread→session file renames
    
    * fix azure ai test
  • Python: Centralize tool result parsing in FunctionTool.invoke() (#3854)
    * Centralize tool result parsing in FunctionTool.invoke()
    
    - Add parse_result static method to FunctionTool that converts raw
      function return values to strings at invocation time
    - Add result_parser parameter to FunctionTool and @tool decorator
      for custom parsing
    - Remove prepare_function_call_results from all 9 consumer files
      and from the public API
    - Update MCPTool to parse MCP types directly to strings via
      _parse_tool_result_from_mcp and _parse_prompt_result_from_mcp
    - Change MCPTool parse_tool_results/parse_prompt_results type from
      Literal[True] | Callable | None to Callable | None
    - Remove ReturnT type parameter from FunctionTool (now single
      generic ArgsT since invoke() always returns str)
    - Update all subclass signatures and docstrings
    
    Fixes #1147
    
    * Fix test_mcp_tool_call_tool_with_meta_integration for string results
    
    The test was still accessing result[0].additional_properties but
    invoke() now returns a string, not a list of Content objects.
    
    * Fix SIM108 lint: use binary operator for output assignment
    
    * Fix bedrock: use FunctionTool.parse_result instead of str() fallback
    
    str(result) turns None into literal 'None' and dicts into Python reprs
    with single quotes, breaking JSON parsing. Use the shared parse_result
    which handles None as '' and serializes via json.dumps.
    
    * updated lock
    
    * updates from feedback
  • Python: (samples): adopt AzureOpenAIResponsesClient, reorganize orchestration examples, and fix workflow/orchestration bugs (#3873)
    * adopt AzureOpenAIResponsesClient, reorganize orchestration examples, and fix workflow/orchestration bugs
    
    * Updates
    
    * add comment
  • Python: Replace Pydantic Settings with TypedDict + load_settings() (#3843)
    * Replace Pydantic Settings with TypedDict + load_settings()
    
    - Remove pydantic-settings dependency, add python-dotenv
    - Delete _pydantic.py (AFBaseSettings, HTTPsUrl)
    - Add _settings.py with generic load_settings() function, SecretString,
      type coercion, and Required field validation (SettingNotFoundError)
    - Convert all 13 settings classes from AFBaseSettings subclasses to
      TypedDict definitions with load_settings() calls
    - Update all consumers from attribute access to dict access
    - Add 20 unit tests for load_settings() covering basic loading, dotenv,
      SecretString, type coercion, and required field validation
    - Update all existing tests for new settings patterns
    
    * Fix mypy type errors from settings conversion
    
    - Fix str | None attribute access in responses_client (walrus operator)
    - Fix SecretString | None narrowing in bedrock (type: ignore after guard)
    - Convert _context_provider.py attribute access to dict access (missed file)
    - Fix endpoint type narrowing in search_provider and context_provider
    - Fix purview: str | None .rstrip(), int | None defaults, urlparse bytes
    
    * Address PR review: required_fields param, type validation, fixes
    
    - Move required field validation from TypedDict annotations (Required)
      to a required_fields parameter on load_settings(), enabling runtime
      decisions about which fields are required
    - Remove Required imports and restore from __future__ import annotations
      in ollama and foundry_local
    - Add _check_override_type() for deterministic ServiceInitializationError
      on invalid override types (e.g. dict passed for str field)
    - Fix all multi-exception test catches back to single exception type
    - Fix Ollama host=None: use .get() so None is passed through to SDK default
    - Fix Purview processor: use explicit is-None checks instead of or operator
    - Remove unused BaseModel import from openai/_shared.py
    - Add 4 new tests (24 total): required_fields param, type validation
    
    * Fix type validation: allow int for float fields
    
    _check_override_type now permits int values for float-typed fields,
    matching Python's standard numeric promotion behavior.
    
    * fix: wrap urlparse arg with str() to fix mypy bytes endswith error
  • [BREAKING] Python: Checkpoint refactor: encode/decode, checkpoint format, etc (#3744)
    * WIP: Checkpoint refactor: encode/decode, checkpoint format, etc
    
    * WIP: Remove workflow ID in checkpoints
    
    * Refactor checkpointing
    
    * Add get_latest tests
    
    * Increase test coverage
    
    * Fix formatting
    
    * Fix unit tests
    
    * Fix samples
    
    * fix unit tests
    
    * fix pipeline
    
    * Copilot comments
    
    * Fix tests
    
    * Fix more tests
    
    * Address comments part 1
    
    * Address comments part 2
    
    * Comments
  • Python: Allow AzureOpenAIResponsesClient creation with Foundry project endpoint (#3814)
    * Initial plan
    
    * feat: extend AzureOpenAIResponsesClient to support Foundry project endpoints
    
    Add project_client and project_endpoint parameters to allow creating
    the client via an Azure AI Foundry project. When provided, the client
    uses AIProjectClient.get_openai_client() to obtain the OpenAI client.
    The azure-ai-projects package is imported lazily and only required
    when using the project endpoint path.
    
    Co-authored-by: eavanvalkenburg <13749212+eavanvalkenburg@users.noreply.github.com>
    
    * fix: address code review - remove duplicate MagicMock imports in tests
    
    Co-authored-by: eavanvalkenburg <13749212+eavanvalkenburg@users.noreply.github.com>
    
    * fix: add type field to Responses API input items and add Foundry sample
    
    - Add 'type: message' to input items in _prepare_message_for_openai
      to comply with the Responses API schema requirement
    - Filter out empty dicts from unsupported content types to prevent
      sending items with invalid empty type values
    - Add azure_responses_client_with_foundry.py sample demonstrating
      AzureOpenAIResponsesClient with project_endpoint
    - Update README and pyrightconfig.samples.json accordingly
    
    * updates to response format and setup
    
    * fix: patch AIProjectClient at correct module path in test
    
    Patch agent_framework.azure._responses_client.AIProjectClient instead of
    azure.ai.projects.aio.AIProjectClient since the import is at module level.
    
    * docs: add Foundry sample to READMEs and document AZURE_AI_PROJECT_ENDPOINT env var
    
    ---------
    
    Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
    Co-authored-by: eavanvalkenburg <13749212+eavanvalkenburg@users.noreply.github.com>
    Co-authored-by: eavanvalkenburg <github@vanvalkenburg.eu>
  • Python: [BREAKING] Replace Hosted*Tool classes with tool methods (#3634)
    * Replace Hosted*Tool classes with client static factory methods
    
    * fixed failing test
    
    * mypy fix
    
    * mypy fix 2
    
    * declarative mypy fix
    
    * addressed comments
    
    * ToolProtocol removal
    
    * fixed test
    
    * agents mypy fix
    
    * fix failing tests
    
    * mypy fix
    
    * addressed comments
    
    * fixed tests
    
    * addressed comments + added factory method overrides for azureai v2 client
    
    * mypy fix
    
    * added kwargs to azureai tool methods
    
    * fixed in test
    
    * _sessions fix
    
    * test fix
  • Python: [BREAKING] Simplify API: ChatAgent -> Agent, ChatMessage -> Message (#3747)
    * [BREAKING] Rename ChatAgent -> Agent, ChatMessage -> Message, ChatClientProtocol -> SupportsChatGetResponse
    
    Simplify the public API by removing redundant 'Chat' prefix from core types:
    - ChatAgent -> Agent
    - RawChatAgent -> RawAgent
    - ChatMessage -> Message
    - ChatClientProtocol -> SupportsChatGetResponse
    
    Also renamed internal WorkflowMessage (was Message in _runner_context) to avoid collision.
    
    No backward compatibility aliases - this is a clean breaking change.
    
    * [BREAKING] Rename Agent chat_client parameter to client
    
    * Fix rebase issues: WorkflowMessage references and broken markdown links
    
    * Fix formatting and lint issues from code quality checks
    
    * Fix import ordering in workflow sample files
    
    * fixed rebase
    
    * Fix test failures: use WorkflowMessage and A2AMessage after ChatMessage→Message rename
    
    - Replace Message(data=..., source_id=...) with WorkflowMessage(...) in workflow tests
    - Fix isinstance check in A2A agent to use A2AMessage instead of Message
    - Fix import in test_workflow_observability.py (Message→WorkflowMessage)
    
    * Fix lint, fmt, and sample errors after ChatMessage→Message rename
    
    - Auto-fix 70+ ruff lint issues across samples (ChatMessage→Message refs)
    - Fix HostedVectorStoreContent→Content.from_hosted_vector_store in file search sample
    - Fix _normalize_messages→normalize_messages in custom agent sample
    - Fix context.terminate→raise MiddlewareTermination in middleware samples
    - Fix with_update_hook→with_transform_hook in override middleware sample
    - Add TOptions_co import back to custom_chat_client sample
    - Add noqa for FastAPI File() default in chatkit sample
    - Fix B023 loop variable capture in weather agent sample
    
    * fix: update Agent constructor calls from chat_client to client in declaration-only tool tests
    
    * fix: add register_cleanup to devui lazy-loading proxy and type stub
    
    * fixed tests and updated new pieces
    
    * fix agui typevar
    
    * fix merge errors
    
    * fix merge conflicts
    
    * fiux merge
    
    * Remove unused links
    
    ---------
    
    Co-authored-by: Evan Mattson <evan.mattson@microsoft.com>
  • [BREAKING] Python: Remove workflow register factory methods. Update tests and samples (#3781)
    * Remove workflow register factory methods. Update tests and samples
    
    * Address Copilot feedback
  • Python: PR1 — New session and context provider types (side-by-side) (#3763)
    * PR1: Add core context provider types and tests
    
    New types in _sessions.py (no changes to existing code):
    - SessionContext: per-invocation state with extend_messages/get_messages/
      extend_instructions/extend_tools and read-only response property
    - _ContextProviderBase: base class with before_run/after_run hooks
    - _HistoryProviderBase: storage base with load/store flags, abstract
      get_messages/save_messages, default before_run/after_run
    - AgentSession: lightweight session with state dict, to_dict/from_dict
    - InMemoryHistoryProvider: built-in provider storing in session.state
    
    35 unit tests covering all classes and configuration flags.
    
    * feat: keyword-only params, stateless InMemoryHistoryProvider, deep serialization
    
    - Make before_run/after_run parameters keyword-only
    - InMemoryHistoryProvider stores ChatMessage objects directly (no per-cycle serialization)
    - Deep serialization via to_dict/from_dict only at session boundary
    - State type registry for automatic deserialization of registered types
    - Updated tests for new serialization approach
    
    * feat: add new-pattern provider implementations for external packages
    
    - _RedisContextProvider(BaseContextProvider) - Redis search/vector context
    - _RedisHistoryProvider(BaseHistoryProvider) - Redis-backed message storage
    - _Mem0ContextProvider(BaseContextProvider) - Mem0 semantic memory
    - _AzureAISearchContextProvider(BaseContextProvider) - Azure AI Search (semantic + agentic)
    
    All use temporary _ prefix names for side-by-side coexistence with existing providers.
    Will be renamed in PR2 when old ContextProvider/ChatMessageStore are removed.
    
    * test: add tests for new-pattern provider implementations
    
    - 32 tests for _RedisContextProvider and _RedisHistoryProvider
    - 29 tests for _Mem0ContextProvider
    - 17 tests for _AzureAISearchContextProvider
    
    * fix: address PR review comments and CI failures
    
    - Move module docstring before imports in _sessions.py (review comment)
    - Import TYPE_CHECKING unconditionally in Redis _context_provider.py (NameError on Python <3.12)
    - Fix Mem0 test_init_auto_creates_client_when_none to patch at class level
    
    * feat: add source attribution to extend_messages
    
    Set attribution marker in additional_properties for each message
    added via extend_messages(), matching the tool attribution pattern.
    Uses setdefault to preserve any existing attribution.
    
    * refactor: make attribution value a dict with source_id key
    
    * add attribution and use sets for filters
    
    * Add source_type to message attribution and copy messages in extend_messages
    
    - SessionContext.extend_messages now accepts source as str or object with
      source_id attribute; when an object is passed, its class name is recorded
      as source_type in the attribution dict
    - Messages are shallow-copied before attribution is added so callers'
      original objects are never mutated
    - Filter framework-internal keys (attribution) from A2A wire metadata
      to prevent leaking internal state over the wire
    
    * fix: correct mypy type: ignore comment from union-attr to attr-defined
    
    * set attribution to _attribution
    
    * adjusted naming of bools
  • Python: Add long-running agents and background responses support (#3808)
    * Python: Add long-running agents and background responses support
    
    - Add ContinuationToken TypedDict to core types
    - Add continuation_token field to ChatResponse, ChatResponseUpdate,
      AgentResponse, and AgentResponseUpdate
    - Add background and continuation_token options to OpenAIResponsesOptions
    - Implement polling via responses.retrieve() and streaming resumption
      in RawOpenAIResponsesClient
    - Propagate continuation tokens through agent run() and
      map_chat_to_agent_update
    - Fix streaming telemetry 'Failed to detach context' error in both
      ChatTelemetryLayer and AgentTelemetryLayer by avoiding
      trace.use_span() context attachment for async-managed spans
    - Add 14 unit tests for continuation token types and background flows
    - Add background_responses sample showing polling and stream resumption
    
    Fixes #2478
    
    * Python: Add A2A long-running task support via ContinuationToken
    
    - Make ContinuationToken provider-agnostic (total=False, optional task_id/context_id fields)
    - Add background param to A2AAgent.run() controlling token emission
    - Add poll_task() for single-request task state retrieval
    - Add resubscribe support via continuation_token param on run()
    - Extract _updates_from_task() and _map_a2a_stream() for cleaner code
    - Streamline run()/streaming by removing intermediate _stream_updates wrapper
    - Update A2A sample to show background=False (default) with link to background_responses sample
    - Remove stale BareAgent from __all__
    - Add 12 new A2A continuation token tests
    
    * fix logic for overriding continuation token when done
    
    * refactored ContinuationToken setup
  • Python: Add streaming support for code interpreter deltas (#3775)
    * add streaming support for code interpreter deltas
    
    * addressed copilot comments
    
    * mypy fix
  • Python: [BREAKING] Standardize TypeVar naming convention (TName → NameT) (#3770)
    * standardized typevar to use suffix T
    
    * addressed copilot comments
  • Python: Include sub-workflow structure in graph signature for checkpoint validation (#3783)
    * Include sub-workflow structure in graph signature for checkpoint validation
    
    * Remove redundant computation
  • Python: Fix prek runner duplication and add skills (#3791)
    * Python: fix prek runner running fmt/lint in all packages on core change
    
    When a core package file changed, run_tasks_in_changed_packages.py ran
    fmt, lint, and pyright in ALL 22 packages (66 tasks). Only type-checking
    tasks (pyright, mypy) need to propagate to all packages since type
    changes in core affect downstream packages. File-local tasks (fmt, lint)
    only need to run in packages with actual file changes.
    
    This reduces a core-only change from 66 tasks to 24 tasks (2 local +
    22 pyright).
    
    Also adds no-commit-to-branch builtin hook to protect the main branch
    from direct commits.
    
    * Python: add agent skills extracted from AGENTS.md and coding standards
    
    Add 5 skills to python/.github/skills/ following the Agent Skills format:
    - python-development: coding standards, type annotations, docstrings, logging
    - python-testing: test structure, fixtures, running tests, async mode
    - python-code-quality: linting, formatting, type checking, prek hooks, CI
    - python-package-management: monorepo structure, lazy loading, versioning
    - python-samples: sample structure, PEP 723, documentation guidelines
    
    * Python: deduplicate AGENTS.md and instructions with agent skills
    
    * updated skills
    
    * fixes from review
    
    * Python: increase timeout for web search integration test
  • Python: Fix workflow not pausing when agent calls declaration-only tool (#3757)
    * Fix workflow not pausing when agent calls declaration-only tool
    
    * Remove comment
  • Python: Added explicit schema handling to @tool decorator (#3734)
    * Added explicit schema handling to @tool decorator
    
    * Resolved comments
  • Python: [BREAKING] Renamed next middleware parameter to call_next (#3735)
    * Renamed next middleware parameter to call_next
    
    * Resolved comments
  • [BREAKING] Python: Move single-config fluent methods to constructor parameters (#3693)
    * Move single-config fluent methods to constructor parameters
    
    * Updates
    
    * Adjust magentic and group chat
  • [BREAKING] Python: Merge send_responses into run method (#3720)
    * Streamline workflow run api with send responses in one method
    
    * Fixes
    
    * Address copilot feedback
  • Python: [BREAKING] Renamed AgentProtocol to SupportsAgentRun (#3717)
    * Renamed AgentProtocol to AgentLike
    
    * Resolved comments
    
    * Renamed AgentLike to SupportsAgentRun
    
    * Resolved comments