> This page is for version 0.5.0.
> For other versions, use one of these documentation indexes:
> - Main (default): https://docs.nvidia.com/nemo/gym/main/llms.txt
> - 0.7.0: https://docs.nvidia.com/nemo/gym/v0.7.0/llms.txt
> - 0.6.0: https://docs.nvidia.com/nemo/gym/v0.6.0/llms.txt
> - 0.5.1: https://docs.nvidia.com/nemo/gym/v0.5.1/llms.txt
> - 0.5.0: https://docs.nvidia.com/nemo/gym/v0.5.0/llms.txt
> - 0.4.0: https://docs.nvidia.com/nemo/gym/v0.4.0/llms.txt
> - 0.3.0: https://docs.nvidia.com/nemo/gym/v0.3.0/llms.txt
> - 0.2.1: https://docs.nvidia.com/nemo/gym/v0.2.1/llms.txt

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.nvidia.com/nemo/gym/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.nvidia.com/nemo/gym/_mcp/server.

# nemo_gym.agents.base_responses_api_agent

## Module Contents

### Classes

| Name                                                                                                             | Description                                                                                                 |
| ---------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| [`AgentCloseSessionRequest`](#nemo_gym-agents-base_responses_api_agent-AgentCloseSessionRequest)                 | Close agent-server state.                                                                                   |
| [`AgentCloseSessionResponse`](#nemo_gym-agents-base_responses_api_agent-AgentCloseSessionResponse)               | Confirm closure and return captured observations.                                                           |
| [`AgentSeedRejectedError`](#nemo_gym-agents-base_responses_api_agent-AgentSeedRejectedError)                     | Refuse an agent session seed this agent cannot serve, such as a grant or sandbox it does not support.       |
| [`AgentSeedSessionRequest`](#nemo_gym-agents-base_responses_api_agent-AgentSeedSessionRequest)                   | Idempotently initialize agent-server state under a caller-assigned identifier.                              |
| [`AgentSeedSessionResponse`](#nemo_gym-agents-base_responses_api_agent-AgentSeedSessionResponse)                 | Confirm the caller-assigned agent session identifier and declare what the harness can use.                  |
| [`AgentSessionCapabilitiesResponse`](#nemo_gym-agents-base_responses_api_agent-AgentSessionCapabilitiesResponse) | What this adapter's sessions can do, asked before any session is seeded.                                    |
| [`AgentSessionConflictError`](#nemo_gym-agents-base_responses_api_agent-AgentSessionConflictError)               | Refuse an agent session request that conflicts with what this agent recorded for the session.               |
| [`AgentSessionSetupError`](#nemo_gym-agents-base_responses_api_agent-AgentSessionSetupError)                     | Retain incomplete setup for close while propagating the original setup error.                               |
| [`AgentSessionState`](#nemo_gym-agents-base_responses_api_agent-AgentSessionState)                               | Harness-owned session state with the immutable caller-assigned seed binding.                                |
| [`BaseResponsesAPIAgent`](#nemo_gym-agents-base_responses_api_agent-BaseResponsesAPIAgent)                       | An agent server: the harness Gym runs against the model for each task.                                      |
| [`BaseResponsesAPIAgentConfig`](#nemo_gym-agents-base_responses_api_agent-BaseResponsesAPIAgentConfig)           | -                                                                                                           |
| [`ModelEndpoint`](#nemo_gym-agents-base_responses_api_agent-ModelEndpoint)                                       | The OpenAI-compatible endpoint a harness sends its model calls to.                                          |
| [`RolloutStopRequest`](#nemo_gym-agents-base_responses_api_agent-RolloutStopRequest)                             | Body of `POST /rollouts/&#123;rollout_id&#125;/stop`; the reason is recorded on the stopped run's response. |
| [`RolloutStopResponse`](#nemo_gym-agents-base_responses_api_agent-RolloutStopResponse)                           | `stopped` is false when the rollout's run already ended or a stop was already requested.                    |
| [`SimpleResponsesAPIAgent`](#nemo_gym-agents-base_responses_api_agent-SimpleResponsesAPIAgent)                   | -                                                                                                           |
| [`_AgentSessionRecord`](#nemo_gym-agents-base_responses_api_agent-_AgentSessionRecord)                           | -                                                                                                           |

### Functions

| Name                                                                                                                           | Description                                                                                    |
| ------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------- |
| [`_agent_boundary`](#nemo_gym-agents-base_responses_api_agent-_agent_boundary)                                                 | `endpoint` with its failures raised as one agent route failure caused by them.                 |
| [`_has_exception_handler`](#nemo_gym-agents-base_responses_api_agent-_has_exception_handler)                                   | Whether `app` registers a handler for `error`'s type or a base of it, as Starlette dispatches. |
| [`_log_seed_refusal`](#nemo_gym-agents-base_responses_api_agent-_log_seed_refusal)                                             | -                                                                                              |
| [`assert_model_url_reachable_from_sandbox`](#nemo_gym-agents-base_responses_api_agent-assert_model_url_reachable_from_sandbox) | Refuse a model URL that a sandboxed agent could not reach.                                     |
| [`is_loopback_host`](#nemo_gym-agents-base_responses_api_agent-is_loopback_host)                                               | Whether `url` points at the caller's own loopback interface (127.0.0.0/8, ::1, localhost).     |

### Data

[`AGENT_ACTIVATION_HEADER`](#nemo_gym-agents-base_responses_api_agent-AGENT_ACTIVATION_HEADER)

[`AGENT_SESSIONS`](#nemo_gym-agents-base_responses_api_agent-AGENT_SESSIONS)

[`AGENT_SESSION_COOKIE_KEY`](#nemo_gym-agents-base_responses_api_agent-AGENT_SESSION_COOKIE_KEY)

[`LOG`](#nemo_gym-agents-base_responses_api_agent-LOG)

[`ROLLOUT_KEY_PREFIX`](#nemo_gym-agents-base_responses_api_agent-ROLLOUT_KEY_PREFIX)

[`ROLLOUT_STOP_METADATA_KEY`](#nemo_gym-agents-base_responses_api_agent-ROLLOUT_STOP_METADATA_KEY)

[`ROLLOUT_STOP_TIMEOUT_SECONDS`](#nemo_gym-agents-base_responses_api_agent-ROLLOUT_STOP_TIMEOUT_SECONDS)

[`_AGENT_CHECKPOINT_MODES`](#nemo_gym-agents-base_responses_api_agent-_AGENT_CHECKPOINT_MODES)

[`_HOST_NETWORK_SANDBOX_PROVIDERS`](#nemo_gym-agents-base_responses_api_agent-_HOST_NETWORK_SANDBOX_PROVIDERS)

[`_LOCAL_DOCKER_SANDBOX_PROVIDERS`](#nemo_gym-agents-base_responses_api_agent-_LOCAL_DOCKER_SANDBOX_PROVIDERS)

[`__getattr__`](#nemo_gym-agents-base_responses_api_agent-__getattr__)

### API

```python
class nemo_gym.agents.base_responses_api_agent.AgentCloseSessionRequest()
```

**Bases:** `BaseModel`

Close agent-server state.

**`agent_session_id`** `str`

---

**`episode_id`** `EpisodeId`

---

**`model_config`** `= ConfigDict(extra='forbid')`

---

```python
class nemo_gym.agents.base_responses_api_agent.AgentCloseSessionResponse()
```

**Bases:** `BaseModel`

Confirm closure and return captured observations.

**`agent_observations`** `AgentObservationBundle | None = None`

---

**`agent_session_id`** `str`

---

**`cleanup_confirmed`** `bool | None`

---

**`model_config`** `= ConfigDict(extra='forbid')`

---

**`resources_cookies`** `dict[str, str] | None`

---

**`trajectory`** `TrajectoryRecord | None`

---

```python
nemo_gym.agents.base_responses_api_agent.AgentCloseSessionResponse._serialize_optional_metadata(
    handler: pydantic.SerializerFunctionWrapHandler
)
```

```python
class nemo_gym.agents.base_responses_api_agent.AgentSeedRejectedError(
    detail: str
)
```

Exception

**Bases:** `HTTPException`, `ValueError`

Refuse an agent session seed this agent cannot serve, such as a grant or sandbox it does not support.

FastAPI answers it with HTTP 422, which an Environment Server treats as terminal, so a configuration error
fails the episode once with this message instead of being retried as if it were transient. It is also a
`ValueError`, so code that validates a seed outside a request (a checkpoint restore, a direct call in a test)
keeps catching it as before.

```python
class nemo_gym.agents.base_responses_api_agent.AgentSeedSessionRequest()
```

**Bases:** `BaseModel`

Idempotently initialize agent-server state under a caller-assigned identifier.

Repeating the same identifier and episode must return the existing session.
Closing an unknown identifier must prevent a racing seed within the close retry window.
The shared implementation fences each closed session and keeps its close's saved reply for
session_close_retry_window_seconds, so callers must use unique IDs and finish retries within that window.
External resources should use provider TTLs when available; there is no active-session expiry timer.

**`agent_session_id`** `str = Field(min_length=1)`

---

**`agent_timeout_sec`** `float | None = Field(default=None, gt=0)`

---

**`continuation`** `AgentContinuationRequirements | None`

---

**`episode_id`** `EpisodeId`

---

**`model_config`** `= ConfigDict(extra='forbid')`

---

**`sandbox_access`** `SandboxAccess | None = None`

---

**`task_id`** `TaskId`

---

**`tool_accesses`** `list[ToolAccess] = Field(default_factory=list)`

---

```python
nemo_gym.agents.base_responses_api_agent.AgentSeedSessionRequest._serialize_optional_metadata(
    handler: pydantic.SerializerFunctionWrapHandler
)
```

```python
nemo_gym.agents.base_responses_api_agent.AgentSeedSessionRequest.require_unique_tool_names(
    tool_accesses: list[nemo_gym.server_runtime.tool_access.ToolAccess]
) -> list[nemo_gym.server_runtime.tool_access.ToolAccess]
```

classmethod

```python
class nemo_gym.agents.base_responses_api_agent.AgentSeedSessionResponse()
```

**Bases:** `BaseModel`

Confirm the caller-assigned agent session identifier and declare what the harness can use.

**`agent_session_id`** `str`

---

**`capabilities`** `AgentContinuationCapabilities | None`

---

**`model_config`** `= ConfigDict(extra='forbid')`

---

**`supports_task_tool_context`** `bool = False`

---

```python
nemo_gym.agents.base_responses_api_agent.AgentSeedSessionResponse._serialize_optional_metadata(
    handler: pydantic.SerializerFunctionWrapHandler
)
```

```python
class nemo_gym.agents.base_responses_api_agent.AgentSessionCapabilitiesResponse()
```

**Bases:** `BaseModel`

What this adapter's sessions can do, asked before any session is seeded.

An environment server reads it to refuse a run before provisioning anything: a multi-step task whose turns
must continue one harness session needs `continuation`, as Harbor's multi-step trial refuses
`resume_trajectory` for an agent without `SUPPORTS_RESUME` before any environment spend.

**`continuation`** `AgentContinuationCapabilities | None = None`

---

**`model_config`** `= ConfigDict(extra='forbid')`

---

**`supports_task_tool_context`** `bool = False`

---

```python
class nemo_gym.agents.base_responses_api_agent.AgentSessionConflictError(
    detail: str
)
```

Exception

**Bases:** `HTTPException`, `ValueError`

Refuse an agent session request that conflicts with what this agent recorded for the session.

Examples: an `agent_session_id` already bound to another seed request, a close that names another episode,
or a seed for a closed session. FastAPI answers it with HTTP 409, which an environment server treats as
terminal. It is also a `ValueError` for direct callers.

```python
class nemo_gym.agents.base_responses_api_agent.AgentSessionSetupError(
    state: nemo_gym.agents.base_responses_api_agent.AgentSessionState,
    error: BaseException
)
```

Exception

**Bases:** `Exception`

Retain incomplete setup for close while propagating the original setup error.

```python
class nemo_gym.agents.base_responses_api_agent.AgentSessionState(
    request: nemo_gym.agents.base_responses_api_agent.AgentSeedSessionRequest
)
```

Dataclass

Harness-owned session state with the immutable caller-assigned seed binding.

**`request`** `AgentSeedSessionRequest`

---

```python
class nemo_gym.agents.base_responses_api_agent.BaseResponsesAPIAgent()
```

**Bases:** [BaseServer](/nemo/gym/nemo-gym/nemo_gym/server_runtime/base_server#nemo_gym-server_runtime-base_server-BaseServer)

An agent server: the harness Gym runs against the model for each task.

`calls_model_from_sandbox`: declare `True` on the class the entrypoint runs when the harness calls the
model server from inside the task sandbox, where the loopback address is the container itself. A Harbor run
(`gym eval run <target> --agent <name>`) reads that literal from the entrypoint source, as Gym reads
`ray_enabled`, and advertises a reachable host (`use_absolute_ip`) by default for such a harness. It is
not read through inheritance: each such class declares it itself.

**`calls_model_from_sandbox`** `bool = False`

---

**`config`** `BaseResponsesAPIAgentConfig`

---

```python
class nemo_gym.agents.base_responses_api_agent.BaseResponsesAPIAgentConfig()
```

**Bases:** [BaseRunServerInstanceConfig](/nemo/gym/nemo-gym/nemo_gym/config/config_types#nemo_gym-config-config_types-BaseRunServerInstanceConfig)

**`session_close_retry_window_seconds`** `float`

---

**`session_close_timeout_seconds`** `float`

---

**`skip_verification`** `bool = False`

---

**`skip_verification_reward`** `float = 0.0`

---

**`token_id_capture`** `bool = False`

---

**`tool_accesses`** `list[ToolAccess] = Field(default_factory=list)`

---

```python
nemo_gym.agents.base_responses_api_agent.BaseResponsesAPIAgentConfig.require_unique_tool_names(
    tool_accesses: list[nemo_gym.server_runtime.tool_access.ToolAccess]
) -> list[nemo_gym.server_runtime.tool_access.ToolAccess]
```

classmethod

```python
class nemo_gym.agents.base_responses_api_agent.ModelEndpoint(
    base_url: str,
    model: str | None = None
)
```

Dataclass

The OpenAI-compatible endpoint a harness sends its model calls to.

`base_url` ends in the API version (for example `/v1`).
`model` is set only when the endpoint dictates the model name; otherwise the harness keeps its own.

**`base_url`** `str`

---

**`model`** `str | None = None`

---

```python
class nemo_gym.agents.base_responses_api_agent.RolloutStopRequest()
```

**Bases:** `BaseModel`

Body of `POST /rollouts/{rollout_id}/stop`; the reason is recorded on the stopped run's response.

**`model_config`** `= ConfigDict(extra='forbid')`

---

**`reason`** `str | None = Field(default=None, max_length=200)`

---

```python
class nemo_gym.agents.base_responses_api_agent.RolloutStopResponse()
```

**Bases:** `BaseModel`

`stopped` is false when the rollout's run already ended or a stop was already requested.

**`rollout_id`** `str`

---

**`stopped`** `bool`

---

```python
class nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent()
```

**Bases:** [BaseResponsesAPIAgent](#nemo_gym-agents-base_responses_api_agent-BaseResponsesAPIAgent), [AggregateMetricsMixin](/nemo/gym/nemo-gym/nemo_gym/metrics/reward_profile#nemo_gym-metrics-reward_profile-AggregateMetricsMixin), [SimpleServer](/nemo/gym/nemo-gym/nemo_gym/server_runtime/base_server#nemo_gym-server_runtime-base_server-SimpleServer)

**`_agent_session_owners`** `Optional[SessionOwners] = PrivateAttr(default=None)`

---

**`_checkpoint_participant`** `Optional[AgentSessionParticipant] = PrivateAttr(default=None)`

---

**`_failed_seed_records`** `OrderedDict[str, _AgentSessionRecord] = PrivateAttr(default_factory=OrderedDict)`

---

**`_failed_seed_releases`** `set[Task] = PrivateAttr(default_factory=set)`

---

**`_fenced_session_records`** `OrderedDict[str, _AgentSessionRecord] = PrivateAttr(default_factory=OrderedDict)`

---

**`_restart_only`** `Optional[RestartOnlyAgentParticipant] = PrivateAttr(default=None)`

---

**`_session_records`** `dict[str, _AgentSessionRecord] = PrivateAttr(default_factory=dict)`

---

**`checkpoint_mode`** `CheckpointMode = 'restart_only'`

---

**`checkpoint_participant`** `Optional[AgentSessionParticipant]`

The checkpoint participant, or `None` when checkpointing is off for this agent.

---

**`config`** `BaseResponsesAPIAgentConfig`

---

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent._acquire_rollout_ownership(
    episode_id: nemo_gym.core.episode_types.EpisodeId
) -> None
```

Own the rollout's key on this worker, so a stop that names only the rollout reaches its session.

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent._activate_agent_session_state(
    state: nemo_gym.agents.base_responses_api_agent.AgentSessionState,
    body: nemo_gym.core.responses_api_types.NeMoGymResponseCreateParamsNonStreaming,
    activation_id: int
) -> nemo_gym.core.responses_api_types.NeMoGymResponse
```

async

Run one input delta with the retained harness session and sandbox.

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent._activation_index(
    request: fastapi.Request
) -> typing.Optional[int]
```

Read the existing 1-based header for checkpointed or multi-turn continuation sessions.

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent._agent_continuation_capabilities() -> nemo_gym.agents.agent_activation_types.AgentContinuationCapabilities | None
```

Opt into multi-turn continuation; existing one-activation adapters stay unchanged.

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent._agent_session_id_from_request(
    request: fastapi.Request | None
) -> str | None
```

staticmethod

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent._capture_correlation_enabled() -> bool
```

Return whether this agent needs rollout correlation.

Evaluation uses `/ng-rollout/<id>/...` for every agent.
Training capture uses `/ng-rollout/<id>/training-token-capture/...`.
Training capture requires `token_id_capture.enabled`.
It also requires the static agent flag or run-level `all_agents`.
Partial-rollout checkpointing also needs it for this agent.
Missing global configuration disables correlation.

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent._close_agent_session_id(
    session_id: str,
    episode_id: nemo_gym.core.episode_types.EpisodeId,
    current: str | None = None
) -> tuple[nemo_gym.agents.base_responses_api_agent.AgentCloseSessionResponse, bool]
```

async

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent._close_agent_session_record(
    record: nemo_gym.agents.base_responses_api_agent._AgentSessionRecord
) -> nemo_gym.agents.base_responses_api_agent.AgentCloseSessionResponse
```

async

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent._close_agent_session_state(
    state: nemo_gym.agents.base_responses_api_agent.AgentSessionState
) -> nemo_gym.agents.base_responses_api_agent.AgentCloseSessionResponse
```

async

Release harness state, or raise without losing the handle needed for another close.

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent._close_continuation_session(
    record: nemo_gym.agents.base_responses_api_agent._AgentSessionRecord
) -> nemo_gym.agents.base_responses_api_agent.AgentCloseSessionResponse
```

async

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent._close_session_state(
    agent_session_id: str,
    record: nemo_gym.agents.base_responses_api_agent._AgentSessionRecord
) -> nemo_gym.agents.base_responses_api_agent.AgentCloseSessionResponse
```

async

Stop the session's activation, then release its state with the close hook.

A close cancelled while it stops the activation leaves the hook to its retry, so the hook runs once.
A retire can release the session while the close awaits.
The close then stops there and leaves the session to the retire.

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent._continuation_close_timeout() -> float
```

Return the adapter's configured bound for stopping an active continuation.

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent._drain_sessions_on_shutdown(
    app: fastapi.FastAPI
) -> collections.abc.AsyncIterator[None]
```

async

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent._install_restored_session(
    agent_session_id: str,
    state: nemo_gym.agents.base_responses_api_agent.AgentSessionState
) -> None
```

Install a session restored from a checkpoint, as its replacement attempt's seed would have.

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent._keep_failed_seed(
    agent_session_id: str,
    record: nemo_gym.agents.base_responses_api_agent._AgentSessionRecord
) -> None
```

Keep a failed seed's state for the caller's close, for as long as a fence lasts.

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent._locked_agent_session(
    session_id: str
) -> collections.abc.AsyncIterator[nemo_gym.agents.base_responses_api_agent._AgentSessionRecord]
```

async

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent._model_call_capture_enabled() -> bool
```

Whether evaluation model-call observability is enabled.

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent._open_rollout_record(
    rollout_id: str
) -> nemo_gym.agents.base_responses_api_agent._AgentSessionRecord | None
```

The record of the open session, seeded or still seeding, that runs the rollout.

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent._release_agent_session_ownership(
    agent_session_id: str
) -> None
```

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent._release_failed_seed(
    agent_session_id: str,
    record: nemo_gym.agents.base_responses_api_agent._AgentSessionRecord
) -> None
```

async

Run the close hook on a failed seed's state that no close reached, then drop the record.

The hook runs under the session's own rollout, as it would for the caller's close.
If it fails, the record keeps its state for a later close, and the release is tried again a window later.

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent._release_retired_session(
    agent_session_id: str
) -> None
```

Release a retired session that has no fence: its episode's close then finds nothing to release.

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent._release_rollout_ownership(
    record: nemo_gym.agents.base_responses_api_agent._AgentSessionRecord
) -> None
```

Release ownership of the rollout's key once its session is no longer open here; a no-op while it is.

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent._require_agent_session(
    agent_session_id: str
) -> nemo_gym.agents.base_responses_api_agent.AgentSessionState
```

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent._require_current_session(
    agent_session_id: str,
    record: nemo_gym.agents.base_responses_api_agent._AgentSessionRecord
) -> None
```

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent._rollout_sandbox_session(
    state: nemo_gym.agents.base_responses_api_agent.AgentSessionState
) -> nemo_gym.agents.utils.sandbox_session.SandboxSession | None
```

The sandbox session that runs `state`'s harness; an agent returns it to support rollout stops.

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent._seed_agent_session_state(
    body: nemo_gym.agents.base_responses_api_agent.AgentSeedSessionRequest
) -> nemo_gym.agents.base_responses_api_agent.AgentSessionState
```

async

Validate grants and initialize harness state.

Raise AgentSeedRejectedError for a seed this agent cannot serve, such as a sandbox or a required grant it
does not support: the seed answers a terminal 422 and binds nothing. An HTTPException keeps its explicit status;
any other, unexpected exception answers 500, which an Environment Server retries as transient.
If setup fails and cleanup cannot finish, raise AgentSessionSetupError with the
partial state and original error. The base retains it for close, never activation.

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent._session_state(
    agent_session_id: str
) -> typing.Optional[nemo_gym.agents.base_responses_api_agent.AgentSessionState]
```

The open state of a session, or `None`; checkpoint hooks export it.

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent._token_id_capture_enabled() -> bool
```

Whether this agent explicitly opted into training-token capture.

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent._undo_seed(
    agent_session_id: str,
    record: nemo_gym.agents.base_responses_api_agent._AgentSessionRecord
) -> None
```

async

Release a seeded session's state with the close hook, or keep it as a failed seed if the hook fails.

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent._validate_agent_activation(
    state: nemo_gym.agents.base_responses_api_agent.AgentSessionState,
    body: nemo_gym.core.responses_api_types.NeMoGymResponseCreateParamsNonStreaming
) -> None
```

Validate a delta without mutating the session or consuming its index.

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent.activate_agent_session(
    request: fastapi.Request,
    body: nemo_gym.core.responses_api_types.NeMoGymResponseCreateParamsNonStreaming
) -> nemo_gym.core.responses_api_types.NeMoGymResponse
```

async

Run or replay one header-indexed delta in a seeded harness session.

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent.agent_session_capabilities() -> nemo_gym.agents.base_responses_api_agent.AgentSessionCapabilitiesResponse
```

async

Declare the session capabilities a seed would confirm, without seeding: the task-tool context and the
multi-turn continuation this adapter supports (`None` for one-activation adapters and for agents that
implement no sessions at all).

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent.aggregate_metrics(
    body: nemo_gym.server_runtime.base_resources_server.AggregateMetricsRequest = Body()
) -> nemo_gym.server_runtime.base_resources_server.AggregateMetrics
```

async

Default: same RewardProfiler aggregation as resources server. Override to proxy.

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent.base_url_for_run(
    base_url: str,
    body: typing.Any
) -> str
```

Apply this run's capture path to a model-server root URL.

Append the API-version suffix after this method returns. While traces export, the URL also
names this run's current span, so the model server parents calls that arrive without a
`traceparent` header (a harness in a sandbox) to it.

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent.classify_outcome(
    native_result: collections.abc.Mapping[str, typing.Any]
) -> nemo_gym.agents.agent_outcome.AgentOutcome
```

Override to classify native failures; the environment decides grading and retry eligibility.

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent.close_agent_session(
    request: fastapi.Request,
    body: nemo_gym.agents.base_responses_api_agent.AgentCloseSessionRequest
) -> nemo_gym.agents.base_responses_api_agent.AgentCloseSessionResponse
```

async

Fence the session and keep the close's saved reply, observations included, for the close retry window.

Failed release keeps state for retry. Closing an unknown ID prevents a delayed seed
within the same window. No timer cancels active sessions: the environment server that drives the episode
and the sandbox provider retain responsibility for normal and crash cleanup.

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent.effective_tool_accesses(
    request: nemo_gym.agents.base_responses_api_agent.AgentSeedSessionRequest
) -> list[nemo_gym.server_runtime.tool_access.ToolAccess]
```

Overlay episode-scoped tool access onto configured declarations by name.

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent.expire_agent_session_records() -> None
```

Drop the fences that expired, and release the failed seeds nobody closed.

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent.export_agent_sessions(
    session_keys: list[str]
) -> dict[str, dict[str, pydantic.JsonValue]]
```

async

Return the state of every session in `session_keys` for a checkpoint.

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent.holds_agent_session(
    agent_session_id: str
) -> bool
```

Whether this worker keeps any record of the session: open, failed and awaiting close, or closed.

For a rollout's key, `/rollouts/<rollout id>`, whether this worker runs the rollout's open session.

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent.model_endpoint(
    model_server: nemo_gym.config.config_types.ModelServerRef | None,
    rollout_id: typing.Optional[str] = None,
    base_url: typing.Optional[str] = None,
    session_endpoint: nemo_gym.agents.base_responses_api_agent.ModelEndpoint | None = None
) -> nemo_gym.agents.base_responses_api_agent.ModelEndpoint
```

Choose the endpoint for a harness's model calls.

In order: `session_endpoint`, an endpoint the episode's session supplies (for example a component
that records model calls from inside the task sandbox); the Gym model server, with this rollout's
capture prefix; the agent's configured `base_url`, used verbatim because it has no prefix routing.

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent.owned_session_routing() -> dict[str, typing.Any]
```

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent.report_outcome(
    response: nemo_gym.core.responses_api_types.NeMoGymResponse,
    native_result: collections.abc.Mapping[str, typing.Any]
) -> nemo_gym.core.responses_api_types.NeMoGymResponse
```

Attach validated evidence through the existing string-valued response metadata.

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent.report_rollout_stop(
    response: nemo_gym.core.responses_api_types.NeMoGymResponse,
    session: nemo_gym.agents.utils.sandbox_session.SandboxSession
) -> nemo_gym.core.responses_api_types.NeMoGymResponse
```

Mark the response of a run that `POST /rollouts/{rollout_id}/stop` ended.

The response keeps a timeout's `incomplete` status, so it is verified like one, and gains the
`ng_rollout_stop` marker that tells it apart from a timeout or a cancellation. A stop is not a
failure, so the response carries no failure kind.

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent.resolve_model_base_url(
    model_server_name: str,
    rollout_id: typing.Optional[str] = None,
    trace_context: bool = True
) -> str
```

Resolve a model-server URL with an optional rollout prefix (and trace context, as `base_url_for_run`).

Pass `trace_context=False` for a URL that a client cached across rollouts will keep using.

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent.responses(
    body: nemo_gym.core.responses_api_types.NeMoGymResponseCreateParamsNonStreaming = Body()
) -> nemo_gym.core.responses_api_types.NeMoGymResponse
```

async

abstract

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent.restore_agent_sessions(
    sessions: list[nemo_gym.server_runtime._checkpoint.agent.RestoredAgentSession]
) -> None
```

async

Validate every session, then install all of them; never install a partial set.

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent.retire_agent_session(
    session_key: str
) -> None
```

async

Discard a session whose attempt was retired.

The default releases the session with the agent's close hook, without a fence,
so a restart-only agent's retire stops the sandbox a seed started.

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent.rollout_id_from_run(
    body: typing.Any
) -> typing.Optional[str]
```

Return the capture id for a run request.

Return `None` when capture is disabled.
Return `None` when the body has no usable identity.

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent.run(
    body: nemo_gym.server_runtime.base_resources_server.BaseRunRequest = Body()
) -> nemo_gym.server_runtime.base_resources_server.BaseVerifyResponse
```

async

abstract

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent.seed_agent_session(
    request: fastapi.Request,
    body: nemo_gym.agents.base_responses_api_agent.AgentSeedSessionRequest,
    response: fastapi.Response = None
) -> nemo_gym.agents.base_responses_api_agent.AgentSeedSessionResponse
```

async

Seed once per caller ID; identical retries reuse the same harness state.

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent.setup_agent_checkpoint(
    app: fastapi.FastAPI
) -> None
```

Install this agent's checkpoint participant on `app`, once.

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent.setup_checkpoint_participant(
    app: fastapi.FastAPI
) -> None
```

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent.setup_webserver() -> fastapi.FastAPI
```

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent.stop_rollout(
    rollout_id: str,
    body: nemo_gym.agents.base_responses_api_agent.RolloutStopRequest | None = None
) -> nemo_gym.agents.base_responses_api_agent.RolloutStopResponse
```

async

End a rollout's harness as at its time limit, so the episode is verified and graded as a timeout.

For a caller that enforces its own budget (agent time, tokens, cost) or an operator's cancel.
`rollout_id` is the id in `/ng-rollout/<id>`. A stop that arrives while the session is still
seeding takes effect when the harness would launch. With several workers, the request reaches the
worker running the rollout without the session cookie (see nemo_gym.server_runtime.request_handling.session_routing).

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent.supports_task_tool_context() -> bool
```

Whether this harness uses the task's own tool declarations.

Harbor tasks declare `[[environment.mcp_servers]]` and `skills_dir`. A harness that drives them
from inside the sandbox answers True, and the seed response carries the answer to the environment
server, which refuses such a task to a harness that would run it without its tools.

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent.url_path_for_request(
    url_path: str,
    request: typing.Optional[fastapi.Request]
) -> str
```

Carry an inbound capture path onto a downstream URL path.

Prefixed self-calls expose the rollout id as a path parameter.
Training-capture requests preserve their dedicated path segment.
Unprefixed requests remain unchanged.

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent.url_path_for_run(
    url_path: str,
    body: typing.Any
) -> str
```

Apply this run's capture path to a downstream URL path.

Evaluation uses `/ng-rollout/<id>/...`.
Training capture uses `/ng-rollout/<id>/training-token-capture/...`.
Calls without a rollout id remain unchanged.

```python
nemo_gym.agents.base_responses_api_agent.SimpleResponsesAPIAgent.use_agent_session_owners(
    owners: nemo_gym.server_runtime.request_handling.session_routing.SessionOwners
) -> None
```

Release ownership of a session when this worker drops its last record.

See nemo_gym.server_runtime.request_handling.session_routing.

```python
class nemo_gym.agents.base_responses_api_agent._AgentSessionRecord(
    lock: asyncio.Lock = asyncio.Lock(),
    state: nemo_gym.agents.base_responses_api_agent.AgentSessionState | None = None,
    closing: bool = False,
    episode_id: nemo_gym.core.episode_types.EpisodeId | None = None,
    close_response: nemo_gym.agents.base_responses_api_agent.AgentCloseSessionResponse | None = None,
    expires_at: float = float('inf'),
    activations: nemo_gym.agents.utils.ordered_operations.OrderedOperationLedger[nemo_gym.core.responses_api_types.NeMoGymResponse] = OrderedOperationLedger(),
    close_task: asyncio.Task[nemo_gym.agents.base_responses_api_agent.AgentCloseSessionResponse] | None = None,
    stop_requested: bool = False,
    stop_reason: str | None = None
)
```

Dataclass

**`activations`** `OrderedOperationLedger[NeMoGymResponse] = field(default_factory=OrderedOperationLedger)`

---

**`close_response`** `AgentCloseSessionResponse | None = None`

---

**`close_task`** `Task[AgentCloseSessionResponse] | None = None`

---

**`closing`** `bool = False`

---

**`episode_id`** `EpisodeId | None = None`

---

**`expires_at`** `float = float('inf')`

---

**`lock`** `Lock = field(default_factory=(asyncio.Lock))`

---

**`state`** `AgentSessionState | None = None`

---

**`stop_reason`** `str | None = None`

---

**`stop_requested`** `bool = False`

---

```python
nemo_gym.agents.base_responses_api_agent._agent_boundary(
    endpoint: typing.Callable[..., typing.Awaitable[typing.Any]],
    app: fastapi.FastAPI,
    operation: str,
    stage: nemo_gym.core.failure_kinds.FailureStage | None = None
)
```

`endpoint` with its failures raised as one agent route failure caused by them.

A model reply that confirms a policy response timeout makes `agent.responses` raise the typed
`model_policy_response_timeout` failure instead.

The reply body and status stay those of the original error. `HTTPException`, cancellation and any error
`app` has a handler for (such as a checkpoint `ControlError`, answered 409) pass through to that
handler. A failure an agent boundary already reported (`/run` calling this server's `/v1/responses`)
is not wrapped again.

```python
nemo_gym.agents.base_responses_api_agent._has_exception_handler(
    app: fastapi.FastAPI,
    error: BaseException
) -> bool
```

Whether `app` registers a handler for `error`'s type or a base of it, as Starlette dispatches.

```python
nemo_gym.agents.base_responses_api_agent._log_seed_refusal(
    agent_session_id: str,
    error: nemo_gym.agents.base_responses_api_agent.AgentSeedRejectedError
) -> None
```

```python
nemo_gym.agents.base_responses_api_agent.assert_model_url_reachable_from_sandbox(
    url: str,
    provider_name: str | None
) -> None
```

Refuse a model URL that a sandboxed agent could not reach.

Agents that run inside a sandbox (Hermes, mini-SWE) hand the Model Server URL to code in the
container. Inside a container on a remote provider (OpenSandbox, E2B, Daytona, ...), a loopback
host is the container itself, so every model call fails and the episode silently scores 0.

**Raises:**

* `ValueError`: when `url` is loopback and `provider_name` is not a host-network or local
  Docker provider. Local Docker only logs a warning: loopback works there only when the
  daemon shares the host network.

```python
nemo_gym.agents.base_responses_api_agent.is_loopback_host(
    url: str
) -> bool
```

Whether `url` points at the caller's own loopback interface (127.0.0.0/8, ::1, localhost).

```python
nemo_gym.agents.base_responses_api_agent.AGENT_ACTIVATION_HEADER = 'x-ng-agent-activation'
```

```python
nemo_gym.agents.base_responses_api_agent.AGENT_SESSIONS = SessionKind(cookie_key=AGENT_SESSION_COOKIE_KEY, id_field='agent_session_id', se...
```

```python
nemo_gym.agents.base_responses_api_agent.AGENT_SESSION_COOKIE_KEY = 'agent_session_id'
```

```python
nemo_gym.agents.base_responses_api_agent.LOG = logging.getLogger(__name__)
```

```python
nemo_gym.agents.base_responses_api_agent.ROLLOUT_KEY_PREFIX = '/rollouts/'
```

```python
nemo_gym.agents.base_responses_api_agent.ROLLOUT_STOP_METADATA_KEY = 'ng_rollout_stop'
```

```python
nemo_gym.agents.base_responses_api_agent.ROLLOUT_STOP_TIMEOUT_SECONDS = 60.0
```

```python
nemo_gym.agents.base_responses_api_agent._AGENT_CHECKPOINT_MODES = ('restart_only', 'exported')
```

```python
nemo_gym.agents.base_responses_api_agent._HOST_NETWORK_SANDBOX_PROVIDERS = frozenset({'local'})
```

```python
nemo_gym.agents.base_responses_api_agent._LOCAL_DOCKER_SANDBOX_PROVIDERS = frozenset({'docker'})
```

```python
nemo_gym.agents.base_responses_api_agent.__getattr__ = moved_names_getattr(__name__)
```