Skip to main content

Data Types

This page documents all data structures used in the Open Reward Standard protocol. Type definitions are shown in TypeScript notation but apply to any language implementation.

Core Types

JSONValue

Recursive type representing any valid JSON value:
type JSONValue =
  | string
  | number
  | boolean
  | null
  | { [key: string]: JSONValue }
  | JSONValue[]

type JSONObject = { [key: string]: JSONValue }
Used throughout the protocol for flexible, task-specific data.

Block Types

Blocks are the fundamental unit of content in ORS. They can be text or images.

TextBlock

Text content with optional metadata:
interface TextBlock {
  type: "text"
  text: string
  detail?: JSONObject
}
Fields:
  • type: Always "text" (literal)
  • text: The text content (string)
  • detail: Optional metadata about this text block (object)
Example:
{
  "type": "text",
  "text": "What is 2+2?",
  "detail": {"language": "en"}
}

ImageBlock

Image content encoded as base64:
interface ImageBlock {
  type: "image"
  data: string
  mimeType: string
  detail?: JSONObject
}
Fields:
  • type: Always "image" (literal)
  • data: Base64-encoded image data (string)
  • mimeType: MIME type like "image/png", "image/jpeg" (string)
  • detail: Optional metadata about this image (object)
Example:
{
  "type": "image",
  "data": "iVBORw0KGgoAAAANSUhEUgA...",
  "mimeType": "image/png",
  "detail": {"width": 800, "height": 600}
}

Blocks

Array of blocks (text and/or images):
type Blocks = Array<TextBlock | ImageBlock>
Usage: Prompts and tool outputs are represented as blocks. Example (multi-modal prompt):
[
  {
    "type": "text",
    "text": "What object is shown in this image?"
  },
  {
    "type": "image",
    "data": "iVBORw0KGgo...",
    "mimeType": "image/jpeg"
  }
]

Tool Types

ToolSpec

Specification for an available tool:
interface ToolSpec {
  name: string
  description: string
  input_schema?: JSONObject
}
Fields:
  • name: Tool identifier, used when calling the tool (string)
  • description: Human-readable description of what the tool does (string)
  • input_schema: JSON Schema defining tool parameters (object, optional)
Example:
{
  "name": "bash",
  "description": "Execute a bash command in the environment",
  "input_schema": {
    "type": "object",
    "properties": {
      "command": {
        "type": "string",
        "description": "The bash command to execute"
      }
    },
    "required": ["command"]
  }
}
Note: If input_schema is null or omitted, the tool takes no parameters.

ToolOutput

Result of executing a tool:
interface ToolOutput {
  blocks: Blocks
  reward?: number
  finished: boolean
  metadata?: JSONObject
}
Fields:
  • blocks: Output content (array of TextBlock/ImageBlock, required)
  • reward: RL reward signal (number, optional)
  • finished: Whether episode is complete (boolean, required, default: false)
  • metadata: Optional additional data (object)
Example (successful completion):
{
  "blocks": [
    {"text": "Correct! The answer is 4.", "detail": null, "type": "text"}
  ],
  "metadata": null,
  "reward": 1.0,
  "finished": true
}
Example (intermediate step):
{
  "blocks": [
    {"text": "File contents: Hello World", "detail": null, "type": "text"}
  ],
  "metadata": {"file_size": 11},
  "reward": 0.0,
  "finished": false
}
Key Fields: finished:
  • Critical for episode termination
  • When true, the episode is complete
  • Agent should stop calling tools and delete the session
  • Represents task completion (success or failure)
reward:
  • RL feedback signal
  • Typically 0.0 for intermediate steps, 1.0 for success, 0.0 or negative for failure
  • Optional - can be null if not using RL
  • Sparse rewards: only at episode end
  • Dense rewards: after each action

ToolCall

Request to execute a tool:
interface ToolCall {
  name: string
  input: JSONObject
  task_id?: string
}
Fields:
  • name: Tool to call (string, required)
  • input: Tool parameters matching its input_schema (object, required)
  • task_id: Optional ID for tracing/logging (string)
Example:
{
  "name": "submit",
  "input": {"answer": "42"},
  "task_id": "trace-123"
}

ListToolsOutput

Response from GET /{env_name}/tools:
interface ListToolsOutput {
  tools: ToolSpec[]
}
Example:
{
  "tools": [
    {
      "name": "submit",
      "description": "Submit an answer",
      "input_schema": {...}
    },
    {
      "name": "bash",
      "description": "Execute bash command",
      "input_schema": {...}
    }
  ]
}

Tool Result Types

Tool execution returns one of two result types:

RunToolSuccess

Successful tool execution:
interface RunToolSuccess {
  ok: true
  output: ToolOutput
}
Example:
{
  "ok": true,
  "output": {
    "blocks": [{"text": "Success", "detail": null, "type": "text"}],
    "metadata": null,
    "reward": 1.0,
    "finished": true
  }
}

RunToolError

