Run a Claude skill as a Microsoft Foundry hosted agent
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.
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 inclaude-agent-sdkcan. - 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. 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
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.outcomemarker and endsresponse.completed, so AMC shows it as Completed with issues.
These are this path's way of meeting the integration contract. The rest of this section walks through each piece.
In this section
| Article | Covers |
|---|---|
| Prerequisites and project setup | Tools, Azure resources, the decisions to make first, vendoring the skill |
| Build the agent from the templates | Every file, the request contract, the prompt, tool policy, gates, publishing |
| Invocation modes and session lifetime | Streaming, background, the 100 s cap, the session idle timeout |
| Run steps, token markers and cost | Phases, item steps, residual tokens, the failure marker, RunFailed |
| Human-in-the-loop | Pausing for a person and resuming with the answer |
| Choose models and spend ceilings | Orchestrator tier, sub-agents, deployment pins, ceilings |
| Deploy to Foundry | Build, deploy.py, identities and RBAC, version payload gotchas |
| Verify and register in AMC | Probes in order, first real run, pricing, registration |
| Troubleshooting | Symptoms, causes and fixes, and where the logs are |
Related
Last updated 2026-10-21