A compact starter that shows how to:
- Define Semantic Kernel agents with embedded prompts and tool plugins (KernelFunctions).
- Orchestrate typed workflows that chain functions/tools and LLM calls.
- Expose clean entrypoints via dedicated services (agent vs workflow).
Program.cs: .NET host composition + logging, registers SK (AddSk), agents/services (AddAgents), then separately invokes an agent service (IIncidentTriageAgentService) and a workflow service (IWorkflowSampleService).Infrastructure/Sk/SkConfiguration.cs: builds theKernel, configures OpenAI chat completion, registers plugins:IncidentTriageToolsfor the triage agent.WorkflowToolsfor the workflow (includes delegation to the SummarizationAgent).
Framework/Agents:AgentBase<TVariables>: handles LLM call, buildsChatHistory, injects system prompt from embedded resource, enables FunctionCalling for authorized KernelFunctions, maps typed inputTVariablesintoKernelArguments.IAgent<TVariables>: onlyAskAsync(AgentRequest<TVariables>).AgentRequest<TVariables>/AgentResponse: typed request/response contract.
Framework/Prompting:PromptBuilderreads embedded YAML, deserializes toPrompt, renders via Handlebars +KernelArguments.EmbeddedResourceManagerreads embedded resources.Framework/Workflow: mini DSL (WorkflowBuilder) +WorkflowRunner+KernelFunctionStep.WorkflowContext.Statepasses values between steps.- Sample agents:
IncidentTriageAgent(promptIncidentTriagePrompt.yaml, toolsIncidentTriageTools.cs, typed inputIncidentTriageInput).SummarizationAgent(promptSummarizationPrompt.yaml, typed inputSummarizationInput).
- Sample services:
IncidentTriageAgentService: entrypoint for the triage agent (AgentRequest<IncidentTriageInput>→ response).WorkflowSampleService: executes a typed workflowIncidentTriageWorkflow(defined inSamples/Workflow/IncidentTriageWorkflow.cs).
- Prereqs
- .NET 10 SDK.
- OpenAI key: replace
open_api_keyinInfrastructure/Sk/SkConfiguration.cs(ideally via config/secret).
- Restore & run
dotnet restore
dotnet run --project PocSKConsole/PocSKConsole.csproj- Create an input record, e.g.,
IncidentTriageInput. - Agent inherits
AgentBase<TVariables>withTVariables= input record. - Call:
AskAsync(new AgentRequest<TVariables>("user message", variables), ct);
- YAML under
Samples/MyAgents/<AgentName>/Prompts/<PromptName>.yaml. - Declared as EmbeddedResource in the csproj.
- Prompt can reference input properties via Handlebars (e.g.,
{{Incident}}).
- Class under
Samples/MyAgents/<AgentName>/Tools/.... - Each method annotated
[KernelFunction("name")]. - Registered in SK (
SkConfiguration) viapluginCollection.AddFromType<YourTools>(pluginName: nameof(YourTools)). - Agent whitelists functions via
AuthorizedKernelFunctions => GetKernelFunctionsForPlugin<YourTools>().
- File e.g.,
IncidentTriageAgent.cs:PromptFileName→ YAML filename (without extension).AuthorizedKernelFunctions→ allowed tools.- Inherits
AgentBase<IncidentTriageInput>.
- Create a dedicated service, e.g.,
IncidentTriageAgentService, that takes the agent via DI and exposes a clear method (CallIncidentTriageAgent). - This service is the “external” entrypoint (API/CLI/worker).
- Defined in its own class under
Samples/Workflow/. - Builds a
WorkflowDefinitionviaWorkflowBuilder:ThenCallFunctionto invoke aKernelFunction(local or LLM-backed).- Can store results in
WorkflowContext.State.
WorkflowRunnerexecutes sequentially and returnsWorkflowResult.
WorkflowToolsexposes operational KernelFunctions (fetch/classify/assign) and delegates toSummarizationAgentfor LLM summarization.- Registered in SK (
SkConfiguration).
WorkflowSampleServicetakes the typed workflow +WorkflowRunnerand exposesRunStaticWorkflow.- This is the “external” entrypoint to orchestrate the workflow.
- Create folder
Samples/MyAgents/<NewAgent>/. - Create input record
Models/<NewInput>.cs. - Create prompt YAML in
Prompts/<PromptName>.yaml; add as EmbeddedResource in csproj. - Create tools in
Tools/<NewTools>.cswith[KernelFunction]. - Create the agent
NewAgent.csinheritingAgentBase<NewInput>, setPromptFileName, whitelist tools. - Register in DI (
Samples/DI.cs) and in SK (SkConfiguration.csviaAddFromType<NewTools>). - Create a dedicated service to expose the agent (
<NewAgent>Service) if needed.
- Create a class
Samples/Workflow/<NewWorkflow>.csthat builds theWorkflowDefinitionviaWorkflowBuilder. - Add required tools (KernelFunctions) and register them in
SkConfiguration. - Create a service entrypoint (
<NewWorkflow>Service) that takes the typed workflow andWorkflowRunner. - Register the workflow and service in DI (
Samples/DI.cs).
- Secrets: don’t hardcode the OpenAI key; use config/Secret Manager.
- Prompts: always embed agent prompts and declare them in the csproj.
- Typing: use
AgentRequest<TVariables>to force required inputs; the agent turns that intoKernelArgumentsand system prompt automatically. - Tools: keep tools per agent/workflow separated and registered as distinct plugins.
- Services: keep agent and workflow entrypoints separated to keep responsibilities clear.
- Agent:
IncidentTriageAgentServicecalls the triage agent with anIncidentTriageInputand gets a triage summary (LLM + allowed tools). - Workflow:
WorkflowSampleServicerunsIncidentTriageWorkflow:fetch_incident(mock) →classify_incident(mock) →summarize_incident(LLM via SummarizationAgent) →assign_incident(mock), chaining state through steps.