Skip to content

Python: Fix broken samples for GitHub Copilot, declarative, and Responses API#4915

Open
giles17 wants to merge 2 commits intomicrosoft:mainfrom
giles17:samples-fix
Open

Python: Fix broken samples for GitHub Copilot, declarative, and Responses API#4915
giles17 wants to merge 2 commits intomicrosoft:mainfrom
giles17:samples-fix

Conversation

@giles17
Copy link
Contributor

@giles17 giles17 commented Mar 25, 2026

Description

GitHub Copilot samples

  • github_copilot_basic.py and github_copilot_with_session.py: Added missing on_permission_request handler, now required by the copilot SDK when creating sessions.
  • github_copilot_with_mcp.py: Increased timeout to 120s for the remote Microsoft Learn MCP query which exceeds the default 60s.
  • github_copilot_with_session.py: Softened session isolation claim from doesn't remember to may not remember since the Copilot CLI backend can share context across sessions.

Declarative samples

  • inline_yaml.py: Removed YAML connection block and passed project_endpoint directly via client_kwargs. The declarative loader maps connection endpoints as endpoint, but AzureAIClient expects project_endpoint.

Responses API client

  • _chat_client.py: Added support for raw JSON schemas in _convert_response_format. The declarative loader's outputSchema produces raw schemas which the Responses client previously rejected. The client now auto-wraps them in the expected json_schema envelope with strict: true and additionalProperties: false.

Checklist

…nses API

- Add missing on_permission_request handler to github_copilot_basic and
  github_copilot_with_session samples (required by copilot SDK)
- Increase timeout for remote MCP query in github_copilot_with_mcp sample
- Soften session isolation claim in github_copilot_with_session sample
- Fix inline_yaml sample: pass project_endpoint via client_kwargs instead
  of relying on YAML connection block (AzureAIClient expects
  project_endpoint, not endpoint)
- Handle raw JSON schemas in Responses client _convert_response_format
  so declarative outputSchema works with the Responses API

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings March 25, 2026 21:15
@markwallace-microsoft
Copy link
Member

markwallace-microsoft commented Mar 25, 2026

Python Test Coverage

Python Test Coverage Report •
FileStmtsMissCoverMissing
packages/azure-ai/agent_framework_azure_ai
   _shared.py2642391%112, 193, 251, 253–255, 287, 330, 342–344, 373, 375, 377, 381, 446, 451, 456, 493, 530, 537, 549, 568
packages/openai/agent_framework_openai
   _chat_client.py89413385%346, 348–349, 406–407, 409, 441, 500–503, 507–508, 513–514, 524–525, 532, 547–553, 574, 582, 605, 723, 822, 881, 883, 885, 887, 953, 967, 1047, 1057, 1062, 1105, 1184, 1201, 1214, 1279, 1372, 1377, 1381–1383, 1387–1388, 1454, 1483, 1489, 1499, 1505, 1510, 1516, 1521–1522, 1583, 1605–1606, 1621–1622, 1640–1641, 1682–1685, 1847, 1902, 1904, 1984–1992, 2114, 2169, 2184, 2204–2214, 2227, 2238–2242, 2256, 2270–2281, 2290, 2322–2325, 2333–2334, 2336–2338, 2352–2354, 2364–2365, 2371, 2386
TOTAL27978341287% 

Python Unit Test Overview

Tests Skipped Failures Errors Time
5425 20 💤 0 ❌ 0 🔥 1m 28s ⏱️

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes broken Python samples and improves the OpenAI Responses client’s handling of declarative output schemas after the OpenAI package extraction and Copilot SDK changes.

Changes:

  • Add required on_permission_request handler usage to GitHub Copilot samples and adjust MCP timeout for slower remote calls.
  • Update declarative inline YAML sample to pass project_endpoint via client_kwargs (instead of YAML connection mapping).
  • Extend OpenAIChatClient response_format conversion to accept raw JSON schemas by wrapping them into a json_schema format config.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
python/samples/02-agents/providers/github_copilot/github_copilot_with_session.py Adds permission request handler wiring and clarifies session isolation note.
python/samples/02-agents/providers/github_copilot/github_copilot_with_mcp.py Increases per-call timeout for remote MCP query.
python/samples/02-agents/providers/github_copilot/github_copilot_basic.py Adds permission request handler wiring for session creation.
python/samples/02-agents/declarative/inline_yaml.py Passes project_endpoint via client_kwargs to align with Azure AI client expectations.
python/packages/openai/agent_framework_openai/_chat_client.py Adds raw JSON-schema wrapping support in _convert_response_format.

Copy link
Contributor Author

@giles17 giles17 left a comment

Choose a reason for hiding this comment

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

Automated Code Review

Reviewers: 4 | Confidence: 86%

✓ Correctness

