Skip to content

refine response format#1368

Merged
iceljc merged 3 commits into
SciSharp:masterfrom
iceljc:features/refine-response-format
Jun 24, 2026
Merged

refine response format#1368
iceljc merged 3 commits into
SciSharp:masterfrom
iceljc:features/refine-response-format

Conversation

@iceljc

@iceljc iceljc commented Jun 24, 2026

Copy link
Copy Markdown
Collaborator

No description provided.

@qodo-code-review

Copy link
Copy Markdown
Contributor

PR Summary by Qodo

Move template response_format into LLM config and update persistence
✨ Enhancement ⚙️ Configuration changes 🕐 20-40 Minutes

Grey Divider

Description

• Relocate response_format from template root to llm_config for consistent schema.
• Update agent/instruct services to build LLM configs from template LLM settings.
• Adjust file and Mongo persistence models to store response_format under LLM config.
Diagram

graph TD
  A["AgentTemplate config JSON"] --> B["AgentTemplateLlmConfig"] --> C["LlmConfigBase"] --> D["AgentLlmConfig"] --> E["InstructService"] --> F["LLM provider"]
  A --> G["Repositories (File/Mongo)"] --> B
  subgraph Legend
    direction LR
    _cfg[["Config/Model"]] ~~~ _svc(["Service"]) ~~~ _ext{{"External"}}
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Backwards-compatible dual-read (template + llm_config)
  • ➕ Avoids breaking existing persisted templates that still have template-level response_format
  • ➕ Enables gradual migration and clearer deprecation path
  • ➖ Adds temporary branching and increases config resolution complexity
  • ➖ Must define precedence rules and eventual removal plan
2. One-time migration for stored templates (File/Mongo)
  • ➕ Keeps runtime code clean (single source of truth)
  • ➕ Eliminates ambiguity and reduces long-term maintenance
  • ➖ Requires migration tooling/steps and operational coordination
  • ➖ Risk of partial migration or rollback complexity

Recommendation: The PR’s direction (single source of truth under llm_config) is cleaner and scales better as LLM settings grow. To reduce rollout risk, consider adding a short-term compatibility layer (read old template-level response_format if llm_config.response_format is missing) or provide an explicit migration step for existing stored templates.

Files changed (11) +31 / -37

Enhancement (2) +12 / -2
LlmConfigBase.csAdd ResponseFormat to LlmConfigBase with JSON serialization +7/-0

Add ResponseFormat to LlmConfigBase with JSON serialization

• Introduces ResponseFormat on the shared LLM config base model with JSON property name response_format. This makes response_format available consistently across config implementations.

src/Infrastructure/BotSharp.Abstraction/Models/LlmConfigBase.cs

AgentTemplateLlmConfigMongoModel.csPersist ResponseFormat within Mongo LLM config model +5/-2

Persist ResponseFormat within Mongo LLM config model

• Adds ResponseFormat to the Mongo LLM config model and includes it in domain↔Mongo conversions. Note: the file now ends without a trailing newline.

src/Plugins/BotSharp.Plugin.MongoStorage/Models/AgentTemplateLlmConfigMongoModel.cs

Refactor (6) +19 / -21
AgentLlmConfig.csConstruct AgentLlmConfig from template LLM config and relocate ResponseFormat +13/-13

Construct AgentLlmConfig from template LLM config and relocate ResponseFormat

• Changes the constructor to accept AgentTemplateLlmConfig and sources provider/model/token/effort/response_format from it. Moves the ResponseFormat property definition higher in the class (no behavioral change beyond source-of-truth).

src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentLlmConfig.cs

AgentService.CreateAgent.csStop copying ResponseFormat from template config into templates +0/-1

Stop copying ResponseFormat from template config into templates

• Removes assignment of template.ResponseFormat during template loading. Templates now rely on their LlmConfig for response_format.

src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.CreateAgent.cs

InstructService.Execute.csBuild runtime LLM config from template LLM config +3/-3

Build runtime LLM config from template LLM config

• Refactors template lookup to use only template.LlmConfig and constructs AgentLlmConfig from AgentTemplateLlmConfig. This aligns execution-time configuration with the new response_format location.

src/Infrastructure/BotSharp.Core/Instructs/Services/InstructService.Execute.cs

InstructService.Instruct.csUse template LLM config when building inner-agent LLM settings +3/-2

Use template LLM config when building inner-agent LLM settings

• Updates inner-agent build logic to pass template.LlmConfig into AgentLlmConfig instead of the full template. Keeps behavior consistent with Execute path and new config ownership.

