mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
Python: Azure AI client based on new azure-ai-projects package (#1910)
* Added changes (#1909)
* Python: [Feature Branch] Renamed Azure AI agent and small fixes (#1919)
* Renaming
* Small fixes
* Update python/packages/core/agent_framework/openai/_shared.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Small fix
* Python: [Feature Branch] Added use_latest_version parameter to AzureAIClient (#1959)
* Added use_latest_version parameter to AzureAIClient
* Added unit tests
* Update python/samples/getting_started/agents/azure_ai/azure_ai_use_latest_version.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update python/packages/azure-ai/agent_framework_azure_ai/_client.py
Co-authored-by: Evan Mattson <35585003+moonbox3@users.noreply.github.com>
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Evan Mattson <35585003+moonbox3@users.noreply.github.com>
* Python: [Feature Branch] Structured Outputs and more examples for AzureAIClient (#1987)
* Small updates
* Added support for structured outputs
* Added code interpreter example
* More examples and fixes
* Added more examples and README
* Small fix
* Addressed PR feedback
* Removed optional ID from FunctionResultContent (#2011)
* Added hosted MCP support (#2018)
* Python: [Feature Branch] Fixed "store" parameter handling (#2069)
* Fixed store parameter handling
* Small fix
* Python: [Feature Branch] Added more examples and fixes for Azure AI agent (#2077)
* Updated azure-ai-projects package version
* Added an example of hosted MCP with approval required
* Updated code interpreter example
* Added file search example
* Update python/samples/getting_started/agents/azure_ai/azure_ai_with_file_search.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update python/samples/getting_started/agents/azure_ai/azure_ai_with_file_search.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Small fix
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Added handling for conversation_id (#2098)
* Merge from main
* Revert "Merge from main"
This reverts commit b8206a85d7.
* Python: [Feature Branch] Merge from main to Azure AI branch (#2111)
* Do not build DevUI assets during .NET project build (#2010)
* .NET: Add unit tests for declarative executor SetMultipleVariables (#2016)
* Add unit tests for create conversation executor
* Update indentation and comment typo.
* Added unit tests for declarative executor SetMultipleVariablesExecutor
* Updated comments and syntactic sugar
* Python: DevUI: Use metadata.entity_id instead of model field (#1984)
* DevUI: Use metadata.entity_id for agent/workflow name instead of model field
* OpenAI Responses: add explicit request validation
* Review feedback
* .NET: DevUI - Do not automatically add/map OpenAI services/endpoints (#2014)
* Don't add OpenAIResponses as part of Dev UI
You should be able to add and remove Dev UI without impacting your other production endpoints.
* Remove `AddDevUI()` and do not map OpenAI endpoints from `MapDevUI()`
* Fix comment wording
* Revise documentation
---------
Co-authored-by: Daniel Roth <daroth@microsoft.com>
* Python: DevUI: Add OpenAI Responses API proxy support + HIL for Workflows (#1737)
* DevUI: Add OpenAI Responses API proxy support with enhanced UI features
This commit adds support for proxying requests to OpenAI's Responses API,
allowing DevUI to route conversations to OpenAI models when configured to enable testing.
Backend changes:
- Add OpenAI proxy executor with conversation routing logic
- Enhance event mapper to support OpenAI Responses API format
- Extend server endpoints to handle OpenAI proxy mode
- Update models with OpenAI-specific response types
- Remove emojis from logging and CLI output for cleaner text
Frontend changes:
- Add settings modal with OpenAI proxy configuration UI
- Enhance agent and workflow views with improved state management
- Add new UI components (separator, switch) for settings
- Update debug panel with better event filtering
- Improve message renderers for OpenAI content types
- Update types and API client for OpenAI integration
* update ui, settings modal and workflow input form, add register cleanup hooks.
* add workflow HIL support, user mode, other fixes
* feat(devui): add human-in-the-loop (HIL) support with dynamic response schemas
Implement HIL workflow support allowing workflows to pause for user input
with dynamically generated JSON schemas based on response handler type hints.
Key Features:
- Automatic response schema extraction from @response_handler decorators
- Dynamic form generation in UI based on Pydantic/dataclass response types
- Checkpoint-based conversation storage for HIL requests/responses
- Resume workflow execution after user provides HIL response
Backend Changes:
- Add extract_response_type_from_executor() to introspect response handlers
- Enrich RequestInfoEvent with response_schema via _enrich_request_info_event_with_response_schema()
- Map RequestInfoEvent to response.input.requested OpenAI event format
- Store HIL responses in conversation history and restore checkpoints
Frontend Changes:
- Add HILInputModal component with SchemaFormRenderer for dynamic forms
- Support Pydantic BaseModel and dataclass response types
- Render enum fields as dropdowns, strings as text/textarea, numbers, booleans, arrays, objects
- Display original request context alongside response form
Testing:
- Add tests for checkpoint storage (test_checkpoints.py)
- Add schema generation tests for all input types (test_schema_generation.py)
- Validate end-to-end HIL flow with spam workflow sample
This enables workflows to seamlessly pause execution and request structured user input
with type-safe, validated forms generated automatically from response type annotations.
* improve HIL support, improve workflow execution view
* ui updates
* ui updates
* improve HIL for workflows, add auth and view modes
* update workflow
* security improvements , ui fixes
* fix mypy error
* update loading spinner in ui
---------
Co-authored-by: Mark Wallace <127216156+markwallace-microsoft@users.noreply.github.com>
* .NET: Remove launchSettings.json from .gitignore in dotnet/samples (#2006)
* Remove launchSettings.json from .gitignore in dotnet/samples
* Update dotnet/samples/GettingStarted/DevUI/DevUI_Step01_BasicUsage/Properties/launchSettings.json
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update dotnet/samples/AGUIClientServer/AGUIServer/Properties/launchSettings.json
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* DevUI: Serialize workflow input as string to maintain conformance with OpenAI Responses format (#2021)
Co-authored-by: Victor Dibia <chuvidi2003@gmail.com>
* Add Microsoft Agent Framework logo to assets (#2007)
* Updated package versions (#2027)
* DevUI: Prevent line breaks within words in the agent view (#2024)
Co-authored-by: Victor Dibia <chuvidi2003@gmail.com>
* .NET [AG-UI]: Adds support for shared state. (#1996)
* Product changes
* Tests
* Dojo project
* Cleanups
* Python: Fix underlying tool choice bug and all for return to previous Handoff subagent (#2037)
* Fix tool_choice override bug and add enable_return_to_previous support
* Add unit test for handoff checkpointing
* Handle tools when we have them
* added missing chatAgent params (#2044)
* .NET: fix ChatCompletions Tools serialization (#2043)
* fix serialization in chat completions on tools
* nit
* .NET: assign AgentCard's URL to mapped-endpoint if not defined explicitly (#2047)
* fix serialization in chat completions on tools
* nit
* write e2e test for agent card resolve + adjust behavior
* nit
* Version 1.0.0-preview.251110.1 (#2048)
* .NET: Remove moved OpenAPI sample and point to SK one. (#1997)
* Remove moved OpenAPI sample and point to SK one.
* Update dotnet/samples/GettingStarted/Agents/README.md
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Bump AWSSDK.Extensions.Bedrock.MEAI from 4.0.4.2 to 4.0.4.6 (#2031)
---
updated-dependencies:
- dependency-name: AWSSDK.Extensions.Bedrock.MEAI
dependency-version: 4.0.4.6
dependency-type: direct:production
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* .NET: Separate all memory and rag samples into their own folders (#2000)
* Separate all memory and rag samples into their own folders
* Fix broken link.
* Python: .Net: Dotnet devui compatibility fixes (#2026)
* DevUI: Add OpenAI Responses API proxy support with enhanced UI features
This commit adds support for proxying requests to OpenAI's Responses API,
allowing DevUI to route conversations to OpenAI models when configured to enable testing.
Backend changes:
- Add OpenAI proxy executor with conversation routing logic
- Enhance event mapper to support OpenAI Responses API format
- Extend server endpoints to handle OpenAI proxy mode
- Update models with OpenAI-specific response types
- Remove emojis from logging and CLI output for cleaner text
Frontend changes:
- Add settings modal with OpenAI proxy configuration UI
- Enhance agent and workflow views with improved state management
- Add new UI components (separator, switch) for settings
- Update debug panel with better event filtering
- Improve message renderers for OpenAI content types
- Update types and API client for OpenAI integration
* update ui, settings modal and workflow input form, add register cleanup hooks.
* add workflow HIL support, user mode, other fixes
* feat(devui): add human-in-the-loop (HIL) support with dynamic response schemas
Implement HIL workflow support allowing workflows to pause for user input
with dynamically generated JSON schemas based on response handler type hints.
Key Features:
- Automatic response schema extraction from @response_handler decorators
- Dynamic form generation in UI based on Pydantic/dataclass response types
- Checkpoint-based conversation storage for HIL requests/responses
- Resume workflow execution after user provides HIL response
Backend Changes:
- Add extract_response_type_from_executor() to introspect response handlers
- Enrich RequestInfoEvent with response_schema via _enrich_request_info_event_with_response_schema()
- Map RequestInfoEvent to response.input.requested OpenAI event format
- Store HIL responses in conversation history and restore checkpoints
Frontend Changes:
- Add HILInputModal component with SchemaFormRenderer for dynamic forms
- Support Pydantic BaseModel and dataclass response types
- Render enum fields as dropdowns, strings as text/textarea, numbers, booleans, arrays, objects
- Display original request context alongside response form
Testing:
- Add tests for checkpoint storage (test_checkpoints.py)
- Add schema generation tests for all input types (test_schema_generation.py)
- Validate end-to-end HIL flow with spam workflow sample
This enables workflows to seamlessly pause execution and request structured user input
with type-safe, validated forms generated automatically from response type annotations.
* improve HIL support, improve workflow execution view
* ui updates
* ui updates
* improve HIL for workflows, add auth and view modes
* update workflow
* security improvements , ui fixes
* fix mypy error
* update loading spinner in ui
* DevUI: Serialize workflow input as string to maintain conformance with OpenAI Responses format
* Phase 1: Add /meta endpoint and fix workflow event naming for .NET DevUI compatibility
* additional fixes for .NET DevUI workflow visualization item ID tracking
**Problem:**
.NET DevUI was generating different item IDs for ExecutorInvokedEvent and
ExecutorCompletedEvent, causing only the first executor to highlight in the
workflow graph. Long executor names and error messages also broke UI layout.
**Changes:**
- Add ExecutorActionItemResource to match Python DevUI implementation
- Track item IDs per executor using dictionary in AgentRunResponseUpdateExtensions
- Reuse same item ID across invoked/completed/failed events for proper pairing
- Add truncateText() utility to workflow-utils.ts
- Truncate executor names to 35 chars in execution timeline
- Truncate error messages to 150 chars in workflow graph nodes
** Details:**
- ExecutorActionItemResource registered with JSON source generation context
- Dictionary cleaned up after executor completion/failure to prevent memory leaks
- Frontend item tracking by unique item.id supports multiple executor runs
- All changes follow existing codebase patterns and conventions
Tested with review-workflow showing correct executor highlighting and state
transitions for sequential and concurrent executors.
* format fixes, remove cors tests
* remove unecessary attributes
---------
Co-authored-by: Mark Wallace <127216156+markwallace-microsoft@users.noreply.github.com>
Co-authored-by: Reuben Bond <reuben.bond@gmail.com>
* DevUI: support having both an agent and a workflow with the same id in discovery (#2023)
* Python: Fix Model ID attribute not showing up in `invoke_agent` span (#2061)
* Best effort to surface the model id to invoke agent span
* Fix tests
* Fix tests
* Version 1.0.0-preview.251107.2 (#2065)
* Version 1.0.0-preview.251110.2 (#2067)
* Update README.md to change Grafana links to Azure portal links for dashboard access (#1983)
* .NET - Enable build & test on branch `feature-foundry-agents` (#2068)
* Tests good, mkay
* Update .github/workflows/dotnet-build-and-test.yml
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Enable feature build pipelines
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com>
* Python: Add concrete AGUIChatClient (#2072)
* Add concrete AGUIChatClient
* Update logging docstrings and conventions
* PR feedback
* Updates to support client-side tool calls
* .NET: Move catalog samples to the HostedAgents folder (#2090)
* move catalog samples to the HostedAgents folder
* move the catalog samples' projects to the HostedAgents folder
* Bump OpenTelemetry.Instrumentation.Runtime from 1.12.0 to 1.13.0 (#1856)
---
updated-dependencies:
- dependency-name: OpenTelemetry.Instrumentation.Runtime
dependency-version: 1.13.0
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* .NET: Bump Microsoft.SemanticKernel.Agents.Abstractions from 1.66.0 to 1.67.0 (#1962)
* Bump Microsoft.SemanticKernel.Agents.Abstractions from 1.66.0 to 1.67.0
---
updated-dependencies:
- dependency-name: Microsoft.SemanticKernel.Agents.Abstractions
dependency-version: 1.67.0
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
* .NET: Bump all Microsoft.SemanticKernel packages from 1.66.* to 1.67.* (#1969)
* Initial plan
* Update all Microsoft.SemanticKernel packages to 1.67.*
Co-authored-by: rogerbarreto <19890735+rogerbarreto@users.noreply.github.com>
* Remove unrelated changes to package-lock.json and yarn.lock
Co-authored-by: markwallace-microsoft <127216156+markwallace-microsoft@users.noreply.github.com>
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: rogerbarreto <19890735+rogerbarreto@users.noreply.github.com>
Co-authored-by: markwallace-microsoft <127216156+markwallace-microsoft@users.noreply.github.com>
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: rogerbarreto <19890735+rogerbarreto@users.noreply.github.com>
Co-authored-by: markwallace-microsoft <127216156+markwallace-microsoft@users.noreply.github.com>
* .NET: fix: WorkflowAsAgent Sample (#1787)
* fix: WorkflowAsAgent Sample
* Also makes ChatForwardingExecutor public
* feat: Expand ChatForwardingExecutor handled types
Make ChatForwardingExecutor match the input types of ChatProtocolExecutor.
* fix: Update for the new AgentRunResponseUpdate merge logic
AIAgent always sends out List<ChatMessage> now.
* Updated (#2076)
* Bump vite in /python/samples/demos/chatkit-integration/frontend (#1918)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 7.1.9 to 7.1.12.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v7.1.12/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v7.1.12/packages/vite)
---
updated-dependencies:
- dependency-name: vite
dependency-version: 7.1.12
dependency-type: direct:development
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* Bump Roslynator.Analyzers from 4.14.0 to 4.14.1 (#1857)
---
updated-dependencies:
- dependency-name: Roslynator.Analyzers
dependency-version: 4.14.1
dependency-type: direct:production
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* Bump MishaKav/pytest-coverage-comment from 1.1.57 to 1.1.59 (#2034)
Bumps [MishaKav/pytest-coverage-comment](https://github.com/mishakav/pytest-coverage-comment) from 1.1.57 to 1.1.59.
- [Release notes](https://github.com/mishakav/pytest-coverage-comment/releases)
- [Changelog](https://github.com/MishaKav/pytest-coverage-comment/blob/main/CHANGELOG.md)
- [Commits](https://github.com/mishakav/pytest-coverage-comment/compare/v1.1.57...v1.1.59)
---
updated-dependencies:
- dependency-name: MishaKav/pytest-coverage-comment
dependency-version: 1.1.59
dependency-type: direct:production
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Chris <66376200+crickman@users.noreply.github.com>
* Python: Handle agent user input request in AgentExecutor (#2022)
* Handle agent user input request in AgentExecutor
* fix test
* Address comments
* Fix tests
* Fix tests
* Address comments
* Address comments
* Python: OpenAI Responses Image Generation Stream Support, Sample and Unit Tests (#1853)
* support for image gen streaming
* small fixes
* fixes
* added comment
* Python: Fix MCP Tool Parameter Descriptions Not Propagated to LLMs (#1978)
* mcp tool description fix
* small fix
* .NET: Allow extending agent run options via additional properties (#1872)
* Allow extending agent run options via additional properties
This mirrors the M.E.AI model in ChatOptions.AdditionalProperties which is very useful when building functionality pipelines.
Fixes https://github.com/microsoft/agent-framework/issues/1815
* Expand XML documentation
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Add AdditionalProperties tests to AgentRunOptions
Co-authored-by: kzu <169707+kzu@users.noreply.github.com>
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: kzu <169707+kzu@users.noreply.github.com>
* Python: Use the last entry in the task history to avoid empty responses (#2101)
* Use the last entry in the task history to avoid empty responses
* History only contains Messages
* Updated package versions (#2104)
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Reuben Bond <203839+ReubenBond@users.noreply.github.com>
Co-authored-by: Peter Ibekwe <109177538+peibekwe@users.noreply.github.com>
Co-authored-by: Jeff Handley <jeffhandley@users.noreply.github.com>
Co-authored-by: Daniel Roth <daroth@microsoft.com>
Co-authored-by: Victor Dibia <chuvidi2003@gmail.com>
Co-authored-by: Mark Wallace <127216156+markwallace-microsoft@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Shawn Henry <sphenry@gmail.com>
Co-authored-by: Javier Calvarro Nelson <jacalvar@microsoft.com>
Co-authored-by: Evan Mattson <35585003+moonbox3@users.noreply.github.com>
Co-authored-by: Eduard van Valkenburg <eavanvalkenburg@users.noreply.github.com>
Co-authored-by: Korolev Dmitry <deagle.gross@gmail.com>
Co-authored-by: westey <164392973+westey-m@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Reuben Bond <reuben.bond@gmail.com>
Co-authored-by: Tao Chen <taochen@microsoft.com>
Co-authored-by: wuweng <wuweng@microsoft.com>
Co-authored-by: Chris <66376200+crickman@users.noreply.github.com>
Co-authored-by: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com>
Co-authored-by: SergeyMenshykh <68852919+SergeyMenshykh@users.noreply.github.com>
Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Jacob Alber <jaalber@microsoft.com>
Co-authored-by: Giles Odigwe <79032838+giles17@users.noreply.github.com>
Co-authored-by: Daniel Cazzulino <daniel@cazzulino.com>
Co-authored-by: kzu <169707+kzu@users.noreply.github.com>
* Updated azure-ai-projects package version and small fixes (#2139)
* Python: [Feature Branch] Resolve CI issues (#2143)
* Small documentation and code fixes
* Small fix in documentation
* Addressed PR feedback
* Added AI Search example
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Evan Mattson <35585003+moonbox3@users.noreply.github.com>
Co-authored-by: Chris <66376200+crickman@users.noreply.github.com>
Co-authored-by: Reuben Bond <203839+ReubenBond@users.noreply.github.com>
Co-authored-by: Peter Ibekwe <109177538+peibekwe@users.noreply.github.com>
Co-authored-by: Jeff Handley <jeffhandley@users.noreply.github.com>
Co-authored-by: Daniel Roth <daroth@microsoft.com>
Co-authored-by: Victor Dibia <chuvidi2003@gmail.com>
Co-authored-by: Mark Wallace <127216156+markwallace-microsoft@users.noreply.github.com>
Co-authored-by: Shawn Henry <sphenry@gmail.com>
Co-authored-by: Javier Calvarro Nelson <jacalvar@microsoft.com>
Co-authored-by: Eduard van Valkenburg <eavanvalkenburg@users.noreply.github.com>
Co-authored-by: Korolev Dmitry <deagle.gross@gmail.com>
Co-authored-by: westey <164392973+westey-m@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Reuben Bond <reuben.bond@gmail.com>
Co-authored-by: Tao Chen <taochen@microsoft.com>
Co-authored-by: wuweng <wuweng@microsoft.com>
Co-authored-by: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com>
Co-authored-by: SergeyMenshykh <68852919+SergeyMenshykh@users.noreply.github.com>
Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Jacob Alber <jaalber@microsoft.com>
Co-authored-by: Giles Odigwe <79032838+giles17@users.noreply.github.com>
Co-authored-by: Daniel Cazzulino <daniel@cazzulino.com>
Co-authored-by: kzu <169707+kzu@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
Unverified
parent
4bffe1ebc8
commit
edb367a2b9
@@ -0,0 +1,69 @@
|
||||
# Azure AI Agent Examples
|
||||
|
||||
This folder contains examples demonstrating different ways to create and use agents with the Azure AI chat client from the `agent_framework.azure` package.
|
||||
|
||||
## Examples
|
||||
|
||||
| File | Description |
|
||||
|------|-------------|
|
||||
| [`azure_ai_basic.py`](azure_ai_basic.py) | The simplest way to create an agent using `ChatAgent` with `AzureAIAgentClient`. It automatically handles all configuration using environment variables. |
|
||||
| [`azure_ai_with_bing_grounding.py`](azure_ai_with_bing_grounding.py) | Shows how to use Bing Grounding search with Azure AI agents to find real-time information from the web. Demonstrates web search capabilities with proper source citations and comprehensive error handling. |
|
||||
| [`azure_ai_with_code_interpreter.py`](azure_ai_with_code_interpreter.py) | Shows how to use the HostedCodeInterpreterTool with Azure AI agents to write and execute Python code. Includes helper methods for accessing code interpreter data from response chunks. |
|
||||
| [`azure_ai_with_existing_agent.py`](azure_ai_with_existing_agent.py) | Shows how to work with a pre-existing agent by providing the agent ID to the Azure AI chat client. This example also demonstrates proper cleanup of manually created agents. |
|
||||
| [`azure_ai_with_existing_thread.py`](azure_ai_with_existing_thread.py) | Shows how to work with a pre-existing thread by providing the thread ID to the Azure AI chat client. This example also demonstrates proper cleanup of manually created threads. |
|
||||
| [`azure_ai_with_explicit_settings.py`](azure_ai_with_explicit_settings.py) | Shows how to create an agent with explicitly configured `AzureAIAgentClient` settings, including project endpoint, model deployment, credentials, and agent name. |
|
||||
| [`azure_ai_with_azure_ai_search.py`](azure_ai_with_azure_ai_search.py) | Demonstrates how to use Azure AI Search with Azure AI agents to search through indexed data. Shows how to configure search parameters, query types, and integrate with existing search indexes. |
|
||||
| [`azure_ai_with_file_search.py`](azure_ai_with_file_search.py) | Demonstrates how to use the HostedFileSearchTool with Azure AI agents to search through uploaded documents. Shows file upload, vector store creation, and querying document content. Includes both streaming and non-streaming examples. |
|
||||
| [`azure_ai_with_function_tools.py`](azure_ai_with_function_tools.py) | Demonstrates how to use function tools with agents. Shows both agent-level tools (defined when creating the agent) and query-level tools (provided with specific queries). |
|
||||
| [`azure_ai_with_hosted_mcp.py`](azure_ai_with_hosted_mcp.py) | Shows how to integrate Azure AI agents with hosted Model Context Protocol (MCP) servers for enhanced functionality and tool integration. Demonstrates remote MCP server connections and tool discovery. |
|
||||
| [`azure_ai_with_local_mcp.py`](azure_ai_with_local_mcp.py) | Shows how to integrate Azure AI agents with local Model Context Protocol (MCP) servers for enhanced functionality and tool integration. Demonstrates both agent-level and run-level tool configuration. |
|
||||
| [`azure_ai_with_multiple_tools.py`](azure_ai_with_multiple_tools.py) | Demonstrates how to use multiple tools together with Azure AI agents, including web search, MCP servers, and function tools. Shows coordinated multi-tool interactions and approval workflows. |
|
||||
| [`azure_ai_with_openapi_tools.py`](azure_ai_with_openapi_tools.py) | Demonstrates how to use OpenAPI tools with Azure AI agents to integrate external REST APIs. Shows OpenAPI specification loading, anonymous authentication, thread context management, and coordinated multi-API conversations using weather and countries APIs. |
|
||||
| [`azure_ai_with_thread.py`](azure_ai_with_thread.py) | Demonstrates thread management with Azure AI agents, including automatic thread creation for stateless conversations and explicit thread management for maintaining conversation context across multiple interactions. |
|
||||
|
||||
## Environment Variables
|
||||
|
||||
Before running the examples, you need to set up your environment variables. You can do this in one of two ways:
|
||||
|
||||
### Option 1: Using a .env file (Recommended)
|
||||
|
||||
1. Copy the `.env.example` file from the `python` directory to create a `.env` file:
|
||||
```bash
|
||||
cp ../../.env.example ../../.env
|
||||
```
|
||||
|
||||
2. Edit the `.env` file and add your values:
|
||||
```
|
||||
AZURE_AI_PROJECT_ENDPOINT="your-project-endpoint"
|
||||
AZURE_AI_MODEL_DEPLOYMENT_NAME="your-model-deployment-name"
|
||||
```
|
||||
|
||||
3. For samples using Bing Grounding search (like `azure_ai_with_bing_grounding.py` and `azure_ai_with_multiple_tools.py`), you'll also need:
|
||||
```
|
||||
BING_CONNECTION_ID="your-bing-connection-id"
|
||||
```
|
||||
|
||||
To get your Bing connection details:
|
||||
- Go to [Azure AI Foundry portal](https://ai.azure.com)
|
||||
- Navigate to your project's "Connected resources" section
|
||||
- Add a new connection for "Grounding with Bing Search"
|
||||
- Copy the ID
|
||||
|
||||
### Option 2: Using environment variables directly
|
||||
|
||||
Set the environment variables in your shell:
|
||||
|
||||
```bash
|
||||
export AZURE_AI_PROJECT_ENDPOINT="your-project-endpoint"
|
||||
export AZURE_AI_MODEL_DEPLOYMENT_NAME="your-model-deployment-name"
|
||||
export BING_CONNECTION_ID="your-bing-connection-id"
|
||||
```
|
||||
|
||||
### Required Variables
|
||||
|
||||
- `AZURE_AI_PROJECT_ENDPOINT`: Your Azure AI project endpoint (required for all examples)
|
||||
- `AZURE_AI_MODEL_DEPLOYMENT_NAME`: The name of your model deployment (required for all examples)
|
||||
|
||||
### Optional Variables
|
||||
|
||||
- `BING_CONNECTION_ID`: Your Bing connection ID (required for `azure_ai_with_bing_grounding.py` and `azure_ai_with_multiple_tools.py`)
|
||||
@@ -0,0 +1,82 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
from random import randint
|
||||
from typing import Annotated
|
||||
|
||||
from agent_framework.azure import AzureAIAgentClient
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
from pydantic import Field
|
||||
|
||||
"""
|
||||
Azure AI Agent Basic Example
|
||||
|
||||
This sample demonstrates basic usage of AzureAIAgentClient to create agents with automatic
|
||||
lifecycle management. Shows both streaming and non-streaming responses with function tools.
|
||||
"""
|
||||
|
||||
|
||||
def get_weather(
|
||||
location: Annotated[str, Field(description="The location to get the weather for.")],
|
||||
) -> str:
|
||||
"""Get the weather for a given location."""
|
||||
conditions = ["sunny", "cloudy", "rainy", "stormy"]
|
||||
return f"The weather in {location} is {conditions[randint(0, 3)]} with a high of {randint(10, 30)}°C."
|
||||
|
||||
|
||||
async def non_streaming_example() -> None:
|
||||
"""Example of non-streaming response (get the complete result at once)."""
|
||||
print("=== Non-streaming Response Example ===")
|
||||
|
||||
# Since no Agent ID is provided, the agent will be automatically created
|
||||
# and deleted after getting a response
|
||||
# For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred
|
||||
# authentication option.
|
||||
async with (
|
||||
AzureCliCredential() as credential,
|
||||
AzureAIAgentClient(async_credential=credential).create_agent(
|
||||
name="WeatherAgent",
|
||||
instructions="You are a helpful weather agent.",
|
||||
tools=get_weather,
|
||||
) as agent,
|
||||
):
|
||||
query = "What's the weather like in Seattle?"
|
||||
print(f"User: {query}")
|
||||
result = await agent.run(query)
|
||||
print(f"Agent: {result}\n")
|
||||
|
||||
|
||||
async def streaming_example() -> None:
|
||||
"""Example of streaming response (get results as they are generated)."""
|
||||
print("=== Streaming Response Example ===")
|
||||
|
||||
# Since no Agent ID is provided, the agent will be automatically created
|
||||
# and deleted after getting a response
|
||||
# For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred
|
||||
# authentication option.
|
||||
async with (
|
||||
AzureCliCredential() as credential,
|
||||
AzureAIAgentClient(async_credential=credential).create_agent(
|
||||
name="WeatherAgent",
|
||||
instructions="You are a helpful weather agent.",
|
||||
tools=get_weather,
|
||||
) as agent,
|
||||
):
|
||||
query = "What's the weather like in Portland?"
|
||||
print(f"User: {query}")
|
||||
print("Agent: ", end="", flush=True)
|
||||
async for chunk in agent.run_stream(query):
|
||||
if chunk.text:
|
||||
print(chunk.text, end="", flush=True)
|
||||
print("\n")
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
print("=== Basic Azure AI Chat Client Agent Example ===")
|
||||
|
||||
await non_streaming_example()
|
||||
await streaming_example()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
|
||||
from agent_framework import ChatAgent, CitationAnnotation
|
||||
from agent_framework.azure import AzureAIAgentClient
|
||||
from azure.ai.agents.aio import AgentsClient
|
||||
from azure.ai.projects.aio import AIProjectClient
|
||||
from azure.ai.projects.models import ConnectionType
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
|
||||
"""
|
||||
Azure AI Agent with Azure AI Search Example
|
||||
|
||||
This sample demonstrates how to create an Azure AI agent that uses Azure AI Search
|
||||
to search through indexed hotel data and answer user questions about hotels.
|
||||
|
||||
Prerequisites:
|
||||
1. Set AZURE_AI_PROJECT_ENDPOINT and AZURE_AI_MODEL_DEPLOYMENT_NAME environment variables
|
||||
2. Ensure you have an Azure AI Search connection configured in your Azure AI project
|
||||
3. The search index "hotels-sample-index" should exist in your Azure AI Search service
|
||||
(you can create this using the Azure portal with sample hotel data)
|
||||
|
||||
NOTE: To ensure consistent search tool usage:
|
||||
- Include explicit instructions for the agent to use the search tool
|
||||
- Mention the search requirement in your queries
|
||||
- Use `tool_choice="required"` to force tool usage
|
||||
|
||||
More info on `query type` can be found here:
|
||||
https://learn.microsoft.com/en-us/python/api/azure-ai-agents/azure.ai.agents.models.aisearchindexresource?view=azure-python-preview
|
||||
"""
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
"""Main function demonstrating Azure AI agent with raw Azure AI Search tool."""
|
||||
print("=== Azure AI Agent with Raw Azure AI Search Tool ===")
|
||||
|
||||
# Create the client and manually create an agent with Azure AI Search tool
|
||||
async with (
|
||||
AzureCliCredential() as credential,
|
||||
AIProjectClient(endpoint=os.environ["AZURE_AI_PROJECT_ENDPOINT"], credential=credential) as project_client,
|
||||
AgentsClient(endpoint=os.environ["AZURE_AI_PROJECT_ENDPOINT"], credential=credential) as agents_client,
|
||||
):
|
||||
ai_search_conn_id = ""
|
||||
async for connection in project_client.connections.list():
|
||||
if connection.type == ConnectionType.AZURE_AI_SEARCH:
|
||||
ai_search_conn_id = connection.id
|
||||
break
|
||||
|
||||
# 1. Create Azure AI agent with the search tool
|
||||
azure_ai_agent = await agents_client.create_agent(
|
||||
model=os.environ["AZURE_AI_MODEL_DEPLOYMENT_NAME"],
|
||||
name="HotelSearchAgent",
|
||||
instructions=(
|
||||
"You are a helpful agent that searches hotel information using Azure AI Search. "
|
||||
"Always use the search tool and index to find hotel data and provide accurate information."
|
||||
),
|
||||
tools=[{"type": "azure_ai_search"}],
|
||||
tool_resources={
|
||||
"azure_ai_search": {
|
||||
"indexes": [
|
||||
{
|
||||
"index_connection_id": ai_search_conn_id,
|
||||
"index_name": "hotels-sample-index",
|
||||
"query_type": "vector",
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
# 2. Create chat client with the existing agent
|
||||
chat_client = AzureAIAgentClient(agents_client=agents_client, agent_id=azure_ai_agent.id)
|
||||
|
||||
try:
|
||||
async with ChatAgent(
|
||||
chat_client=chat_client,
|
||||
# Additional instructions for this specific conversation
|
||||
instructions=("You are a helpful agent that uses the search tool and index to find hotel information."),
|
||||
) as agent:
|
||||
print("This agent uses raw Azure AI Search tool to search hotel data.\n")
|
||||
|
||||
# 3. Simulate conversation with the agent
|
||||
user_input = (
|
||||
"Use Azure AI search knowledge tool to find detailed information about a winter hotel."
|
||||
" Use the search tool and index." # You can modify prompt to force tool usage
|
||||
)
|
||||
print(f"User: {user_input}")
|
||||
print("Agent: ", end="", flush=True)
|
||||
|
||||
# Stream the response and collect citations
|
||||
citations: list[CitationAnnotation] = []
|
||||
async for chunk in agent.run_stream(user_input):
|
||||
if chunk.text:
|
||||
print(chunk.text, end="", flush=True)
|
||||
|
||||
# Collect citations from Azure AI Search responses
|
||||
for content in getattr(chunk, "contents", []):
|
||||
annotations = getattr(content, "annotations", [])
|
||||
if annotations:
|
||||
citations.extend(annotations)
|
||||
|
||||
print()
|
||||
|
||||
# Display collected citations
|
||||
if citations:
|
||||
print("\n\nCitations:")
|
||||
for i, citation in enumerate(citations, 1):
|
||||
print(f"[{i}] Reference: {citation.url}")
|
||||
|
||||
print("\n" + "=" * 50 + "\n")
|
||||
print("Hotel search conversation completed!")
|
||||
|
||||
finally:
|
||||
# Clean up the agent manually
|
||||
await agents_client.delete_agent(azure_ai_agent.id)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,59 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
|
||||
from agent_framework import ChatAgent, HostedWebSearchTool
|
||||
from agent_framework_azure_ai import AzureAIAgentClient
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
|
||||
"""
|
||||
The following sample demonstrates how to create an Azure AI agent that
|
||||
uses Bing Grounding search to find real-time information from the web.
|
||||
|
||||
Prerequisites:
|
||||
1. A connected Grounding with Bing Search resource in your Azure AI project
|
||||
2. Set BING_CONNECTION_ID environment variable
|
||||
Example: BING_CONNECTION_ID="your-bing-connection-id"
|
||||
|
||||
To set up Bing Grounding:
|
||||
1. Go to Azure AI Foundry portal (https://ai.azure.com)
|
||||
2. Navigate to your project's "Connected resources" section
|
||||
3. Add a new connection for "Grounding with Bing Search"
|
||||
4. Copy either the connection name or ID and set the appropriate environment variable
|
||||
"""
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
"""Main function demonstrating Azure AI agent with Bing Grounding search."""
|
||||
# 1. Create Bing Grounding search tool using HostedWebSearchTool
|
||||
# The connection ID will be automatically picked up from environment variable
|
||||
bing_search_tool = HostedWebSearchTool(
|
||||
name="Bing Grounding Search",
|
||||
description="Search the web for current information using Bing",
|
||||
)
|
||||
|
||||
# 2. Use AzureAIAgentClient as async context manager for automatic cleanup
|
||||
async with (
|
||||
AzureAIAgentClient(async_credential=AzureCliCredential()) as client,
|
||||
ChatAgent(
|
||||
chat_client=client,
|
||||
name="BingSearchAgent",
|
||||
instructions=(
|
||||
"You are a helpful assistant that can search the web for current information. "
|
||||
"Use the Bing search tool to find up-to-date information and provide accurate, "
|
||||
"well-sourced answers. Always cite your sources when possible."
|
||||
),
|
||||
tools=bing_search_tool,
|
||||
) as agent,
|
||||
):
|
||||
# 4. Demonstrate agent capabilities with web search
|
||||
print("=== Azure AI Agent with Bing Grounding Search ===\n")
|
||||
|
||||
user_input = "What is the most popular programming language?"
|
||||
print(f"User: {user_input}")
|
||||
response = await agent.run(user_input)
|
||||
print(f"Agent: {response.text}\n")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
|
||||
from agent_framework import AgentRunResponse, ChatResponseUpdate, HostedCodeInterpreterTool
|
||||
from agent_framework.azure import AzureAIAgentClient
|
||||
from azure.ai.agents.models import (
|
||||
RunStepDeltaCodeInterpreterDetailItemObject,
|
||||
)
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
|
||||
"""
|
||||
Azure AI Agent with Code Interpreter Example
|
||||
|
||||
This sample demonstrates using HostedCodeInterpreterTool with Azure AI Agents
|
||||
for Python code execution and mathematical problem solving.
|
||||
"""
|
||||
|
||||
|
||||
def print_code_interpreter_inputs(response: AgentRunResponse) -> None:
|
||||
"""Helper method to access code interpreter data."""
|
||||
|
||||
print("\nCode Interpreter Inputs during the run:")
|
||||
if response.raw_representation is None:
|
||||
return
|
||||
for chunk in response.raw_representation:
|
||||
if isinstance(chunk, ChatResponseUpdate) and isinstance(
|
||||
chunk.raw_representation, RunStepDeltaCodeInterpreterDetailItemObject
|
||||
):
|
||||
print(chunk.raw_representation.input, end="")
|
||||
print("\n")
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
"""Example showing how to use the HostedCodeInterpreterTool with Azure AI."""
|
||||
print("=== Azure AI Agent with Code Interpreter Example ===")
|
||||
|
||||
# For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred
|
||||
# authentication option.
|
||||
async with (
|
||||
AzureCliCredential() as credential,
|
||||
AzureAIAgentClient(async_credential=credential) as chat_client,
|
||||
):
|
||||
agent = chat_client.create_agent(
|
||||
name="CodingAgent",
|
||||
instructions=("You are a helpful assistant that can write and execute Python code to solve problems."),
|
||||
tools=HostedCodeInterpreterTool(),
|
||||
)
|
||||
query = "Generate the factorial of 100 using python code, show the code and execute it."
|
||||
print(f"User: {query}")
|
||||
response = await AgentRunResponse.from_agent_response_generator(agent.run_stream(query))
|
||||
print(f"Agent: {response}")
|
||||
# To review the code interpreter outputs, you can access
|
||||
# them from the response raw_representations, just uncomment the next line:
|
||||
# print_code_interpreter_inputs(response)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,57 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
|
||||
from agent_framework import ChatAgent
|
||||
from agent_framework.azure import AzureAIAgentClient
|
||||
from azure.ai.agents.aio import AgentsClient
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
|
||||
"""
|
||||
Azure AI Agent with Existing Agent Example
|
||||
|
||||
This sample demonstrates working with pre-existing Azure AI Agents by providing
|
||||
agent IDs, showing agent reuse patterns for production scenarios.
|
||||
"""
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
print("=== Azure AI Chat Client with Existing Agent ===")
|
||||
|
||||
# Create the client
|
||||
async with (
|
||||
AzureCliCredential() as credential,
|
||||
AgentsClient(endpoint=os.environ["AZURE_AI_PROJECT_ENDPOINT"], credential=credential) as agents_client,
|
||||
):
|
||||
azure_ai_agent = await agents_client.create_agent(
|
||||
model=os.environ["AZURE_AI_MODEL_DEPLOYMENT_NAME"],
|
||||
# Create remote agent with default instructions
|
||||
# These instructions will persist on created agent for every run.
|
||||
instructions="End each response with [END].",
|
||||
)
|
||||
|
||||
chat_client = AzureAIAgentClient(agents_client=agents_client, agent_id=azure_ai_agent.id)
|
||||
|
||||
try:
|
||||
async with ChatAgent(
|
||||
chat_client=chat_client,
|
||||
# Instructions here are applicable only to this ChatAgent instance
|
||||
# These instructions will be combined with instructions on existing remote agent.
|
||||
# The final instructions during the execution will look like:
|
||||
# "'End each response with [END]. Respond with 'Hello World' only'"
|
||||
instructions="Respond with 'Hello World' only",
|
||||
) as agent:
|
||||
query = "How are you?"
|
||||
print(f"User: {query}")
|
||||
result = await agent.run(query)
|
||||
# Based on local and remote instructions, the result will be
|
||||
# 'Hello World [END]'.
|
||||
print(f"Agent: {result}\n")
|
||||
finally:
|
||||
# Clean up the agent manually
|
||||
await agents_client.delete_agent(azure_ai_agent.id)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,59 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
from random import randint
|
||||
from typing import Annotated
|
||||
|
||||
from agent_framework import ChatAgent
|
||||
from agent_framework.azure import AzureAIAgentClient
|
||||
from azure.ai.agents.aio import AgentsClient
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
from pydantic import Field
|
||||
|
||||
"""
|
||||
Azure AI Agent with Existing Thread Example
|
||||
|
||||
This sample demonstrates working with pre-existing conversation threads
|
||||
by providing thread IDs for thread reuse patterns.
|
||||
"""
|
||||
|
||||
|
||||
def get_weather(
|
||||
location: Annotated[str, Field(description="The location to get the weather for.")],
|
||||
) -> str:
|
||||
"""Get the weather for a given location."""
|
||||
conditions = ["sunny", "cloudy", "rainy", "stormy"]
|
||||
return f"The weather in {location} is {conditions[randint(0, 3)]} with a high of {randint(10, 30)}°C."
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
print("=== Azure AI Chat Client with Existing Thread ===")
|
||||
|
||||
# Create the client
|
||||
async with (
|
||||
AzureCliCredential() as credential,
|
||||
AgentsClient(endpoint=os.environ["AZURE_AI_PROJECT_ENDPOINT"], credential=credential) as agents_client,
|
||||
):
|
||||
# Create an thread that will persist
|
||||
created_thread = await agents_client.threads.create()
|
||||
|
||||
try:
|
||||
async with ChatAgent(
|
||||
# passing in the client is optional here, so if you take the agent_id from the portal
|
||||
# you can use it directly without the two lines above.
|
||||
chat_client=AzureAIAgentClient(agents_client=agents_client),
|
||||
instructions="You are a helpful weather agent.",
|
||||
tools=get_weather,
|
||||
) as agent:
|
||||
thread = agent.get_new_thread(service_thread_id=created_thread.id)
|
||||
assert thread.is_initialized
|
||||
result = await agent.run("What's the weather like in Tokyo?", thread=thread)
|
||||
print(f"Result: {result}\n")
|
||||
finally:
|
||||
# Clean up the thread manually
|
||||
await agents_client.threads.delete(created_thread.id)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
from random import randint
|
||||
from typing import Annotated
|
||||
|
||||
from agent_framework import ChatAgent
|
||||
from agent_framework.azure import AzureAIAgentClient
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
from pydantic import Field
|
||||
|
||||
"""
|
||||
Azure AI Agent with Explicit Settings Example
|
||||
|
||||
This sample demonstrates creating Azure AI Agents with explicit configuration
|
||||
settings rather than relying on environment variable defaults.
|
||||
"""
|
||||
|
||||
|
||||
def get_weather(
|
||||
location: Annotated[str, Field(description="The location to get the weather for.")],
|
||||
) -> str:
|
||||
"""Get the weather for a given location."""
|
||||
conditions = ["sunny", "cloudy", "rainy", "stormy"]
|
||||
return f"The weather in {location} is {conditions[randint(0, 3)]} with a high of {randint(10, 30)}°C."
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
print("=== Azure AI Chat Client with Explicit Settings ===")
|
||||
|
||||
# Since no Agent ID is provided, the agent will be automatically created
|
||||
# and deleted after getting a response
|
||||
# For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred
|
||||
# authentication option.
|
||||
async with (
|
||||
AzureCliCredential() as credential,
|
||||
ChatAgent(
|
||||
chat_client=AzureAIAgentClient(
|
||||
project_endpoint=os.environ["AZURE_AI_PROJECT_ENDPOINT"],
|
||||
model_deployment_name=os.environ["AZURE_AI_MODEL_DEPLOYMENT_NAME"],
|
||||
async_credential=credential,
|
||||
agent_name="WeatherAgent",
|
||||
should_cleanup_agent=True, # Set to False if you want to disable automatic agent cleanup
|
||||
),
|
||||
instructions="You are a helpful weather agent.",
|
||||
tools=get_weather,
|
||||
) as agent,
|
||||
):
|
||||
result = await agent.run("What's the weather like in New York?")
|
||||
print(f"Result: {result}\n")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,91 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
from pathlib import Path
|
||||
|
||||
from agent_framework import ChatAgent, HostedFileSearchTool, HostedVectorStoreContent
|
||||
from agent_framework.azure import AzureAIAgentClient
|
||||
from azure.ai.agents.models import FileInfo, VectorStore
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
|
||||
"""
|
||||
The following sample demonstrates how to create a simple, Azure AI agent that
|
||||
uses a file search tool to answer user questions.
|
||||
"""
|
||||
|
||||
|
||||
# Simulate a conversation with the agent
|
||||
USER_INPUTS = [
|
||||
"Who is the youngest employee?",
|
||||
"Who works in sales?",
|
||||
"I have a customer request, who can help me?",
|
||||
]
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
"""Main function demonstrating Azure AI agent with file search capabilities."""
|
||||
client = AzureAIAgentClient(async_credential=AzureCliCredential())
|
||||
file: FileInfo | None = None
|
||||
vector_store: VectorStore | None = None
|
||||
|
||||
try:
|
||||
# 1. Upload file and create vector store
|
||||
pdf_file_path = Path(__file__).parent.parent / "resources" / "employees.pdf"
|
||||
print(f"Uploading file from: {pdf_file_path}")
|
||||
|
||||
file = await client.agents_client.files.upload_and_poll(file_path=str(pdf_file_path), purpose="assistants")
|
||||
print(f"Uploaded file, file ID: {file.id}")
|
||||
|
||||
vector_store = await client.agents_client.vector_stores.create_and_poll(
|
||||
file_ids=[file.id], name="my_vectorstore"
|
||||
)
|
||||
print(f"Created vector store, vector store ID: {vector_store.id}")
|
||||
|
||||
# 2. Create file search tool with uploaded resources
|
||||
file_search_tool = HostedFileSearchTool(inputs=[HostedVectorStoreContent(vector_store_id=vector_store.id)])
|
||||
|
||||
# 3. Create an agent with file search capabilities
|
||||
# The tool_resources are automatically extracted from HostedFileSearchTool
|
||||
async with ChatAgent(
|
||||
chat_client=client,
|
||||
name="EmployeeSearchAgent",
|
||||
instructions=(
|
||||
"You are a helpful assistant that can search through uploaded employee files "
|
||||
"to answer questions about employees."
|
||||
),
|
||||
tools=file_search_tool,
|
||||
) as agent:
|
||||
# 4. Simulate conversation with the agent
|
||||
for user_input in USER_INPUTS:
|
||||
print(f"# User: '{user_input}'")
|
||||
response = await agent.run(user_input)
|
||||
print(f"# Agent: {response.text}")
|
||||
|
||||
# 5. Cleanup: Delete the vector store and file
|
||||
try:
|
||||
if vector_store:
|
||||
await client.agents_client.vector_stores.delete(vector_store.id)
|
||||
if file:
|
||||
await client.agents_client.files.delete(file.id)
|
||||
except Exception:
|
||||
# Ignore cleanup errors to avoid masking issues
|
||||
pass
|
||||
finally:
|
||||
# 6. Cleanup: Delete the vector store and file in case of earlier failure to prevent orphaned resources.
|
||||
|
||||
# Refreshing the client is required since chat agent closes it
|
||||
client = AzureAIAgentClient(async_credential=AzureCliCredential())
|
||||
try:
|
||||
if vector_store:
|
||||
await client.agents_client.vector_stores.delete(vector_store.id)
|
||||
if file:
|
||||
await client.agents_client.files.delete(file.id)
|
||||
except Exception:
|
||||
# Ignore cleanup errors to avoid masking issues
|
||||
pass
|
||||
finally:
|
||||
await client.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,140 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
from datetime import datetime, timezone
|
||||
from random import randint
|
||||
from typing import Annotated
|
||||
|
||||
from agent_framework import ChatAgent
|
||||
from agent_framework.azure import AzureAIAgentClient
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
from pydantic import Field
|
||||
|
||||
"""
|
||||
Azure AI Agent with Function Tools Example
|
||||
|
||||
This sample demonstrates function tool integration with Azure AI Agents,
|
||||
showing both agent-level and query-level tool configuration patterns.
|
||||
"""
|
||||
|
||||
|
||||
def get_weather(
|
||||
location: Annotated[str, Field(description="The location to get the weather for.")],
|
||||
) -> str:
|
||||
"""Get the weather for a given location."""
|
||||
conditions = ["sunny", "cloudy", "rainy", "stormy"]
|
||||
return f"The weather in {location} is {conditions[randint(0, 3)]} with a high of {randint(10, 30)}°C."
|
||||
|
||||
|
||||
def get_time() -> str:
|
||||
"""Get the current UTC time."""
|
||||
current_time = datetime.now(timezone.utc)
|
||||
return f"The current UTC time is {current_time.strftime('%Y-%m-%d %H:%M:%S')}."
|
||||
|
||||
|
||||
async def tools_on_agent_level() -> None:
|
||||
"""Example showing tools defined when creating the agent."""
|
||||
print("=== Tools Defined on Agent Level ===")
|
||||
|
||||
# Tools are provided when creating the agent
|
||||
# The agent can use these tools for any query during its lifetime
|
||||
# For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred
|
||||
# authentication option.
|
||||
async with (
|
||||
AzureCliCredential() as credential,
|
||||
ChatAgent(
|
||||
chat_client=AzureAIAgentClient(async_credential=credential),
|
||||
instructions="You are a helpful assistant that can provide weather and time information.",
|
||||
tools=[get_weather, get_time], # Tools defined at agent creation
|
||||
) as agent,
|
||||
):
|
||||
# First query - agent can use weather tool
|
||||
query1 = "What's the weather like in New York?"
|
||||
print(f"User: {query1}")
|
||||
result1 = await agent.run(query1)
|
||||
print(f"Agent: {result1}\n")
|
||||
|
||||
# Second query - agent can use time tool
|
||||
query2 = "What's the current UTC time?"
|
||||
print(f"User: {query2}")
|
||||
result2 = await agent.run(query2)
|
||||
print(f"Agent: {result2}\n")
|
||||
|
||||
# Third query - agent can use both tools if needed
|
||||
query3 = "What's the weather in London and what's the current UTC time?"
|
||||
print(f"User: {query3}")
|
||||
result3 = await agent.run(query3)
|
||||
print(f"Agent: {result3}\n")
|
||||
|
||||
|
||||
async def tools_on_run_level() -> None:
|
||||
"""Example showing tools passed to the run method."""
|
||||
print("=== Tools Passed to Run Method ===")
|
||||
|
||||
# Agent created without tools
|
||||
# For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred
|
||||
# authentication option.
|
||||
async with (
|
||||
AzureCliCredential() as credential,
|
||||
ChatAgent(
|
||||
chat_client=AzureAIAgentClient(async_credential=credential),
|
||||
instructions="You are a helpful assistant.",
|
||||
# No tools defined here
|
||||
) as agent,
|
||||
):
|
||||
# First query with weather tool
|
||||
query1 = "What's the weather like in Seattle?"
|
||||
print(f"User: {query1}")
|
||||
result1 = await agent.run(query1, tools=[get_weather]) # Tool passed to run method
|
||||
print(f"Agent: {result1}\n")
|
||||
|
||||
# Second query with time tool
|
||||
query2 = "What's the current UTC time?"
|
||||
print(f"User: {query2}")
|
||||
result2 = await agent.run(query2, tools=[get_time]) # Different tool for this query
|
||||
print(f"Agent: {result2}\n")
|
||||
|
||||
# Third query with multiple tools
|
||||
query3 = "What's the weather in Chicago and what's the current UTC time?"
|
||||
print(f"User: {query3}")
|
||||
result3 = await agent.run(query3, tools=[get_weather, get_time]) # Multiple tools
|
||||
print(f"Agent: {result3}\n")
|
||||
|
||||
|
||||
async def mixed_tools_example() -> None:
|
||||
"""Example showing both agent-level tools and run-method tools."""
|
||||
print("=== Mixed Tools Example (Agent + Run Method) ===")
|
||||
|
||||
# Agent created with some base tools
|
||||
# For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred
|
||||
# authentication option.
|
||||
async with (
|
||||
AzureCliCredential() as credential,
|
||||
ChatAgent(
|
||||
chat_client=AzureAIAgentClient(async_credential=credential),
|
||||
instructions="You are a comprehensive assistant that can help with various information requests.",
|
||||
tools=[get_weather], # Base tool available for all queries
|
||||
) as agent,
|
||||
):
|
||||
# Query using both agent tool and additional run-method tools
|
||||
query = "What's the weather in Denver and what's the current UTC time?"
|
||||
print(f"User: {query}")
|
||||
|
||||
# Agent has access to get_weather (from creation) + additional tools from run method
|
||||
result = await agent.run(
|
||||
query,
|
||||
tools=[get_time], # Additional tools for this specific query
|
||||
)
|
||||
print(f"Agent: {result}\n")
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
print("=== Azure AI Chat Client Agent with Function Tools Examples ===\n")
|
||||
|
||||
await tools_on_agent_level()
|
||||
await tools_on_run_level()
|
||||
await mixed_tools_example()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,70 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
from typing import Any
|
||||
|
||||
from agent_framework import AgentProtocol, AgentRunResponse, AgentThread, HostedMCPTool
|
||||
from agent_framework.azure import AzureAIAgentClient
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
|
||||
"""
|
||||
Azure AI Agent with Hosted MCP Example
|
||||
|
||||
This sample demonstrates integration of Azure AI Agents with hosted Model Context Protocol (MCP)
|
||||
servers, including user approval workflows for function call security.
|
||||
"""
|
||||
|
||||
|
||||
async def handle_approvals_with_thread(query: str, agent: "AgentProtocol", thread: "AgentThread") -> AgentRunResponse:
|
||||
"""Here we let the thread deal with the previous responses, and we just rerun with the approval."""
|
||||
from agent_framework import ChatMessage
|
||||
|
||||
result = await agent.run(query, thread=thread, store=True)
|
||||
while len(result.user_input_requests) > 0:
|
||||
new_input: list[Any] = []
|
||||
for user_input_needed in result.user_input_requests:
|
||||
print(
|
||||
f"User Input Request for function from {agent.name}: {user_input_needed.function_call.name}"
|
||||
f" with arguments: {user_input_needed.function_call.arguments}"
|
||||
)
|
||||
user_approval = input("Approve function call? (y/n): ")
|
||||
new_input.append(
|
||||
ChatMessage(
|
||||
role="user",
|
||||
contents=[user_input_needed.create_response(user_approval.lower() == "y")],
|
||||
)
|
||||
)
|
||||
result = await agent.run(new_input, thread=thread, store=True)
|
||||
return result
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
"""Example showing Hosted MCP tools for a Azure AI Agent."""
|
||||
async with (
|
||||
AzureCliCredential() as credential,
|
||||
AzureAIAgentClient(async_credential=credential) as chat_client,
|
||||
):
|
||||
agent = chat_client.create_agent(
|
||||
name="DocsAgent",
|
||||
instructions="You are a helpful assistant that can help with microsoft documentation questions.",
|
||||
tools=HostedMCPTool(
|
||||
name="Microsoft Learn MCP",
|
||||
url="https://learn.microsoft.com/api/mcp",
|
||||
),
|
||||
)
|
||||
thread = agent.get_new_thread()
|
||||
# First query
|
||||
query1 = "How to create an Azure storage account using az cli?"
|
||||
print(f"User: {query1}")
|
||||
result1 = await handle_approvals_with_thread(query1, agent, thread)
|
||||
print(f"{agent.name}: {result1}\n")
|
||||
print("\n=======================================\n")
|
||||
# Second query
|
||||
query2 = "What is Microsoft Agent Framework?"
|
||||
print(f"User: {query2}")
|
||||
result2 = await handle_approvals_with_thread(query2, agent, thread)
|
||||
print(f"{agent.name}: {result2}\n")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,88 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
|
||||
from agent_framework import ChatAgent, MCPStreamableHTTPTool
|
||||
from agent_framework.azure import AzureAIAgentClient
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
|
||||
"""
|
||||
Azure AI Agent with Local MCP Example
|
||||
|
||||
This sample demonstrates integration of Azure AI Agents with local Model Context Protocol (MCP)
|
||||
servers, showing both agent-level and run-level tool configuration patterns.
|
||||
"""
|
||||
|
||||
|
||||
async def mcp_tools_on_run_level() -> None:
|
||||
"""Example showing MCP tools defined when running the agent."""
|
||||
print("=== Tools Defined on Run Level ===")
|
||||
|
||||
# Tools are provided when running the agent
|
||||
# This means we have to ensure we connect to the MCP server before running the agent
|
||||
# and pass the tools to the run method.
|
||||
async with (
|
||||
AzureCliCredential() as credential,
|
||||
MCPStreamableHTTPTool(
|
||||
name="Microsoft Learn MCP",
|
||||
url="https://learn.microsoft.com/api/mcp",
|
||||
) as mcp_server,
|
||||
ChatAgent(
|
||||
chat_client=AzureAIAgentClient(async_credential=credential),
|
||||
name="DocsAgent",
|
||||
instructions="You are a helpful assistant that can help with microsoft documentation questions.",
|
||||
) as agent,
|
||||
):
|
||||
# First query
|
||||
query1 = "How to create an Azure storage account using az cli?"
|
||||
print(f"User: {query1}")
|
||||
result1 = await agent.run(query1, tools=mcp_server)
|
||||
print(f"{agent.name}: {result1}\n")
|
||||
print("\n=======================================\n")
|
||||
# Second query
|
||||
query2 = "What is Microsoft Agent Framework?"
|
||||
print(f"User: {query2}")
|
||||
result2 = await agent.run(query2, tools=mcp_server)
|
||||
print(f"{agent.name}: {result2}\n")
|
||||
|
||||
|
||||
async def mcp_tools_on_agent_level() -> None:
|
||||
"""Example showing tools defined when creating the agent."""
|
||||
print("=== Tools Defined on Agent Level ===")
|
||||
|
||||
# Tools are provided when creating the agent
|
||||
# The agent can use these tools for any query during its lifetime
|
||||
# The agent will connect to the MCP server through its context manager.
|
||||
async with (
|
||||
AzureCliCredential() as credential,
|
||||
AzureAIAgentClient(async_credential=credential).create_agent(
|
||||
name="DocsAgent",
|
||||
instructions="You are a helpful assistant that can help with microsoft documentation questions.",
|
||||
tools=MCPStreamableHTTPTool( # Tools defined at agent creation
|
||||
name="Microsoft Learn MCP",
|
||||
url="https://learn.microsoft.com/api/mcp",
|
||||
),
|
||||
) as agent,
|
||||
):
|
||||
# First query
|
||||
query1 = "How to create an Azure storage account using az cli?"
|
||||
print(f"User: {query1}")
|
||||
result1 = await agent.run(query1)
|
||||
print(f"{agent.name}: {result1}\n")
|
||||
print("\n=======================================\n")
|
||||
# Second query
|
||||
query2 = "What is Microsoft Agent Framework?"
|
||||
print(f"User: {query2}")
|
||||
result2 = await agent.run(query2)
|
||||
print(f"{agent.name}: {result2}\n")
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
print("=== Azure AI Chat Client Agent with MCP Tools Examples ===\n")
|
||||
|
||||
await mcp_tools_on_agent_level()
|
||||
await mcp_tools_on_run_level()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,99 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
from datetime import datetime, timezone
|
||||
from typing import Any
|
||||
|
||||
from agent_framework import (
|
||||
AgentProtocol,
|
||||
AgentThread,
|
||||
HostedMCPTool,
|
||||
HostedWebSearchTool,
|
||||
)
|
||||
from agent_framework.azure import AzureAIAgentClient
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
|
||||
"""
|
||||
Azure AI Agent with Multiple Tools Example
|
||||
|
||||
This sample demonstrates integrating multiple tools (MCP and Web Search) with Azure AI Agents,
|
||||
including user approval workflows for function call security.
|
||||
|
||||
Prerequisites:
|
||||
1. Set AZURE_AI_PROJECT_ENDPOINT and AZURE_AI_MODEL_DEPLOYMENT_NAME environment variables
|
||||
2. For Bing search functionality, set BING_CONNECTION_ID environment variable to your Bing connection ID
|
||||
Example: BING_CONNECTION_ID="/subscriptions/{subscription-id}/resourceGroups/{resource-group}/
|
||||
providers/Microsoft.CognitiveServices/accounts/{ai-service-name}/projects/{project-name}/
|
||||
connections/{connection-name}"
|
||||
|
||||
To set up Bing Grounding:
|
||||
1. Go to Azure AI Foundry portal (https://ai.azure.com)
|
||||
2. Navigate to your project's "Connected resources" section
|
||||
3. Add a new connection for "Grounding with Bing Search"
|
||||
4. Copy the connection ID and set it as the BING_CONNECTION_ID environment variable
|
||||
"""
|
||||
|
||||
|
||||
def get_time() -> str:
|
||||
"""Get the current UTC time."""
|
||||
current_time = datetime.now(timezone.utc)
|
||||
return f"The current UTC time is {current_time.strftime('%Y-%m-%d %H:%M:%S')}."
|
||||
|
||||
|
||||
async def handle_approvals_with_thread(query: str, agent: "AgentProtocol", thread: "AgentThread"):
|
||||
"""Here we let the thread deal with the previous responses, and we just rerun with the approval."""
|
||||
from agent_framework import ChatMessage
|
||||
|
||||
result = await agent.run(query, thread=thread, store=True)
|
||||
while len(result.user_input_requests) > 0:
|
||||
new_input: list[Any] = []
|
||||
for user_input_needed in result.user_input_requests:
|
||||
print(
|
||||
f"User Input Request for function from {agent.name}: {user_input_needed.function_call.name}"
|
||||
f" with arguments: {user_input_needed.function_call.arguments}"
|
||||
)
|
||||
user_approval = input("Approve function call? (y/n): ")
|
||||
new_input.append(
|
||||
ChatMessage(
|
||||
role="user",
|
||||
contents=[user_input_needed.create_response(user_approval.lower() == "y")],
|
||||
)
|
||||
)
|
||||
result = await agent.run(new_input, thread=thread, store=True)
|
||||
return result
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
"""Example showing Hosted MCP tools for a Azure AI Agent."""
|
||||
async with (
|
||||
AzureCliCredential() as credential,
|
||||
AzureAIAgentClient(async_credential=credential) as chat_client,
|
||||
):
|
||||
agent = chat_client.create_agent(
|
||||
name="DocsAgent",
|
||||
instructions="You are a helpful assistant that can help with microsoft documentation questions.",
|
||||
tools=[
|
||||
HostedMCPTool(
|
||||
name="Microsoft Learn MCP",
|
||||
url="https://learn.microsoft.com/api/mcp",
|
||||
),
|
||||
HostedWebSearchTool(count=5),
|
||||
get_time,
|
||||
],
|
||||
)
|
||||
thread = agent.get_new_thread()
|
||||
# First query
|
||||
query1 = "How to create an Azure storage account using az cli and what time is it?"
|
||||
print(f"User: {query1}")
|
||||
result1 = await handle_approvals_with_thread(query1, agent, thread)
|
||||
print(f"{agent.name}: {result1}\n")
|
||||
print("\n=======================================\n")
|
||||
# Second query
|
||||
query2 = "What is Microsoft Agent Framework and use a web search to see what is Reddit saying about it?"
|
||||
print(f"User: {query2}")
|
||||
result2 = await handle_approvals_with_thread(query2, agent, thread)
|
||||
print(f"{agent.name}: {result2}\n")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,91 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
import json
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
from agent_framework import ChatAgent
|
||||
from agent_framework_azure_ai import AzureAIAgentClient
|
||||
from azure.ai.agents.models import OpenApiAnonymousAuthDetails, OpenApiTool
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
|
||||
"""
|
||||
The following sample demonstrates how to create a simple, Azure AI agent that
|
||||
uses OpenAPI tools to answer user questions.
|
||||
"""
|
||||
|
||||
# Simulate a conversation with the agent
|
||||
USER_INPUTS = [
|
||||
"What is the name and population of the country that uses currency with abbreviation THB?",
|
||||
"What is the current weather in the capital city of that country?",
|
||||
]
|
||||
|
||||
|
||||
def load_openapi_specs() -> tuple[dict[str, Any], dict[str, Any]]:
|
||||
"""Load OpenAPI specification files."""
|
||||
resources_path = Path(__file__).parent.parent / "resources"
|
||||
|
||||
with open(resources_path / "weather.json") as weather_file:
|
||||
weather_spec = json.load(weather_file)
|
||||
|
||||
with open(resources_path / "countries.json") as countries_file:
|
||||
countries_spec = json.load(countries_file)
|
||||
|
||||
return weather_spec, countries_spec
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
"""Main function demonstrating Azure AI agent with OpenAPI tools."""
|
||||
# 1. Load OpenAPI specifications (synchronous operation)
|
||||
weather_openapi_spec, countries_openapi_spec = load_openapi_specs()
|
||||
|
||||
# 2. Use AzureAIAgentClient as async context manager for automatic cleanup
|
||||
async with AzureAIAgentClient(async_credential=AzureCliCredential()) as client:
|
||||
# 3. Create OpenAPI tools using Azure AI's OpenApiTool
|
||||
auth = OpenApiAnonymousAuthDetails()
|
||||
|
||||
openapi_weather = OpenApiTool(
|
||||
name="get_weather",
|
||||
spec=weather_openapi_spec,
|
||||
description="Retrieve weather information for a location using wttr.in service",
|
||||
auth=auth,
|
||||
)
|
||||
|
||||
openapi_countries = OpenApiTool(
|
||||
name="get_country_info",
|
||||
spec=countries_openapi_spec,
|
||||
description="Retrieve country information including population and capital city",
|
||||
auth=auth,
|
||||
)
|
||||
|
||||
# 4. Create an agent with OpenAPI tools
|
||||
# Note: We need to pass the Azure AI native OpenApiTool definitions directly
|
||||
# since the agent framework doesn't have a HostedOpenApiTool wrapper yet
|
||||
async with ChatAgent(
|
||||
chat_client=client,
|
||||
name="OpenAPIAgent",
|
||||
instructions=(
|
||||
"You are a helpful assistant that can search for country information "
|
||||
"and weather data using APIs. When asked about countries, use the country "
|
||||
"API to find information. When asked about weather, use the weather API. "
|
||||
"Provide clear, informative answers based on the API results."
|
||||
),
|
||||
# Pass the raw tool definitions from Azure AI's OpenApiTool
|
||||
tools=[*openapi_countries.definitions, *openapi_weather.definitions],
|
||||
) as agent:
|
||||
# 5. Simulate conversation with the agent maintaining thread context
|
||||
print("=== Azure AI Agent with OpenAPI Tools ===\n")
|
||||
|
||||
# Create a thread to maintain conversation context across multiple runs
|
||||
thread = agent.get_new_thread()
|
||||
|
||||
for user_input in USER_INPUTS:
|
||||
print(f"User: {user_input}")
|
||||
# Pass the thread to maintain context across multiple agent.run() calls
|
||||
response = await agent.run(user_input, thread=thread)
|
||||
print(f"Agent: {response.text}\n")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,154 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
from random import randint
|
||||
from typing import Annotated
|
||||
|
||||
from agent_framework import AgentThread, ChatAgent
|
||||
from agent_framework.azure import AzureAIAgentClient
|
||||
from azure.identity.aio import AzureCliCredential
|
||||
from pydantic import Field
|
||||
|
||||
"""
|
||||
Azure AI Agent with Thread Management Example
|
||||
|
||||
This sample demonstrates thread management with Azure AI Agents, comparing
|
||||
automatic thread creation with explicit thread management for persistent context.
|
||||
"""
|
||||
|
||||
|
||||
def get_weather(
|
||||
location: Annotated[str, Field(description="The location to get the weather for.")],
|
||||
) -> str:
|
||||
"""Get the weather for a given location."""
|
||||
conditions = ["sunny", "cloudy", "rainy", "stormy"]
|
||||
return f"The weather in {location} is {conditions[randint(0, 3)]} with a high of {randint(10, 30)}°C."
|
||||
|
||||
|
||||
async def example_with_automatic_thread_creation() -> None:
|
||||
"""Example showing automatic thread creation (service-managed thread)."""
|
||||
print("=== Automatic Thread Creation Example ===")
|
||||
|
||||
# For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred
|
||||
# authentication option.
|
||||
async with (
|
||||
AzureCliCredential() as credential,
|
||||
ChatAgent(
|
||||
chat_client=AzureAIAgentClient(async_credential=credential),
|
||||
instructions="You are a helpful weather agent.",
|
||||
tools=get_weather,
|
||||
) as agent,
|
||||
):
|
||||
# First conversation - no thread provided, will be created automatically
|
||||
first_query = "What's the weather like in Seattle?"
|
||||
print(f"User: {first_query}")
|
||||
first_result = await agent.run(first_query)
|
||||
print(f"Agent: {first_result.text}")
|
||||
|
||||
# Second conversation - still no thread provided, will create another new thread
|
||||
second_query = "What was the last city I asked about?"
|
||||
print(f"\nUser: {second_query}")
|
||||
second_result = await agent.run(second_query)
|
||||
print(f"Agent: {second_result.text}")
|
||||
print("Note: Each call creates a separate thread, so the agent doesn't remember previous context.\n")
|
||||
|
||||
|
||||
async def example_with_thread_persistence() -> None:
|
||||
"""Example showing thread persistence across multiple conversations."""
|
||||
print("=== Thread Persistence Example ===")
|
||||
print("Using the same thread across multiple conversations to maintain context.\n")
|
||||
|
||||
# For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred
|
||||
# authentication option.
|
||||
async with (
|
||||
AzureCliCredential() as credential,
|
||||
ChatAgent(
|
||||
chat_client=AzureAIAgentClient(async_credential=credential),
|
||||
instructions="You are a helpful weather agent.",
|
||||
tools=get_weather,
|
||||
) as agent,
|
||||
):
|
||||
# Create a new thread that will be reused
|
||||
thread = agent.get_new_thread()
|
||||
|
||||
# First conversation
|
||||
first_query = "What's the weather like in Tokyo?"
|
||||
print(f"User: {first_query}")
|
||||
first_result = await agent.run(first_query, thread=thread)
|
||||
print(f"Agent: {first_result.text}")
|
||||
|
||||
# Second conversation using the same thread - maintains context
|
||||
second_query = "How about London?"
|
||||
print(f"\nUser: {second_query}")
|
||||
second_result = await agent.run(second_query, thread=thread)
|
||||
print(f"Agent: {second_result.text}")
|
||||
|
||||
# Third conversation - agent should remember both previous cities
|
||||
third_query = "Which of the cities I asked about has better weather?"
|
||||
print(f"\nUser: {third_query}")
|
||||
third_result = await agent.run(third_query, thread=thread)
|
||||
print(f"Agent: {third_result.text}")
|
||||
print("Note: The agent remembers context from previous messages in the same thread.\n")
|
||||
|
||||
|
||||
async def example_with_existing_thread_id() -> None:
|
||||
"""Example showing how to work with an existing thread ID from the service."""
|
||||
print("=== Existing Thread ID Example ===")
|
||||
print("Using a specific thread ID to continue an existing conversation.\n")
|
||||
|
||||
# First, create a conversation and capture the thread ID
|
||||
existing_thread_id = None
|
||||
|
||||
# For authentication, run `az login` command in terminal or replace AzureCliCredential with preferred
|
||||
# authentication option.
|
||||
async with (
|
||||
AzureCliCredential() as credential,
|
||||
ChatAgent(
|
||||
chat_client=AzureAIAgentClient(async_credential=credential),
|
||||
instructions="You are a helpful weather agent.",
|
||||
tools=get_weather,
|
||||
) as agent,
|
||||
):
|
||||
# Start a conversation and get the thread ID
|
||||
thread = agent.get_new_thread()
|
||||
first_query = "What's the weather in Paris?"
|
||||
print(f"User: {first_query}")
|
||||
first_result = await agent.run(first_query, thread=thread)
|
||||
print(f"Agent: {first_result.text}")
|
||||
|
||||
# The thread ID is set after the first response
|
||||
existing_thread_id = thread.service_thread_id
|
||||
print(f"Thread ID: {existing_thread_id}")
|
||||
|
||||
if existing_thread_id:
|
||||
print("\n--- Continuing with the same thread ID in a new agent instance ---")
|
||||
|
||||
# Create a new agent instance but use the existing thread ID
|
||||
async with (
|
||||
AzureCliCredential() as credential,
|
||||
ChatAgent(
|
||||
chat_client=AzureAIAgentClient(thread_id=existing_thread_id, async_credential=credential),
|
||||
instructions="You are a helpful weather agent.",
|
||||
tools=get_weather,
|
||||
) as agent,
|
||||
):
|
||||
# Create a thread with the existing ID
|
||||
thread = AgentThread(service_thread_id=existing_thread_id)
|
||||
|
||||
second_query = "What was the last city I asked about?"
|
||||
print(f"User: {second_query}")
|
||||
second_result = await agent.run(second_query, thread=thread)
|
||||
print(f"Agent: {second_result.text}")
|
||||
print("Note: The agent continues the conversation from the previous thread.\n")
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
print("=== Azure AI Chat Client Agent Thread Management Examples ===\n")
|
||||
|
||||
await example_with_automatic_thread_creation()
|
||||
await example_with_thread_persistence()
|
||||
await example_with_existing_thread_id()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
Reference in New Issue
Block a user