Skip to main content

API Overview

Overview

Runner Codes uses a JSON-based API over virtio-vsock for communication between the host and guest components of infra.operator. This provides low-latency, secure communication without network stack overhead.

Communication Flow

Communication Flow Sequence Diagram

Protocol Layers

Layer 1: Vsock Connection

The host connects to Firecracker's vsock Unix Domain Socket (UDS):

Vsock socket path
/tmp/fc-{instance_id}.vsock

Layer 2: Firecracker Vsock Multiplexer

After connecting to the UDS, the host sends a text command to connect to a specific guest port:

Connect to guest port
CONNECT 5000\n

The guest responds:

Guest connection acknowledgment
OK 5000\n

Layer 3: Message Framing

All messages use a 4-byte big-endian length prefix:

Message Framing Protocol

Example (Python):

Send and receive messages with length prefix
import struct

def send_message(conn, data):
payload = json.dumps(data).encode('utf-8')
length = struct.pack('>I', len(payload)) # Big-endian unsigned int
conn.sendall(length + payload)

def recv_message(conn):
length_bytes = conn.recv(4)
length = struct.unpack('>I', length_bytes)[0]
payload = conn.recv(length)
return json.loads(payload.decode('utf-8'))

Layer 4: JSON Messages

Messages are JSON objects with defined schemas for requests and responses.

HTTP API

POST /api/v1/run

Execute code in a Firecracker microVM.

Request:

Execute Python code with stdin
{
"language": "python",
"stdin": "Peter",
"files": [
{
"name": "main.py",
"content": "import sys\nname = sys.stdin.readline()\nprint('Hello ' + name)"
}
]
}

Response:

Successful execution result
{
"status": "success",
"stdout": "Hello Peter\n",
"stderr": null,
"exception": null,
"executionTime": 41
}

Batch Execution

Pass stdin as an array to execute the same code with multiple inputs:

Request:

Batch execution with multiple stdin values
{
"language": "python",
"stdin": ["Peter", "Brian", "Meg"],
"files": [
{
"name": "main.py",
"content": "import sys\nname = sys.stdin.readline()\nprint('Hello ' + name)"
}
]
}

Response (Array):

Batch execution results
[
{
"status": "success",
"stdout": "Hello Peter\n",
"stderr": null,
"exception": null,
"executionTime": 30,
"stdin": "Peter"
},
{
"status": "success",
"stdout": "Hello Brian\n",
"stderr": null,
"exception": null,
"executionTime": 26,
"stdin": "Brian"
},
{
"status": "success",
"stdout": "Hello Meg\n",
"stderr": null,
"exception": null,
"executionTime": 33,
"stdin": "Meg"
}
]

Response Fields

FieldDescription
statussuccess or failed
stdoutStandard output of the code execution
stderrStandard error (null if empty)
exceptionException details (Timeout, Compilation failure, etc.)
executionTimeTime taken to execute in milliseconds
stdinEcho of stdin value (batch execution only)
errorError message when status: failed

Error Codes

ErrorDescription
E001: operation timed outExecution timeout exceeded
E002: API quota exceededRate limit reached
E003: invalid access_tokenInvalid authentication
E004: access_token missingNo token provided
E005: stdin too longSTDIN exceeds 1MB limit
E006: unsupported language xyzLanguage not supported

Error Response Examples

Timeout:

Execution timeout error
{
"status": "success",
"exception": "Timeout",
"executionTime": 30000
}

Unsupported Language:

Unsupported language error
{
"status": "failed",
"error": "E006: unsupported language brainfuck"
}

STDIN Too Long:

STDIN size limit error
{
"status": "failed",
"error": "E005: stdin too long"
}

Vsock Protocol (Internal)

Job Request (Internal Format)

Internal job request format
{
"trace_id": "tr-1764388648079963068",
"lang": "python",
"code": "print('Hello, World!')",
"timeout": 30
}

Job Response (Internal Format)

Internal job response format
{
"trace_id": "tr-1764388648079963068",
"status": "success",
"stdout": "Hello, World!\n",
"stderr": null,
"exception": null,
"executionTime": 41
}

Supported Languages

Runner Codes supports 45 programming languages. Here are the most common:

LanguageIdentifierExecution Method
Pythonpythonpython3 script.py
Node.jsnodenode script.js
TypeScripttypescriptts-node script.ts
Gogogo run script.go
Rustrustrustc script.rs -o bin && ./bin
Javajavajavac Main.java && java Main
Kotlinkotlinkotlinc -include-runtime -d Main.jar && java -jar Main.jar
Ccgcc script.c -o bin && ./bin
C++cppg++ script.cpp -o bin && ./bin
Rubyrubyruby script.rb
PHPphpphp script.php
Bashbashbash script.sh
Haskellhaskellghc -o bin script.hs && ./bin
Elixirelixirelixir script.exs
Juliajuliajulia script.jl
RrRscript script.R
note

See Language Support Overview for the complete list of 45 supported languages with performance benchmarks.

Quick Reference

Code Examples

Go Implementation

Host-side vsock connection and job submission
// Connect to vsock UDS
conn, err := net.Dial("unix", "/tmp/fc-12345.vsock")
if err != nil {
return err
}

// Send CONNECT command
fmt.Fprintf(conn, "CONNECT 5000\n")

// Read response
response, _ := bufio.NewReader(conn).ReadString('\n')
if !strings.HasPrefix(response, "OK") {
return errors.New("vsock connect failed")
}

// Send job request
job := Job{
TraceID: "tr-123",
Lang: "python",
Code: "print('Hello')",
Timeout: 30,
}
sendMessage(conn, job)

// Receive result
result := recvMessage(conn)

Python Implementation

Client code execution via vsock protocol
import json
import socket
import struct

def execute_code(sock_path, port, lang, code, timeout=30):
# Connect to vsock UDS
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
sock.connect(sock_path)

# Connect to guest port
sock.send(f"CONNECT {port}\n".encode())
response = sock.recv(100).decode()
if not response.startswith("OK"):
raise Exception("Vsock connect failed")

# Send job
job = {
"trace_id": f"tr-{uuid.uuid4().hex[:16]}",
"lang": lang,
"code": code,
"timeout": timeout
}
payload = json.dumps(job).encode()
sock.send(struct.pack('>I', len(payload)) + payload)

# Receive result
length = struct.unpack('>I', sock.recv(4))[0]
result = json.loads(sock.recv(length).decode())

sock.close()
return result

Performance Characteristics

MetricValue
Vsock latency< 1ms
Message overhead4 bytes per message
Max payload sizeLimited by memory
Concurrent connections1 per VM (current)

Security Considerations

  • Vsock communication is isolated within the VM boundary
  • No network exposure; only host can communicate with guest
  • Each VM has unique vsock UDS path
  • Guest CID (Context ID) is fixed at 3 (Firecracker default)

Debugging

Enable Verbose Logging

Run with verbose debug output
sudo infra.operator host \
--kernel /srv/firecracker/vmlinux \
--rootfs /srv/firecracker/rootfs.ext4 \
--lang python \
--code "print('test')" \
--verbose # Enable debug output

Monitor Vsock Traffic

Trace vsock communication
# On host, before starting VM
sudo strace -e trace=read,write -s 1000 infra.operator host ...

Check Guest Logs

Mount rootfs and view logs
# SSH into instance, mount rootfs
sudo mount -o loop /srv/firecracker/rootfs.ext4 /mnt
cat /mnt/var/log/infra.operator.log
sudo umount /mnt