Repository navigation
Add agent resource support - #17757
Tommaso Stocchi (tommasodotNET) wants to merge 39 commits into
Conversation
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 17757Or
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 17757" |
There was a problem hiding this comment.
Pull request overview
Adds generic agent-resource support to Aspire Hosting so endpoint-backed compute resources can be marked as A2A/OpenAI Responses agents, surfaced in the dashboard, and referenced by consumers via agent-card environment variables.
Changes:
- Adds
Aspire.Hosting.Agentspublic APIs for agent protocols, invocation mode, annotations, andAsAgent(...)extensions. - Extends
WithReference(...)to inject A2A agent-card URLs into consumers. - Adds tests, code-generation coverage, and a new
playground/AspireAgentssample.
Reviewed changes
Copilot reviewed 21 out of 22 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
src/Aspire.Hosting/Agents/AgentResourceBuilderExtensions.cs |
Adds agent configuration, dashboard commands, URLs, and request preparation helpers. |
src/Aspire.Hosting/Agents/AgentResourceAnnotation.cs |
Adds metadata annotation for agent protocols and paths. |
src/Aspire.Hosting/Agents/AgentProtocol.cs |
Adds supported agent protocol enum. |
src/Aspire.Hosting/Agents/A2AInvocationMode.cs |
Adds A2A dashboard invocation mode enum. |
src/Aspire.Hosting/ResourceBuilderExtensions.cs |
Adds A2A agent-card env-var injection during references. |
src/Aspire.Hosting/api/Aspire.Hosting.cs |
Updates public API surface for new agent APIs. |
tests/Aspire.Hosting.Tests/AgentResourceBuilderExtensionsTests.cs |
Adds hosting tests for annotations, commands, and reference injection. |
tests/Aspire.Hosting.CodeGeneration.TypeScript.Tests/AtsTypeScriptCodeGeneratorTests.cs |
Adds ATS capability and enum coverage for TypeScript. |
tests/Aspire.Hosting.CodeGeneration.Python.Tests/AtsPythonCodeGeneratorTests.cs |
Adds ATS capability coverage for Python. |
tests/Aspire.Hosting.CodeGeneration.Java.Tests/AtsJavaCodeGeneratorTests.cs |
Adds ATS capability coverage for Java. |
tests/Aspire.Hosting.CodeGeneration.Go.Tests/AtsGoCodeGeneratorTests.cs |
Adds ATS capability coverage for Go. |
playground/AspireAgents/AspireAgents.AppHost/AppHost.cs |
Adds sample AppHost wiring for A2A and Responses agents. |
playground/AspireAgents/AspireAgents.AppHost/AspireAgents.AppHost.csproj |
Adds sample AppHost project configuration. |
playground/AspireAgents/AspireAgents.AppHost/Properties/launchSettings.json |
Pins local dashboard/resource-service endpoints for the sample. |
playground/AspireAgents/ResponsesAgent/ResponsesAgent.csproj |
Adds Responses agent project dependencies. |
playground/AspireAgents/ResponsesAgent/Program.cs |
Implements sample OpenAI Responses weather agent. |
playground/AspireAgents/weather-agent-python/weather_agent_python/main.py |
Implements sample Python A2A weather agent. |
playground/AspireAgents/weather-agent-python/weather_agent_python/__init__.py |
Adds Python package marker/docstring. |
playground/AspireAgents/weather-agent-python/pyproject.toml |
Adds Python sample package metadata and dependencies. |
playground/AspireAgents/weather-agent-python/.python-version |
Pins Python version for the sample. |
playground/AspireAgents/aspire.config.json |
Points Aspire CLI/config tooling at the sample AppHost. |
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Definitely don’t want this in Aspire.Hosting. Also this needs to be proven across more than just MAF since it’s a general abstraction. Make this PR a draft until we do more research |
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt. |
Validate custom agent paths and A2A stream completion, terminate MCP sessions across invocation outcomes, and dispose invalid protocol responses. Update the Azure connector reflection caller and enable integration analyzers. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved protocol-response validation and cancellation-race defects can report failures as successes or complete cancelled work.
Get a fresh assessment by requesting another Copilot review.
Review details
Files not reviewed (1)
- playground/AspireAgents/vercel-ai-responses-agent/package-lock.json: Generated file
- Files reviewed: 55/59 changed files
- Comments generated: 4
- Review effort level: Balanced
|
Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt. |
Reject malformed A2A and MCP responses, handle A2A media types case-insensitively, and stop Python task execution before publishing cancellation. Add focused protocol and cancellation regression coverage. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🔵 Needs a closer look
Agent configuration currently mishandles case-insensitive endpoint schemes and undefined enum values.
Review details
Files not reviewed (1)
- playground/AspireAgents/vercel-ai-responses-agent/package-lock.json: Generated file
Suppressed comments (2)
Previously missed (2) — in code that hasn't changed since the last review.
src/Aspire.Hosting.Agents/AgentResourceBuilderExtensions.cs:195
- Undefined enum values are accepted silently. An unknown
AgentProtocoladds metadata and an icon but configures no protocol, while an unknownA2AInvocationModeis treated as non-streaming. Validate both enum arguments so invalid configuration fails at the public API boundary instead of producing a partially configured resource.
src/Aspire.Hosting.Agents/AgentResourceBuilderExtensions.cs:276 - URI schemes are case-insensitive, but this filter rejects otherwise valid endpoints whose scheme is
HTTPorHTTPS. The following ordering already compares schemes case-insensitively, so endpoint eligibility should do the same; otherwiseAsAgentcan fail with “no ... endpoint was found” for a valid endpoint.
- Files reviewed: 56/60 changed files
- Comments generated: 0 new
- Review effort level: Balanced
|
Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt. |
|
My main concern is the scope of the changes in Aspire.Hosting. This looks primarily like a developer-productivity feature for sending a message to an agent and displaying the response. I think we should keep that functionality in Aspire.Hosting.Agents and constrain changes to Aspire.Hosting unless there is a compelling reason they are needed. In particular, exposing the generic WithReference(...) dispatcher seems broader than this feature requires. We already have WithEnvironment(...) and endpoint expressions to pass an agent-card URL to another resource. If we are missing general-purpose behavior in WithReference(...), that change should stand on its own, with its own justification and API review, rather than being introduced as plumbing for agent invocation. I also think there is a natural limit to how useful this interaction can be once these endpoints require authentication. For scenarios involving sign-in, token acquisition/refresh, or other application-specific auth requirements, an interactive driver program that manages those requirements may be a more natural fit. How quickly we reach that limit depends on whether and how people secure these endpoints, but it is worth being explicit about the intended scope here. |
Remove generic reference dispatch and all production core Hosting changes. Move MCP tool commands into an explicit Agents opt-in, keep deferred agent HTTP execution local, and use endpoint expressions for agent-card wiring. Document authentication boundaries and validate run/publish behavior and generated SDKs. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Thanks Mitch Denny (@mitchdenny) — agreed, and I have narrowed the implementation in 590d39e rather than retaining the broader core changes.
|
There was a problem hiding this comment.
🟡 Changes recommended
Protocol validation, malformed response handling, TypeScript documentation, and the ATS baseline need correction.
Get a fresh assessment by requesting another Copilot review.
Review details
Files not reviewed (1)
- playground/AspireAgents/vercel-ai-responses-agent/package-lock.json: Generated file
Suppressed comments (1)
src/Aspire.Hosting.Agents/AgentResourceBuilderExtensions.cs:767
- The ACP command uses
mode: "sync", but this validation treats every 2xx JSON response exceptfailed/cancelledas success. A malformed{}or a nonterminalcreated/in-progressrun therefore appears successful even though a synchronous run must returnstatus: "completed". Require a presentcompletedstatus and fail every other status while preserving the response for diagnostics.
if (validateAcpRunStatus && TryGetAcpTerminalFailureStatus(responseJson, out var runStatus))
{
return CommandResults.Failure(
$"Agent run ended in the '{runStatus}' state.",
JsonSerializer.Serialize(responseJson["error"] ?? responseJson, s_indentedJsonOptions),
CommandResultFormat.Json);
}
- Files reviewed: 49/53 changed files
- Comments generated: 4
- Review effort level: Balanced
Reject undefined protocols and invocation modes before changing resource state, require the MCP CallToolResult content array, and fix the README enum import. Cover invalid enum inputs, malformed content, and valid empty content arrays. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🔵 Needs a closer look
Valid endpoint casing and several protocol-compliant A2A and AG-UI configurations currently produce failed or incompatible invocations.
Review details
Files not reviewed (1)
- playground/AspireAgents/vercel-ai-responses-agent/package-lock.json: Generated file
Suppressed comments (5)
Previously missed (5) — in code that hasn't changed since the last review.
src/Aspire.Hosting.Agents/AgentResourceBuilderExtensions.cs:269
- HTTP URI schemes are case-insensitive, but this pattern only accepts lowercase values. Because
EndpointAnnotation.UriSchemepreserves the supplied casing, a valid endpoint configured asHTTPorHTTPSreaches the “no endpoint found” exception. Compare both schemes withOrdinalIgnoreCase.
src/Aspire.Hosting.Agents/AgentResourceBuilderExtensions.cs:507 - The first JSONRPC/HTTP+JSON interface is accepted without checking its protocol version. Since
IsA2AProtocolVersionV03treats every0.*value as v0.3 and every other value as v1, a card advertising0.2or2.0before a supported interface is invoked with an incompatible request shape instead of continuing negotiation. Restrict selection to the advertised v0.3/v1.0 versions and continue past unsupported versions.
src/Aspire.Hosting.Agents/AgentResourceBuilderExtensions.cs:552 - Legacy v0.3 cards can advertise alternate bindings in
additionalInterfaces, but this fallback yields only the primaryurl/preferredTransport. If the primary binding is unsupported (for example gRPC) and an additional interface provides JSONRPC or HTTP+JSON, the dashboard command incorrectly reports that no invokable binding exists. Normalize and append eachadditionalInterfacesentry (urlplustransport) using the card's protocol version.
src/Aspire.Hosting.Agents/AgentResourceBuilderExtensions.cs:553 - For a legacy card with a top-level
urlbut noprotocolVersion, this storesnull; request preparation then classifies it as v1 and sends v1 method names and anA2A-Version: 1.0header. A2A's backward-compatibility mapping defaults this legacy shape to0.3.0, so such v0.3 agents cannot be invoked unless the same default is applied here.
src/Aspire.Hosting.Agents/AgentResourceBuilderExtensions.cs:661 - The AG-UI
RunAgentInputcontract requirestools,context, andforwardedProps, but this request sends only IDs and messages. Tolerant endpoints may supply defaults, while protocol-conforming validators reject the dashboard invocation before the agent runs. Send empty collections/object for these required fields when the command has none to provide.
- Files reviewed: 49/53 changed files
- Comments generated: 0 new
- Review effort level: Balanced
|
This implementation has moved to the Aspire Community Toolkit: CommunityToolkit/Aspire#2249 (CommunityToolkit/Aspire#2249), tracking CommunityToolkit/Aspire#2248 (CommunityToolkit/Aspire#2248). The replacement preserves the agent invocation feature, tests, and examples in CommunityToolkit.Aspire.Hosting.Agents without production changes to core Aspire.Hosting. Closing this PR in favor of the Toolkit PR; further implementation discussion and review should continue there. Thanks for the review and guidance here. |
Port microsoft/aspire#17757 via standalone source 8d93031b42666b353aee4a8370a8b5349703ad98. Preserve all protocols, MCP invocation, 277 tests and six examples, adapting Toolkit naming, packaging and test infrastructure. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Port microsoft/aspire#17757 via standalone source 8d93031b42666b353aee4a8370a8b5349703ad98. Preserve all protocols, MCP invocation, 277 tests and six examples, adapting Toolkit naming, packaging and test infrastructure. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Add agent hosting integration from upstream Aspire proposal Port microsoft/aspire#17757 via standalone source 8d93031b42666b353aee4a8370a8b5349703ad98. Preserve all protocols, MCP invocation, 277 tests and six examples, adapting Toolkit naming, packaging and test infrastructure. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * Fix agent invocation issues identified in Copilot review Complete AG-UI inputs, preserve distinct protocol paths, correlate MCP tool responses, handle dialog cancellation and fall back to raw JSON for complex parameter schemas. Add regression coverage for all five review findings. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * Address agent integration maintainer review Reuse shared test helpers, centralize sample package versions, use application configuration, and document Toolkit diagnostics and the dashboard workflow. Preserve publish assertions without a local xUnit override and add safe agent-card failure diagnostics. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * Align agent examples and tests with Aspire 17 Use the shared test project's runtime setup, migrate sample .NET resources to AddDotnetProject, and retain explicit legacy ProjectResource regression coverage. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * Adopt official MCP SDK for agent tool commands Replace handwritten protocol handling with ModelContextProtocol.Core while preserving dashboard inputs, endpoint resolution, authentication boundaries, and bounded cleanup. Align MCP versions centrally and document accepted SDK failure-path limitations and actual dashboard diagnostics. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Description
Adds
Aspire.Hosting.Agents, a developer-productivity integration for identifying endpoint-backed agents and invoking them during local development. It supports A2A, OpenAI Responses, AG-UI, and ACP message commands, plus an explicit opt-in for MCP tool commands.Fixes #17752
Scope
Aspire.Hosting.Agents.Aspire.Hosting: existingWithReference, HTTP commands, and MCP discovery/proxying retain their behavior.WithEnvironmentand endpoint expressions.User-facing usage
Call
AsAgentonce per protocol/path pair. The A2A resource receivesA2A_AGENT_BASE_URLfor its advertised agent-card base URL; consumer wiring remains explicit. StandardWithReferencecan still be used independently for service discovery or connection strings.A2A invocation reads the agent card and selects a supported JSON-RPC or HTTP+JSON binding, with v0.3 and v1.0 support. It defaults to non-streaming and can opt into streaming with
A2AInvocationMode.Streaming.The existing core
WithMcpServerAPI only configures discovery/proxying. The experimentalWithMcpToolCommandsAPI in the Agents package opts into interactive and argument-driven tool commands using that configured endpoint resolver. Tool invocation handles initialization, session termination, cancellation, JSON/SSE responses, and protocol errors.The APIs are exported for generated TypeScript, Python, Go, Java, and Rust AppHosts.
Authentication boundary
Commands issue requests from the AppHost process to endpoints reachable by it. This integration does not implement interactive sign-in, token acquisition/refresh, or forwarding the dashboard user's identity.
For application-specific authentication or user-interactive flows, use a driver application that owns the interaction and authentication; Aspire can orchestrate and observe it. Endpoint authentication should not be disabled to accommodate these commands. Authentication from an agent to a model provider such as Foundry remains the agent application's responsibility.
Playground
playground/AspireAgentscontains Foundry-backed examples:a2a-jsonrpc-agent: Python A2A SDK with a LangChain-backed agent.responses-agent: .NET OpenAI Responses agent, also exposing MCP weather tools.vercel-ai-responses-agent: Vercel AI SDK Responses implementation.mcp-agent: .NET MCP server with a model-backedanswer_questiontool.agui-acp-agent: Python application exposing AG-UI and ACP.agent-env-dump: verifies explicitly configured agent-card environment wiring.Checklist
<remarks />and<code />elements on your triple slash comments?