src/Infrastructure/BotSharp.Core/Instructs/Services/InstructService.Instruct.cs

FileRepository.csRemove ResponseFormat mapping when fetching templates from files +0/-1

Remove ResponseFormat mapping when fetching templates from files

• Eliminates copying config.ResponseFormat into template.ResponseFormat during template fetch. Template LlmConfig becomes the sole source for response_format.

src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.cs

MongoRepository.Agent.csStop patching template-level ResponseFormat in Mongo repository +0/-1

Stop patching template-level ResponseFormat in Mongo repository

• Removes the update of foundTemplate.ResponseFormat during template patch operations. Template updates now only touch Content and LlmConfig (which includes ResponseFormat).

src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Agent.cs

Other (3) +0 / -14
AgentTemplate.csRemove ResponseFormat from AgentTemplateConfig root +0/-7

Remove ResponseFormat from AgentTemplateConfig root

• Deletes the template-level response_format field so templates no longer own format directly. This enforces that response_format is part of llm_config instead.

src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentTemplate.cs

FileRepository.Agent.csRemove ResponseFormat persistence for file-stored templates +0/-4

Remove ResponseFormat persistence for file-stored templates

• Stops writing, reading, and patching ResponseFormat at the template config level in file repository operations. Only LlmConfig is persisted for template LLM settings now.

src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.Agent.cs

AgentTemplateMongoElement.csRemove template-level ResponseFormat field from Mongo template element +0/-3

Remove template-level ResponseFormat field from Mongo template element

• Deletes ResponseFormat from the stored template element and removes mapping in ToMongoElement/ToDomainElement. This matches the new schema where response_format lives under LlmConfig.

src/Plugins/BotSharp.Plugin.MongoStorage/Models/AgentTemplateMongoElement.cs

ⓘ You are approaching your monthly quota for Qodo. Upgrade your plan

@qodo-code-review

Copy link
Copy Markdown
Contributor

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Legacy response_format ignored 🐞 Bug ☼ Reliability
Description
Existing stored templates that still use the old top-level response_format field will deserialize
without that value (field removed), so the runtime AgentLlmConfig.ResponseFormat will not be set
from legacy data. This silently changes LLM request behavior (e.g., OpenAI chat
options.ResponseFormat becomes null) after upgrade.
Code

src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentTemplate.cs[R24-29]

