Restore hosted agents (PR(#28) after revert - #29
Merged
Conversation
…ve configuration - Added support for Microsoft Foundry hosted agents in AGENTS.md. - Refactored AuthorAgent and BloggerAgent to accept AIAgent instead of IChatClient. - Updated BlogWriter.csproj to include Microsoft.Agents.AI.Foundry package. - Removed ProjectReferences for shared prompts in hosted agent projects. - Introduced AgentPrompt.cs files for each hosted agent with specific instructions. - Updated eval.yaml files for hosted agents to include new configurations. - Enhanced README.md with new environment variable requirements. - Removed RemoteHostedAgentChatClient as it is no longer needed. - Added detailed instructions for each agent in their respective .agent_configs.
…n cap test: Add test for shared token budget across clients chore: Update YAML configuration by removing infra provider feat: Implement cumulative token budget for MAF-hosted agents docs: Remove MAX_OUTPUT_TOKENS from README in favor of MAX_TOTAL_TOKENS
…prove revision handling
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
There are breaking/incorrect defaults and compatibility gaps (notably agent name defaults and removed in-process constructor used by tests) plus documentation mismatches that should be corrected before approval.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Restores the previously-reverted migration from in-process agents to Azure AI Foundry Hosted Agents orchestrated via Microsoft Agent Framework (MAF), including new hosted-agent projects and supporting documentation.
Changes:
- Switch console app orchestration to call pre-deployed Foundry hosted agents via
AIProjectClient.AsAIAgent(...)(no in-process agent construction, no custom Tavily/MCP tooling). - Introduce a shared, cumulative token budget across all agent calls via
TokenCapChatClient.CreateSharedFactory(...). - Add
HostedAgents/*projects plusdocs/*documenting architecture, configuration, and deployment.
File summaries
| File | Description |
|---|---|
| TokenCapChatClient.cs | Refactors token cap tracking into a shareable budget and adds CreateSharedFactory. |
| Program.cs | Replaces direct model/tool wiring with Foundry hosted-agent clients + shared token budget. |
| BloggerAgent.cs | Updates agent construction to accept hosted AIAgent, with an in-process compatibility overload. |
| ResearcherAgent.cs | Updates Researcher to use a hosted AIAgent (tools now run server-side). |
| AuthorAgent.cs | Updates Author to use a hosted AIAgent. |
| ReviewerAgent.cs | Updates Reviewer to use a hosted AIAgent. |
| ResearchState.cs | Adds RevisionLimitReached helper for clearer workflow termination reporting. |
| README.md | Documents hosted-agent architecture and configuration for the new deployment model. |
| BlogWriter.csproj | Excludes HostedAgents/** sources and adds Foundry + identity dependencies for console app. |
| BlogWriter.Tests/TokenCapChatClientTests.cs | Adds coverage for shared token budget across multiple clients. |
| BlogWriter.Tests/ResearchStateTests.cs | Adds coverage for RevisionLimitReached. |
| HostedAgents/README.md | Adds shared deploy/run guidance for hosted-agent subprojects. |
| HostedAgents/Blogger/Blogger.HostedAgent.csproj | New hosted-agent project for Blogger. |
| HostedAgents/Blogger/Program.cs | Hosts Blogger role via Foundry Hosting + Responses endpoint. |
| HostedAgents/Blogger/AgentPrompt.cs | Deployment-local Blogger prompt copy. |
| HostedAgents/Blogger/README.md | Blogger hosted-agent configuration notes. |
| HostedAgents/Blogger/azure.yaml | azd manifest for Blogger hosted agent. |
| HostedAgents/Blogger/eval.yaml | Smoke eval configuration for Blogger hosted agent. |
| HostedAgents/Blogger/.agentignore | Packaging exclusions for Blogger agent deploy. |
| HostedAgents/Blogger/.gitignore | Ignores local .azure artifacts in Blogger project. |
| HostedAgents/Blogger/.agent_configs/baseline/metadata.yaml | Baseline config metadata for eval/deploy tooling. |
| HostedAgents/Blogger/.agent_configs/baseline/instructions.md | Baseline instruction summary for tooling. |
| HostedAgents/Researcher/Researcher.HostedAgent.csproj | New hosted-agent project for Researcher. |
| HostedAgents/Researcher/Program.cs | Hosts Researcher role and wires HostedWebSearchTool. |
| HostedAgents/Researcher/AgentPrompt.cs | Deployment-local Researcher prompt copy. |
| HostedAgents/Researcher/README.md | Researcher hosted-agent configuration notes. |
| HostedAgents/Researcher/azure.yaml | azd manifest for Researcher hosted agent. |
| HostedAgents/Researcher/eval.yaml | Smoke eval configuration for Researcher hosted agent. |
| HostedAgents/Researcher/.agentignore | Packaging exclusions for Researcher agent deploy. |
| HostedAgents/Researcher/.agent_configs/baseline/metadata.yaml | Baseline config metadata for eval/deploy tooling. |
| HostedAgents/Researcher/.agent_configs/baseline/instructions.md | Baseline instruction summary for tooling. |
| HostedAgents/Author/Author.HostedAgent.csproj | New hosted-agent project for Author. |
| HostedAgents/Author/Program.cs | Hosts Author role via Foundry Hosting + Responses endpoint. |
| HostedAgents/Author/AgentPrompt.cs | Deployment-local Author prompt copy. |
| HostedAgents/Author/README.md | Author hosted-agent configuration notes. |
| HostedAgents/Author/azure.yaml | azd manifest for Author hosted agent. |
| HostedAgents/Author/eval.yaml | Smoke eval configuration for Author hosted agent. |
| HostedAgents/Author/.agentignore | Packaging exclusions for Author agent deploy. |
| HostedAgents/Author/.agent_configs/baseline/metadata.yaml | Baseline config metadata for eval/deploy tooling. |
| HostedAgents/Author/.agent_configs/baseline/instructions.md | Baseline instruction summary for tooling. |
| HostedAgents/Reviewer/Reviewer.HostedAgent.csproj | New hosted-agent project for Reviewer. |
| HostedAgents/Reviewer/Program.cs | Hosts Reviewer role via Foundry Hosting + Responses endpoint. |
| HostedAgents/Reviewer/AgentPrompt.cs | Deployment-local Reviewer prompt copy. |
| HostedAgents/Reviewer/README.md | Reviewer hosted-agent configuration notes. |
| HostedAgents/Reviewer/azure.yaml | azd manifest for Reviewer hosted agent. |
| HostedAgents/Reviewer/eval.yaml | Smoke eval configuration for Reviewer hosted agent. |
| HostedAgents/Reviewer/.agentignore | Packaging exclusions for Reviewer agent deploy. |
| HostedAgents/Reviewer/.agent_configs/baseline/metadata.yaml | Baseline config metadata for eval/deploy tooling. |
| HostedAgents/Reviewer/.agent_configs/baseline/instructions.md | Baseline instruction summary for tooling. |
| docs/architecture.md | Documents end-to-end architecture and workflow graph for hosted agents. |
| docs/changelog-v1-to-v2.md | Summarizes migration changes and rationale from in-process to hosted agents. |
| docs/configuration.md | Centralizes env var / secrets reference for console + hosted agents. |
| docs/deployment.md | Documents azd deployment flow and operational guidance. |
| AGENTS.md | Adds note about Foundry hosted-agents skills reference. |
| .gitignore | Adds .env ignore patterns (with .env.example allowed). |
Review details
Suppressed comments (1)
README.md:58
- This bullet claims the console app authenticates with DefaultAzureCredential, but Program.cs uses AzureCliCredential. Keeping the README consistent with the actual authentication flow will avoid confusion.
- Files reviewed: 54/55 changed files
- Comments generated: 6
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+24
to
30
| public AuthorAgent(AIAgent agent, ILogger<AuthorAgent> logger) | ||
| { | ||
| _logger = logger; | ||
| _maxOutputTokens = chatOptions.MaxOutputTokens; | ||
|
|
||
| _agent = new ChatClientAgent(llm, new ChatClientAgentOptions | ||
| { | ||
| Name = "Author", | ||
| ChatOptions = new ChatOptions | ||
| { | ||
| Instructions = Prompts.AuthorInstructions, | ||
| Temperature = chatOptions.Temperature, | ||
| MaxOutputTokens = chatOptions.MaxOutputTokens, | ||
| }, | ||
| }) | ||
| .AsBuilder() | ||
| .UseOpenTelemetry(sourceName: "BlogWriter.Agents") | ||
| .Build(); | ||
| _agent = agent; | ||
| _logger.LogInformation("AuthorAgent initialized."); | ||
| } |
Comment on lines
+26
to
+29
| string bloggerAgentName = config["BLOGGER_AGENT_NAME"] ?? "Blogger"; | ||
| string researcherAgentName = config["RESEARCHER_AGENT_NAME"] ?? "Researcher"; | ||
| string authorAgentName = config["AUTHOR_AGENT_NAME"] ?? "Author"; | ||
| string reviewerAgentName = config["REVIEWER_AGENT_NAME"] ?? "Reviewer"; |
Comment on lines
+42
to
+46
| public BloggerAgent(IChatClient llm, ChatOptions chatOptions, ILogger<BloggerAgent> logger) | ||
| : this(new ChatClientAgent(llm, new ChatClientAgentOptions | ||
| { | ||
| Name = "Blogger", | ||
| ChatOptions = new ChatOptions | ||
| { | ||
| Instructions = Prompts.BloggerInstructions, | ||
| Temperature = chatOptions.Temperature, | ||
| MaxOutputTokens = chatOptions.MaxOutputTokens, | ||
| }, | ||
| }) | ||
| .AsBuilder() | ||
| .UseOpenTelemetry(sourceName: "BlogWriter.Agents") | ||
| .Build(); | ||
| _logger.LogInformation("BloggerAgent initialized."); | ||
| ChatOptions = chatOptions, |
| await Task.Delay(TimeSpan.FromSeconds(Math.Pow(2, attempt - 1)), cancellationToken); | ||
| } | ||
| } | ||
| Uri agentEndpoint = new($"{foundryProjectEndpoint.AbsoluteUri.TrimEnd('/')}/agents/{hostedAgentName}/endpoint/protocols/openai"); |
Comment on lines
+35
to
+37
| Set via `dotnet user-secrets` (preferred for local dev) or environment | ||
| variables — Entra ID (`DefaultAzureCredential`) is used for all Foundry/model | ||
| auth, no API keys: |
Comment on lines
+12
to
+16
| /// The web-search tool runs inside the Researcher Foundry Hosted | ||
| /// Agent itself (see HostedAgents/Researcher), not in this process — the | ||
| /// <paramref name="llm"/> passed in is a remote <c>IChatClient</c> talking to | ||
| /// that hosted agent's <c>/responses</c> endpoint, so tool calls happen | ||
| /// server-side and are already reflected in the returned text/usage. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PR #28 was reverted
I cherry-picked the commits cleanly
This PR restores the intended changes