This PR adds handling for raw JSON schemas in _convert_response_format (needed for declarative outputSchema to work with the Responses API), fixes the inline_yaml sample to pass project_endpoint via client_kwargs, and adds on_permission_request handlers to GitHub Copilot samples. The core logic change is correct: raw schemas like {"type": "object", "properties": {...}} are properly detected (after all other format types are checked) and wrapped in the json_schema envelope. The shallow copy avoids mutating the input. The strict: True and additionalProperties: false additions align with OpenAI Structured Outputs requirements. One notable omission: the identical _convert_response_format method in python/packages/core/agent_framework/openai/_responses_client.py (used by RawOpenAIResponsesClient and its subclass RawAzureAIClient) is not updated, meaning the same raw-schema issue would occur when declarative agents use the Azure AI client path.

✓ Security Reliability

This PR adds a convenience wrapper in _convert_response_format to handle raw JSON schemas (dicts with a properties key) by auto-wrapping them in a json_schema envelope, updates GitHub Copilot samples to include permission-request handlers, and adjusts the inline_yaml.py sample to pass the project endpoint via client_kwargs instead of YAML. No blocking security or reliability issues were found. The properties-based heuristic for detecting raw schemas is loose but positioned after all explicit type checks, so misclassification risk is minimal — invalid schemas would be rejected by the downstream API. The sample changes are straightforward additions of interactive permission prompts.

✗ Test Coverage

The PR adds a new code path in _convert_response_format to handle raw JSON schemas (dicts with a properties key) by wrapping them into the json_schema envelope. This is non-trivial logic with multiple branches (title extraction, additionalProperties defaulting, strict mode), but the PR includes zero unit tests for the new behavior. The remaining changes are sample code updates (permission handlers, endpoint config, timeout increase) which don't require unit tests. The Responses client's equivalent _convert_response_format method has thorough test coverage (title fallback, strict mode, missing schema, unsupported types), and the same level of coverage should be provided here.

✗ Design Approach

