Skip to content

.Net: [Python] KernelJsonSchemaBuilder maps None to JSON "object" in multi-member unions #14482

Description

Description

KernelJsonSchemaBuilder maps NoneType to JSON type "object" in multi-member unions. A type like int | str | None becomes anyOf: [integer, string, object] instead of including "null".

This breaks function-calling / agent tool schemas for pydantic model parameters: models may emit {} where null/omit was intended.

Distinct from open #14443 (Ge constraint objects in descriptions).

Environment

  • semantic-kernel==1.44.1 (Python)
  • Python 3.13

Minimal repro

import json
from typing import Annotated
from pydantic import BaseModel, Field
from semantic_kernel.connectors.ai.function_calling_utils import (
    kernel_function_metadata_to_function_call_format,
)
from semantic_kernel.functions import KernelPlugin, kernel_function
from semantic_kernel.schema.kernel_json_schema_builder import KernelJsonSchemaBuilder

direct = KernelJsonSchemaBuilder.build(int | str | None)
print(json.dumps(direct))
# {"anyOf": [{"type": "integer"}, {"type": "string"}, {"type": "object"}]}
# null missing; object stand-in for None

class Payload(BaseModel):
    value: int | str | None = Field(default=None, description="flexible")

@kernel_function(name="handle")
def handle(payload: Annotated[Payload, "payload"]) -> str:
    """handle payload"""
    return str(payload)

fn = KernelPlugin(name="P", functions=[handle])["handle"]
fmt = kernel_function_metadata_to_function_call_format(fn.metadata)
print(json.dumps(fmt["function"]["parameters"]["properties"]["payload"]["properties"]["value"]))
# anyOf includes type object for None

Expected

None in unions should map to JSON Schema "null" (or an equivalent nullable form), not "object".

Actual

anyOf includes {"type": "object"} and no "null".

Root cause (pointer)

semantic_kernel/schema/kernel_json_schema_builder.py — TYPE_MAPPING / get_json_schema default "object"; handle_complex_type Union branch only special-cases 2-arg Optional, not multi-member unions containing None.

Suggested fix direction

Map type(None) → {"type": "null"} in TYPE_MAPPING/get_json_schema, and/or strip None from multi-unions into a proper nullable / anyOf+null form.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    .NETIssue or Pull requests regarding .NET codepythonPull requests for the Python Semantic Kerneltriage

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions