# Invocation modes and session lifetime

Agent Mission Control developer docs > Claude skill on Microsoft Foundry

> The three ways to call a hosted agent, the session idle timeout that kills long runs, and how to size the run timeout.

**Before you start:** An agent built from the templates. See [Build the agent from the templates](/developers/foundry-build-the-agent/).

## The endpoint

The endpoint is agent-scoped and isn't in the agent record. `deploy.py` prints it:

```text
<your-foundry-project-endpoint>/agents/<agent-name>/endpoint/protocols/openai/responses?api-version=v1
```

The project-level `openai/v1/responses` path returns 400. Callers authenticate with an Entra token for `https://ai.azure.com`.

## Three calls

| Call | Served by | Limit | Use for |
| --- | --- | --- | --- |
| `POST {"input": …}` (no stream, no background) | `_run_once` | About **100 s**, platform-capped. A real run never finishes. | `{"mode":"preflight"}` and local tests |
| `POST {"input": …, "stream": true}` | `_run_stream` | Session idle timeout and `RUN_TIMEOUT_SECONDS` | A watching consumer: AMC, its scheduler, a person. Steps arrive live; the run ends `completed` or `failed`. |
| `POST {"input": …, "background": true}`, then `GET …/responses/{id}` | `_run_once` | Same | A raw scheduler that can't hold a stream. Read the envelope's `status`. |

### What each mode means

- **A cut stream cancels the turn.** So a streaming client's own timeout must exceed `RUN_TIMEOUT_SECONDS`, and a probe that closes early has still spent the minutes it watched.
- **Background runs don't depend on the client,** but the stored response holds only the final items: no `Starting …` step and no phase steps. Its status reads `completed` even when the envelope says `failed`. See [Run steps, token markers and cost](https://www.agentmissioncontrol.ai/developers/foundry-steps-and-cost/).
- **Stale background responses can't be cancelled** through the endpoint once the container is gone; they stay `in_progress`. The shell logs `Responses resilience: DISABLED` at start, which is the platform saying so.
- **One turn per session.** A second request during a turn is refused before spend.

## The session idle timeout

This is the one setting that silently kills every long run until you set it. `session_configuration.idle_timeout_seconds` on the agent version tells the platform to suspend the sandbox after that many seconds without an **inbound request**. The default is **900 s**; the range is **120 to 3600**.

A running turn, an open stream with keepalives, a background response in progress, and completed output items do not count as activity. Without the setting, a run dies at about 15 minutes: the stream is cut, a background response sticks at `in_progress`, there's no envelope, and the spend is lost. It's easy to misread as gateway flakiness or the model.

- `deploy.py` sets it from `SESSION_IDLE_TIMEOUT_SECONDS`, default 3600. Set the maximum for any run over about 10 minutes.
- A run that can exceed 60 minutes also needs its caller to `GET /responses/{id}` within the window. A GET is an inbound request. Polling every 60 s is good hygiene either way.
- Between HITL turns the same timer applies: an unanswered question past the timeout lands the resumed turn in a fresh sandbox with an empty `/work`.

## RUN_TIMEOUT_SECONDS

A different limit: the wall clock for one turn. When it expires the runner terminates the CLI and the envelope reports `timed_out`. The spend up to that point is real.

- It must be at least 300 s below the session idle timeout. `deploy.py` refuses otherwise. The idle timer starts at the inbound request and the runner still needs time to end the turn and write the envelope.
- With the 3600 s maximum, the default is 3300.
- Size it at 2× or more of a measured run's wall clock.
- If the skill calls MCP servers, the per-turn token lives about 60 to 90 minutes. Keep the timeout inside that.

## What a scheduler sends

`Scheduler body`
```json
{"input": "{}", "background": true}
```

Every request field is optional with a server-side default, so `{}` is a full run. A raw scheduler then polls by id and alerts on a `failed` envelope status or a missing run. AMC streams instead and treats `response.failed` as a failed run. See [how AMC calls this agent](https://www.agentmissioncontrol.ai/developers/foundry-verify-and-register/).

## Sizing

Illustrative only: a research-and-write skill on Sonnet took on the order of 60 to 90 turns and 25 to 35 minutes. On Opus the same skill took more turns and roughly twice the cost. Measure your own skill with one dry run, then set ceilings at about 1.5× and `RUN_TIMEOUT_SECONDS` at 2× or more of the wall clock.

## Related

- [Run steps, token markers and cost reporting](https://www.agentmissioncontrol.ai/developers/foundry-steps-and-cost/)
- [Deploy to Foundry](https://www.agentmissioncontrol.ai/developers/foundry-deploy/)
- [Choose models and spend ceilings](https://www.agentmissioncontrol.ai/developers/foundry-model-selection/)

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