Workers in your language.
One wire protocol, multiple implementations. Every SDK interoperates over the same Apache Arrow IPC format.
Python
Reference ImplementationThe original implementation with full feature support — strict mypy typing, all transports, streaming, introspection, shared memory, and OpenTelemetry. Two layers: `vgi-rpc` for the transport, `vgi` for the higher-level DuckDB worker framework.
from typing import Annotated
import pyarrow as pa
import pyarrow.compute as pc
from vgi import ScalarFunction, Param, Returns, Worker
class Upper(ScalarFunction):
@classmethod
def compute(
cls,
s: Annotated[pa.StringArray, Param()],
) -> Annotated[pa.StringArray, Returns()]:
return pc.utf8_upper(s)
class W(Worker):
functions = [Upper]
if __name__ == "__main__":
W().run() TypeScript
Feature ParityFull-featured TypeScript implementation for Bun, Node.js, and Deno. HTTP server/client, OpenTelemetry, dispatch hooks, HTML pages, external storage with S3/GCS backends, and SHA-256 checksums.
import { protocol, runStdio } from "@query-farm/vgi-rpc";
const service = protocol()
.unary({
name: "upper",
params: { s: "str" },
result: "str",
}, ({ s }) => ({ result: s.toUpperCase() }));
await runStdio(service); Go
Feature ParityFull-featured Go implementation built on apache/arrow-go. HTTP server, OpenTelemetry, dispatch hooks, HTML pages, external storage with S3/GCS backends, and SHA-256 checksums.
package main
import (
"context"
"strings"
"github.com/Query-farm/vgi-rpc/vgirpc"
)
type UpperParams struct {
S string `vgirpc:"s"`
}
func main() {
server := vgirpc.NewServer()
vgirpc.Unary(server, "upper",
func(_ context.Context, _ *vgirpc.CallContext, p UpperParams) (string, error) {
return strings.ToUpper(p.S), nil
})
server.RunStdio()
} Rust
Feature ParityRust workspace tracking the Python reference byte-for-byte on the wire — 452 / 452 conformance tests pass across pipe, subprocess, http, and unix transports. Optional features for HTTP, JWT, OAuth-PKCE, mTLS, OpenTelemetry, and Sentry.
use std::sync::Arc;
use arrow_schema::{DataType, Field, Schema};
use vgi_rpc::{MethodInfo, RpcServer};
#[tokio::main]
async fn main() {
let mut srv = RpcServer::builder()
.protocol_name("MyService")
.build();
let params = Arc::new(Schema::new(vec![
Field::new("s", DataType::Utf8, false),
]));
let result = Arc::new(Schema::new(vec![
Field::new("result", DataType::Utf8, false),
]));
srv.register(MethodInfo::unary("upper", params, result, /* handler */));
srv.run_stdio().await.unwrap();
} Java
In DevelopmentJava 21 server framework under the `farm.query.vgirpc` package. Stdio, Unix-socket, and HTTP transports; bearer / JWT / mTLS authenticators; access-log hooks. Conformance-tested against the Python reference; Maven publishing in progress.
Active development
Conformance with the Python reference is the gate for release. A code example will land here as the SDK stabilises.
Track progress on GitHub →C++
In DevelopmentC++20 server framework with pipe and subprocess transports. All RPC patterns (unary, producer, exchange), introspection, error propagation, client logging, and stream headers. Conformance-tested against the Python reference.
Active development
Conformance with the Python reference is the gate for release. A code example will land here as the SDK stabilises.
Track progress on GitHub →Don't see your language?
VGI is a protocol — anyone can implement it
The wire format is Apache Arrow IPC over a pluggable transport. If your language has Arrow bindings (R, Julia, …) it can speak VGI. The full byte-level spec lives at vgi-rpc.query.farm/wire-protocol.
Working on a port? Get in touch — we're happy to help, and to list it here.
Expert help
Need a custom worker built?
We build VGI workers and DuckDB extensions for clients across stacks — pick the language, we'll ship the worker.