Agent Framework Foundry
This package contains the Microsoft Foundry integrations for Microsoft Agent Framework, including Foundry chat clients, preconfigured Foundry agents, Foundry embedding clients, and Foundry memory providers.
SDK compatibility
This package supports azure-ai-projects>=2.2.0,<2.8.0. Projects 2.5 and later require
openai>=3.0.0, so agent-framework-foundry requires agent-framework-openai>=1.14.2,
which supports both OpenAI 2.x and 3.x.
Tracing an existing Foundry agent
Install Azure Monitor to connect client and service traces:
pip install --upgrade agent-framework-foundry "azure-monitor-opentelemetry>=1.8.10,<2"
With Application Insights connected to your project, call
await agent.configure_azure_monitor() before invoking a FoundryAgent.
See the tracing sample
for streaming and non-streaming examples.
Embeddings
FoundryEmbeddingClient supports OpenAI text embedding deployments exposed through a Microsoft Foundry project.
Pass an existing AIProjectClient, or provide the project endpoint and an async Azure credential:
import os
from agent_framework.foundry import FoundryEmbeddingClient
from azure.identity.aio import AzureCliCredential
async with AzureCliCredential() as credential:
async with FoundryEmbeddingClient(
project_endpoint=os.environ["FOUNDRY_PROJECT_ENDPOINT"],
model=os.environ["FOUNDRY_EMBEDDING_MODEL"],
credential=credential,
) as client:
result = await client.get_embeddings(["Hello, world!"])
print(result[0].dimensions)
Set FOUNDRY_PROJECT_ENDPOINT to the project endpoint and FOUNDRY_EMBEDDING_MODEL to the embedding deployment
name. When an AIProjectClient is already available, pass it as project_client and omit the endpoint and
credential.
The client uses the project for authentication and converts a
https://<resource>.services.ai.azure.com/api/projects/<project> endpoint to the documented resource-scoped
https://<resource>.openai.azure.com/openai/v1/ model route. The existing FOUNDRY_MODELS_ENDPOINT and
FOUNDRY_MODELS_API_KEY configuration remains available for Foundry Models inference endpoints. A Models endpoint is
required for image embedding models. If both project and Models endpoints are configured only through environment
variables, the Models endpoint is retained for backward compatibility; pass project_endpoint explicitly to select
the project OpenAI deployment.
Evaluations
FoundryEvals implements the provider-neutral Evaluator protocol with
Microsoft Foundry's built-in and generated evaluators. Core owns EvalItem,
local evaluation, and the evaluate_agent() / evaluate_workflow()
orchestration functions; this package owns the Foundry Evals data mappings,
wire serialization, submission, polling, and result parsing.
Use evaluate_agent() for the common run-and-evaluate path:
from agent_framework import evaluate_agent
from agent_framework.foundry import FoundryEvals
results = await evaluate_agent(
agent=agent,
queries=["What's the weather in Seattle?"],
evaluators=FoundryEvals(),
)
For manual control, construct public EvalItem instances and pass them to
FoundryEvals.evaluate(). The Foundry wire format is private to this package.
evaluate_traces() and evaluate_foundry_target() provide Foundry-specific
entry points for existing traces, response IDs, and registered targets.
Concurrent reuse
A FoundryChatClient instance can be shared by concurrent asynchronous calls on the same event loop. Streaming,
non-streaming, and mixed calls are supported. Keep mutable run state isolated by creating a separate Agent and
AgentSession for each concurrent run and by passing separate messages and options.
This guarantee does not extend to user-supplied middleware, tools, or callbacks unless those implementations are also safe for concurrent use. Do not share one client across OS threads or event loops, and do not mutate its configuration while calls are active.
Toolboxes
A toolbox is a named, versioned bundle of hosted tool configurations — code interpreter, file search, image generation, MCP, web search, and so on — stored inside a Microsoft Foundry project. Toolboxes let you manage tool configuration once and reuse it across agents.
Authoring a toolbox
Toolboxes can be authored two ways:
- Foundry portal — create and version toolboxes through the UI without touching code.
- Programmatically — use the
azure-ai-projectsSDK to create, update, and version toolboxes from Python.
In
azure-ai-projects2.2, toolbox authoring is available throughproject_client.beta.toolboxes. Projects 2.3 and later expose stableproject_client.toolboxesoperations.
Using toolboxes with FoundryAgent
For hosted FoundryAgent, the toolbox must already be attached to the agent in the Microsoft Foundry project. Once attached, the agent invokes its toolbox tools transparently — no client-side wiring required — and you interact with the agent the same way you would with any other tool-equipped Foundry agent.
Using toolboxes with FoundryChatClient
Each toolbox is reachable as an MCP server. Connect to the toolbox's MCP endpoint with MCPStreamableHTTPTool — the agent then discovers and calls its tools over MCP at runtime:
from agent_framework import Agent, MCPStreamableHTTPTool
from agent_framework.foundry import FoundryChatClient
async with Agent(
client=FoundryChatClient(...),
instructions="You are a helpful assistant. Use the toolbox tools when useful.",
tools=MCPStreamableHTTPTool(
name="my_toolbox",
description="Tools served by my Foundry toolbox",
url="https://<your-toolbox-mcp-endpoint>",
),
) as agent:
result = await agent.run("What tools are available?")
print(result.text)
Hosted tool factories
FoundryChatClient exposes static factory methods that return Foundry SDK tool
configurations ready to pass to an Agent's tools=[...] argument. These
factories don't require a FoundryChatClient instance — you can call them
statically and reuse the same tool configuration across agents.
from agent_framework import Agent
from agent_framework.foundry import FoundryChatClient
agent = Agent(
client=FoundryChatClient(...),
instructions="...",
tools=[
FoundryChatClient.get_web_search_tool(),
FoundryChatClient.get_code_interpreter_tool(),
],
)
Non-preview factories: get_computer_tool, get_code_interpreter_tool,
get_file_search_tool, get_web_search_tool,
get_image_generation_tool, get_mcp_tool.
get_computer_tool() returns the Foundry SDK's ComputerTool (available in
azure-ai-projects>=2.3.0). The package still supports 2.2.x for other tools:
only calling this factory on an older SDK raises ImportError with upgrade guidance.
get_computer_use_tool(...) remains available for the separate preview API.
The OpenAI Responses client also exposes OpenAIChatClient.get_computer_tool().
The new ComputerSafetyCheck type and Content.from_computer_tool_call /
Content.from_computer_tool_result constructors are experimental Agent Framework APIs,
even though Foundry's ComputerTool is a non-preview SDK model.
Computer calls arrive as Content with type="computer_tool_call", a
provider item id, a distinct call_id, ordered actions, and optional
pending_safety_checks. Unanswered calls require application input: inspect
AgentResponse.user_input_requests (or ChatResponse.messages[*].contents),
show the actions and warnings to the user, and execute actions only after
approval. To continue, return Content.from_computer_tool_result(call_id=..., screenshot=Content.from_data(image_bytes, "image/png")) in a tool message;
Content.from_uri(...) and Content.from_hosted_file(...) also work for
screenshots. Shared Content allows a result without a screenshot for other
providers, but OpenAI and Foundry Responses require one. If checks were pending,
explicitly pass only those the
application has confirmed as acknowledged_safety_checks=[{"id": "..."}].
The framework never acknowledges warnings on your behalf. Calls and results
can be persisted as Content.to_dict() and restored with Content.from_dict().
A call already paired with a completed screenshot result stays in the transcript
for audit (informational_only=True), but does not appear in
AgentResponse.user_input_requests. When a workflow pauses on a computer call
alongside locally executable functions, it sends their completed results with
the screenshot in the original call order after the application responds. If
any computer request in a workflow batch is cancelled, the remaining requests
in that agent's batch are cancelled too; the terminal output retains already
resolved results, and the next turn starts with a fresh agent session.
Choosing a web grounding tool.
get_web_search_toolis the recommended default — it requires no separate Bing resource and works with Azure OpenAI models out of the box. Reach forget_bing_grounding_tool(experimental, see below) when you need finer Bing parameters (count,freshness,market,set_lang), are grounding non-OpenAI Foundry models, or are migrating from Grounding with Bing Search on the classic platform — it requires a Grounding with Bing Search Azure resource that you manage.get_bing_custom_search_tool(also experimental) is for grounding restricted to a curated list of domains via a Bing Custom Search instance. See the web grounding overview for the full comparison.
Experimental —
ExperimentalFeature.FOUNDRY_TOOLS. The following factories wrap GA Foundry tool SDK classes but are new wrappers inagent-framework-foundryand may change before the wrappers themselves reach GA. Calls emit anExperimentalWarningthe first time theFOUNDRY_TOOLSfeature is exercised in a process (then deduplicated).
| Factory | Foundry SDK tool |
|---|---|
get_azure_ai_search_tool(index_connection_id, index_name, ...) |
AzureAISearchTool |
get_bing_grounding_tool(connection_id, ...) |
BingGroundingTool |
Experimental —
ExperimentalFeature.FOUNDRY_PREVIEW_TOOLS. The following factories wrap preview Foundry tool SDK types — the underlying Foundry capability itself is in preview and may change or be removed before reaching GA. Calls emit a separateExperimentalWarningthe first time theFOUNDRY_PREVIEW_TOOLSfeature is exercised in a process (then deduplicated). UseFOUNDRY_TOOLSfor "wrapper is new" andFOUNDRY_PREVIEW_TOOLSfor "underlying Foundry feature is preview".
| Factory | Foundry SDK tool |
|---|---|
get_sharepoint_tool(connection_id) |
SharepointPreviewTool |
get_fabric_tool(connection_id) |
MicrosoftFabricPreviewTool |
get_memory_search_tool(memory_store_name, scope, ...) |
MemorySearchPreviewTool |
get_computer_use_tool(environment, display_width, display_height) |
ComputerUsePreviewTool |
get_browser_automation_tool(connection_id) |
BrowserAutomationPreviewTool |
get_bing_custom_search_tool(connection_id, instance_name, ...) |
BingCustomSearchPreviewTool |
get_a2a_tool(base_url=..., project_connection_id=..., ...) |
A2APreviewTool |
Creating Foundry conversation sessions
FoundryAgent.create_conversation() creates a server-side Foundry
project conversation and returns an AgentSession that can be passed to
agent.run(...) without reaching into the raw OpenAI client.
from agent_framework.foundry import FOUNDRY_HOSTED_AGENT_SESSION_ID_KEY, FoundryAgent
agent = FoundryAgent(
project_endpoint=project_endpoint,
agent_name="travel-agent",
credential=credential,
)
session = await agent.create_conversation()
response = await agent.run("Help me plan a trip to Seattle.", session=session)
For HostedAgents, start with a normal AgentSession. When no hosted-agent
session ID is supplied, the service creates one and the agent stores it in
session.state[FOUNDRY_HOSTED_AGENT_SESSION_ID_KEY]. The response conversation
ID or response ID remains separate in session.service_session_id and is used
as the next request's continuation handle.
Publishing an agent as a Foundry prompt agent
Experimental —
ExperimentalFeature.TO_PROMPT_AGENT.to_prompt_agentis a preview API and may change before reaching GA. The warning fires the first time theTO_PROMPT_AGENTfeature is exercised in a process and is then deduplicated.
to_prompt_agent(agent) converts an Agent whose chat client is a
FoundryChatClient into a Foundry PromptAgentDefinition that can be
published with AIProjectClient.agents.create_version(...). The model is read
from default_options["model"] first and falls back to the bound
FoundryChatClient.model (matching Agent.__init__'s resolution order), so
the same agent definition you run locally can be published as a hosted prompt
agent without restating the model deployment name.
Every generation parameter that has an Agent Framework equivalent is sourced
from agent.default_options and translated into the matching Foundry shape by
_prepare_prompt_agent_options (a module-private helper in
agent_framework_foundry._to_prompt_agent that reuses the chat client's own
request-path helpers):
default_options key |
PromptAgentDefinition field |
|---|---|
temperature |
temperature |
top_p |
top_p |
tool_choice (dropped when no tools) |
tool_choice (str / ToolChoiceFunction / ToolChoiceAllowed) |
reasoning (dict or Reasoning) |
reasoning |
response_format (dict or BaseModel) |
text.format |
verbosity |
text.verbosity |
text |
merged into text |
This keeps the Agent as the single source of truth for everything it can
already express. Only Foundry-specific fields with no Agent Framework
equivalent are accepted as keyword arguments on to_prompt_agent:
structured_inputs—dict[str, StructuredInputDefinition]rai_config—RaiConfig
import asyncio
import os
from agent_framework import Agent
from agent_framework.foundry import FoundryChatClient, to_prompt_agent
from azure.ai.projects.aio import AIProjectClient
from azure.identity.aio import AzureCliCredential
async def main() -> None:
credential = AzureCliCredential()
project_endpoint = os.environ["FOUNDRY_PROJECT_ENDPOINT"]
agent = Agent(
client=FoundryChatClient(
project_endpoint=project_endpoint,
model="gpt-4o",
credential=credential,
),
name="travel-agent",
description="Helps Contoso employees book travel.",
instructions="You are a helpful travel assistant.",
tools=[
FoundryChatClient.get_web_search_tool(),
FoundryChatClient.get_code_interpreter_tool(),
],
# Generation parameters set on the Agent flow through automatically.
default_options={
"temperature": 0.3,
"top_p": 0.95,
"reasoning": {"effort": "medium"},
},
)
definition = to_prompt_agent(agent)
project_client = AIProjectClient(endpoint=project_endpoint, credential=credential)
created = await project_client.agents.create_version(
agent_name=agent.name,
definition=definition,
description=agent.description,
)
print(f"Published {created.name} v{created.version}")
asyncio.run(main())
Behaviour:
-
agent.clientmust be aFoundryChatClient(or subclass) — otherwise the converter raisesTypeError. -
The bound client must have a
modelset — otherwise the converter raisesValueError. -
Foundry SDK tool instances returned by
FoundryChatClient.get_*_tool()are passed through unchanged. -
AF
FunctionToolinstances (and@tool-decorated callables) are emitted as FoundryFunctionTooldeclarations — the prompt agent receives the schema only, not the Python implementation. To execute the function when invoking the deployed prompt agent, connect withFoundryAgentand pass the same callable viatools=:from agent_framework.foundry import FoundryAgent deployed = FoundryAgent( project_endpoint=project_endpoint, agent_name="travel-agent", credential=credential, tools=[book_hotel], # same @tool-decorated callable used at publish time ) result = await deployed.run("Book me a hotel in Seattle for 3 nights.")
FoundryAgentruns the function locally when the prompt agent calls it, so the declaration on the server and the implementation on the client stay in sync via the shared@tooldefinition. -
Local Agent Framework MCP tools cannot be published as prompt-agent tools — the converter raises
ValueErrorand points atFoundryChatClient.get_mcp_tool(...)for hosted MCP servers.
See the runnable example under samples/02-agents/providers/foundry/:
foundry_prompt_agents.py— publish withto_prompt_agent, then connect back withFoundryAgentand execute the same local@toolcallable that the deployed prompt agent invokes by name.
Metadata
Release files for agent-framework-foundry 1.14.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| agent_framework_foundry-1.14.0.tar.gz | 59.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| agent_framework_foundry-1.14.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 120.0 kB
Release files / agent_framework_foundry-1.14.0.tar.gz
| Download URL | agent_framework_foundry-1.14.0.tar.gz |
|---|---|
| Size | 59.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
051209db092b358554c55ca804428279530c3787c37199e0c863b7599c0c7eb7
|
|
BLAKE2b-256 checksum How to use checksums |
41b255451d14a8dff13814535b2a3d594dab7bac91980b717d6e3830fc16aebe
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.22 {"installer":{"name":"uv","version":"0.12.22","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / agent_framework_foundry-1.14.0-py3-none-any.whl
| Download URL | agent_framework_foundry-1.14.0-py3-none-any.whl |
|---|---|
| Size | 60.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ae7c8d6881f351f237f40ee787c150cb81af642d8e2d5e11d0b9daf9fe05fd46
|
|
BLAKE2b-256 checksum How to use checksums |
f3c5cd4340b1d08d87dfeba908da55347179b8cb63187ac066ed15734d4f0163
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.22 {"installer":{"name":"uv","version":"0.12.22","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|