In the previous blog posts we ported a Python implementation of an agentic application to C# and Microsoft Agent Framework. We used interfaces, but we did not use Dependency Injection (DI). It is pretty easy to add.

Agents, tools, executors and workflows all depend on interfaces, and DI depends on registering the relationship between these interfaces and the concrete class that implements them.
For example, here is how you create a workflow
services.AddSingleton<Workflow>(sp =>
{
var blogger = sp.GetRequiredService<BloggerExecutor>();
var researcher = sp.GetRequiredService<ResearcherExecutor>();
var author = sp.GetRequiredService<AuthorExecutor>();
var reviewer = sp.GetRequiredService<ReviewerExecutor>();
return new WorkflowBuilder(blogger)
.AddEdge(blogger, researcher)
.AddEdge(researcher, author)
.AddEdge(author, reviewer)
.AddEdge<ResearchState>(reviewer, author, s => s?.NeedsRevision == true)
.WithOutputFrom(reviewer)
.Build();
});
In our console application we would then register the interfaces, agents, executors, and workflows in .configureServices:
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
var host = Host.CreateDefaultBuilder(args)
.ConfigureServices(services =>
{
// Register your interfaces here
services.AddSingleton<IResearchService, ResearchService>();
services.AddSingleton<IAuthorTools, AuthorTools>();
services.AddSingleton<IReviewerLogic, ReviewerLogic>();
// Register agents
services.AddSingleton<ResearchAgent>();
services.AddSingleton<AuthorAgent>();
services.AddSingleton<BloggerAgent>();
services.AddSingleton<ReviewerAgent>();
// Register executors
services.AddSingleton<ResearcherExecutor>();
services.AddSingleton<AuthorExecutor>();
services.AddSingleton<BloggerExecutor>();
services.AddSingleton<ReviewerExecutor>();
// Register workflow
services.AddSingleton<Workflow>(sp =>
{
var blogger = sp.GetRequiredService<BloggerExecutor>();
var researcher = sp.GetRequiredService<ResearcherExecutor>();
var author = sp.GetRequiredService<AuthorExecutor>();
var reviewer = sp.GetRequiredService<ReviewerExecutor>();
return new WorkflowBuilder(blogger)
.AddEdge(blogger, researcher)
.AddEdge(researcher, author)
.AddEdge(author, reviewer)
.AddEdge<ResearchState>(reviewer, author, s => s?.NeedsRevision == true)
.WithOutputFrom(reviewer)
.Build();
});
})
.Build();
// Resolve your entry point service
var workflow = host.Services.GetRequiredService<Workflow>();
This has all the advantages of DI as used anywhere, principally decoupling objects from their dependencies. This allows for greater flexibility (e.g., swapping out executors, etc.) and especially for testing (where moq objects can be used).
DI will inject all the following relationships:
- Agents depend on services
- Tools depend on services
- Executors depend on agents
- Workflows depend on executors
And your console app resolves the workflow.
In an ASP application you do the same, but in the usual place (startup.cs for ASP.NET Core and in program.cs for Minimal API)





































