Skip to content

Kiota generates empty objects in the plugin manifests instead of simply omitting them. #6944

@sebastienlevert

Description

@sebastienlevert

What are you generating using Kiota, clients or plugins?

Kiota plugin

In what context or format are you using Kiota?

Nuget tool

Client library/SDK language

None

Describe the bug

When using the API plugin generator, when serializing the plugins, empty objects are rendered are {} instead of being omitted. We should check for the content and if null or empty, not emit the objects.

For example:

"functions": [
    {
      "name": "getAgents",
      "description": "List all available agents for the current context.",
      "capabilities": {}
    },
    {
      "name": "getFeedback",
      "description": "Retrieve feedback entries for a specific agent. Optionally limit to last N days.\nDSAT rate is derived from the filtered subset.",
      "capabilities": {}
    },
    {
      "name": "getUsage",
      "description": "Retrieve usage metrics for a specific agent/application identifier. If the ID is unavailable,\nuse the listAgents operation to enumerate valid IDs.",
      "capabilities": {}
    }
  ],

This should be the case for all objects created by Kiota.

Expected behavior

Should be rendered as:

"functions": [
{
"name": "getAgents",
"description": "List all available agents for the current context."
},
{
"name": "getFeedback",
"description": "Retrieve feedback entries for a specific agent. Optionally limit to last N days.\nDSAT rate is derived from the filtered subset."
},
{
"name": "getUsage",
"description": "Retrieve usage metrics for a specific agent/application identifier. If the ID is unavailable,\nuse the listAgents operation to enumerate valid IDs."
}
],

How to reproduce

Use ATK and use the following OpenAPI file

