The Intermediate Representation (IR) is the runtime-independent JSON output of the OAF compiler. It captures the fully validated meaning of an .oaf workflow and serves as the contract between the compiler and runtime adapters.
| Principle | Description |
|---|---|
| Self-contained | All information needed to generate runtime code. No reference back to source needed. |
| Deterministic | Same .oaf input always produces the same IR output. |
| Serializable | Valid JSON document. |
| Extensible | Unknown keys are ignored by adapters, enabling forward compatibility. |
{
"version": "0.1.0",
"workflow": {
"name": "<string>",
"config": { "<key>": "<value>" }
},
"state": {
"variables": [
{
"name": "<string>",
"type": "<type_descriptor>",
"options": [
{ "name": "<string>", "args": ["<any>"] }
]
}
]
},
"agents": [
{
"id": "<string>",
"instructions": "<string>",
"model": "<string|null>",
"provider": "<string|null>",
"temperature": "<number|null>",
"tools": ["<string>"],
"inputs": ["<string>"],
"outputs": ["<string>"]
}
],
"graph": {
"edges": [
{ "source": "<string>", "target": "<string>" }
],
"entrypoint": "<string>",
"terminals": ["<string>"]
}
}
| Field | Type | Description |
|---|---|---|
version |
string |
IR schema version (semver). Current: "0.1.0" |
workflow |
object |
Workflow metadata |
state |
object |
Shared state definition |
agents |
array |
Agent declarations |
graph |
object |
Execution graph |
workflow| Field | Type | Description |
|---|---|---|
name |
string |
Workflow name from the source |
config |
object |
Key-value config entries. Empty object {} if no config block. |
state| Field | Type | Description |
|---|---|---|
variables |
array |
List of state variable definitions |
Each variable:
| Field | Type | Description |
|---|---|---|
name |
string |
Variable identifier |
type |
string |
Type descriptor (see below) |
options |
array |
Options/decorators applied to the variable |
Each option:
| Field | Type | Description |
|---|---|---|
name |
string |
Option name (without @) |
args |
array |
Arguments passed to the option |
agents| Field | Type | Description |
|---|---|---|
id |
string |
Agent identifier |
instructions |
string |
Agent prompt text |
model |
string \| null |
LLM model identifier |
provider |
string \| null |
LLM provider ("gemini" or "openai") |
temperature |
number \| null |
Sampling temperature |
tools |
string[] |
Tool names |
inputs |
string[] |
State variables read |
outputs |
string[] |
State variables written |
graph| Field | Type | Description |
|---|---|---|
edges |
array |
Agent-to-agent directed edges |
entrypoint |
string |
Agent ID that start connects to |
terminals |
string[] |
Agent IDs that connect to end |
Each edge:
| Field | Type | Description |
|---|---|---|
source |
string |
Source agent ID |
target |
string |
Target agent ID |
Note: The
startandendpseudo-nodes are resolved intoentrypointandterminals. Only agent-to-agent edges appear in theedgesarray.
Type descriptors are string representations of OAF types in the IR:
| OAF Source | IR Type Descriptor |
|---|---|
string |
"string" |
int |
"int" |
float |
"float" |
bool |
"bool" |
list[string] |
"list<string>" |
list[list[int]] |
"list<list<int>>" |
map[string, int] |
"map<string,int>" |
map[string, list[string]] |
"map<string,list<string>>" |
Note the syntax differences:
[T] brackets → IR uses <T> angle brackets[K, V] with space → IR uses <K,V> without spaceThe IR generator transforms flow edges as follows:
| Source Edge | IR Mapping |
|---|---|
start -> AgentA |
graph.entrypoint = "AgentA" |
AgentB -> end |
graph.terminals.push("AgentB") |
AgentA -> AgentB |
graph.edges.push({source: "AgentA", target: "AgentB"}) |
Flow block:
flow {
start -> Analyst
Analyst -> Architect
Architect -> Developer
Developer -> end
}
IR graph:
{
"edges": [
{ "source": "Analyst", "target": "Architect" },
{ "source": "Architect", "target": "Developer" }
],
"entrypoint": "Analyst",
"terminals": ["Developer"]
}
For this .oaf source:
workflow "Summarize" {
state {
source_text: string @required
key_points: list[string]
summary: string
}
agent Analyst {
instructions: "Extract key points from the source text."
model: "gemini-2.0-flash"
temperature: 0.2
inputs: [source_text]
outputs: [key_points]
}
agent Writer {
instructions: "Write a summary from the key points."
model: "gpt-4"
temperature: 0.7
inputs: [key_points]
outputs: [summary]
}
flow {
start -> Analyst
Analyst -> Writer
Writer -> end
}
config {
timeout_seconds: 300
}
}
The IR output is:
{
"version": "0.1.0",
"workflow": {
"name": "Summarize",
"config": {
"timeout_seconds": 300
}
},
"state": {
"variables": [
{
"name": "source_text",
"type": "string",
"options": [
{ "name": "required", "args": [] }
]
},
{
"name": "key_points",
"type": "list<string>",
"options": []
},
{
"name": "summary",
"type": "string",
"options": []
}
]
},
"agents": [
{
"id": "Analyst",
"instructions": "Extract key points from the source text.",
"model": "gemini-2.0-flash",
"provider": null,
"temperature": 0.2,
"tools": [],
"inputs": ["source_text"],
"outputs": ["key_points"]
},
{
"id": "Writer",
"instructions": "Write a summary from the key points.",
"model": "gpt-4",
"provider": null,
"temperature": 0.7,
"tools": [],
"inputs": ["key_points"],
"outputs": ["summary"]
}
],
"graph": {
"edges": [
{ "source": "Analyst", "target": "Writer" }
],
"entrypoint": "Analyst",
"terminals": ["Writer"]
}
}
An adapter consuming the IR must:
Before generating code, an adapter should verify:
graph.entrypoint is not nullgraph.terminals has at least one entryagents array is not emptyAdapters should check the version field and reject IRs with incompatible major versions. The current version is 0.1.0.