microsoft / microsoft/kiota

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

Open
#6,944 0 comments 1 reaction 1 assignee Assigned to @Copilot View on GitHub
type:bug
Dominant language
C#
Stars
3.8k
Forks
333
Avg merge
16h 29m
Merged PRs (30d)
116

Description

### 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:

```json
"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
```

```

### Other information

_No response_

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.