{
  "openapi": "3.0.0",
  "info": {
    "title": "Usage Insights",
    "x-ai-description": "Provides a list of agents with identifiers, version, and status for disambiguation in analytics queries.",
    "x-description-for-human": "List available Microsoft 365 Copilot agents and their basic metadata.",
    "version": "0.0.0"
  },
  "tags": [],
  "paths": {
    "/agents": {
      "get": {
        "operationId": "getAgents",
        "description": "List all available agents for the current context.",
        "parameters": [],
        "responses": {
          "200": {
            "description": "The request has succeeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Models.AgentsListResponse"
                }
              }
            }
          }
        },
        "x-ai-capabilities": {}
      }
    },
    "/feedback/{id}": {
      "get": {
        "operationId": "getFeedback",
        "description": "Retrieve feedback entries for a specific agent. Optionally limit to last N days.\nDSAT rate is derived from the filtered subset.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Agent identifier (GUID or composite appId prefix accepted by server)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "days",
            "in": "query",
            "required": false,
            "description": "Optional number of days to include from now (positive integer)",
            "schema": {
              "type": "integer",
              "format": "int32"
            },
            "explode": false
          }
        ],
        "responses": {
          "200": {
            "description": "The request has succeeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Models.FeedbackSummaryResponse"
                }
              }
            }
          }
        },
        "x-ai-capabilities": {}
      }
    },
    "/usage/{id}": {
      "get": {
        "operationId": "getUsage",
        "description": "Retrieve usage metrics for a specific agent/application identifier. If the ID is unavailable,\nuse the listAgents operation to enumerate valid IDs.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The unique application identifier (appId) for the agent. It should **ABSOLUTELY** be a GUID.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "grain",
            "in": "query",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/Models.UsageGrain",
              "default": "weekly"
            },
            "explode": false
          },
          {
            "name": "limitDays",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 720
            },
            "explode": false
          },
          {
            "name": "periods",
            "in": "query",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/Models.UsagePeriod",
              "default": "RL30"
            },
            "explode": false
          }
        ],
        "responses": {
          "200": {
            "description": "The request has succeeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Models.UsageDataResponse"
                }
              }
            }
          }
        },
        "x-ai-capabilities": {}
      }
    }
  },
  "components": {
    "schemas": {
      "Models.AgentProperties": {
        "type": "object",
        "required": [
          "name",
          "status"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "version": {
            "type": "string"
          },
          "status": {
            "type": "string"
          }
        },
        "description": "Agent properties nested object."
      },
      "Models.AgentRecord": {
        "type": "object",
        "required": [
          "id",
          "appId",
          "properties"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "appId": {
            "type": "string"
          },
          "createdDate": {
            "type": "string"
          },
          "lastModifiedDate": {
            "type": "string"
          },
          "properties": {
            "$ref": "#/components/schemas/Models.AgentProperties"
          }
        },
        "description": "A single agent record surfaced for disambiguation and listing."
      },
      "Models.AgentsListResponse": {
        "type": "object",
        "required": [
          "agents"
        ],
        "properties": {
          "agents": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Models.AgentRecord"
            }
          }
        },
        "description": "Response wrapper mirroring mocks/agents.json shape."
      },
      "Models.FeedbackEmotion": {
        "type": "string",
        "enum": [
          "Positive",
          "Neutral",
          "Negative"
        ],
        "description": "Enumerated sentiment of a feedback item"
      },
      "Models.FeedbackItem": {
        "type": "object",
        "required": [
          "id",
          "timestamp",
          "positive",
          "prompt",
          "response"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "timestamp": {
            "type": "string"
          },
          "positive": {
            "type": "boolean"
          },
          "emotion": {
            "$ref": "#/components/schemas/Models.FeedbackEmotion"
          },
          "hasUserConsent": {
            "type": "boolean"
          },
          "prompt": {
            "type": "string"
          },
          "response": {
            "type": "string"
          },
          "verbatim": {
            "type": "string"
          },
          "comment": {
            "type": "string"
          }
        },
        "description": "Simplified normalized feedback item returned by API.\nDerived from rich RawFeedbackEnvelope records."
      },
      "Models.FeedbackSummaryResponse": {
        "type": "object",
        "required": [
          "agentId",
          "total",
          "negatives",
          "dsatRate",
          "feedback"
        ],
        "properties": {
          "agentId": {
            "type": "string"
          },
          "total": {
            "type": "integer",
            "format": "int32"
          },
          "negatives": {
            "type": "integer",
            "format": "int32"
          },
          "dsatRate": {
            "type": "number",
            "format": "double"
          },
          "days": {
            "type": "integer",
            "format": "int32"
          },
          "feedback": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Models.FeedbackItem"
            }
          }
        },
        "description": "Summary response for feedback listing including DSAT"
      },
      "Models.LatestUsageSummary": {
        "type": "object",
        "required": [
          "usage"
        ],
        "properties": {
          "usage": {
            "type": "integer",
            "format": "int32"
          },
          "moMString": {
            "type": "string"
          },
          "moMPercent": {
            "type": "number",
            "format": "float"
          }
        }
      },
      "Models.MetricSeries": {
        "type": "object",
        "required": [
          "metric",
          "period",
          "data",
          "latestUsage"
        ],
        "properties": {
          "metric": {
            "type": "string"
          },
          "metricTranslationKey": {
            "type": "string"
          },
          "period": {
            "type": "string"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Models.UsagePoint"
            }
          },
          "latestUsage": {
            "$ref": "#/components/schemas/Models.LatestUsageSummary"
          },
          "moMGrowth": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Models.MoMGrowthPoint"
            }
          }
        }
      },
      "Models.MoMGrowthPoint": {
        "type": "object",
        "required": [
          "date"
        ],
        "properties": {
          "date": {
            "type": "string"
          },
          "moMString": {
            "type": "string"
          },
          "moMPercent": {
            "type": "number",
            "format": "float"
          }
        }
      },
      "Models.UsageDataResponse": {
        "type": "object",
        "required": [
          "latestUsageDate",
          "appId",
          "name",
          "failures",
          "successes"
        ],
        "properties": {
          "latestUsageDate": {
            "type": "string"
          },
          "appId": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "failures": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "successes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Models.UsageGroup"
            }
          }
        }
      },
      "Models.UsageGrain": {
        "type": "string",
        "enum": [
          "daily",
          "weekly",
          "monthly"
        ],
        "description": "Supported aggregation grains"
      },
      "Models.UsageGroup": {
        "type": "object",
        "required": [
          "groupName",
          "metrics"
        ],
        "properties": {
          "groupName": {
            "type": "string"
          },
          "metrics": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Models.MetricSeries"
            }
          }
        }
      },
      "Models.UsagePeriod": {
        "type": "string",
        "enum": [
          "RL1",
          "RL7",
          "RL28",
          "RL30"
        ],
        "description": "Supported range shortcuts mapping to days (RL1=1, RL7=7, RL28=28, RL30=30)."
      },
      "Models.UsagePoint": {
        "type": "object",
        "required": [
          "date",
          "usage"
        ],
        "properties": {
          "date": {
            "type": "string"
          },
          "usage": {
            "type": "integer",
            "format": "int32"
          }
        }
      }
    }
  },
  "servers": [
    {
      "url": "https://fc1gzm0d-3000.usw2.devtunnels.ms",
      "variables": {}
    }
  ]
}

Open API description file

No response

Kiota Version

1.28

Latest Kiota version known to work for scenario above?(Not required)

No response

Known Workarounds

No response

Configuration

No response

Debug output

Click to expand log ```
</details>


### Other information

_No response_

Metadata

Metadata

Assignees

Labels

type:bugA broken experience

Type

No type

Projects

Status

Needs Triage 🔍

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions