Dependency Injection & Agent Framework

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)

Unknown's avatar

About Jesse Liberty

** Note ** Jesse is currently looking for a new position. You can learn more about him at https://jesseliberty.bio Thank you. Jesse Liberty has three decades of experience writing and delivering software projects and is the author of 2 dozen books and a couple dozen online courses. His latest book, Building APIs with .NET, is now available wherever you buy your books. Liberty was a Team Lead and Senior Software Engineer for various corporations, a Senior Technical Evangelist for Microsoft, a Distinguished Software Engineer for AT&T, a VP for Information Services for Citibank and a Software Architect for PBS. He is a 13 year Microsoft MVP.
This entry was posted in AI, C#, Essentials, Programming. Bookmark the permalink.