Failed tool execution:
interface RunToolError {
  ok: false
  error: string
}
Example:
{
  "ok": false,
  "error": "Tool 'submit' failed: Answer must be a number"
}

RunToolOutput

Union type for tool results:
type RunToolOutput = RunToolSuccess | RunToolError
The ok field discriminates between success and error:
  • ok: true → result has output field
  • ok: false → result has error field
Usage: Returned in SSE end event from POST /{env_name}/call.

Task Types

Task

Tasks are environment-specific JSON objects:
type Task = JSONObject
No fixed schema - each environment defines its own task structure. Examples: Math environment:
{
  "question": "What is 2+2?",
  "answer": "4",
  "difficulty": "easy"
}
Coding environment:
{
  "description": "Write a function to reverse a string",
  "test_cases": [
    {"input": "hello", "output": "olleh"},
    {"input": "world", "output": "dlrow"}
  ],
  "time_limit": 5
}
Web navigation:
{
  "goal": "Find the price of product XYZ",
  "start_url": "https://example.com",
  "max_steps": 20
}

Split

Categorization of task lists:
interface Split {
  name: string
  type: "train" | "validation" | "test"
}
Fields:
  • name: Split identifier (string)
  • type: Split category (string, one of: “train”, “validation”, “test”)
Example:
{
  "name": "train",
  "type": "train"
}
Common splits:
  • {"name": "train", "type": "train"} - Training tasks
  • {"name": "validation", "type": "validation"} - Validation tasks
  • {"name": "test", "type": "test"} - Test tasks
Custom splits: Environments can define custom splits (e.g., “hard”, “easy”) which default to type “validation”.

ListTasks

Request body for POST /{env_name}/tasks:
interface ListTasks {
  split: string
}
Example:
{
  "split": "train"
}

Session Types

CreateSession

Request to create an episode:
interface CreateSession {
  env_name: string
  task_spec: JSONObject
  secrets: { [key: string]: string }
}
Fields:
  • env_name: Environment to instantiate (string, required)
  • task_spec: Task data for this episode (object, required)
  • secrets: API keys, credentials, etc. (object, required but can be empty)
Example:
{
  "env_name": "math",
  "task_spec": {
    "question": "If x + 5 = 12, what is x?",
    "answer": "7"
  },
  "secrets": {
    "openai_api_key": "sk-..."
  }
}
Security note: Secrets are passed to the environment but should not be logged or persisted by the server.

Type Examples by Use Case

Discovery Flow

// 1. List environments
GET /list_environments
string[]

// 2. List tools
GET /{env_name}/tools
ListToolsOutput

// 3. List splits
GET /{env_name}/splits
Split[]

// 4. List tasks
POST /{env_name}/tasks
Body: ListTasks
→ { tasks: Task[], env_name: string }

Episode Flow

// 1. Create session
POST /create_session
→ { sid: string }

// 2. Create episode
POST /create
Body: CreateSession
Headers: X-Session-ID
→ { sid: string }

// 3. Get prompt
GET /{env_name}/prompt
Headers: X-Session-ID
Blocks

// 4. Call tool
POST /{env_name}/call
Body: ToolCall
Headers: X-Session-ID
SSE stream with RunToolOutput

// 5. Delete episode
POST /delete
Headers: X-Session-ID
→ { sid: string }

Type Validation

Implementations should validate:

Input Validation

  • Tool calls match the tool’s input_schema
  • Required fields are present
  • Types match specifications

Output Guarantees

  • ToolOutput.blocks is non-empty array
  • ToolOutput.finished is boolean
  • ToolOutput.reward is number or null
  • Block type is exactly “text” or “image”

Episode Invariants

  • Once finished: true is returned, no more tools should be called
  • Session IDs are unique across the server
  • Tool names match those in list_tools() output

Language-Specific Notes

Python (Reference Implementation)

from openreward.environments.types import (
    TextBlock,
    ImageBlock,
    Blocks,
    ToolOutput,
    ToolSpec,
    Split,
)

# Create tool output
output = ToolOutput(
    blocks=[TextBlock(text="Correct!", type="text")],
    reward=1.0,
    finished=True
)

TypeScript

interface ToolOutput {
  blocks: Blocks;
  reward?: number;
  finished: boolean;
  metadata?: JSONObject;
}

// Create tool output
const output: ToolOutput = {
  blocks: [{type: "text", text: "Correct!"}],
  reward: 1.0,
  finished: true
};

JSON Schema

For validation in any language, use JSON Schema:
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "definitions": {
    "ToolOutput": {
      "type": "object",
      "properties": {
        "blocks": {"type": "array"},
        "reward": {"type": ["number", "null"]},
        "finished": {"type": "boolean"},
        "metadata": {"type": ["object", "null"]}
      },
      "required": ["blocks", "finished"]
    }
  }
}

Next Steps


Key Takeaway: ORS uses simple, composable types. Blocks provide flexible content representation. ToolOutput bundles content, rewards, and episode termination. Task structure is environment-specific for maximum flexibility.