AgentWorkflow is the SDK contract for rollout behavior. You subclass it, implement one async run() method, and create one sample either by returning its message history or by calling the current policy through an Osmosis-supported agent integration that registers the sample source.
The workflow should answer one question: given this dataset prompt, what should the agent do before the grader scores the result?
Base Class
run() is called once for each workflow execution. Construct any per-execution agent or session objects inside the method and run the agent. Then either return the sample directly or let the integration register the resulting conversation with the active RolloutContext.
Workflow return value
run() accepts three shapes, all normalized to a single sample:
Supported integrations register a sample source for you, so most workflows return
None: OsmosisStrandsAgent registers its Strands history, while OsmosisMemorySession registers an OpenAI Agents SDK session. Return AgentWorkflowOutput when you build the message history yourself:
AgentWorkflowOutput.info is reserved and is not currently passed to graders. Use metrics for finite numeric sample measurements and ctx.artifacts_dir for files.
AgentWorkflowContext
Thectx object gives the workflow its input and config:
If your dataset row contains
system_prompt, user_prompt, and ground_truth, the prompt fields are assembled into ctx.prompt. The reference answer is not passed to the workflow; it is exposed to your grader as ctx.label. The same metadata object is available on both AgentWorkflowContext and GraderContext, so workflows and graders can read the same per-row context.
Writing Artifacts
Usectx.artifacts_dir to write files that shouldn’t be embedded in the sample payload — logs, traces, screenshots, or other large or binary outputs. Each rollout gets its own directory, but it’s None when the environment can’t provision one, so guard with if ctx.artifacts_dir: before writing to it — an unguarded write raises and fails the workflow.
ctx.artifacts_dir. Artifact collection never affects rewards or rollout status.
Saved Trajectories
Rollout servers created withcreate_rollout_server() save finished samples as ATIF (Agent Trajectory Interchange Format) documents alongside run artifacts. Persistence is best-effort and never changes reward or rollout status. Calling LocalBackend.run_workflow() or another backend method directly in a custom harness does not install this server lifecycle; that harness must save any trajectory it needs.
Files land next to the artifacts directory on the platform-managed host:
RolloutSample.messages preserves the framework-native history that graders read. For ATIF persistence, built-in integrations make a separate, best-effort normalized copy in trajectory_messages; normalization failure leaves the native sample intact and skips trajectory persistence. Explicit workflow output uses its returned messages for both views when they can be copied.
ATIF includes usage, model, and timestamp data only when the source messages or server report provide those fields. Missing metadata stays absent; the SDK does not fabricate it.
Model Routing Requirement
Use one of the supported integrations:
Do not call
litellm, the OpenAI SDK, or another provider SDK directly with a hard-coded policy model from run(). Direct calls bypass the rollout context and are not compatible with training.
Strands Pattern
For Strands, passctx.prompt directly as messages and call invoke_async():
OsmosisStrandsAgent inside run() binds it to the active rollout context and registers the agent as a sample source.
See Strands Integration for tool examples, migration steps, and details about OsmosisRolloutModel.
OpenAI Agents Pattern
For OpenAI Agents, construct anOsmosisAgent, attach OpenAI Agents ModelSettings, create one OsmosisMemorySession, and pass that session to Runner.run():
run() so it registers with the current RolloutContext.
See OpenAI Agents Integration for session behavior, tracing notes, and migration steps.
Custom Configuration
Custom configs extendAgentWorkflowConfig. Define a module-level config instance in your rollout entrypoint and pass it to the backend:
LocalBackend(workflow=SearchWorkflow, workflow_config=search_workflow_config). Eval and training TOML files do not currently set workflow config fields directly.
BaseConfig allows extra fields, so simple rollout configs usually do not need additional Pydantic boilerplate.
Tool-Using Workflows
Tool use belongs inside your agent framework, not in the backend. Define tools the way your framework expects, pass them into the Osmosis-wrapped agent, and let the integration record the resulting messages. For example, a Strands workflow can keep its tool list in config:Entry Point Wiring
Workflow classes and config objects require explicit wiring. Select them in the backend constructor and expose that backend through the rollout server:AgentWorkflow subclasses can exist in the same module; only the class passed as workflow runs. Submit preflight imports the entrypoint once to surface import-time errors and does not inspect the module namespace; see Files in a Rollout for when that import is skipped and what it executes locally.
Next Steps
Strands Integration
Build a Strands-based rollout with tools and
OsmosisStrandsAgent.OpenAI Agents Integration
Build an OpenAI Agents SDK rollout with
OsmosisAgent and OsmosisMemorySession.Grader
Define reward logic for the sample your workflow produces.
Evaluation
Submit an evaluation run to test your workflow and grader before a training run.