Skip to content

Commit 47f5c33

Browse files
Python: feat(foundry): add experimental hosted tool factories on FoundryChatClient (microsoft#5958)
* feat(foundry): add experimental hosted tool factories on FoundryChatClient Adds eight new `@experimental` static factory methods on `FoundryChatClient` covering Foundry-hosted tools that previously had no helper: - get_azure_ai_search_tool - get_sharepoint_tool - get_fabric_tool - get_memory_search_tool - get_computer_use_tool - get_browser_automation_tool - get_bing_custom_search_tool - get_a2a_tool All factories are marked with the new `ExperimentalFeature.FOUNDRY_TOOLS` tag and resolve the underlying `azure-ai-projects` preview classes lazily through a `_require_sdk_class` helper so older SDK versions still import cleanly and fail with a clear `ImportError` only on use. Tests cover each factory's return type and field wiring, the experimental metadata, and the missing-SDK-class fallback. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * test(foundry): address review comments on tool-factory tests * Skip preview-tool tests gracefully (`_skip_if_sdk_class_missing`) when the installed `azure-ai-projects` does not expose the required preview class, matching the lazy-import guard in production code so the test suite stays green on older SDK installs. * Add `filterwarnings("ignore::FutureWarning")` to each new tool-factory test (and the parametrized metadata test) so they remain stable under strict warning configurations \u2014 the global dedup in `_feature_stage._WARNED_FEATURES` makes `pytest.warns` brittle across ordered runs. * Use `monkeypatch.setattr(..., None, raising=False)` instead of `delattr` in the missing-SDK-class test so it works for modules that implement PEP 562 `__getattr__`. * Split the long `get_bing_custom_search_tool` return into two lines for readability. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(foundry): harden tool-factory kwargs against silent override * Reorder the dict-literal kwargs assembly in get_azure_ai_search_tool, get_memory_search_tool, and get_bing_custom_search_tool so explicit parameters always take precedence over **kwargs (matching the safe pattern already used in get_a2a_tool). This prevents a caller passing `project_connection_id`, `index_name`, `memory_store_name`, `scope`, or `instance_name` through `**kwargs` from silently overriding the explicit security-sensitive arguments. * Update the README experimental note to reflect once-per-feature-id dedup semantics of `_feature_stage._WARNED_FEATURES` rather than claiming a per-factory "first use" warning. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat(foundry): split FOUNDRY_TOOLS / FOUNDRY_PREVIEW_TOOLS, add bing-grounding - Add ExperimentalFeature.FOUNDRY_PREVIEW_TOOLS to distinguish wrappers around preview Foundry SDK tool classes (Sharepoint/Fabric/Memory/ComputerUse/ BrowserAutomation/BingCustomSearch/A2A) from FOUNDRY_TOOLS, which is for GA-SDK wrappers that are simply new in agent-framework-foundry (AzureAISearch, BingGrounding). - Add get_bing_grounding_tool factory and a 'Choosing a web grounding tool' comparison block on get_web_search_tool / get_bing_grounding_tool / get_bing_custom_search_tool docstrings. - Drop the _require_sdk_class lazy resolver: every guarded class is available at azure-ai-projects>=2.1.0 (the package floor), so import them eagerly. Concrete return types replace 'Any'. - README: split the experimental factories into two tables, one per feature flag, with a note explaining the distinction. - Tests: split into FOUNDRY_TOOLS / FOUNDRY_PREVIEW_TOOLS factory cases; drop the obsolete missing-SDK-class ImportError test. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 01a3c5b commit 47f5c33

4 files changed

Lines changed: 699 additions & 10 deletions

File tree

python/packages/core/agent_framework/_feature_stage.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ class ExperimentalFeature(str, Enum):
4949
EVALS = "EVALS"
5050
FILE_HISTORY = "FILE_HISTORY"
5151
FIDES = "FIDES"
52+
FOUNDRY_TOOLS = "FOUNDRY_TOOLS"
53+
FOUNDRY_PREVIEW_TOOLS = "FOUNDRY_PREVIEW_TOOLS"
5254
FUNCTIONAL_WORKFLOWS = "FUNCTIONAL_WORKFLOWS"
5355
HARNESS = "HARNESS"
5456
SKILLS = "SKILLS"

python/packages/foundry/README.md

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,70 @@ async with Agent(
3939
result = await agent.run("What tools are available?")
4040
print(result.text)
4141
```
42+
43+
## Hosted tool factories
44+
45+
`FoundryChatClient` exposes static factory methods that return Foundry SDK tool
46+
configurations ready to pass to an `Agent`'s `tools=[...]` argument. These
47+
factories don't require a `FoundryChatClient` instance — you can call them
48+
statically and reuse the same tool configuration across agents.
49+
50+
```python
51+
from agent_framework import Agent
52+
from agent_framework.foundry import FoundryChatClient
53+
54+
agent = Agent(
55+
client=FoundryChatClient(...),
56+
instructions="...",
57+
tools=[
58+
FoundryChatClient.get_web_search_tool(),
59+
FoundryChatClient.get_code_interpreter_tool(),
60+
],
61+
)
62+
```
63+
64+
Generally available factories: `get_code_interpreter_tool`,
65+
`get_file_search_tool`, `get_web_search_tool`,
66+
`get_image_generation_tool`, `get_mcp_tool`.
67+
68+
> **Choosing a web grounding tool.** `get_web_search_tool` is the recommended
69+
> default — it requires no separate Bing resource and works with Azure OpenAI
70+
> models out of the box. Reach for `get_bing_grounding_tool` (experimental,
71+
> see below) when you need finer Bing parameters (`count`, `freshness`,
72+
> `market`, `set_lang`), are grounding non-OpenAI Foundry models, or are
73+
> migrating from Grounding with Bing Search on the classic platform — it
74+
> requires a Grounding with Bing Search Azure resource that you manage.
75+
> `get_bing_custom_search_tool` (also experimental) is for grounding
76+
> restricted to a curated list of domains via a Bing Custom Search instance.
77+
> See the
78+
> [web grounding overview](https://learn.microsoft.com/azure/foundry/agents/how-to/tools/web-overview)
79+
> for the full comparison.
80+
81+
> **Experimental — `ExperimentalFeature.FOUNDRY_TOOLS`.** The following
82+
> factories wrap GA Foundry tool SDK classes but are new wrappers in
83+
> `agent-framework-foundry` and may change before the wrappers themselves
84+
> reach GA. Calls emit an `ExperimentalWarning` the first time the
85+
> `FOUNDRY_TOOLS` feature is exercised in a process (then deduplicated).
86+
87+
| Factory | Foundry SDK tool |
88+
|---------|-----------------|
89+
| `get_azure_ai_search_tool(index_connection_id, index_name, ...)` | `AzureAISearchTool` |
90+
| `get_bing_grounding_tool(connection_id, ...)` | `BingGroundingTool` |
91+
92+
> **Experimental — `ExperimentalFeature.FOUNDRY_PREVIEW_TOOLS`.** The
93+
> following factories wrap **preview** Foundry tool SDK types — the underlying
94+
> Foundry capability itself is in preview and may change or be removed before
95+
> reaching GA. Calls emit a separate `ExperimentalWarning` the first time the
96+
> `FOUNDRY_PREVIEW_TOOLS` feature is exercised in a process (then
97+
> deduplicated). Use `FOUNDRY_TOOLS` for "wrapper is new" and
98+
> `FOUNDRY_PREVIEW_TOOLS` for "underlying Foundry feature is preview".
99+
100+
| Factory | Foundry SDK tool |
101+
|---------|-----------------|
102+
| `get_sharepoint_tool(connection_id)` | `SharepointPreviewTool` |
103+
| `get_fabric_tool(connection_id)` | `MicrosoftFabricPreviewTool` |
104+
| `get_memory_search_tool(memory_store_name, scope, ...)` | `MemorySearchPreviewTool` |
105+
| `get_computer_use_tool(environment, display_width, display_height)` | `ComputerUsePreviewTool` |
106+
| `get_browser_automation_tool(connection_id)` | `BrowserAutomationPreviewTool` |
107+
| `get_bing_custom_search_tool(connection_id, instance_name, ...)` | `BingCustomSearchPreviewTool` |
108+
| `get_a2a_tool(base_url=..., project_connection_id=..., ...)` | `A2APreviewTool` |

0 commit comments

Comments
 (0)