> ## Documentation Index
> Fetch the complete documentation index at: https://docs.osmosis.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# OpenAI Agents Integration

> Use the OpenAI Agents SDK with Osmosis for training

The Osmosis SDK includes an integration for the [OpenAI Agents SDK](https://openai.github.io/openai-agents-python/). Use it when your rollout is built around `Agent`, `Runner.run`, sessions, tools, handoffs, or other OpenAI Agents SDK primitives.

The integration has three main objects:

| Object                 | Purpose                                                                                                             |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------- |
| `OsmosisAgent`         | Drop-in replacement for OpenAI Agents SDK `Agent` that binds an `OsmosisRolloutModel` to the active rollout context |
| `OsmosisRolloutModel`  | Placeholder policy model that `OsmosisAgent` replaces with the active rollout model                                 |
| `OsmosisMemorySession` | In-memory session that records the runner conversation and exposes it as a rollout sample for grading               |

## Quick Example

```python theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/cli.json"]}}
from agents import ModelSettings, Runner
from osmosis_ai.rollout import AgentWorkflow, AgentWorkflowContext
from osmosis_ai.rollout.integrations.agents.openai_agents import (
    OsmosisAgent,
    OsmosisMemorySession,
    OsmosisRolloutModel,
)


class OpenAIWorkflow(AgentWorkflow):
    async def run(self, ctx: AgentWorkflowContext) -> None:
        agent = OsmosisAgent(
            name="assistant",
            instructions="Answer the user's request clearly.",
            model=OsmosisRolloutModel(),
            model_settings=ModelSettings(temperature=1.0, max_tokens=4096),
        )
        session = OsmosisMemorySession(name="assistant")
        await Runner.run(
            agent,
            ctx.prompt,
            session=session,
        )
```

<Warning>
  Always pass an `OsmosisMemorySession` when using `OsmosisRolloutModel`. The session publishes the sample ID used for rollout headers and persists the conversation that your grader will read. Construct the session inside `AgentWorkflow.run()` so it registers with the active `RolloutContext`.
</Warning>

## How It Works

<Steps>
  <Step title="Construct the agent inside run">
    `OsmosisAgent` checks whether the `model` argument is an `OsmosisRolloutModel`. If so, it replaces the placeholder with an `OsmosisLitellmModel` bound to the active `RolloutContext`.
  </Step>

  <Step title="Create a memory session">
    `OsmosisMemorySession` registers itself as a sample source on the current `RolloutContext`. The session name becomes the rollout sample ID.
  </Step>

  <Step title="Run the OpenAI agent">
    `Runner.run()` interacts with the session through `get_items()` and `add_items()`. The session stores the persisted OpenAI Agents SDK items in the canonical Responses API shape.
  </Step>

  <Step title="Route policy calls">
    The resolved model sends requests to the Osmosis chat completions endpoint and injects `x-sample-id` and `x-rollout-id` headers for every model call.
  </Step>

  <Step title="Collect samples">
    After `run()` completes, the backend asks the rollout context for samples. The session returns a `RolloutSample` containing the runner's persisted conversation.
  </Step>
</Steps>

## Complete Example

This example uses an OpenAI Agents SDK tool and a grader that reads the final assistant text from the session-backed sample.

```python theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/cli.json"]}}
from agents import ModelSettings, Runner, function_tool
from osmosis_ai.rollout import (
    AgentWorkflow,
    AgentWorkflowContext,
    Grader,
    GraderContext,
)
from osmosis_ai.rollout.integrations.agents.openai_agents import (
    OsmosisAgent,
    OsmosisMemorySession,
    OsmosisRolloutModel,
)


@function_tool
def multiply(a: int, b: int) -> int:
    """Multiply two integers."""
    return a * b


class MultiplyWorkflow(AgentWorkflow):
    async def run(self, ctx: AgentWorkflowContext) -> None:
        agent = OsmosisAgent(
            name="multiply-agent",
            instructions="Use the multiply tool when arithmetic is required.",
            model=OsmosisRolloutModel(),
            model_settings=ModelSettings(temperature=1.0, max_tokens=4096),
            tools=[multiply],
        )
        session = OsmosisMemorySession(name="multiply-agent")
        await Runner.run(
            agent,
            ctx.prompt,
            session=session,
        )


def _last_text(sample) -> str:
    for item in reversed(sample.messages):
        if item.get("role") != "assistant":
            continue
        content = item.get("content", "")
        if isinstance(content, str):
            return content
        if isinstance(content, list):
            for block in content:
                if isinstance(block, dict):
                    text = block.get("text") or block.get("content")
                    if text:
                        return text
    return ""


class MultiplyGrader(Grader):
    async def grade(self, ctx: GraderContext) -> None:
        for sample_id, sample in ctx.samples.items():
            answer = _last_text(sample)
            reward = 1.0 if ctx.label and ctx.label.strip() in answer else 0.0
            ctx.set_sample_reward(sample_id, reward)
```

<Note>
  OpenAI Agents SDK sessions persist conversation items rather than Strands-style messages. When writing graders for OpenAI Agents rollouts, inspect `sample.messages` as the runner's persisted session items.
</Note>

## OsmosisRolloutModel

`OsmosisRolloutModel` is a placeholder. Do not call it directly and do not pass a fixed policy model name into rollout code. In the workspace templates, sampling options live in OpenAI Agents `ModelSettings`.

```python theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/cli.json"]}}
from agents import ModelSettings
from osmosis_ai.rollout.integrations.agents.openai_agents import (
    OsmosisAgent,
    OsmosisRolloutModel,
)

agent = OsmosisAgent(
    name="assistant",
    model=OsmosisRolloutModel(),
    model_settings=ModelSettings(
        temperature=1.0,
        top_p=1.0,
        max_tokens=4096,
    ),
)
```

At runtime, `OsmosisAgent` replaces the placeholder with a model that points at the active Osmosis rollout endpoint.

<Warning>
  `OsmosisRolloutModel` is different from the Strands integration's placeholder constructor. For OpenAI Agents examples, use `OsmosisRolloutModel()` with `ModelSettings(...)`, not a `params={...}` dict.
</Warning>

## Sessions and Sample IDs

Use exactly one `OsmosisMemorySession` per `Runner.run()` call when that run uses `OsmosisRolloutModel`.

```python theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/cli.json"]}}
session = OsmosisMemorySession(name="main")
await Runner.run(agent, ctx.prompt, session=session)
```

The session name is used as the sample ID. If your workflow runs multiple independent agents for the same prompt, give each session a distinct name:

```python theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/cli.json"]}}
planner_session = OsmosisMemorySession(name="planner")
executor_session = OsmosisMemorySession(name="executor")
```

Create sessions inside `run()`. A session created outside the active rollout context cannot be reused inside a rollout run because it was not registered with that context.

## Migrating from OpenAI Agents SDK

If you already have an OpenAI Agents SDK workflow, migrate it in four steps:

<Steps>
  <Step title="Replace Agent with OsmosisAgent">
    Change the import and class:

    ```python theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/cli.json"]}}
    from osmosis_ai.rollout.integrations.agents.openai_agents import OsmosisAgent
    ```

    Then construct `OsmosisAgent(...)` instead of `Agent(...)`.
  </Step>

  <Step title="Replace the policy model">
    Replace a fixed model string with an `OsmosisRolloutModel` placeholder:

    ```python theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/cli.json"]}}
    from osmosis_ai.rollout.integrations.agents.openai_agents import OsmosisRolloutModel

    model = OsmosisRolloutModel()
    ```
  </Step>

  <Step title="Add an OsmosisMemorySession">
    Create the session inside `AgentWorkflow.run()` and pass it to `Runner.run()`:

    ```python theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/cli.json"]}}
    session = OsmosisMemorySession(name="main")
    await Runner.run(agent, ctx.prompt, session=session)
    ```
  </Step>

  <Step title="Wrap the runner in AgentWorkflow">
    Put the runner call inside an `AgentWorkflow.run()` method. Keep your tools, instructions, handoffs, and agent behavior the same unless they depend on out-of-band state.
  </Step>
</Steps>

## Evaluation

Use the normal eval command:

```cli theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/cli.json"]}}
osmosis eval submit configs/eval/<rollout-name>.toml
```

During an evaluation run, the platform routes `openai/osmosis-rollout` to the model named in `[experiment].model_path` of the evaluation TOML. During a training run, Osmosis routes the same placeholder to the current training policy.

## Next Steps

<CardGroup cols={2}>
  <Card title="Building AgentWorkflows" icon="robot" href="/cli/rollout/agent-workflows">
    Review the shared `AgentWorkflow.run(ctx)` contract.
  </Card>

  <Card title="Building Graders" icon="scale-balanced" href="/cli/rollout/graders">
    Write reward logic for OpenAI Agents session samples.
  </Card>

  <Card title="Evaluation" icon="flask-vial" href="/cli/rollout/eval">
    Submit an evaluation run for your OpenAI Agents rollout before a training run.
  </Card>
</CardGroup>
