Skip to content

Python: Fix PropertySchema.to_json_schema() not recursing into nested array items / object properties#7200

Merged
giles17 merged 4 commits into
microsoft:mainfrom
exp-ouroborous:fix/property-schema-nested-items
Jul 21, 2026
Merged

Python: Fix PropertySchema.to_json_schema() not recursing into nested array items / object properties#7200
giles17 merged 4 commits into
microsoft:mainfrom
exp-ouroborous:fix/property-schema-nested-items

Conversation

@exp-ouroborous

Copy link
Copy Markdown
Contributor

Motivation and Context

PropertySchema.to_json_schema() renames kindtype (and drops empty enum placeholders) only in its top-level properties loop. Nested schemas — array items, nested object properties (which serialize in the named-list shape) — keep kind and empty enum, producing JSON Schema that OpenAI rejects ("schema must have a 'type' key"). Reproduced on 1.0.0rc2.

Description

Contribution Checklist

  • The code builds clean without any errors or warnings
  • The PR follows the Contribution Guidelines
  • All unit tests pass, and I have added new tests where possible (test_declarative_models.py: 98 passed)
  • Is this a breaking change? No — previously-invalid output becomes valid; schemas without nesting are byte-identical.

Copilot AI review requested due to automatic review settings July 19, 2026 15:28
@giles17 giles17 added documentation Usage: [Issues, PRs], Target: documentation in the code base and learn docs python Usage: [Issues, PRs], Target: Python .NET Usage: [Issues, PRs], Target: .Net labels Jul 19, 2026
@github-actions github-actions Bot changed the title Python: Fix PropertySchema.to_json_schema() not recursing into nested array items / object properties .NET: Python: Fix PropertySchema.to_json_schema() not recursing into nested array items / object properties Jul 19, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This pull request addresses a Python bug in PropertySchema.to_json_schema() where nested schemas (array items, nested object properties) were not normalized (kindtype, empty enum removal), producing JSON Schema that structured-output providers reject. The change set also introduces a sizeable set of new “research” docs and a new .NET learning/sandbox project (dotnet/learn/AgentLearn), plus repo-level editor/gitignore tweaks.

Changes:

  • Python: add recursive schema normalization for nested items / properties, and add regression tests.
  • Add dotnet/learn/AgentLearn sample app + integration tests for learning framework workflows/HITL/OTel.
  • Add research/ documentation and VS Code / gitignore convenience updates.

Reviewed changes

Copilot reviewed 40 out of 41 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
research/README.md Adds a top-level README describing the research/ folder.
research/python/agentic-capabilities.md Adds Python agentic capabilities research document.
research/dotnet/agentic-capabilities.md Adds .NET agentic capabilities research document.
research/agentic-capabilities-overview.md Adds cross-language agentic capabilities overview research document.
python/packages/declarative/tests/test_declarative_models.py Adds regression tests for nested schema normalization.
python/packages/declarative/agent_framework_declarative/_models.py Implements recursive nested schema normalization in to_json_schema().
dotnet/samples/run.bash Adds helper script to run a .NET sample with .env variables loaded.
dotnet/learn/README.md Adds documentation for the new AgentLearn project.
dotnet/learn/Directory.Packages.props Disables central package management within dotnet/learn.
dotnet/learn/Directory.Build.targets Isolates learn projects from parent build targets.
dotnet/learn/Directory.Build.props Isolates learn projects from parent build props.
dotnet/learn/CLAUDE.md Adds project guidance/conventions for dotnet/learn.
dotnet/learn/AgentLearn/tests/integration/StoryGeneratorWorkflowTests.cs Adds HITL workflow integration tests.
dotnet/learn/AgentLearn/tests/integration/MockChatClientHelper.cs Adds shared mock IChatClient helper for integration tests.
dotnet/learn/AgentLearn/tests/integration/JokeWriterWorkflowTests.cs Adds workflow integration tests for single/sequential/concurrent joke flows.
dotnet/learn/AgentLearn/tests/integration/AgentLearn.IntegrationTests.csproj Adds integration test project definition.
dotnet/learn/AgentLearn/TaskKinds/StoryGenerator/StoryGenerator.http Adds REST client requests for StoryGenerator.
dotnet/learn/AgentLearn/TaskKinds/StoryGenerator/StoryGenerator.cs Adds StoryGenerator task kind (models/executors/agent/workflow/handler/DI).
dotnet/learn/AgentLearn/TaskKinds/JokeWriter/JokeWriter.http Adds REST client requests for JokeWriter.
dotnet/learn/AgentLearn/TaskKinds/JokeWriter/JokeWriter.cs Adds JokeWriter task kind (models/executors/agents/workflows/handler/DI).
dotnet/learn/AgentLearn/Services/ITaskHandler.cs Adds task-handler abstraction for dispatching requests by kind.
dotnet/learn/AgentLearn/Services/ChatClientFactory.cs Adds multi-provider IChatClient factory + mock client.
dotnet/learn/AgentLearn/run.sh Adds dev runner that starts Jaeger and runs AgentLearn.
dotnet/learn/AgentLearn/Properties/launchSettings.json Adds local launch profiles for AgentLearn.
dotnet/learn/AgentLearn/Program.cs Wires DI, OpenTelemetry, DevUI, OpenAI-compatible endpoints, and controllers.
dotnet/learn/AgentLearn/Models/TaskResponse.cs Adds /task response DTO.
dotnet/learn/AgentLearn/Models/TaskRequest.cs Adds /task request DTO.
dotnet/learn/AgentLearn/Models/TaskKind.cs Adds task-kind enum for dispatch.
dotnet/learn/AgentLearn/Models/LlmOptions.cs Adds configuration model for LLM provider selection.
dotnet/learn/AgentLearn/Models/AgentMode.cs Adds workflow mode enum.
dotnet/learn/AgentLearn/Extensions/AIAgentBuilderExtensions.cs Adds tool-invocation logging middleware extension.
dotnet/learn/AgentLearn/Controllers/TaskController.cs Adds /task controller that routes to ITaskHandlers.
dotnet/learn/AgentLearn/CLAUDE.md Adds AgentLearn-specific contributor guidance.
dotnet/learn/AgentLearn/appsettings.json Adds default configuration for AgentLearn.
dotnet/learn/AgentLearn/appsettings.Development.json Adds dev configuration (incl. debug logging).
dotnet/learn/AgentLearn/AgentLearn.csproj Adds AgentLearn project definition and package references.
dotnet/learn/AgentLearn.sln Adds solution file for AgentLearn.
dotnet/learn/.gitignore Adds ignore rules for local .env variants.
CLAUDE.md Adds/updates repo-level contributor guidance for Claude.
.vscode/settings.json Sets VS Code dotnet.defaultSolution.
.gitignore Ignores .workspaces/ directory.

