This page documents data structures used in the Open Reward Standard. 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"
}
]
Specification for an available tool:
interface ToolSpec {
name : string
description : string
input_schema : JSONObject | null
}
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, or null if the tool takes no parameters (always present in output, nullable)
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, the tool takes no parameters.
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, default: false). Optional in input — always present in output.
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
Environment-defined; common patterns include sparse rewards (only at episode end) and dense rewards (after each action)
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 identifier for SSE reconnection (string). When provided, clients can reconnect to an in-progress or recently completed tool call and retrieve its result within a 60-second linger window.
Example :
{
"name" : "submit" ,
"input" : { "answer" : "42" },
"task_id" : "trace-123"
}
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 execution returns one of two result types:
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
}
}
Failed tool execution:
interface RunToolError {
ok : false
error : string
}
Example :
{
"ok" : false ,
"error" : "Tool 'submit' failed: Answer must be a number"
}
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:
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 :
NumTasks
Request body for POST /{env_name}/num_tasks:
interface NumTasks {
split : string
}
Fields :
split: Split name to count tasks in (string, required)
GetTask
Request body for POST /{env_name}/task:
interface GetTask {
split : string
index : number
}
Fields :
split: Split name (string, required)
index: Task index within the split (number, required)
GetTaskRange
Request body for POST /{env_name}/task_range:
interface GetTaskRange {
split : string
start ?: number
stop ?: number
}
Fields :
split: Split name (string, required)
start: Start index, inclusive (number, optional)
stop: Stop index, exclusive (number, optional)
Session Types
CreateSession
Request to create an episode:
interface CreateSession {
env_name ?: string
task_spec ?: JSONObject
split ?: string
index ?: number
secrets ?: { [ key : string ] : string }
}
Fields :
env_name: Environment to instantiate (string, optional — defaults to first registered environment)
task_spec: Task data for this episode (object, optional — provide this or split+index)
split: Split name to load task from (string, optional — required with index if task_spec not provided)
index: Task index within the split (number, optional — required with split if task_spec not provided)
secrets: API keys, credentials, etc. (object, optional, defaults to {})
Exactly one of task_spec or the split+index pair must be provided. Providing both or neither is a validation error.
Example (with inline task spec):
{
"env_name" : "math" ,
"task_spec" : {
"question" : "If x + 5 = 12, what is x?" ,
"answer" : "7"
},
"secrets" : {
"openai_api_key" : "sk-..."
}
}
Example (with split and index):
{
"env_name" : "math" ,
"split" : "train" ,
"index" : 42 ,
"secrets" : {}
}
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 response with RunToolOutput
// 5. Delete episode
POST / delete
Headers : X - Session - ID
→ { sid : string }
Type Validation
Implementations should validate:
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 ors 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
HTTP API See how these types are used in API endpoints
Sessions Understand episode lifecycle and state
Tools Concept Learn about tool design and usage
Implementation Guide Implement these types in your server
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.