{
    public string Name { get; set; }

-    /// <summary>
-    /// Response format: json, xml, markdown, yaml, etc.
-    /// </summary>
-    [JsonPropertyName("response_format")]
-    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
-    public string? ResponseFormat { get; set; }
-
    [JsonPropertyName("llm_config")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public AgentTemplateLlmConfig? LlmConfig { get; set; }
Evidence
AgentTemplateConfig no longer defines a top-level response_format, while ResponseFormat is now
only present on LlmConfigBase (and thus under llm_config). The file repository deserializes
stored template configs into List<AgentTemplateConfig> and applies only config.LlmConfig, so any
legacy top-level response_format is ignored. Mongo template documents similarly no longer map a
ResponseFormat field on the template element, so legacy docs will drop the value; at runtime,
template LLM settings are applied via new AgentLlmConfig(templateLlmConfig) and OpenAI chat
options read agent.LlmConfig.ResponseFormat, so losing the legacy value changes request behavior.

src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentTemplate.cs[23-33]
src/Infrastructure/BotSharp.Abstraction/Models/LlmConfigBase.cs[3-25]
src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.cs[386-414]
src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.cs[511-522]
src/Plugins/BotSharp.Plugin.MongoStorage/Models/AgentTemplateMongoElement.cs[5-30]
src/Infrastructure/BotSharp.Core/Instructs/Services/InstructService.Execute.cs[244-256]
src/Plugins/BotSharp.Plugin.OpenAI/Providers/Chat/ChatCompletionProvider.Chat.cs[621-644]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`response_format` was removed from `AgentTemplateConfig` (and from Mongo template element), but repositories still load stored template configs/documents that may contain legacy top-level `response_format`. System.Text.Json and Mongo conventions will ignore unknown fields, so existing agents/templates silently lose this setting and runtime LLM calls won’t apply the intended response format.

### Issue Context
- Old schema: `[{ name, response_format, llm_config: {...} }]`
- New schema: `[{ name, llm_config: { ..., response_format } }]`
- Current load paths deserialize into `AgentTemplateConfig` and only apply `LlmConfig`, so legacy `response_format` is dropped.

### Fix Focus Areas
- src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentTemplate.cs[23-33]
- src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.cs[511-522]
- src/Plugins/BotSharp.Plugin.MongoStorage/Models/AgentTemplateMongoElement.cs[5-30]

### Suggested approach
1. **File repository backward-compat**:
  - Re-introduce a deprecated/legacy `ResponseFormat` property on `AgentTemplateConfig` *only for deserialization* (e.g., `[JsonPropertyName("response_format")]` + `[Obsolete]`).
  - In `GetAgentTemplateConfigs`, after deserialization, migrate:
    - If `config.ResponseFormat` is not null/empty and `config.LlmConfig?.ResponseFormat` is null/empty, set `config.LlmConfig ??= new AgentTemplateLlmConfig(); config.LlmConfig.ResponseFormat = config.ResponseFormat;`
    - Optionally set `config.ResponseFormat = null` to avoid re-writing legacy field.
2. **Mongo backward-compat**:
  - Re-introduce a deprecated `ResponseFormat` field on `AgentTemplateMongoElement` to read existing documents.
  - In `ToDomainElement`, if `mongoTemplate.ResponseFormat` is set and `mongoTemplate.LlmConfig?.ResponseFormat` is null, migrate into the domain `LlmConfig.ResponseFormat`.
  - Ensure `ToMongoElement` does **not** populate the legacy field (keep writing only the new nested format).
3. Add a small regression test (or fixture) covering deserialization of old template config JSON / Mongo element with top-level `response_format` and verifying it ends up in `template.LlmConfig.ResponseFormat`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ You are approaching your monthly quota for Qodo. Upgrade your plan

Qodo Logo

Comment on lines 24 to 29
{
public string Name { get; set; }

/// <summary>
/// Response format: json, xml, markdown, yaml, etc.
/// </summary>
[JsonPropertyName("response_format")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? ResponseFormat { get; set; }

[JsonPropertyName("llm_config")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public AgentTemplateLlmConfig? LlmConfig { get; set; }

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.

Action required

1. Legacy response_format ignored 🐞 Bug ☼ Reliability

Existing stored templates that still use the old top-level response_format field will deserialize
without that value (field removed), so the runtime AgentLlmConfig.ResponseFormat will not be set
from legacy data. This silently changes LLM request behavior (e.g., OpenAI chat
options.ResponseFormat becomes null) after upgrade.
Agent Prompt
### Issue description
`response_format` was removed from `AgentTemplateConfig` (and from Mongo template element), but repositories still load stored template configs/documents that may contain legacy top-level `response_format`. System.Text.Json and Mongo conventions will ignore unknown fields, so existing agents/templates silently lose this setting and runtime LLM calls won’t apply the intended response format.

### Issue Context
- Old schema: `[{ name, response_format, llm_config: {...} }]`
- New schema: `[{ name, llm_config: { ..., response_format } }]`
- Current load paths deserialize into `AgentTemplateConfig` and only apply `LlmConfig`, so legacy `response_format` is dropped.

### Fix Focus Areas
- src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentTemplate.cs[23-33]
- src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.cs[511-522]
- src/Plugins/BotSharp.Plugin.MongoStorage/Models/AgentTemplateMongoElement.cs[5-30]

### Suggested approach
1. **File repository backward-compat**:
   - Re-introduce a deprecated/legacy `ResponseFormat` property on `AgentTemplateConfig` *only for deserialization* (e.g., `[JsonPropertyName("response_format")]` + `[Obsolete]`).
   - In `GetAgentTemplateConfigs`, after deserialization, migrate:
     - If `config.ResponseFormat` is not null/empty and `config.LlmConfig?.ResponseFormat` is null/empty, set `config.LlmConfig ??= new AgentTemplateLlmConfig(); config.LlmConfig.ResponseFormat = config.ResponseFormat;`
     - Optionally set `config.ResponseFormat = null` to avoid re-writing legacy field.
2. **Mongo backward-compat**:
   - Re-introduce a deprecated `ResponseFormat` field on `AgentTemplateMongoElement` to read existing documents.
   - In `ToDomainElement`, if `mongoTemplate.ResponseFormat` is set and `mongoTemplate.LlmConfig?.ResponseFormat` is null, migrate into the domain `LlmConfig.ResponseFormat`.
   - Ensure `ToMongoElement` does **not** populate the legacy field (keep writing only the new nested format).
3. Add a small regression test (or fixture) covering deserialization of old template config JSON / Mongo element with top-level `response_format` and verifying it ends up in `template.LlmConfig.ResponseFormat`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@iceljc iceljc merged commit 1d2a00b into SciSharp:master Jun 24, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant