Add local developlment experience using Aspire - #15
Conversation
a587125 to
66dc51b
Compare
There was a problem hiding this comment.
Pull request overview
This PR introduces an Aspire-based local development stack for AWS.AgentCore, centered on a new AWS.AgentCore.Testing package that embeds an in-process Runtime emulator, Memory emulator, and a Blazor chat UI so developers can run agents locally with an F5 workflow.
Changes:
- Added
AWS.AgentCore.Testingpackage: embedded runtime + memory emulators, embedded Blazor Chat UI, and Aspire hosting extensions (AddAgentCoreRuntime,WithStreaming,WithInMemory,WithReference). - Updated
AWS.AgentCoreandChatBotUIto support Aspire/local endpoint overrides via environment variables. - Added sample AppHost + Remote MCP agent sample plus extensive unit/property/integration test coverage for the new testing components.
Reviewed changes
Copilot reviewed 75 out of 78 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| test/AWS.AgentCore.Testing.UnitTests/RuntimeEmulatorServiceTests.cs | Unit tests for runtime emulator request formatting/headers |
| test/AWS.AgentCore.Testing.UnitTests/RuntimeEmulatorServicePropertyTests.cs | Property tests for runtime emulator uniqueness/concurrency |
| test/AWS.AgentCore.Testing.UnitTests/InMemoryEventStoreTests.cs | Unit tests for in-memory memory-event store behavior |
| test/AWS.AgentCore.Testing.UnitTests/InMemoryEventStorePropertyTests.cs | Property tests for store round-trip/ordering/pagination/isolation |
| test/AWS.AgentCore.Testing.UnitTests/GlobalUsings.cs | Global test usings |
| test/AWS.AgentCore.Testing.UnitTests/AWS.AgentCore.Testing.UnitTests.csproj | Unit test project definition |
| test/AWS.AgentCore.Testing.UnitTests/AgentCoreTestingPropertyTests.cs | Property tests for Aspire extension invariants |
| test/AWS.AgentCore.Testing.UnitTests/AgentCoreTestingExtensionsTests.cs | Unit tests for Aspire extension API surface |
| test/AWS.AgentCore.Testing.IntegrationTests/GlobalUsings.cs | Global integration-test usings |
| test/AWS.AgentCore.Testing.IntegrationTests/AWS.AgentCore.Testing.IntegrationTests.csproj | Integration test project definition |
| test/AWS.AgentCore.Testing.IntegrationTests/AspireIntegrationTests.cs | Aspire-hosted end-to-end smoke tests |
| src/AWS.AgentCore/Extensions/AgentCoreBuilderExtensions.cs | Add Aspire-managed port binding + local service endpoint override |
| src/AWS.AgentCore/Constants.cs | Adds env var constants for service endpoint + Aspire managed mode |
| src/AWS.AgentCore.Testing/wwwroot/aws.svg | Dark theme logo asset |
| src/AWS.AgentCore.Testing/wwwroot/aws-light.svg | Light theme logo asset |
| src/AWS.AgentCore.Testing/wwwroot/app.css | Base styling for embedded chat UI |
| src/AWS.AgentCore.Testing/Services/PortAllocator.cs | Utility for local port selection |
| src/AWS.AgentCore.Testing/Services/ChatSessionManager.cs | In-memory chat session state for UI |
| src/AWS.AgentCore.Testing/Services/AspireLoggerProvider.cs | Bridges embedded server logs into Aspire dashboard |
| src/AWS.AgentCore.Testing/Services/AgentCoreService.cs | Chat UI service to invoke runtime (non-streaming + streaming) |
| src/AWS.AgentCore.Testing/RuntimeEmulatorServer.cs | Embedded Kestrel runtime emulator host |
| src/AWS.AgentCore.Testing/Program.cs | Placeholder entry point for Web SDK output type |
| src/AWS.AgentCore.Testing/Models/ChatSession.cs | Chat session model |
| src/AWS.AgentCore.Testing/Models/ChatMessage.cs | Chat message model + role enum |
| src/AWS.AgentCore.Testing/Models/AgentCoreSettings.cs | Chat UI settings/options model |
| src/AWS.AgentCore.Testing/MemoryEmulatorServer.cs | Embedded Kestrel memory emulator host |
| src/AWS.AgentCore.Testing/Emulators/Runtime/RuntimeEmulatorService.cs | Runtime emulator forwarding + session tracking |
| src/AWS.AgentCore.Testing/Emulators/Runtime/Models/StreamThroughResult.cs | Runtime streaming passthrough result model |
| src/AWS.AgentCore.Testing/Emulators/Runtime/Models/SessionState.cs | Runtime session state model |
| src/AWS.AgentCore.Testing/Emulators/Runtime/Models/PromptSubmission.cs | Runtime prompt submission model |
| src/AWS.AgentCore.Testing/Emulators/Runtime/Models/InvocationResult.cs | Runtime invocation result model |
| src/AWS.AgentCore.Testing/Emulators/Memory/Models/StoredEvent.cs | Internal event storage model |
| src/AWS.AgentCore.Testing/Emulators/Memory/Models/PayloadTypeModel.cs | Memory wire-format payload wrapper model |
| src/AWS.AgentCore.Testing/Emulators/Memory/Models/ListEventsApiResponse.cs | Memory ListEvents response model |
| src/AWS.AgentCore.Testing/Emulators/Memory/Models/EventModel.cs | Memory event wire-format model |
| src/AWS.AgentCore.Testing/Emulators/Memory/Models/CreateEventApiResponse.cs | Memory CreateEvent response model |
| src/AWS.AgentCore.Testing/Emulators/Memory/Models/CreateEventApiRequest.cs | Memory CreateEvent request model |
| src/AWS.AgentCore.Testing/Emulators/Memory/Models/ConversationalModel.cs | Memory conversational payload model |
| src/AWS.AgentCore.Testing/Emulators/Memory/Models/ContentModel.cs | Memory content model |
| src/AWS.AgentCore.Testing/Emulators/Memory/InMemoryEventStore.cs | In-memory store implementation for memory emulator |
| src/AWS.AgentCore.Testing/Components/Routes.razor | Blazor router setup |
| src/AWS.AgentCore.Testing/Components/Pages/NotFound.razor | NotFound page |
| src/AWS.AgentCore.Testing/Components/Pages/Home.razor.css | Main chat UI styling |
| src/AWS.AgentCore.Testing/Components/Pages/Error.razor | Error page |
| src/AWS.AgentCore.Testing/Components/Layout/Sidebar.razor.css | Sidebar styling |
| src/AWS.AgentCore.Testing/Components/Layout/Sidebar.razor | Sidebar component |
| src/AWS.AgentCore.Testing/Components/Layout/ReconnectModal.razor.js | Reconnect modal behavior |
| src/AWS.AgentCore.Testing/Components/Layout/ReconnectModal.razor.css | Reconnect modal styling |
| src/AWS.AgentCore.Testing/Components/Layout/ReconnectModal.razor | Reconnect modal markup |
| src/AWS.AgentCore.Testing/Components/Layout/MainLayout.razor.css | Layout styling |
| src/AWS.AgentCore.Testing/Components/Layout/MainLayout.razor | Layout component |
| src/AWS.AgentCore.Testing/Components/CodeEditor.razor.js | Code editor JS (indentation/brackets/scroll sync) |
| src/AWS.AgentCore.Testing/Components/CodeEditor.razor.css | Code editor styling |
| src/AWS.AgentCore.Testing/Components/CodeEditor.razor | Code editor component |
| src/AWS.AgentCore.Testing/Components/App.razor | App host document for embedded Blazor UI |
| src/AWS.AgentCore.Testing/Components/_Imports.razor | Blazor imports for embedded UI |
| src/AWS.AgentCore.Testing/ChatAppServer.cs | Embedded chat UI Kestrel host setup |
| src/AWS.AgentCore.Testing/build/AWS.AgentCore.Testing.targets | MSBuild targets to copy packaged wwwroot assets |
| src/AWS.AgentCore.Testing/AWS.AgentCore.Testing.csproj | Testing package project + packaging/build targets |
| src/AWS.AgentCore.Testing/AgentCoreTestingExtensions.cs | Aspire hosting extensions to wire emulators/UI |
| sampleapps/RemoteMcpAgent/Startup.cs | Sample agent startup wiring |
| sampleapps/RemoteMcpAgent/RemoteMcpAgent.csproj | Sample project definition |
| sampleapps/RemoteMcpAgent/Models/PromptRequest.cs | Sample invocation payload model |
| sampleapps/RemoteMcpAgent/McpToolProvider.cs | Lazy MCP connection + tool discovery |
| sampleapps/RemoteMcpAgent/Dockerfile | Container image build for sample |
| sampleapps/RemoteMcpAgent/Agent.cs | Sample handler invoking agent framework with MCP tools |
| sampleapps/ChatBotUI/Services/AgentCoreService.cs | Refactor to DI-injected BedrockAgentCore client |
| sampleapps/ChatBotUI/Program.cs | Local runtime emulator endpoint override wiring |
| sampleapps/AspireAppHost/Properties/launchSettings.json | AppHost launch profiles |
| sampleapps/AspireAppHost/Program.cs | Sample AppHost wiring multiple agents/emulators |
| sampleapps/AspireAppHost/AspireAppHost.csproj | AppHost project definition |
| AWS.AgentCore.slnx | Adds new projects to solution |
| .kiro/specs/aspire-local-dev/tasks.md | Implementation plan documentation |
| .kiro/specs/aspire-local-dev/requirements.md | Requirements documentation |
| .kiro/specs/aspire-local-dev/design.md | Design documentation |
| .kiro/specs/aspire-local-dev/.config.kiro | Spec metadata |
Comments suppressed due to low confidence (2)
src/AWS.AgentCore.Testing/Emulators/Runtime/RuntimeEmulatorService.cs:87
- InvokeAgentStreamThroughAsync reads and returns response.Content as a Stream but the HttpResponseMessage is never disposed, and callers currently don't dispose the returned stream either. This is likely to leak connections, especially with repeated streaming invocations. Consider returning the HttpResponseMessage (or IDisposable wrapper) and disposing it after the response has been copied to the upstream response body.
src/AWS.AgentCore.Testing/Emulators/Runtime/RuntimeEmulatorService.cs:112 - WaitForAgentReadyAsync allocates an HttpResponseMessage on each GET /ping attempt but never disposes it. Please dispose the response (even when non-success) and consider accepting/passing a CancellationToken so AppHost shutdown or upstream request abort can stop the readiness polling promptly.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
normj
left a comment
There was a problem hiding this comment.
In the Aspire dashboard the https://localhost endpoint is showing up along with the Chat and Agent links. But the localhost link returns a 404. Seems like the localhost endpoint isn't useful and we should figure out how to remove that.
This behavior was only on Windows which is why I didn't notice it. I fixed it for both platforms. |
Issue #, if available:
DOTNET-8675
Description of changes
Adds a complete local development experience for AWS AgentCore agents using .NET Aspire. Developers can press F5/Run and get a fully functional testing stack — agent app,
runtime emulator, memory emulator, and an interactive chat UI — with zero AWS credentials required for the core development loop.
What's included
AWS.AgentCore.TestingNuGet package — A self-contained package that provides:POST /runtimes/{arn}/invocationsendpoint. The AWS SDK talks to this emulator identically tohow it talks to the real AgentCore Runtime service.
AgentCoreMemoryProviderto persist conversation history locally without AWS.support.
AddAgentCoreRuntime<T>(),WithStreaming(),WithInMemory(), andWithReference()for wiring everything together.Key design decisions:
AddAgentCoreRuntime<T>()returnsIResourceBuilder<ProjectResource>, making it fully compatible with Aspire deployment features likePublishAsECSFargateService()fromAspire.Hosting.AWS.WithReference(agent)injectsAGENTCORE_SERVICE_ENDPOINTas an environment variable, allowing consuming web apps to override the AWS SDK'sServiceURLand communicatethrough the runtime emulator using the same SDK code they'd use in production.
Sample apps:
AspireAppHost— Demonstrates registering multiple agents with streaming, memory, andWithReferencefor a standalone ChatBotUI.ChatBotUI— A standalone Blazor web app that readsAGENTCORE_SERVICE_ENDPOINTand overrides the SDK's endpoint. Works identically against the local emulator and the realAWS service.
RemoteMcpAgent— Demonstrates connecting to remote MCP servers and registering their tools with the Microsoft Agent Framework at invocation time.Usage
Note
▎ The Aspire extension methods (AddAgentCoreRuntime, WithStreaming, WithInMemory, WithReference) currently live in the AWS.AgentCore.Testing package. Once AWS.AgentCore.Testing
▎ is published to NuGet, these extensions should be migrated to the Aspire.Hosting.AWS package to align with the standard Aspire integration pattern where hosting extensions
▎ live in the Aspire.Hosting.* namespace.
Test plan
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.