Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Build and deploy AI applications on Azure AI Foundry using Microsoft's model catalog and AI services
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
foundry-agent/create/create-hosted.md
1# Create Hosted Agent Application23Create new hosted agent applications for Microsoft Foundry, or convert existing agent projects to be Foundry-compatible using the hosting adapter.45## Quick Reference67| Property | Value |8|----------|-------|9| **Samples Repo** | `microsoft-foundry/foundry-samples` |10| **Python Samples** | `samples/python/hosted-agents/` |11| **C# Samples** | `samples/csharp/hosted-agents/` |12| **Hosted Agents Docs** | https://learn.microsoft.com/azure/ai-foundry/agents/concepts/hosted-agents |13| **Default Selection** | `Python` + `responses` + `Microsoft Agent Framework` |14| **Best For** | Creating new or converting existing agent projects for Foundry |1516## When to Use This Skill1718- Create a new hosted agent application from scratch (greenfield)19- Start from an official sample and customize it20- Convert an existing agent project to be Foundry-compatible (brownfield)21- Help user choose a language, protocol, framework, or sample for their agent2223## Workflow2425> Relative reference paths in this file are resolved from the directory containing `create.md`. For example, `./references/agentframework.md` means the file next to this document under `create/references/`, not a path relative to the runtime working directory.2627### Step 1: Determine Scenario2829Check the user's workspace for existing agent project indicators:3031- **No agent-related code found** → **Greenfield**. Proceed to Greenfield Workflow (Step 2).32- **Existing agent code present** → **Brownfield**. Proceed to Brownfield Workflow.3334### Step 2: Gather Requirements (Greenfield)3536If the user hasn't already specified, use `ask_user` to collect in this order:3738**Language:** Python (default) or C#.3940**Protocol:**4142| Protocol | Best For |43|----------|----------|44| `responses` (default) | Conversational agents using the OpenAI-compatible `/responses` contract |45| `invocations` | Arbitrary payloads, custom SSE behavior, protocol bridges, webhook-style callers, or client-managed sessions |4647**Framework:**4849The paths below refer to the framework-level directories in the Foundry sample repo. Choose the protocol-specific subpath in Step 3.5051| Framework | Python Path | C# Path |52|-----------|-------------|---------|53| Microsoft Agent Framework (default) | `agent-framework` | `agent-framework` |54| LangGraph | `bring-your-own` | ❌ Python only |55| Custom | `bring-your-own` | `bring-your-own` |5657> ⚠️ **Warning:** LangGraph is Python-only. For C# + LangGraph, suggest Microsoft Agent Framework or Custom instead.5859> 💡 **Tip:** In the sample repo, **Custom** corresponds to the **Bring Your Own** lanes.6061> 💡 **Tip:** LangGraph samples are under **Bring Your Own**, not under a separate top-level `langgraph` directory.6263If user has no specific preference, suggest Python + `responses` + Microsoft Agent Framework as defaults.6465In non-interactive or YOLO mode, default to Python + `responses` + Microsoft Agent Framework unless the user's request clearly requires another supported combination.6667### Step 3: Browse and Select Sample6869List available samples using the GitHub API. First resolve the `sample_browse_path` (the browse root) from the selected language, protocol, and framework:7071| Selection | Sample Browse Path |72|-----------|--------------------|73| Python + Microsoft Agent Framework + `responses` | `samples/python/hosted-agents/agent-framework/responses/` |74| Python + Microsoft Agent Framework + `invocations` | `samples/python/hosted-agents/agent-framework/invocations/` |75| Python + LangGraph | `samples/python/hosted-agents/bring-your-own/{protocol}/langgraph-chat/` |76| Python + Custom | `samples/python/hosted-agents/bring-your-own/{protocol}/` |77| C# + Microsoft Agent Framework + `responses` | `samples/csharp/hosted-agents/agent-framework/` |78| C# + Microsoft Agent Framework + `invocations` | `samples/csharp/hosted-agents/agent-framework/invocations-echo-agent/` |79| C# + Custom | `samples/csharp/hosted-agents/bring-your-own/{protocol}/` |8081Use the chosen lane to browse the repo under `sample_browse_path`:8283```84GET https://api.github.com/repos/microsoft-foundry/foundry-samples/contents/{sample_browse_path}85```8687If the user has specified what they want the agent to do, choose the most relevant or most simple sample under that lane and record its exact `selected_sample_path`. Only if the user has not given any preferences, present the sample directories under `sample_browse_path` to the user and help them choose based on their requirements (e.g., RAG, tools, multi-agent workflows, HITL).8889If the requested combination does not have a real sample, say so clearly and suggest the nearest supported lane.9091> ⚠️ **Tools:** If the user wants an agent with tools (web search, AI search, code interpreter, MCP servers, etc.), select the `toolbox` samples. These samples include Foundry Toolbox integration in the sample code out of the box, but the user still needs an actual toolbox resource and must configure its endpoint/auth as described in [references/toolbox.md](references/toolbox.md) (see Step 1).9293### Step 4: Download Sample Files9495Download only the selected sample directory — do NOT clone the entire repo. Preserve the directory structure by creating subdirectories as needed.9697Use the exact `selected_sample_path` selected in Step 3.9899**Using `gh` CLI (preferred if available):**100```bash101gh api repos/microsoft-foundry/foundry-samples/contents/{selected_sample_path} \102--jq '.[] | select(.type=="file") | .download_url' | while read url; do103filepath="${url##*/{selected_sample_path}/}"104mkdir -p "$(dirname "$filepath")"105curl -sL "$url" -o "$filepath"106done107```108109**Using curl (fallback):**110```bash111curl -s "https://api.github.com/repos/microsoft-foundry/foundry-samples/contents/{selected_sample_path}" | \112jq -r '.[] | select(.type=="file") | .path + "\t" + .download_url' | while IFS=$'\t' read path url; do113relpath="${path#{selected_sample_path}/}"114mkdir -p "$(dirname "$relpath")"115curl -sL "$url" -o "$relpath"116done117```118119For nested directories, recursively fetch the GitHub contents API for entries where `type == "dir"` and repeat the download for each.120121### Step 5: Customize and Implement1221231. Read the sample's `README.md` and `agent.yaml` or `agent.manifest.yaml` to understand its structure1242. Read the sample code to understand patterns, protocol handling, and dependencies used1253. If using Agent Framework, follow the best practices in [references/agentframework.md](references/agentframework.md)1264. Implement the user's specific requirements on top of the sample1275. Update configuration (`.env`, dependency files, `agent.yaml`, `agent.manifest.yaml`) as needed, and keep the selected protocol consistent across code and config1286. Ensure the project is in a runnable state129130### Step 6: Verify Startup1311321. Install dependencies (use virtual environment for Python)1332. Ask user to provide values for `.env` variables if placeholders were used using `ask_user` tool.1343. Run the main entrypoint1354. Fix startup errors and retry if needed1365. Send a protocol-appropriate test request to the correct endpoint:137- `responses` → `POST http://localhost:8088/responses`138- `invocations` → `POST http://localhost:8088/invocations`1396. Fix any errors from the test request and retry until it succeeds1407. Once startup and test request succeed, stop the server to prevent resource usage141142**Guardrails:**143- ✅ Perform real run to catch startup errors144- ✅ Cleanup after verification (stop server)145- ✅ Ignore auth/connection/timeout errors (expected without Azure config)146- ❌ Don't wait for user input or create test scripts147148## Brownfield Workflow: Convert Existing Agent to Hosted Agent149150Use this workflow when the user has an existing agent project that needs to be made compatible with Foundry hosted agent deployment. The key requirement is wrapping the existing agent with the appropriate hosting adapter.151152### Step B1: Analyze Existing Project153154Scan the project to determine:1551561. **Language** — Python (look for `requirements.txt`, `pyproject.toml`, `*.py`) or C# (look for `*.csproj`, `*.cs`)1572. **Framework** — Identify which agent framework is in use:158159| Indicator | Framework |160|-----------|-----------|161| Imports from `agent_framework` or `Microsoft.Agents.AI` | Microsoft Agent Framework |162| Imports from `langgraph`, `langchain` | LangGraph |163| No recognized framework imports, or other frameworks (e.g., Semantic Kernel, AutoGen, custom code) | Custom |1641653. **Target protocol** — If the user has not specified one, infer whether the project should target `responses` or `invocations` based on the existing caller contract1664. **Entry point** — Identify the main script/entrypoint that creates and runs the agent1675. **Agent object** — Identify the agent instance that needs to be wrapped (e.g., a `BaseAgent` subclass, a compiled `StateGraph`, or an existing server/app)168169### Step B2: Add Hosting Adapter Dependency170171Add the correct adapter package based on framework, language, and protocol. Get the latest version from the package registry — do not hardcode versions.172173**Python adapter packages:**174175| Framework | Package(s) |176|-----------|------------|177| Microsoft Agent Framework | `responses`: `agent-framework-foundry-hosting`; `invocations`: `agent-framework-foundry-hosting` |178| LangGraph | `responses`: `azure-ai-agentserver-responses` + `azure-ai-agentserver-core`; `invocations`: `azure-ai-agentserver-invocations` + `azure-ai-agentserver-core` |179| Custom | `responses`: `azure-ai-agentserver-responses`; `invocations`: `azure-ai-agentserver-invocations` |180181**.NET adapter packages:**182183| Framework | Package(s) |184|-----------|------------|185| Microsoft Agent Framework | `responses`: `Microsoft.Agents.AI.Foundry.Hosting`; `invocations`: `Microsoft.Agents.AI.Foundry.Hosting` + `Azure.AI.AgentServer.Invocations` |186| Custom | `responses`: `Azure.AI.AgentServer.Responses`; `invocations`: `Azure.AI.AgentServer.Invocations` |187188Add the package to the project's dependency file (`requirements.txt`, `pyproject.toml`, or `.csproj`). For Python, also add `python-dotenv` if not present.189190### Step B3: Wrap Agent with Hosting Adapter191192Modify the project's main entrypoint to wrap the existing agent with the adapter. The approach differs by framework and protocol:193194**Microsoft Agent Framework + `responses` (Python):**195- Import `ResponsesHostServer` from the adapter package196- Pass the agent instance (from `agent_framework` package) to the adapter197- Call `.run()` on the adapter as the default entrypoint198199**Microsoft Agent Framework + `invocations` (Python):**200- Use `InvocationAgentServerHost()`201- Implement an `@app.invoke_handler`202- Manage session state if the agent needs multi-turn memory203204**Microsoft Agent Framework + `responses` (C#):**205- Register Foundry responses hosting and map the `responses` protocol206207**Microsoft Agent Framework + `invocations` (C#):**208- Register invocations services and an invocation handler209- Map the `invocations` protocol210211**LangGraph:**212- Python only213- Follow the `bring-your-own/{protocol}/langgraph-chat` sample for the selected protocol lane214215**Custom:**216- Follow the corresponding `bring-your-own/{protocol}` sample for the selected language217- Prefer the protocol SDK sample for the selected lane instead of inventing a custom contract when a sample already exists218219> ⚠️ **Warning:** The adapter MUST be the default entrypoint (no flags required to start). This is required for both local debugging and containerized deployment.220221### Step B4: Configure Environment2222231. Create or update a `.env` file with required environment variables (project endpoint, model deployment name, etc.)2242. For Python: ensure the code uses `load_dotenv(override=False)` so Foundry-injected environment variables are available at runtime.2253. If the project uses Azure credentials: ensure Python uses `azure.identity.DefaultAzureCredential` for **local development**. In production, use `ManagedIdentityCredential`. See [auth-best-practices.md](../../references/auth-best-practices.md)226227### Step B5: Create agent.yaml228229Create an `agent.yaml` file in the project root. This file defines the agent's metadata and deployment configuration for Foundry. Required fields:230231- `name` — Unique identifier (alphanumeric + hyphens, max 63 chars)232- `description` — What the agent does233- `template.kind` — Must be `hosted`234- `template.protocols` — Must include the selected protocol and matching version from the chosen sample235- `template.environment_variables` — List all environment variables the agent needs at runtime236237Refer to the chosen sample's `agent.yaml` or `agent.manifest.yaml` in the [foundry-samples repo](https://github.com/microsoft-foundry/foundry-samples/tree/main/samples/python/hosted-agents) for the exact schema.238239### Step B6: Create Dockerfile240241Create a `Dockerfile` if one doesn't exist. Requirements:242243- Base image appropriate for the language (e.g., `python:3.12-slim` for Python, `mcr.microsoft.com/dotnet/sdk` for C#)244- Copy source code into the container245- Install dependencies246- Expose port **8088** (the adapter's default port)247- Set the main entrypoint as the CMD248249> ⚠️ **Warning:** When building, MUST use `--platform linux/amd64`. Hosted agents run on Linux AMD64 infrastructure. Images built for other architectures (e.g., ARM64 on Apple Silicon) will fail.250251Refer to the chosen sample's `Dockerfile` in the [foundry-samples repo](https://github.com/microsoft-foundry/foundry-samples/tree/main/samples/python/hosted-agents) for the exact pattern.252253### Step B7: Test Locally2542551. Install dependencies (use virtual environment for Python)2562. Run the main entrypoint — the adapter should start an HTTP server on `localhost:8088`2573. Send a protocol-appropriate test request to either `/responses` or `/invocations`2584. Verify the response follows the expected protocol shape for the selected lane2595. Fix any errors and retry until the test request succeeds2606. Stop the server261262> 💡 **Tip:** If auth/connection errors occur for Azure services, that's expected without real Azure credentials configured. The key validation is that the HTTP server starts and accepts requests.263264## Common Guidelines265266IMPORTANT: YOU MUST FOLLOW THESE.267268Apply these to both greenfield and brownfield projects:2692701. **Sample-first** — Start from a real sample in the current `foundry-samples` repo. Do not invent unsupported combinations, paths, or protocol behavior.2712722. **Protocol consistency** — Keep the selected protocol consistent across sample choice, code, config, and verification steps.2732743. **Logging** — Implement proper logging using the language's standard logging framework (Python `logging` module, .NET `ILogger`). Hosted agents stream container stdout/stderr logs to Foundry, so all log output is visible via the troubleshoot workflow. Use structured log levels (INFO, WARNING, ERROR) and include context like request IDs and agent names.2752764. **Framework-specific best practices** — When using Microsoft Agent Framework, read the [Agent Framework best practices](references/agentframework.md) for hosting adapter setup, credential patterns, and debugging guidance.2772785. **Deploy handoff** — After the agent has been created and local verification succeeds, explicitly tell the user that they can deploy the agent if they want, and ask them to say `deploy agent to foundry` to continue with the deploy sub-skill.2792806. **Tool integration** — Hosted agents access tools through [Foundry Toolbox](references/toolbox.md), NOT by wiring tools directly. If the user needs tools (web search, AI search, code execution, MCP servers, etc.), follow the toolbox integration guide. The toolbox provides a single MCP-compatible endpoint that handles credential injection and tool discovery.2812827. **Reserved environment variables** — The Foundry platform injects environment variables into every hosted agent container at startup. You MUST NOT generate, suggest, or configure any of these in `.env` files, `agent.yaml` `environment_variables`, or application code:283284**Blocked prefixes** (any variable starting with these is reserved):285- `FOUNDRY_*` — platform-injected identity, session, project, and toolset variables286- `AGENT_*` — reserved for platform use287288**Exact reserved names** (platform-managed, overwritten at runtime):289- `PORT` — HTTP listen port (default `8088`)290- `HOME` — session filesystem path (`/home/session`)291- `SSE_KEEPALIVE_INTERVAL` — SSE keep-alive config292- `APPLICATIONINSIGHTS_CONNECTION_STRING` — observability293- `OTEL_EXPORTER_OTLP_ENDPOINT` — OTLP collector endpoint294295**Key `FOUNDRY_*` variables available at runtime** (read-only, do not set):296- `FOUNDRY_PROJECT_ENDPOINT` — project endpoint URL for calling Azure services297- `FOUNDRY_AGENT_NAME` — the deployed agent's name298- `FOUNDRY_AGENT_VERSION` — the deployed agent's version299- `FOUNDRY_TOOLBOX_ENDPOINT` — MCP-compatible toolbox endpoint (if toolbox is configured)300301If user code needs to read these values at runtime (e.g., `FOUNDRY_PROJECT_ENDPOINT` to call Azure services), read them from the environment — do not set or override them.302303## Coding Tips304305Use these when generating or modifying project code:3063071. **Create a `.gitignore` file** — After generating code, create a `.gitignore` file if one does not already exist. If one already exists, update it as needed.308- Choose the ignore entries based on the language, framework, and files generated.309- Do not leave the project with no ignored files.310- For Python projects, `.venv/` MUST be ignored at a minimum.311312## Non-Interactive / YOLO Mode313314When running in non-interactive mode (e.g., YOLO mode), skip selection prompts and use these defaults unless the user has already specified otherwise:315316- **Language** — `Python`317- **Protocol** — `responses`318- **Framework** — `Microsoft Agent Framework`319320If the user's request clearly requires another supported lane, use that lane instead of forcing the defaults.321322## Error Handling323324| Error | Cause | Resolution |325|-------|-------|------------|326| GitHub API rate limit | Too many requests | Authenticate with `gh auth login` |327| `gh` not available | CLI not installed | Use curl REST API fallback |328| Sample not found | Path changed in repo or selected lane has no matching sample | List the selected parent directory again and choose a current sample |329| Requested combination not supported | Example: C# + LangGraph | Explain the gap and switch to the nearest supported lane |330| Protocol mismatch | Code, `agent.yaml`, and test request are not aligned | Make all three match the selected protocol |331| Dependency install fails | Version conflicts | Use versions from the selected sample's own dependency file |332