Files
microsoft--agent-framework/python/samples/04-hosting/foundry-hosted-agents
Eduard van Valkenburg 6e95517659 Python: Split type checkers by target (pyright source, 5 checkers on tests/samples) (#6443)
* Python: Split type checkers by target (pyright source, 5 checkers on tests/samples)

Rework the typing setup along the lines of the 'too many type checkers'
approach:

- Pyright (strict) is now the sole source-code type checker; mypy is
  removed from source and its [tool.mypy] block becomes a relaxed profile
  used only for tests/samples.
- Tests are checked by all five checkers (pyright relaxed, mypy, pyrefly,
  ty, zuban); samples by pyright, pyrefly, and ty. All run in a relaxed/
  basic profile so authors aren't forced into over-annotation.
- Add pyrightconfig.tests.json and bump sample pyright configs to basic.
- Unify test/sample typing onto the same parallel fan-out used by source
  pyright via run_command_items in task_runner.py.
- Make version-conditional imports symmetric: keep or drop the
  '# type: ignore' on both branches so results match across interpreter
  versions (local vs CI).
- Update SKILL.md, DEV_SETUP.md, and CODING_STANDARD.md for the five
  gating checkers and pyright on source+tests+samples.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Python: Fix merge regressions from main (typing + runtime)

Merging main into the type-checker split branch surfaced regressions that
the new five-checker test suite and unit tests caught:

Runtime fixes:
- anthropic: restore the dropped `cache_read_input_token_count` mapping in
  _parse_usage_from_anthropic (lost during merge conflict resolution).
- gemini: _get_function_calling_mode test helper returned str(enum)
  ('FunctionCallingConfigMode.AUTO') instead of the enum value ('AUTO').
- openai: _response_id_from_token test helper was an infinite self-recursion;
  return token['response_id'].
- orchestrations: reset output_events per approval iteration so the terminal
  output assertion counts only the final run.
- core: drop a stale duplicate harness test whose message ('non-negative')
  contradicted the source ('positive').
- purview: import PolicyLocation/PolicyScope/ProtectionScopeActivities/
  ExecutionMode used by the processor tests.

Type-checker fixes (tests, relaxed profile):
- core: pyright/mypy/pyrefly/ty/zuban green-ups across the harness, MCP,
  observability and types tests.
- anthropic/openai: route provider-namespaced UsageDetails keys through a
  dict cast (extra_items TypedDict unsupported by mypy/ty).
- purview: typed model constructors and cache-mock casts.
- ag-ui: annotate WorkflowContext[Any, Any] so yield_output accepts test
  payloads, guard Optional forwarded_props, and ty-ignore intentional bad args.

Source pyright (sole source checker) flagged unnecessary ignores newly
introduced by merged code in core _tools.py and declarative _declarative_base.py.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Python: Isolate per-package mypy cache in test-typing fan-out

The parallel test-typing fan-out runs many mypy processes concurrently,
all defaulting to a single shared ./.mypy_cache. Concurrent writes corrupt
the cache and mypy aborts with INTERNAL ERROR (intermittently, depending on
worker timing) -- which is why CI's Test Typing job failed on a shifting set
of packages while a single-package run was fine.

Give each mypy invocation an isolated cache dir keyed by its target paths so
incremental caching still works per package without races. Other checkers
(zuban/pyrefly/ty/pyright) maintain their own caches and are unaffected.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Python: Make lab pyright-only on source (drop source mypy)

Lab was the last package still running mypy on its source code, requiring
mypy-only `# type: ignore` comments that pyright (the sole source checker
everywhere else) flags as unnecessary. Align lab with the rest of the
monorepo:

- Remove the lab source mypy poe tasks (mypy-gaia/lightning/tau2) and the
  now-dead strict [tool.mypy] config block.
- Drop the 'Run lab mypy' CI step; lab source is type-checked by pyright only.

Lab tests remain covered by the workspace test-typing fan-out (mypy, pyrefly,
ty, zuban, pyright over tests using the relaxed root config).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Python: Fix test-typing regressions from latest main merge

A fresh merge from main brought in new test code never run under the
five-checker test-typing suite. Green up across the affected packages:

- core: narrow Optional span.attributes with 'and' guards in span filters
  and assert+cast the json.loads(...attributes[...]) reads (test_observability);
  match the existing as_agent ignore on the protocol-typed fixture (test_clients).
- openai: align new streaming tests with the established chat_options dict
  pattern (ChatOptions TypedDict isn't assignable to dict), route Optional
  .annotations[0] access through a small _first_annotation helper (mirrors the
  file's assert-not-None convention), and annotate a mapped ResponseStream.
- foundry_hosting: annotate error: dict[str, Any] = body.get(...) or {}
  (zuban needs the annotation).
- foundry: narrow ignores for the live AIProjectClient credential arg (pyrefly)
  and connections.get_default (zuban) SDK type gaps.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* updated pyright version

* pyright fix

* Python: Fix source typing for pyright 1.1.410

Pyright 1.1.410 tightened several checks. Apply the same source fixes as
upstream PR #6275:

- anthropic: import AsyncAnthropicBedrock from anthropic.lib.bedrock and
  AsyncAnthropicVertex from anthropic.lib.vertex (no longer re-exported from
  the anthropic top-level package -> reportPrivateImportUsage).
- core _types.py: cast the transform-hook result to UpdateT (reportAssignmentType).
- core _workflows/_events.py: annotate the @contextmanager helper as
  Generator[None] instead of Iterator[None] (reportDeprecated).
- redis: build the combined filter expression with an explicit loop instead of
  reduce(and_, ...), which pyright could no longer fully type (drops the now
  unused functools.reduce / operator.and_ imports).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Python: Accept plain-text body in Azure Functions workflow/run endpoint

The workflow_orchestrator already accepts plain strings as well as JSON
objects via context.get_input(), but the start_workflow_orchestration HTTP
handler only accepted JSON and returned 400 for any non-JSON body. This made
the functions integration tests that POST text/plain to /api/workflow/run
(e.g. test_09_workflow_shared_state) fail consistently with 400 != 202.

Fall back to the raw request body (decoded as UTF-8) when the body is not
JSON, rejecting only a truly empty body. The JSON path is unchanged.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-18 15:06:20 +00:00
..

Foundry Hosted Agent Samples

This directory contains samples that demonstrate how to use hosted Agent Framework agents with different capabilities and configurations on Foundry using the Foundry Hosting Agent service. Each sample includes a README with instructions on how to set up, run, and interact with the agent.

Samples

Responses API

# Sample Description
1 Basic A minimal agent demonstrating basic request/response interaction and multi-turn conversations using previous_response_id.
2 Tools An agent with local tools (e.g., weather lookup), demonstrating how to register and invoke custom tool functions alongside the LLM.
3 MCP An agent connected to a remote MCP server (GitHub), demonstrating external MCP tool provider integration.
4 Foundry Toolbox An agent using Azure Foundry Toolbox, demonstrating toolbox provisioning and querying available tools at runtime.
5 Workflows An agent with a multi-step orchestrated workflow, demonstrating chaining prompts through an orchestrated flow.
6 Files An agent demonstrating how to work with files in a hosted agent session, including uploading files to a hosted agent session and having the agent read and manipulate those files at runtime.
7 Observability A sample demonstrating how to enable observability for the agent deployed to Foundry.
8 Azure AI Search RAG An agent with Retrieval Augmented Generation (RAG) capabilities backed by Azure AI Search, grounding answers in documents indexed in a pre-provisioned search index.
9 Foundry Skills An agent that uploads SKILL.md files to the Foundry Skills REST API and downloads them at startup, decoupling tone/policy guidelines from agent code.
10 Foundry Memory An agent with persistent semantic memory backed by an Azure AI Foundry Memory Store, using FoundryMemoryProvider to remember user facts across sessions.
11 Monty CodeAct An agent with a Monty-backed CodeAct context provider, exposing a single execute_code tool that runs Python in a pydantic-monty interpreter and invokes typed host tools (compute, fetch_data) from inside the sandbox. Uses the alpha agent-framework-monty package.
12 Foundry Toolbox MCP Skills An agent that discovers MCP-based skills attached to a Foundry Toolbox and serves them via SkillsProvider(MCPSkillsSource(...)), fetching SKILL.md bodies and supplementary resources on demand.
13 Using deployed agent A sample demonstrating how to invoke an agent that has already been deployed to Foundry, showing how to interact with a hosted agent in code.

Invocations API

# Sample Description
1 Basic A minimal agent demonstrating session state management via agent_session_id in URL params/response headers.
2 Break Glass An agent demonstrating a "break glass" scenario where customizations of the API behaviors are needed, allowing for more direct control over how requests and responses are handled by the hosting layer.

Running the Agent Host Locally

Using azd

Prerequisites

  1. Azure Developer CLI (azd)

    • Install azd and the AI agent extension: azd ext install azure.ai.agents
    • Authenticated: azd auth login
  2. Azure Subscription

Create a new project

No cloning required. Create a new folder, point azd at the manifest on GitHub.

mkdir hosted-agent-framework-agent && cd hosted-agent-framework-agent

# Initialize from the manifest
azd ai agent init -m https://github.com/microsoft/agent-framework/blob/main/python/samples/04-hosting/foundry-hosted-agents/responses/01_basic/agent.manifest.yaml

Follow the instructions from azd ai agent init to complete the agent initialization. If you don't have an existing Foundry project and a model deployment, azd ai agent init will guide you through creating them.

Provision Azure Resources

This step is only needed if you don't have an existing Foundry project and model deployment.

Run the following command to provision the necessary Azure resources:

azd provision

This will create the following Azure resources:

  • A new resource group named rg-[project_name]-dev. In this guide, [project_name] will be hosted-agent-framework-agent.
  • Within the resource group, among other resources, the most important ones are:
    • A new Foundry instance
    • A new Foundry project, within which a new model deployment will be created
    • An Application Insights instance
    • A container registry, which will be used to store the container images for the hosted agent

Set Environment Variables

export FOUNDRY_PROJECT_ENDPOINT="https://<account>.services.ai.azure.com/api/projects/<project>"
export AZURE_AI_MODEL_DEPLOYMENT_NAME="<your-model-deployment-name>"
# And any other environment variables required by the sample

Or in PowerShell:

$env:FOUNDRY_PROJECT_ENDPOINT="https://<account>.services.ai.azure.com/api/projects/<project>"
$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="<your-model-deployment-name>"
# And any other environment variables required by the sample

Note: The environment variables set above are only for the current session. You will need to set them again if you open a new terminal session. if you want to set the environment variables permanently in the azd environment, you can use azd env set <name> <value>.

Running the Agent Host

azd ai agent run

Right now, the agent host should be running on http://localhost:8088

Invoking the Agent

Open another terminal, navigate to the project directory, and run the following command to invoke the agent:

azd ai agent invoke --local "Hello!"

Or you can in another terminal, without navigating to the project directory, run the following command to invoke the agent:

curl -X POST http://localhost:8088/responses -H "Content-Type: application/json" -d '{"input": "Hello!"}'

Or in PowerShell:

(Invoke-WebRequest -Uri http://localhost:8088/responses -Method POST -ContentType "application/json" -Body '{"input": "Hello!"}').Content

Using python

Prerequisites

  1. An existing Foundry project
  2. A deployed model in your Foundry project
  3. Azure CLI installed and authenticated
  4. Python 3.10 or later

Running the Agent Host with Python

Clone the repository containing the sample code:

git clone https://github.com/microsoft/agent-framework.git
cd agent-framework/python/samples/04-hosting/foundry-hosted-agents/responses

Environment setup

  1. Navigate to the sample directory you want to explore. Create and activate a virtual environment using uv (recommended):

    uv venv .venv
    
    # Windows (PowerShell)
    .venv\Scripts\Activate.ps1
    
    # Windows (Command Prompt)
    .venv\Scripts\activate.bat
    
    # macOS/Linux
    source .venv/bin/activate
    

    Note: python -m venv .venv also works, but can hang indefinitely on Windows with Microsoft Store Python due to a known ensurepip issue. Use uv venv .venv to avoid this.

  2. Install dependencies:

    uv pip install -r requirements.txt
    
  3. Create a .env file with your Foundry configuration following the env.example file in the sample.

  4. Make sure you are logged in with the Azure CLI:

    az login
    

Running the Agent Host

python main.py

Right now, the agent host should be running on http://localhost:8088

Invoking the Agent

On another terminal, run the following command to invoke the agent:

curl -X POST http://localhost:8088/responses -H "Content-Type: application/json" -d '{"input": "Hello!"}'

Or in PowerShell:

(Invoke-WebRequest -Uri http://localhost:8088/responses -Method POST -ContentType "application/json" -Body '{"input": "Hello!"}').Content

Deploying the Agent to Foundry

Once you've tested locally, deploy to Microsoft Foundry.

With an Existing Foundry Project

If you already have a Foundry project and the necessary Azure resources provisioned, you can skip the setup steps and proceed directly to deploying the agent.

After running azd ai agent init -m <agent.manifest.yaml> and following the prompts to configure your agent, you will have a project ready for deployment.

Setting Up a New Foundry Project

Follow the steps in Using azd to set up the project and provision the necessary Azure resources for your Foundry deployment.

Deploying the Agent

Once the project is setup and resources are provisioned, you can deploy the agent to Foundry by running:

azd deploy

The Foundry hosting infrastructure will inject the following environment variables into your agent at runtime:

  • FOUNDRY_PROJECT_ENDPOINT: The endpoint URL for the Foundry project where the agent is deployed.
  • AZURE_AI_MODEL_DEPLOYMENT_NAME: The name of the model deployment in your Foundry project. This is configured during the agent initialization process with azd ai agent init.
  • APPLICATIONINSIGHTS_CONNECTION_STRING: The connection string for Application Insights to enable telemetry for your agent.

This will package your agent and deploy it to the Foundry environment, making it accessible through the Foundry project endpoint. Once it's deployed, you can also access the agent through the Foundry UI.

For the full deployment guide, see the official deployment guide.

Once deployed, learn more about how to manage deployed agents in the official management guide.