The main design concern is in _convert_response_format: the heuristic of checking for a top-level "properties" key to detect raw JSON schemas is unreliable. It fails silently for schemas without "properties" (e.g., {"type": "object"}, {"anyOf": [...]}, {"$defs": {...}), and could falsely match other dict shapes that happen to include "properties". The remaining changes — moving on_permission_request into default_options, adding a per-call timeout for MCP, and shifting project_endpoint out of YAML into client_kwargs — are straightforward and well-structured. The duplication of prompt_permission across two sample files is a minor concern.

Flagged Issues

  • The new raw JSON schema handling in _convert_response_format (lines 630–641 of _chat_client.py) has no unit tests. This code has at least 5 distinct behaviors: (1) wrapping a raw schema into a json_schema envelope, (2) adding additionalProperties: false for type: object schemas, (3) preserving existing additionalProperties, (4) extracting title as the schema name, and (5) defaulting name to "response". Comparable tests exist for the Responses client's version (see test_openai_responses_client.py lines 1428–1562) and should be mirrored here.
  • The "properties" in response_format heuristic is both over-inclusive and under-inclusive as a raw-schema detector. It mises valid schemas lacking a top-level properties key (e.g., {"type": "object"}, {"anyOf": [...]}, {"$ref": ".."}) and could incorrectly match non-schema dicts. A more robust approach is to key on format_type being a JSON Schema primitive type ("object", "array", "string", etc.) or to check for known schema keywords (anyOf, oneOf, allOf, $ref, $defs, properties).

Suggestions

  • The identical _convert_response_format method in python/packages/core/agent_framework/openai/_responses_client.py (line 408) is not updated. RawAzureAIClient extends RawOpenAIResponsesClient, so declarative agents using AzureAIClient with outputSchema would still hit the Unsupported response_format exception. Apply the same fix there for consistency.
  • The prompt_permission function is duplicated verbatim in github_copilot_basic.py and github_copilot_with_session.py. Consider extracting it into a shared sample helper (e.g., github_copilot/_shared.py) to keep the samples DRY and prevent drift.
  • The strict field is unconditionally hardcoded to True in the new raw-schema branch, unlike the existing json_schema branch which conditionally includes it from the input. Consider allowing calers to opt out of strict mode via a strict key in the raw schema dict.
  • Add a parametrized test covering the key branches: raw schema with title, without title, with existing additionalProperties, with type != object (verifying additionalProperties is not injected), and confirming strict: True is always set.
  • The schema.pop("title", None) call silently strips title from the schema forwarded to the API. While necessary for strict mode, a brief comment explaining the removal would make the intent clearer to future readers.

Automated review by giles17's agents

- Broaden raw schema detection to handle anyOf, oneOf, allOf, $ref, $defs
  keywords and JSON Schema primitive types, not just 'properties'
- Apply same raw schema handling to azure-ai _shared.py for consistency
- Add unit tests for both openai and azure-ai response_format conversion

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy link
Contributor Author

@giles17 giles17 left a comment

Choose a reason for hiding this comment

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

Automated Code Review

Reviewers: 4 | Confidence: 86%

✓ Correctness

This PR adds handling for raw JSON schemas in _convert_response_format (needed for declarative outputSchema to work with the Responses API), fixes the inline_yaml sample to pass project_endpoint via client_kwargs, and adds on_permission_request handlers to GitHub Copilot samples. The core logic change is correct: raw schemas like {"type": "object", "properties": {...}} are properly detected (after all other format types are checked) and wrapped in the json_schema envelope. The shallow copy avoids mutating the input. The strict: True and additionalProperties: false additions align with OpenAI Structured Outputs requirements. One notable omission: the identical _convert_response_format method in python/packages/core/agent_framework/openai/_responses_client.py (used by RawOpenAIResponsesClient and its subclass RawAzureAIClient) is not updated, meaning the same raw-schema issue would occur when declarative agents use the Azure AI client path.

✓ Security Reliability

This PR adds a convenience wrapper in _convert_response_format to handle raw JSON schemas (dicts with a properties key) by auto-wrapping them in a json_schema envelope, updates GitHub Copilot samples to include permission-request handlers, and adjusts the inline_yaml.py sample to pass the project endpoint via client_kwargs instead of YAML. No blocking security or reliability issues were found. The properties-based heuristic for detecting raw schemas is loose but positioned after all explicit type checks, so misclassification risk is minimal — invalid schemas would be rejected by the downstream API. The sample changes are straightforward additions of interactive permission prompts.

✗ Test Coverage

The PR adds a new code path in _convert_response_format to handle raw JSON schemas (dicts with a properties key) by wrapping them into the json_schema envelope. This is non-trivial logic with multiple branches (title extraction, additionalProperties defaulting, strict mode), but the PR includes zero unit tests for the new behavior. The remaining changes are sample code updates (permission handlers, endpoint config, timeout increase) which don't require unit tests. The Responses client's equivalent _convert_response_format method has thorough test coverage (title fallback, strict mode, missing schema, unsupported types), and the same level of coverage should be provided here.

✗ Design Approach

The main design concern is in _convert_response_format: the heuristic of checking for a top-level "properties" key to detect raw JSON schemas is unreliable. It fails silently for schemas without "properties" (e.g., {"type": "object"}, {"anyOf": [...]}, {"$defs": {...}), and could falsely match other dict shapes that happen to include "properties". The remaining changes — moving on_permission_request into default_options, adding a per-call timeout for MCP, and shifting project_endpoint out of YAML into client_kwargs — are straightforward and well-structured. The duplication of prompt_permission across two sample files is a minor concern.

Flagged Issues

  • The new raw JSON schema handling in _convert_response_format (lines 630–641 of _chat_client.py) has no unit tests. This code has at least 5 distinct behaviors: (1) wrapping a raw schema into a json_schema envelope, (2) adding additionalProperties: false for type: object schemas, (3) preserving existing additionalProperties, (4) extracting title as the schema name, and (5) defaulting name to "response". Comparable tests exist for the Responses client's version (see test_openai_responses_client.py lines 1428–1562) and should be mirrored here.
  • The "properties" in response_format heuristic is both over-inclusive and under-inclusive as a raw-schema detector. It mises valid schemas lacking a top-level properties key (e.g., {"type": "object"}, {"anyOf": [...]}, {"$ref": ".."}) and could incorrectly match non-schema dicts. A more robust approach is to key on format_type being a JSON Schema primitive type ("object", "array", "string", etc.) or to check for known schema keywords (anyOf, oneOf, allOf, $ref, $defs, properties).

Suggestions

  • The identical _convert_response_format method in python/packages/core/agent_framework/openai/_responses_client.py (line 408) is not updated. RawAzureAIClient extends RawOpenAIResponsesClient, so declarative agents using AzureAIClient with outputSchema would still hit the Unsupported response_format exception. Apply the same fix there for consistency.
  • The prompt_permission function is duplicated verbatim in github_copilot_basic.py and github_copilot_with_session.py. Consider extracting it into a shared sample helper (e.g., github_copilot/_shared.py) to keep the samples DRY and prevent drift.
  • The strict field is unconditionally hardcoded to True in the new raw-schema branch, unlike the existing json_schema branch which conditionally includes it from the input. Consider allowing calers to opt out of strict mode via a strict key in the raw schema dict.
  • Add a parametrized test covering the key branches: raw schema with title, without title, with existing additionalProperties, with type != object (verifying additionalProperties is not injected), and confirming strict: True is always set.
  • The schema.pop("title", None) call silently strips title from the schema forwarded to the API. While necessary for strict mode, a brief comment explaining the removal would make the intent clearer to future readers.

Automated review by giles17's agents

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants