Files
AgenticCode/openspec/changes/archive/2026-04-04-migrate-to-semantic-kernel/tasks.md
local 471e9ce935 feat: migrate chat backend to Semantic Kernel with tool calling support
Replace manual HTTP proxy in ChatController with Semantic Kernel's
OpenAI chat completion service pointed at CLIProxyAPI. Add extraction
plugin with validation function for structured field extraction from
natural language, enabling an agentic loop with auto-retry and
human-in-the-loop escalation.

- Add Microsoft.SemanticKernel 1.74.0 with OpenAI connector
- Create ExtractedFields schema and ValidationResult models
- Create ExtractionPlugin with [KernelFunction] validation
- Rewrite ChatController to use IChatCompletionService streaming
- Configure FunctionChoiceBehavior.Auto() for tool calling
- Preserve existing SSE contract (client unchanged)
- Update tests to mock SK services, add plugin and integration tests
- Archive multi-turn-conversations and migrate-to-semantic-kernel changes
- Sync specs for agent-extraction, semantic-kernel-integration, chat-streaming

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 23:59:13 +01:00

2.3 KiB

1. Add Semantic Kernel Dependencies

  • 1.1 Add Microsoft.SemanticKernel and Microsoft.SemanticKernel.Connectors.OpenAI NuGet packages to ChatAgent.Api
  • 1.2 Remove the OpenAI SDK package if no longer needed after migration

2. Define Extraction Schema

  • 2.1 Create ExtractedFields class in ChatAgent.Shared/Models/ with the predefined set of key-value fields (placeholder fields until real schema is provided)
  • 2.2 Create ValidationResult class in ChatAgent.Shared/Models/ with IsValid, Errors properties

3. Create Extraction Plugin

  • 3.1 Create ExtractionPlugin class in ChatAgent.Api/Plugins/ with a [KernelFunction] validation method that checks ExtractedFields for required fields and type correctness
  • 3.2 Add inline tutorial comments explaining SK plugin concepts ([KernelFunction], [Description], auto-invocation)

4. Wire Semantic Kernel in Program.cs

  • 4.1 Register OpenAIChatCompletionService in DI using ResponsesApi:BaseUrl and ResponsesApi:Model from config
  • 4.2 Register Kernel with AddKernel() and import ExtractionPlugin
  • 4.3 Add inline tutorial comments explaining kernel setup, connectors, and plugin registration

5. Rewrite ChatController

  • 5.1 Replace IHttpClientFactory and IConfiguration injection with Kernel injection
  • 5.2 Replace manual HTTP proxy logic with IChatCompletionService.GetStreamingChatMessageContentsAsync() using the conversation history from the request
  • 5.3 Configure OpenAIPromptExecutionSettings with FunctionChoiceBehavior.Auto() and autoInvokeMaxCallCount = 3
  • 5.4 Re-emit streaming content as the existing SSE format (data: {"text":"..."}\n\n and data: [DONE]\n\n)
  • 5.5 Add inline tutorial comments explaining streaming chat completion, execution settings, and tool call behavior

6. Update Tests

  • 6.1 Update ChatControllerTests to mock IChatCompletionService instead of upstream HTTP calls
  • 6.2 Add tests for the validation plugin (ExtractionPlugin returns correct pass/fail results)
  • 6.3 Add a test verifying the agent escalates to the user after max retries

7. Verify

  • 7.1 Run dotnet build to confirm no errors
  • 7.2 Run dotnet test to confirm all tests pass
  • 7.3 Manual smoke test: send a chat message and verify streaming still works end-to-end through SK