[docs] Update Foundry hosted agent API from PublishAsHostedAgent to AsHostedAgent#1130
Conversation
…Agent Documents the API rename from WithComputeEnvironment/PublishAsHostedAgent to AsHostedAgent introduced in microsoft/aspire#17669. Updates all code examples, section headings, and prose in the Azure AI Foundry hosting integration docs to use the new AsHostedAgent method. Also clarifies that the default Azure Container Registry is only created in publish mode, not local run mode. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR updates the Azure AI Foundry hosting docs to use the renamed hosted-agent API and clarify publish-mode behavior for default Azure Container Registry creation.
Changes:
- Replaces
PublishAsHostedAgent/publishAsHostedAgentwithAsHostedAgent/asHostedAgent. - Renames the hosted-agent section to “Add a hosted agent to Azure AI Foundry.”
- Clarifies that
AddProjectcreates a default ACR only in publish mode.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| .withReference(project) | ||
| .withReference(chat) | ||
| .publishAsHostedAgent({ project }); | ||
| .asHostedAgent({ project }); |
IEvangelist
left a comment
There was a problem hiding this comment.
docs-from-code review — PR #1130
Phase A — Claim verification source of truth
- Repo:
microsoft/aspire - Branch:
release/13.4 - SHA:
e258349fd49dd0fdf08f92468d79f0cfaaf13012 - PR head SHA reviewed:
c3ac0ba184f463ed192acaa340203f86cac45207
| Verdict | Count |
|---|---|
| ✅ verified | 9 |
| 0 | |
| ❓ unverifiable | 0 |
| ❌ contradicted | 3 |
Phase B — doc-tester skill run
- Local docs site:
http://localhost:59650(thefrontendresource ofAspire.Dev.AppHost, PR head applied to the worktree). - Routes exercised:
/integrations/cloud/azure/azure-ai-foundry/azure-ai-foundry-host/(the only file the PR changes) + HEAD-checks against the page's outbound internal links and the two screenshot URLs. - Result: 1 critical issue, 2 warnings, 7 passed checks (full report below).
Combined verdict: Requesting changes — Phase A finds three contradicted claims (the TypeScript asHostedAgent shape and the dashboard /liveness / /readiness URLs), and Phase B independently surfaces the same TS shape as a critical user-blocking issue plus a screenshot/prose mismatch in the dashboard section.
Inline comments are anchored to the specific PR lines below.
Phase A — Claim verdicts
Contradicted claims
The three failed claims are posted as inline review comments. In short:
- TypeScript
asHostedAgent({ project })is the wrong call shape for the renamed API onrelease/13.4. The polyglot exportAsHostedAgentForExport<T>(builder, IResourceBuilder<AzureCognitiveServicesProjectResource> project, HostedAgentOptions? options = null)(src/Aspire.Hosting.Foundry/HostedAgent/HostedAgentBuilderExtension.cs:62-67) makesprojecta required positional argument.HostedAgentOptions(HostedAgentOptions.cs:15-46) has noprojectfield. The polyglot integration test fixture confirms the canonical shape:asHostedAgent(project, { description, cpu, memory, metadata, environmentVariables })(tests/PolyglotAppHosts/Aspire.Hosting.Foundry/TypeScript/apphost.mts:113). The pre-rename TS sample worked because the priorpublishAsHostedAgent/withComputeEnvironmentexports treatedprojectas a nullable optional. The rename made it required, but the TS samples were carried over unchanged. Affects lines 400, 407, 453. - "Dashboard links for
/responses,/liveness, and/readiness" is no longer true onrelease/13.4. CurrentConfigureRunMode(HostedAgentBuilderExtension.cs:171-183) only rewrites the existinghttpendpoint URL to/responses(display text"Responses Endpoint") — no/livenessor/readinessURLs are added and there is no.WithHttpHealthCheck("/liveness")call. The source PR that drove this rename removed the commented-out health-check URL setup. The mechanical PublishAsHostedAgent → AsHostedAgent rename on line 540 carried the old prose forward.
Verified claims (9 — click to expand)
Verified claims (9 — click to expand)
| # | Line | Claim | Evidence |
|---|---|---|---|
| 1 | 350 | AddProject creates default ACR only in publish mode |
src/Aspire.Hosting.Foundry/Project/ProjectBuilderExtension.cs:53-56 — wrapped in if (builder.ApplicationBuilder.ExecutionContext.IsPublishMode) |
| 2 | 350 | WithContainerRegistry overrides default |
Generic WithContainerRegistry<TDestination, TContainerRegistry> in src/Aspire.Hosting/ContainerRegistryResourceBuilderExtensions.cs; AzureCognitiveServicesProjectResource satisfies the destination constraint |
| 3 | 352, 354 | AsHostedAgent section heading + intro |
HostedAgentBuilderExtension.cs:86 (AsHostedAgent<T>(builder, project?, configure?)) and surface file api/Aspire.Hosting.Foundry.cs:100 |
| 4 | 369, 375 | C# .AsHostedAgent(project) after AddPythonApp / AddProject<T> |
Same overload as Claim 3 — both PythonAppResource and ProjectResource satisfy IComputeResource, IResourceWithEndpoints, IResourceWithEnvironment |
| 5 | 415 | Run-mode endpoint: preserves existing http target port, defaults to 8088 |
HostedAgentBuilderExtension.cs:163-170 (var targetPort = existingHttpEndpoint?.TargetPort ?? 8088;) |
| 6 | 420 | Port is injected as DEFAULT_AD_PORT |
HostedAgentBuilderExtension.cs:170 (.WithHttpEndpoint(name: "http", env: "DEFAULT_AD_PORT", …)) |
| 7 | 424 | Declare endpoint before calling AsHostedAgent(...) |
Consequence of Claim 5 — verified by tests/PolyglotAppHosts/Aspire.Hosting.Foundry/TypeScript/apphost.mts declaring the endpoint first |
| 8 | 435 | C# dotnetWeatherAgent.AsHostedAgent(project) |
Same overload as Claim 3 |
| 9 | 540 | Highlighted Send Message command posting to /responses |
HostedAgentBuilderExtension.cs:184-193 (.WithHttpCommand(path: "/responses", displayName: "Send Message", commandOptions: { IsHighlighted = true, IconName = "ChatSparkle", … })) |
Phase B — doc-tester skill report
| Category | Passed | Failed | Warnings |
|---|---|---|---|
| Content Accuracy (readable from the page alone) | 6 | 1 | 1 |
| Code Examples (parse, copy-paste fidelity) | 5 | 1 | 1 |
CLI Commands (aspire add azure-ai-foundry) |
1 | 0 | 0 |
| Links (resolve + trailing-slash convention) | 7 | 0 | 0 |
Critical issue (Phase B)
TypeScript example for asHostedAgent shows an API shape that contradicts the C# example in the same section — section “Add a hosted agent to Azure AI Foundry” and the “Declare endpoint before AsHostedAgent” subsection.
A polyglot reader toggling between tabs sees .AsHostedAgent(project) in C# but .asHostedAgent({ project }) in TypeScript. The TS samples include no other named properties alongside project, so a new TS user has no way to discover whether the API accepts options (description, cpu, memory, env vars, metadata, etc.) and no way to validate the API shape from the docs alone. Hovering the call in the rendered Twoslash output surfaces project: any — a TS user has no way to tell whether any is intentional or a sign the types aren't resolving.
Recommended action:
- Reconcile the TypeScript shape with the C# shape on lines 400, 407, and 453.
- Show at least one additional option in the TypeScript example so users learn what else fits in the call.
Warnings (Phase B)
1. Claim about /liveness and /readiness dashboard links is not corroborated by the screenshots on the page. The prose under the first hosted-agent example (line 459, unchanged by this PR) and the recap in the "Invoke agents from the Aspire dashboard" section (line 540, changed by this PR) both promise three dashboard URLs (/responses, /liveness, /readiness). The two embedded screenshots (agent-send-message.png, agent-responses-result.png) show Send Message and the response result, but neither shows the three URLs. From the page alone a reader is told to expect something the visuals do not demonstrate. (Phase A confirms the /liveness and /readiness URLs are no longer wired up.)
2. Sibling link in the intro paragraph uses a relative path while every other internal link on the page is site-relative. The PR adds [Connect to Azure AI Foundry](../azure-ai-foundry-connect/). The relative form works (HTTP 200), but the rest of the page consistently uses fully-qualified site-relative paths. Worth normalizing for consistency.
Passed checks (Phase B)
- The PR-modified route resolves with HTTP 200 against the PR head content.
- Both screenshots referenced by the page load (HTTP 200).
- Internal links sampled from the page all resolve:
azure-ai-foundry-connect/,azure-ai-foundry-get-started/,/get-started/app-host/,/reference/cli/commands/aspire-add/. - All site-relative links on the page (except favicon/feed assets, which are intentionally extensionful) end with a trailing slash.
- The
aspire add azure-ai-foundrysnippet uses the documented short-name form. - The Pivot/PivotSelector pairing for C# / TypeScript renders correctly across the page.
- Prose ordering inside the “Add a hosted agent” section flows logically: method intro → base example → run-mode endpoint defaults → custom-port pattern → publish-mode behavior.
- The “
AddProjectcreates a default Azure Container Registry … only in publish mode” clarification aligns cleanly with the immediately precedingWithContainerRegistry(registry)example.
Knowledge gaps surfaced (Phase B)
- Polyglot binding mechanics. Evaluating whether the TS / C# shape divergence is intentional required prior knowledge of how Aspire's polyglot export attribute drives the TS shim — nothing on the page (or anything it links to) explains this. A short conceptual link from this page would let a new TS user reason about which divergences are bugs vs. design.
DEFAULT_AD_PORTabbreviation. The page introducesDEFAULT_AD_PORTwithout expanding whatADstands for. Easy fix — a parenthetical the first time it appears.
This review was produced by the hourly docs-from-code reviewer (Phase A reads microsoft/aspire@release/13.4 source of truth; Phase B runs the doc-tester skill against the locally-served PR head, blind to source code; Phase C merges and posts both).
Encoding was corrupted; reposting clean review.
IEvangelist
left a comment
There was a problem hiding this comment.
docs-from-code review - PR #1130
Phase A - Claim verification source of truth
- Repo:
microsoft/aspire - Branch:
release/13.4 - SHA:
e258349fd49dd0fdf08f92468d79f0cfaaf13012 - PR head SHA reviewed:
c3ac0ba184f463ed192acaa340203f86cac45207
| Verdict | Count |
|---|---|
| verified | 9 |
| verified-with-nuance | 0 |
| unverifiable | 0 |
| contradicted | 3 |
Phase B - doc-tester skill run
- Local docs site:
http://localhost:59650(thefrontendresource ofAspire.Dev.AppHost, PR head applied to the worktree). - Routes exercised:
/integrations/cloud/azure/azure-ai-foundry/azure-ai-foundry-host/(the only file the PR changes) + HEAD-checks against the page's outbound internal links and the two screenshot URLs. - Result: 1 critical issue, 2 warnings, 7 passed checks (full report below).
Combined verdict: Requesting changes - Phase A finds three contradicted claims (the TypeScript asHostedAgent shape and the dashboard /liveness / /readiness URLs), and Phase B independently surfaces the same TS shape as a critical user-blocking issue plus a screenshot/prose mismatch in the dashboard section.
Inline comments are anchored to the specific PR lines below.
Phase A - Claim verdicts
Contradicted claims
The three failed claims are posted as inline review comments. In short:
- TypeScript
asHostedAgent({ project })is the wrong call shape for the renamed API onrelease/13.4. The polyglot exportAsHostedAgentForExport<T>(builder, IResourceBuilder<AzureCognitiveServicesProjectResource> project, HostedAgentOptions? options = null)(src/Aspire.Hosting.Foundry/HostedAgent/HostedAgentBuilderExtension.cs:62-67) makesprojecta required positional argument.HostedAgentOptions(HostedAgentOptions.cs:15-46) has noprojectfield. The polyglot integration test fixture confirms the canonical shape:asHostedAgent(project, { description, cpu, memory, metadata, environmentVariables })(tests/PolyglotAppHosts/Aspire.Hosting.Foundry/TypeScript/apphost.mts:113). The pre-rename TS sample worked because the priorpublishAsHostedAgent/withComputeEnvironmentexports treatedprojectas a nullable optional. The rename made it required, but the TS samples were carried over unchanged. Affects lines 400, 407, 453. - "Dashboard links for
/responses,/liveness, and/readiness" is no longer true onrelease/13.4. CurrentConfigureRunMode(HostedAgentBuilderExtension.cs:171-183) only rewrites the existinghttpendpoint URL to/responses(display text"Responses Endpoint") - no/livenessor/readinessURLs are added and there is no.WithHttpHealthCheck("/liveness")call. The source PR that drove this rename removed the commented-out health-check URL setup. The mechanicalPublishAsHostedAgent->AsHostedAgentrename on line 540 carried the old prose forward.
Verified claims (9 - click to expand)
Verified claims (9 - click to expand)
| # | Line | Claim | Evidence |
|---|---|---|---|
| 1 | 350 | AddProject creates default ACR only in publish mode |
src/Aspire.Hosting.Foundry/Project/ProjectBuilderExtension.cs:53-56 - wrapped in if (builder.ApplicationBuilder.ExecutionContext.IsPublishMode) |
| 2 | 350 | WithContainerRegistry overrides default |
Generic WithContainerRegistry<TDestination, TContainerRegistry> in src/Aspire.Hosting/ContainerRegistryResourceBuilderExtensions.cs; AzureCognitiveServicesProjectResource satisfies the destination constraint |
| 3 | 352, 354 | AsHostedAgent section heading + intro |
HostedAgentBuilderExtension.cs:86 (AsHostedAgent<T>(builder, project?, configure?)) and surface file api/Aspire.Hosting.Foundry.cs:100 |
| 4 | 369, 375 | C# .AsHostedAgent(project) after AddPythonApp / AddProject<T> |
Same overload as Claim 3 - both PythonAppResource and ProjectResource satisfy IComputeResource, IResourceWithEndpoints, IResourceWithEnvironment |
| 5 | 415 | Run-mode endpoint: preserves existing http target port, defaults to 8088 |
HostedAgentBuilderExtension.cs:163-170 (var targetPort = existingHttpEndpoint?.TargetPort ?? 8088;) |
| 6 | 420 | Port is injected as DEFAULT_AD_PORT |
HostedAgentBuilderExtension.cs:170 (.WithHttpEndpoint(name: "http", env: "DEFAULT_AD_PORT", ...)) |
| 7 | 424 | Declare endpoint before calling AsHostedAgent(...) |
Consequence of Claim 5 - verified by tests/PolyglotAppHosts/Aspire.Hosting.Foundry/TypeScript/apphost.mts declaring the endpoint first |
| 8 | 435 | C# dotnetWeatherAgent.AsHostedAgent(project) |
Same overload as Claim 3 |
| 9 | 540 | Highlighted Send Message command posting to /responses |
HostedAgentBuilderExtension.cs:184-193 (.WithHttpCommand(path: "/responses", displayName: "Send Message", commandOptions: { IsHighlighted = true, IconName = "ChatSparkle", ... })) |
Phase B - doc-tester skill report
| Category | Passed | Failed | Warnings |
|---|---|---|---|
| Content Accuracy (readable from the page alone) | 6 | 1 | 1 |
| Code Examples (parse, copy-paste fidelity) | 5 | 1 | 1 |
CLI Commands (aspire add azure-ai-foundry) |
1 | 0 | 0 |
| Links (resolve + trailing-slash convention) | 7 | 0 | 0 |
Critical issue (Phase B)
TypeScript example for asHostedAgent shows an API shape that contradicts the C# example in the same section - section "Add a hosted agent to Azure AI Foundry" and the "Declare endpoint before AsHostedAgent" subsection.
A polyglot reader toggling between tabs sees .AsHostedAgent(project) in C# but .asHostedAgent({ project }) in TypeScript. The TS samples include no other named properties alongside project, so a new TS user has no way to discover whether the API accepts options (description, cpu, memory, env vars, metadata, etc.) and no way to validate the API shape from the docs alone. Hovering the call in the rendered Twoslash output surfaces project: any - a TS user has no way to tell whether any is intentional or a sign the types aren't resolving.
Recommended action:
- Reconcile the TypeScript shape with the C# shape on lines 400, 407, and 453.
- Show at least one additional option in the TypeScript example so users learn what else fits in the call.
Warnings (Phase B)
1. Claim about /liveness and /readiness dashboard links is not corroborated by the screenshots on the page. The prose under the first hosted-agent example (line 459, unchanged by this PR) and the recap in the "Invoke agents from the Aspire dashboard" section (line 540, changed by this PR) both promise three dashboard URLs (/responses, /liveness, /readiness). The two embedded screenshots (agent-send-message.png, agent-responses-result.png) show Send Message and the response result, but neither shows the three URLs. From the page alone a reader is told to expect something the visuals do not demonstrate. (Phase A confirms the /liveness and /readiness URLs are no longer wired up.)
2. Sibling link in the intro paragraph uses a relative path while every other internal link on the page is site-relative. The PR adds [Connect to Azure AI Foundry](../azure-ai-foundry-connect/). The relative form works (HTTP 200), but the rest of the page consistently uses fully-qualified site-relative paths. Worth normalizing for consistency.
Passed checks (Phase B)
- The PR-modified route resolves with HTTP 200 against the PR head content.
- Both screenshots referenced by the page load (HTTP 200).
- Internal links sampled from the page all resolve:
azure-ai-foundry-connect/,azure-ai-foundry-get-started/,/get-started/app-host/,/reference/cli/commands/aspire-add/. - All site-relative links on the page (except favicon/feed assets, which are intentionally extensionful) end with a trailing slash.
- The
aspire add azure-ai-foundrysnippet uses the documented short-name form. - The Pivot/PivotSelector pairing for C# / TypeScript renders correctly across the page.
- Prose ordering inside the "Add a hosted agent" section flows logically: method intro -> base example -> run-mode endpoint defaults -> custom-port pattern -> publish-mode behavior.
- The "
AddProjectcreates a default Azure Container Registry ... only in publish mode" clarification aligns cleanly with the immediately precedingWithContainerRegistry(registry)example.
Knowledge gaps surfaced (Phase B)
- Polyglot binding mechanics. Evaluating whether the TS / C# shape divergence is intentional required prior knowledge of how Aspire's polyglot export attribute drives the TS shim - nothing on the page (or anything it links to) explains this. A short conceptual link from this page would let a new TS user reason about which divergences are bugs vs. design.
DEFAULT_AD_PORTabbreviation. The page introducesDEFAULT_AD_PORTwithout expanding whatADstands for. Easy fix - a parenthetical the first time it appears.
This review was produced by the hourly docs-from-code reviewer (Phase A reads microsoft/aspire@release/13.4 source of truth; Phase B runs the doc-tester skill against the locally-served PR head, blind to source code; Phase C merges and posts both).
| .withReference(project) | ||
| .withReference(chat) | ||
| .publishAsHostedAgent({ project }); | ||
| .asHostedAgent({ project }); |
There was a problem hiding this comment.
Contradicted (Phase A - microsoft/aspire@release/13.4 @ e258349)
The TypeScript polyglot export for AsHostedAgent makes project a required positional argument, not a field on a single options object. The PR appears to have mechanically renamed publishAsHostedAgent -> asHostedAgent but didn't update the call shape to match the new signature.
Source of truth - src/Aspire.Hosting.Foundry/HostedAgent/HostedAgentBuilderExtension.cs:62-67:
[AspireExport("asHostedAgentExecutable", MethodName = "asHostedAgent")]
internal static IResourceBuilder<T> AsHostedAgentForExport<T>(
this IResourceBuilder<T> builder,
IResourceBuilder<AzureCognitiveServicesProjectResource> project,
HostedAgentOptions? options = null)HostedAgentOptions (HostedAgentOptions.cs:15-46) has only Description, Cpu, Memory, Metadata, EnvironmentVariables - no project property.
The canonical TS call shape is in the in-repo polyglot fixture, tests/PolyglotAppHosts/Aspire.Hosting.Foundry/TypeScript/apphost.mts:113:
await hostedAgent.asHostedAgent(project, {
description: 'Validation hosted agent',
cpu: 1,
memory: 2,
metadata: { scenario: 'validation' },
environmentVariables: { VALIDATION_MODE: 'true' }
});Suggested change (mirrors the C# tab):
.asHostedAgent(project);The Phase B doc-tester run independently flagged the same shape as a critical issue from a polyglot reader's perspective. Same fix applies to lines 407 and 453.
| .withReference(project) | ||
| .withReference(chat) | ||
| .publishAsHostedAgent({ project }); | ||
| .asHostedAgent({ project }); |
There was a problem hiding this comment.
Contradicted (Phase A) - same root cause as the comment on line 400. asHostedAgent takes project as a required positional argument; { project } does not match the polyglot export signature (HostedAgentBuilderExtension.cs:62-67). Replace with:
.asHostedAgent(project);| .waitFor(chat); | ||
|
|
||
| await dotnetWeatherAgent.publishAsHostedAgent({ project }); | ||
| await dotnetWeatherAgent.asHostedAgent({ project }); |
There was a problem hiding this comment.
Contradicted (Phase A) - same root cause as the comments on lines 400 and 407. The polyglot export takes (project, options?) positionally, so { project } doesn't bind. Replace with:
await dotnetWeatherAgent.asHostedAgent(project);| ## Invoke agents from the Aspire dashboard | ||
|
|
||
| Aspire also makes the declared agents easy to try from the dashboard. Prompt agents get a **Send Message** command from `AddPromptAgent(...)`. Hosted agents published with `PublishAsHostedAgent(...)` get a highlighted **Send Message** command that posts to the local `/responses` endpoint, plus dashboard links for `/responses`, `/liveness`, and `/readiness`. | ||
| Aspire also makes the declared agents easy to try from the dashboard. Prompt agents get a **Send Message** command from `AddPromptAgent(...)`. Hosted agents configured with `AsHostedAgent(...)` get a highlighted **Send Message** command that posts to the local `/responses` endpoint, plus dashboard links for `/responses`, `/liveness`, and `/readiness`. |
There was a problem hiding this comment.
Contradicted (Phase A - microsoft/aspire@release/13.4 @ e258349)
"plus dashboard links for
/responses,/liveness, and/readiness"
On the renamed AsHostedAgent, ConfigureRunMode only rewrites the existing http endpoint URL to /responses - no /liveness or /readiness URLs are added and no HTTP health check is wired up.
Source of truth - src/Aspire.Hosting.Foundry/HostedAgent/HostedAgentBuilderExtension.cs:171-183:
.WithUrls(c =>
{
var responsesUrl = c.Urls.FirstOrDefault(u => u.Endpoint?.EndpointName == "http");
if (responsesUrl is not null)
{
responsesUrl.Url = "/responses";
responsesUrl.DisplayText = "Responses Endpoint";
}
});The pre-rename code (PublishAsHostedAgent) did wire up the three URLs and a /liveness health check, but those were intentionally removed in the source PR alongside the rename (see commit message: "Remove commented-out health check URLs from hosted agent configuration"). The mechanical rename here carried the old prose forward.
Suggested change - trim the dashboard recap to what's actually wired up:
"Hosted agents configured with
AsHostedAgent(...)get a highlighted Send Message command that posts to the local/responsesendpoint, plus a/responsesdashboard URL."
(Note: line 459, which is unchanged by this PR, makes the same /liveness + /readiness + WithHttpHealthCheck claim and is also stale. It's outside this PR's diff but worth fixing in a follow-up.)
Documents changes from microsoft/aspire#17669 (
@davidfowl).Targeting
release/13.4based on the source PR milestone13.4(exact match onmicrosoft/aspire.dev).Why this PR is needed
PR microsoft/aspire#17669 renamed the hosted-agent builder API from
WithComputeEnvironmenttoAsHostedAgent(a breaking API removal per the public API surface file). The existing docs usedPublishAsHostedAgent(a previous name) which no longer exists in the public API. All hosted-agent code examples and prose must be updated to use the newAsHostedAgentmethod.Additionally, the PR changed the behavior of
AddProject: the default Azure Container Registry is now only created in publish mode (when deploying to Azure), not in local run mode. The docs previously stated it was always created.Changes
src/frontend/src/content/docs/integrations/cloud/azure/azure-ai-foundry/azure-ai-foundry-host.mdx:PublishAsHostedAgent(C#) andpublishAsHostedAgent(TypeScript) withAsHostedAgent/asHostedAgentin code examples and proseAddProjectonly creates a default ACR in publish mode, not local run mode