Add a dedicated integration test job for the github_copilot package to both
python-integration-tests.yml and python-merge-tests.yml.
The job:
- Runs 6 integration tests marked with @pytest.mark.integration
- Uses COPILOT_GITHUB_TOKEN secret from the integration environment
- Follows the same pattern as other provider integration jobs
- Includes path filtering in merge-tests (github_copilot package + core changes)
- Added to needs lists in report and check jobs
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replaces every floating tag in our workflow and composite action files
with an immutable 40-character commit SHA, keeping the original `# vX`
comment so Dependabot can still propose version bumps. 186 occurrences
across 25 workflows and 2 composite actions.
Also widens the github-actions Dependabot entry to use the plural
`directories` key with `/.github/actions/*` so composite actions under
`.github/actions/<name>/action.yml` are kept up to date. Previously
Dependabot only scanned `.github/workflows` and the repo-root
`action.yml`, leaving our `python-setup` and `sample-validation-setup`
composite actions unmaintained.
* Enable Ollama integration tests in CI and rename report to Integration Test Report
- Install Ollama, cache models (qwen2.5:0.5b + nomic-embed-text), and start
server in the Misc integration job for both workflow files
- Set OLLAMA_MODEL and OLLAMA_EMBEDDING_MODEL env vars so the 5 Ollama tests
are no longer skipped
- Rename Flaky Test Report to Integration Test Report throughout (job names,
artifact names, cache keys, file names, script titles/docstrings)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Bump Ollama model to qwen2.5:1.5b for better instruction following
The 0.5b model was too small to reliably follow simple prompts like
'Say Hello World', causing test assertion failures. The 1.5b model
follows instructions more reliably while still being small enough
for fast CI pulls (~1GB).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Re-enable reliable streaming integration tests
Remove the hard skip on test_03_reliable_streaming tests that was
temporarily disabled for instability investigation. CI infrastructure
(Azurite, DTS emulator, Redis, func CLI) is already in place.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Re-enable skipped Functions/DurableTask tests and bump timeout to 480s
- Remove hard skips from 4 tests in test_11_workflow_parallel.py
- Remove hard skip from test_conditional_branching in test_06_dt_multi_agent_orchestration_conditionals.py
- Increase pytest --timeout from 360 to 480 for Functions+DurableTask CI job
- Updated in both python-merge-tests.yml and python-integration-tests.yml
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Re-skip failing Functions/DurableTask tests with specific root causes
- test_11_workflow_parallel (4 tests): xdist worker crashes during execution
- test_conditional_branching: orchestration fails with RuntimeError, not a timeout
- Keep 480s timeout bump for remaining Functions tests
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix auth routing in samples 06/11: api_key -> credential for Azure OpenAI
Both samples passed a bearer token provider via api_key= which caused the
client to route to api.openai.com instead of Azure OpenAI, resulting in
401 Unauthorized. Changed to credential= which correctly triggers Azure
routing and picks up AZURE_OPENAI_ENDPOINT from the environment.
- samples/azure_functions/11_workflow_parallel/function_app.py: 1 fix
- samples/durabletask/06_multi_agent_orchestration_conditionals/worker.py: 2 fixes
- Re-enable 4 parallel workflow tests and 1 conditional branching test
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Re-skip parallel workflow tests: xdist worker distribution issue
The 4 parallel workflow tests crash because xdist worksteal distributes
them across separate workers, each spawning its own func process against
shared emulators. Auth fix (api_key->credential) was valid and stays.
test_conditional_branching now passes with the auth fix.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix E501 line-too-long in azurefunctions parallel test skip reasons
Wrap skip reason strings to stay within 120 char line limit.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add retry logic and port-conflict fix for Ollama CI setup
- Kill any auto-started Ollama before launching serve (fixes port
conflict: 'address already in use')
- Retry ollama pull up to 3 times with 15s backoff (fixes 429 rate
limit failures)
- Applied to both python-merge-tests.yml and python-integration-tests.yml
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix flaky integration tests and re-enable skipped tests
- Foundry agent: add allow_preview=True to custom client test
- Foundry hosting: raise max_output_tokens 50->200, add temperature,
relax assertion in test_temperature_and_max_tokens
- Foundry embedding: update skip reason with root cause (endpoint mismatch)
- OpenAI file search: fix vector store indexing race condition by polling
file_counts before querying; fix get_streaming_response -> get_response(stream=True)
- Azure OpenAI file search: remove skip (transient 500 resolved)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Remove temperature from foundry hosting test (unsupported by CI model)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Stabilize Ollama tool call integration tests with no-arg function
Use a no-argument greet() function instead of hello_world(arg1) for
integration tests. The 1.5B model in CI is unreliable at generating
correct tool call arguments, causing 'Argument parsing failed' errors.
A no-arg function eliminates this flakiness entirely.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Increase reliable streaming test timeouts from 30s to 60s
The LLM call through Azure OpenAI + Redis streaming pipeline can exceed
30s in CI due to cold starts or throttling. Raise to 60s to reduce
flaky timeouts while still bounded by pytest's 120s per-test limit.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Re-enable workflow parallel tests with xdist_group marker
The tests were skipped because xdist distributes module tests across
workers, each spawning their own func process (port conflicts). Adding
xdist_group forces all tests in this module onto a single worker so
the module-scoped function_app_for_test fixture works correctly.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Revert "Re-enable workflow parallel tests with xdist_group marker"
This reverts commit 455c28da62.
* Rename flaky_report to integration_test_report and add try/finally cleanup
- Rename scripts/flaky_report/ to scripts/integration_test_report/ to
reflect expanded scope beyond flaky-test detection
- Update workflow references in both CI files
- Wrap file search integration tests in try/finally to ensure vector
store cleanup runs even on test failure or timeout
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix Ollama pull failure propagation and Azure OpenAI vector store readiness
- Ollama CI: fail the step immediately if model pull fails after 3
retries instead of silently proceeding to tests
- Azure OpenAI file search: add the same vector-store readiness polling
that was applied to the non-Azure OpenAI tests, preventing eventual
consistency race conditions
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* remove load_dotenv from test file
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add flaky test trend reporting to CI workflows
Parse JUnit XML (pytest.xml) from each integration test job and
aggregate results into a markdown trend report showing per-test
pass/fail/skip status across the last 5 runs.
Changes:
- Add python/scripts/flaky_report/ package (JUnit XML parser + trend
report generator following the sample_validation pattern)
- Add upload-artifact steps to all 6 integration test jobs in both
python-merge-tests.yml and python-integration-tests.yml
- Add python-flaky-test-report aggregation job with history caching
- Add --junitxml=pytest.xml to integration-tests.yml jobs (already
present in merge-tests.yml)
- Fix Cosmos job --junitxml path (use absolute path since uv run
--directory changes cwd)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix flaky report: handle missing test results gracefully
- Guard against missing reports directory in load_current_run()
- Only run report job when at least one integration test job completed
(skip when all jobs are skipped, e.g. on pull_request events)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address PR review: fix provider names and if-expression precedence
- Use explicit provider name mapping in _derive_provider() so OpenAI
renders correctly instead of 'Openai'
- Fix operator precedence in workflow if-expressions by wrapping
success/failure checks in parentheses
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add File column and xfail detection to flaky test report
- Add File column showing module name (e.g., test_openai_chat_client)
to disambiguate tests with the same function name across files
- Detect pytest xfail tests in JUnit XML (type=pytest.xfail) and
show them with a distinct warning emoji instead of skip emoji
- Update legend to include xfail explanation
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add Foundry embedding env vars to merge-tests workflow
Sync the Foundry integration job in python-merge-tests.yml with
python-integration-tests.yml by adding FOUNDRY_MODELS_ENDPOINT,
FOUNDRY_MODELS_API_KEY, FOUNDRY_EMBEDDING_MODEL, and
FOUNDRY_IMAGE_EMBEDDING_MODEL. Once the repo variables/secrets
are configured, the embedding integration test will run in CI.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix File column showing class name instead of module name
When a test is inside a class, pytest writes the classname as e.g.
'pkg.test_file.TestClass'. The previous rsplit logic extracted
'TestClass' instead of 'test_file'. Now detect uppercase-starting
segments as class names and use the preceding segment instead.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address PR review: UTC timestamps, XML error handling, summary fix, docstring
- Use datetime.now(timezone.utc) for accurate UTC timestamps
- Catch ET.ParseError per-file so corrupt XML doesn't crash the report
- Remove separate 'error' key from summary (errors folded into 'failed')
- Fix _short_name docstring to show actual dotted classname::name format
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The misc-integration job (Anthropic, Ollama, MCP) frequently fails on merge to main when the upstream MCP server (e.g. learn.microsoft.com/api/mcp) returns a transient rate-limit error. The previous 5s retry delay is too short to ride out the upstream backoff window, so all retries fail and the merge queue is blocked. Bumping to 30s gives the upstream a chance to recover before pytest-retry re-runs the test.
* Fix reasoning text done events duplicating streamed delta content (#5157)
The OpenAI Responses API sends both reasoning_text.delta (incremental
chunks) and reasoning_text.done (full accumulated text) events. The
chat client was emitting Content for both, causing ag-ui to append the
full done text onto already-accumulated delta text, producing
duplicated reasoning output.
Stop emitting Content for reasoning_text.done and
reasoning_summary_text.done events, matching how output_text.done is
already handled (not emitted). The deltas contain all the content;
the done event is redundant.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(openai): emit reasoning done content as fallback when no deltas observed (#5157)
Address PR review feedback:
- Track item_ids that received reasoning deltas via seen_reasoning_delta_item_ids set
- Emit content from done events only when no deltas were received for the
item_id, preventing silent content loss on stream resumption
- Add comment documenting code_interpreter done event asymmetry
- Replace redundant ag-ui test with deduplication-focused test
- Add integration test for delta+done sequence in OpenAI chat client tests
- Add fallback path tests for done events without preceding deltas
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address review feedback for #5157: Python: [Bug]: "type": "response.reasoning_text.delta" and "response.reasoning_text.done" both get exposed as "text_reasoning"
* Fix AG-UI reasoning streaming to use proper Start/End pattern (#5157)
_emit_text_reasoning now follows the same streaming pattern as _emit_text:
- Emits ReasoningStartEvent/ReasoningMessageStartEvent only on the first
delta for a given message_id
- Emits only ReasoningMessageContentEvent for subsequent deltas
- Defers ReasoningMessageEndEvent/ReasoningEndEvent until
_close_reasoning_block is called (on content type switch or end-of-run)
This produces the correct protocol pattern:
ReasoningStartEvent
ReasoningMessageStartEvent
ReasoningMessageContentEvent(delta1)
ReasoningMessageContentEvent(delta2)
ReasoningMessageEndEvent
ReasoningEndEvent
Instead of wrapping every delta in a full Start→End sequence.
Backward compatibility is preserved: calling _emit_text_reasoning without
a flow argument still produces the full sequence per call.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix import ordering lint error in AG-UI test file (#5157)
Move inline import of TextMessageContentEvent to the top-level import
block and ensure alphabetical ordering to satisfy ruff I001 rule.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix mypy error: rename loop variable to avoid type conflict with WorkflowEvent
The 'event' variable was already typed as WorkflowEvent[Any] from the
async for loop at line 590. Reusing it in the _close_reasoning_block
loop (which returns list[BaseEvent]) caused an incompatible assignment
error. Renamed to 'reasoning_evt' to avoid the conflict.
Fixes#5162
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address review feedback for #5157: review comment fixes
* narrow test result reporting to explicit pytest JUnit XML
* Fix test args
* Fix pytest-results-action in merge workflow and remove committed test artifacts
Apply the same JUnit XML fix from python-tests.yml to python-merge-tests.yml:
add --junitxml=pytest.xml to all test commands and narrow the results action
path from ./python/**.xml to ./python/pytest.xml. Also remove accidentally
committed pytest.xml and python-coverage.xml and add them to .gitignore.
---------
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Refactor Anthropic model option and provider clients
Rename the Anthropic client model option from model_id to model, add provider-specific Anthropic wrappers for Foundry, Bedrock, and Vertex, and expose them through the Anthropic, Foundry, Amazon, and Google namespaces. Update core option handling, docs, samples, and tests accordingly.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix Anthropic skills sample typing
Cast the Anthropic beta client to Any in the skills sample so the pre-commit sample pyright check no longer fails on beta skills and files endpoints that are not exposed by the current SDK stubs.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* undo sample mypy
* Retry CI after transient external failures
Retrigger PR validation after an unrelated Copilot review workflow SAML failure and a transient external tau2 git fetch failure in the Windows Python test setup.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address review feedback on model option merging
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address Anthropic compatibility review feedback
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* moved all to `model`
* fixes for azure ai search
* Python: standardize remaining sample env var names
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Python: fix foundry-local pyright compatibility
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* updated env vars in cicd
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* updated automation tasks and commands, with alias for the time being
* Restore aggregate test exclusions
Preserve the legacy all-tests scope for test --all by excluding lab and devui from the default aggregate sweep, while still allowing explicit package selection. Also ignore hidden/generated test directories such as .mypy_cache during aggregate discovery.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* updated versions in pre-commit
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Update github_copilot package for github-copilot-sdk>=0.1.32 (#4549)
- Update requires-python from >=3.10 to >=3.11
- Remove Python 3.10 classifier
- Update mypy python_version to 3.11
- Update dependency to github-copilot-sdk>=0.1.32
- Fix ToolResult API: use snake_case kwargs (text_result_for_llm,
result_type) instead of camelCase (textResultForLlm, resultType)
- Update test assertions to use attribute access on ToolResult
- Add ToolResult type assertions to tool handler tests
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix tests to use ToolInvocation dataclass instead of plain dict (#4549)
Update test_github_copilot_agent.py to pass ToolInvocation objects to tool
handlers instead of plain dicts, matching the github-copilot-sdk>=0.1.32 API
where ToolInvocation is a dataclass with an .arguments attribute.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add regression tests for ToolInvocation contract (#4549)
Add tests to lock in the new ToolInvocation-based calling convention:
- test_tool_handler_rejects_raw_dict_invocation: verifies passing a raw
dict (old calling convention) raises TypeError/AttributeError
- test_tool_handler_with_empty_arguments: verifies ToolInvocation with
empty arguments works correctly for no-arg tools
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Revert requires-python to >=3.10 to avoid breaking CI (#4549)
The repo CI runs with Python 3.10 (uv sync --all-packages) and all other
packages require >=3.10. Raising this package to >=3.11 would break the
shared install flow. The SDK dependency version constraint (>=0.1.32) will
enforce any Python version requirement from the SDK itself.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix min Python version for github_copilot package to >=3.11
github-copilot-sdk>=0.1.32 requires Python>=3.11, which conflicts
with the package's declared >=3.10 minimum, breaking uv sync.
* Bump py version for GH workflows to 3.11, exclude GHCP sdk from 3.10 items
* Fix uv command
* Fixes
* Update samples
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* 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>
* 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>
* Updated merge test permissions
* Removed repo check
* Added fetch from main for comparison
* Updated path detection logic
* Small updates
* Reverted file rename
* Created dedicated workflows for integration tests
* Small fix for Python
* Small fixes
* Small update
* Small update
* Added tests check for Python
* WIP
* big update to new ResponseStream model
* fixed tests and typing
* fixed tests and typing
* fixed tools typevar import
* fix
* mypy fix
* mypy fixes and some cleanup
* fix missing quoted names
* and client
* fix imports agui
* fix anthropic override
* fix agui
* fix ag ui
* fix import
* fix anthropic types
* fix mypy
* refactoring
* updated typing
* fix 3.11
* fixes
* redid layering of chat clients and agents
* redid layering of chat clients and agents
* Fix lint, type, and test issues after rebase
- Add @overload decorators to AgentProtocol.run() for type compatibility
- Add missing docstring params (middleware, function_invocation_configuration)
- Fix TODO format (TD002) by adding author tags
- Fix broken observability tests from upstream:
- Replace non-existent use_instrumentation with direct instantiation
- Replace non-existent use_agent_instrumentation with AgentTelemetryLayer mixin
- Fix get_streaming_response to use get_response(stream=True)
- Add AgentInitializationError import
- Update streaming exception tests to match actual behavior
* Fix AgentExecutionException import error in test_agents.py
- Replace non-existent AgentExecutionException with AgentRunException
* Fix test import and asyncio deprecation issues
- Add 'tests' to pythonpath in ag-ui pyproject.toml for utils_test_ag_ui import
- Replace deprecated asyncio.get_event_loop().run_until_complete with asyncio.run
* Fix azure-ai test failures
- Update _prepare_options patching to use correct class path
- Fix test_to_azure_ai_agent_tools_web_search_missing_connection to clear env vars
* Convert ag-ui utils_test_ag_ui.py to conftest.py
- Move test utilities to conftest.py for proper pytest discovery
- Update all test imports to use conftest instead of utils_test_ag_ui
- Remove old utils_test_ag_ui.py file
- Revert pythonpath change in pyproject.toml
* fix: use relative imports for ag-ui test utilities
* fix agui
* Rename Bare*Client to Raw*Client and BaseChatClient
- Renamed BareChatClient to BaseChatClient (abstract base class)
- Renamed BareOpenAIChatClient to RawOpenAIChatClient
- Renamed BareOpenAIResponsesClient to RawOpenAIResponsesClient
- Renamed BareAzureAIClient to RawAzureAIClient
- Added warning docstrings to Raw* classes about layer ordering
- Updated README in samples/getting_started/agents/custom with layer docs
- Added test for span ordering with function calling
* Fix layer ordering: FunctionInvocationLayer before ChatTelemetryLayer
This ensures each inner LLM call gets its own telemetry span, resulting in
the correct span sequence: chat -> execute_tool -> chat
Updated all production clients and test mocks to use correct ordering:
- ChatMiddlewareLayer (first)
- FunctionInvocationLayer (second)
- ChatTelemetryLayer (third)
- BaseChatClient/Raw...Client (fourth)
* Remove run_stream usage
* Fix conversation_id propagation
* Python: Add BaseAgent implementation for Claude Agent SDK (#3509)
* Added ClaudeAgent implementation
* Updated streaming logic
* Small updates
* Small update
* Fixes
* Small fix
* Naming improvements
* Updated imports
* Addressed comments
* Updated package versions
* Update Claude agent connector layering
* fix test and plugin
* Store function middleware in invocation layer
* Fix telemetry streaming and ag-ui tests
* Remove legacy ag-ui tests folder
* updates
* Remove terminate flag from FunctionInvocationContext, use MiddlewareTermination instead
- Remove terminate attribute from FunctionInvocationContext
- Add result attribute to MiddlewareTermination to carry function results
- FunctionMiddlewarePipeline.execute() now lets MiddlewareTermination propagate
- _auto_invoke_function captures context.result in exception before re-raising
- _try_execute_function_calls catches MiddlewareTermination and sets should_terminate
- Fix handoff middleware to append to chat_client.function_middleware directly
- Update tests to use raise MiddlewareTermination instead of context.terminate
- Add middleware flow documentation in samples/concepts/tools/README.md
- Fix ag-ui to use FunctionMiddlewarePipeline instead of removed create_function_middleware_pipeline
* fix: remove references to removed terminate flag in purview tests, add type ignore
* fix: move _test_utils.py from package to test folder
* fix: call get_final_response() to trigger context provider notification in streaming test
* fix: correct broken links in tools README
* docs: clarify default middleware behavior in summary table
* fix: ensure inner stream result hooks are called when using map()/from_awaitable()
* Fix mypy type errors
* Address PR review comments on observability.py
- Remove TODO comment about unconsumed streams, add explanatory note instead
- Remove redundant _close_span cleanup hook (already called in _finalize_stream)
- Clarify behavior: cleanup hooks run after stream iteration, if stream is not
consumed the span remains open until garbage collected
* Remove gen_ai.client.operation.duration from span attributes
Duration is a metrics-only attribute per OpenTelemetry semantic conventions.
It should be recorded to the histogram but not set as a span attribute.
* Remove duration from _get_response_attributes, pass directly to _capture_response
Duration is a metrics-only attribute. It's now passed directly to _capture_response
instead of being included in the attributes dict that gets set on the span.
* Remove redundant _close_span cleanup hook in AgentTelemetryLayer
_finalize_stream already calls _close_span() in its finally block,
so adding it as a separate cleanup hook is redundant.
* Use weakref.finalize to close span when stream is garbage collected
If a user creates a streaming response but never consumes it, the cleanup
hooks won't run. Now we register a weak reference finalizer that will close
the span when the stream object is garbage collected, ensuring spans don't
leak in this scenario.
* Fix _get_finalizers_from_stream to use _result_hooks attribute
Renamed function to _get_result_hooks_from_stream and fixed it to
look for the _result_hooks attribute which is the correct name in
ResponseStream class.
* Add missing asyncio import in test_request_info_mixin.py
* Fix leftover merge conflict marker in image_generation sample
* Update integration tests
* Fix integration tests: increase max_iterations from 1 to 2
Tests with tool_choice options require at least 2 iterations:
1. First iteration to get function call and execute the tool
2. Second iteration to get the final text response
With max_iterations=1, streaming tests would return early with only
the function call/result but no final text content.
* Fix duplicate function call error in conversation-based APIs
When using conversation_id (for Responses/Assistants APIs), the server
already has the function call message from the previous response. We
should only send the new function result message, not all messages
including the function call which would cause a duplicate ID error.
Fix: When conversation_id is set, only send the last message (the tool
result) instead of all response.messages.
* Add regression test for conversation_id propagation between tool iterations
Port test from PR #3664 with updates for new streaming API pattern.
Tests that conversation_id is properly updated in options dict during
function invocation loop iterations.
* Fix tool_choice=required to return after tool execution
When tool_choice is 'required', the user's intent is to force exactly one
tool call. After the tool executes, return immediately with the function
call and result - don't continue to call the model again.
This fixes integration tests that were failing with empty text responses
because with tool_choice=required, the model would keep returning function
calls instead of text.
Also adds regression tests for:
- conversation_id propagation between tool iterations (from PR #3664)
- tool_choice=required returns after tool execution
* Document tool_choice behavior in tools README
- Add table explaining tool_choice values (auto, none, required)
- Explain why tool_choice=required returns immediately after tool execution
- Add code example showing the difference between required and auto
- Update flow diagram to show the early return path for tool_choice=required
* Fix tool_choice=None behavior - don't default to 'auto'
Remove the hardcoded default of 'auto' for tool_choice in ChatAgent init.
When tool_choice is not specified (None), it will now not be sent to the
API, allowing the API's default behavior to be used.
Users who want tool_choice='auto' can still explicitly set it either in
default_options or at runtime.
Fixes#3585
* Fix tool_choice=none should not remove tools
In OpenAI Assistants client, tools were not being sent when
tool_choice='none'. This was incorrect - tool_choice='none' means
the model won't call tools, but tools should still be available
in the request (they may be used later in the conversation).
Fixes#3585
* Add test for tool_choice=none preserving tools
Adds a regression test to ensure that when tool_choice='none' is set but
tools are provided, the tools are still sent to the API. This verifies
the fix for #3585.
* Fix tool_choice=none should not remove tools in all clients
Apply the same fix to OpenAI Responses client and Azure AI client:
- OpenAI Responses: Remove else block that popped tool_choice/parallel_tool_calls
- Azure AI: Remove tool_choice != 'none' check when adding tools
When tool_choice='none', the model won't call tools, but tools should
still be sent to the API so they're available for future turns.
Also update README to clarify tool_choice=required supports multiple tools.
Fixes#3585
* Keep tool_choice even when tools is None
Move tool_choice processing outside of the 'if tools' block in OpenAI
Responses client so tool_choice is sent to the API even when no tools
are provided.
* Update test to match new parallel_tool_calls behavior
Changed test_prepare_options_removes_parallel_tool_calls_when_no_tools to
test_prepare_options_preserves_parallel_tool_calls_when_no_tools to reflect
that parallel_tool_calls is now preserved even when no tools are present,
consistent with the tool_choice behavior.
* Fix ChatMessage API and Role enum usage after rebase
- Update ChatMessage instantiation to use keyword args (role=, text=, contents=)
- Fix Role enum comparisons to use .value for string comparison
- Add created_at to AgentResponse in error handling
- Fix AgentResponse.from_updates -> from_agent_run_response_updates
- Fix DurableAgentStateMessage.from_chat_message to convert Role enum to string
- Add Role import where needed
* Fix additional ChatMessage API and method name changes
- Fix ChatMessage usage in workflow files (use text= instead of contents= for strings)
- Fix AgentResponse.from_updates -> from_agent_run_response_updates in workflow files
- Fix test files for ChatMessage and Role enum usage
* Fix remaining ChatMessage API usage in test files
* Fix more ChatMessage and Role API changes in source and test files
- Fix ChatMessage in _magentic.py replan method
- Fix Role enum comparison in test assertions
- Fix remaining test files with old ChatMessage syntax
* Fix ChatMessage and Role API changes across packages
- Add Role import where missing
- Fix ChatMessage signature: positional args to keyword args (role=, text=, contents=)
- Fix Role enum comparisons: .role.value instead of .role string
- Fix FinishReason enum usage in ag-ui event converters
- Rename AgentResponse.from_updates to from_agent_run_response_updates in ag-ui
Fixes API compatibility after Types API Review improvements merge
* Fix ChatMessage and Role API changes in github_copilot tests
* Fix ChatMessage and Role API changes in redis and github_copilot packages
- Fix redis provider: Role enum comparison using .value
- Fix redis tests: ChatMessage signature and Role comparisons
- Fix github_copilot tests: ChatMessage signature and Role comparisons
- Update docstring examples in redis chat message store
* Fix ChatMessage and Role API changes in devui package
- Fix executor: ChatMessage signature change
- Fix conversations: Role enum to string conversion in two places
- Fix tests: ChatMessage signatures and Role comparisons
* Fix ChatMessage and Role API changes in a2a and lab packages
- Fix a2a tests: Role comparisons and ChatMessage signatures
- Fix lab tau2 source: Role enum comparison in flip_messages, log_messages, sliding_window
- Fix lab tau2 tests: ChatMessage signatures and Role comparisons
* Remove duplicate test files from ag-ui/tests (tests are in ag_ui_tests)
* Fix ChatMessage and Role API changes across packages
After rebasing on upstream/main which merged PR #3647 (Types API Review
improvements), fix all packages to use the new API:
- ChatMessage: Use keyword args (role=, text=, contents=) instead of
positional args
- Role: Compare using .value attribute since it's now an enum
Packages fixed:
- ag-ui: Fixed Role value extraction bugs in _message_adapters.py
- anthropic: Fixed ChatMessage and Role comparisons in tests
- azure-ai: Fixed Role comparison in _client.py
- azure-ai-search: Fixed ChatMessage and Role in source/tests
- bedrock: Fixed ChatMessage signatures in tests
- chatkit: Fixed ChatMessage and Role in source/tests
- copilotstudio: Fixed ChatMessage and Role in tests
- declarative: Fixed ChatMessage in _executors_agents.py
- mem0: Fixed ChatMessage and Role in source/tests
- purview: Fixed ChatMessage in source/tests
* Fix mypy errors for ChatMessage and Role API changes
- durabletask: Use str() fallback in role value extraction
- core: Fix ChatMessage in _orchestrator_helpers.py to use keyword args
- core: Add type ignore for _conversation_state.py contents deserialization
- ag-ui: Fix type ignore comments (call-overload instead of arg-type)
- azure-ai-search: Fix get_role_value type hint to accept Any
- lab: Move get_role_value to module level with Any type hint
* Improve CI test timeout configuration
- Increase job timeout from 10 to 15 minutes
- Reduce per-test timeout to 60s (was 900s/300s)
- Add --timeout_method thread for better timeout handling
- Add --timeout-verbose to see which tests are slow
- Reduce retries from 3 to 2 and delay from 10s to 5s
This ensures individual test timeouts are shorter than the job
timeout, providing better visibility when tests hang.
With 60s timeout and 2 retries, worst case per test is ~180s.
* Fix ChatMessage API usage in docstrings and source
- Fix ChatMessage positional args in docstrings: _serialization.py, _threads.py, _middleware.py
- Fix ChatMessage in tau2 runner.py
- Fix role comparison in _orchestrator_helpers.py to use .value
- Fix role comparison in _group_chat.py docstring example
- Fix role assertions in test_durable_entities.py to use .value
* Revert tool_choice/parallel_tool_calls changes - must be removed when no tools
OpenAI API requires tool_choice and parallel_tool_calls to only be
present when tools are specified. Restored the logic that removes
these options when there are no tools.
- Restored check in _chat_client.py to remove tool_choice and
parallel_tool_calls when no tools present
- Restored same logic in _responses_client.py
- Reverted test to expect the correct behavior
* fixed issue in tests
* fix: resolve merge conflict markers in ag-ui tests
* fix: restructure ag-ui tests and fix Role/FinishReason to use string types
* fix: streaming function invocation and middleware termination
- Refactor streaming function invocation to use get_final_response() on inner streams
- Fix MiddlewareTermination to accept result parameter for passing results
- Fix _AutoHandoffMiddleware to use MiddlewareTermination instead of context.terminate
- Fix AgentMiddlewareLayer.run() to properly forward function/chat middleware
- Remove duplicate middleware registration in AgentMiddlewareLayer.__init__
- Fix exception handling in _auto_invoke_function to properly capture termination
- Fix mypy errors in core package
- Update tests to use stream=True parameter for unified run API
* fix all tests command
* Refactor integration tests to use pytest fixtures
- Merge testutils.py into conftest.py for azurefunctions integration tests
- Merge dt_testutils.py into conftest.py for durabletask integration tests
- Convert all integration tests to use fixtures instead of direct imports
(fixes ModuleNotFoundError with --import-mode=importlib)
- Add sample_helper fixture for azurefunctions tests
- Add agent_client_factory and orchestration_helper fixtures for durabletask
- Integration tests now skip with descriptive messages when services unavailable
- Restructure devui tests into tests/devui/ with proper conftest.py
- Add test organization guidelines to CODING_STANDARD.md
- Remove __init__.py from test directories per pytest best practices
* Fix pytest_collection_modifyitems to only skip integration tests
The hook was skipping all tests in the test session, not just
integration tests. Now it only skips items in the integration_tests
directory.
* Fix mem0 tests failing on Python 3.13
Use patch.object on the imported module instead of @patch with string
path to ensure the mock takes effect regardless of import timing.
* fix mem0
* another attempt for mem0
* fix for mem0
* fix mem0
* Increase worker initialization wait time in durabletask tests
Increase from 2 to 8 seconds to allow time for:
- Python startup and module imports
- Azure OpenAI client creation
- Agent registration with DTS worker
- Worker connection to DTS
This helps prevent test failures in CI where the first tests may run
before the worker is fully ready to process requests.
* Fix streaming test to use ResponseStream with finalizer
The _consume_stream method now expects a ResponseStream that can provide
a final AgentResponse via get_final_response(). Update the test to use
ResponseStream with AgentResponse.from_updates as the finalizer.
* Fix MockToolCallingAgent to use new ResponseStream API and update samples
* small updates to run_stream to run
* fix sub workflow
* temp fix for az func test
---------
Co-authored-by: Dmytro Struk <13853051+dmytrostruk@users.noreply.github.com>
* changed AIFunction to FunctionTool and @ai_function to @tool
* test and mypy fixes
* mypy fix
* switch function tool to always_require
* fix noop
* fix github copilot imports
* test fixes
* fix ollama test
* fixes for tests
* fix tests
* reverted change to always_require and extended timeout
* fix test
* initial version of anthropic connector
* updated implementation and added tests
* fix type and readme
* mypy fix and int tests enabled
* add integration test setup
* updated based on comments
* improved function result handling
* added extra unordered test
* updated from review
* fix tool choice handling
* same fix for chat client
* initial work on User Approval (and hosted mcp to validate)
* small update to the comments in the sample
* enable local MCP tools in chatClient get methods
* working streaming and improved setup
* fix for pyright
* updated create_approval -> create_response method
* added tests
* updated HostedMcpTool and addressed feedback
* update type name
* naming updates
* small docstring update
* mypy fix
* fixes and updates
* fixes for responses
* fix int tests
* removed broken tests
* updated test running
* removed specific content check on websearch
* increased timeout
* split slow foundry test
* don't parallel run samples
* add dist load to unit tests
---------
Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com>
* mcp parts
* mcp parts 2
* removed structured output in favor of handling in chatresponse, mcp as AITool and running samples
* updated naming
* fixed test
* Azure Responses client
* Fix a change made in the wrong place
* allow api_version and token_endpoint to use env vars
* Add getting started sample
* add responses deployment name env var
* update azure clients to use defaults for api_version and token_endpoint
* make tests more reliable
---------
Co-authored-by: Chris <66376200+crickman@users.noreply.github.com>