Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 13 additions & 15 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,32 +1,29 @@
# Contributing to Microsoft Foundry Samples

This repository contains official Microsoft Foundry documentation samples. Changes are submitted as pull requests directly to this repository.
This repository contains official Microsoft Foundry documentation samples. The contents are published automatically from a private staging repository and are not edited directly here.

## Reporting Issues

If you find a bug, have a question, or want to suggest an improvement to an existing sample, please [open an issue](https://github.com/microsoft-foundry/foundry-samples/issues/new) on this repository. We welcome feedback from everyone!

Before starting a substantial change, check for an existing issue. Open one when discussion or design agreement would help avoid duplicate work.
## Contributing Changes (Microsoft Contributors)

## Contributing Changes
Sample contributions are currently limited to Microsoft Foundry teams.

Sample contributions are currently limited to Microsoft Foundry teams with permission to create a branch in this repository. Fork pull requests cannot satisfy the intentionally failing `trusted` gate, so sample changes must use a same-repository branch.
All changes — new samples, updates, and bug fixes — are submitted through the private staging repository [`foundry-samples-pr`](https://github.com/microsoft-foundry/foundry-samples-pr). Changes merged there are automatically synced to this public repository on a nightly basis.

Contributors should always submit publishable changes through a public same-repository pull request. Maintainers may independently operate a separate bridge for approved eligible content already in the private repository; contributors must not dispatch it.
> [!NOTE]
> The link above will return a **404** until you've completed step 1 below.

1. **Create a branch in this repository.** Use a same-repository branch for all sample changes.
2. **Make a focused change.** Keep each pull request scoped to one sample, fix, or related set of updates. Follow the conventions in the surrounding sample.
3. **Respect file ownership.** Review [CODEOWNERS](.github/CODEOWNERS) before editing. The listed owners will be requested when their files are changed.
4. **Validate locally.** Run the setup, build, test, or sample-specific validation documented by the affected sample. Never commit credentials, local environment files, or generated secrets.
5. **Open a pull request against `main`.** In the pull request description, explain what changed, why it changed, and the local validation you ran. Link the relevant issue when one exists.
### How to get started

### Pull request checks
1. **Join the `microsoft-foundry` GitHub organization.** Navigate to the organization page on the Open Source Management Portal and click **Join**:

Pull requests run repository validation automatically:
<https://repos.opensource.microsoft.com/orgs/microsoft-foundry>

- The required `trusted` check must pass.
- Review and address the other checks reported on the pull request.
- Contributor pull requests are not merged automatically; after required checks and review, a maintainer triggers the merge.
2. **Access the staging repository.** Once you've joined the org, you'll be able to view [`foundry-samples-pr`](https://github.com/microsoft-foundry/foundry-samples-pr).

3. **Follow the contributing guide there.** The `foundry-samples-pr` repository has its own [`CONTRIBUTING.md`](https://github.com/microsoft-foundry/foundry-samples-pr/blob/main/CONTRIBUTING.md) with full instructions for setting up write access, creating a branch, and submitting a pull request.

## Contributor License Agreement

Expand All @@ -35,3 +32,4 @@ This project requires a Contributor License Agreement (CLA). When you submit a p
## Code of Conduct

This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information, see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com).

3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ Use the samples in this repository to try out Microsoft Foundry scenarios on you

Found a bug or have a suggestion? [Open an issue](https://github.com/microsoft-foundry/foundry-samples/issues/new) — we welcome feedback from everyone!

Microsoft contributors with permission to create a branch in this repository can contribute a sample or fix by opening a pull request directly against `main`. Pull requests must pass the required `trusted` check and are merged by a maintainer. See the [contributing guidelines](CONTRIBUTING.md) for setup, validation, and review details.
Sample contributions are submitted through a private staging repository. If you're a Microsoft employee or contractor, see the [contributing guidelines](CONTRIBUTING.md) for how to get started.

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#
# This file is autogenerated by pip-compile with Python 3.13
# This file is autogenerated by pip-compile with Python 3.12
# by the following command:
#
# pip-compile --no-annotate --output-file=requirements.txt requirements.in
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Coding Agent Instructions

This project is a **Microsoft Foundry hosted agent** — a containerized AI agent that runs in [Foundry Agent Service](https://learn.microsoft.com/en-us/azure/foundry/agents/concepts/hosted-agents). The platform handles containerization, hosting, security, scaling, and observability so you can focus on agent logic.

## Key files

- `Dockerfile` — container definition

## Development workflow

The **Azure Developer CLI (`azd`)** manages the full lifecycle:

```bash
azd ai agent run # Run locally on http://localhost:8088
azd ai agent invoke --local "your message" # Test the local agent
azd deploy # Deploy to Foundry
azd ai agent invoke "your message" # Invoke the deployed agent
```

## Microsoft Foundry Skill

Install the **Microsoft Foundry Skill** for guided deployment, evaluation, and troubleshooting workflows.

Direct install (preferred, works with any coding agent):

```bash
npx skills add https://github.com/microsoft/azure-skills --skill microsoft-foundry
```

Or install the Azure Skills Plugin:

- **Copilot CLI**: `/plugin marketplace add microsoft/azure-skills` then `/plugin install azure@azure-skills`
- **Claude Code**: `/plugin install azure@claude-plugins-official`

Then ask naturally, e.g. `Use the Microsoft Foundry Skill to deploy this agent.`

## References

- [Hosted agents overview](https://learn.microsoft.com/en-us/azure/foundry/agents/concepts/hosted-agents)
- [Microsoft Foundry Skill](https://learn.microsoft.com/en-us/azure/foundry/how-to/develop/use-microsoft-foundry-skill)
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# CLAUDE.md

This project uses [AGENTS.md](./AGENTS.md) as the single source of truth for coding agent instructions. The import below loads it into Claude Code's context.

@AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
<!-- Begin standard disclaimer — do not modify -->
**IMPORTANT!** All samples and other resources made available in this GitHub repository ("samples") are designed to assist in accelerating development of agents, solutions, and agent workflows for various scenarios. Review all provided resources and carefully test output behavior in the context of your use case. AI responses may be inaccurate and AI actions should be monitored with human oversight. Learn more in the transparency documents for [Agent Service](https://learn.microsoft.com/en-us/azure/ai-foundry/responsible-ai/agents/transparency-note) and [Agent Framework](https://github.com/microsoft/agent-framework/blob/main/TRANSPARENCY_FAQ.md).

Agents, solutions, or other output you create may be subject to legal and regulatory requirements, may require licenses, or may not be suitable for all industries, scenarios, or use cases. By using any sample, you are acknowledging that any output created using those samples are solely your responsibility, and that you will comply with all applicable laws, regulations, and relevant safety standards, terms of service, and codes of conduct.

Third-party samples contained in this folder are subject to their own designated terms, and they have not been tested or verified by Microsoft or its affiliates.

Microsoft has no responsibility to you or others with respect to any of these samples or any resulting output.
<!-- End standard disclaimer -->

# LangGraph Toolbox User Identity Agent (Responses)

This sample hosts a LangGraph ReAct agent on Microsoft Foundry over the
Responses protocol using
[`langchain_azure_ai.agents.hosting.ResponsesHostServer`](https://github.com/langchain-ai/langchain-azure/tree/main/libs/azure-ai/langchain_azure_ai/agents/hosting).
It loads tools from a Foundry Toolbox through
`langchain_azure_ai.tools.AzureAIProjectToolbox`.

The layered deployment provisions three MCP integrations:

- WorkIQ Mail with `UserEntraToken`
- WorkIQ Calendar with `UserEntraToken`
- GitHub MCP with managed OAuth2

The toolbox is named `langgraph-toolbox-user-identity-tools` so it does not
collide with shared toolboxes in the Foundry project.

## How it works

1. The Foundry infrastructure layer provisions the project and model.
2. The dependent Bicep layer provisions the connections before the toolbox and
hosted agent are deployed.
3. `ResponsesHostServer` exposes the OpenAI-compatible `/responses` endpoint
and manages Responses streaming and conversation history.
4. On the first request, `AzureAIProjectToolbox` resolves `TOOLBOX_NAME` and
loads the toolbox tools as LangChain tools.
5. `langchain.agents.create_agent` builds the LangGraph ReAct agent.
6. If a connection requires consent, the tool error handler recognizes MCP
error `-32006` and returns the validated consent URL to the caller.

Tool loading is lazy so the hosted agent can pass readiness checks before an
upstream MCP server finishes warming up.

## Prerequisites

- Python 3.12+
- Azure Developer CLI (`azd`) 1.25 or later
- The Microsoft Foundry `azd` extension
- An Azure subscription where you can create Foundry resources

Install the extension and sign in:

```bash
azd ext install microsoft.foundry
azd auth login
```

## Initialize and deploy

Create a directory and initialize it from this sample:

```bash
mkdir langgraph-toolbox-user-identity
cd langgraph-toolbox-user-identity
azd ai agent init -m https://github.com/microsoft-foundry/foundry-samples/blob/main/samples/python/hosted-agents/langgraph/responses/03-langgraph-toolbox-user-identity/azure.yaml
```

Provision the Foundry layer, followed by the dependent
[connections Bicep layer](infra/connections/main.bicep):

```bash
azd provision
```

Deploy the hosted agent:

```bash
azd deploy
```

Invoke it:

```bash
azd ai agent invoke "Summarize my upcoming calendar events."
```

## Run locally

From `src/toolbox-langgraph-user-identity`, create a local environment:

```bash
cp .env.example .env
python -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements.txt
```

Set `FOUNDRY_PROJECT_ENDPOINT`, `AZURE_AI_MODEL_DEPLOYMENT_NAME`, and
`TOOLBOX_NAME` in `.env`. The project must already contain the connections and
toolbox declared by the sample; running `azd provision` creates them.

Start the server:

```bash
python main.py
```

In another terminal, invoke the local Responses endpoint:

```bash
curl -X POST http://localhost:8088/responses \
-H "Content-Type: application/json" \
-d '{"input":"Summarize my upcoming calendar events."}'
```

You can also use `azd`:

```bash
azd ai agent run
azd ai agent invoke --local "Summarize my upcoming calendar events."
```

## User consent

The WorkIQ connections use the calling user's Microsoft Entra identity. The
GitHub connection uses Foundry-managed OAuth2. A user may need to grant consent
before a tool can access their data.

When the Foundry MCP gateway returns consent error `-32006`, the agent responds
with a URL on `consent.azure-apim.net`. Open that URL, complete the consent
flow, and retry the request. The implementation accepts only URLs whose host is
exactly `consent.azure-apim.net`.

## Configuration

| Variable | Description |
| --- | --- |
| `FOUNDRY_PROJECT_ENDPOINT` | Foundry project endpoint; injected in hosted containers. |
| `AZURE_AI_MODEL_DEPLOYMENT_NAME` | Chat model deployment name. |
| `TOOLBOX_NAME` | Foundry Toolbox name; defaults to `langgraph-toolbox-user-identity-tools` through `azure.yaml`. |
| `PORT` | Local listening port; defaults to `8088`. |

## Troubleshooting

### The agent reports that consent is required

Open the returned consent URL, authorize the connection, and retry the same
request.

### The agent loads no tools

Verify that `TOOLBOX_NAME` matches a toolbox in the project identified by
`FOUNDRY_PROJECT_ENDPOINT`, and confirm that the toolbox version containing the
three MCP tools is the default version.

### A tool schema is rejected

The sample repairs the common case where an object schema omits `properties`.
For other schema errors, inspect the schema returned by the upstream MCP server.
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# yaml-language-server: $schema=https://raw.githubusercontent.com/Azure/azure-dev/main/schemas/v1.0/azure.yaml.json

requiredVersions:
extensions:
azure.ai.agents: '>=1.0.0-beta.6'
name: toolbox-langgraph-user-identity
services:
ai-project:
host: azure.ai.project
deployments:
- name: gpt-5.4-mini
model:
format: OpenAI
name: gpt-5.4-mini
version: '2026-03-17'
sku:
name: GlobalStandard
capacity: 10
langgraph-toolbox-user-identity-tools:
host: azure.ai.toolbox
uses:
- ai-project
tools:
- type: mcp
server_label: workiq-mail
connection: workiq-mail-conn
server_url: https://agent365.svc.cloud.microsoft/agents/servers/mcp_MailTools
- type: mcp
server_label: workiq-calendar
connection: workiq-calendar-conn
server_url: https://agent365.svc.cloud.microsoft/agents/servers/mcp_CalendarTools
- type: mcp
server_label: github
connection: github-oauth-conn
server_url: https://api.githubcopilot.com/mcp
toolbox-langgraph-user-identity:
host: azure.ai.agent
metadata:
tags:
- AI Agent Hosting
- LangGraph
- Toolbox
- MCP
- OAuth2
- User Identity
- Microsoft Foundry
project: src/toolbox-langgraph-user-identity
language: python
codeConfiguration:
runtime: python_3_13
entryPoint: main.py
uses:
- ai-project
- langgraph-toolbox-user-identity-tools
kind: hosted
name: toolbox-langgraph-user-identity
displayName: LangGraph Toolbox User Identity Agent
description: LangGraph agent with toolbox MCP tools using user identity and OAuth.
protocols:
- protocol: responses
version: 2.0.0
environmentVariables:
- name: AZURE_AI_MODEL_DEPLOYMENT_NAME
value: ${AZURE_AI_MODEL_DEPLOYMENT_NAME}
- name: TOOLBOX_NAME
value: langgraph-toolbox-user-identity-tools
container:
resources:
cpu: '0.5'
memory: 1Gi
infra:
layers:
- provider: microsoft.foundry
path: infra/foundry
name: foundry
- provider: bicep
path: infra/connections
name: connections
dependsOn:
- foundry
Loading
Loading