# Run a Claude skill as a Microsoft Foundry hosted agent

Agent Mission Control developer docs > Claude skill on Microsoft Foundry

> How a Claude skill runs unattended inside Foundry, with Agent Framework as the host and claude-agent-sdk as the brain, and reports to AMC.

**Before you start:** A Claude skill folder (with SKILL.md) and a Microsoft Foundry project. Read [How agents connect](/developers/how-agents-connect/) first.

This path turns a Claude skill into a **Foundry hosted agent**. Foundry owns the endpoint, the sessions, the sandbox, scale-to-zero and Entra auth on the data plane. Inside the container, Microsoft Agent Framework (MAF) speaks the Foundry Responses protocol, and `claude-agent-sdk` runs the skill. AMC streams the run and shows it as steps, with tokens and cost per step.

The `foundry-hybrid-agent-creator` skill scaffolds the agent from templates. The templates already contain fixes for the failure modes agents of this shape hit in production, so a new agent starts with them instead of rediscovering them.

## Why two layers

- **Not pure MAF:** MAF's chat client reasons over a chat API. It can't load a `SKILL.md`, follow its method, run its scripts through Bash, or delegate through Task. Only the Claude Code CLI bundled in `claude-agent-sdk` can.
- **Not pure claude-agent-sdk:** that gives you a self-hosted HTTP service where you own the endpoint and the auth. See [Claude skill, self-hosted](https://www.agentmissioncontrol.ai/developers/choose-a-build-path/). The hybrid exists for when the agent must be a first-class Foundry resource: invocable over the Responses protocol, deployed as immutable versions, and visible to the platform and to AMC.

## Architecture

`Process tree inside the container`
```text
python3 main.py                      container entrypoint; Foundry starts this
  └── ResponsesHostServer :8088      agent-framework-foundry-hosting (MAF): HTTP + session only
        └── InvoiceSummarizerAgent(BaseAgent)
              │                      clientless shell: parse, Starting step, stream, envelope,
              │                      trailing markers, failed-run verdict, HITL plumbing
              ├── steps.StepReporter  maps tool calls to phase steps; copies produced items out
              └── runner.run_turn()   claude_agent_sdk.query(): the ONLY thing that reasons
                    └── claude (bundled CLI)  executes SKILL.md via the Skill tool
                          ├── Bash -> the skill's own scripts (gated by the PreToolUse hook)
                          ├── mcp__<server> -> the skill's integrations, as the instance identity
                          └── Task -> sub-agents, only if you enable them
```

| Layer | Owns | Must never |
| --- | --- | --- |
| `main.py` (MAF hosting) | HTTP on `:8088`, `/readiness`, sessions | Add a `/health` route; reason |
| `agent.py` (MAF shell) | Request parsing with defaults, refusal before spend, one turn at a time, the `Starting …` step, streaming, the envelope, trailing markers, the failed-run verdict, HITL plumbing | Hold a chat client, call a model, grow business logic |
| `runner.py` (brain wiring) | The prompt, `ClaudeAgentOptions`, the tool-policy hook, the `query()` loop, the gates, host post-processing (publishing as plain I/O) | Make judgments the skill owns |
| `steps.py` (host observer) | Mapping tool calls to phases, copying produced items out of the skill's data files, per-phase token attribution | Ask a model anything |
| The skill | The method | Be patched to fit the host |

## The rule that holds it together

**MAF never reasons.** The `BaseAgent` takes no chat client. The host may compute facts about the run (which tool was called, what a file contains, whether a regex matched) and enforce policy in code. It may not ask a model a question or compose content. Uploading the output after the turn is I/O, not reasoning, so the host does it. Having the model retype a large file through its output tokens is slow, costly and fails.

Claude models are reached through Foundry: `CLAUDE_CODE_USE_FOUNDRY=1` and the agent's Entra **instance identity**. There is no API key in the sandbox.

## What AMC sees

- A `Starting …` step the moment the request is accepted, before any model call.
- One step per skill phase, each with its own tokens and `model`.
- One step per produced item, copied from the skill's own data files.
- Host steps for publishing, red when refused.
- Trailing per-model markers with the tokens no step claimed, cost and run totals.
- A failed run ends `response.failed`, so AMC shows it as failed.
- A run that completed with issues sends one `run.outcome` marker and ends `response.completed`, so AMC shows it as **Completed with issues**.

These are this path's way of meeting the [integration contract](https://www.agentmissioncontrol.ai/developers/integration-contract/). The rest of this section walks through each piece.

## In this section

| Article | Covers |
| --- | --- |
| [Prerequisites and project setup](https://www.agentmissioncontrol.ai/developers/foundry-prerequisites-and-setup/) | Tools, Azure resources, the decisions to make first, vendoring the skill |
| [Build the agent from the templates](https://www.agentmissioncontrol.ai/developers/foundry-build-the-agent/) | Every file, the request contract, the prompt, tool policy, gates, publishing |
| [Invocation modes and session lifetime](https://www.agentmissioncontrol.ai/developers/foundry-invocation-and-sessions/) | Streaming, background, the 100 s cap, the session idle timeout |
| [Run steps, token markers and cost](https://www.agentmissioncontrol.ai/developers/foundry-steps-and-cost/) | Phases, item steps, residual tokens, the failure marker, `RunFailed` |
| [Human-in-the-loop](https://www.agentmissioncontrol.ai/developers/foundry-human-in-the-loop/) | Pausing for a person and resuming with the answer |
| [Choose models and spend ceilings](https://www.agentmissioncontrol.ai/developers/foundry-model-selection/) | Orchestrator tier, sub-agents, deployment pins, ceilings |
| [Deploy to Foundry](https://www.agentmissioncontrol.ai/developers/foundry-deploy/) | Build, `deploy.py`, identities and RBAC, version payload gotchas |
| [Verify and register in AMC](https://www.agentmissioncontrol.ai/developers/foundry-verify-and-register/) | Probes in order, first real run, pricing, registration |
| [Troubleshooting](https://www.agentmissioncontrol.ai/developers/foundry-troubleshooting/) | Symptoms, causes and fixes, and where the logs are |

## Related

- [Prerequisites and project setup](https://www.agentmissioncontrol.ai/developers/foundry-prerequisites-and-setup/)
- [Build the agent from the templates](https://www.agentmissioncontrol.ai/developers/foundry-build-the-agent/)
- [How agents connect to AMC](https://www.agentmissioncontrol.ai/developers/how-agents-connect/)
- [Choose a build path](https://www.agentmissioncontrol.ai/developers/choose-a-build-path/)

---
Source: https://www.agentmissioncontrol.ai/developers/foundry-hybrid-overview/ · Last updated 2026-10-21 · Full index: https://www.agentmissioncontrol.ai/llms.txt