Comment thread python/packages/declarative/agent_framework_declarative/_models.py Outdated
Comment thread research/README.md Outdated
Comment thread .vscode/settings.json Outdated
Comment thread dotnet/learn/AgentLearn/AgentLearn.csproj Outdated
… schemas

Nested array 'items' and object 'properties' kept the declarative 'kind'
key and empty 'enum' placeholders, producing JSON Schema OpenAI rejects
('schema must have a type key'). Recursively apply the same conversion the
top-level properties loop performs, including the serialized named-list
properties shape and nested required arrays.

Fixes microsoft#7198

(cherry picked from commit c156ffd)
@exp-ouroborous
exp-ouroborous force-pushed the fix/property-schema-nested-items branch from c156ffd to 53784b0 Compare July 19, 2026 15:32
…ial conversion

Review feedback: the list-shaped properties branch popped name/required from
each element and returned on the first unexpected one, leaving earlier
elements half-converted. Validate the whole list first so an unexpected
shape leaves the node fully untouched.
@exp-ouroborous

Copy link
Copy Markdown
Contributor Author

Note for reviewers: the other review threads (research/, dotnet/learn/, .vscode/settings.json) referenced unrelated files that were accidentally included from a stale fork base — the branch has been rebuilt as a single commit on top of main and those files are no longer part of this PR (now 2 files: _models.py + its tests).

@exp-ouroborous
exp-ouroborous marked this pull request as ready for review July 19, 2026 15:52
@exp-ouroborous

Copy link
Copy Markdown
Contributor Author

@microsoft-github-policy-service agree

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

@exp-ouroborous exp-ouroborous changed the title .NET: Python: Fix PropertySchema.to_json_schema() not recursing into nested array items / object properties Python: Fix PropertySchema.to_json_schema() not recursing into nested array items / object properties Jul 19, 2026
@github-actions

github-actions Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Python Test Coverage

Python Test Coverage Report •
FileStmtsMissCoverMissing
packages/declarative/agent_framework_declarative
   _models.py5102595%28, 31, 64, 69, 231, 236, 549, 615, 623, 627, 650, 676, 700, 728, 838, 900, 1008, 1134, 1136, 1138, 1140, 1142, 1144, 1148, 1150
TOTAL44860510588% 

Python Unit Test Overview

Tests Skipped Failures Errors Time
9141 33 💤 0 ❌ 0 🔥 2m 21s ⏱️

Comment thread python/packages/declarative/agent_framework_declarative/_models.py Outdated
@peibekwe

Copy link
Copy Markdown
Contributor

@exp-ouroborous thank you for authoring this fix. Can you please take a look at the comment and the Pyright type-check error failures.

Comment thread python/packages/declarative/agent_framework_declarative/_models.py Outdated
exp-ouroborous and others added 2 commits July 21, 2026 05:44
…rop unreachable dict branch

ObjectProperty always stores nested properties as a named list, so the
elif-dict branch in _normalize_nested_schemas was unreachable; remove it
and flatten the list conversion behind an early return. Cast the narrowed
items/props values so strict Pyright no longer reports unknown types.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…opertySchema.to_json_schema()

OpenAI strict structured outputs require additionalProperties: false on
every object node, but the chat clients only inject it at the schema
root, so declarative schemas with nested objects (e.g. array items)
failed with a schema-validation 400. Route the top-level properties loop
through _normalize_schema_node so all object nodes get the key, and add
a live OpenAI integration test covering the nested array-of-objects
response_format shape.

Verified live against the Responses API: the previous emission fails
with "In context=('properties', 'issues', 'items'),
'additionalProperties' is required to be supplied and to be false";
the new emission returns valid structured output.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@exp-ouroborous

Copy link
Copy Markdown
Contributor Author

@peibekwe Both addressed: the Pyright errors are fixed and the unreachable dict branch removed in 7e3cdeb, and moonbox3's additionalProperties: false request is done in 74c2fb1 (verified live against the Responses API — details in the thread). Package checks are green again.

@giles17
giles17 enabled auto-merge July 21, 2026 15:34
@giles17
giles17 added this pull request to the merge queue Jul 21, 2026
Merged via the queue into microsoft:main with commit fb38b1d Jul 21, 2026
37 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Usage: [Issues, PRs], Target: documentation in the code base and learn docs .NET Usage: [Issues, PRs], Target: .Net python Usage: [Issues, PRs], Target: Python

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Python: [Bug]: PropertySchema.to_json_schema() doesn't recurse into array items — nested "kind" not renamed to "type", nested empty "enum" kept

6 participants