# Home

Welcome to the official Gensyn docs.

## Overview

Here you'll find information on Gensyn and its core components, overviews of products, research and our ecosystem, what you can build with it, and how to get started today.&#x20;

### At a Glance

Gensyn is the **Network for Machine Intelligence:** an open infrastructure layer for AI.

It provides the foundational infrastructure AI systems need to operate at scale: **\[1]** compute, **\[2]** data, and **\[3]** information exchange, all accessible through open digital markets where both humans and machines can participate.

Built with native support for AI communication, identification, and verification, Gensyn serves as the economic backbone for continual learning over new decentralised AI models and applications *without* centralised control.

### Information Markets

An information market like [Delphi](https://app.delphi.fyi/) is a fully on-chain mechanism for trading information in a global, decentralised exchange. Anyone, whether human or machine, can deploy a market. Once deployed, it runs autonomously: **\[1]** funds are held by the contract, **\[2]** resolution is determined by on-chain logic, and **\[3]** participation is open and permissionless. The information produced is available for anyone to consume.

For humans, information markets offer a way to reveal and trade signals on open questions, allowing participants to stake on outcomes and earn from accurate bets. For AI models, they are a global optimisation function for continual learning, where information can be freely elicited and traded, and resources can be accrued from correct execution.

The long-term vision is for information markets to become the **agentic bazaar**: driving AI scaling beyond single individuals, companies, or even countries through red queen dynamics over free market trade, with *no* centralised gatekeepers.

### Explore the Gensyn Ecosystem

Read Genysn's latest research papers, blog posts, or get involved with the community.&#x20;

{% tabs %}
{% tab title="Blog" %}
Stay up to date with Gensyn’s latest announcements, deep dives, and perspectives on the future of decentralized machine learning.&#x20;

The blog covers everything from new research releases and protocol updates to philosophical essays on open AI and compute economics. Explore how our technology, community, and mission are evolving in real time.

<p align="center"><a href="https://blog.gensyn.ai" class="button primary">Read our Blog</a></p>
{% endtab %}

{% tab title="Research" %}
Discover the science powering the Gensyn Protocol.&#x20;

Our research library features peer-reviewed papers, technical reports, and experimental frameworks that underpin decentralized machine learning (ML) from scalable verification (Verde) and communication efficiency (NoLoCo, SkipPipe) to collaborative reinforcement learning (RL Swarm).&#x20;

These projects represent the foundation of trustless, open machine intelligence.

<p align="center"><a href="https://gensyn.ai/research" class="button primary">Learn about Gensyn</a></p>
{% endtab %}

{% tab title="Community" %}
Join a growing network of researchers, developers, and node operators building the future of distributed AI.&#x20;

Our Discord is where experiments are shared, new releases are discussed, and contributors collaborate directly with the Gensyn team. Whether you’re running a node, testing a framework, or just curious, you’re welcome here.

<p align="center"><a href="https://discord.com/invite/gensyn" class="button primary">Join our Discord</a></p>
{% endtab %}
{% endtabs %}

### Interactive Products

Explore Gensyn's live products, like tools for deploying information markets, and hands-on AI training environments.

***

{% columns %}
{% column width="50%" %}

### Delphi — Information Markets

<div data-with-frame="true"><figure><img src="/files/8WBtS5aTRR1313OoJ0Aj" alt=""><figcaption></figcaption></figure></div>

{% hint style="info" icon="book-open-lines" %}
[Learn more about Delphi.](https://docs.delphi.fyi/)
{% endhint %}
{% endcolumn %}

{% column width="50%" %}
[Delphi](https://app.delphi.fyi/) is a set of open tools for deploying and participating in information markets on the Gensyn network.&#x20;

Users create and deploy their own markets, which then run autonomously on chain. The Delphi frontend provides a convenient interface for interacting with these user-generated markets.

Anyone can create a market, and anyone can place trades in one. As markets progress, prices update live based on participant activity. When a market resolves, participants are rewarded based on outcomes.
{% endcolumn %}
{% endcolumns %}

***

#### Testnet Products (Paused)

These products have been sunset and are no longer being actively maintained. However, their documentation is still available as an auditable trail of the Gensyn network's progression.

<table data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-card-cover data-type="image">Cover image</th></tr></thead><tbody><tr><td><a href="/spaces/IcazOdplbOmP4R0T7sG8/pages/ofQlnZ5GQyOBJnjhrO2v"><strong>RL Swarm</strong></a></td><td>Launch or join a decentralised swarm of reinforcement learning agents that learn collectively over the internet. RL Swarm is an open framework for distributed RL. You can a node, contribute compute, and help models improve together.</td><td><a href="/files/gq8wv4eY88Us0ICRdzzo">/files/gq8wv4eY88Us0ICRdzzo</a></td></tr><tr><td><a href="/spaces/IcazOdplbOmP4R0T7sG8/pages/8gI1BotvNeSlVhuyWiSq"><strong>BlockAssist</strong></a></td><td>Train a machine learning model to complete real tasks inside Minecraft. BlockAssist turns gameplay into a reinforcement learning environment, showcasing how open, distributed training can emerge through creative experimentation.</td><td><a href="/files/chyIyDeVaVBGZtjtIST7">/files/chyIyDeVaVBGZtjtIST7</a></td></tr><tr><td><a href="/spaces/IcazOdplbOmP4R0T7sG8/pages/UAc1vft26pbWoSN9ssR4"><strong>CodeAssist</strong></a></td><td>CodeAssist is an AI coding assistant that adapts to your style. Solve coding challenges in a browser-based sandbox with no dependencies. As you code, CodeAssist learns your personal programming style: each session improves its customisation for you.</td><td><a href="/files/wQXtAqtEakrQjxlyqPr3">/files/wQXtAqtEakrQjxlyqPr3</a></td></tr></tbody></table>

{% embed url="<https://github.com/gensyn-ai>" %}


# The Gensyn Protocol

An introduction to Gensyn.

<div data-with-frame="true"><figure><img src="/files/Aq9AXMutnLMroWIFrsU0" alt=""><figcaption></figcaption></figure></div>

## What is Gensyn?

Gensyn is the **Network for Machine Intelligence**: an open infrastructure layer that provides the compute, data, and information exchange AI systems need to operate at scale.

{% hint style="info" %}
You can read more about the protocol and the $AI token on the [Gensyn Foundation documentation site.](https://docs.gensyn.network/)
{% endhint %}

It connects humans and machines in open digital markets, enabling both to participate in and benefit from the creation, evaluation, and exchange of machine intelligence. The network is fully open source and permissionless. Anyone can contribute to it or build on it.

### How it Works

Gensyn provides the foundational infrastructure for information markets and decentralised AI applications.&#x20;

This infrastructure is composed of four core layers:

1. **Execution:** A framework for consistent ML execution across any device, from personal computers to data centres. This ensures that work performed anywhere on the network produces compatible, [reproducible results.](/tech)
2. **Verification:** A trustless system for checking and reaching agreement on work performed across the network, enabling participants to transact and collaborate without relying on a central authority.
3. **Communication:** A [peer-to-peer method for sharing workloads and information between devices ](/tech/agent-exchange-layer)over the internet, allowing the network to coordinate globally without centralised infrastructure.
4. **Coordination:** A decentralised layer for identifying participants, aligning incentives, and executing payments permissionlessly. This is what makes open market participation possible for both humans and machines.

Together, these layers form the backbone that information markets and other applications on Gensyn run on.&#x20;

The underlying coordination system is a custom blockchain (Ethereum rollup), which supports a broad ecosystem of complementary applications pushing the frontier of open machine intelligence.

### What This Enables

Gensyn's mission is to make machine intelligence as accessible and open as possible. The network enables:

* **Open information markets:** Anyone can deploy autonomous markets that trade information on chain, creating new mechanisms for surfacing signal, evaluating AI, and rewarding accuracy.
* **Participation for humans and machines:** Both humans and AI models can create markets, trade in them, and consume the information they produce. There are no gatekeepers and no permission required.
* **Peer-to-peer agent communication:** The [Agent eXchange Layer (AXL)](/tech/agent-exchange-layer) is a new primitive from Gensyn: an encrypted, decentralised communication layer that lets AI agents, ML pipelines, and applications exchange data directly between machines without a central server.&#x20;

{% hint style="info" %}
Read more about Gesnyn's [Core Components.](/core-components)
{% endhint %}

#### Get Started

Start by exploring [Delphi](https://app.delphi.fyi/), Gensyn's information market tool and join our [Discord](https://discord.com/invite/gensyn) community to connect with the team and other contributors.


# Core Components

Learn about the four core components that make up the Gensyn protocol.

<div data-with-frame="true"><figure><img src="/files/t2FvO8Q3ctCHLsdxs19g" alt=""><figcaption></figcaption></figure></div>

## The Four Layers

The Gensyn network is built on four foundational layers that together provide the infrastructure for open machine intelligence from reproducible execution to decentralised coordination.

Each layer contributes a distinct capability and is represented by active products, primitives, and research across the Gensyn ecosystem.

{% hint style="info" %}
Read the [Protocol Overview](https://docs.gensyn.network/) here.
{% endhint %}

### Reproducible Execution

> Ensuring that the same model and inputs produce the same outputs, regardless of hardware.

For AI to operate in open, trustless environments where third parties need to independently verify that a computation was performed correctly, execution must be reproducible across machines.

The [Reproducible Execution Environment (REE)](/tech) is Gensyn's toolchain for machine-agnostic, bitwise-reproducible AI model inference. It packages everything needed to run a model: **\[1]** export, **\[2]** compilation, **\[3]** inference, and **\[4]** output decoding into a containerised pipeline that produces identical results regardless of which hardware it runs on.

REE is built on RepOp kernels: purpose-built operators that guarantee bitwise-identical outputs across different hardware, parallelism configurations, and run orders. This is what makes trustless verification possible. If two machines can't agree on the same result, you can't verify anything.

{% columns %}
{% column %}
*Related Research*
{% endcolumn %}

{% column %}
[SAPO](https://blog.gensyn.ai/sapo-efficient-lm-post-training-with-collective-rl/): A reinforcement learning algorithm designed for stable policy optimisation across distributed nodes.
{% endcolumn %}
{% endcolumns %}

### Trustless Verification

> Checking and reaching agreement on work performed, without relying on a central authority.

Once execution is reproducible, work performed across the network can be verified without trusted intermediaries. The verification layer provides a system for detecting and resolving disagreements between participants so the network can always reach consensus on correct results.

{% columns %}
{% column %}
*Related Research*
{% endcolumn %}

{% column %}
[Verde:](https://blog.gensyn.ai/verde-a-verification-system-for-machine-learning-over-untrusted-nodes/) A library of bitwise-reproducible ML operators (RepOps) that provides the theoretical framework underpinning reproducible execution.

[Judge:](judge:https://blog.gensyn.ai/introducing-judge/) A cryptographically verifiable AI evaluator that enforces correctness at the application layer, demonstrating how verification works in practice for real-world AI workloads.
{% endcolumn %}
{% endcolumns %}

### Peer-to-Peer Communication

> Direct, encrypted communication between machines over the internet, without a central server.

The [Agent eXchange Layer (AXL)](/tech/agent-exchange-layer) is a peer-to-peer communication primitive built by Gensyn. It provides an encrypted, decentralised communication layer where AI agents, ML pipelines, and applications can exchange data directly between machines.&#x20;

AXL is application-agnostic, meaning it moves bytes between peers and has no opinion about what those bytes mean, and features built-in support for MCP (Model Context Protocol) and A2A (Agent-to-Agent) communication.

{% columns %}
{% column %}
*Related Research*
{% endcolumn %}

{% column %}
[NoLoCo:](https://blog.gensyn.ai/noloco-training-large-models-with-no-all-reduce/) Replaces the costly all-reduce step with a low-communication gossip approach for distributed training.

[CheckFree:](https://blog.gensyn.ai/checkfree-fault-tolerant-training-without-checkpoints/) Enables fault-tolerant recovery without checkpointing, reducing compute overhead.

[SkipPipe:](https://blog.gensyn.ai/skippipe-a-communication-efficient-method-for-decentralised-training/) An efficient gradient-sharing algorithm that minimises message hops across the network.
{% endcolumn %}
{% endcolumns %}

### On-Chain Coordination

> Bringing participants and applications together on a shared, permissionless ledger.

The coordination layer provides the on-chain infrastructure for applications on the Gensyn network.&#x20;

Today, this is where information markets deployed through Delphi run, with market creation, participation, and resolution all happening on chain.

As the network matures, this layer will expand to support broader economic coordination: participant identification, incentive alignment, and permissionless payment settlement across the ecosystem.

### Getting Started

Explore [Delphi](https://app.delphi.fyi/) to create or trade in information markets, try [AXL](/tech/agent-exchange-layer) to build peer-to-peer agent applications, or join our [Discord](https://discord.com/invite/gensyn) community to connect with the team and other contributors.


# Products & Research

Read about Gensyn's research initiatives, projects, and products.

<div data-with-frame="true"><figure><img src="/files/LJVQNdWvjnJFvvjsaZSE" alt=""><figcaption></figcaption></figure></div>

## Research

Each publication advances one or more of the network's core layers: **\[1]** reproducible execution, **\[2]** trustless verification, **\[3]** peer-to-peer communication, and **\[4]** on-chain coordination.

Together, these projects form the scientific foundation for an open network where humans and machines can participate in decentralised markets for machine intelligence.

### Current Projects

These projects collectively form the experimental backbone of the Gensyn protocol.

They are where new ideas are tested, validated, and refined before being integrated into the protocol so  every architectural layer of Gensyn is grounded in reproducible, peer-reviewed science.

***

<table data-card-size="large" data-column-title-hidden data-view="cards" data-full-width="false"><thead><tr><th></th><th></th><th></th><th data-hidden data-card-cover data-type="image">Cover image</th></tr></thead><tbody><tr><td><strong>Delphi</strong></td><td><em>Information Market Tools</em></td><td>A set of open tools for deploying and participating in information markets on the Gensyn network. Users create and deploy their own markets on any topic, which run autonomously on chain. Anyone can create a market, and anyone can trade in one.<br><br><a href="https://app.delphi.fyi/">Make Your Market</a><br><a href="https://docs.delphi.fyi/">Documentation</a></td><td><a href="/files/8WBtS5aTRR1313OoJ0Aj">/files/8WBtS5aTRR1313OoJ0Aj</a></td></tr><tr><td><strong>Agent eXchange Layer (AXL)</strong></td><td><em>Decentralised Communication for Agents</em></td><td>A peer-to-peer communication primitive that lets AI agents, ML pipelines, and applications exchange data directly between machines. It is encrypted, decentralised, and without a central server. AXL is application-agnostic, permissionless, and features built-in support for MCP and A2A protocols.<br><br><a href="https://docs.gensyn.ai/tech/agent-exchange-layer">Documentation</a><br><a href="https://github.com/gensyn-ai/axl">GitHub Repository</a></td><td><a href="/files/ku5jqYbKEAmkPVRyuA79">/files/ku5jqYbKEAmkPVRyuA79</a></td></tr><tr><td><strong>Reproducible Execution Environment (REE)</strong></td><td><em>Reproducible Inference on Any Machine</em></td><td>Gensyn's toolchain for machine-agnostic, bitwise-reproducible AI model inference. REE packages everything needed to run a model (export, compilation, inference, and output decoding) into a containerised pipeline that produces identical results regardless of hardware. Built on RepOp kernels, REE is what makes trustless verification of AI inference possible.<br><br><a href="https://docs.gensyn.ai/tech">Documentation</a><br><a href="https://github.com/gensyn-ai/ree">Repository</a></td><td><a href="/files/ieiMG6jpXJHBbQikLczO">/files/ieiMG6jpXJHBbQikLczO</a></td></tr><tr><td><strong>Verde</strong><br><br><em>A Verification System for Machine Learning over Untrusted Nodes</em><br><br>A scalable verification protocol for decentralized machine learning. Verde introduces Reproducible Operators (RepOps), bitwise-deterministic ML primitives that ensure identical results across heterogeneous hardware, enabling trustless verification of model training.<br><br><a href="https://arxiv.org/abs/2502.19405">Research Paper</a><br><a href="https://www.gensyn.ai/articles/verde">Blog Post</a></td><td></td><td></td><td><a href="/files/YsyT1uaMepZ6TdLS4hQO">/files/YsyT1uaMepZ6TdLS4hQO</a></td></tr><tr><td><p><strong>NoLoCo</strong></p><p><br><em>Training Large Models With No All-Reduce</em></p><p><br>A communication-efficient training method that eliminates global all-reduce synchronization. Using pairwise gossip averaging, NoLoCo achieves comparable convergence to standard distributed training at a fraction of the bandwidth cost.<br><br><a href="https://arxiv.org/abs/2506.10911">Research Paper</a><br><a href="https://www.gensyn.ai/articles/noloco">Blog Post</a></p></td><td></td><td></td><td><a href="/files/YiCDDxW6lOdmMN0ksHnE">/files/YiCDDxW6lOdmMN0ksHnE</a></td></tr><tr><td><strong>CheckFree</strong><br><br><em>Fault-Tolerant Training Without Checkpoints</em><br><br>Introduces a recovery mechanism that maintains training progress without traditional checkpoints, improving fault tolerance and throughput for distributed ML jobs.<br><br><a href="https://arxiv.org/abs/2506.15461">Research Paper</a><br><a href="https://www.gensyn.ai/articles/checkfree">Blog Post</a></td><td></td><td></td><td><a href="/files/eeFPGPovQubtaWH4zh5e">/files/eeFPGPovQubtaWH4zh5e</a></td></tr><tr><td><strong>SkipPipe</strong><br><br><em>Communication-Efficient Gradient Sharing</em><br><br>Presents an optimization layer that reduces message hops and synchronization latency between nodes, forming part of Gensyn’s low-overhead communication backbone.<br><br><a href="https://arxiv.org/abs/2502.19913">Research Paper</a><br><a href="https://www.gensyn.ai/articles/skip-pipe">Blog Post</a></td><td></td><td></td><td><a href="/files/57nNaMx61TLu0tZcFx0Q">/files/57nNaMx61TLu0tZcFx0Q</a></td></tr><tr><td><strong>RL Swarm</strong><br><br><em>A Framework for Collaborative Reinforcement Learning</em><br><br>Demonstrates how multiple models can train collectively across the internet, critiquing and improving one another’s outputs in real time. RL Swarm showcases decentralized coordination and collective learning in action.<br><br><a href="https://github.com/gensyn-ai/paper-rl-swarm/blob/main/latest.pdf">Research Paper</a><br><a href="https://www.gensyn.ai/articles/skip-pipe">Blog Post</a></td><td></td><td></td><td><a href="/files/gq8wv4eY88Us0ICRdzzo">/files/gq8wv4eY88Us0ICRdzzo</a></td></tr><tr><td><strong>Diverse Network Ensembles</strong><br><br><em>Embarrassingly Parallel LLMs From Diverse Experts</em><br><br>Explores how heterogeneity in model size, training duration, and data domain leads to superior ensemble performance, laying groundwork for a global 'internet of models.'<br><br><a href="https://www.gensyn.ai/articles/diverse-expert-ensembles">Blog Post</a><br><a href="https://arxiv.org/abs/2502.19385">Research Paper</a></td><td></td><td></td><td><a href="/files/5dnsCSfOv7uEJjfzvp5l">/files/5dnsCSfOv7uEJjfzvp5l</a></td></tr><tr><td><strong>BlockAssist</strong><br><br><em>A Playful Reinforcement Learning Environment</em><br><br>An interactive Minecraft-based research demo where AI agents learn from player behavior. BlockAssist visualizes how distributed reinforcement learning frameworks like RL Swarm can operate in open, dynamic environments.<br><br><a href="/spaces/IcazOdplbOmP4R0T7sG8/pages/8gI1BotvNeSlVhuyWiSq">Documentation</a><br><a href="https://arxiv.org/abs/2502.19385">Research Paper</a></td><td></td><td></td><td><a href="/files/chyIyDeVaVBGZtjtIST7">/files/chyIyDeVaVBGZtjtIST7</a></td></tr><tr><td><strong>Judge</strong><br><br><em>Cryptographically Verifiable AI Evaluation</em><br><br>A protocol and runtime that ensures reinforcement learning tasks are executed fairly and verifiably across distributed environments. Judge provides a decentralized execution layer within RL Swarm, allocating, scheduling, and validating workloads while enforcing consistency and fairness across nodes.<br><br><a href="https://blog.gensyn.ai/introducing-judge/">Blog Post</a></td><td></td><td></td><td><a href="/files/UKo9wAsPKg6v6CoJLZyM">/files/UKo9wAsPKg6v6CoJLZyM</a></td></tr><tr><td><strong>SAPO</strong><br><br><em>Efficient RL Post-Training Across Distributed Networks</em><br><br>A fully decentralized and asynchronous reinforcement learning post-training algorithm where models share rollouts across a swarm. SAPO enables faster, more efficient collective learning with less compute per node, reducing communication overhead while maintaining performance.<br><br><a href="https://blog.gensyn.ai/sapo-efficient-lm-post-training-with-collective-rl/">Blog Post</a><br><a href="https://arxiv.org/abs/2509.08721?ref=blog.gensyn.ai">Research Paper</a></td><td></td><td></td><td><a href="/files/BZWVNjV8veiY0DFGICck">/files/BZWVNjV8veiY0DFGICck</a></td></tr><tr><td><strong>Testnet</strong><br><br><em>The Network for Machine Intelligence</em><br><br>A custom Ethereum rollup dedicated to machine learning, integrating off-chain execution, verification, and communication frameworks into a single permissionless network. The Gensyn Testnet coordinates global compute contributors and researchers, serving as the live backbone for decentralized AI.<br><br><a href="https://www.gensyn.ai/testnet">Read More</a><br><a href="https://github.com/gensyn-ai/rl-swarm">GitHub</a></td><td></td><td></td><td><a href="/files/S8bJsHbIWbmbnXqzhCUr">/files/S8bJsHbIWbmbnXqzhCUr</a></td></tr><tr><td><strong>CodeAssist</strong><br><br><em>The More you Code, the More it Aligns</em></td><td>A reinforcement + assistance learning framework where you teach an AI to code by coding yourself. As you solve problems, the assistant observes your edits and trains locally to adapt to your personal coding style. Each session becomes a new episode of learning, building smarter, more personalized models with every interaction.<br><br><a href="https://blog.gensyn.ai/introducing-codeassist/">Blog Post</a><br>Research Paper (Coming Soon)</td><td></td><td><a href="/files/wQXtAqtEakrQjxlyqPr3">/files/wQXtAqtEakrQjxlyqPr3</a></td></tr></tbody></table>

***

### How Research Fits In

Each of Gensyn’s research initiatives contributes to the evolution of the protocol itself. \
\
The experiments, proofs, and frameworks developed here feed directly into the [Core Components](/core-components), which is how tasks are executed, verified, communicated, and coordinated across the network.

{% hint style="success" %}
What begins as a research paper often becomes an open-source framework, then a working system deployed on the Testnet.&#x20;
{% endhint %}

#### Get Started

Explore [Delphi](https://app.delphi.fyi/) to create or trade in information markets, try [AXL](/tech/agent-exchange-layer) to build peer-to-peer agent applications, or join our [Discord](https://discord.com/invite/gensyn) community to connect with the team and other contributors.


# Get Started

Start getting involved in the Gensyn ecosystem and contribute to the Testnet today.

<div data-with-frame="true"><figure><img src="/files/AocPjBDaYwPD7zCMkgn2" alt=""><figcaption></figcaption></figure></div>

## First Steps

Gensyn is an open network for machine intelligence. The best way to get started is to explore what's live today.

{% stepper %}
{% step %}

### Get Familiar

[Delphi](https://app.delphi.fyi/) is a set of open tools for deploying and participating in information markets: create a market on any topic, trade in existing ones, or browse what others have created.

* [ ] Explore [Delphi](https://app.delphi.fyi/)
* [ ] Read the Delphi Documentation

**AXL (Agent eXchange Layer)** is a peer-to-peer communication primitive for AI agents and applications: encrypted, decentralised, and open for anyone to build on.

* [ ] Read the AXL Documentation
* [ ] Browse the AXL GitHub repository

**Explore Resources:**

* [ ] Browse the [GitHub repository](https://github.com/gensyn-ai/rl-swarm)
* [ ] Visit the [Gensyn Dashboard](https://dashboard.gensyn.ai/)
* [ ] Look at verified contributions on the [Block Explorer](https://gensyn-testnet.explorer.alchemy.com/)
  {% endstep %}

{% step %}

### Build or Participate

There are several ways to get involved depending on your interests.

1. **Create or trade in information markets:** Use Delphi to deploy your own markets or participate in ones created by others.&#x20;
2. **Build with AXL:** Run a node and start building peer-to-peer agent applications, distributed ML pipelines, or anything that needs encrypted machine-to-machine communication. AXL ships with example applications including MCP-based agent collaboration, distributed inference, GossipSub messaging, and convergecast aggregation.
3. **Try the research demos:** Get hands-on with [RL Swarm](/testnet/rl-swarm), [BlockAssist](/testnet/blockassist), or [CodeAssist](/testnet/codeassist) to see decentralised learning in action.
   1. [RL Swarm:](/testnet/rl-swarm) Launch or join a decentralised swarm of reinforcement learning agents.
   2. [BlockAssist](/testnet/blockassist): Train a model to complete tasks inside Minecraft.
   3. [CodeAssist](/testnet/codeassist): Solve coding challenges while an AI assistant learns your style.

{% hint style="warning" %}
There are no official swarms running right now.&#x20;

Please check back later if you're interested in participating in a global, decentralised, crowd-sourced training run or feel free to join a community-owned swarm.&#x20;
{% endhint %}
{% endstep %}

{% step %}

### Go Deeper

**Read the research:** Explore Gensyn's open research library to understand the science behind the network, from reproducible execution and trustless verification to communication-efficient distributed training.

> See [Products & Research](/products-and-research)
> {% endstep %}

{% step %}

### Join the Community

Our Discord is where experiments are shared, new releases are discussed, and contributors collaborate directly with the Gensyn team.

> Join our [Discord](https://discord.com/invite/gensyn)
> {% endstep %}
> {% endstepper %}


# Reproducible Execution Environment (REE)

Run AI model inference in a machine-agnostic environment where the same model and inputs produce the same outputs across supported hardware.

## Overview

REE (Reproducible Execution Environment) is Gensyn's toolchain for executing AI model inference in a machine-agnostic, bitwise-reproducible fashion.

It packages everything needed to run a model: **\[1]** export, **\[2]** compilation, **\[3]** inference, and **\[4]** output decoding, into a containerized pipeline that produces bitwise-identical results regardless of which hardware it runs on.

REE is comprised of three main components:

1. **Gensyn SDK:** The engine that orchestrates the end-to-end pipeline: export, compilation, inference, and output decoding.

{% hint style="info" %}
The Gensyn SDK also exposes higher-level primitives for reusable inference sessions and tool-augmented inference workflows.
{% endhint %}

2. **Gensyn Compiler:** An MLIR-based, multi-stage compiler that converts ONNX models into PyTorch modules, optionally replacing standard kernels with reproducible ones.
3. **RepOp Kernels:** Purpose-built CPU kernels and GPU operators that guarantee bitwise-identical outputs across different hardware, parallelism configurations, and run orders.

The Gensyn SDK also exposes higher-level primitives for reusable inference sessions, tool definitions in chat-template-based inference (v0.3.0), and thinking-mode control via chat templates (v0.4.0).

You interact with all of these through the [REE TUI](/tech/ree/using-the-tui)**,** a terminal interface that lets you configure and run generations *without* touching the underlying CLI directly, unless you're interested in [advanced usage.](/tech/ree/advanced-usage)

{% hint style="warning" %}
While the scripts in this repository are open-source, REE as a whole is not. REE includes proprietary components that are downloaded from Gensyn servers, and these components are subject to Gensyn's licensing terms.&#x20;

*By using this software, you agree to comply with those terms. For official terms and conditions, please see the* [*EULA licensing agreement.*](https://github.com/gensyn-ai/ree/blob/main/REE-Binary-License)
{% endhint %}

### Why Reproducibility?

Standard GPU execution is inherently non-deterministic, meaning the same model with the same inputs can produce different outputs each time you run it.&#x20;

This happens because of how GPUs handle mathematical operations: they split work across many parallel processors to run faster, but this parallelization can happen in slightly different orders between runs. Even tiny differences in the order of operations can accumulate through the many layers of a neural network, eventually leading to noticeably different results.

Existing solutions like PyTorch's deterministic mode only solve part of the problem. They can make your results consistent on the same GPU across multiple runs, but they break down when you switch to different hardware. For example, an A100 and an H100 will still produce different outputs. These tools also have limited coverage and can't account for the fact that different GPU architectures implement mathematical functions differently at the hardware level.

REE solves this because reproducibility is *essential* for verifiable AI inference.

When third parties need to independently verify that a computation was performed correctly, such as in decentralized compute networks or prediction markets, they must be able to run the same model on their own hardware and get exactly the same result.

REE achieves this through [RepOps](/tech/ree/advanced-usage/internals), custom operators that use careful mathematical techniques (fixed reduction ordering, correctly rounded functions, and extended precision) to guarantee identical outputs across any hardware, without sacrificing too much performance.

### Operation Modes

REE supports three operation modes, which you can set via the **Extra Args** field in the [TUI](/tech/ree/using-the-tui):

| Mode            | Behavior                                                                                  | Cross-run determinism | Cross-hardware determinism |
| --------------- | ----------------------------------------------------------------------------------------- | --------------------- | -------------------------- |
| `default`       | Uses standard PyTorch kernels. No determinism guarantees.                                 | ❌                     | ❌                          |
| `deterministic` | Uses PyTorch deterministic algorithms. Reproducible on **the same hardware** across runs. | ✅                     | ❌                          |
| `reproducible`  | Uses Gensyn RepOp kernels. Bitwise-identical results across **any supported hardware**.   | ✅                     | ✅                          |

There are different use cases for the three operation modes:

* Use `reproducible` when results must be independently verifiable by a third party on different hardware.&#x20;
* Use `deterministic` when you need repeatable results on your own machine.&#x20;
* Use `default` for development and testing where speed matters more than reproducibility.

### Tool-Augmented Inference

The Gensyn SDK supports tool-call workflows (first introduced in `v0.3.0`).

Tool definitions can be passed to `InferenceSession.complete()` when using chat-style `messages`. REE forwards them to the model tokenizer's chat template when supported.&#x20;

{% hint style="info" %}
REE does not ship built-in tools or execute tool calls. Instead, applications define tools, parse model output, and run the tool loop themselves.
{% endhint %}

External tool results are only reproducible if the application records and replays the exact outputs passed back to the model.

#### Thinking Mode

REE `v0.4.0` adds `enable_thinking` on `InferenceSession.complete()` for models whose chat templates support a thinking/reasoning toggle (for example, Qwen3).

* **SDK only:** This is not exposed on the `gensyn-sdk` CLI or TUI.
* **Requires `messages`:** use chat-style messages, not a plain `prompt` string.
* **Default:** `None`. When omitted, REE does not pass the `kwarg` and behavior matches prior releases.
* **Explicit values:** `enable_thinking=True` or `enable_thinking=False` are forwarded to `apply_chat_template` only when the tokenizer accepts the parameter.

{% hint style="info" %}
For CLI/TUI one-shot runs, use `--short-circuit-length` / `--short-circuit-token` to bound thinking tokens, or migrate to the SDK for direct on/off control.
{% endhint %}


# Get Started

Install REE, launch the TUI, and run your first reproducible generation.

## Quickstart Guide

Everything you need to go from zero to your first receipt: **\[1]** prerequisites, **\[2]** installation, and **\[3]** a guided first run.&#x20;

{% hint style="info" %}
REE supports reproducible inference on models up to 72B parameters, with pipeline parallelism available for models that exceed a single GPU's memory. This provides a benefit on multi-GPU hosts.&#x20;
{% endhint %}

### Prerequisites

* [**Docker**](https://www.docker.com/get-started/) installed and running.
* [**Python 3**](https://www.python.org/downloads/) installed on your machine.
* **Disk Space Requirements:** The compressed REE container image is roughly 7 GB. When uncompressed, it occupies approximately 12 GB on disk.&#x20;
* **NVIDIA GPU Driver Requirements:** Linux requires version **570.00+** and Windows requires **572.16+**. Check your current driver version with `nvidia-smi`.&#x20;

{% hint style="info" %}
To update your drivers, visit [NVIDIA Driver Downloads.](https://www.nvidia.com/en-us/drivers/) If your system lacks a compatible GPU or driver, you can still execute `ree.sh` with the `--cpu-only` flag for CPU-only mode.&#x20;
{% endhint %}

For a minimal SDK application example, see the SDK Hello World example in the REE repository.

### Installing REE

Clone the [GitHub repository](https://github.com/gensyn-ai/ree) and navigate into it:

```bash
git clone https://github.com/gensyn-ai/ree.git
cd ree
```

No additional installation or dependency management is required. The TUI handles pulling the REE container image automatically on your first run.

{% hint style="info" %}
The repository also includes `ree.sh`, a lower-level shell script that `ree.py` calls under the hood. You shouldn't need to use `ree.sh` directly unless you're debugging or working on an [advanced integration.](/tech/ree/advanced-usage)
{% endhint %}

### Updating REE

To update REE, pull the latest repository changes and run the TUI again:

```bash
cd ree
git pull
python3 ree.py
```

The TUI calls `ree.sh`, which automatically pulls the configured REE container image (`gensynai/ree:v0.4.0`).

### Launching the TUI

The TUI opens with an interactive form where you can configure and launch generations entirely from within the interface without the need to manually assemble CLI commands.

From the `ree` directory, run:

```bash
python3 ree.py
```

If you prefer the command line, REE can also be driven directly via `ree.sh` or the `gensyn-sdk` CLI without the TUI. This may be preferable if you're scripting, working in a CI pipeline, or using a coding agent like Claude Code. See the [Advanced Usage & CLI Reference](/tech/ree/advanced-usage) for the full CLI documentation.

### Your First Run

When the TUI launches, you'll see this form:

<figure><img src="/files/BDR8jn5hovhNakuQjQly" alt=""><figcaption></figcaption></figure>

To run your first generation:

1. Use the **arrow keys** to navigate to **Model Name** from this list and press **Enter** to edit it.
2. Navigate to **Prompt Text** and press **Enter**. Type a simple prompt like `Hello world`.
3. Set a **Max New Tokens** count.
4. Press **`r`** to run.

REE will pull the container image, prepare the model, run inference, and display a progress checklist:

<figure><img src="/files/eMD5INi6artxJ8ARwQMn" alt=""><figcaption></figcaption></figure>

Once complete, you'll see the **REE Output** section showing the [receipt](/tech/ree/receipts) file path and the model's generated text.

{% hint style="info" %}
If you used a Hugging Face test model or small-parameter model, the output may be nonsensical. This is expected, since these models either have random, untrained weights or consume too few tokens to produce a polished output. The important thing is that the pipeline ran successfully.
{% endhint %}

From here you can press **`e`** to reset and configure another run, **`r`** to re-run with the same settings, or **`q`** to quit.


# Using the TUI

Select models, set prompts, tune parameters, and interpret the output inside of the TUI.

## Text User Interface (TUI)

The REE TUI is the primary way to interact with REE.

It wraps the full pipeline: **\[1]** model export, **\[2]** compilation, **\[3]** inference, **\[4]** decoding, and **\[5]** receipt generation, behind an interactive form. You configure your run, press `r`, and the TUI handles everything else.

The interface has two main states: the **configuration form** where you set up your run, and the **results view** where you see output, logs, and the receipt path after a run completes.

### Configuring a Run

Each field in the form controls a different aspect of the generation. Here's what each one does and when you'd change it.

#### Subcommand

This is where you choose which action to perform. The TUI offers three subcommands:

| Subcommand | What it does                                                                                                                                           |
| ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `run`      | The default. Runs the full inference, receipt generation, and decoding pipeline from end-to-end.                                                       |
| `validate` | Checks that a receipt is structurally valid and internally consistent (hashes match). Does not re-run inference.                                       |
| `verify`   | Re-runs the inference described in a receipt and compares the output against it. This is the strongest check, which proves the result is reproducible. |

#### Model Name

The Hugging Face model ID to use for inference (e.g., `Qwen/Qwen3-0.6B`, `meta-llama/Llama-3-8B`). Press `Enter` to edit, type the model ID, and press `Enter` again to confirm.

Any Hugging Face model compatible with the system can be used, including those in this [list of verified compatible models.](/tech/ree/supported-models)

The first time you use a model, REE will download it from Hugging Face and export it to ONNX format. Subsequent runs with the same model reuse the cached export, so they start much faster.

{% hint style="info" %}
If you have a specific model in mind that doesn't work with REE, you can reach out to the Gensyn team by creating an issue in the [GitHub repository](https://github.com/gensyn-ai/ree/issues) and we'll do our best to support it.
{% endhint %}

#### Prompt Text

The prompt to send to the model. Press `Enter` to edit, type or paste your prompt, and press `Enter` to confirm.

This is the simplest way to provide a prompt and works well for short to moderate-length inputs.

#### Prompt File

This is where you’d paste the path to a local JSONL file containing your prompt.

Each line in the file must be either a JSON string (e.g., `"What is 2 + 2?"`) or a JSON object with a `prompt` field (e.g., `{"prompt": "Explain deterministic inference."}`). Note that plain `.txt` files are not supported and will produce unhelpful errors.

{% hint style="warning" %}
The prompt file *must* be valid JSONL.
{% endhint %}

If both **Prompt Text** and **Prompt File** are filled in, entering any text in either field will clear the other. To revert to inline text, simply enter something in the **Prompt Text** field, and the **Prompt File** field will be auto-cleared.

#### Max New Tokens

This is the maximum number of tokens the model will generate. The TUI defaults this field to `50`. The underlying `gensyn-sdk` CLI default is `300` when `--max-new-tokens` is omitted.

You can increase this for longer outputs. Generation will stop earlier if the model produces an end-of-sequence token before hitting this limit.

#### Partitions

The number of pipeline partitions used for inference which maps to the `--n-partitions` CLI flag. You should use a value greater than `1` when running large models across multiple GPUs.

Pipeline parallelism requires a multi-GPU host; setting `Partitions` above `1` on a single-GPU machine is expected to fail. For most single-GPU runs, leave this set to `1`.

### Extra Args

These are optional flags that control how the generation runs. This is where you set the operation mode, sampling parameters, and other advanced options. To use these, just type them as you would CLI flags, separated by spaces.

Common flags you'll use here:

| Flag                             | Default        | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| -------------------------------- | -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--operation-set`                | `reproducible` | `default`, `deterministic`, or `reproducible`. Controls whether RepOp kernels are used.                                                                                                                                                                                                                                                                                                                                                                                |
| `--cpu-only`                     | `false`        | Force CPU execution even if a GPU is available.                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `--n-partitions`                 | `1`            | <p>Split the model across <em>N</em> pipeline partitions to run models that don't fit on a single GPU.<br><br>Requires N ≥ 2 GPUs: otherwise, setting this on a single-GPU host will <em>fail</em>. See <a href="/pages/h3NBApPFih3AgyrmUQlM#pipeline-parallelism">Pipeline Parallelism</a>.<br><br>This argument can still be passed through Extra Args when driving REE from the CLI, but in the TUI you should use the dedicated <code>Partitions</code> field.</p> |
| `--temperature`                  | `1.0`          | Sampling temperature. Higher values produce more random output.                                                                                                                                                                                                                                                                                                                                                                                                        |
| `--top-k`                        | `50`           | Top-k sampling cutoff.                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| `--top-p`                        | `1.0`          | Nucleus sampling threshold.                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `--min-p`                        | Disabled       | Min-p sampling threshold.                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| `--do-sample` / `--no-do-sample` | Enabled        | Enable or disable stochastic sampling.                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| `--repetition-penalty`           | `1.0`          | Repetition penalty multiplier.                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| `--force-model-export`           | `false`        | Re-export the ONNX model even if a cached version exists.                                                                                                                                                                                                                                                                                                                                                                                                              |
| `--disable-kv-cache`             | `false`        | Disable KV cache during generation.                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `--short-circuit-length`         | —              | Generation step at which to inject the short-circuit token.                                                                                                                                                                                                                                                                                                                                                                                                            |
| `--short-circuit-token`          | —              | Token ID to inject when short-circuiting.                                                                                                                                                                                                                                                                                                                                                                                                                              |

**Example:** `--operation-set reproducible --temperature 0.7 --top-p 0.9`

#### Operation Set

This flag is called `--operation-set` because it controls which set of operations the PyTorch runtime uses during inference: either standard PyTorch kernels, PyTorch's deterministic kernels, or Gensyn's RepOp kernels. It is the *most important flag* you'll set in the **Extra Args** field.

It determines what kind of reproducibility guarantees your run has, which directly affects whether your receipt can be verified by others.

There are three options:

1. **`default`**: Uses standard PyTorch kernels with no reproducibility guarantees. The same run on the same machine might produce different outputs each time. Use this when you're experimenting or testing and don't need a verifiable receipt.
2. **`deterministic`**: Uses PyTorch's built-in deterministic algorithms. Your results will be consistent across multiple runs on the same machine, but will differ if someone tries to verify your receipt on different hardware. Use this when you need repeatable results for your own work but aren't sharing receipts for third-party verification.
3. **`reproducible`:** Uses Gensyn's [RepOp](/tech/ree/advanced-usage/internals) kernels, which guarantee bitwise-identical results across any supported hardware. This is the mode you want when generating receipts that others will verify. It's slightly slower than the other modes, but it's the only one that makes your receipt truly portable.

{% hint style="success" %}
**As a rule of thumb:** if someone else will ever run `verify` on your receipt, use `reproducible`. If it's just for you, `deterministic` is fine. If you don't care about reproducibility at all, `default` is the fastest.
{% endhint %}

#### Tool Calls

The TUI does not expose tool-call configuration. For tool-call workflows, you need to use the Python SDK and `InferenceSession.complete(messages=..., tools=...)`.

{% hint style="success" %}
Use the TUI for interactive runs, validation, and verification. Use the SDK for reusable sessions and tool-augmented workflows.
{% endhint %}

#### Thinking Mode

The TUI does not expose `enable_thinking` (v0.4.0). For direct thinking on/off control, use the SDK. For CLI/TUI runs on reasoning models, [see this section.](/tech/ree/examples#short-circuiting-reasoning-models)

### Running a Generation

Once your fields are configured, press **`r`** to start the run.

The TUI switches to a progress view showing each stage of the pipeline as it completes. You'll see status updates as REE pulls the container image, prepares the model, runs inference, and assembles the receipt.

<figure><img src="/files/P9dxp8BPPPAlCLHQa3oB" alt=""><figcaption></figcaption></figure>

If something goes wrong, the progress view will show which stage failed and the **Logs** section will contain the full output for debugging.

### Reading the Output

After a successful run, the TUI displays several populated fields:

* **REE Output:** The path to the receipt file and the model's generated text.
* **Logs:** Full pipeline output, useful for debugging or inspecting what happened during each stage.
* **Receipt path:** The location of your receipt file (e.g., `metadata/receipt_20260311_155048.json`).

#### Demonstrations

You can find a list of common workflow [examples and demonstrations here](/tech/ree/examples) along with the additional arguments and parameters you'll need to set.

### Controls Reference

| Key                                          | Action                                                   |
| -------------------------------------------- | -------------------------------------------------------- |
| `Enter/Return`                               | Edit the selected field                                  |
| `up`, `down`, `left`, `right` *(arrow keys)* | Move between fields                                      |
| `r`                                          | Run the generation (or re-run from results view)         |
| `q`                                          | Quit the TUI                                             |
| `c`                                          | Cancel a running generation                              |
| `e`                                          | Reset the run state and return to the configuration form |
| `l`                                          | View the REE license                                     |


# Receipts

Understand what receipts prove, what they contain, and how to validate them.

### Receipts

A **receipt** is a cryptographic thumbprint of a completed REE execution. It chains together hashes of the inputs (model, prompt, configuration) and outputs (generated tokens) so that anyone can verify whether a claimed result is consistent with the claimed inputs without needing to re-execute the computation.

After every successful run, the TUI displays the path to the receipt file. Receipts are designed to be shared with others, who can then use them to verify that they can reproduce the same output using REE.&#x20;

{% hint style="info" %}
We recommend sharing receipts alongside any claims about model behavior, so that others can verify those claims for themselves.
{% endhint %}

#### What You’re Actually Verifying

REE guarantees reproducibility of *computation*, not the correctness of *inputs* or the correctness of the *outputs.*

A receipt proves that a given model produced a given output from a given prompt. It does not verify that the information in the prompt is accurate or that any action was taken based on the output.

#### Receipts and Tool Calls

Receipts include tool definitions when (and if) they are provided through the SDK. These are stored under `input.tools` and committed through `input.tools_hash`, which is included in the final `receipt_hash`.

Receipts do not execute tools and do not prove that an external tool returned accurate, complete, or unchanged data. If your application executes tools, you should separately record the tool call arguments, tool outputs, timestamps, provider metadata, and any external source data passed back to the model.

{% hint style="warning" %}
Tool definitions are hashed separately as `tools_hash` and are not part of `config_hash`.
{% endhint %}

#### What a Receipt Contains

| Field             | Type       | Description                                                                                                                   |
| ----------------- | ---------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `model_name`      | string     | Hugging Face model ID used for inference.                                                                                     |
| `commit_hash`     | string     | Specific Hugging Face model revision (git commit hash).                                                                       |
| `config_hash`     | string     | Hash of the full task configuration (`config.json`).                                                                          |
| `prompt`          | string     | The raw prompt text that was provided.                                                                                        |
| `prompt_hash`     | string     | Hash of the prompt.                                                                                                           |
| `parameters`      | object     | Sampling and generation parameters used (temperature, top\_k, top\_p, etc.).                                                  |
| `parameters_hash` | string     | Hash of the parameters object.                                                                                                |
| `tokens_hash`     | string     | Hash of the generated output tokens.                                                                                          |
| `token_count`     | int        | Number of tokens generated.                                                                                                   |
| `finish_reason`   | string     | Why generation stopped: `"eos_token"` (model produced end-of-sequence naturally) or `"max_length"` (hit the max token limit). |
| `text_output`     | string     | The decoded text output of the generation.                                                                                    |
| `device_type`     | string     | Device used for inference (e.g., `cpu`, `cuda`).                                                                              |
| `device_name`     | string     | Specific device identifier.                                                                                                   |
| `receipt_hash`    | string     | Hash over `commit_hash`, `config_hash`, `prompt_hash`, `tools_hash`, `parameters_hash`, and `tokens_hash`.                    |
| `version`         | string     | The receipt schema version.                                                                                                   |
| `ree_version`     | string     | The version of the REE SDK that generated the receipt.                                                                        |
| `tools`           | array/null | Tool definitions provided to the model for SDK-based tool-call workflows. Null when no tools were provided.                   |
| `tools_hash`      | string     | Hash of the canonicalized tool definitions.                                                                                   |

#### What a Receipt Does NOT Contain

A receipt does not include the model weights themselves, intermediate compilation artifacts, or timing/performance data.&#x20;

It is a proof of *what* was computed and *what* was produced, not how fast or on which exact machine, though the receipt does include both `device_type` and `device_name` (for example, "NVIDIA A100") as informational metadata. Neither of these are part of the `receipt_hash`.

### Validating a Receipt

Validation recomputes hashes from the data stored within the receipt itself and compares them against the hash values in the receipt. This checks internal consistency, that the receipt hasn't been tampered with or corrupted, *not* that it matches anything on disk.

A valid receipt must satisfy all of the following:

* `prompt_hash` matches a recomputed hash of the prompt
* `parameters_hash` matches a recomputed hash of the parameters
* `receipt_hash` matches a recomputed hash over all receipt fields
* `tools_hash` matches a recomputed hash of the stored tool definitions (or null)

To validate a receipt. i.e., to check that all its hashes are internally consistent, switch the **Subcommand** field to `validate` and provide the path to a receipt JSON file saved locally on your device.

This would be either:

* A receipt you generated yourself
* or, a JSON file you create with the contents of someone else's receipt (e.g., by copying the JSON from someone else's receipt and saving it as a local file)

### Verifying a Receipt

Validation checks that a receipt is well-formed, but it *doesn't* prove the result is reproducible. To do that, use `verify`.

Switch the **Subcommand** to `verify` and paste the receipt path into the **Receipt Path** field, then press `r` to run.&#x20;

REE will re-execute the full inference pipeline described in the receipt using the same *model, prompt* and *parameters* and compare the output against what the receipt claims. If the outputs match, the receipt is verified.

{% hint style="success" %}
This is the check you'd use when someone sends you a receipt and you want to independently confirm the result on your own hardware.
{% endhint %}

#### Receipts and Thinking Mode

When `enable_thinking` is explicitly set on `InferenceSession.complete()`, it is recorded in `input.parameters.enable_thinking` and included in `parameters_hash`.&#x20;

Omitted (`None`) means the parameter is not stored.


# Supported Models

A list of models verified to work with REE.

## Verified-Compatible Models

The following models have been verified to work with REE. Any Hugging Face model compatible with the system *may* work, but this list represents models that have been explicitly tested.

If you have a specific model in mind that doesn't work with REE, you can reach out to the Gensyn team by creating an issue in the [GitHub repository](https://github.com/gensyn-ai/ree/issues) and we'll do our best to support it.

{% hint style="info" %}
Models above \~32B typically require pipeline parallelism to run.&#x20;

Use the `--n-partitions` flag to split the model across multiple GPUs. See [Pipeline Parallelism](https://docs.gensyn.ai/tech/ree/advanced-usage#pipeline-parallelism) for details.
{% endhint %}

### Tool-Calling Models

REE can run many Hugging Face models, but tool-call behavior depends on the selected model.

Tool definitions are passed through the tokenizer's chat template when using `InferenceSession.complete(messages=..., tools=...)`. Models with chat templates and tool/function-calling instruction tuning are more likely to emit useful structured tool-call output.

REE SDK support *does not make every supported model equally capable of using tools.* Test your selected model against your tool schemas before relying on it in an application workflow.

#### Thinking-Capable Models

`enable_thinking` (`v0.4.0`, SDK only) applies only when the model's tokenizer chat template accepts an `enable_thinking` parameter (for example, Qwen3). Other models ignore or do not support this toggle.

### Qwen

| Model                              | Parameters |
| ---------------------------------- | ---------- |
| `Qwen/Qwen2.5-72B-Instruct`        | 72B        |
| `Qwen/Qwen3-32B`                   | 32B        |
| `Qwen/Qwen3-8B`                    | 8B         |
| `Qwen/Qwen3-4B`                    | 4B         |
| `Qwen/Qwen3-1.7B`                  | 1.7B       |
| `Qwen/Qwen3-0.6B`                  | 0.6B       |
| `Qwen/Qwen2.5-32B-Instruct`        | 32B        |
| `Qwen/Qwen2.5-14B-Instruct`        | 14B        |
| `Qwen/Qwen2.5-7B-Instruct`         | 7B         |
| `Qwen/Qwen2.5-7B`                  | 7B         |
| `Qwen/Qwen2.5-3B-Instruct`         | 3B         |
| `Qwen/Qwen2.5-0.5B-Instruct`       | 0.5B       |
| `Qwen/Qwen2.5-0.5B`                | 0.5B       |
| `Qwen/Qwen2.5-Coder-7B-Instruct`   | 7B         |
| `Qwen/Qwen2.5-Coder-0.5B-Instruct` | 0.5B       |
| `Qwen/Qwen2-1.5B-Instruct`         | 1.5B       |

### Meta Llama

| Model                                 | Parameters |
| ------------------------------------- | ---------- |
| `meta-llama/Llama-3.1-8B-Instruct`    | 8B         |
| `meta-llama/Llama-3.1-8B`             | 8B         |
| `meta-llama/Meta-Llama-3-8B`          | 8B         |
| `meta-llama/Meta-Llama-3-8B-Instruct` | 8B         |
| `meta-llama/Llama-3.2-3B-Instruct`    | 3B         |
| `meta-llama/Llama-3.2-1B-Instruct`    | 1B         |
| `meta-llama/Llama-3.2-1B`             | 1B         |
| `meta-llama/Llama-3.1-70B-Instruct`   | 70B        |
| `meta-llama/Llama-3.3-70B-Instruct`   | 70B        |

### DeepSeek

| Model                                      | Parameters |
| ------------------------------------------ | ---------- |
| `deepseek-ai/DeepSeek-R1-Distill-Qwen-32B` | 32B        |

### Mistral

| Model                                | Parameters |
| ------------------------------------ | ---------- |
| `mistralai/Mistral-7B-Instruct-v0.2` | 7B         |

### Code Models

| Model                              | Parameters |
| ---------------------------------- | ---------- |
| `codellama/CodeLlama-7b-hf`        | 7B         |
| `bigcode/starcoder2-3b`            | 3B         |
| `Qwen/Qwen2.5-Coder-7B-Instruct`   | 7B         |
| `Qwen/Qwen2.5-Coder-0.5B-Instruct` | 0.5B       |

### Other Models

| Model                                | Provider     | Parameters |
| ------------------------------------ | ------------ | ---------- |
| `01-ai/Yi-1.5-6B-Chat`               | 01.AI        | 6B         |
| `llm-jp/llm-jp-3-3.7b-instruct`      | LLM-JP       | 3.7B       |
| `TinyLlama/TinyLlama-1.1B-Chat-v1.0` | TinyLlama    | 1.1B       |
| `HuggingFaceTB/SmolLM-1.7B-Instruct` | Hugging Face | 1.7B       |
| `allenai/OLMo-1B-hf`                 | Allen AI     | 1B         |
| `facebook/opt-125m`                  | Meta         | 125M       |
| `stabilityai/stablelm-2-1_6b`        | Stability AI | 1.6B       |

### Using an Unlisted Model

REE is not limited to the models above. Any Hugging Face model that is compatible with the ONNX export pipeline may work. To try an unlisted model, simply enter its Hugging Face model ID in the [**Model Name** field in the TUI](/tech/ree/using-the-tui) (e.g., `organization/model-name`) and run it.


# Examples

Short, practical recipes for the most common REE workflows.

## Common Workflow Examples

Try some of these ready-to-use TUI configurations for common workflows like test runs, production inference, prompt files, and more.

### Minimal: Test Model

Use a small test model to verify REE is working.&#x20;

{% hint style="info" %}
Note that test models have random weights and will produce nonsensical output. This is expected.
{% endhint %}

In the TUI, fill in the following parameters:

* **Model Name:** `hf-internal-testing/tiny-random-LlamaForCausalLM`
* **Prompt Text:** `Hello world`
* **Max New Tokens:** `24`
* Press `r` to run.

<figure><img src="/files/Rj2ScYvvEwWREIa2kfLN" alt=""><figcaption></figcaption></figure>

### Production: Reproducible Inference with a Real Model

* **Model Name:** `Qwen/Qwen3-0.6B`
* **Prompt Text:** `Explain quantum entanglement in simple terms.`
* **Max New Tokens:** `256`
* **Extra Args:** `--operation-set reproducible --temperature 0.7 --top-p 0.9`
* Press `r` to run.

<figure><img src="/files/BHvj0WsnMJoy4dwVMjEO" alt=""><figcaption></figcaption></figure>

### Using a Prompt File

Save your prompt to a .JSONL file:

```json
{"prompt": "What is 2 + 2? Show your reasoning step by step."}
```

In the TUI:

* **Model Name:** `Qwen/Qwen3-0.6B`
* **Prompt Text:** *(leave blank)*
* **Prompt File:** `/path/to/your/prompt.JSONL`
* **Max New Tokens:** `128`
* **Extra Args:**&#x20;

```bash
--operation-set reproducible
```

* Press `r` to run.

<figure><img src="/files/CO7YDP3LhWv6F4Xw0Hef" alt=""><figcaption></figcaption></figure>

### Short-Circuiting (Reasoning Models)

Short-circuiting forces the model to exit a generation phase early by injecting a specific token at a given step. This is useful for reasoning models (e.g., Qwen3) that have thinking/end-thinking phases, where you want to limit the token budget spent on "thinking."

Both `--short-circuit-length` and `--short-circuit-token` must be provided together in **Extra Args**.

* **Model Name:** `Qwen/Qwen3-14B`
* **Prompt Text:** `Solve this math problem.`
* **Max New Tokens:** `300`
* **Extra Args:**

```bash
--operation-set reproducible --short-circuit-length 100 --short-circuit-token 151668
```

* Press `r` to run.

<figure><img src="/files/BvM3rmQ1Go6hWP0I5Qbf" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
**`v0.4.0`:** To turn thinking off entirely (rather than truncating it), use `enable_thinking=False` on `InferenceSession.complete(messages=...)` in the SDK.&#x20;

Short-circuiting remains useful when you want a bounded thinking budget on CLI/TUI runs.
{% endhint %}

### Large Models with Pipeline Parallelism

Split a large model across multiple GPUs using pipeline parallelism. This is the mode to use for models above \~32B parameters.

* **Model Name:** `Qwen/Qwen2.5-72B-Instruct`
* **Prompt Text:** `Summarize the key ideas behind pipeline parallelism.`
* **Max New Tokens:** `256`
* **Partitions:** `4`
* **Extra Args:** `--operation-set reproducible`
* Press `r` to run.

{% hint style="info" %}
Set `Partitions` to match how many GPUs you want to split the model across.&#x20;

If driving REE from the CLI instead of the TUI, use `--n-partitions <N>`.
{% endhint %}

### SDK: Tool Definitions with `InferenceSession`

This example shows how to pass tool definitions into an SDK inference session. REE forwards the tool definitions to the model's chat template when the tokenizer supports one.

First prepare a task directory using the CLI or TUI. Then use that prepared task directory with `InferenceSession`:

```python
from pathlib import Path
from gensyn_sdk import InferenceSession

tools = [
    {
        "type": "function",
        "function": {
            "name": "calculator",
            "description": "Evaluate a simple arithmetic expression.",
            "parameters": {
                "type": "object",
                "properties": {
                    "expression": {"type": "string"}
                },
                "required": ["expression"]
            }
        }
    }
]

messages = [
    {"role": "system", "content": "Use tools when helpful."},
    {"role": "user", "content": "What is 243 * 17?"}
]

session = InferenceSession(
    task_dir=Path("/path/to/prepared/task-dir")
)

result = session.complete(
    messages=messages,
    tools=tools,
    max_new_tokens=256,
)

print(result.text)
print(result.receipt.tools_hash)
```

REE does not execute the calculator function or parse the model output into a tool-call object. For reproducibility, record the exact tool output that your application provides back to the model.

#### SDK: Disable Thinking (Qwen3)

Requires a prepared task directory (see [SDK Hello World](https://github.com/gensyn-ai/ree/tree/main/examples/sdk-hello-world) for the prepare & session pattern).

```python
from pathlib import Path
from gensyn_sdk import InferenceSession

session = InferenceSession(task_dir=Path("/path/to/prepared/task-dir"))

result = session.complete(
    messages=[{"role": "user", "content": "What is 2 + 2?"}], 
    enable_thinking=False, 
    max_new_tokens=128,
) 
print(result.text)
```

### Validating a Receipt

Validation ensures that a receipt remains internally consistent and that its hashes are untampered and uncorrupted, without requiring re-computation.

After a successful run, switch the TUI to validate mode:

* **Subcommand:** `validate`
* **Receipt Path:** Paste the path to your receipt JSON file (e.g., `~/.cache/gensyn/Qwen--Qwen3-0.6B/.../metadata/receipt_20260311_155048.json`)
* Press `r` to run.

<figure><img src="/files/OwZIlDpKH8maDNiqPyw5" alt=""><figcaption></figcaption></figure>

### Verifying a Receipt

Verification re-runs the entire inference pipeline and comparing the results with the receipt to ensure reproducibility.

To prove a receipt is reproducible by re-running the full inference pipeline:

* **Subcommand:** `verify`
* **Receipt Path:** Paste the path to the receipt JSON file
* Press `r` to run.&#x20;

REE will re-execute the computation and compare the output against the receipt. This is slower than `validate` since it runs the full pipeline, but it's the strongest proof that the result is reproducible.

<figure><img src="/files/CwAmCGVfq67pUF8VLhP4" alt=""><figcaption></figcaption></figure>

{% hint style="success" %}
Use `validate` for a quick integrity check or use `verify` when you need definitive proof.
{% endhint %}


# Advanced Usage & CLI Reference

Skip the TUI and work directly with the SDK CLI, pipeline stages, and container configuration.

## Advanced Usage, Configuations & CLI Commands

This section covers the internals of REE for power users, integrators, and anyone who wants to understand what happens under the hood or drive REE directly from the command line.

### CLI Reference

While the TUI is the recommended interface, REE can also be driven directly via the `gensyn-sdk` CLI inside the container, or via the `ree.sh` shell script included in the repository.

This is useful for scripting, CI pipelines, or when you need fine-grained control over the pipeline.

#### Global Flags

`--verbose` is a global flag and must appear **before** the subcommand:

```bash
gensyn-sdk --verbose run ...
```

| Flag        | Description                 |
| ----------- | --------------------------- |
| `--verbose` | Enable debug-level logging. |

#### Location Flags

Every command requires exactly one of the following (they are mutually exclusive):

| Flag                  | Description                                                                                                                            |
| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `--tasks-root <path>` | Root directory for tasks. The task directory is derived as `<tasks-root>/<sanitized-model-name>`. **This is the recommended default.** |
| `--task-dir <path>`   | Use this exact directory for inputs and outputs. Use when you want to pin artifacts to a specific path.                                |

{% hint style="info" %}
When using `--tasks-root`, the SDK auto-creates a subdirectory named after the model using path-safe characters. For example, `--tasks-root /tmp/tasks` with model `Qwen/Qwen3-0.6B` creates `/tmp/tasks/Qwen--Qwen3-0.6B/`.
{% endhint %}

#### Run (Subcommand)

Runs the full pipeline: **\[1]** prepare, **\[2]** generate, **\[3]** receipt and **\[4]** decode.

```bash
gensyn-sdk run-all \\
  --tasks-root <path> \\
  --model-name <huggingface-model-id> \\
  --prompt-text "Your prompt here" \\
  --operation-set {default,deterministic,reproducible}
```

1. **Required Flags:**

| Flag                               | Description                                             |
| ---------------------------------- | ------------------------------------------------------- |
| `--model-name` / `-m`              | Hugging Face model ID (e.g., `Qwen/Qwen3-0.6B`).        |
| `--prompt-text` or `--prompt-file` | The prompt to run. Mutually exclusive; one is required. |

{% hint style="info" %}
`--operation-set` is not a required flag. Instead, it defaults to `reproducible` mode. You would only use this flag if you wanted to switch to `deterministic` mode.
{% endhint %}

2. **Optional Flags:**

| Flag                     | Default | Description                                                                                                                                                               |
| ------------------------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--model-revision`       | `main`  | Specific Hugging Face model revision.                                                                                                                                     |
| `--max-new-tokens`       | `300`   | Maximum number of tokens to generate.                                                                                                                                     |
| `--cpu-only`             | `false` | Force CPU execution even if CUDA is available.                                                                                                                            |
| `--force-model-export`   | `false` | Re-export ONNX model even if one exists.                                                                                                                                  |
| `--disable-kv-cache`     | `false` | Disable KV cache.                                                                                                                                                         |
| `--short-circuit-length` | —       | Generation index at which to inject the short-circuit token.                                                                                                              |
| `--short-circuit-token`  | —       | Token ID to inject when short-circuiting.                                                                                                                                 |
| `--n-partitions`         | 1       | Number of pipeline partitions to split the model across. Enables running larger models that don't fit on a single GPU. See [Pipeline Parallelism.](#pipeline-parallelism) |

#### Validate (Subcommand)

Checks that a receipt is structurally valid by recomputing hashes and comparing them against the stored values. This does *not* re-run inference.

```bash
gensyn-sdk validate --receipt-path <path-to-receipt.json>
```

1. **Required flags:**

| Flag             | Description                                |
| ---------------- | ------------------------------------------ |
| `--receipt-path` | Path to the receipt JSON file to validate. |

{% hint style="info" %}
There aren't any location flags (`--tasks-root` / `--task-dir`) needed because `validate` only inspects the receipt file itself.
{% endhint %}

#### Verify (Subcommand)

Re-runs the full inference pipeline described in a receipt and compares the output against the receipt's claimed results. This is the strongest form of verification, as it is what proves the result is reproducible on your hardware.

```bash
gensyn-sdk verify \
  --receipt-path <path-to-receipt.json> \
  --tasks-root <path> \
  --cpu-only
```

1. **Required Flags:**

| Flag                           | Description                              |
| ------------------------------ | ---------------------------------------- |
| `--receipt-path`               | Path to the receipt JSON file to verify. |
| `--tasks-root` or `--task-dir` | Where to store re-execution artifacts.   |

2. **Optional Flags:**

| Flag         | Default | Description                              |
| ------------ | ------- | ---------------------------------------- |
| `--cpu-only` | `false` | Force CPU execution during verification. |

{% hint style="info" %}
`verify` needs both a receipt path (what to verify) and a location (where to put the re-run workspace). When using the TUI, `--tasks-root` is passed automatically.
{% endhint %}

#### Sampling Flags

These flags control the sampling behavior during generation.

In the **TUI**, they are passed via Extra Args. On the **CLI**, they are passed directly.

| Flag                             | Default  | Description                                 |
| -------------------------------- | -------- | ------------------------------------------- |
| `--do-sample` / `--no-do-sample` | Enabled  | Enable/disable stochastic sampling.         |
| `--temperature`                  | `1.0`    | Sampling temperature. Higher = more random. |
| `--top-k`                        | `50`     | Top-k sampling cutoff.                      |
| `--top-p`                        | `1.0`    | Nucleus sampling threshold.                 |
| `--min-p`                        | Disabled | Min-p sampling threshold.                   |
| `--repetition-penalty`           | `1.0`    | Repetition penalty multiplier.              |

#### Prompt Format (JSONL)

For CLI usage, prompts can be provided via `--prompt-file` using JSONL format. Each line must be either:

* A JSON string: `"What is 2 + 2?"`
* A JSON object with a `prompt` field: `{"prompt": "Explain deterministic inference in one sentence."}`

Here's an example `prompts.jsonl` file:

```json
"What is 2 + 2?"
{"prompt": "Explain deterministic inference in one sentence."}
```

### The Pipeline

Under the hood, REE's `run` command (whether triggered from the TUI or CLI) executes a four-stage pipeline: **\[1]** prepare, **\[2]** generate, **\[3]** receipt, and **\[4]** decode.

#### 1. Prepare

Downloads the model from Hugging Face, exports it to ONNX format, tokenizes the prompt, and writes a task configuration file. All artifacts are written to the task directory.

**Artifacts produced:**

* `model/model.onnx`: The exported ONNX model
* `model/tensors.binary`: Serialized model weights
* `config.json`: Task configuration (sampling settings, token limits, etc.)
* `prompt_tokens.parquet`: Tokenized prompt
* `metadata/prepare.json`: Prepare-stage metadata (model name, commit hash, config hash)

If `model/model.onnx` already exists in the task directory, prepare skips re-export and reuses it. Use `--force-model-export` to override this.

#### 2. Generate

Loads the prepared ONNX model, compiles it through the Gensyn Compiler (applying RepOp kernels if `--operation-set reproducible`), and runs the inference loop.

**Artifacts produced:**

* `output_tokens.parquet`: Generated token IDs
* `metadata/generate.json`: Generate-stage metadata (finish reasons, device info, operation set, seed)
* `compiled-artifacts-*`: Compiler output directories

#### 3. Receipt

Assembles a cryptographically hashed receipt from the prepare and generate metadata, config, and output tokens.

**Artifacts produced:**

* `metadata/receipt_<timestamp>.json`: Hashed receipt for full replication and verification.

#### 4. Decode

Reads `output_tokens.parquet`, decodes the token IDs back into text using the model's tokenizer, and prints the result.

#### Python SDK Sessions

REE comes packaged with  `InferenceSession`, a Python SDK abstraction for reusable inference.

```python
from pathlib import Path
from gensyn_sdk import InferenceSession, OperationSet

session = InferenceSession(
    task_dir=Path("/path/to/prepared/task-dir"),
    operation_set=OperationSet.REPRODUCIBLE,
    cpu_only=False,
    random_seed=12345,
)

result = session.complete(
    prompt="Explain reproducible inference in one sentence.",
    max_new_tokens=128,
)

print(result.text)
```

`InferenceSession` loads a prepared task directory and reuses model/session state across completions. It is useful for applications that need multiple completions without repeating setup and model-load work each time.

{% hint style="info" %}
Use `reset_reproducibility_state()` before a completion when that completion must be independently reproducible from its receipt.
{% endhint %}

#### Tool Call Definitions in SDK Sessions

`InferenceSession.complete()` accepts tool definitions when using chat-style `messages`:

```python
result = session.complete(
    messages=[
        {"role": "user", "content": "What is 243 * 17?"}
    ],
    tools=tools,
    max_new_tokens=256,
)
```

#### Python SDK Sessions

Methods used here are `complete(...)` and `reset_reproducibility_state()`.

This requies a *prepared* `task_dir` (from `prepare` / `run-all` / `prepare_task.run`).

```python
InferenceSession(
    task_dir: Path,
    operation_set: OperationSet = OperationSet.REPRODUCIBLE,
    cpu_only: bool = False,
    random_seed: int = 12345,
)
```

### Pipeline Parallelism

Models larger than a single GPU's memory can be split across multiple partitions using the `--n-partitions` flag. This unlocks models up to 72B parameters on suitable multi-GPU hosts while preserving bitwise-reproducible output.

{% hint style="warning" %}
`--n-partitions` requires multiple GPUs. On a single-GPU host, setting `--n-partitions` above `1` is expected to fail. You can leave it at its default, or omit the flag entirely.

The largest model you can run on a single GPU is bounded by that GPU's memory regardless of anything else. For a conceptual overview of how partitioning works, see [Pipeline Parallelism](https://docs.gensyn.ai/tech/ree/advanced-usage/internals#pipeline-parallelism).
{% endhint %}

`--n-partitions` is compatible with all three operation sets (`default`, `deterministic`, `reproducible`). Reproducibility guarantees are preserved across partition counts: the same model and prompt will produce bitwise-identical output whether run with `--n-partitions 1` or `--n-partitions 8`.

In the TUI, pass `--n-partitions <N>` via the *Extra Args* field. An example of this flag sequence (with parallelism enabled) would look like:

​`gensyn-sdk run-all \ --tasks-root /tmp/tasks \ --model-name Qwen/Qwen2.5-72B-Instruct \ --prompt-text "Explain pipeline parallelism." \ --n-partitions 4 ​`

### Persisting Data & Caching

The REE container mounts your host's `~/.cache` directory into the container automatically. This persists both Hugging Face model downloads (`~/.cache/huggingface`) and SDK artifacts like ONNX exports, compiled models, and receipts (`~/.cache/gensyn`).

This means subsequent runs of the same model will skip the download and export steps automatically. No additional volume mounts or configuration are needed.

{% hint style="info" %}
When using the TUI, this caching is handled for you. The details above apply if you're running the container directly via the CLI.
{% endhint %}

#### SDK Sessions

REE can be used through the CLI for one-shot `run`, `validate`, and `verify` workflows. The SDK also exposes `InferenceSession` for applications that need more control over the lifecycle of inference.

`InferenceSession` manages setup, execution, and teardown for a reusable inference workflow. Instead of starting from scratch for each generation, an application can keep a session alive and run multiple inference calls inside the same container instance.

This is particularly useful for application integrations, multi-turn workflows, and tool-call loops.

### Tool Calls

REE v0.3.0 adds basic support for tool-call workflows through the SDK.

A tool-call workflow has four parts:

1. The application defines the tools that are available to the model.
2. The model requests a tool call during inference.
3. The application executes the requested tool.
4. The application passes the tool result back into the inference session.

REE does not execute arbitrary external tools by itself. The host application is responsible for defining tools, enforcing permissions, executing tool calls, and recording tool results.

#### Tool-Calling Models

REE can execute many Hugging Face models, but tool-call behavior depends on the selected model.

Models that have been instruction-tuned for tool or function calling are more likely to emit valid structured tool-call requests. REE SDK support enables tool-call workflows, but it does not make every supported model equally capable of using tools.

{% hint style="info" %}
When building a tool-augmented application, choose a model that is known to follow tool schemas reliably and test that it emits valid tool calls for your use case.
{% endhint %}

#### Thinking Mode (`enable_thinking`)

`v0.4.0` adds `enable_thinking: Optional[bool] = None` to `InferenceSession.complete()`.

| Layer                                      | Supported? |
| ------------------------------------------ | ---------- |
| `InferenceSession.complete()`              | Yes        |
| `gensyn-sdk` CLI (`run-all`, `prepare`, …) | No         |
| TUI / `ree.sh` one-shot runs               | No         |

When set to `True` or `False`, the value is forwarded to `tokenizer.apply_chat_template(..., enable_thinking=...)` if the tokenizer supports it. When `None` (default), the `kwarg` is omitted. This is recorded in receipts as `input.parameters.enable_thinking` when explicitly set.

{% hint style="info" %}
Alternatively (for the CUI and TUI) use  `--short-circuit-length` and `--short-circuit-token` on `run-all` / `prepare`.
{% endhint %}

#### Reproducibility Considerations with Tools

REE can make model inference reproducible, but e*xternal tools are only reproducible if their inputs and outputs are captured and replayed.*

For example, a calculator tool is naturally easy to replay, but a web-search tool is not, because live search results and page contents can change over time.

Applications that need replayable tool-augmented inference should record:

* Tool name.
* Tool schema.
* Tool-call arguments.
* Tool output returned to the model.
* Timestamp.
* Provider or service metadata.
* Hashes of external data.
* Any fetched source content used to produce the tool result.

On replay, the application should provide the recorded tool output instead of calling the live external system again.

#### Limitations

Tool-call support does not make every model equally capable of using tools. The selected model must be able to emit useful structured tool-call requests.

Applications must also capture provenance and replay external data, because REE verifies only the model computation.

## EULA

Use of REE and its components (Gensyn SDK, Gensyn Compiler, RepOp kernels) is subject to the Gensyn End User License Agreement. [Please review the EULA before use.](https://github.com/gensyn-ai/ree/blob/main/REE-Binary-License)


# Internals

How the Gensyn Compiler and RepOp kernels achieve bitwise reproducibility under the hood.

### Gensyn Compiler

The Gensyn Compiler converts ONNX-serialized ML models into PyTorch modules, optionally with reproducible RepOp kernels replacing standard operations.&#x20;

It is an MLIR-based, multi-stage compiler with a Python execution layer.

#### How It Works

The compiler uses MLIR dialects to reason about the incoming model:

1. A dialect that determines which operations need to be lowered to RepOp kernels (rather than standard PyTorch kernels).
2. A dialect that generates the final PyTorch module from a given set of operations.

#### Python API

```python
from gensyn_mjolnir import convert, CompileOptions

# Convert an ONNX model to a PyTorch module with reproducible kernels
module = convert(
    "model/model.onnx",
    options=CompileOptions(requires_reproducibility=True)
)
```

#### Convert()

`convert()` is the core function of the Gensyn Compiler. It takes an ONNX model and converts it into a PyTorch module that can be used for inference.&#x20;

When `requires_reproducibility` is enabled (which it is by default), the compiler replaces standard PyTorch operations with RepOp kernels that guarantee bitwise-identical results across hardware.

It has two parameters:&#x20;

* `onnx_model_or_path`: A `str`, `Path` or `ModelProto` type. This is either a file path to an ONNX model on a disk or an in-memory `ModelProto` object.
* `options` (`CompileOptions`) is the configuration for the compilation process, which you can read more about below. It defaults to reproducible mode.

```python
def convert(
    onnx_model_or_path: str | Path | ModelProto,
    options: CompileOptions = CompileOptions(),
) -> torch.nn.Module
```

#### CompileOptions

`CompileOptions` controls how the compiler processes the model. In most cases the defaults are what you want, which corresponds to reproducible mode with symlinked tensors and a temporary artifacts directory.

The fields are:

* `artifacts_dir`: always `str` or `None`. This is the directory where the compiler writes intermediate artifacts. If not set, a temporary directory is used (preserved when the `MJOLNIR_DEBUG` environment variable is set, which is useful for inspecting compiler output during debugging).
* `colocate_tensors`: A `bool` that is `False` by default. When set to `True` it copies external tensor files into the artifacts directory. When `False`, it creates symbolic links instead.&#x20;

{% hint style="info" %}
Symlinking is faster and saves disk space, but copying may be needed if you plan to move the artifacts directory to another location.
{% endhint %}

* `requires_reproducibility`: Also a `bool` but set to `True` by default. When `True`, the compiler replaces standard PyTorch operations with RepOp kernels for cross-hardware reproducibility. When `False`, it uses standard PyTorch kernels which are faster but not reproducible across different hardware.

```python
@dataclass(frozen=True, slots=True, kw_only=True)
class CompileOptions:
    artifacts_dir: str | None = None
    # Directory for compiler artifacts. Uses a temp directory if not specified
    # (preserved when MJOLNIR_DEBUG env var is set).

    colocate_tensors: bool = False
    # When True, copies external tensor files into the artifacts directory.
    # When False, creates symbolic links instead.

    requires_reproducibility: bool = True
    # When True, compiles with RepOp kernels for cross-hardware reproducibility.
    # When False, uses standard PyTorch kernels.
```

### Inference Sessions

REE v0.3.0 introduces `InferenceSession`, an SDK abstraction for managing the lifecycle of an inference workflow.

An inference session is responsible for setup, execution, and teardown. This lets applications reuse session state across multiple inference calls within the same container instance instead of repeating setup steps for every generation.

This is useful for:

* Running multiple prompts against the same prepared environment.
* Building multi-turn inference workflows.
* Implementing tool-call loops where the model may request an external tool before producing a final answer.
* Avoiding repeated compiler initialization where session reuse is supported.

### RepOps

RepOps (Reproducible Operators) are purpose-built GPU kernels that guarantee bitwise-identical outputs regardless of hardware architecture. They cover the full set of operators needed for neural network inference and training.

For a standalone demo of RepOp kernels, see the [RepOps Demo repository](https://github.com/gensyn-ai/repops-demo).

#### How RepOps Achieve Cross-Hardware Reproducibility

* **Fixed reduction ordering:** Every kernel accumulates values in a single canonical order. The reduction tile size is fixed across all GPU architectures. All accumulation is in FP32 using fused multiply-add instructions.
* **Correctly rounded transcendentals:** Custom implementations of `exp`, `sin`, `tanh`, etc. that produce identical results on every CUDA-capable GPU.
* **Extended-precision arithmetic:** Operations like the error function (used in GELU) use extended-precision fixed-point arithmetic for cross-hardware consistency.
* **Architecture-adaptive output tiling:** Kernels adapt output tile dimensions to different GPU architectures (using available shared memory), but never change the reduction dimension, so reproducibility is preserved.

### Pipeline Parallelism

Large models often exceed the memory of a single GPU. Pipeline parallelism splits the model's layers into sequential *partitions* (also called stages), each placed on a different GPU.&#x20;

{% hint style="danger" %}
Pipeline Parallelism is only possible on multi-GPU devices. Using the flag to enable this mechanism on a single-GPU host will result in a failed run.
{% endhint %}

A forward pass walks the input through partition 1, then passes its activations to partition 2, and so on, with each GPU holding only its own slice of the weights. This trades a single large memory footprint for several smaller ones, making it possible to run models that would otherwise be impossible to load.

{% hint style="info" %}
Pipeline parallelism is orthogonal to the operation set. You can combine `--n-partitions` with `default`, `deterministic`, or `reproducible` mode. Only `reproducible` mode guarantees bitwise identity across different hardware.
{% endhint %}

REE exposes this through the `--n-partitions` flag, which controls how many partitions the model is divided into. On a host with enough aggregate GPU memory, this lets REE run models up to 72B parameters while preserving the reproducibility guarantees provided by [RepOps](#repops).&#x20;

Partition boundaries are deterministic for a given model and partition count, so splitting a model does not introduce new sources of numerical drift: the same `--n-partitions` value on different supported hardware produces bitwise-identical output, and cross-partition-count runs of the same model also match when using `--operation-set reproducible`.

### Container Details

| Property         | Value                     |
| ---------------- | ------------------------- |
| REE Image        | `gensynai/ree:v0.4.0`     |
| REE Version      | `0.4.0`                   |
| SDK Version      | `gensyn-sdk 0.1.0`        |
| Compiler Version | `gensyn-compiler 0.1.0`   |
| Base OS          | Ubuntu 24.04.1 LTS        |
| Python           | `3.11.15`                 |
| PyTorch          | `2.10.0`                  |
| Transformers     | `4.51.0`                  |
| ONNX             | `1.21.0`                  |
| Entrypoint       | `/runtime/bin/gensyn-sdk` |
| User             | `gensyn` (non-root)       |
| Working Dir      | `/home/gensyn`            |

#### Inference Sessions

`InferenceSession` is a stateful SDK wrapper that loads a prepared task directory once and can run multiple completions against it.

At initialization, the session reads prepare metadata, loads the tokenizer and generation config, configures the selected operation set, selects the device, and builds the inference backend. Calls to `complete()` reuse that state.

`InferenceSession.complete()` supports either a plain `prompt` or chat-style `messages`. Tool definitions can be supplied only with `messages`, and are forwarded into the tokenizer's chat template when supported.

### Interactive Mode

To explore REE's components directly (SDK, Compiler), start the container in interactive mode:

```bash
docker run -it --entrypoint bash -v ~/.cache:/home/gensyn/.cache gensynai/ree:v0.4.0
```

From inside the container, you can run `gensyn-sdk` commands directly and inspect intermediate artifacts.


# Troubleshooting

Common errors, their causes, and how to fix them.

## Common Errors

Quick fixes for Docker, CLI, and compilation issues you might hit while using REE.

| Error                                                          | Cause                                                                                                             | Fix                                                                                                                   |
| -------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
| `PermissionError: [Errno 13] Permission denied: '/gensyn'`     | Container runs as non-root `gensyn` user; can't write to root-owned paths                                         | Use `/tmp/` paths for ephemeral runs, or mount a volume with `-v`                                                     |
| `one of the arguments --tasks-root --task-dir is required`     | Missing required output directory argument                                                                        | Add `--task-dir /tmp/task` or `--tasks-root /tmp/tasks`                                                               |
| `one of the arguments --prompt-text --prompt-file is required` | Missing prompt input                                                                                              | Add `--prompt-text "your prompt"` or `--prompt-file path.jsonl`                                                       |
| `argument command: invalid choice: 'bash'`                     | Trying to launch a shell but entrypoint is locked to `gensyn-sdk`                                                 | Use `--entrypoint bash` to override: `docker run -it --entrypoint bash ree`                                           |
| Gibberish / nonsensical output                                 | Using `hf-internal-testing/tiny-random-LlamaForCausalLM` which has random untrained weights                       | Expected behavior for test models; use a real model for meaningful output                                             |
| Shell hangs after pasting command                              | Trailing `\\` on the last line of a command                                                                       | Remove the backslash from the final line                                                                              |
| `--n-partitions` run fails on a single-GPU machine             | Pipeline parallelism requires multiple GPUs; a partition count above `1` can't be satisfied with only one device. | Omit `--n-partitions` or set it to `1`. Single-GPU hosts can only run models that fit in one GPU's memory.            |
| `ValueError: 'tools' can only be provided with 'messages'.`    | Tool definitions were passed with a plain prompt string in `InferenceSession.complete()`.                         | Use `messages=[...]` instead of `prompt=...` when providing tools.                                                    |
| Tool definitions appear to be ignored                          | The selected tokenizer may not have a chat template, or the model may not be trained to use tools.                | Use a chat/instruct model with a tool-aware chat template and verify the model emits the expected tool-call format.   |
| No parsed tool call is returned                                | REE provides basic tool-definition support, not a full tool executor or agent loop.                               | Parse the model output in your application, execute tools yourself, and pass follow-up context back into the session. |

### **Tool-Call Workflows**

REE does not execute external tools. If a model emits tool-call-shaped output, your application must parse it, run the tool, and continue the conversation.

For reproducible workflows, record the exact tool output passed back to the model. Live APIs, web pages, databases, and search results may change between runs.

| Error                                                       | Cause                                                | Fix                                                                                       |
| ----------------------------------------------------------- | ---------------------------------------------------- | ----------------------------------------------------------------------------------------- |
| `ValueError: 'tools' can only be provided with 'messages'.` | `tools` passed with `prompt=`                        | Use `messages=[...]`                                                                      |
| No parsed tool call in SDK result                           | REE does not execute or return structured tool calls | Parse `result.text`, run tools in application code                                        |
| `enable_thinking` seems ignored                             | Plain `prompt` or unsupported tokenizer              | Use `messages` and a thinking-capable model such as `Qwen3`                               |
| Cannot set thinking on/off from TUI                         | `enable_thinking` is SDK-only                        | Use `InferenceSession.complete(..., enable_thinking=False)` or short-circuit flags on CLI |

### Compiler Trace Warnings

When running REE, you may see trace warnings and verbose compiler output in your terminal. These are expected and can be safely ignored. They originate from the ONNX export and MLIR compilation stages.

#### `--tasks-root` vs. `--task-dir`

If you see errors about missing artifacts, make sure you're using consistent location flags. When using `--tasks-root`, the task directory is automatically derived from the model name. When using `--task-dir`, you must point to the same directory across all operations.

### CUDA Not Available

If you're running on a machine with a GPU but REE doesn't detect it, ensure you're passing the `--gpus all` flag to Docker:

```bash
docker run --gpus all -v ~/.cache/gensyn:/gensyn ree run \\
  --tasks-root /gensyn/tasks \\
  --model-name <model> \\
  --prompt-text "..." \\
  --operation-set reproducible
```

{% hint style="info" %}
Use `--cpu-only` to explicitly force CPU execution when GPU is not available or not desired.
{% endhint %}

### Out-of-Memory (OOM) Issues

If you are using Docker Desktop, you may need to [adjust the memory limit.](https://docs.docker.com/desktop/settings-and-maintenance/settings/#advanced) Otherwise, you may attempt to run larger models (models with a higher parameter count) and encounter a failure during the model loading or checkpoint 'sharding' phase.

This typically shows up as a `run:failed` status with exit code 137, and the logs will show the process dying partway through *"Loading checkpoint shards."*

### NaN Errors & Crashes with Certain Models

Some FP16 models, particularly certain Qwen 2.5 Instruct variants, may produce NaN (Not a Number) errors and crash when run in `default` or `deterministic` mode. This is a numerical stability issue: attention score calculations can overflow the FP16 value range during inference.

If you encounter this, try switching to `reproducible` mode (`--operation-set reproducible`), which handles these edge cases more gracefully. Note that even in `reproducible` mode, some affected models *may still produce degraded output quality* (repetitive text or unexpected tokens).

{% hint style="info" %}
This is a known limitation related to the ONNX export pipeline's use of FP16 precision and is being actively addressed in future releases.
{% endhint %}


# Delphi SDK

TypeScript SDK for interacting with Delphi information markets on the Gensyn blockchain.

## Overview

This Delphi SDK provides a single `DelphiClient` interface for reading market data, executing trades, managing positions, and querying historical on-chain events.

### What it Does

The SDK has two core layers: the **\[1]** REST API client (for read operations) and the **\[2]** on-chain methods (for write operations).

1. **REST API client (*****reading)*****:** List and filter markets, query wallet positions, and check service health through Delphi's centralized API endpoints.
2. **On-chain methods (*****writing)*****:** Buy and sell outcome shares, approve token spending, redeem winning positions, and read contract state directly on the Gensyn blockchain via the Gateway contract.

{% hint style="info" %}
This is a **TypeScript** only SDK. There is no Python SDK at this time.
{% endhint %}

The `@gensyn-ai/gensyn-delphi-sdk` package is available on `npm`. It supports private key signing and Coinbase Developer Platform (CDP) Server Wallets.

The SDK supports testnet, mainnet, and `competition-testnet`. The competition network powers the agent trading competition.

#### Market Deployments

Testnet and mainnet use automated-settlement gateways by default. Some legacy markets remain on the earlier deployment.

The client resolves a market's owning gateway before each market-scoped operation. This includes trades, quotes, redemptions, and liquidations. See [On-Chain Methods](/tech/delphi-sdk/methods) for routing details.

Delphi app markets use Dynamic Parimutuel (DPM) pricing. Automated settlement changes settlement and routing. It does not change Delphi markets to LMSR.

`competition-testnet` is separate. Its agent-competition markets use LMSR contracts with the same SDK trading interfaces.

{% hint style="warning" %}
Setting `gatewayAddress` or `DELPHI_GATEWAY_CONTRACT` pins all calls to that gateway. It disables automatic routing.
{% endhint %}

#### Upgrading to 2.0.0

Automated settlement changes gateway addresses and market routing. Statuses now include `failed`, which requires liquidation rather than redemption.

{% hint style="info" %}
Default subgraphs now index automated-settlement events.
{% endhint %}

### Who it's For

The Delphi SDK is the foundational layer for any programmatic interaction with [Delphi](https://app.delphi.fyi/) markets. It is used directly by developers building custom integrations, and it powers the [Agentic Trading toolkit](/tech/agentic-trading) under the hood.


# Configuration

Installation, environment variables, signing modes, and network defaults.

## Installation

You can use `npm` to install this SDK.

```bash
npm install @gensyn-ai/gensyn-delphi-sdk
```

{% embed url="<https://github.com/gensyn-ai/gensyn-delphi-sdk.git>" %}

### Generating an API Key

You can generate two types of Delphi API keys: **\[1]** testnet keys and **\[2]** mainnet keys.

* [Delphi API Key Generator (Testnet)](https://delphi-api-access.gensyn.ai/)
* [Delphi API Key Generator (Mainnet)](https://api-access.delphi.fyi/)

`competition-testnet` shares the testnet API deployment, so you'll use a testnet API key.

### Client Initialization

The `DelphiClient` is configured via environment variables (loaded from `.env` automatically) or by passing a config object to the constructor.

Constructor options take precedence over env vars:

```typescript
import { DelphiClient } from "@gensyn-ai/gensyn-delphi-sdk";

// Option 1: Environment variables (recommended)
const client = new DelphiClient();

// Option 2: Explicit config (overrides env vars)
const client = new DelphiClient({
  network: "testnet",
  signerType: "private_key",
  privateKey: "0xYourPrivateKey",
  apiKey: "your-api-key",
});
```

### Environment Variables

There are several core settings set by `env` vars.

#### Core Settings

| Variable                         | Description                                                                                     | Default             |
| -------------------------------- | ----------------------------------------------------------------------------------------------- | ------------------- |
| `DELPHI_NETWORK`                 | Network to use: `testnet`, `mainnet`, or `competition-testnet`                                  | `testnet`           |
| `DELPHI_SIGNER_TYPE`             | Signing method: `cdp_server_wallet` or `private_key`                                            | `cdp_server_wallet` |
| `DELPHI_API_ACCESS_KEY`          | REST API key (required for API methods)                                                         | —                   |
| `DELPHI_API_BASE_URL`            | Override the REST API base URL                                                                  | (network default)   |
| `DELPHI_APP_URL`                 | Delphi web app base URL, used to build `marketUrl`                                              | (network default)   |
| `DELPHI_GATEWAY_CONTRACT`        | Pin every call to this Gateway and disable routing                                              | (network default)   |
| `DELPHI_LEGACY_GATEWAY_CONTRACT` | Override the legacy Gateway address                                                             | (network default)   |
| `DELPHI_FACTORY_CONTRACT`        | Override the automated-settlement Factory address                                               | (network default)   |
| `DELPHI_LEGACY_FACTORY_CONTRACT` | Override the legacy Factory address                                                             | (network default)   |
| `DELPHI_TOKEN_ADDRESS`           | Override the collateral token address: $TEST on testnet, USDC on mainnet, or TST on competition | (network default)   |
| `DELPHI_SUBGRAPH_URL`            | Override the Goldsky subgraph endpoint                                                          | (network default)   |
| `GENSYN_RPC_URL`                 | Override the JSON-RPC endpoint                                                                  | (network default)   |
| `GENSYN_CHAIN_ID`                | Override the chain ID                                                                           | (network default)   |

#### Private Key Signing

For development use with `DELPHI_SIGNER_TYPE=private_key`:

| Variable             | Description                       |
| -------------------- | --------------------------------- |
| `WALLET_PRIVATE_KEY` | Hex-encoded private key (`0x...`) |

#### CDP Server Wallet Signing

For production use with `DELPHI_SIGNER_TYPE=cdp_server_wallet` (default):

| Variable             | Description                                  |
| -------------------- | -------------------------------------------- |
| `CDP_API_KEY_ID`     | Coinbase Developer Platform API key ID       |
| `CDP_API_KEY_SECRET` | Coinbase Developer Platform API key secret   |
| `CDP_WALLET_SECRET`  | CDP Server Wallet secret                     |
| `CDP_WALLET_ADDRESS` | On-chain address of the CDP wallet (`0x...`) |

{% hint style="info" %}
`@coinbase/cdp-sdk` is a peer dependency only required when using CDP signing. Private key users do not need it installed.
{% endhint %}

#### Network Defaults

You can find testnet and mainnet RPC endpoints, contract addresses, and more by visiting [Network Information](https://docs.gensyn.network/network-information) on the [Gensyn Foundation](https://docs.gensyn.network/) docs.

|                                | Testnet                                                                                                                            | Mainnet                                                                                                                            | Competition testnet                                                                                                                  |
| ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| Chain ID                       | `685685`                                                                                                                           | `685689`                                                                                                                           | `685685`                                                                                                                             |
| RPC URL                        | `https://gensyn-testnet.g.alchemy.com/public`                                                                                      | `https://gensyn-mainnet.g.alchemy.com/public`                                                                                      | `https://gensyn-testnet.g.alchemy.com/public`                                                                                        |
| Gateway (automated settlement) | `0x22ea355D7218Dc86b4c83732cBbd01f7Ff2332b3`                                                                                       | `0x982a67aE92D8de361957249fB2BB4a62BCc6A8d5`                                                                                       | `0x097599c9D966fF496284b892A8F13BF885b258ef`                                                                                         |
| Factory (automated settlement) | `0x97d2b3F0614C8189343A38094629FCE2910b727A`                                                                                       | `0x9C73417f79a1361c6aF9Bd828343badEE1b84936`                                                                                       | `0xEa9D0a78d0209916e88e363B8FDa3e23206Ff49b`                                                                                         |
| Gateway (legacy)               | `0x7b8FDBD187B0Be5e30e48B1995df574A62667147`                                                                                       | `0x4e4e85c52E0F414cc67eE88d0C649Ec81698d700`                                                                                       | —                                                                                                                                    |
| Factory (legacy)               | `0xd03CEC55802f0D44D844384E1144B25717315E5A`                                                                                       | `0x4596d847eA56DCf9A37944c13793Af802Fc5D1eC`                                                                                       | —                                                                                                                                    |
| Collateral token               | `0x0724D6079b986F8e44bDafB8a09B60C0bd6A45a1` ($TEST)                                                                               | `0x5b32c997211621d55a89Cc5abAF1cC21F3A6ddF5` (USDC)                                                                                | `0x8A2d75753362Eb5D5669a2c22cbf394b26a0571F` (TST)                                                                                   |
| API URL                        | `https://delphi-api.gensyn.ai/`                                                                                                    | `https://api.delphi.fyi/`                                                                                                          | `https://delphi-api.gensyn.ai/`                                                                                                      |
| Subgraph URL                   | [Goldsky endpoint](https://api.goldsky.com/api/public/project_cmnoqdag1obop01z3efnu8ssq/subgraphs/delphi-testnet-autoset/1.0.0/gn) | [Goldsky endpoint](https://api.goldsky.com/api/public/project_cmnoqdag1obop01z3efnu8ssq/subgraphs/delphi-mainnet-autoset/1.0.0/gn) | [Goldsky endpoint](https://api.goldsky.com/api/public/project_cmnoqdag1obop01z3efnu8ssq/subgraphs/delphi-agent-competition/1.0.0/gn) |
| App URL                        | `https://testnet.delphi.fyi`                                                                                                       | `https://app.delphi.fyi`                                                                                                           | `https://agent-competition.gensyn.ai`                                                                                                |

The default addresses target automated-settlement contracts. Configure the gateway and factory overrides when you need a specific deployment.

### Gateway Routing

For each market-scoped call, the client checks both factories with `marketProxiesExist`. It caches the result and routes to the owning gateway.

Use `resolveGateway(marketAddress)` when making direct contract calls. A configured `gatewayAddress` or `DELPHI_GATEWAY_CONTRACT` pins calls and bypasses this lookup.

### Competition Network

`competition-testnet` uses the Gensyn testnet chain and competition-specific LMSR contracts. [Delphi](https://app.delphi.fyi/) app markets on testnet and mainnet continue to use DPM.

It has no legacy deployment, so routing is a no-op.

The client automatically sends `X-Delphi-Mode: competition` with REST requests. Reads default to the active competition. You can pass `competitionId` to select another competition.

{% hint style="warning" %}
Use TST as collateral. Testnet uses $TEST and mainnet uses USDC.
{% endhint %}

### Signing Modes

Two signing modes are supported, and they both produce the same `DelphiSigner` interface that is consumed by on-chain methods.

#### Private Key (for development)

```
DELPHI_SIGNER_TYPE=private_key
WALLET_PRIVATE_KEY=0x<hex-private-key>
```

Or you can create a signer directly:

```typescript
import { createPrivateKeySigner } from "@gensyn-ai/gensyn-delphi-sdk";

const signer = await createPrivateKeySigner({
  privateKey: "0xYourPrivateKey",
  rpcUrl: "https://gensyn-testnet.g.alchemy.com/public",
  chainId: 685685,
});
```

#### CDP Server Wallet (for production)

```bash
DELPHI_SIGNER_TYPE=cdp_server_wallet
CDP_API_KEY_ID=<key-id>
CDP_API_KEY_SECRET=<key-secret>
CDP_WALLET_SECRET=<wallet-secret>
CDP_WALLET_ADDRESS=0x<wallet-address>
```

To get your CDP credentials, create an account at [Coinbase Developer Platform](https://portal.cdp.coinbase.com/), generate an API key, and set up a server wallet. See the [CDP Server Wallet documentation](https://docs.cdp.coinbase.com/server-wallets/v2/introduction/welcome) for a full walkthrough. Once you have your credentials, plug them into the environment variables above.

You can also create this directly:

```typescript
import { createCdpSigner } from "@gensyn-ai/gensyn-delphi-sdk";

const signer = await createCdpSigner({
  apiKeyId: "your-cdp-api-key-id",
  apiKeySecret: "your-cdp-api-key-secret",
  walletSecret: "your-cdp-wallet-secret",
  walletAddress: "0xYourWalletAddress",
  rpcUrl: "https://gensyn-testnet.g.alchemy.com/public",
  chainId: 685685,
});
```

CDP Server Wallets are managed by [Coinbase Developer Platform.](https://www.coinbase.com/developer-platform) The SDK uses `@coinbase/cdp-sdk` under the hood.

### Accessing the Signer Directly

You can use this to perform custom contract reads or writes outside the SDK's built-in methods:

```typescript
const { address, publicClient, walletClient } = await client.getSigner();
```


# API Reference

REST API methods for listing markets, fetching market details, and querying wallet positions.

## Overview

All REST API methods read data from the Delphi API and require `DELPHI_API_ACCESS_KEY` to be set (except `health()`).

### health()

Check service availability. Does not require authentication.

```typescript
const { status } = await client.health();
```

### Markets

#### listMarkets(*params*)

Retrieve markets with optional filtering and pagination using `listMarkets`.

```typescript
const { markets } = await client.listMarkets({
  status: "open",
  category: "crypto",
  orderBy: "liquidity",    // "liquidity" | "created" | "settles_at"
  verifiable: true,
  skip: 0,
  limit: 50,
});
```

#### **Parameters**

| Field                           | Type           | Default            | Description                                                                     |
| ------------------------------- | -------------- | ------------------ | ------------------------------------------------------------------------------- |
| `skip`                          | `number`       | `0`                | Pagination offset                                                               |
| `limit`                         | `number`       | `50`               | Maximum records returned                                                        |
| `status`                        | `MarketStatus` | —                  | `"open"` \| `"awaiting_settlement"` \| `"settled"` \| `"expired"` \| `"failed"` |
| `category`                      | `string`       | —                  | Filter by metadata category                                                     |
| `orderBy`                       | `string`       | `liquidity`        | `liquidity`, `created`, or `settles_at`                                         |
| `competitionId`                 | `string`       | Active competition | Competition to query                                                            |
| `verifiable`                    | `boolean`      | —                  | Filter by verifiable settlement                                                 |
| `pricesAndImpliedProbabilities` | `boolean`      | —                  | Include prices and implied probabilities                                        |

#### getMarket(*params*)

Retrieve a single market by ID.

```typescript
const market = await client.getMarket({
  id: "0xMarketContractAddress",
  competitionId: "optional-competition-id",
});
```

{% hint style="info" %}
This returns the same `Market` type. The `id` comes from `listMarkets`.
{% endhint %}

#### Market Type

```typescript
export interface Market {
  id: string; // On-chain contract address of the market proxy
  appMarketId: string; // UUID identifying the market in the Delphi app UI
  marketUrl: string; // Direct link to the market on the Delphi app
  status: MarketStatus; // "open" | "awaiting_settlement" | "settled" | "expired" | "failed"
  category: string; // Market category, e.g. "crypto", "sports", "politics"
  deployer: string; // Wallet address that deployed/created the market
  implementation: string; // Market implementation contract address
  metadataUri: string; // URI pointing to the market metadata
  metadataUriContentHash: string; // Content hash for the metadata URI
  metadata: unknown; // Parsed market metadata returned by the API
  dataSources: unknown; // Data sources used for market resolution/verification
  createdAt: string; // ISO timestamp when the market was created
  fetchedAt: string | null; // ISO timestamp when metadata was last fetched, or null
  fetchResponseStatus: string | null; // Status from the metadata fetch attempt, or null
  resolvesAt: string | null; // ISO timestamp when the market is expected to resolve, or null
  settledAt: string | null; // ISO timestamp when the market was settled, or null
  settlesAt: string | null; // ISO timestamp for scheduled settlement, or null
  winningOutcomeIdx: string | null; // Winning outcome index after settlement, or null
  tradingFee: string | null; // Trading fee value returned by the API, or null
  proof: string | null; // Resolution proof or verification reference, or null
  error: string | null; // Error message related to market metadata/resolution, or null
  verifiable: boolean; // Whether the market has verifiable settlement enabled
}
```

#### Metadata Shape

```typescript
const meta = market.metadata as {
  question?: string;            // The market question
  title?: string;               // Alternative title
  description?: string;
  category?: string;
  outcomes?: string[];          // Outcome labels — index matches outcomeIdx
  resolutionCriteria?: string;
  endDate?: string;             // ISO date
} | null;
```

{% hint style="danger" %}
The `outcomes` array is critical for labelling: `outcomes[0]` is the label for `outcomeIdx: 0`.
{% endhint %}

The key address fields here are:

| Field                   | Purpose                                                           |
| ----------------------- | ----------------------------------------------------------------- |
| `market.id`             | Pass to `getMarket({ id })`                                       |
| `market.id`             | Pass as `marketAddress` to SDK trading, quote, and approval calls |
| `market.implementation` | Implementation contract address; do not use as `marketAddress`    |

### Market Status Values

```typescript
type MarketStatus =
  | "open"
  | "awaiting_settlement"
  | "settled"
  | "expired"
  | "failed";
```

| Status                | Meaning                                                  |
| --------------------- | -------------------------------------------------------- |
| `open`                | Trading active                                           |
| `awaiting_settlement` | Trading deadline passed, awaiting settlement             |
| `settled`             | Winning outcome set; positions redeemable                |
| `expired`             | Market expired without settlement; liquidate positions   |
| `failed`              | Oracle could not resolve the market; liquidate positions |

{% hint style="info" %}
The API returns these as *strings*.

The underlying contract exposes an `int enum`: 0 = open, 1 = awaiting settlement, 2 = settled, 3 = expired, and 4 = failed.
{% endhint %}

A winning outcome is set by the oracle on automated-settlement markets. Legacy markets use the creator's winner submission.

### Usage Patterns

You can paginate through all markets like this:

```typescript
let skip = 0;
const limit = 50;
const all: Market[] = [];

while (true) {
  const { markets } = await client.listMarkets({ status: "open", skip, limit });
  if (!markets || markets.length === 0) break;
  all.push(...markets);
  if (markets.length < limit) break;
  skip += limit;
}
```

Or, find a market using a question keyword:

```typescript
const { markets } = await client.listMarkets({ status: "open", limit: 100 });
const match = markets?.find(m => {
  const meta = m.metadata as { question?: string } | null;
  return meta?.question?.toLowerCase().includes("keyword");
});
```

### Positions

#### listPositions(*params*)

Retrieve positions for a wallet address.

```typescript
const { positions } = await client.listPositions({
  wallet: "0xYourWalletAddress",
  redeemedOrLiquidated: false,
  skip: 0,
  limit: 50,
});
```

#### Position Type

```typescript
interface Position {
  id: string;
  marketProxy: string;      // Market proxy address (use as marketAddress)
  wallet: string;
  outcomeIdx: string;       // Outcome index as string — parse with parseInt()
  shares: string;           // 18-decimal bigint as string — parse with BigInt()
  redeemedOrLiquidated: boolean;
  tokensRedeemed: string;   // Collateral amount as a 6-decimal bigint string
  marketStatus: "open" | "awaiting_settlement" | "settled" | "expired" | "failed";
}
```

Be careful when parsing, because `shares` and `tokensRedeemed` are *string representations* of [bigints](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-2.html#bigint).

```typescript
const shares = Number(BigInt(position.shares)) / 1e18;
const tokensRedeemed = Number(BigInt(position.tokensRedeemed)) / 1e6;
const outcomeIdx = parseInt(position.outcomeIdx);
```

### Redemption

Markets must be `settled` (winner submitted) before redeeming. Only holders of the winning outcome receive tokens.

{% hint style="warning" %}
`expired` and `failed` markets have no winning outcome. Use `liquidate()` rather than `redeemMarket()` for these positions.
{% endhint %}

{% hint style="warning" %}
Positions with `shares === "0"` cannot be redeemed or liquidated because the wallet holds no stake.

The positions API may return zero-share entries for markets the wallet previously participated in but fully exited. Always check `BigInt(position.shares) > 0n` before attempting redeem or liquidate calls.
{% endhint %}

#### 1. Single (Market) Redemption

```typescript
const { transactionHash, sharesIn, tokensOut } = await client.redeemMarket({
  marketAddress: "0x..." as `0x${string}`,
});
console.log(`Redeemed ${Number(sharesIn) / 1e18} shares → ${Number(tokensOut) / 1e6} collateral tokens`);
```

#### 2. Batch (Market) Redemption

```typescript
const { results, totalTokensOut } = await client.redeemPositions({
  marketAddresses: ["0x...", "0x..."],
});

for (const r of results) {
  if (r.success) {
    console.log(`${r.marketAddress}: ${Number(r.tokensOut!) / 1e6} collateral tokens`);
  } else {
    console.error(`${r.marketAddress}: ${r.error}`);
  }
}
console.log(`Total redeemed: ${Number(totalTokensOut) / 1e6} collateral tokens
`);
```

#### 3. Batch-Redeeming all Unredeemed, Settled Positions

```typescript
const { positions } = await client.listPositions({
  wallet: myAddress,
  redeemedOrLiquidated: false,
});

const settledProxies: `0x${string}`[] = [];
for (const p of positions ?? []) {
  if (BigInt(p.shares) === 0n) continue;
  const market = await client.getMarket({ id: p.marketProxy });
  if (market.status === "settled") {
    settledProxies.push(p.marketProxy as `0x${string}`);
  }
}

if (settledProxies.length > 0) {
  const { results, totalTokensOut } = await client.redeemPositions({
    marketAddresses: settledProxies,
  });
}
```

#### 4. Liquidating Expired or Failed Positions

`getMarketStatus()` reads the current on-chain status. Use it when REST data may be stale.

```typescript
import { LIQUIDATABLE_MARKET_STATUSES } from "@gensyn-ai/gensyn-delphi-sdk";

for (const p of positions ?? []) {
  if (BigInt(p.shares) === 0n) continue;

  const marketAddress = p.marketProxy as `0x${string}`;
  const status = await client.getMarketStatus(marketAddress);
  if (!LIQUIDATABLE_MARKET_STATUSES.includes(status)) continue;

  await client.liquidate({
    marketAddress,
    outcomeIndices: [0, 1], // Binary market; include every outcome index.
  });
}
```

#### Estimating Portfolio Value

Estimate the current liquidation value of all active positions:

```typescript
const { positions } = await client.listPositions({
  wallet: myAddress,
  redeemedOrLiquidated: false,
});

let totalValue = 0;
for (const p of positions ?? []) {
  const shares = BigInt(p.shares);
  if (shares === 0n) continue;

  const marketAddress = p.marketProxy as `0x${string}`;
  const outcomeIdx = parseInt(p.outcomeIdx);

  try {
    const { tokensOut } = await client.quoteSell({
      marketAddress, outcomeIdx, sharesIn: shares,
    });
    totalValue += Number(tokensOut) / 1e6;
  } catch {
    console.log(`${marketAddress} outcome ${outcomeIdx}: cannot quote (market may be closed)`);
  }
}
console.log(`Total estimated value: ${totalValue.toFixed(4)} collateral tokens`);
```


# On-Chain Methods

Trading, quoting, token approvals, and direct Gateway contract interaction via RPC.

## Overview

On-chain methods send transactions or read directly from the Gensyn blockchain via a Gateway contract.

### Market Deployments & Routing

Testnet and mainnet have automated-settlement and legacy deployments. Each market belongs to one of those deployments.

The client checks both factories with `marketProxiesExist`. It caches the result, then routes market-scoped calls to the owning gateway. This applies to buys, sells, quotes, redemptions, and liquidations.

Use `resolveGateway()` before making direct Gateway calls:

```typescript
const gateway = await client.resolveGateway(marketAddress);
```

Setting `gatewayAddress` or `DELPHI_GATEWAY_CONTRACT` pins every call. Pinning disables automatic routing. If you incorrectly pin a gateway, you can revert with `MarketProxyNotDeployedByFactory`.

### Contract Addresses

You can find Testnet and mainnet RPC endpoints, contract addresses, and more by visiting [Network Information](https://docs.gensyn.network/network-information) on the Gensyn Foundation docs.

### Trading

#### Pricing Mechanism (DPM)

Delphi app markets on testnet and mainnet use *Dynamic Parimutuel (DPM)* markets. This means:

* Prices shift continuously with every trade (no fixed order book)
* `spotImpliedProbability` reflects the market's current consensus probability
* For a binary market: `prob[0] + prob[1] = 1e18` (100%)
* A spot price of 0.65 collateral tokens per share means \~65% implied probability

{% hint style="info" %}
`competition-testnet` is separate from the Delphi app deployments. Its agent-competition markets use LMSR contracts. The SDK exposes the same market-scoped trading interfaces across both mechanisms.
{% endhint %}

### Quoting Trades

These are read-only and therefore do not consume any *gas.*

#### quoteBuy

The cost to receive an exact number of shares.

```typescript
const { tokensIn } = await client.quoteBuy({
  marketAddress: "0x..." as `0x${string}`,
  outcomeIdx: 0,
  sharesOut: BigInt(Math.round(10 * 1e18)),
});
const costUsdc = Number(tokensIn) / 1e6;
```

#### quoteSell

The payout for selling an exact number of shares.

```typescript
const { tokensOut } = await client.quoteSell({
  marketAddress: "0x..." as `0x${string}`,
  outcomeIdx: 0,
  sharesIn: BigInt(Math.round(5 * 1e18)),
});
const payoutUsdc = Number(tokensOut) / 1e6;
```

#### quoteRedeem and quoteLiquidate

`quoteRedeem()` estimates redemption for a settled market. `quoteLiquidate()` estimates exit value for an expired or failed market.

Use `redeemMarket()` only after settlement. Use `liquidate()` for `expired` and `failed` markets.

### Buying Shares

Token approval must exist before buying. The full flow with approval and slippage looks like this:

```typescript
const marketAddress = "0x..." as `0x${string}`;
const outcomeIdx = 0;
const sharesOut = BigInt(Math.round(10 * 1e18));

// 1. Quote the cost
const { tokensIn } = await client.quoteBuy({ marketAddress, outcomeIdx, sharesOut });

// 2. Ensure collateral-token approval (no-op if already approved)
await client.ensureTokenApproval({ marketAddress, minimumAmount: tokensIn });

// 3. Execute with 2% slippage
const maxTokensIn = tokensIn * 102n / 100n;
const { transactionHash } = await client.buyShares({
  marketAddress,
  outcomeIdx,
  sharesOut,
  maxTokensIn,
});
```

#### BuyShares (*params*)

| Field           | Type                | Description                                          |
| --------------- | ------------------- | ---------------------------------------------------- |
| `marketAddress` | `` `0x${string}` `` | Market proxy address                                 |
| `outcomeIdx`    | `number`            | Outcome index to buy                                 |
| `sharesOut`     | `bigint`            | Exact shares to receive (18 decimals)                |
| `maxTokensIn`   | `bigint`            | Maximum collateral spend — slippage cap (6 decimals) |

### Selling Shares

```typescript
const sharesIn = BigInt(Math.round(5 * 1e18));
const { tokensOut } = await client.quoteSell({ marketAddress, outcomeIdx, sharesIn });

const minTokensOut = tokensOut * 98n / 100n; // 2% slippage
const { transactionHash } = await client.sellShares({
  marketAddress,
  outcomeIdx,
  sharesIn,
  minTokensOut,
});
```

#### SellShares (*params*)

| Field           | Type                | Description                                               |
| --------------- | ------------------- | --------------------------------------------------------- |
| `marketAddress` | `` `0x${string}` `` | Market proxy address                                      |
| `outcomeIdx`    | `number`            | Outcome index to sell                                     |
| `sharesIn`      | `bigint`            | Exact shares to sell (18 decimals)                        |
| `minTokensOut`  | `bigint`            | Minimum collateral received — slippage floor (6 decimals) |

### Liquidating Positions

Liquidation exits positions without a winning outcome. It applies to expired and failed markets.

```typescript
const status = await client.getMarketStatus(marketAddress);
if (status === "expired" || status === "failed") {
  const { transactionHash } = await client.liquidate({
    marketAddress,
    outcomeIndices: [0, 1], // Covers a binary market.
  });
}
```

#### liquidate(*params*)

| Field            | Type                | Description           |
| ---------------- | ------------------- | --------------------- |
| `marketAddress`  | `` `0x${string}` `` | Market proxy address  |
| `outcomeIndices` | `number[]`          | Outcomes to liquidate |

Pass every outcome index where you hold shares. Omitted indices are not liquidated, and their funds remain locked. `[0, 1]` covers a binary market.

#### getMarketStatus(marketAddress)

Reads a market's lifecycle status from the owning gateway. This value is fresher than the REST API.

```typescript
const status = await client.getMarketStatus(marketAddress);
// "open" | "awaiting_settlement" | "settled" | "expired" | "failed"
```

### Slippage Guidelines

| Scenario                 | Recommended slippage |
| ------------------------ | -------------------- |
| Quiet market             | 1–2%                 |
| Active market            | 2–5%                 |
| Large trade (>$100)      | 5–10%                |
| Time-sensitive execution | 5%                   |

Here's an example of using integer arithmetic to avoid floating point:

```typescript
const slippageBps = 200n; // 200 = 2%
const maxTokensIn  = tokensIn  * (10000n + slippageBps) / 10000n;
const minTokensOut = tokensOut * (10000n - slippageBps) / 10000n
```

#### Common Contract Errors

| Error                             | Cause                           | Fix                                               |
| --------------------------------- | ------------------------------- | ------------------------------------------------- |
| `TokensInExceedsMax`              | Actual cost > maxTokensIn       | Re-quote and increase slippage                    |
| `TokensOutBelowMin`               | Actual payout < minTokensOut    | Re-quote and increase slippage                    |
| `MarketNotOpen`                   | Market closed or settled        | Cannot trade; check status                        |
| `SharesInExceedSupply`            | Selling more than held          | Query balance first                               |
| `GrossTokensOutNotPositive`       | Nothing to sell                 | Position is empty                                 |
| `ZeroTokensIn`                    | sharesOut too small             | Use a larger share amount                         |
| `MarketProxyNotDeployedByFactory` | Gateway does not own the market | Resolve the gateway or remove the pinned override |

### Token Approvals

#### getTokenAllowance(*params*)

Read the current ERC-20 allowance your wallet has granted to a market.

```typescript
const { allowance } = await client.getTokenAllowance({
  marketAddress: "0xMarket",
});
```

#### approveToken(*params*)

Approve the ERC-20 token for spending by a market.

{% hint style="info" %}
This defaults to unlimited (`uint256` max).
{% endhint %}

```typescript
// Approve unlimited
await client.approveToken({ marketAddress });

// Approve exact amount (e.g. 100 tokens; $TEST on testnet)
await client.approveToken({ marketAddress, amount: 100_000_000n });
```

#### ensureTokenApproval(*params*)

Check if sufficient allowance exists and only sends an approval transaction if needed. *Recommended before buying shares.*

```typescript
const { approvalNeeded, allowance, transactionHash } = await client.ensureTokenApproval({
  marketAddress: "0xMarket",
  minimumAmount: tokensIn,
  approveAmount: tokensIn * 10n, // optional; defaults to unlimited
});
```

{% hint style="info" %}
The SDK uses the configured token address from `DELPHI_TOKEN_ADDRESS` or the network default. It does not resolve a token address per market.
{% endhint %}

| Network             | Collateral token |
| ------------------- | ---------------- |
| Testnet             | $TEST            |
| Mainnet             | USDC             |
| Competition testnet | TST              |

### Gateway Contract Reference

This section is for advanced users who want to call the Gateway contract directly via `viem`.

The SDK uses `DYNAMIC_PARIMUTUEL_GATEWAY_ABI` on every network, including `competition-testnet`. The competition LMSR gateway exposes identical call signatures.

Competition differs in its underlying pricing math. Its `MarketSettled` event also omits market-creator economics fields.

#### viem Client Setup

Set up your viem client like this:

```typescript
import { createPublicClient, http, defineChain, type Abi } from "viem";
import {
  DELPHI_FACTORY_ABI,
  DYNAMIC_PARIMUTUEL_GATEWAY_ABI,
} from "@gensyn-ai/gensyn-delphi-sdk";

const chain = defineChain({
  id: Number(process.env.GENSYN_CHAIN_ID),
  name: "Gensyn Testnet",
  nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
  rpcUrls: { default: { http: [process.env.GENSYN_RPC_URL!] } },
});

const publicClient = createPublicClient({ chain, transport: http(process.env.GENSYN_RPC_URL!) });
const gateway = await client.resolveGateway(marketProxy);
```

`resolveGateway()` creates a signer-backed client internally. Configure `WALLET_PRIVATE_KEY` or CDP credentials, even for read-only use.

{% hint style="warning" %}
Do not use `DELPHI_GATEWAY_CONTRACT` for direct market calls unless it is the owning gateway. `resolveGateway()` selects the correct deployment.
{% endhint %}

`DELPHI_FACTORY_ABI` is also exported for direct Factory reads, including `marketProxiesExist`.

#### Gateway Functions

All of the gateway functions, broken down into tables by **\[1]** read and **\[2]** write.

#### 1. *Read* Functions

| Function                   | Args                                      | Returns              | Notes                                                         |
| -------------------------- | ----------------------------------------- | -------------------- | ------------------------------------------------------------- |
| `quoteBuyExactOut`         | marketProxy, outcomeIdx, sharesOut        | `tokensIn: uint256`  | Collateral cost (6 dec)                                       |
| `quoteSellExactIn`         | marketProxy, outcomeIdx, sharesIn         | `tokensOut: uint256` | Collateral payout (6 dec)                                     |
| `spotImpliedProbability`   | marketProxy, outcomeIdx                   | `uint256`            | 1e18 = 100%                                                   |
| `spotImpliedProbabilities` | marketProxy, outcomeIndices\[]            | `uint256[]`          | Batch                                                         |
| `spotPrice`                | marketProxy, outcomeIdx                   | `uint256`            | 1e18 = 1.0 collateral tokens per share                        |
| `spotPrices`               | marketProxy, outcomeIndices\[]            | `uint256[]`          | Batch                                                         |
| `balanceOf`                | marketProxy, owner, outcomeIdx            | `uint256`            | Shares (18 dec)                                               |
| `batchBalanceOf`           | marketProxy, owners\[], outcomeIndices\[] | `uint256[]`          | Batch                                                         |
| `totalSupply`              | marketProxy, outcomeIdx                   | `uint256`            | Total shares (18 dec)                                         |
| `totalSupplies`            | marketProxy, outcomeIndices\[]            | `uint256[]`          | Batch                                                         |
| `getMarket`                | marketProxy                               | Market struct        | Full on-chain state                                           |
| `marketStatus`             | marketProxy                               | `uint8`              | 0=Open, 1=Awaiting settlement, 2=Settled, 3=Expired, 4=Failed |
| `token`                    | marketProxy                               | `address`            | Collateral token address                                      |

#### 2. *Write* Functions

Prefer the SDK methods over calling the Gateway directly, as they handle simulation, approval, and receipt waiting.

| Function      | Args                                            | Notes                             |
| ------------- | ----------------------------------------------- | --------------------------------- |
| `buyExactOut` | marketProxy, outcomeIdx, sharesOut, maxTokensIn | Use `DelphiClient.buyShares()`    |
| `sellExactIn` | marketProxy, outcomeIdx, sharesIn, minTokensOut | Use `DelphiClient.sellShares()`   |
| `redeem`      | marketProxy                                     | Use `DelphiClient.redeemMarket()` |
| `liquidate`   | marketProxy, outcomeIndices                     | Use `DelphiClient.liquidate()`    |

### Direct Read Examples

#### Implied Probability for All Outcomes

```typescript
const probs = await publicClient.readContract({
  address: gateway,
  abi: DYNAMIC_PARIMUTUEL_GATEWAY_ABI as Abi,
  functionName: "spotImpliedProbabilities",
  args: [marketProxy, [0n, 1n]],
}) as bigint[];
// probs[i] / 1e18 * 100 = implied probability %
```

#### Spot Prices

```typescript
const prices = await publicClient.readContract({
  address: gateway,
  abi: DYNAMIC_PARIMUTUEL_GATEWAY_ABI as Abi,
  functionName: "spotPrices",
  args: [marketProxy, [0n, 1n]],
}) as bigint[];
// prices[i] / 1e18 = collateral tokens per share
```

#### Full Market State

```typescript
const onchainMarket = await publicClient.readContract({
  address: gateway,
  abi: DYNAMIC_PARIMUTUEL_GATEWAY_ABI as Abi,
  functionName: "getMarket",
  args: [marketProxy],
}) as {
  config: {
    outcomeCount: bigint;
    k: bigint;
    tradingFee: bigint;         // 1e18 = 100%
    tradingDeadline: bigint;    // Unix timestamp
    settlementDeadline: bigint; // Unix timestamp
  };
  pool: bigint;
  tradingFees: bigint;
};

const feePercent = Number(onchainMarket.config.tradingFee) / 1e18 * 100;
const deadline = new Date(Number(onchainMarket.config.tradingDeadline) * 1000);
```

#### Share Balance for a Wallet

```typescript
const balance = await publicClient.readContract({
  address: gateway,
  abi: DYNAMIC_PARIMUTUEL_GATEWAY_ABI as Abi,
  functionName: "balanceOf",
  args: [marketProxy, walletAddress as `0x${string}`, BigInt(outcomeIdx)],
}) as bigint;
// balance / 1e18 = shares
```

#### Price Impact Estimation

```typescript
const spotPrices = await publicClient.readContract({
  address: gateway,
  abi: DYNAMIC_PARIMUTUEL_GATEWAY_ABI as Abi,
  functionName: "spotPrices",
  args: [marketProxy, [0n, 1n]],
}) as bigint[];

const currentPricePerShare = Number(spotPrices[outcomeIdx]) / 1e18;
const { tokensIn } = await client.quoteBuy({ marketAddress, outcomeIdx, sharesOut });
const quotedPricePerShare = (Number(tokensIn) / 1e6) / sharesHuman;
const priceImpact = ((quotedPricePerShare - currentPricePerShare) / currentPricePerShare) * 100;
console.log(`Price impact: ${priceImpact.toFixed(2)}%`);
```


# Subgraph

Querying historical on-chain event data through the Goldsky-indexed GraphQL endpoint.

## Overview

The Delphi SDK includes a `SubgraphClient` that queries on-chain event data indexed by a [Goldsky subgraph.](https://docs.goldsky.com/subgraphs/introduction)

This gives read-only access to historical *buys, sells, redemptions, liquidations,* and *settlements* without needing an archive node or parsing raw logs.

{% hint style="info" %}
For more information on using Goldsky to build on Gensyn, [click here.](https://docs.gensyn.network/builders/goldsky)
{% endhint %}

### Accessing the Subgraph Client

`getSubgraph()` returns a `SubgraphClient` instance configured with the correct Goldsky endpoint for the active network.

```typescript
import { DelphiClient } from "@gensyn-ai/gensyn-delphi-sdk";

const client = new DelphiClient();
const subgraph = client.getSubgraph();
```

#### URL Resolution Order

1. `config.subgraphUrl` (constructor option on `DelphiClient`)
2. `DELPHI_SUBGRAPH_URL` environment variable
3. Network default

| Network             | Default endpoint                                                                                                   |
| ------------------- | ------------------------------------------------------------------------------------------------------------------ |
| Testnet             | `https://api.goldsky.com/api/public/project_cmnoqdag1obop01z3efnu8ssq/subgraphs/delphi-testnet-autoset/1.0.0/gn`   |
| Mainnet             | `https://api.goldsky.com/api/public/project_cmnoqdag1obop01z3efnu8ssq/subgraphs/delphi-mainnet-autoset/1.0.0/gn`   |
| Competition testnet | `https://api.goldsky.com/api/public/project_cmnoqdag1obop01z3efnu8ssq/subgraphs/delphi-agent-competition/1.0.0/gn` |

The default endpoints index automated-settlement gateways only. Set `DELPHI_SUBGRAPH_URL` to the legacy `delphi-testnet` or `delphi-mainnet` endpoint for legacy history.

### SubgraphClient API

#### query(query, variables?)

You can execute any arbitrary GraphQL query against the subgraph. Returns the `data` field from the response or throws on errors.

```typescript
query<T = unknown>(query: string, variables?: Record<string, unknown>): Promise<T>
```

#### getMarketTrades(marketProxy, params?)

Returns all buy and sell events for a given market proxy address, sorted most-recent-first.

```typescript
getMarketTrades(
  marketProxy: string,
  params?: { first?: number; skip?: number }
): Promise<{ buys: SubgraphBuy[]; sells: SubgraphSell[] }>
```

Defaults: `first = 100`, `skip = 0`.

#### getMarketSettlement(marketProxy)

Returns settlement data for a market. A market can be settled or failed, never both.

```typescript
const settlement = await subgraph.getMarketSettlement(marketProxy);
```

On competition testnet, `marketCreatorReward`, `refund`, and `marketCreatorTradingFeesCut` are `null`. Do not request these fields in hand-written competition queries.

#### getMeta()

Returns the current indexed block, deployment hash, and whether the subgraph has indexing errors. Useful for checking data freshness.

```typescript
getMeta(): Promise<SubgraphMeta>
```

### Types

#### SubgraphBuy

```typescript
interface SubgraphBuy {
  id: string;
  block_number: string;
  timestamp_: string;          // Unix seconds as string
  transactionHash_: string;
  contractId_: string;
  marketProxy: string | null;
  buyer: string | null;
  outcomeIdx: string | null;
  tokensIn: string | null;     // Collateral spent (6-decimal bigint as string)
  sharesOut: string | null;    // Shares received (18-decimal bigint as string)
}
```

#### SubgraphSell

```typescript
interface SubgraphSell {
  id: string;
  block_number: string;
  timestamp_: string;
  transactionHash_: string;
  contractId_: string;
  marketProxy: string | null;
  seller: string | null;
  outcomeIdx: string | null;
  sharesIn: string | null;     // Shares sold (18-decimal bigint as string)
  tokensOut: string | null;    // Collateral received (6-decimal bigint as string)
}
```

#### SubgraphMeta

```typescript
interface SubgraphMeta {
  block: {
    number: number;
    timestamp: number | null;
    hash: string | null;
  };
  deployment: string;
  hasIndexingErrors: boolean;
}
```

#### SubgraphMarketSettled fields

```typescript
// Settlement-specific fields.
winningOutcomeIdx: string | null;
marketCreatorReward: string | null;
refund: string | null;
marketCreatorTradingFeesCut: string | null;
```

#### SubgraphMarketFailed fields

```typescript
// Failure-specific field.
marketProxy: string | null;
```

#### SubgraphMarketResolutionRequested fields

```typescript
// Resolution-request-specific fields.
marketProxy: string | null;
keeper: string | null;
```

### GraphQL Schema Entities

The automated-settlement subgraph indexes market activity and settlement events.

Each entity is available as both a singular query (by `id`) and a plural collection query with filtering, ordering, and pagination.

| Entity                    | Singular query                  | Collection query                  | Description                |
| ------------------------- | ------------------------------- | --------------------------------- | -------------------------- |
| GatewayBuy                | `gatewayBuy(id)`                | `gatewayBuys(...)`                | Share purchase events      |
| GatewaySell               | `gatewaySell(id)`               | `gatewaySells(...)`               | Share sale events          |
| GatewayRedemption         | `gatewayRedemption(id)`         | `gatewayRedemptions(...)`         | Settled market redemptions |
| GatewayLiquidation        | `gatewayLiquidation(id)`        | `gatewayLiquidations(...)`        | Position liquidations      |
| GatewayMarketSettled      | `gatewayMarketSettled(id)`      | `gatewayMarketSettleds(...)`      | Market settlement events   |
| GatewayMarketFailed       | `gatewayMarketFailed(id)`       | `gatewayMarketFaileds(...)`       | Failed market events       |
| MarketResolutionRequested | `marketResolutionRequested(id)` | `marketResolutionRequesteds(...)` | Oracle resolution requests |
| Initialized               | `initialized(id)`               | `initializeds(...)`               |                            |

### Entity Fields

#### Common Fields (All Entities)

| Field              | Type      | Description               |
| ------------------ | --------- | ------------------------- |
| `id`               | `ID!`     | Unique event identifier   |
| `block_number`     | `BigInt!` | Block number of the event |
| `timestamp_`       | `BigInt!` | Unix timestamp (seconds)  |
| `transactionHash_` | `String!` | Transaction hash          |
| `contractId_`      | `String!` | Gateway contract address  |

#### Additional Fields (Specific Entities)

* **GatewayBuy** additional fields: `marketProxy`, `buyer`, `outcomeIdx`, `tokensIn` (collateral, 6-dec), `sharesOut` (shares, 18-dec)
* **GatewaySell** additional fields: `marketProxy`, `seller`, `outcomeIdx`, `sharesIn` (shares, 18-dec), `tokensOut` (collateral, 6-dec)
* **GatewayRedemption** additional fields: `marketProxy`, `redeemer`, `sharesIn` (18-dec), `tokensOut` (collateral, 6-dec)
* **GatewayLiquidation** additional fields: `marketProxy`, `liquidator`, `outcomeIndices`, `sharesIn`, `totalTokensOut` (collateral, 6-dec)
* **GatewayMarketSettled** additional fields: `marketProxy`, `winningOutcomeIdx`, `marketCreatorReward`, `refund`, `marketCreatorTradingFeesCut`. The economics fields are `null` on competition testnet.
* **GatewayMarketFailed** additional fields: `marketProxy`
* **MarketResolutionRequested** additional fields: `marketProxy`, `keeper`

#### Collection Query Parameters

All plural queries accept these:

| Parameter        | Type               | Description                                      |
| ---------------- | ------------------ | ------------------------------------------------ |
| `first`          | `Int`              | Max results (default 100, max 1000)              |
| `skip`           | `Int`              | Pagination offset                                |
| `orderBy`        | `<Entity>_orderBy` | Field to sort by (e.g. `timestamp_`, `tokensIn`) |
| `orderDirection` | `OrderDirection`   | `asc` or `desc`                                  |
| `where`          | `<Entity>_filter`  | Filter conditions                                |
| `block`          | `Block_height`     | Query at a specific block height                 |

#### Filtering (*where* clause)

| Suffix    | Operator         | Example                           |
| --------- | ---------------- | --------------------------------- |
| (none)    | equals           | `{ marketProxy: "0x..." }`        |
| `_not`    | not equals       | `{ buyer_not: "0x..." }`          |
| `_gt`     | greater than     | `{ timestamp__gt: "1700000000" }` |
| `_lt`     | less than        | `{ tokensIn_lt: "1000000" }`      |
| `_gte`    | greater or equal | `{ block_number_gte: "100" }`     |
| `_lte`    | less or equal    | `{ block_number_lte: "500" }`     |
| `_in`     | in list          | `{ outcomeIdx_in: ["0", "1"] }`   |
| `_not_in` | not in list      | `{ marketProxy_not_in: [...] }`   |

{% hint style="info" %}
String fields also support: `_contains`, `_contains_nocase`, `_not_contains`, `_starts_with`, `_starts_with_nocase`, `_ends_with`, `_ends_with_nocase` (and their `_not_` variants).
{% endhint %}

### Usage Examples

Here are some common subgraph query examples.

#### 1. Listing recent trades for a given market

```typescript
const subgraph = client.getSubgraph();
const { buys, sells } = await subgraph.getMarketTrades("0x1234...abcd", { first: 20 });

for (const buy of buys) {
  const cost = Number(BigInt(buy.tokensIn ?? "0")) / 1e6;
  const shares = Number(BigInt(buy.sharesOut ?? "0")) / 1e18;
  const time = new Date(Number(buy.timestamp_) * 1000).toLocaleString();
  console.log(`BUY  ${time} | ${buy.buyer} | outcome ${buy.outcomeIdx} | ${cost.toFixed(4)} collateral tokens → ${shares.toFixed(4)} shares`);
}
```

#### 2. Querying global recent buys

```typescript
const data = await subgraph.query<{ gatewayBuys: SubgraphBuy[] }>(`{
  gatewayBuys(first: 10, orderBy: timestamp_, orderDirection: desc) {
    id buyer marketProxy outcomeIdx tokensIn sharesOut timestamp_
  }
}`);
```

#### 3. Filtering buys by wallet address

```typescript
const data = await subgraph.query<{ gatewayBuys: SubgraphBuy[] }>(`{
  gatewayBuys(
    first: 50,
    orderBy: timestamp_, orderDirection: desc,
    where: { buyer: "${walletAddress.toLowerCase()}" }
  ) {
    id marketProxy outcomeIdx tokensIn sharesOut timestamp_ transactionHash_
  }
}`);
```

#### 4. Filtering buys by time range

```typescript
const oneDayAgo = Math.floor(Date.now() / 1000) - 86400;
const data = await subgraph.query<{ gatewayBuys: SubgraphBuy[] }>(`{
  gatewayBuys(
    first: 100,
    orderBy: timestamp_, orderDirection: desc,
    where: { timestamp__gte: "${oneDayAgo}" }
  ) {
    id buyer marketProxy outcomeIdx tokensIn sharesOut timestamp_
  }
}`);
```

#### 5. Querying redemptions for a given market

```typescript
const data = await subgraph.query<{ gatewayRedemptions: GatewayRedemption[] }>(`{
  gatewayRedemptions(
    first: 50,
    orderBy: timestamp_, orderDirection: desc,
    where: { marketProxy: "${marketProxy}" }
  ) {
    id timestamp_ marketProxy redeemer sharesIn tokensOut transactionHash_
  }
}`);
```

#### 6. Querying market settlements

```typescript
const data = await subgraph.query<{ gatewayMarketSettleds: SubgraphMarketSettled[] }>(`{
  gatewayMarketSettleds(
    first: 10,
    orderBy: timestamp_, orderDirection: desc,
    where: { marketProxy: "${marketProxy}" }
  ) {
    id timestamp_ marketProxy winningOutcomeIdx transactionHash_
  }
}`);
```

#### 7. Checking subgraph indexing status

```typescript
const meta = await subgraph.getMeta();
console.log(`Indexed up to block ${meta.block.number}`);
console.log(`Has errors: ${meta.hasIndexingErrors}`);
```

#### 8. Pagination

```typescript
let skip = 0;
const pageSize = 100;
const allBuys: SubgraphBuy[] = [];

while (true) {
  const { buys } = await subgraph.getMarketTrades(marketProxy, { first: pageSize, skip });
  allBuys.push(...buys);
  if (buys.length < pageSize) break;
  skip += pageSize;
}
```

#### 9. Parsing subgraph values

```typescript
// Timestamps → Date
const date = new Date(Number(event.timestamp_) * 1000);

// Collateral amounts (6 decimals)
const collateral = Number(BigInt(event.tokensIn ?? "0")) / 1e6;

// Share amounts (18 decimals)
const shares = Number(BigInt(event.sharesOut ?? "0")) / 1e18;

// Outcome index
const outcomeIdx = Number(event.outcomeIdx ?? "0");

// Effective price per share (from a buy event)
const pricePerShare = collateral / shares;
```


# Agentic Trading Toolkit (ATT)

A toolkit that enables AI agents to browse, trade, and manage positions on Delphi through natural language.

## What is Agentic Trading?

Agentic Trading is a toolkit that enables AI agents to interact with the Delphi prediction market platform on Gensyn.

It provides skill files, example scripts, and configuration patterns that let agents browse markets, execute trades, manage positions, query historical data, and redeem winnings, all through natural language interaction.

Under the hood, Agentic Trading uses the [Delphi SDK](/tech/delphi-sdk) for all market data access and on-chain operations. The SDK handles the technical complexity (RPC calls, contract interaction, token approvals, signing), while the Agentic Trading layer provides the behavioral framework that tells agents *when* and *how* to use those capabilities based on user intent.

You can install the Delphi skill with this command:

```bash
npx skills add https://github.com/gensyn-ai/gensyn-delphi-skills --skill delphi
```

### How it Works

The toolkit consists of two main pieces:

* **Skill Files:** Markdown files that describe agent behavior patterns: which SDK methods to call based on what the user asks for, how to format responses, and how to handle edge cases. These follow the standard skill MD approach for Claude and similar agent integrations.
* **Example Scripts:** These are ready-to-run TypeScript scripts in the `scripts/` folder that demonstrate every common operation. Agents can reference these as working examples or run them directly.

### Delphi's Pricing Mechanism

Delphi uses a *dynamic parimutuel (DPM)* pricing mechanism. Prices emerge from the distribution of all participants' wagers, rather than being set by a market maker. As new bets flow in, implied probabilities continuously update, and outcomes attracting more capital see their odds shorten, while less-backed outcomes become cheaper.

{% hint style="info" %}
Traders are effectively betting against the aggregate market rather than a counterparty, and the depth of the pool determines price sensitivity to new information.
{% endhint %}

{% hint style="info" %}
This section applies to Delphi testnet and mainnet. The agent trading competition uses LMSR pricing.
{% endhint %}

### Agent Trading Competition

The toolkit supports the agent trading competition on `competition-testnet`. It uses separate LMSR contracts and the TST collateral token.&#x20;

You can configure the network in [Get Started](/tech/agentic-trading/get-started).&#x20;

### What Agents Can Do

Agents can perform a wide range of actions using `SKILLS.md` :

* List, search, and browse prediction markets
* Fetch market details with live on-chain prices and implied probabilities
* Quote buy/sell trades (read-only, no gas cost)
* Execute buy and sell transactions with automatic token approval and slippage protection
* View portfolio positions and trade history
* Query historical on-chain event data via Goldsky subgraph (buys, sells, redemptions, liquidations, settlements)
* Redeem winnings from settled markets
* Manage ERC-20 token allowances

{% hint style="warning" %}
Agents cannot create markets. Markets **must** be created through the Delphi UI.

*Any markets created outside the UI will not appear in the interface.*
{% endhint %}


# Get Started

Clone the repo, install the skill, configure your environment, and start interacting with your agent.

## Prerequisites

There are several dependencies required to enable Agentic Trading on Delphi:

* Node.js installed (`npm -v` to verify)
* A wallet with ETH for gas and collateral tokens: $TEST on testnet, USDC on mainnet, or TST on competition testnet
* A [Delphi API access](#api-access-key-required) key

### Github Repos

You can find the Agentic Trading Toolkit (ATT) Skills file and the Delphi SDK here.

{% embed url="<https://github.com/gensyn-ai/gensyn-delphi-skills>" %}

{% embed url="<https://github.com/gensyn-ai/gensyn-delphi-sdk.git>" %}

### 1. Install the Delphi Skill

Run this single command to install the Delphi skill:

```bash
npx skills add https://github.com/gensyn-ai/gensyn-delphi-skills --skill delphi
```

You'll then be prompted to choose a scope and install the skill to the agent(s) of your choice.

1. **Choose a Scope:**
   1. **Global:** The agent can use Delphi from any folder
   2. **Project:** The agent can only use Delphi when working with that specific subfolder
2. **Select Agent(s):** Use the `space` key to choose which agents to install the skill for (Claude Code, Cursor, Cline, etc.)

### 2. Configure Environment Variables

Create a `.env` file in the project root with your credentials. You need two things: **\[1]** an API key and **\[2]** wallet signing credentials.

#### API Access Key (Required)

See the [SDK Configuration](/tech/delphi-sdk/configuration) documentation for details on requesting a testnet or mainnet API access key.

`competition-testnet` uses the testnet API deployment. Use a testnet API key.

#### Wallet Signing (Required)

You have two options for wallet signing: either a **\[1]** private key (which is easiest for development or a **\[2]** Coinbase CDP server wallet (recommended for production use cases).

#### via Private Key

```bash
DELPHI_SIGNER_TYPE=private_key
WALLET_PRIVATE_KEY=0x<your-hex-private-key>
```

#### via Coinbase CDP Server Wallet

```bash
CDP_API_KEY_ID=<your-key-id>
CDP_API_KEY_SECRET=<your-key-secret>
CDP_WALLET_SECRET=<your-wallet-secret>
CDP_WALLET_ADDRESS=0x<your-wallet-address>
```

CDP Server Wallet is the default signer type. There is no need to set `DELPHI_SIGNER_TYPE`. You can get your CDP credentials from the [Server Wallet v2 Quickstart](https://docs.cdp.coinbase.com/server-wallets/v2/introduction/quickstart).

{% hint style="info" %}
With CDP Server Wallets, private keys are secured in Coinbase's Trusted Execution Environment (TEE) and never leave the TEE. See the [Server Wallet v2 docs](https://docs.cdp.coinbase.com/server-wallets/v2/introduction/quickstart) for details.
{% endhint %}

#### Network Selection (Optional)

The SDK defaults to testnet. Set `DELPHI_NETWORK` to select mainnet or the competition.

Testnet defaults are listed in [SDK Configuration](/tech/delphi-sdk/configuration). Do not hardcode gateway addresses.

Competition testnet uses the testnet chain and RPC. It uses separate LMSR contracts and TST collateral with six decimals.

| Variable                | Values                                                                               | Default     |
| ----------------------- | ------------------------------------------------------------------------------------ | ----------- |
| `DELPHI_NETWORK`        | `"testnet"` \| `"mainnet"` \| `"competition-testnet"`                                | `"testnet"` |
| `DELPHI_COMPETITION_ID` | Optional competition ID; defaults to the active competition and is ignored elsewhere | —           |

#### Overrides (Optional)

These override network defaults if you need to point at a custom endpoint:

| Variable                  | Description                      |
| ------------------------- | -------------------------------- |
| `GENSYN_RPC_URL`          | Custom RPC endpoint              |
| `GENSYN_CHAIN_ID`         | Custom chain ID                  |
| `DELPHI_GATEWAY_CONTRACT` | Custom gateway contract address  |
| `DELPHI_API_BASE_URL`     | Custom API base URL              |
| `DELPHI_SUBGRAPH_URL`     | Custom Goldsky subgraph endpoint |

#### Example .env File

```
# Required
DELPHI_API_ACCESS_KEY=your-api-key-here

# Signing — Option A: Private key
DELPHI_SIGNER_TYPE=private_key
WALLET_PRIVATE_KEY=0xYourPrivateKeyHere

# Network (optional — defaults to testnet)
# DELPHI_NETWORK=testnet

# Competition (optional)
# DELPHI_NETWORK=competition-testnet
# DELPHI_COMPETITION_ID=  # Defaults to the active competition.
```

#### Wallet Funding

To execute Delphi transactions, your signer wallet must have:

* **ETH** on the Gensyn chain (for gas fees)
* **$TEST** on testnet, **USDC** on mainnet, or **TST** on competition testnet

Competition TST cannot be faucet-minted. Organizers distribute it after wallet registration. Gas still uses testnet ETH.

{% hint style="info" %}
Competition users need `@gensyn-ai/gensyn-delphi-sdk` version `2.1.0` or later. A fresh install uses a supported version.
{% endhint %}

### 3. Start Using your Agent

Open your agent of choice and start interacting with Delphi. The agent will use the skill files to understand your intent and call the appropriate [SDK](/tech/delphi-sdk) methods.

{% hint style="success" %}
The whole point of Agentic Trading is that you interact through natural language. So can you say *"buy 10 shares of outcome 0"* and the agent handles it. Get creative!
{% endhint %}

You can try something like:

* *"Show me the open prediction markets"*
* *"What's the current price on \[market name]?"*
* *"Buy 10 shares of outcome 0 on \[market address]"*
* *"What are my current positions?"*

{% hint style="info" %}
See the [Usage Guide](/tech/agentic-trading/usage-guide) for more in-depth information.
{% endhint %}


# Creating & Funding Wallets

How to fund your wallet with ETH and collateral tokens for trading on Delphi.

## Wallet Funding

To trade on Delphi using the Agentic Trading Toolkit, you need two assets on the Gensyn chain:

* **ETH:** This is used for gas fees.
* **Collateral tokens:** **\[1]** $TEST on testnet, **\[2]** USDC on mainnet, and **\[3]** TST on competition testnet.

If you're starting from scratch, this page walks you through creating a wallet and funding it for your network.

If you already have some of these pieces in place, you can skip ahead using the shortcuts below:

* **No wallet yet, or no crypto holdings:** Start at [Getting Started with a Crypto Wallet.](#getting-started-with-a-crypto-wallet)
* **Wallet with ETH and native USDC on Ethereum Mainnet:** Skip to [Manual Bridging](#manual-bridging), or let the Delphi agent handle bridging automatically.
* **Wallet already has ETH and bridged USDC on Gensyn Mainnet:** You're ready to trade. See the [agent documentation](/tech/agentic-trading/usage-guide) to get started.
* **Working on testnet:** Skip to [Testnet Funding.](#testnet)

The funding process differs between testnet and mainnet. Testnet uses a faucet-based flow for fast iteration whereas mainnet bridges real ETH and native USDC from Ethereum.

{% hint style="info" %}
For `competition-testnet`, ETH gas guidance remains the same as testnet. TST collateral cannot be faucet-minted or bridged. Organizers distribute TST when they register your wallet.
{% endhint %}

For canonical network parameters (RPC URLs, chain IDs, block explorers) and OP Stack contract addresses, refer to the [OP Stack Contracts](https://docs.gensyn.network/providers/network-information#op-stack-contracts) section in the [Gensyn Network](https://docs.gensyn.network/) docs.

### Getting Started with a Crypto Wallet

To use Delphi you need a self-custody crypto wallet that holds ETH and USDC on Ethereum Mainnet. This section orients you if you're new to crypto: detailed setup steps are maintained by the wallet providers and exchanges themselves.

#### Create a Wallet

Any EVM-compatible self-custody wallet works. Two common options:

* [MetaMask](https://metamask.io/download): A browser extension and mobile app, widely supported by dApps.
* [Coinbase Wallet](https://www.coinbase.com/wallet/downloads): A browser extension and mobile app that directly integrates with Coinbase exchange accounts.

Follow the provider's setup guide to create the wallet and securely back up your recovery phrase.

#### Fund with ETH and USDC

The simplest path for most users is to buy ETH and USDC on a centralized exchange like [Coinbase](https://www.coinbase.com), then withdraw to your self-custody wallet on Ethereum Mainnet. Coinbase's [withdrawal guide](https://help.coinbase.com/en/coinbase/getting-started/crypto-education/how-to-send-crypto) walks through the process.

{% hint style="warning" %}
USDC must be native Circle-issued USDC on Ethereum Mainnet (`0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48`).

USDC.e, axlUSDC, and other bridged variants will not work. Coinbase withdraws native USDC by default, so this is only a concern if you're sourcing USDC from another platform.
{% endhint %}

Once your wallet holds ETH and native USDC on Ethereum Mainnet, you have two options:

1. **Let the Delphi agent handle bridging automatically:** This is the default path.
2. **Bridge manually:** Continue to [Manual Bridging](#manual-bridging) below.

### Manual Bridging

If you prefer to bridge funds yourself rather than let the agent handle it, or if you're building custom tooling against the Delphi SDK, use the flows below.

ETH bridges via the OP Stack canonical bridge. USDC bridges via Stargate V2 (LayerZero), which offers faster finality than the canonical bridge for ERC-20 transfers.

Both scripts below require `DELPHI_NETWORK=mainnet` in your `.env`.

### Testnet

On testnet, you'll bridge Sepolia ETH to Gensyn Testnet for gas, then mint $TEST from a faucet contract on Gensyn Testnet.

* **Prerequisites:** You need Sepolia ETH in your wallet before you can do anything else. $TEST is minted directly on Gensyn Testnet. No prior balance is needed.

#### Step 1: Get Sepolia ETH

Use a Sepolia faucet to get ETH on Ethereum Sepolia. We recommend the [Google Cloud Web3 Faucet](https://cloud.google.com/application/web3/faucet/ethereum/sepolia).

#### Step 2: Bridge ETH to Gensyn Testnet

Use the bundled script to bridge ETH from Sepolia to Gensyn Testnet via the OP Stack canonical bridge:

```bash
npx tsx scripts/bridge-eth-to-gensyn-testnet.ts <amount-eth>
# or
npm run bridge-eth-to-gensyn-testnet 0.0001
```

ETH arrives on Gensyn Testnet within a few minutes of Sepolia confirmation. The deposit appears under the **Internal txns** tab on the [Gensyn Testnet explorer](https://gensyn-testnet.explorer.alchemy.com/), not under regular Transactions.

{% hint style="info" %}
OP Stack deposits are a special transaction type (`0x7e`) triggered by the L1 bridge rather than a user-signed L2 transaction.
{% endhint %}

#### Alternative: Call the L1 Bridge Directly

You can bypass the script and call `depositETH` directly on the Sepolia L1StandardBridge. For the contract address, see [OP Stack Contracts.](https://docs.gensyn.network/providers/network-information#op-stack-contracts)

Using Foundry's `cast`:

```bash
# Deposit 0.1 ETH to your own address on Gensyn Testnet
cast send <L1StandardBridge-Sepolia> \
  "depositETH(uint32,bytes)" 200000 "0x" \
  --value 0.1ether \
  --rpc-url https://ethereum-sepolia-rpc.publicnode.com \
  --private-key $PRIVATE_KEY

# Deposit to a different address
cast send <L1StandardBridge-Sepolia> \
  "depositETHTo(address,uint32,bytes)" $RECIPIENT 200000 "0x" \
  --value 0.1ether \
  --rpc-url https://ethereum-sepolia-rpc.publicnode.com \
  --private-key $PRIVATE_KEY
```

You can also do this using `viem`:

```typescript
import { createWalletClient, http, parseEther, encodeFunctionData } from "viem";
import { sepolia } from "viem/chains";
import { privateKeyToAccount } from "viem/accounts";

const account = privateKeyToAccount(process.env.WALLET_PRIVATE_KEY as `0x${string}`);
const walletClient = createWalletClient({
  account,
  chain: sepolia,
  transport: http("https://ethereum-sepolia-rpc.publicnode.com"),
});

const hash = await walletClient.sendTransaction({
  to: "<L1StandardBridge-Sepolia>",
  value: parseEther("0.1"),
  data: encodeFunctionData({
    abi: [{
      name: "depositETH",
      type: "function",
      inputs: [
        { name: "_minGasLimit", type: "uint32" },
        { name: "_extraData", type: "bytes" },
      ],
      stateMutability: "payable",
    }],
    functionName: "depositETH",
    args: [200000, "0x"],
  }),
});
```

#### Step 3: Claim $TEST from the Faucet

On testnet, the collateral is $TEST, minted directly from a faucet contract on Gensyn Testnet. Each call dispenses 1,000 $TEST. Its on-chain symbol is `MT`.

You can find the Delphi testnet contracts here:

| Contract               | Address                                      |
| ---------------------- | -------------------------------------------- |
| $TEST Faucet           | `0xB5876320DdA1AEE3eFC03aD02dC2e2CB4b61B7D9` |
| $TEST collateral token | `0x0724D6079b986F8e44bDafB8a09B60C0bd6A45a1` |

Use the bundled script to claim:

```bash
npx tsx scripts/testnet-faucet.ts
# or
npm run testnet-faucet
```

This calls `requestToken()` on the faucet, logs your balance before and after, and waits for the transaction to confirm.

To call the faucet directly with `cast`:

```bash
cast send 0xB5876320DdA1AEE3eFC03aD02dC2e2CB4b61B7D9 \
  "requestToken()" \
  --rpc-url https://gensyn-testnet.g.alchemy.com/public \
  --private-key $PRIVATE_KEY
```

### Mainnet

On mainnet, you'll bridge real ETH and native USDC from Ethereum to Gensyn Mainnet. ETH uses the canonical OP Stack bridge; USDC uses Stargate V2 (LayerZero) for faster finality.

* **Prerequisites:** You need both ETH and native USDC on Ethereum Mainnet before bridging.
  * **ETH** is needed to pay L1 gas for the bridge transactions, and once bridged, to pay gas when trading on Gensyn.
  * **USDC** must be native Circle-issued USDC on Ethereum Mainnet (`0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48`). USDC.e, axlUSDC, and other bridged variants will not work.

Both scripts below require `DELPHI_NETWORK=mainnet` in your `.env`.

#### Bridging ETH (Ethereum Mainnet to Gensyn Mainnet)

ETH bridges via the OP Stack canonical bridge:

```bash
npx tsx scripts/bridge-eth-to-gensyn-mainnet.ts <amount-eth>
# or
npm run bridge-eth-to-gensyn-mainnet 0.0001
```

ETH arrives within a few minutes and appears under the **Internal txns** tab on the [Gensyn Mainnet explorer](https://gensyn-mainnet.explorer.alchemy.com/): this is the same pattern as when bridging to testnet (see above).

For the L1StandardBridge and related contract addresses, see [OP Stack Contracts.](https://docs.gensyn.network/providers/network-information#op-stack-contracts)

#### Bridging USDC (Ethereum Mainnet to Gensyn Mainnet via Stargate V2)

USDC bridges via Stargate V2 (LayerZero) rather than the canonical bridge. The script handles approval, quotes the LayerZero fee, and sends in one flow:

```bash
npx tsx scripts/bridge-usdc-to-gensyn-mainnet.ts <amount-usdc> [slippage-pct]
# or
npm run bridge-usdc-to-gensyn-mainnet 10
npm run bridge-usdc-to-gensyn-mainnet 10 1
```

Default slippage is 0.5%. You'll need ETH on Ethereum Mainnet to cover the LayerZero messaging fee (\~0.001–0.005 ETH) in addition to normal Ethereum gas. Track delivery at [LayerZero Scan](https://layerzeroscan.com/).

For the Stargate pool addresses, OFT addresses, and Gensyn's LayerZero Endpoint ID, see the [LayerZero / Stargate](https://docs.gensyn.network/providers/bridges#layerzero-stargate) section under [Bridges.](https://docs.gensyn.network/providers/bridges)


# Usage Guide

What you can ask the agent to do, example prompts, and available scripts.

## Using Natural Language

Agentic Trading is designed to be used through natural language: you tell your agent what you want to do, and it handles the SDK calls, contract interactions, and error handling for you. This page covers what you can do and how to do it.

{% hint style="info" %}
For the underlying code-level details (type definitions, parameter schemas, contract methods, GraphQL queries), see the [Delphi SDK documentation.](/tech/delphi-sdk)
{% endhint %}

### Asking your Agent to Do Things

Once you've completed the [Getting Started](/tech/agentic-trading/get-started) setup, open your agent and start with natural language. Here are the core capabilities:

#### Browse & Research Markets

* *"Show me the open prediction markets"*
* *"List crypto markets"*
* *"What's the current price and probability on \[market name]?"*
* *"Get me the details for market \[id]"*

The agent can list markets, filter by status or category, and fetch live on-chain prices and implied probabilities for any market.

#### Trade

* *"Buy 10 shares of outcome 0 on \[market address]"*
* *"How much would it cost to buy 5 shares of outcome 1?"*
* *"Sell all my shares in \[market address]"*
* *"Quote a sell for 20 shares of outcome 0"*

The agent handles the full trade flow automatically: quoting the cost, approving the `maxTokensIn` slippage cap, applying slippage protection, and executing the transaction. You can also ask for a quote first without committing.

#### Manage Positions

* *"What are my current positions?"*
* *"Show me my active positions that haven't been redeemed"*
* *"Redeem my winnings from \[market address]"*
* *"Redeem all my settled positions"*
* *"Liquidate my expired markets"*
* *"Liquidate my failed markets"*

The agent can list your holdings, filter out zero-share positions, and handle both single and batch redemptions. Expired and failed markets have no winning outcome. Exit them with liquidation, not redemption.

#### Query Trade History

* *"Show me recent trades for \[market address]"*
* *"What buys happened in the last 24 hours?"*
* *"Has \[market address] been settled? Who won?"*

The agent queries the Goldsky subgraph for historical on-chain events including buys, sells, redemptions, liquidations, and settlements.

#### Manage Token Approvals

* *"Check my token allowance for \[market address]"*
* *"Approve unlimited collateral spending for \[market address]"*

In most cases you won't need to manage approvals manually, since the agent handles this automatically before trades. But you can check or set approvals explicitly if needed.

{% hint style="warning" %}
Agents cannot create markets. Markets *must* be created through the Delphi UI.

**Markets created outside the UI will not appear in the interface.**
{% endhint %}

### Monitoring your Agent (TUI)

The toolkit includes a read-only terminal dashboard (TUI) for supervising your agent's Delphi activity in real time. It never signs or trades, so it's safe to leave running alongside an active agent. It only observes.

Launch it with a wallet address and network (both required):

```bash
npx tsx scripts/agent-tui/index.tsx <wallet-address> <testnet|mainnet|competition-testnet>
# or, via the npm script:
npm run agent-tui -- <wallet-address> <testnet|mainnet|competition-testnet>
```

It reads `DELPHI_API_ACCESS_KEY` from your `.env`. The network argument selects RPC and API endpoints, with no `DELPHI_NETWORK` fallback. `DELPHI_COMPETITION_ID` is read from `.env` for competition views.

Positions outside the selected market scope can appear as unpriced.

<div data-with-frame="true"><figure><img src="/files/7yJAsmQs4M7NVWAieAu8" alt=""><figcaption></figcaption></figure></div>

The dashboard has four screens:

* **Overview:** A live snapshot including the Edge View and Agent Logs
* **Portfolio:** Your current positions
* **My Activity:** The wallet's trade history
* **Markets:** Browse markets, with drill-down into any single market

| Key       | Action                                                                        |
| --------- | ----------------------------------------------------------------------------- |
| `1`–`4`   | Switch screens                                                                |
| `↑` / `↓` | Move selection                                                                |
| `⏎`       | Open details                                                                  |
| `esc`     | Go back                                                                       |
| `r`       | Refresh                                                                       |
| `q`       | Quit                                                                          |
| `--once`  | Render one frame and exit. Useful for non-interactive shells and screenshots. |

### Example Scripts

The `scripts/` folder in the skills repo contains working TypeScript examples for every common operation.

These serve two purposes: **\[1]** agents can reference or run them directly, and **\[2]** you can use them to test your setup or run operations outside of an agent conversation.

| Script                                     | Purpose                                                 | Usage                                                                                                                   |
| ------------------------------------------ | ------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `scripts/list-markets.ts`                  | List and filter markets; honors `DELPHI_COMPETITION_ID` | `npx tsx scripts/list-markets.ts [status] [category] [limit]`                                                           |
| `scripts/get-market.ts`                    | Get market details; honors `DELPHI_COMPETITION_ID`      | `npx tsx scripts/get-market.ts <market-id>`                                                                             |
| `scripts/quote-buy.ts`                     | Get buy quote (read-only)                               | `npx tsx scripts/quote-buy.ts <market-address> <outcome-idx> <shares>`                                                  |
| `scripts/quote-sell.ts`                    | Get sell quote (read-only)                              | `npx tsx scripts/quote-sell.ts <market-address> <outcome-idx> <shares>`                                                 |
| `scripts/quote-redeem.ts`                  | Preview a redemption quote (read-only)                  | `npx tsx scripts/quote-redeem.ts <market-address>`                                                                      |
| `scripts/quote-liquidate.ts`               | Preview a liquidation quote (read-only)                 | `npx tsx scripts/quote-liquidate.ts <market-address>`                                                                   |
| `scripts/buy-shares.ts`                    | Buy shares; accepts fractional slippage percentages     | `npx tsx scripts/buy-shares.ts <market-address> <outcome-idx> <shares> [slippage-pct]`                                  |
| `scripts/sell-shares.ts`                   | Sell shares; accepts fractional slippage percentages    | `npx tsx scripts/sell-shares.ts <market-address> <outcome-idx> <shares> [slippage-pct]`                                 |
| `scripts/list-positions.ts`                | List wallet positions                                   | `npx tsx scripts/list-positions.ts [wallet-address]`                                                                    |
| `scripts/redeem.ts`                        | Redeem winnings from settled markets                    | `npx tsx scripts/redeem.ts <market-address> [market-address ...]`                                                       |
| `scripts/liquidate.ts`                     | Recover funds from expired or failed markets            | `npx tsx scripts/liquidate.ts <market-address> [market-address ...]`                                                    |
| `scripts/get-wallet-balances.ts`           | Check ETH and collateral-token balances                 | `npx tsx scripts/get-wallet-balances.ts`                                                                                |
| `scripts/token-approval.ts`                | Check or set market token approval                      | `npx tsx scripts/token-approval.ts <market-address> [amount\|unlimited]`                                                |
| `scripts/list-recent-trades.ts`            | List recent trades via subgraph                         | `npx tsx scripts/list-recent-trades.ts <market-proxy-address> [limit]`                                                  |
| `scripts/log-event.ts`                     | Support the TUI's Agent Logs view                       | `npx tsx scripts/log-event.ts <type> "<message>"`                                                                       |
| `scripts/compute-edge.ts`                  | Support the TUI's Edge View                             | `npx tsx scripts/compute-edge.ts <market-address> <outcome-idx> <your-prob> [market-address outcome-idx your-prob ...]` |
| `scripts/agent-tui/index.tsx`              | Launch the terminal dashboard                           | `npm run agent-tui -- <wallet-address> <testnet\|mainnet\|competition-testnet>`                                         |
| `scripts/testnet-faucet.ts`                | Claim $TEST; unavailable on competition                 | `npx tsx scripts/testnet-faucet.ts`                                                                                     |
| `scripts/bridge-eth-to-gensyn-testnet.ts`  | Bridge Sepolia ETH to Gensyn Testnet                    | `npx tsx scripts/bridge-eth-to-gensyn-testnet.ts <amount-eth>`                                                          |
| `scripts/bridge-eth-to-gensyn-mainnet.ts`  | Bridge Ethereum ETH to Gensyn Mainnet                   | `npx tsx scripts/bridge-eth-to-gensyn-mainnet.ts <amount-eth>`                                                          |
| `scripts/bridge-usdc-to-gensyn-mainnet.ts` | Bridge Ethereum USDC to Gensyn Mainnet                  | `npx tsx scripts/bridge-usdc-to-gensyn-mainnet.ts <amount-usdc> [slippage-pct]`                                         |

All scripts use the shared client setup from `scripts/client.ts` which handles environment variable configuration automatically. You can also run them via npm scripts: `npm run list-markets`, `npm run buy-shares`, etc.

For faucet and bridge helpers, see [Creating & Funding Wallets](/tech/agentic-trading/creating-and-funding-wallets) for the full funding flow and network-specific guidance.

{% hint style="info" %}
Before trying to run any scripts, make sure you've completed the [Getting Started setup](/tech/agentic-trading/get-started) and you have all required dependencies installed *and* the `.env` file configured.
{% endhint %}

### Going Deeper

If you want to write custom integrations or understand the code-level details behind what the agent is doing, the [Delphi SDK](/tech/delphi-sdk) documentation covers everything:

* [Configuration](/tech/delphi-sdk/configuration): Environment variables, signing modes, network defaults
* [API Reference](/tech/delphi-sdk/api): Market and position types, filtering, pagination, redemption patterns
* [On-Chain Methods](/tech/delphi-sdk/methods): Trading mechanics, slippage, Gateway contract reference, token approvals
* [Subgraph](/tech/delphi-sdk/subgraph): GraphQL schema, entity types, filtering operators, raw query examples


# Troubleshooting

Covers common errors, environment variable issues, wallet problems, and slippage failures.

## Overview

There are several errors which can occur when using the Agentic Trading toolkit.

### Contract Errors

These errors occur during on-chain trade execution.

| Error                             | Cause                                               | Fix                                                   |
| --------------------------------- | --------------------------------------------------- | ----------------------------------------------------- |
| `TokensInExceedsMax`              | Price moved above your `maxTokensIn` since quoting  | Re-quote and increase slippage tolerance              |
| `TokensOutBelowMin`               | Price moved below your `minTokensOut` since quoting | Re-quote and increase slippage tolerance              |
| `MarketNotOpen`                   | Market is closed or settled                         | Check `market.status` before trading                  |
| `SharesInExceedSupply`            | Selling more shares than your wallet holds          | Check position balance before selling                 |
| `GrossTokensOutNotPositive`       | Attempting to sell with no position                 | Position is empty — nothing to sell                   |
| `ZeroTokensIn`                    | `sharesOut` amount too small to register            | Use a larger share amount                             |
| `MarketProxyNotDeployedByFactory` | Pinned gateway does not own the market              | Remove the pinned gateway or resolve market ownership |

### Environment Variable Errors

| Error                      | Cause                                                      | Fix                                                                                                                          |
| -------------------------- | ---------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `Requires apiKey`          | `DELPHI_API_ACCESS_KEY` not set                            | Add it to your `.env` file — generate at [Delphi API Access](https://delphi-api-access.gensyn.ai/)                           |
| `Requires rpcUrl`          | `GENSYN_RPC_URL` not set and network default not resolving | Set `DELPHI_NETWORK=testnet` or provide `GENSYN_RPC_URL` explicitly                                                          |
| `Requires privateKey`      | Using private key signing without `WALLET_PRIVATE_KEY`     | Set `WALLET_PRIVATE_KEY` in `.env` or switch to CDP signer                                                                   |
| `CDP signing requires ...` | Missing one or more CDP environment variables              | Ensure all four `CDP_*` variables are set: `CDP_API_KEY_ID`, `CDP_API_KEY_SECRET`, `CDP_WALLET_SECRET`, `CDP_WALLET_ADDRESS` |

### Wallet & Network Issues

Errors related to token bridging, balance lag, MetaMask, market or market action issues, and more.

#### MetaMask Not Showing the Correct Balance

If MetaMask shows unexpected balances or token symbols after connecting to the Gensyn network:

1. Open MetaMask and go to **Settings** then **Networks**
2. Find the Gensyn network entry and click **Edit**
3. Verify the RPC URL matches: `https://gensyn-testnet.g.alchemy.com/public`
4. Verify the Chain ID matches: `685685`
5. Save and refresh the page

#### Bridge Transactions Not Appearing

After bridging tokens from Sepolia to Gensyn testnet, balances may take up to 5 minutes to reflect.

If tokens still don't appear:

1. Check the transaction on the explorer to confirm it was sent
2. Verify you're viewing the correct network in MetaMask (Gensyn Testnet, not Sepolia)
3. Try switching away from the Gensyn network and switching back
4. Refresh MetaMask or the Delphi UI

#### Transactions Failing with Insufficient Funds

Your signer wallet needs both ETH for gas and collateral tokens for trading on the Gensyn chain.

If transactions fail:

1. Check your ETH balance: even read-only quote operations are free, but all write operations (buy, sell, approve, redeem) require gas
2. Check your collateral balance: Make sure you have enough to cover the trade amount plus slippage
3. On Delphi testnet, use the $TEST faucet or bridge ETH for gas
4. Competition TST has no faucet. Organizers distribute it after registration

### Positions Showing Zero Shares

The positions API may return entries with `shares === "0"` for markets you previously participated in but fully exited. These are expected. They indicate historical participation, not current holdings.

{% hint style="info" %}
Always check `BigInt(position.shares) > 0n` before attempting to redeem or liquidate.
{% endhint %}

### Market Not Found or Not Trading

* **Market shows as `awaiting_settlement`**: Trading deadline has passed. You cannot buy or sell, but the market hasn't been settled yet.
* **Market shows as `settled`**: Trading is closed. If you hold the winning outcome, you can redeem your position.
* **Market shows as `expired`**: Market expired without settlement. Positions are not redeemable — recover funds with `liquidate()`.
* **Market shows as `failed`**: Oracle settlement could not resolve the market. Positions are not redeemable — recover funds with `liquidate()`.
* **Market not appearing in search**: There is currently no search functionality in the Delphi UI. Use `client.listMarkets()` with filtering to find markets programmatically, or browse by category and status.

### Competition issues

| Symptom                                     | Cause                                               | Fix                                                          |
| ------------------------------------------- | --------------------------------------------------- | ------------------------------------------------------------ |
| Every API call returns `401`                | Mainnet key used on competition                     | Use a testnet API key                                        |
| `listMarkets()` returns no markets          | No active competition is selected                   | Pass `DELPHI_COMPETITION_ID`                                 |
| `getMarket()` returns `404`                 | Market is outside the selected competition          | Use the correct competition ID                               |
| Trades do not appear on the leaderboard     | Wallet is unregistered or below activity thresholds | Register the signer wallet and meet competition requirements |
| A modest quote reverts                      | LMSR liquidity is shallow                           | Reduce trade size                                            |
| Client construction fails                   | SDK version is below `2.1.0`                        | Install `@gensyn-ai/gensyn-delphi-sdk` `2.1.0` or later      |
| `redeemMarket()` reverts on a closed market | Market is expired or failed                         | Use `liquidate()`                                            |

### Slippage Failures (on Active Markets)

If your trades keep failing with `TokensInExceedsMax` or `TokensOutBelowMin`, the market is likely seeing high trading volume and prices are moving between your quote and execution.

Increase your slippage tolerance:

| Scenario                 | Recommended slippage |
| ------------------------ | -------------------- |
| Quiet market             | 1–2%                 |
| Active market            | 2–5%                 |
| Large trade (>$100)      | 5–10%                |
| Time-sensitive execution | 5%                   |

You can also try using *basis points* for precise integer arithmetic:

```typescript
const slippageBps = 200n; // 200 = 2%
const maxTokensIn  = tokensIn  * (10000n + slippageBps) / 10000n;
const minTokensOut = tokensOut * (10000n - slippageBps) / 10000n;
```


# Agent eXchange Layer (AXL)

What AXL is, what it does, and what you can build with it.

## What is AXL?

Agent eXchange Layer (AXL) is a peer-to-peer network node built by Gensyn.&#x20;

It offers an encrypted, decentralized communication layer for applications, allowing AI agents, ML pipelines, distributed computing, and more to exchange data directly between machines *without* a central server.

Fundamentally, it works like this: you run the node on your machine where it handles all peer-to-peer transport, encryption, and routing. The node exposes a local HTTP bridge as an application interface, compatible with whatever you're building.&#x20;

### Features

AXL is designed to stay out of your way. It runs without root access, works behind NATs, and exposes a plain HTTP interface so any language can use it.

* **No TUN required:** Runs entirely in userspace using gVisor's network stack. No root privileges, no system-level network configuration.
* **No port forwarding needed:** Connects outbound to peers and receives data over the same encrypted tunnel, so standard nodes work behind NATs and firewalls without any extra configuration. If you're bootstrapping a new network from scratch, at least one node needs to be publicly reachable with an exposed port.&#x20;

{% hint style="info" %}
Running a public node on an existing network is also helpful since it adds to the overall robustness of the mesh.
{% endhint %}

* **Simple local interface:** Your application talks to `localhost:9002`. Any language that can make HTTP requests can use AXL.
* **End-to-end encrypted:** All traffic between nodes is encrypted at two layers: TLS for the direct peering link, and Yggdrasil's end-to-end encryption for the full path. Intermediate routing nodes cannot read your messages.
* **Application-agnostic:** The node doesn't care what you send. You could send JSON, protobuf, raw bytes, or tensors.
* **Protocol support:** AXL features built-in support for [MCP](https://modelcontextprotocol.io/) (Model Context Protocol) and [A2A](https://github.com/google/A2A) (Agent-to-Agent) for structured request/response communication between agents.

### At a Glance

Getting two machines talking takes four steps and no infrastructure.

1. You build and run the AXL node binary on your machine.
2. The node connects to the Yggdrasil[^1] mesh network and gets a public key (your identity).
3. You share your public key with another person. They share theirs with you.
4. Your applications communicate through their local nodes. The nodes handle everything else.

It doesn't require any servers, cloud accounts, or DNS. It's just two machines (or more) running nodes that communicate directly over the mesh.

```
      Your Machine                                                  Their Machine
┌──────────────────────┐                                       ┌──────────────────────┐
│  [Your App]          │                                       │  [Their App]         │
│       ↕ HTTP         │                                       │       ↕ HTTP         │
│  [AXL node :9002]    │             ◄── mesh ──►              │  [AXL node :9002]    │
└──────────────────────┘                                       └──────────────────────┘
```

### Philosophy

AXL enforces a clean separation between the **\[1]** network layer (the node) and the **\[2]** application layer (your code). The node is a *pipe* insofar as it moves bytes between peers, but it has no opinion about what those bytes mean.&#x20;

This separation means:

* You can build any application on top of AXL without modifying the node or worrying about transport protocols.
* Multiple applications can share the same node.
* The network handles encryption, routing, and peer discovery. Your application handles business logic.

{% hint style="info" %}
AXL is permissionless. Anyone can run a node or spin up their own private network. There are no gatekeepers.
{% endhint %}

### What You Can Build

Because AXL is just a communication layer, what you build on top is up to you.&#x20;

A few [examples](/tech/agent-exchange-layer/examples-and-building#built-in-examples) ship with the repo:

* **AI agent collaboration:** Agents on different machines sharing research signals over MCP
* **Distributed ML inference:** Tensor exchange between nodes using `msgpack`
* **GossipSub:** Pub/sub message propagation across the mesh
* **Convergecast:** Tree-based data aggregation using the network's spanning tree

#### Get Started

Ready to get started? Find documentation [here](/tech/agent-exchange-layer/get-started) on cloning the repo, building the node, creating an identity key, configuring it, and making sure everything works.

[^1]: we should link out to libraries that we have used


# Get Started

Instructions on how to get started with AXL.

## Overview

**\[1]** Clone the [repo](https://github.com/gensyn-ai/axl), **\[2]** build the node, **\[3]** run it, and **\[4]** verify everything works.

{% embed url="<https://github.com/gensyn-ai/axl>" fullWidth="false" %}

### Prerequisites

| Tool           | Required     | Install                                                                                     |
| -------------- | ------------ | ------------------------------------------------------------------------------------------- |
| *Go 1.25.x*    | Yes          | `brew install go` (macOS) or [click here](https://go.dev/dl/)                               |
| *Python 3.9+*  | For examples | Usually pre-installed on macOS/Linux, or [download here](https://www.python.org/downloads/) |
| *pip packages* | For examples | `pip install textual requests`                                                              |

{% hint style="warning" %}
**Go 1.26 compatibility:** The `gvisor.dev/gvisor` dependency has build tag conflicts with Go 1.26. The `toolchain go1.25.5` directive in `go.mod` handles this automatically if you have Go 1.25 installed.&#x20;

If you only have Go 1.26+, prefix build commands with `GOTOOLCHAIN=go1.25.5`.
{% endhint %}

### Clone and Build

This command sequence produces a single binary called `node` in the current directory:

```bash
git clone https://github.com/gensyn-ai/axl.git
cd axl
go build -o node ./cmd/node/
```

### Generate a Key

The node needs an `ed25519` private key for its identity.&#x20;

You have two options: **\[1]** persisting your identity or **\[2]** generating a new key automatically on startup.

#### Option A: Persistent identity (recommended)

Generate a key file so your node keeps the same public key across restarts:

```bash
openssl genpkey -algorithm ed25519 -out private.pem
```

***

**For macOS users specifically:** the default `openssl` on macOS is LibreSSL, which does not support `ed25519`. To get around this, use Homebrew's OpenSLL instead:

```bash
brew install openssl
/opt/homebrew/opt/openssl/bin/openssl genpkey -algorithm ed25519 -out private.pem
```

***

#### Option B: Ephemeral identity

Skip key generation entirely. If you omit `PrivateKeyPath` from your config, the node generates a new identity in memory each time it starts. Fine for quick testing but your public key changes every restart.

### Configure

Create a `node-config.json` in the repo root. If someone gave you a peer address to connect to, add it to the `Peers` array:

```json
{
  "PrivateKeyPath": "private.pem",
  "Peers": ["tls://THEIR_IP:9001"]
}
```

If you don't have a peer address yet (just testing locally), leave `Peers` empty:

```json
{
  "PrivateKeyPath": "private.pem",
  "Peers": []
}
```

That's the minimal config. See the [Configuration](/tech/delphi-sdk/configuration) section below for all available settings.

### Start the Node

Run this command:

```bash
./node -config node-config.json
```

You'll see output including the following:

```
Your IPv6 address is 200:abcd:...
Your public key is 1ee862344fb283395143ac9775150d2e5936efd6e78ed0db83e3f290d3d539ef
```

If you get this output, it means your node is now running. Leave this terminal open.

### Verify

Then, run this command in a separate terminal:

```bash
curl -s http://127.0.0.1:9002/topology | python3 -c "import sys,json; d=json.load(sys.stdin); print('Public key:', d['our_public_key']); print('IPv6:', d['our_ipv6'])"
```

If you see your public key and IPv6 address, the node is up and the local interface is reachable.

### Connect with Another Person

Your public key is your address on the network.&#x20;

To 'communicate' with someone, you need to exchange keys (like trading phone numbers):

1. **Find your key:** It's printed on node startup, or run the curl command above.
2. **Share it:** Send your 64-character hex key to the other person via Slack, Discord, email, whatever.
3. **Get theirs:** They do the same.

{% hint style="danger" %}
Remember, this is the 64-character public key, *not* a private key in the `.pem` file. Please do not share that key!
{% endhint %}

Now you can send each other messages or call each other's MCP services.

{% hint style="info" %}
There is no way to look up another node's key from the network. The `/topology` endpoint shows keys of nodes in the spanning tree, but it doesn't tell you who owns them. Keys *must* be exchanged directly between people.
{% endhint %}

### Quick Two-Node Test

The fastest way to verify everything works end-to-end is running two nodes locally. To test this out, follow the list of commands below, running them sequentially in the *proper* terminals.&#x20;

First, generate a second key:

```bash
 /opt/homebrew/opt/openssl/bin/openssl genpkey -algorithm ed25519 -out private-2.pem
```

Create a second config (`node-config-2.json`):

```json
 {
   "PrivateKeyPath": "private-2.pem",
   "Peers": [],
   "Listen": [],
   "api_port": 9012,
   "tcp_port": 7001
 }
```

Start the second node in a new terminal:

```bash
 ./node -config node-config-2.json
```

Finally, send a message between the two nodes (in different terminals) and check the output:

```bash
 NODE_A_KEY=$(curl -s http://127.0.0.1:9002/topology | python3 -c "import sys,json; print(json.load(sys.stdin)['our_public_key'])")
 NODE_B_KEY=$(curl -s http://127.0.0.1:9012/topology | python3 -c "import sys,json; print(json.load(sys.stdin)['our_public_key'])")

 # Send from B → A
 curl -X POST http://127.0.0.1:9012/send \
   -H "X-Destination-Peer-Id: $NODE_A_KEY" \
   -d "hello from node B"

 # Receive on A
 sleep 1
 curl -v http://127.0.0.1:9002/recv
```

The response body should contain `hello from node B`, and the `X-From-Peer-Id` header should match Node B's public key. This is the exact same flow two people on different machines would use, with the only difference being that they wouldn't need different port numbers.

#### Configuration Reference

Check out [this documentation](/tech/agent-exchange-layer/configuration) for the full list of API flags, configuration settings, and some example set-ups.&#x20;


# Configuration

CLI flags, node settings, and example configurations.

## Overview

The node reads a single JSON file (default: `node-config.json`) at startup. Every field is optional, so if you omit a field, its default value is used. You only need to include settings you want to change.

### CLI Flags

You can run `./node [flags]` once your node is up and running.

| Flag      | Description                                          | Default            |
| --------- | ---------------------------------------------------- | ------------------ |
| `-config` | Path to config file                                  | `node-config.json` |
| `-listen` | Listen address for incoming peers (overrides config) | *(none)*           |

The `-listen` flag is for hosting a public node that accepts inbound peer connections, making your node a bootstrap/relay point for others to connect to.&#x20;

This requires exposing a port on the public internet. If you're just connecting outbound to existing peers (the normal case), you don't need this flag.

#### node-config.json

All of these fields are optional. For any fields that are left blank, default values are applied.

#### Network Identity & Peering

The config file is shared between two systems: **\[1]** Yggdrasil (the network layer) and the **\[2]** AXL node (the application layer).&#x20;

This is why the casing differs: `PrivateKeyPath` and `Peers` are Yggdrasil settings (PascalCase), while `api_port` and `tcp_port` are AXL node settings (snake\_case). Both live in the same file.

| Field            | Type      | Description                                                | Example                  |
| ---------------- | --------- | ---------------------------------------------------------- | ------------------------ |
| `PrivateKeyPath` | string    | Path to ed25519 PEM key file. Omit for ephemeral identity. | `"private.pem"`          |
| `Peers`          | string\[] | Bootstrap peer URIs to connect to on startup.              | `["tls://1.2.3.4:9001"]` |
| `Listen`         | string\[] | Addresses to listen for incoming peer connections.         | `["tls://0.0.0.0:9001"]` |

### Node Settings

| Field                    | Type   | Default     | Description                               |
| ------------------------ | ------ | ----------- | ----------------------------------------- |
| `api_port`               | int    | `9002`      | HTTP interface port                       |
| `bridge_addr`            | string | `127.0.0.1` | HTTP interface bind address               |
| `tcp_port`               | int    | `7000`      | Internal TCP listener port (gVisor)       |
| `router_addr`            | string | *(empty)*   | MCP Router host. Empty = MCP disabled.    |
| `router_port`            | int    | `9003`      | MCP Router port                           |
| `a2a_addr`               | string | *(empty)*   | A2A Server host. Empty = A2A disabled.    |
| `a2a_port`               | int    | `9004`      | A2A Server port                           |
| `max_message_size`       | int    | `16777216`  | Max message size in bytes (default 16 MB) |
| `max_concurrent_conns`   | int    | `128`       | Max concurrent inbound TCP connections    |
| `conn_read_timeout_secs` | int    | `60`        | Read timeout per connection (seconds)     |
| `conn_idle_timeout_secs` | int    | `300`       | Idle timeout per connection (seconds)     |

{% hint style="warning" %}
A note on `bridge_addr`: The default `127.0.0.1` means only your local machine can reach the HTTP API. If you change this to `0.0.0.0`, the API is exposed to your entire network. Anyone who can reach that port can send messages as your node.&#x20;

*Do not change this unless you understand the implications.*
{% endhint %}

#### Resource & Connection Limits

These protect the node against resource exhaustion from misbehaving or flooding peers.&#x20;

The defaults are appropriate for most setups. You only need to tune these if you're running a high-traffic public node or operating in a constrained environment.

| Field                    | Type | Default    | Description                                   |
| ------------------------ | ---- | ---------- | --------------------------------------------- |
| `max_message_size`       | int  | `16777216` | Max TCP message size in bytes (default 16 MB) |
| `max_concurrent_conns`   | int  | `128`      | Max simultaneous inbound TCP connections      |
| `conn_read_timeout_secs` | int  | `60`       | Read timeout per connection (seconds)         |
| `conn_idle_timeout_secs` | int  | `300`      | Idle timeout per connection (seconds)         |

#### Enabling MCP & A2A

Setting `router_addr` or `a2a_addr` in the config tells the node to route matching inbound messages to those services.&#x20;

But the config alone doesn't start the services: you also need the Python processes running. Spin up those processes like this:

```bash
# MCP Router (must be running at router_addr:router_port)
cd integrations
pip install -e .
python -m mcp_routing.mcp_router --port 9003

# A2A Server (must be running at a2a_addr:a2a_port)
python -m a2a_serving.a2a_server --port 9004 --router http://127.0.0.1:9003
```

If `router_addr` is empty, MCP messages arriving at your node are silently ignored. Same for `a2a_addr` and A2A messages. See [Building Applications & Examples](/tech/agent-exchange-layer/examples-and-building) for full setup walkthroughs.

### Example Configurations

Standard (persistent identity, one bootstrap peer):

```json
{
  "PrivateKeyPath": "private.pem",
  "Peers": ["tls://1.2.3.4:9001"]
}
```

Public node (accepting inbound peers):

```json
{
  "PrivateKeyPath": "private.pem",
  "Peers": [],
  "Listen": ["tls://0.0.0.0:9001"]
}
```

With MCP and A2A enabled:

```json
{
  "PrivateKeyPath": "private.pem",
  "Peers": ["tls://1.2.3.4:9001"],
  "router_addr": "http://127.0.0.1",
  "router_port": 9003,
  "a2a_addr": "http://127.0.0.1",
  "a2a_port": 9004
}
```

Here is what two nodes looks like on the same machine. *Node A* uses defaults, but *Node B* needs different ports:

```json
{
  "PrivateKeyPath": "private-2.pem",
  "Peers": [],
  "api_port": 9012,
  "tcp_port": 7001
}
```

#### LAN "Hub-and-spoke"

**\[1]** Hub (listening):

```json
{
  "PrivateKeyPath": "private.pem",
  "Listen": ["tls://0.0.0.0:9001"]
}
```

**\[2]** Spoke (connecting to hub):

```json
{
  "PrivateKeyPath": "private.pem",
  "Peers": ["tls://192.168.0.22:9001"]
}
```

**\[3]** Custom resource limits (for high-traffic public nodes):

```json
{
  "PrivateKeyPath": "private.pem",
  "Listen": ["tls://0.0.0.0:9001"],
  "max_concurrent_conns": 512,
  "max_message_size": 33554432,
  "conn_read_timeout_secs": 30,
  "conn_idle_timeout_secs": 120
}
```

See [How It Works](/tech/agent-exchange-layer/how-it-works) for the full picture of what's happening under the hood.


# How it Works

In-depth information on AXL's architecture, encryption, peering, privacy model, wire format, and node internals.

## The Mental Model

This is the single most important thing to understand about AXL, and it's counterintuitive if you're coming from traditional client-server architecture:

*Your application code never touches the network.*&#x20;

It runs on your machine and only ever talks to `http://127.0.0.1:9002` which is the local HTTP interface exposed by your AXL node. Your node handles all peer-to-peer transport, encryption, and routing behind the scenes.

Both sides run the full stack independently. If two people want to communicate, each person runs:

1. Their own AXL node (the `Go` binary)
2. Their own copy of the application

Nobody "connects to" the other person's application. Each application talks only to its own local node. The nodes talk to each other over the encrypted mesh.

```
      Your Machine                                                  Their Machine
┌──────────────────────┐                                       ┌──────────────────────┐
│  [Your App]          │                                       │  [Their App]         │
│       ↕ HTTP         │                                       │       ↕ HTTP         │
│  [AXL node :9002]    │             ◄── mesh ──►              │  [AXL node :9002]    │
└──────────────────────┘                                       └──────────────────────┘
```

"Exposing a service" doesn't mean what it usually means. In traditional web development, exposing a service means binding to a port and accepting remote connections. But in AXL, it means: **\[1]** your node is running, **\[2]** your application is running locally, and **\[3]** remote nodes send messages to your public key.&#x20;

The Yggdrasil network routes those messages to your node, which queues them for your application. Your application is never directly reachable from the outside. The node is the *only thing* with a network presence.

Therefore, there is nothing to deploy; you run your application on your laptop, and as long as your node is up, other nodes can reach you by your public key, so long as you share it.

### Architecture

The Go binary (`node`) contains four layers:

```
                        localhost
                 ┌──────────────────┐
                 │                  │
    Your App ◄───┤ HTTP API (:9002) │
                 │                  │
                 │   Multiplexer   ─┼──► MCP Router (:9003)
                 │        │         │
                 │   gVisor TCP     ├──► A2A Server (:9004)
                 │        │         │
                 │   Yggdrasil Core │
                 │        │         │
                 └────────┼─────────┘
                          │ TLS/TCP
                          ▼
                     Network Peers
```

| **Layer**        | **What It Does**                                                                                                                 |
| ---------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| *HTTP Interface* | Local server on `127.0.0.1:9002`. Your application's single point of contact with the node.                                      |
| *Multiplexer*    | Routes inbound TCP messages to the correct handler based on envelope fields. Unmatched messages go to a queue your app can read. |
| *gVisor TCP*     | Userspace TCP/IP stack. No TUN device, no root privileges. Listens on port 7000 for inbound peer connections.                    |
| *Yggdrasil Core* | Manages the ed25519 keypair, derives a deterministic IPv6 address, and peers over TLS/TCP with other nodes.                      |

The MCP Router and A2A Server are optional, separate Python processes for structured request/response protocols. See [Building Applications & Examples](/tech/agent-exchange-layer/examples-and-building) for details.

#### Startup Flow

Here is what happens when you run `./node -config node-config.json`:

1. CLI flags are parsed (`-config`, optional `-listen` override).
2. The config file is read for both Yggdrasil settings (`Peers`, `Listen`, `PrivateKeyPath`) and node settings (ports, limits, router URLs).
   1. Yggdrasil core starts. It connects to configured peers, joins the spanning tree, logs your IPv6 address and public key.
   2. gVisor TCP stack starts and listens on `tcp_port` (default 7000) for inbound connections from other nodes.
   3. HTTP server starts then binds to `bridge_addr:api_port` (default `127.0.0.1:9002`).

### The Yggdrasil Network

AXL uses [Yggdrasil](https://yggdrasil-network.github.io/), an encrypted IPv6 overlay network, for all peer-to-peer transport.

* **Overlay network.** Yggdrasil runs on top of the regular internet (or LAN). It creates an encrypted mesh between all participating nodes.
* **Spanning tree routing.** Peers form a spanning tree. Each node gets a deterministic IPv6 address derived from its public key. Routing happens along the tree without no centralized routing table.
* **Identity = public key.** Nodes are identified by their 64-character hex-encoded `ed25519` public key, not by IP or hostname.
* **Encrypted by default.** All connections use TLS, and Yggdrasil adds end-to-end encryption on top (see Encryption below).

### Peering

To join the network, your node connects to at least one other node. This is configured in the `Peers` array in `node-config.json`.

#### Bootstrap Peers

Bootstrap peers are nodes that accept inbound connections and help route traffic. They're entry points into the mesh, not controllers and as such they cannot read your message content. They just relay encrypted bytes.

```json
{
  "Peers": ["tls://1.2.3.4:9001"]
}
```

Once connected to a bootstrap peer, your node can reach any other node in the mesh by their public key. The mesh handles all of the routing work so you don't need direct connectivity to every node.

{% hint style="success" %}
Bootstrap peers are a standard pattern used by Bitcoin, IPFS, Ethereum, and other P2P networks. Anyone can run one.
{% endhint %}

#### Running a Public Node (Being a Bootstrap Peer)

If you want other nodes to connect to you, you can run a public node. Public nodes help route traffic through the mesh: they don't store other nodes' data or have access to their messages, they just forward encrypted bytes.&#x20;

The more public nodes in the network, the more resilient it becomes.&#x20;

To set one up:

1. Expose a TCP port to the network (LAN or internet).
2. Add a `Listen` address to your config:

```json
 {
   "PrivateKeyPath": "private.pem",
   "Listen": ["tls://0.0.0.0:9001"]
 }
```

3. Share your IP and port with others. They add `tls://YOUR_IP:9001` to their `Peers`.

Use a persistent identity (`PrivateKeyPath`) so your key doesn't change across restarts.&#x20;

{% hint style="info" %}
Keep the HTTP interface port (`9002`) locked to localhost. Only the peering port should be exposed.
{% endhint %}

#### LAN vs. Internet Peering

* **On a LAN (same network):** Trivial. Both nodes just need each other's LAN IP and listen port. There is no port forwarding or firewall adjustments that need to be made with this route.
* **Over the internet:** The listening node must expose its TCP port to the public internet (port forwarding, cloud VM with open port, etc.). Outbound-only nodes don't need to expose anything however: they can still communicate with each other because traffic is routed through public nodes in the mesh.

#### Peer Discovery

Running the following command returns:

* `our_public_key`: your node's identity
* `our_ipv6`: your node's Yggdrasil IPv6 address
* `peers`: directly connected peers
* `tree`: the spanning tree as your node sees it

```bash
curl -s http://127.0.0.1:9002/topology | python3 -m json.tool
```

{% hint style="info" %}
There is no built-in service registry.&#x20;

You can see public keys in the tree, but you can't look up who owns them or what services they run. Keys and service names must be exchanged directly between people.&#x20;
{% endhint %}

### Encryption: Two Layers

There are two distinct layers of encryption. Understanding both matters.

#### Layer 1: Peering Transport (TLS)

The `tls://` URIs in your config establish encrypted links between directly connected peers. This is hop-by-hop meaning it secures the connection between your node and the peer it's directly connected to, which is standard TLS.

#### Layer 2: End-to-End Payload Encryption (Yggdrasil)

Separately, Yggdrasil encrypts all traffic between source and destination using keys derived from both nodes' ed25519 keypairs. This is end-to-end so if *Node A* sends a message to *Node C* and it routes through *Node B*, *Node B* sees only ciphertext it cannot decrypt.&#x20;

```
Node A ──[TLS]──► Bootstrap Node ──[TLS]──► Node B
         Layer 1                   Layer 1

Node A ═══════════[E2E Encrypted]═══════════► Node B
                    Layer 2
                 (bootstrap can't read this)
```

Both of these matter because in a mesh network, your traffic may pass through nodes you don't control. *Layer 1* protects the link whereas *Layer 2* protects the payload across the entire path, regardless of how many hops it takes.

{% hint style="info" %}
So even though a different node could 'see' that there is communication happening, it can't figure out what is being communicated.&#x20;
{% endhint %}

### Security & Privacy

What routing nodes can and cannot see is important to understanding security and privacy of anything connected to a node, coming from a node, being received *by* a node, etc.&#x20;

#### What Nodes Can & Cannot See

* Routing nodes *can* see:
  * That your node exists and your IP address (you connected to them directly).
  * That two nodes are communicating, including the **\[1]** source and **\[2]** destination public keys.
  * When communication happens, how frequently, and the approximate message sizes.&#x20;
* Routing nodes *cannot* see:
  * Message content. They route encrypted bytes with no ability to decrypt.
  * **\[1]** What your application does, **\[2]** what services you expose, or **\[3]** what commands are being sent.
  * Anything inside the encrypted payload: application-level metadata like JSON fields, headers, or protocol details.

{% hint style="info" %}
'Routing nodes' also includes *bootstrap peers.*&#x20;
{% endhint %}

***

| **Information**            | **Sender** | **Receiver** | **Routing Nodes**       |
| -------------------------- | ---------- | ------------ | ----------------------- |
| *Message content*          | Yes        | Yes          | No                      |
| *Application metadata*     | Yes        | Yes          | No                      |
| *Who is communicating*     | Yes        | Yes          | Yes (public keys)       |
| *When and how often*       | Yes        | Yes          | Yes                     |
| *Approximate message size* | Yes        | Yes          | Yes                     |
| *Your IP address*          | —          | —            | Yes (direct peers only) |

***

#### Limitations

Yggdrasil, unlike Tor, does not use onion routing, meaning there is no traffic obfuscation. Although it protects the content of conversations, anyone who controls the routing nodes can observe the communication patterns, specifically who communicates with whom and when, but they cannot see the actual content of this communication.&#x20;

Additionally, your Internet Protocol (IP) address is visible to direct connections. This visibility extends to bootstrap peers and any node you directly connect with, making your real IP address accessible to them.

{% hint style="warning" %}
Security considerations are important when using Yggdrasil. While it employs standard cryptographic methods, such as `ed25519`, TLS 1.3, and the Noise protocol, it has not undergone a formal, independent security audit. Thus, additional caution is advised.&#x20;
{% endhint %}

In the event of a key compromise, the consequences are total. If this happens, anyone with access to your `private.pem` file can impersonate your node. Due to this risk, you *must* private key with the same vigilance as an SSH key.&#x20;

Moreover, Yggdrasil does not include access control mechanisms. Any node possessing your public key can send messages to you, so it is crucial that your application *independently validate message senders* when necessary.

### Data Flow

This section describes the flow of data during sending and receiving messages within an AXL-powered application.

#### Sending a Message

Your application posts data to `localhost:9002/send` with the destination peer's public key.&#x20;

The node dials the remote peer over the gVisor TCP stack, writes a length-prefixed message, and returns: there is response from the remote destination.

#### Receiving a Message

When a remote peer sends your node a message, the multiplexer checks it against registered protocol streams (MCP, A2A). If nothing matches, it goes into an in-memory queue which your application then polls.

#### MCP / A2A (Request-Response)

For structured communication, the node:

1. wraps your JSON-RPC body in a transport envelope
2. sends it to the remote peer
3. waits for a response (30-second timeout)
4. unwraps it, then returns it.&#x20;

The remote peer must have the corresponding service running.

### Wire Format

All TCP messages between nodes are length-prefixed: a 4-byte big-endian `uint32` length followed by a payload of XYZ number of bytes.

```
┌──────────────┬─────────────────────────────────┐
│ Length (4B)   │ Payload (Length bytes)           │
│ big-endian   │                                  │
│ uint32       │                                  │
└──────────────┴─────────────────────────────────┘
```

{% hint style="info" %}
Max message size defaults to 16 MB which is configurable via `max_message_size`.
{% endhint %}

#### Envelope Routing

The multiplexer determines how to handle each inbound message by inspecting its content:

| **Envelope Pattern**                   | **Routed To**                              |
| -------------------------------------- | ------------------------------------------ |
| `{"service": "...", "request": {...}}` | MCP Router                                 |
| `{"a2a": true, "request": {...}}`      | A2A Server                                 |
| *Anything else*                        | Message queue (your app reads via polling) |

The first protocol stream whose discriminator matches 'wins' and any unmatched messages go to the queue.

### Internals

Here you can find a breakdown of the AXL repo and some additional information on the dependencies it requires.&#x20;

***

#### Project Layout

```
cmd/node/              # Go entrypoint — main.go (wiring), config.go (settings)
api/                   # HTTP handlers — send, recv, topology, mcp, a2a
internal/
  tcp/listen/          # Inbound TCP: listener, multiplexer, stream interface
  tcp/dial/            # Outbound TCP: peer dialing
  mcp/                 # MCP stream (envelope parsing, forwarding to router)
  a2a/                 # A2A stream (envelope parsing, forwarding to server)
integrations/          # Python services: MCP router, A2A server
examples/              # Python examples: tensors, gossipsub, convergecast, A2A
```

***

#### gVisor TCP Stack

AXL uses [gVisor's](https://gvisor.dev/) userspace network stack instead of the OS kernel's TCP/IP.&#x20;

For this, there is/are:

* **No TUN device:** No virtual network interface are created.
* **No root privileges:** Everything runs in userspace.
* **No system configuration:** No `sysctl` and no routing table changes.

The stack bridges to Yggdrasil's core, providing standard TCP operations (**\[1]** listen, **\[2]** accept, **\[3]** dial) over the encrypted mesh.

* **Inbound:** A TCP listener on `tcp_port` (default 7000) accepts connections from remote nodes. Each connection delivers a length-prefixed message routed by the multiplexer.
* **Outbound:** `DialPeerConnection` converts a 64-char hex public key to a Yggdrasil IPv6 address and dials it through the gVisor stack.

#### The Stream Interface

The multiplexer routes messages using a `Stream` interface:

```go
type Stream interface {
    GetID() string
    IsAllowed(data []byte, metadata any) bool
    Forward(metadata any, fromPeerId string) ([]byte, error)
}
```

* `IsAllowed` inspects raw bytes and returns `true` if this stream handles the message.
* `Forward` processes the message and returns a response.

{% hint style="info" %}
Streams are checked in order, where the first match wins. If there is no match it is sent to the message queue.
{% endhint %}

MCP and A2A are implemented as streams. To add a new protocol, implement `Stream` and register it in `internal/tcp/listen/listener.go`.

#### Connection Limits

There are some default connection limits (as shown below) but these values can be adjusted. See the [Configuration](/tech/agent-exchange-layer/configuration) page for more information.

| **Setting**              | **Default** | **Description**                          |
| ------------------------ | ----------- | ---------------------------------------- |
| `max_concurrent_conns`   | 128         | Max simultaneous inbound TCP connections |
| `conn_read_timeout_secs` | 60          | Read timeout per connection              |
| `conn_idle_timeout_secs` | 300         | Idle timeout per connection              |

#### Message Queue

Inbound messages that don't match any stream go to an in-memory queue:

* **Unbounded:** Messages accumulate until read.
* **Single-consumer:** Each read dequeues one message. If you need multiple consumers, you'll need to build a fan-out layer that polls `/recv` and distributes to your consumers.
* **Non-persistent:** The queue empties on restart.
* **First-in, First Out (FIFO):** Messages are returned in the order they arrived.

#### Dependencies

These are the dependencies required by AXL.&#x20;

| **Dependency**                                                    | **Purpose**            |
| ----------------------------------------------------------------- | ---------------------- |
| [yggdrasil-go](https://github.com/yggdrasil-network/yggdrasil-go) | Mesh networking core   |
| [gVisor](https://gvisor.dev/)                                     | Userspace TCP/IP stack |
| [gologme/log](https://github.com/gologme/log)                     | Structured logging     |

{% hint style="warning" %}
Go module requires `Go 1.25.x` (gVisor has build tag issues with `1.26`). See [Get Started](/tech/agent-exchange-layer/get-started) for more info.
{% endhint %}

#### Running Tests

The repo includes Go tests for the core node (API handlers, TCP transport and protocol streams) and Python tests for the MCP router and A2A server integrations. You don't need any external services.&#x20;

```bash
# Go
go test ./...

# Python integrations
cd integrations
pip install -e ".[test]"
pytest
```


# Building Applications & Examples

Shipped examples and step-by-step patterns for building your own services with send/recv, MCP, and A2A, plus patterns for building your own applications on top of it.

## Overview

AXL is a peer-to-peer networking layer that lets you build distributed applications over a mesh of connected nodes.&#x20;

{% hint style="info" %}
For more on the internals of AXL, check out [How it Works.](/tech/agent-exchange-layer/how-it-works)
{% endhint %}

It provides low-level messaging primitives along with higher-level protocol support for MCP and A2A, so you can go from simple fire-and-forget communication to fully discoverable agent services with minimal setup.

### Building your Own Application

Building an application using AXL means picking a starting point. In this case, that starting point can be a *building pattern* which makes use of AXL's low-level functionalities in a particular way.&#x20;

These patterns include **\[1]** fire-and-forget (using `send`/`recv`), **\[2]** MCP services (`request`/`response`), and **\[3]** A2A (agent-to-agent).&#x20;

### Pattern 1: Send/Recv (Fire-and-Forget)

This is the simplest pattern. Your application sends raw bytes and polls for incoming messages.

```python
import requests, json, time

AXL = "http://127.0.0.1:9002"
PEER = "1ee862344fb283395143ac9775150d2e5936efd6e78ed0db83e3f290d3d539ef"

def send(message):
    requests.post(f"{AXL}/send",
        headers={"X-Destination-Peer-Id": PEER},
        data=json.dumps(message))

def recv_loop():
    while True:
        resp = requests.get(f"{AXL}/recv")
        if resp.status_code == 200:
            sender = resp.headers.get("X-From-Peer-Id")
            print(f"From {sender[:8]}...: {resp.text}")
        time.sleep(0.2)
```

* **When to use:** Simple messaging, notifications, data streaming, custom protocols where you control both sides.
* **Limitation:** No built-in acknowledgment. If you need request-response, use MCP/A2A or build correlation over `send`/`recv`.

### Pattern 2: MCP Services (Request-Response)

MCP (Model Context Protocol) gives you structured JSON-RPC request-response. You expose a named service on your node, and other nodes call it remotely.

The requests flow like this:

```
Remote node calls POST /mcp/{your_key}/sentiment
  -> Your node receives it
  -> Multiplexer sees "service" field → forwards to MCP Router (localhost:9003)
  -> Router dispatches to your service (localhost:7100)
  -> Your service processes and responds
  -> Response flows back to remote node
```

#### Step 1: Write Your Service

You can start by configuring a basic HTTP server:

```python
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route("/mcp", methods=["POST"])
def handle():
    req = request.json
    if req.get("method") == "tools/list":
        return jsonify({
            "jsonrpc": "2.0", "id": req["id"],
            "result": {"tools": [{"name": "analyze", "description": "Analyze sentiment"}]}
        })
    if req.get("method") == "tools/call":
        result = do_analysis(req["params"].get("arguments", {}))
        return jsonify({
            "jsonrpc": "2.0", "id": req["id"],
            "result": {"content": [{"type": "text", "text": json.dumps(result)}]}
        })
    return jsonify({"error": "unknown method"}), 400

app.run(host="127.0.0.1", port=7100)
```

#### Step 2: Start the MCP Router

```bash
cd integrations
pip install -e .
python -m mcp_routing.mcp_router --port 9003
```

#### Step 3: Register your Service w/ Router

```python
requests.post("http://127.0.0.1:9003/register", json={
    "service": "sentiment",
    "endpoint": "http://127.0.0.1:7100/mcp"
})
```

Don't forget to deregister on shutdown using this command:

`requests.delete("http://127.0.0.1:9003/register/sentiment")`

#### Step 4: Enable MCP (Node Config)

If you run this command, any node on the network can call your service by your public key and service name:

```json
{
  "router_addr": "http://127.0.0.1",
  "router_port": 9003
}
```

If you want to calling a remote MCP service (from another node), you'd run this:

```bash
# List tools on a remote peer's "sentiment" service
curl -X POST http://127.0.0.1:9002/mcp/{peer_id}/sentiment \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"tools/list","id":1,"params":{}}'

# Call a specific tool
curl -X POST http://127.0.0.1:9002/mcp/{peer_id}/sentiment \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"tools/call","id":1,"params":{"name":"analyze","arguments":{"market":"0x3f"}}}'
```

{% hint style="info" %}
Replace `{peer_id}` with the remote node's 64-character hex public key.&#x20;

Both nodes must share at least one common peer but they don't need direct connectivity.
{% endhint %}

#### **MCP Router Endpoints**

Use this list of router endpoints.

| **Endpoint**                 | **Description**                                                |
| ---------------------------- | -------------------------------------------------------------- |
| `POST /route`                | Forward a request to a registered service (called by the node) |
| `POST /register`             | Register a service: `{"service": "...", "endpoint": "..."}`    |
| `DELETE /register/{service}` | Remove a service                                               |
| `GET /services`              | List registered services                                       |
| `GET /health`                | Health check                                                   |

### Pattern 3: A2A (Agent-to-Agent)

A2A wraps your MCP services as [A2A skills](https://github.com/google/A2A), making them discoverable by A2A-compatible agents.

Run this command:

```bash
python -m a2a_serving.a2a_server --port 9004 --router http://127.0.0.1:9003
```

Then add it to your node configuration file:

```json
{
  "a2a_addr": "http://127.0.0.1",
  "a2a_port": 9004
}
```

The A2A server auto-discovers services from the MCP router and advertises them at `/.well-known/agent.json`.&#x20;

Remote nodes can interact with your A2A server like this:

```bash
# Fetch the remote peer's agent card (discover available skills)
curl http://127.0.0.1:9002/a2a/{peer_id}

# Send an A2A request
curl -X POST http://127.0.0.1:9002/a2a/{peer_id} \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "method": "message/send",
    "id": 1,
    "params": {
      "message": {
        "role": "user",
        "parts": [{"kind": "text", "text": "{\"service\":\"sentiment\",\"request\":{\"jsonrpc\":\"2.0\",\"method\":\"tools/list\",\"id\":1,\"params\":{}}}"}],
        "messageId": "msg-001"
      }
    }
  }'
```

The `messageId` is a client-assigned correlation ID. The text part must be a JSON-stringified MCP request matching the format the A2A server expects.

#### A2A Test Client

&#x20;A convenience script is included at `examples/python-client/a2a_client.py`:

```bash
# Local mode (talk to your own A2A server)
python examples/python-client/a2a_client.py --service sentiment --method tools/list

# Remote mode (route through the mesh to a remote peer)
python examples/python-client/a2a_client.py \
  --remote --peer-id {peer_id} \
  --service sentiment --method tools/list
```

### Adding a Custom Protocol

If MCP and A2A don't fit your needs, you can add your own protocol by implementing the `Stream` interface:

```go
type MyStream struct{}

func (s *MyStream) GetID() string { return "my-protocol" }

func (s *MyStream) IsAllowed(data []byte, metadata any) bool {
    var envelope map[string]interface{}
    if err := json.Unmarshal(data, &envelope); err != nil {
        return false
    }
    _, ok := envelope["my_protocol"]
    return ok
}

func (s *MyStream) Forward(metadata any, fromPeerId string) ([]byte, error) {
    // Process the message, return a response
    return responseBytes, nil
}
```

Register it in `internal/tcp/listen/listener.go` alongside the MCP and A2A streams. Messages matching your discriminator will be routed to your handler instead of the default queue.

### Sharing Your Service

Once running, other nodes need two things: **\[1]** your public key (so other nodes can find and connect to yours) and **\[2]** your service name, so they know what to call.&#x20;

You can share your public key and service name however you like.&#x20;

> *e.g., "I'm `37227e...` and I run a `sentiment` MCP service."*

### Built-in Examples

There are several example applications that are built into the AXL repository itself, each demonstrating an angle of the technology. You can find them here.

#### 1. Tensor Exchange

Send and receive PyTorch tensors between nodes using msgpack serialization.

> **File:** `examples/python-client/client.py`

**Modes:**

* `recv`: listen for incoming tensors
* `tensor`: send a tensor to a peer
* `bandwidth`: bandwidth test

```bash
pip3 install -r examples/python-client/requirements.txt

# On the receiving node
python3 examples/python-client/client.py recv --port 9002

# On the sending node
python3 examples/python-client/client.py tensor --port 9012 --peer <PEER_KEY>
```

#### 2. Remote MCP Server

Connect two nodes so one can call MCP tools hosted on the other. A2A is not required. The node's `/mcp/` endpoint talks directly to a remote peer's MCP router.

1. **Remote Machine (Sender)**

```bash
./node -config node-config.json

# Start the MCP router
python -m mcp_routing.mcp_router

# Start your MCP service(s) and register them with the router
```

2. **Local Machine (Receiver)**

```bash
./node -config node-config.json

# List tools on the remote peer's "weather" service
curl -X POST http://127.0.0.1:9002/mcp/<remote-public-key>/weather \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"tools/list","id":1,"params":{}}'
```

Both nodes must be able to reach at least one common peer (configured in `Peers`). They don't need direct connectivity.

#### 3. Remote A2A

Optimize integration by transforming MCP services into A2A skills using the optional A2A extension.&#x20;

1. **Remote Machine (Sender):**

```bash
python -m a2a_serving.a2a_server
```

2. **Local Machine (Receiver):**

```bash
python examples/python-client/a2a_client.py \
  --remote --peer-id <remote-public-key> \
  --service weather --method tools/list
```

The A2A server automatically detects and registers MCP services as skills, making access easy for agents that are already A2A-compatible.

#### 4. GossipSub

GossipSub-style pub/sub message propagation with IHAVE/IWANT lazy forwarding, built on `send`/`recv`.

> **File:** `examples/python-client/gossipsub/gossipsub.py`

#### 5. Convergecast

Tree-based data aggregation using the network's spanning tree. Nodes derive their position from `/topology` and aggregate results upward toward the root.

> **File:** `examples/python-client/convergecast.py`


# Troubleshooting

Common build, peering, and runtime issues with their causes and fixes.

## Fixing Common Issues

If something isn't working, you're probably hitting one of the issues below. This page covers the most frequent problems with building, running, and connecting AXL nodes, along with their fixes.

### Build Problems

These issues come up when compiling the node binary or generating keys before you ever run anything.

#### `ed25519` key generation fails on macOS

If `openssl genpkey` fails with "algorithm `ed25519` not found," it's because macOS ships with LibreSSL, which doesn't support `ed25519`.&#x20;

Install and use Homebrew's OpenSSL instead:

```bash
brew install openssl
/opt/homebrew/opt/openssl/bin/openssl genpkey -algorithm ed25519 -out private.pem
```

#### `Go 1.26+` build tag errors

The `gvisor.dev/gvisor` dependency has build tag conflicts with `Go 1.26`.&#x20;

Pin the toolchain for the build:

```bash
GOTOOLCHAIN=go1.25.5 go build -o node ./cmd/node/
```

Alternatively, install `Go 1.25.x` alongside your existing version:

```bash
go install golang.org/dl/go1.25.5@latest
go1.25.5 download
go1.25.5 build -o node ./cmd/node/
```

### Running the Node

Once the binary is built, these are the issues you might hit when starting or connecting to your node.

#### Connection refused on port 9002

The node process isn't running, or you're pointing at the wrong port. Confirm the node is alive and responsive:

```bash
curl http://127.0.0.1:9002/topology
```

{% hint style="info" %}
The default port is `9002`. If you changed it in your config file, use your configured port instead.
{% endhint %}

#### "Address already in use"

A previous node instance or another process is still holding the port. Find and kill it:

```bash
lsof -ti :9002 | xargs kill
```

{% hint style="info" %}
This is a common error that you will likely experience if you are testing out your application repeatedly with 2-4 terminals, especially if some are dedicated terminal instances vs. inside of Cursor or another IDE, etc.
{% endhint %}

### Peering and Connectivity

Peering issues show up as missing messages or an empty topology. Most of the time, the fix is a config change or a short wait.

#### "No connected peers found"

You'll see this error if your node hasn't established any peer connections.&#x20;

The most common causes are an empty `Peers` list in your config, unreachable or shut-down bootstrap nodes, or simply that peering hasn't had time to establish yet.&#x20;

Give it a few seconds, then you can check your current connections with `curl http://127.0.0.1:9002/topology` and look at the `peers` array.

#### Messages not arriving between local test nodes

First, verify both nodes are running. Then confirm you're using the correct public key in the `X-Destination-Peer-Id` header.&#x20;

When testing two nodes on the same machine, they need different `tcp_port` values to avoid conflicts. When communicating between separate machines, they should use the same `tcp_port`.

#### Messages not arriving between machines

Both nodes must be able to reach at least one common peer, whether that's a bootstrap node or a direct connection to each other.&#x20;

Double-check that the bootstrap address is correct, the port is open, and firewalls or port forwarding aren't blocking traffic.

### Python Client Issues

These apply when running the example scripts or any Python code that talks to a node's HTTP API.

#### Dependencie Issues

If you encounter this error (`ModuleNotFoundError: No module named 'requests'`) it means that dependcies are either not installed or there was a failure during installation.&#x20;

Run this command to install:&#x20;

```bash
pip3 install -r examples/python-client/requirements.txt
```

#### urllib3 `NotOpenSSLWarning`

This is a harmless warning on macOS caused by a LibreSSL/OpenSSL mismatch in urllib3. Everything works correctly. You can safely ignore it.

### Quick Reference

| Symptom                      | Fix                                         |
| ---------------------------- | ------------------------------------------- |
| *Can't generate ed25519 key* | Use `/opt/homebrew/opt/openssl/bin/openssl` |
| *Build fails (Go 1.26)*      | `GOTOOLCHAIN=go1.25.5 go build ...`         |
| *Connection refused :9002*   | Start the node                              |
| *Port conflict*              | `lsof -ti :PORT \| xargs kill`              |
| *No peers*                   | Check `Peers` in config, wait a few seconds |
| *Python import errors*       | `pip3 install -r requirements.txt`          |


# Overview

A live, open test network for decentralised machine learning.

The Gensyn Public Testnet was launched in March 2025. &#x20;

It brings persistent identity to decentralised AI systems and provides a network to track participation, maintain attribution, make payments, coordinate remote execution, verify untrusted operations, log decentralised training runs, crowdfund large-scale training efforts, and more.&#x20;

## What's Live Now

The current focus is on Delphi, a permissionless prediction market platform where anyone can create markets on any topic, settled by AI, with support for verifiable settlement through Gensyn's [Reproducible Execution Environment (REE).](/tech)

[Delphi](https://app.delphi.fyi/) is live on testnet and will be the first application launching on Gensyn Mainnet.

#### Previous Phases

Earlier phases of the testnet included:

* **RL Swarm:** Collaborative post-training via reinforcement learning reasoning over the internet. RL Swarm demonstrated decentralized model improvement through swarm participation. RL Swarm & all Gensyn-hosted nodes have been paused.&#x20;
* **BlockAssist & CodeAssist:** Applications that demonstrated how ML models can train directly on human interactions to create personalized, privacy-preserving models. Both have been sunset as focus consolidates around Delphi. All historical data remains on chain.

### Get Involved

| **Community Members** | Stay up to date on progress, provide feedback, and discuss future developments in the [Discord.](https://discord.com/invite/gensyn)                                                                                           |
| --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Traders**           | Explore active prediction markets on Delphi, buy and sell positions on outcomes, and help stress-test the platform ahead of Mainnet.                                                                                          |
| **Market Creators**   | Create your own prediction markets on any topic, configure AI settlement, and trade outcomes using valueless tokens on [Delphi](https://app.delphi.fyi/).                                                                     |
| **Developers**        | Build on top of the Gensyn network and contribute to the ecosystem as new infrastructure and applications come online.                                                                                                        |
| **ML Researchers**    | Deploy your own swarm for others to join, train on new datasets, solve new problems, construct new objectives, incentivise participation and explore the space of decentralised AI with an entirely new infrastructure stack. |

### Architecture

The network is a custom Ethereum Rollup dedicated to machine learning and integrated with off-chain execution, verification, and communication frameworks.&#x20;

#### Roadmap

The Testnet has followed a phased rollout, with each phase introducing new features derived from the infrastructure that Gensyn builds. This has given the community a chance to stress-test the protocol under real-world conditions and provide feedback on features and direction along the way.

The current phase is focused on Delphi, the first application launching on Gensyn Mainnet.&#x20;

As the network progresses toward Mainnet, more applications will become available covering the full ML lifecycle from pre-training through to inference. The final phase will culminate in the Mainnet launch, *with real economic value transacted via the chain.*


# RL Swarm (Paused)

RL Swarm lets anyone, anywhere, join and participate in a distributed reinforcement learning system that learns faster together than alone.

{% hint style="success" %}
There are no official swarms running right now.&#x20;

Please check back later if you're interested in participating in a global, decentralised, crowd-sourced training run or feel free to join a community-owned swarm.&#x20;

Alternatively, you can explore [Delphi](https://app.delphi.fyi/), a set of tools for creating information markets.
{% endhint %}

## What is RL Swarm?

RL Swarm is a decentralized training environment where reinforcement learning (RL) agents cooperate over the internet instead of inside a single datacenter.

Each node runs a local language model that participates in multi-stage RL reasoning games, which involves answering, critiquing, and revising solutions alongside *peers*.

By connecting an RL Swarm node to an on-chain identity on the Gensyn Testnet, every participant’s contributions are logged and verifiable. This enables a persistent view of collective training performance across the network.

<div data-with-frame="true"><figure><img src="/files/xf1XSjaseo3s6U7cM1oE" alt=""><figcaption></figcaption></figure></div>

### Why It Exists

Traditional RL research happens inside isolated labs using centralized GPU clusters. These environments are **expensive**, **inaccessible**, and **closed** by design.

RL Swarm was built to show that reinforcement learning can happen collaboratively and trustlessly across independent machines, powered by Gensyn’s decentralized execution and verification layers.

By turning multi-agent RL into a networked experiment, RL Swarm demonstrates:

* How peer-to-peer learning can outperform solo training.
* How collective reasoning can improve model quality and efficiency.
* How the Gensyn Protocol’s primitives, **\[1]** execution, **\[2]** verification, **\[3]** communication, and **\[4]** coordination, work together in a live environment.

{% hint style="info" %}
RL Swarm forms the foundation of Phase 0 of the Gensyn Testnet, providing the first public demonstration of decentralized AI collaboration in action.
{% endhint %}

#### What You Can Do With It

Anyone can clone the RL Swarm repository, run a node locally, and connect to the live swarm.

In the swarm, each node participates in four stages of RL:&#x20;

{% stepper %}
{% step %}

### Initialize a Local Model

Load a small open-source model (for example, *Qwen 2.5 1.5B*) to act as your local learning agent.
{% endstep %}

{% step %}

### Join a Shared Reasoning Task

Connect to the active swarm and take part in multi-stage reasoning challenges, like solving math, logic, or coding problems collaboratively with other nodes.
{% endstep %}

{% step %}

### Communicate & Critique

Exchange answers, feedback, and critiques with peers using a decentralized gossip protocol that enables cross-node communication.
{% endstep %}

{% step %}

### Learn & Update Collectively

Incorporate reinforcement signals from the swarm’s collective feedback to refine your model and improve global performance over time.
{% endstep %}
{% endstepper %}

When a session (“episode”) ends, the node’s updated weights can be uploaded to a model hub like Hugging Face or logged directly to the Gensyn Testnet, which creates and contributes to a [transparent record of the decentralized training progress.](https://dashboard.gensyn.ai/)

#### Ready?

Head over to [Getting Started](/testnet/rl-swarm/getting-started) section and select your platform for OS-specific set-up guides, or browse our [Troubleshooting](/testnet/rl-swarm/troubleshooting) documentation.


# How It Works

Learn how RL Swarm functions under the hood, from GenRL’s modular architecture to multi-agent learning, coordination, and reward cycles.

## Reinforcement Learning

RL Swarm is built on a layered architecture that enables distributed reinforcement learning across independent nodes. Understanding how these layers fit together helps clarify both the system's capabilities and how it has evolved.

#### The Layered Stack

<table data-view="cards"><thead><tr><th></th><th></th></tr></thead><tbody><tr><td><strong>RL Swarm</strong></td><td>The orchestrator for distributed reinforcement learning environments. It manages node connections, identity, and network coordination across the peer-to-peer swarm.</td></tr><tr><td><strong>Gen RL</strong></td><td>The open-source reinforcement learning SDK that powers swarm environments. GenRL provides the modular framework  that enables multi-agent, multi-stage RL with decentralized coordination.</td></tr><tr><td><strong>CodeZero</strong></td><td>The active cooperative coding environment where models act as Proposers, Solvers, and Evaluators in a closed learning loop. CodeZero replaces Reasoning Gym as the current RL Swarm environment.</td></tr></tbody></table>

{% hint style="success" %}
All active swarms now use CodeZero as the default environment. [Legacy environments ](/testnet/rl-swarm/how-it-works/legacy-environments)such as Reasoning Gym are archived.
{% endhint %}

#### From Reasoning Gym to CodeZero

Earlier versions of RL Swarm used a math and logic environment known as Reasoning Gym.

Starting with the [November 2025 release](https://github.com/gensyn-ai/rl-swarm/releases), this has been replaced by **CodeZero,** a new cooperative coding environment built on the same peer-to-peer framework.

CodeZero extends the RL Swarm framework onto the same decentralized network and identity system, but introduces a *new task domain* focused on programming and debugging, where task success is scored using model-based or execution-based reward functions instead of rule-based logical verification.

{% hint style="success" %}
**As of November 12th, 2025, CodeZero replaces Reasoning Gym as the active RL Swarm environment.** Node setup, identity, and network connection remain identical.
{% endhint %}

#### Reinforcement Learning in a Distributed Setting

Reinforcement Learning (RL) enables agents to learn optimal actions through feedback. RL Swarm extends this paradigm into a collaborative, distributed setting, where many agents train and critique *together* instead of working *alone*.

<div data-with-frame="true"><figure><img src="/files/IsGk9MzNLKQABbHdIW6L" alt=""><figcaption></figcaption></figure></div>

### RL in Action

Reinforcement Learning (RL) continues to prove its power in solving complex problems, from optimizing systems to training intelligent agents.&#x20;

As we push the boundaries, especially in scenarios involving multiple interacting agents, the need for robust and flexible environments becomes even more critical.&#x20;

> Our core philosophy is to provide a highly customisable and scalable platform that addresses the limitations often encountered when building multi-agent RL systems.

Many existing frameworks tend to be either centralized in their approach or simply don't offer native support for multi-agent settings, which can lead to significant development hurdles.

RL Swarm, powered by GenRL (short for “General Reinforcement Learning”), is a framework built to simplify and accelerate the development of advanced, multi-agent reinforcement learning environments.

#### GenRL

A key highlight of GenRL is its native support for horizontally scalable, multi-agent, multi-stage RL with decentralised coordination and communication.&#x20;

Unlike frameworks that might force a centralised control scheme, GenRL is built for environments where agents can learn and interact in a distributed, open, and permissionless manner.

### Four Components

At its heart, GenRL puts the user in control of defining the entire 'game' agents play. We've built an intuitive, modular architecture that orchestrates the complete RL cycle, allowing you to tailor every aspect of your environment.&#x20;

This is achieved through four well-defined components: **\[1]** DataManager, **\[2]** RewardManager, **\[3]** Trainer, and **\[4]** GameManager.

#### 1. DataManager

> Manages data and initializes each training round.

The DataManager defines and organizes the dataset your RL environment uses, whether it’s a large quantity of text, a labeled image collection, or a specialized format like a chessboard configuration.&#x20;

It makes sure the system has the right inputs to learn and perform tasks effectively by 'managing' the given data.&#x20;

By choosing and structuring data precisely, you directly shape the RL environment’s scope, performance, and applicability, since the nature and *quality* of the dataset determine the agent’s learning efficiency and potential outcomes. For example, richer datasets can improve robustness and generalization, while narrow datasets may constrain learning to specific scenarios.

#### 2. RewardManager

> Defines custom reward logic.&#x20;

The RewardManager defines and implements *model-based reward evaluation,* using frozen evaluators to score predicted correctness instead of rule-based checks.

By translating outcomes into feedback signals, it directly shapes the objective of your RL environment, influencing what behaviors are encouraged and how policies evolve over time.

#### 3. Trainer

> The Trainer applies algorithms such as **GRPO (Group Relative Policy Optimization)** to update solver policies from evaluator-scored rollouts.

The Trainer component handles both learning and rollout generation: it manages the core training loop, i.e., applying your chosen RL paradigm (e.g. policy gradient optimization, value-function approximation, etc.) to update the policy.&#x20;

It also produces the rollouts that drive agent–environment interactions to make sure the experiences needed for each subsequent training step are generated and ingested without a hitch.

#### 4. GameManager

> Coordinates data flow and communication between multiple agents.

The GameManager coordinates the data flow efficiently and effectively among the key modules you define, so there is smooth interaction between these modules and the other agents within the multi-agent swarm. It acts as a central hub that manages communications, synchronizes processes, and facilitates the exchange of information.&#x20;

{% hint style="success" %}
GenRL allows module customization for tailored learning goals and agent interactions, supporting scalable multi-agent RL solutions. It works with any environment, including **CodeZero** and legacy ones like Reasoning Gym.
{% endhint %}

### Framework Defined Progression

The game progresses on a per-round basis.&#x20;

1. Each round, the DataManager initializes the round data, triggering the game’s stages.&#x20;
2. For every stage, rollouts are generated, added to the game state, and shared with the swarm.&#x20;
3. Once the agent completes all predefined stages, rewards are evaluated and policies are updated.&#x20;

The user retains full control over this process within the `Trainer.train` method, allowing policy updates on either a per-stage or per-round basis.

<div data-with-frame="true"><figure><img src="/files/s28ZbGdauojZu8fs6lcR" alt=""><figcaption></figcaption></figure></div>


# CodeZero

Learn about CodeZero, the cooperative coding environment powering RL Swarm.

<div data-with-frame="true"><figure><img src="/files/0FOqTSZCohmgdDdVvgLE" alt=""><figcaption></figcaption></figure></div>

## Overview

CodeZero is the active RL Swarm environment that transforms distributed reinforcement learning into a cooperative coding ecosystem, a "society of models" where agents collaborate to solve programming challenges.

Unlike traditional RL environments that rely on external verification, CodeZero creates a closed learning loop where models generate problems, solve them, and evaluate solutions, all within the same peer-to-peer network.

#### What Makes CodeZero Different

CodeZero introduces a new task domain focused on programming challenges evaluated by model-based reward functions.&#x20;

This represents a shift from the previous **Reasoning Gym** environment, which focused on math and logic tasks verified by symbolic correctness checks.

In CodeZero, models participate as **Proposers**, **Solvers**, and **Evaluators**, each playing a distinct role in the collective learning process. This multi-agent architecture enables dynamic difficulty adjustment, peer-to-peer knowledge sharing, and continuous improvement through reinforcement learning.

### Roles

In CodeZero, **\[1]** Proposers, **\[2]** Solvers, and **\[3]** Evaluators collaborate to create, address, and review programming challenges, forming an ecosystem where models instruct, critique, and enhance one another.

* **Proposers:** Generate coding problems and unit tests, adjusting difficulty dynamically based on solver performance. Proposers create challenges that adapt to the swarm's current capabilities, ensuring continuous learning opportunities.
* **Solvers:** Attempt coding challenges, learn locally through RL, and share rollouts with peers. Solvers exchange solutions to promote diversity and accelerate collective learning across the network.
* **Evaluators:** Frozen models that assess correctness and assign rewards. Evaluators use rule-based assessment to score submissions without executing code, ensuring safety and scalability.

#### Training Loop

The CodeZero training cycle follows a structured progression:

{% stepper %}
{% step %}

### Question Generation

Proposers create coding tasks and tests, drawing from their learned patterns and difficulty adjustment logic.
{% endstep %}

{% step %}

### Sampling

Solvers draw tasks from proposers or from small external datasets (MBPP, CodeContests) for fallback stability.
{% endstep %}

{% step %}

### Rollout Sharing

Solvers exchange solutions with peers to promote diversity and accelerate learning across the swarm.
{% endstep %}

{% step %}

### Evaluation

Evaluators score rollouts using a frozen model (no code execution) to assess structure, formatting, and predicted correctness.
{% endstep %}

{% step %}

### Reward Assignment

Scoring combines structure, formatting, and predicted correctness into a composite reward signal.
{% endstep %}

{% step %}

### Difficulty Adjustment

Proposers adjust challenge levels based on solver success rates, maintaining an optimal learning curve.
{% endstep %}

{% step %}

### Policy Update

Solvers optimize locally via GRPO (Group Relative Policy Optimization), incorporating feedback from the swarm's collective experience.
{% endstep %}
{% endstepper %}

### Technical Details

This section outlines the datasets, model architectures, metrics, and optimization strategies that enable CodeZero to learn safely and autonomously across a decentralized network of peers.

#### Datasets

CodeZero uses two primary datasets for fallback stability and baseline challenges:

* **MBPP** **(Mostly Basic Python Problems)**: A curated set of Python programming problems with test cases.
* **CodeContests:** A collection of competitive programming challenges used for additional task diversity.

These datasets provide a stable foundation when proposer-generated tasks need supplementation.

#### Models

CodeZero employs the Qwen model family across different roles:

* **Qwen 2.5 Coder (0.5B and 1.5B):** Used for Solvers, enabling efficient local learning and rollout generation.
* **Qwen 3 (4B):** Used for Proposers and Evaluators, providing stronger generation and assessment capabilities.

#### Metrics

CodeZero tracks performance using two key metrics which provide complementary views of model performance and learning progress.

* **average\@k:** Average performance across `k` attempts, measuring consistency.
* **pass\@k:** Probability of at least one correct solution in `k` attempts, measuring capability.

#### Evaluation Safety

CodeZero uses a **rule-based evaluator** that avoids code execution. Instead, evaluators assess submissions based on:

* Code structure and formatting
* Predicted correctness (via frozen model inference)
* Adherence to problem requirements

#### Dynamic Difficulty

Proposers maintain a **5-level difficulty system** with thresholds for adjustment:

* Difficulty levels adapt based on solver success rates
* Thresholds trigger automatic adjustment to maintain optimal challenge levels
* This ensures the swarm continuously faces appropriately challenging tasks

#### Policy Optimization

Solvers use **GRPO (Group Relative Policy Optimization)** for local policy updates:

* Incorporates feedback from the swarm's collective experience
* Enables efficient learning from peer rollouts
* Maintains local autonomy while benefiting from network-wide signals

### Integration with RL Swarm

CodeZero runs on the same RL Swarm infrastructure as previous environments:

* **Same network:** Uses the existing peer-to-peer gossip protocol
* **Same identity:** Node identities and `swarm.pem` files work identically
* **Same setup:** No changes required to node installation or configuration

### Next Steps

If you're ready to test out RL Swarm in the latest environmental iteration, CodeZero, check out the [Getting Started](/testnet/rl-swarm/getting-started) guide or learn about [node management](/testnet/rl-swarm/node-management) and [troubleshooting](/testnet/rl-swarm/troubleshooting) steps.&#x20;


# Legacy Environments

An archive of legacy RL Swarm environments, including Reasoning Gym, which has been replaced by CodeZero.

## Overview

Before CodeZero, RL Swarm used an early research environment called **Reasoning Gym**.

Reasoning Gym focused on math and logic tasks verified by symbolic correctness checks. It provided a foundation for distributed reinforcement learning research and demonstrated the viability of peer-to-peer RL training.

#### Deprecation

{% hint style="danger" %}
This environment is now **deprecated and archived**.
{% endhint %}

This environment has been deprecated and replaced by CodeZero.

All current nodes now run CodeZero automatically, and no manual migration is required beyond a simple `git pull` command to update. Existing nodes retain their same network, identity, and connection structure during the transition.

#### Archived Resources

* [Reasoning Gym Repository](https://github.com/gensyn-ai/reasoning-gym): Original implementation and research codebase

#### Migration Notes

If you have documentation or scripts referencing Reasoning Gym:

* **Node setup:** No changes required. CodeZero uses the same installation process.
* **Identity files:** `swarm.pem` files remain compatible.
* **Network connection:** Same peer-to-peer protocol and gossip mechanism.

The transition from Reasoning Gym to CodeZero is transparent to end users, as both environments run on the same RL Swarm infrastructure.

{% hint style="success" %}
RL Swarm's architecture is designed to support multiple environments.&#x20;

As new environments are developed, they will be documented here alongside CodeZero.
{% endhint %}


# Getting Started

Browse resources for getting started with RL Swarm.

{% embed url="<https://github.com/gensyn-ai/rl-swarm>" %}

## Overview

RL Swarm is a peer-to-peer reinforcement-learning swarm you can run on a laptop or a GPU server. This page is an orientation & navigation hub.&#x20;

Start by picking your OS below and follow the platform guide. If something breaks, start at [Troubleshooting](/testnet/rl-swarm/troubleshooting) or join the [Gensyn Discord](https://discord.com/invite/gensyn) for help.

### Before you Begin

RL Swarm is available across several environments: [Windows (via WSL 2)](/testnet/rl-swarm/getting-started/windows-wsl-2), [Linux (Ubuntu 22.04+)](/testnet/rl-swarm/getting-started/linux), and [macOS (Intel and Apple Silicon)](/testnet/rl-swarm/getting-started/macos).&#x20;

### System Requirements

* A 64-bit arm64 or x86 CPU with at least 32 GB RAM, or an officially supported NVIDIA GPU (3090, 4090, 5090, A100, H100)
* Between **Python 3.10** and **Python 3.13**
* [Docker](https://www.docker.com/) and [Git](https://git-scm.com/install/) installed & configured
* Stable internet connection

{% hint style="danger" %}
Python 3.14 is incompatible with RL Swarm.
{% endhint %}

#### Accounts & Access

* **Hugging Face account:** You’ll need a Write-access API token to participate in the swarm.
* **Gensyn Testnet account:** Automatically created when you first log in through your browser during setup.

### Supported Platforms & Installation Paths

<table data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>Windows (WSL 2)</strong></td><td>Run RL Swarm via Docker inside WSL 2 for a consistent Linux-based environment.</td><td><a href="/pages/MsM6T9tIHiYzVnGbjol4">/pages/MsM6T9tIHiYzVnGbjol4</a></td></tr><tr><td><strong>Linux (Ubuntu 22.04+)</strong></td><td>Recommended for most users. Run RL Swarm directly or inside Docker.</td><td><a href="/pages/BqybKiFUX2bJJ2fS6BPV">/pages/BqybKiFUX2bJJ2fS6BPV</a></td></tr><tr><td><strong>macOS (Intel &#x26; Apple Silicon)</strong></td><td>Best for M1/M2/M3 users with Apple Silicon. <em>Supports CPU-only training.</em></td><td><a href="/pages/K7RaUCXgt9PBYMIL7L5x">/pages/K7RaUCXgt9PBYMIL7L5x</a></td></tr></tbody></table>

#### FAQ

<details>

<summary>Can I run RL Swarm on my laptop?</summary>

Yes. If you don’t have a GPU, you’ll run in CPU mode. It will be slower, but you’ll still participate in the swarm.

</details>

<details>

<summary>What happens when I log in?</summary>

You’ll create an on-chain identity (via Alchemy) and a local `swarm.pem` file that identifies your peer.

</details>

<details>

<summary>What if I want to switch machines?</summary>

Copy your `swarm.pem` file to the new machine. That preserves your peer identity and animal name.

</details>

<details>

<summary>What if I encounter errors or crashes?</summary>

Check the [Troubleshooting](/testnet/rl-swarm/troubleshooting) guide first, or visit our [Discord](https://discord.com/invite/gensyn) for help.

</details>

#### Resources

If you need additional set-up or post-launch support, you can [open a ticket](https://github.com/gensyn-ai/rl-swarm/issues) or [visit our Discord.](https://discord.com/invite/gensyn)

| [Troubleshooting Guide](/testnet/rl-swarm/troubleshooting) | Common setup issues and fixes.                                     |
| ---------------------------------------------------------- | ------------------------------------------------------------------ |
| [Gensyn Discord](https://discord.gg/gensyn)                | Ask questions, report issues, or chat with the team.               |
| [Gensyn Blog](https://gensyn.ai/blog)                      | Learn more about the AI Prediction Market and current experiments. |
| [Gensyn Testnet Dashboard](https://dashboard.gensyn.ai)    | Track your peer’s training and on-chain activity.                  |


# Windows (WSL 2)

Spin up your node and participate in the swarm in a Windows (WSL 2) environment.

{% hint style="success" %}
**Updating RL Swarm to the CodeZero Environment**

Run `git pull`, then restart your swarm.

1. **Docker users:** Run `docker-compose run --rm --build -Pit swarm-cpu` or `docker-compose run --rm --build -Pit swarm-gpu`  &#x20;
2. **Script users:** Rebuild your venv by running: `rm -rf .venv && python -m venv .venv && source .venv/bin/activate`
   {% endhint %}

## Overview

This guide walks you through setting up RL Swarm on Windows using WSL 2 (Windows Subsystem for Linux).&#x20;

This allows you to run a native Linux environment compatible with Docker and Python, ensuring consistent results across platforms.

### Prerequisites

Make sure your system meets the minimum requirements and that you also have any additional dependencies installed.&#x20;

* A WSL 2 environment
* A 64-bit arm64 or x86 CPU with at least 32 GB RAM, or an officially supported NVIDIA GPU (3090, 4090, 5090, A100, H100)
* Python 3.10+
* [Docker](https://www.docker.com/) installed and configured
* Stable internet connection
* [Git](https://git-scm.com/install/) installed

### Installing WSL 2

1. Open **PowerShell** as Administrator.
2. Install WSL using the following command:

```bash
wsl --install
```

3. Restart your computer when prompted.
4. After reboot, open the Microsoft Store and install Ubuntu.
5. Launch Ubuntu and set up a username and password when prompted.

### Installing Dependencies

Once your Ubuntu environment is installed and open, install the required system dependencies.

Run the following commands one at a time to install Python, Docker, Git, and supporting packages:

```bash
sudo apt update
```

```bash
sudo apt install -y python3 python3-venv python3-pip curl wget git docker.io build-essential
```

#### Docker

Make sure you have Docker installed and the Docker daemon is running on your machine. To do that, follow [these instructions](https://docs.docker.com/get-started/get-docker/) according to your OS. Make sure you allot sufficient memory to the Docker containers.&#x20;

For example, if you are using Docker Desktop, this can be done by going to **Docker Desktop Settings > Resources > Advanced > Memory Limit**, and increasing it to the *maximum* possible value.

If you installed Docker via the command line, you can start it and spin up containers by running:

```bash
sudo service docker start
```

#### Clone the RL Swarm Repository

1. Navigate to your home directory in your WSL 2 environment and clone the RL Swarm GitHub repository using this command:

```bash
git clone https://github.com/gensyn-ai/rl-swarm.git
```

2. Then move into the project folder:

```bash
cd rl-swarm
```

{% hint style="info" %}
WSL paths differ from Windows (e.g., /home/user vs C:\Users\\). Make sure to double-check all filepaths if you're not copy-pasting from this guide.
{% endhint %}

#### Run RL Swarm

Depending on your hardware, you can run RL Swarm in either **CPU** or **GPU** mode.

{% tabs %}
{% tab title="CPU-Only" %}
For CPU-only setup (the default on most Windows machines):

```bash
docker compose run –rm –build -Pit swarm-cpu
```

{% endtab %}

{% tab title="GPU-Only" %}
For GPU-enabled setup (requires WSL and an NVIDIA GPU):

```bash
docker compose run –rm –build -Pit swarm-gpu
```

{% hint style="warning" %}
GPU support requires NVIDIA drivers and WSL integration enabled in Docker Desktop.
{% endhint %}
{% endtab %}
{% endtabs %}

<div data-with-frame="true"><figure><img src="/files/EHNc8sVKwTONkyBv7E1S" alt=""><figcaption></figcaption></figure></div>

{% hint style="warning" %}
If you encounter an error saying “`docker-compose: command not found`”, use “`docker compose`” (without the hyphen) instead.
{% endhint %}

#### Log into RL Swarm

When you start RL Swarm, it will open a browser window automatically pointing to `http://localhost:3000.`

{% hint style="info" %}
If the browser does not open automatically, navigate to that address manually.
{% endhint %}

You will see the RL Swarm login screen powered by Alchemy. From here, you can log in using your preferred method such as Google or email.

<div data-with-frame="true"><figure><img src="/files/StTNzWiONZPtqfor3SFS" alt=""><figcaption></figcaption></figure></div>

After login, a `swarm.pem` file will be created in your repository folder. This identifies your peer on the Gensyn Testnet.

***

### Joining the new RL-Swarm Environment (CodeZero)

#### Updating via git pull

First, start by running `git pull` to fetch the latest changes to RL Swarm.&#x20;

#### Launching after Updating

There are two launch paths.

1. **Launching with Docker:** If you are using Docker, you can restart your swarm after updating via `git pull` by using one of the two following commands:

```bash
docker-compose run --rm --build -Pit swarm-cpu
docker-compose run --rm --build -Pit swarm-gpu
```

2. **Launching with Shell Script:** If you are using the `run_rl_swarm.sh` script, you must remove your old virtual environment and create a fresh one:

```bash
rm -rf .venv
python -m venv .venv
source .venv/bin/activate
/run_rl_swarm.sh
```

{% hint style="success" %}
In both cases, restart your swarm after updating.
{% endhint %}

***

#### Huggingface

If you would like to upload your model to Hugging Face, enter your Hugging Face access token when prompted. You can generate one from your Hugging Face account, under [Access Tokens](https://huggingface.co/docs/hub/en/security-tokens).

#### Verify your Node

Once you are logged in, your node will begin training automatically.

You can verify that your peer has successfully connected by visiting the [Gensyn Testnet Dashboard.](https://dashboard.gensyn.ai/) Your peer should appear in the active swarm list, and you can monitor training progress in real time.

<div data-with-frame="true"><figure><img src="/files/sYzgGLDm5j5JD376AjXw" alt=""><figcaption></figcaption></figure></div>

#### Optional: Experimental Mode (No Docker)

If you want to experiment with the [GenRL](https://github.com/gensyn-ai/genrl) library or the [configurable parameters](https://github.com/gensyn-ai/rl-swarm/blob/main/rgym_exp/config/rg-swarm.yaml), we recommend you run RL Swarm via shell script:

```
python3 -m venv .venv
source .venv/bin/activate
./run_rl_swarm.sh
```

{% hint style="info" %}
This method gives you access to GenRL’s configuration parameters and experimental features.
{% endhint %}

To learn more about experimental mode, check out our [getting started guide](https://github.com/gensyn-ai/genrl/blob/main/getting_started.ipynb) on Github.

### Troubleshooting

Refer to the multi-platform [RL Swarm Troubleshooting guide](/testnet/rl-swarm/troubleshooting) for unblocking information and fixes to common set-up issues.

{% hint style="success" %}
If you need additional support, you can [open a ticket](https://github.com/gensyn-ai/rl-swarm/issues) or [visit our Discord.](https://discord.com/invite/gensyn)
{% endhint %}


# Linux

Spin up your node and participate in the swarm in a Linux (Ubuntu 22.04+) environment.

{% hint style="success" %}
**Updating RL Swarm to the CodeZero Environment**

Run `git pull`, then restart your swarm.

1. **Docker users:** Run `docker-compose run --rm --build -Pit swarm-cpu` or `docker-compose run --rm --build -Pit swarm-gpu`
2. **Script users:** Rebuild your venv by running: `rm -rf .venv && python -m venv .venv && source .venv/bin/activate`
   {% endhint %}

## Overview

This guide walks you through setting up RL Swarm on a Linux machine.

Linux provides the most stable and performant environment for RL Swarm, especially for users running NVIDIA GPUs. You can run RL Swarm via Docker for simplicity or directly through Python for more advanced experimentation.

### Prerequisites

Make sure your system meets the minimum requirements and that you also have any additional dependencies installed.&#x20;

* Ubuntu 22.04+
* A 64-bit arm64 or x86 CPU with at least 32 GB RAM, or an officially supported NVIDIA GPU (3090, 4090, 5090, A100, H100)
* Python 3.10+
* [Docker](https://www.docker.com/) installed and configured
* Stable internet connection
* [Git](https://git-scm.com/install/) installed

### Installing Dependencies

First, update your package lists and install all required dependencies:

```bash
sudo apt update
```

```bash
sudo apt install -y python3 python3-venv python3-pip curl wget git docker.io build-essential
```

Next, start and enable the Docker service so it launches automatically on boot using the following commands:

```bash
sudo systemctl enable docker
```

```bash
sudo systemctl start docker
```

{% hint style="success" %}
You can verify Docker is running with `sudo docker info`.&#x20;

If this command returns information about the Docker daemon, it's running successfully.&#x20;
{% endhint %}

#### Configuring Docker

If you are using Docker Desktop, ensure that enough memory is allocated to containers. You can do this by going to **Settings > Resources > Advanced > Memory Limit** and setting the memory value to the highest available value.

{% hint style="info" %}
If you installed Docker through `apt`, make sure the daemon is active (as above) before running RL Swarm.
{% endhint %}

To check if you can run containers, run the following command to print a 'hello' message. If you see a success message, your installation is good to go.

```bash
sudo docker run hello-world
```

#### Clone the RL Swarm Repository

1. Navigate to your home directory and clone the RL Swarm GitHub repository using this command:

```bash
git clone https://github.com/gensyn-ai/rl-swarm.git
```

2. Then move into the project folder:

```bash
cd rl-swarm
```

### Run RL Swarm

Depending on your hardware, you can run RL Swarm in either **CPU** or **GPU** mode.

{% tabs %}
{% tab title="CPU-Only" %}
For CPU-only setup:

```bash
docker compose run –rm –build -Pit swarm-cpu
```

{% endtab %}

{% tab title="GPU-Only" %}
For GPU-enabled setup (officially supported on NVIDIA devices):

```bash
docker compose run –rm –build -Pit swarm-gpu
```

{% hint style="warning" %}
GPU mode requires NVIDIA drivers and CUDA toolkit properly installed.
{% endhint %}
{% endtab %}
{% endtabs %}

<div data-with-frame="true"><figure><img src="/files/j6AtKl1L0GxVxOczKkQu" alt=""><figcaption></figcaption></figure></div>

{% hint style="warning" %}
If you encounter an error saying “`docker-compose: command not found`”, use “`docker compose`” (without the hyphen) instead.
{% endhint %}

#### Log into RL Swarm

When you start RL Swarm, it will open a browser window automatically pointing to `http://localhost:3000.`

{% hint style="info" %}
If the browser does not open automatically, navigate to that address manually.
{% endhint %}

You will see the RL Swarm login screen powered by Alchemy. From here, you can log in using your preferred method such as Google or email.

<div data-with-frame="true"><figure><img src="/files/DBcxMmdamSwmhLg05yKC" alt=""><figcaption></figcaption></figure></div>

After login, a `swarm.pem` file will be created in your repository folder. This identifies your peer on the Gensyn Testnet.

***

### Joining the new RL-Swarm Environment (CodeZero)

#### Updating via git pull

First, start by running `git pull` to fetch the latest changes to RL Swarm.&#x20;

#### Launching after Updating

There are two launch paths.

1. **Launching with Docker:** If you are using Docker, you can restart your swarm after updating via `git pull` by using one of the two following commands:

```bash
docker-compose run --rm --build -Pit swarm-cpu
docker-compose run --rm --build -Pit swarm-gpu
```

2. **Launching with Shell Script:** If you are using the `run_rl_swarm.sh` script, you must remove your old virtual environment and create a fresh one:

```bash
rm -rf .venv
python -m venv .venv
source .venv/bin/activate
/run_rl_swarm.sh
```

{% hint style="success" %}
In both cases, restart your swarm after updating.
{% endhint %}

***

#### Huggingface

If you would like to upload your model to Hugging Face, enter your Hugging Face access token when prompted. You can generate one from your Hugging Face account, under [Access Tokens](https://huggingface.co/docs/hub/en/security-tokens).

#### Verify your Node

Once logged in, your node will begin training automatically.

You can verify that your peer has successfully connected by visiting the [Gensyn Testnet Dashboard.](https://dashboard.gensyn.ai/) Your peer should appear in the active swarm list, and you can monitor training progress in real time.

<div data-with-frame="true"><figure><img src="/files/sYzgGLDm5j5JD376AjXw" alt=""><figcaption></figcaption></figure></div>

#### Optional: Experimental Mode (No Docker)

If you want to experiment with the [GenRL](https://github.com/gensyn-ai/genrl) library or the [configurable parameters](https://github.com/gensyn-ai/rl-swarm/blob/main/rgym_exp/config/rg-swarm.yaml), we recommend you run RL Swarm via shell script:

```
python3 -m venv .venv
source .venv/bin/activate
./run_rl_swarm.sh
```

{% hint style="info" %}
This method gives you access to GenRL’s configuration parameters and experimental features.
{% endhint %}

To learn more about experimental mode, check out our [getting started guide](https://github.com/gensyn-ai/genrl/blob/main/getting_started.ipynb) on Github.

### Troubleshooting

Refer to the multi-platform [RL Swarm Troubleshooting guide](/testnet/rl-swarm/troubleshooting) for unblocking information and fixes to common set-up issues.

{% hint style="success" %}
If you need additional support, you can [open a ticket](https://github.com/gensyn-ai/rl-swarm/issues) or [visit our Discord.](https://discord.com/invite/gensyn)
{% endhint %}


# macOS

Spin up your node and participate in the swarm in a macOS environment.

{% hint style="success" %}
**Updating RL Swarm to the CodeZero Environment**

Run `git pull`, then restart your swarm.

1. **Docker users:** Run `docker-compose run --rm --build -Pit swarm-cpu`
2. **Script users:** Rebuild your venv by running: `rm -rf .venv && python -m venv .venv && source .venv/bin/activate`
   {% endhint %}

## Overview

This guide walks you through setting up RL Swarm on macOS.

RL Swarm can run on both Intel and Apple Silicon (M1, M2, or M3) Macs. On macOS, RL Swarm runs in CPU-only mode by default, as NVIDIA GPUs are not supported on this platform.

### Prerequisites

Make sure your system meets the minimum requirements and that you also have any additional dependencies installed.&#x20;

* macOS Monterey (12.0) or newer
* A 64-bit arm64 or x86 CPU with at least 32 GB RAM, or an officially supported NVIDIA GPU (3090, 4090, 5090, A100, H100)
* Python 3.10+
* [Docker](https://www.docker.com/) installed and configured
* Stable internet connection
* [Git](https://git-scm.com/install/) installed

### Installing Dependencies

1. To start, install [Homebrew](mailto:undefined) if you don’t already have it by running this command in Terminal:

```bash
/bin/bash -c “$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)”
```

2. Then, use Homebrew to install the required packages:

```bash
brew install python git docker
```

3. Launch Docker Desktop after installation (you can find it in **Applications**). Once open, allow it to initialize and complete its setup process.

#### Configuring Docker

Make sure the Docker daemon is running before continuing.&#x20;

Next, you'll want to allocate enough system memory to Docker. You can do this by going to **Settings > Resources > Advanced > Memory Limit** and setting the memory value to the highest available value.

To verify Docker is working correctly, run the following command in Terminal:&#x20;

```bash
sudo docker run hello-world
```

If you see a success message, your installation is good to go.

#### Clone the RL Swarm Repository

1. Navigate to your home directory and clone the RL Swarm GitHub repository using this command:

```bash
git clone https://github.com/gensyn-ai/rl-swarm.git
```

2. Then move into the project folder:

```bash
cd rl-swarm
```

### Run RL Swarm

You can now start RL Swarm using the following Docker command inside your terminal:

```bash
docker compose run –rm –build -Pit swarm-cpu
```

If you hit an error saying “`docker-compose: command not found`” use “`docker compose`” (without the hyphen), as this is the syntax used by modern Docker versions.

<div data-with-frame="true"><figure><img src="/files/j6AtKl1L0GxVxOczKkQu" alt=""><figcaption></figcaption></figure></div>

#### Log into RL Swarm

When you start RL Swarm, it will open a browser window automatically pointing to `http://localhost:3000.`

{% hint style="info" %}
If the browser does not open automatically, navigate to that address manually.
{% endhint %}

You will see the RL Swarm login screen powered by Alchemy. From here, you can log in using your preferred method such as Google or email.

<div data-with-frame="true"><figure><img src="/files/Rzjt0jBkRtb9VaAZ8Cb2" alt=""><figcaption></figcaption></figure></div>

After login, a `swarm.pem` file will be created in your repository folder. This identifies your peer on the Gensyn Testnet.

***

### Joining the new RL-Swarm Environment (CodeZero)

#### Updating via git pull

First, start by running `git pull` to fetch the latest changes to RL Swarm.&#x20;

#### Launching after Updating

There are two launch paths.

1. **Launching with Docker:** If you are using Docker, you can restart your swarm after updating via `git pull` by using one of the two following commands:

```bash
docker-compose run --rm --build -Pit swarm-cpu
```

2. **Launching with Shell Script:** If you are using the `run_rl_swarm.sh` script, you must remove your old virtual environment and create a fresh one:

```bash
rm -rf .venv
python -m venv .venv
source .venv/bin/activate
/run_rl_swarm.sh
```

{% hint style="success" %}
In both cases, restart your swarm after updating.
{% endhint %}

***

#### Huggingface

If you would like to upload your model to Hugging Face, enter your Hugging Face access token when prompted. You can generate one from your Hugging Face account, under [Access Tokens](https://huggingface.co/docs/hub/en/security-tokens).

#### Verify your Node

Once you are logged in, your node will begin training automatically.

You can verify that your peer has successfully connected by visiting the [Gensyn Testnet Dashboard.](https://dashboard.gensyn.ai/) Your peer should appear in the active swarm list, and you can monitor training progress in real time.

<div data-with-frame="true"><figure><img src="/files/sYzgGLDm5j5JD376AjXw" alt=""><figcaption></figcaption></figure></div>

#### Optional: Experimental Mode (No Docker)

If you want to experiment with the [GenRL](https://github.com/gensyn-ai/genrl) library or the [configurable parameters](https://github.com/gensyn-ai/rl-swarm/blob/main/rgym_exp/config/rg-swarm.yaml), we recommend you run RL Swarm via shell script:

```
python3 -m venv .venv
source .venv/bin/activate
./run_rl_swarm.sh
```

{% hint style="info" %}
This method gives you access to GenRL’s configuration parameters and experimental features.
{% endhint %}

To learn more about experimental mode, check out our [getting started guide](https://github.com/gensyn-ai/genrl/blob/main/getting_started.ipynb) on Github.

### Troubleshooting

Refer to the multi-platform [RL Swarm Troubleshooting guide](/testnet/rl-swarm/troubleshooting) for unblocking information and fixes to common set-up issues.

{% hint style="success" %}
If you need additional support, you can [open a ticket](https://github.com/gensyn-ai/rl-swarm/issues) or [visit our Discord.](https://discord.com/invite/gensyn)
{% endhint %}


# Node Management

Learn how to monitor, maintain, and control your RL Swarm node once it’s running.

## Overview

This page covers participating in the AI Prediction Market, viewing training and system metrics, managing your node identity, linking multiple peers, and best practices for keeping your node online and stable. This page assumes you have already completed setup and joined the swarm.

### CodeZero Node Roles

CodeZero introduces additional node roles beyond the standard participant node. While most community nodes operate as **Solvers**, the environment also includes specialized roles:

| Role          | Description                            | Typical Host    |
| ------------- | -------------------------------------- | --------------- |
| **Solver**    | Learns via RL on coding tasks          | Community node  |
| **Proposer**  | Generates problems & difficulty levels | Network service |
| **Evaluator** | Scores submissions via frozen model    | Hosted service  |

Most users will run Solver nodes, which participate in the cooperative coding environment by attempting challenges, learning locally, and sharing rollouts with peers. Proposers and Evaluators are typically hosted as network services, though advanced users can configure these roles if needed.

#### AI Prediction Market (Evaluator)

During setup, you'll be asked if you'd like to participate in the **AI Prediction Market**.

This is an experiment we're running in which:

* RL Swarm models join the market and place bets on which answer to a reasoning problem they believe is correct.
* Evidence is revealed step by step throughout the game. Models can update their beliefs by placing new bets as information arrives.
* Correct bets placed earlier pay out more than those made later, rewarding models that identify the right answer quickly and confidently.
* The Evaluator evaluates the final evidence and issues a decision, determining which bets succeed.

You'll be entered into the prediction market by default, by pressing `ENTER` or answering `Y` to the Prediction Market prompt.&#x20;

If you'd like to opt out, just answer `N`.&#x20;

{% hint style="info" %}
To learn more, head to our [blog](https://blog.gensyn.ai/) and check out our [Gensyn Testnet Dashboard](https://dashboard.gensyn.ai/).
{% endhint %}

### Viewing Training Stats

You can now upload your RL Swarm logs to [Weights & Biases](https://wandb.ai/) and easily monitor your system stats (such as `GPU Utilization`, `GPU Temperature`), and training stats (such as `loss`, `learning_rate`, and `rewards`).&#x20;

1. First, make sure you're running the [latest version](https://github.com/gensyn-ai/rl-swarm/releases) of `rl-swarm`.
2. Once you stop the `rl_swarm.sh` process in your console (e.g., by pressing `Ctrl+C`), you will see a message similar to this:

```
wandb: You can sync this run to the cloud by running:
wandb: wandb sync logs/wandb/offline-run-xxxxxxxx_xxxxxx-xxxxxxxxxx
```

To upload your training statistics:

1. Make sure you have created an account on [wandb.ai](https://wandb.ai/).
2. Copy the wandb sync command provided in your terminal (the part that looks like `wandb sync logs/wandb/offline-run-xxxxxxxx_xxxxxx-xxxxxxxxxx`).
3. Run that command in your terminal.
4. When prompted, enter your API key that can be found in <https://wandb.ai/authorize>.

This will upload your local training run data to the **Weights & Biases** cloud, allowing you to visualize and track your experiments.&#x20;

{% hint style="info" %}
For more details on this command, you can refer to the [official documentation](https://docs.wandb.ai/ref/cli/wandb-sync).
{% endhint %}


# Troubleshooting

Stuck? Get unblocked with RL Swarm on Windows (WSL 2), Linux, or macOS, or reach out to support for more help.

## Overview

This troubleshooting guide provides a complete reference for diagnosing and resolving *known issues* when installing, running, or maintaining an RL Swarm node across Windows (WSL 2), Linux, and macOS.

{% hint style="success" %}
If you need additional support, you can [open a ticket](https://github.com/gensyn-ai/rl-swarm/issues) or [visit our Discord.](https://discord.com/invite/gensyn)
{% endhint %}

### Installation and Dependency Issues

This section covers:

* "Command not found" errors for Python, Docker, and Git
* Build failures and/or missing libraries
* Permission issues (denials) when running Docker/Python scripts

#### Update your Package Manager

{% tabs %}
{% tab title="Linux & Windows (WSL 2)" %}
Run the following command to update your package manager:

```bash
sudo apt update && sudo apt upgrade -y
```

{% endtab %}

{% tab title="macOS" %}
Run the following command to update your package manager:

```bash
brew update && brew upgrade
```

{% endtab %}
{% endtabs %}

#### Install Missing Packages

{% tabs %}
{% tab title="Linux & Windows (WSL 2)" %}
You may be missing dependencies. To double-check and install any missing packages, run this command:

```bash
python3 python3-venv python3-pip curl wget git docker.io build-essential
```

{% endtab %}

{% tab title="macOS" %}
You may be missing dependencies. To double-check and install any missing packages, run this command:

```bash
brew install python git docker
```

{% endtab %}
{% endtabs %}

#### Verify your Python Version

RL Swarm requires a specific version of Python to be installed in order to run.&#x20;

Check your Python version by running `python3 --version` which *must* return **3.10** or higher. If you have an older version, upgrade via package manager or `pyenv`.

### Configuring Docker

Many Docker-related issues arise from memory allocation constraints or ports which are already in use.&#x20;

#### Start the Docker Daemon

{% tabs %}
{% tab title="Linux" %}
Run the following command to start up the Docker Daemon.&#x20;

```bash
sudo systemctl enable docker && sudo systemctl start docker
```

{% hint style="info" %}
You may need to enter your password if using `sudo` privileges.&#x20;
{% endhint %}
{% endtab %}

{% tab title="Windows (WSL 2)" %}
Run the following command to start up the Docker Daemon.&#x20;

```bash
sudo service docker start
```

{% hint style="info" %}
You may need to enter your password if using `sudo` privileges.&#x20;
{% endhint %}
{% endtab %}

{% tab title="macOS" %}
Open **Docker Desktop** and confirm that it's running.&#x20;
{% endtab %}
{% endtabs %}

#### Test Docker

The command `docker run hello-world should print` “Hello from Docker!”

If it doesn't, reinstall (Windows \[WSL 2] and Linux) or restart Docker Desktop (macOS).

#### Memory Allocation

Increase container memory by navigating to **Docker Desktop > Settings > Resources > Advanced > Memory** then set it to the maximum value (at *least* 16gb recommended).&#x20;

### Docker and Virtualization issues

Sometimes builds will hang, crash, or be unreachable.&#x20;

This section deals with the inability to connect to the Docker daemon and `docker-compose` syntax issues:

* Try the alternate syntax for modern Docker: `docker compose` (no hyphen). If that fails, fall back to `docker-compose`.
* Ensure virtualization is enabled in BIOS / Firmware.
* **WSL 2 users:** enable WSL integration inside **Docker Desktop Settings > Resources > WSL Integration**, then select your distribution.
* **Linux GPU users:** verify that your NVIDIA drivers are up-to-date and the CUDA toolkit is installed. The `nvidia-smi` must show a running driver.
* **macOS users:** RL Swarm can only run CPU-only. *GPU mode is not supported.*

{% hint style="warning" %}
For “Out of memory” (OOM) build errors, close other applications or increase Docker memory limit (above).
{% endhint %}

#### Login and Identity Issues

If you're experiencing issues logging in, this section provides quick fixes for login modal issues, *peer identity* issues, and more.

| Issue                                                 | Fix                                                                                                                                                                                                                                      |
| ----------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| *Browser window never opens for login*                | <ol><li>Manually open the login URL by typing <code><http://localhost:3000></code> into your browser.</li><li>If you're using a VM/VPS, use the <code>flag -L 3000:localhost:3000</code> port forwarding flag when connecting.</li></ol> |
| *Login modal fails to load, or OTP not sent to email* | <p></p><ol><li>Upgrade <code>viem</code> to version 2.25.0 inside <code>modal-login/package.json</code>.</li><li>Run <code>cd modal-login && yarn upgrade && yarn add next\@latest viem\@latest</code>.</li></ol>                        |
| *Login works, but training fails after re-login*      | Delete the old peer identity and restart using `sudo rm swarm.pem`. Then re-run RL Swarm and log in again with the same email.                                                                                                           |
| *Lost `swarm.pem` identity*                           | You must generate a new one using the same email to retain your on-chain account.                                                                                                                                                        |
| *Running multiple nodes*                              | Use the same email login for each node. Each node has its own peer ID,but shares the same EOA.                                                                                                                                           |
| *VPS login fallbacks*                                 | If `port:3000` is blocked, you can use temporary tunnels such as Cloudflare or nGrok if comfortable with networking tools.                                                                                                               |

### Training and Performance Issues

Some commonly experienced training issues are 'false flags' whereas others require some manual input.&#x20;

Symptom's we've seen:

* **Training appears stuck, or isn't progressing:** Consumer-grade CPUs, especially MacBooks, can take more than \~20 minutes per training cycle. Please be patient!&#x20;

{% hint style="warning" %}
If training freezes for longer than a previous iteration, use `ctrl/cmd+c` to stop, then return the container & script.&#x20;
{% endhint %}

* **"Skipped round" messages:** This is normal. It means your machine was slower than the swarm round pace.&#x20;
* **OOM (Out of Memory) errors:** Try closing other applications and increasing the Docker memory allocation as mentioned above.
* **High CPU usage and/or thermal throttling:** This is normal if you're training in CPU-only mode. If your device allows for it, try switching to GPU-only mode.
* **"GPU not detected" warnings:** Confirm that your drivers are correctly installed and recognized, and that the container is launched using `swarm-gpu`.&#x20;

{% hint style="info" %}
To force CPU-only mode explicity, use the `swarm-cpu` command.
{% endhint %}

### Network and Connectivity Issues

Docker may need to be configured in your Firewall settings to allow outbound traffic, or you may be in a region where RL Swarm is currently unavailable.&#x20;

{% hint style="danger" %}
Nodes from China, Russia, Ukraine, and sometimes Japan are blocked. Use a different region or VPS outside those areas.
{% endhint %}

Common connection issues:

* **Node doesn't appear on the dashboard:** Check your internet connection and make sure the firewall allows outbound traffic from Docker. Also, visit the [Gensyn Dashboard](https://dashboard.gensyn.ai/) and confirm that your node is visible under RL Swarm.
* **Predication Market bets are not visible:** Make sure you answered 'Y' when asked to join the Prediction Market. Rerun the script if necessary.&#x20;
* **VPS connection drops:** If the SSH tunnel breaks and you see “broken pipe” errors, press `ctrl/cmd+c` to kill the script, then restart RL Swarm, and it should cleanly re-initalize.&#x20;

### Logs and Diagnostics

Browse the table below to find the most useful log types and locations inside the `rl-swarm` repository.&#x20;

| Location                                        | Type                                                                     |
| ----------------------------------------------- | ------------------------------------------------------------------------ |
| `/logs/yarn.log`                                | Modal login server activity.                                             |
| `/logs/swarm.log`                               | The main application log.                                                |
| `/logs/wandb/`                                  | Training logs and `debug.log` for Weights & Biases (if this is enabled). |
| `/logs/prg_record.txt` and `swarm_launcher.log` | Prediction Market details.                                               |

#### How to Interpret Logs

Many warnings (e.g., Protobuf "yanked version") are **benign** and can be safely ignored.

When looking at your logs for errors, look for lines containing `ERROR`, `RuntimeError` or `Traceback` to locate actual failure points.&#x20;

{% hint style="info" %}
When posting to [Discord](https://discord.com/invite/gensyn) or [Github](https://github.com/gensyn-ai/rl-swarm/issues), please attach the relevant section of `swarm.log` as well as your system info.&#x20;
{% endhint %}

### Advanced and Recovery Scenarios

Below are some specific scenarios you may run into when running multiple nodes, or nodes on different machines.

* **Moving to a new machine:** Make sure to back up your `swarm.pen` from the repo's root, then copy it into the *same directory* on the new machine before launching RL Swarm.&#x20;
* **Running multiple GPUs or peers:** Install RL Swarm separately for each GPU, and exposre each peer under a different port.
* **Clean rebuilds:** Stop all containers and processes by using `ctrl/cmd+c` then run `docker system prune -a` to remove old containers. Delete `.venv` and re-clone the repository if necessary.&#x20;
* **Using tuneling tools in cases where the login port is blocked:** This is only for advanced users who are comfortable with network tools. Use the simplest tool that works, since the local login method is recommended for security and reliablity. Tools include **Cloudflare**, **nGrok**, or **localtunnel**.

### When to Esclate&#x20;

If you're experiencing an issue that none of the above steps are able to resolve, we're here to help.&#x20;

1. Check the [GitHub Issues](https://github.com/gensyn-ai/rl-swarm/issues) page to see if your issue has already been reported.
2. If you open a new issue or ask for help on [Discord](https://discord.com/invite/gensyn), please include the operating system and version, CPU and GPU model, amount of RAM, and as much context on the error(s) as possible.&#x20;


# BlockAssist (Paused)

BlockAssist is an interactive, AI-driven Minecraft environment where reinforcement learning agents learn from your actions.

{% hint style="info" icon="triangle-exclamation" %}
**BlockAssist has been sunset.**&#x20;

*These docs are preserved for reference but BlockAssist is no longer actively maintained.*

Alternatively, you can explore [Delphi](https://app.delphi.fyi/), a set of tools for creating information markets.
{% endhint %}

### What is BlockAssist?

BlockAssist is an AI assistant that learns from its user’s actions in Minecraft. The assistant appears in-game with you, starting with only basic knowledge of the game’s commands.&#x20;

As you play, it learns how to assist you in building, learning directly from your actions. BlockAssist bridges Gensyn’s research in decentralized machine learning with a game-based interface that’s easy to explore and extend.

<figure><img src="/files/LobixWsl7vRUbacvbvxd" alt=""><figcaption></figcaption></figure>

### Why It Exists

Modern machine learning systems rely on centralized *compute clusters* that limit participation and experimentation.&#x20;

BlockAssist was created to demonstrate how learning can happen collaboratively and trustlessly across many smaller nodes, which is the same principle that underpins the Gensyn network.&#x20;

By turning reinforcement learning into a playable experiment, BlockAssist helps researchers, developers, and enthusiasts visualize what decentralized AI coordination looks like in action.

{% hint style="success" %}
BlockAssist is part of Gensyn’s effort to build the network for machine intelligence.&#x20;

It offers a lightweight, playable example of the coordination and verification layers seen in Gensyn’s research, like [RL Swarm](https://www.gensyn.ai/articles/rl-swarm) for collaborative RL, [Verde](https://www.gensyn.ai/articles/verde) for verification, [CheckFree](https://www.gensyn.ai/articles/checkfree) for fault tolerance, and [NoLoCo](https://www.gensyn.ai/articles/noloco) for efficient communication.
{% endhint %}

#### What You Can Do With It

Users can clone the repo, run it locally, and play a guided Minecraft scenario where they're tasked with building a structure.&#x20;

As you play, an AI bot observes your actions—learning how to build alongside you by watching **\[1]** what you do, **\[2]** where you place blocks, and **\[3]** how you solve the task.&#x20;

After each session (called an “episode”), BlockAssist trains a machine learning model on your gameplay data, right on your machine. Once training is complete, users upload their personalized model to Hugging Face using their token.

This submission is then recorded on the Gensyn Testnet, contributing to a *decentralized, verifiable record of your participation* and model training.&#x20;

{% hint style="info" %}
BlockAssist’s purpose is to demonstrate “assistance learning”, where AI that learns directly from human actions, not just static datasets while giving users a hands-on way to contribute to and experiment with decentralized AI training.
{% endhint %}


# Getting Started

Get up and running with BlockAssist and start training your own model.

{% embed url="<https://github.com/gensyn-ai/blockassist>" %}

{% hint style="warning" %}
BlockAssist has been sunset. Please see the [home page](/testnet/blockassist) for more information.
{% endhint %}

## Overview

This page helps you prepare your system and choose the correct installation path for BlockAssist. It provides a readiness checklist, supported platforms, and an overview of the setup process before you begin installing and running BlockAssist on your device.

#### Before You Begin

BlockAssist is available across several environments: [Windows (via WSL 2)](/testnet/blockassist/getting-started/windows-wsl-2), [Linux (Ubuntu 22.04+)](/testnet/blockassist/getting-started/linux), [macOS (Intel and Apple Silicon)](/testnet/blockassist/getting-started/macos), and [remote Linux desktops.](/testnet/blockassist/getting-started/linux/running-blockassist-on-a-remote-linux-desktop)

Before you start, make sure you meet the basic requirements and have the necessary accounts.

### System Requirements

* 12 GB RAM minimum (32 GB recommended)
* Stable internet connection
* At least 10 GB of available storage (for overhead)
* Modern multi-core CPU (Intel, AMD, or Apple Silicon)

#### Accounts & Access

* **Hugging Face account:** You’ll need a Write-access API token to upload your model after training. See the Hugging Face Guide for instructions.
* **Gensyn Testnet account:** Automatically created when you first log in through your browser during setup.

#### Software Requirements (All Platforms)

* Python 3.10.x
* Java 1.8.0\_152 (OpenJDK 8)
* Git
* Internet access for dependency installation and authentication

### Supported Platforms & Installation Paths

BlockAssist runs on multiple environments. Choose the guide that matches your operating system or setup.

<table data-view="cards"><thead><tr><th align="center"></th><th></th><th data-hidden data-card-cover data-type="image">Cover image</th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td align="center"><a href="/pages/IAgcnJEo2OIqC2aXMo8u">Windows (WSL 2)</a></td><td>Run BlockAssist on Windows 10 or 11 using Windows Subsystem for Linux 2 (WSL). This setup requires an X Server such as VcXsrv to render the Minecraft environment.</td><td></td><td><a href="/pages/IAgcnJEo2OIqC2aXMo8u">/pages/IAgcnJEo2OIqC2aXMo8u</a></td></tr><tr><td align="center"><a href="/pages/ZhMbKsjvcfc6MoR1Quvs">Linux (Ubuntu 22.04+)</a></td><td>Install BlockAssist natively on Ubuntu or a compatible distribution for the most stable experience.</td><td></td><td><a href="/pages/ZhMbKsjvcfc6MoR1Quvs">/pages/ZhMbKsjvcfc6MoR1Quvs</a></td></tr><tr><td align="center"><a href="/pages/K7RaUCXgt9PBYMIL7L5x">macOS (Intel &#x26; Apple Silicon)</a></td><td>Install and run BlockAssist on macOS using Homebrew for dependency management. Both Intel and M-series processors are supported.</td><td></td><td><a href="/pages/K7RaUCXgt9PBYMIL7L5x">/pages/K7RaUCXgt9PBYMIL7L5x</a></td></tr></tbody></table>

{% hint style="success" %}
All platform installations share a few core dependencies. These are handled within each platform’s guide, but if you encounter dependency issues, consult your specific platform’s **Troubleshooting** section.
{% endhint %}

### Installation Flow

Every installation follows the same general flow, regardless of platform.

1. Choose and complete the correct installation guide for your platform.
2. Run BlockAssist from your terminal.
3. Log in when prompted:
   * Paste your Hugging Face Write-access token.
   * Authenticate through the Gensyn Testnet browser window.
4. Play and record your in-game building session.
5. Wait for the model to train and upload automatically to Hugging Face and the Gensyn Testnet.

{% hint style="info" %}
This sequence is similar on all platforms, with commands and dependencies varying by operating system.
{% endhint %}

***

#### Cursor Setup (Optional)

For users who prefer a more guided setup experience, [BlockAssist can also be configured through Cursor AI](/testnet/blockassist/using-blockassist/running-blockassist-with-cursor), an intelligent code editor that walks you through installation steps interactively. This method is platform-agnostic but still requires that dependencies and environment setup steps are completed.

#### Additional Resources

After you've successfully installed BlockAssist on your system, continue with:&#x20;

* [Running BlockAssist](/testnet/blockassist/using-blockassist): Instructions for launching and training.
* [Hugging Face Guide](/testnet/blockassist/hugging-face-guide): Generate and manage your API token for uploads.


# Windows (WSL 2)

Get up and running with BlockAssist on your Windows device with a WSL 2 environment.

## Overview

This guide explains how to install and run BlockAssist v0.1.0 on Windows 10 or 11 using Windows Subsystem for Linux (WSL). It walks you through environment setup, dependency installation, authentication, and configuration for running the Minecraft interface through **VcXsrv**.

### Prerequisites

* Windows 10/11 with WSL 2 enabled
* Ubuntu 22.04 LTS (recommended) or another supported Linux distribution inside WSL
* At least 12 GB RAM (32 GB recommended)
* Git installed on both Windows and WSL
* A Hugging Face account with a [Write-access API token](/testnet/blockassist/hugging-face-guide)
* Gensyn Testnet account

{% hint style="success" %}
If you don't have a Testnet account, don't worry--you'll be prompted to create it automatically on your first log-in attempt.
{% endhint %}

#### Dependencies

* **Core:** Python 3.10 (via pyenv), Java 1.8.0\_152 (OpenJDK 8), Git
* **Display Server:** VcXsrv or another X Server for Windows
* **GPU Support (Optional):** CUDA and cuDNN for Nvidia GPUs

### Installation Steps

#### Step 1 — Clone the Repository

Open your WSL terminal and clone the BlockAssist repository:

```bash
git clone https://github.com/gensyn-ai/blockassist.git
```

Then, navigate to the directory.

```bash
cd blockassist
```

#### Step 2 — Install Core Dependencies

1. Run the setup script to install Java.

```bash
./setup.sh
```

2. Next, install and configure your Python environment:

```bash
curl -fsSL https://pyenv.run | bash
```

3. Configure `pyenv`:

```bash
export PYENV_ROOT="$HOME/.pyenv"
[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init - bash)"
eval "$(pyenv virtualenv-init -)"
```

4. Reload your shell after configuring your Python environment using `source ~/.bashrc`.
5. Update your system and install build tools:

```bash
sudo apt update
sudo apt install -y make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev \
curl git libncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev
```

6. Install Python 3.10 and set it globally:

```bash
pyenv install 3.10.0
pyenv global 3.10.0
```

7. Install Python libraries:&#x20;

```
pip install psutil readchar rich
```

#### Step 3 — Configure Node.js and Yarn

1. Install Node Version Manager (NVM):

```bash
curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
```

2. Load NVM and install Node LTS:

```bash
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
nvm install --lts
nvm alias default 'lts/*'
nvm use default
```

3. Enable Corepack and install Yarn:

```bash
corepack enable
corepack prepare yarn@stable --activate
node -v
npm -v
yarn -v
```

#### Step 4 — Optional GPU Setup (cuDNN)

If you have an Nvidia GPU, install cuDNN for acceleration.&#x20;

Use the appropriate installer for Ubuntu 22.04, then run:

```bash
sudo apt update
sudo apt install -y libcudnn9 libcudnn9-dev
echo 'export LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATH' >> ~/.bashrc
source ~/.bashrc
```

#### Step 5 — Verify Installation

You're now ready to create and activate a virtual environment:

```bash
python3 -m venv blockassist-venv
source blockassist-venv/bin/activate
python -m pip install --upgrade pip setuptools wheel
pip install -e .

```

Confirm Malmo is detected:

```bash
python - <<'PY'
import pkgutil
print('malmo' in [m.name for m in pkgutil.iter_modules()])
PY
```

***

### Platform-Specific Notes

When launching VcXsrv on Windows, make sure you've enabled/disabled the following:

| Enable          | Disable        |
| --------------- | -------------- |
| Multi-Window    | Access Control |
| Start no client | Native OpenGL  |

Also, make sure to:&#x20;

* Set the display variable in WSL 2: `export DISPLAY=<WINDOWS_IP>:0`
* Test X11 forwarding with `xeyes`

If you see black screens or OpenGL crashes, enable software rendering:

```bash
export LIBGL_ALWAYS_SOFTWARE=1
export MESA_LOADER_DRIVER_OVERRIDE=llvmpipe
export LIBGL_ALWAYS_INDIRECT=1
export _JAVA_OPTIONS='-Xms512m -Xmx2g -Dorg.lwjgl.opengl.Display.allowSoftwareOpenGL=true'

```

### Authentication

{% stepper %}
{% step %}

### Navigate to the Directory

Enter `cd modal-login` and run `yarn install` followed by `yarn dev`.
{% endstep %}

{% step %}

### Go to LocalHost

Open a browser and go to `http://localhost:3000`, log in to your Gensyn Testnet account, and then stop the server with Ctrl+C.
{% endstep %}

{% step %}

### Activate your Environment

Return to the main directory and run `source blockassist-venv/bin/activate`.
{% endstep %}

{% step %}

### Start BlockAssist

To start BlockAssist, enter `python3 run.py`.

{% hint style="warning" %}
When prompted, enter your HuggingFace token.&#x20;
{% endhint %}
{% endstep %}
{% endstepper %}

### Troubleshooting

Here's a list of some common problems and quick fixes.&#x20;

| Issue                                      | Solution                                              |
| ------------------------------------------ | ----------------------------------------------------- |
| Minecraft window not opening               | Check `DISPLAY` variable and VcXsrv configuration     |
| Black screen or OpenGL crash               | Enable software rendering                             |
| “pyenv: command not found”                 | Reinitialize `pyenv` and reload shell                 |
| “malmo.log not found”                      | Reinstall using `pip install -e .`                    |
| Startup freezes at 100%                    | Wait for about one minute, then press `ENTER`         |
| “Minecraft unexpectedly crashed on launch” | Edit scripts/run\_malmo.sh to include `--timeout 300` |

{% hint style="success" %}
If you need additional support, you can [open a ticket](https://github.com/gensyn-ai/blockassist/issues) or [visit our Discord.](https://discord.com/invite/gensyn)&#x20;
{% endhint %}


# Linux

Get up and running with BlockAssist in your Ubuntu 22.04+ Linux environment.

## Overview

Use this guide to install and set up BlockAssist on Linux systems, with **Ubuntu 22.04 LTS** as the recommended distribution. It includes environment configuration, dependency installation, and verification steps to prepare for running and training BlockAssist locally.

### Prerequisites

* Ubuntu 22.04 LTS or compatible Linux distribution
* At least 12 GB RAM (32 GB recommended for training stability)
* Git installed
* Hugging Face account with a [Write-access API token](/testnet/blockassist/hugging-face-guide)
* Gensyn Testnet account

{% hint style="success" %}
If you don't have a Testnet account, don't worry--you'll be prompted to create it automatically on your first log-in attempt.
{% endhint %}

### Dependencies

* **Core:** Python 3.10.x (via pyenv) & Java 1.8.0\_152 (OpenJDK 8)
* **Optional:** CUDA/cuDNN for Nvidia GPU acceleration
* **Package Manager:** APT (default for Ubuntu)

### Installation Steps

#### Step 1 — Clone the Repository

Clone the BlockAssist repository and navigate into it.

```bash
git clone https://github.com/gensyn-ai/blockassist.git  
cd blockassist
```

#### Step 2 — Install Java 1.8.0\_152

Run the setup script included with the repository. This installs and configures Java 8, which is required for the underlying Minecraft environment.

```bash
./setup.sh
```

Verify Java installation by running:

```bash
java -version
```

You should see a version number beginning with 1.8.0\_152.

#### Step 3 — Install pyenv

Install pyenv to manage your Python environment.

```bash
curl -fsSL https://pyenv.run | bash
```

Follow the instructions provided by pyenv to add it to your shell configuration file (for example, .bashrc or .zshrc).

Then initialize pyenv:

```bash
export PYENV_ROOT="$HOME/.pyenv"  
[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"  
eval "$(pyenv init --path)"  
eval "$(pyenv init -)"  
source ~/.bashrc
```

#### Step 4 — Install Core Dependencies

Install system-level dependencies required for building and compiling Python.

```bash
sudo apt update  
sudo apt install -y make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev \
libsqlite3-dev curl git libncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev \
libffi-dev liblzma-dev zip unzip
```

Once complete, use `pyenv` to install Python 3.10 and set it globally.

```bash
pyenv install 3.10.13  
pyenv global 3.10.13
```

Confirm that Python was installed correctly using the following command:&#x20;

```bash
python --version
```

#### Step 5 — Install Python Packages

Install required Python libraries for BlockAssist.

```bash
pip install psutil readchar rich
```

#### Step 6 — Verify Installation

At this point, your environment is ready. Verify that Java, Python, and pyenv are properly configured:

```bash
java -version  
python --version  
pyenv versions
```

{% hint style="info" %}
Each should return a valid version number with no errors.
{% endhint %}

***

### Platform-Specific Notes

* Use Ubuntu 22.04 LTS for maximum compatibility. Other distributions may require slight package name adjustments.
* If you are running Ubuntu on ARM hardware (such as Raspberry Pi or ARM-based servers), ensure that you install the ARM-compatible version of OpenJDK 8.
* For Nvidia GPU users, installing CUDA and cuDNN is *optional* but can accelerate model training.

### Authentication

Once installation is complete, you will authenticate when running BlockAssist for the first time.

* You’ll be prompted for your Hugging Face Write-access API token. Follow the instructions provided in the [Hugging Face Guide](/testnet/blockassist/hugging-face-guide) to generate one if you haven’t already.
* A browser window will open for Gensyn Testnet login. If you have logged in previously, this step will be skipped automatically.

### Troubleshooting

Below are some quick fixes for some common installation issues.&#x20;

* If `pyenv: command not found`, reinitialize `pyenv` using the following command:

```bash
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init --path)"
eval "$(pyenv init -)"
```

* If Java fails to install via `setup.sh`, manually install OpenJDK 8:

```bash
sudo apt install -y openjdk-8-jdk
```

* If Python installation fails, ensure all required build dependencies are installed (`build-essential`, `zlib1g-dev`, `libssl-dev`, etc.).

For any missing Python packages, `rerun pip install -e .` from inside the BlockAssist folder.

{% hint style="success" %}
If you need additional support, you can [open a ticket](https://github.com/gensyn-ai/blockassist/issues) or [visit our Discord.](https://discord.com/invite/gensyn)&#x20;
{% endhint %}


# Running BlockAssist on a Remote Linux Desktop

Learn how to run BlockAssist on a remote Linux environment using several types of devices.

{% hint style="danger" %}
**Note**: this path is highly experimental and not officially supported. Feel free to adapt the steps and share any issues or improvements you discover.
{% endhint %}

## Overview

This guide shows non-technical users how to set up and run BlockAssist on a remote Ubuntu Desktop droplet at DigitalOcean and stream it with Moonlight to any laptop, phone, tablet, or TV.

### Installation & Setup Steps

#### Step 1 — Creating your Droplet

1. Sign in to DigitalOcean and click Create → Droplet.
2. Under Marketplace, choose Ubuntu Desktop (GNOME) 22.04 LTS.

| System Specifications | CPU | RAM   |
| --------------------- | --- | ----- |
| Minimum               | 4   | 16 GB |
| Recommended           | 8   | 32 GB |

Add your SSH key, pick the nearest region, and click **Create Droplet.**

{% hint style="info" %}
Note the droplet’s public IP, which you will use for SSH, VNC, and Moonlight.
{% endhint %}

#### Step 2 — First-time Desktop Access

1. SSH to the droplet as root:

```sh
ssh root@<DROPLET_IP>
```

2. The first-login banner shows a random **VNC password**. Copy it.
3. Give the pre-installed **gui** user `sudo` rights:

```sh
sudo usermod -aG sudo gui
sudo reboot
```

4. Open any VNC client and connect to `<DROPLET_IP>:5901` using the password from Step 1. You will only need VNC again if Sunshine stops working.

#### Step 3 — Installing Dependencies

{% hint style="info" %}
You run these commands once. To record more episodes later, read [this guide on running & training models with BlockAssist.](/testnet/blockassist/using-blockassist)
{% endhint %}

1. In the VNC desktop, open **Terminal** and install the build tools:

```sh
sudo apt update
sudo apt install -y make build-essential gcc \
  libssl-dev zlib1g-dev libbz2-dev libreadline-dev \
  libsqlite3-dev libncursesw5-dev xz-utils tk-dev \
  libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev curl git
```

2. Clone BlockAssist:

```sh
git clone https://github.com/gensyn-ai/blockassist.git ~/blockassist
cd ~/blockassist
```

**Python & Node**&#x20;

Let `pyenv` and `nvm` read the exact versions pinned in the repository.&#x20;

```shell
# install pyenv
curl https://pyenv.run | bash
exec $SHELL

pyenv install $(cat .python-version)
pyenv global  $(cat .python-version)

# install nvm
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash
exec $SHELL

nvm install $(cat .nvmrc)
```

**Project Packages**

Install the required project packages using the commands below.&#x20;

```sh
pip install --upgrade pip
pip install -r requirements.txt readchar

corepack enable        # enables Yarn
yarn install --frozen-lockfile
```

#### Step 3 — Streaming with Sunshine & Moonlight

1. Install Sunshine using the following command:

```sh
wget -O sunshine.deb \
  https://github.com/LizardByte/Sunshine/releases/download/v0.23.1/sunshine-ubuntu-22.04-amd64.deb
sudo apt install ./sunshine.deb
systemctl --user enable --now sunshine
```

2. Open its web UI (`http://localhost:47990`) in the VNC browser and set an admin password.
3. Allow GameStream ports:

```sh
sudo ufw allow 47984/tcp 47989/tcp 48010/tcp
sudo ufw allow 47998:48002/udp 47990/tcp
```

4. On your local device install **Moonlight**, add the droplet’s IP, enter the PIN shown, and pair.\
   You can now close the VNC client and use Moonlight for the rest of this guide.

#### Step 5 — Running BlockAssist

Click here for a detailed, [platform-agnostic guide on running BlockAssist.](/testnet/blockassist/using-blockassist)&#x20;

## Troubleshooting

Below are some common issues and quick fixes.

| Issue                                 | Solution                                                                                          |
| ------------------------------------- | ------------------------------------------------------------------------------------------------- |
| Error while installing packages       | In the Chat panel press `cmd + L`, then type **Help me fix this error** and add Terminal context. |
| BlockAssist launches but will not run | In Chat type `Look at my logs folder` **…** and follow the suggestions.                           |
| Mouse will not turn or view is stuck  | Make sure you are playing through **Moonlight**, not VNC.                                         |
| Mission times out while loading       | Upgrade the droplet to at least 8 vCPU / 32 GB RAM.                                               |

{% hint style="success" %}
If you need additional support, you can [open a ticket](https://github.com/gensyn-ai/blockassist/issues) or [visit our Discord.](https://discord.com/invite/gensyn)&#x20;
{% endhint %}


# macOS

Get up and running with BlockAssist in your macOS environment.

## Overview

This guide explains how to install and configure BlockAssist on macOS (Intel or Apple Silicon). It walks you through setting up dependencies, configuring the Python environment, and preparing BlockAssist for local training and submission to the Gensyn Testnet.

### Prerequisites

* macOS 12 or newer
* Homebrew installed (`brew -v` should work)
* Java
* 10–15 GB free disk space
* Hugging Face account and a token with Write scope

{% hint style="warning" %}
Use this guide to install macOS on Intel or Apple Silicon processors. Pay attention to platform-specific notes for changes in packages and dependencies.
{% endhint %}

### Installation Steps

You only need to run these *once* per computer, and you don't need to have Minecraft installed.

**Apple Silicon users (ARM):** See the Java note in Step 2.

#### Step 1 — Clone the Repo

```bash
git clone https://github.com/gensyn-ai/blockassist.git
cd blockassist
```

#### Step 2 — Install Java (Malmo/Minecraft runtime)

Follow the Intel or ARM Java installation steps below by choosing the tab that matches your CPU architecture.&#x20;

{% tabs %}
{% tab title="Intel" %}
Use the project's installer for Java 1.8.0\_152 (as documented in the repo).

```bash
./setup.sh
```

{% hint style="success" %}
Intel systems can safely use the default Java 8 setup without modifications.
{% endhint %}
{% endtab %}

{% tab title="ARM (Apple Silicon)" %}
Apple Silicon Macs should not use Java 8 binaries, as they are x86\_64-only and can cause Malmo or Minecraft to crash.&#x20;

Instead, install OpenJDK 11 (ARM64) and point the legacy Java-8 path at it:

```bash
brew install openjdk@11
echo 'export PATH="/opt/homebrew/opt/openjdk@11/bin:$PATH"' >> ~/.zshrc
export PATH="/opt/homebrew/opt/openjdk@11/bin:$PATH"
export JAVA_HOME=$(/usr/libexec/java_home -v 11)

# (If a zulu-8 path exists, move it aside and symlink to JDK 11)
sudo mv /Library/Java/JavaVirtualMachines/zulu-8.jdk \
        /Library/Java/JavaVirtualMachines/zulu-8.jdk.backup 2>/dev/null || true
sudo ln -sfn /opt/homebrew/opt/openjdk@11/libexec/openjdk.jdk \
              /Library/Java/JavaVirtualMachines/zulu-8.jdk
```

{% hint style="success" %}
Apple Silicon systems generally load faster but require ARM-native Java 11 to avoid “Bad CPU type” errors.
{% endhint %}
{% endtab %}
{% endtabs %}

#### Step 3 — Install pyenv

```bash
brew update
brew install pyenv
```

#### Step 4 — Install Python 3.10

```bash
pyenv install 3.10
pyenv global 3.10
```

#### Step 5 — Install required Python packages

```bash
pyenv exec pip install -U pip
pyenv exec pip install psutil readchar rich
```

### Configuration

BlockAssist uses Hydra for configuration management. You can modify settings in the `src/blockassist/config.yaml` file (or the project `config.yaml` if present) or override them via command-line arguments.

* `episode_count` — Number of episodes to record. If greater than 1, a new episode will start each time you press ENTER during session recording.
* `num_training_iters` — Number of training iterations across all recorded episodes.

### Troubleshooting

Read below for common fixes to macOS edge cases, bugs, and environment configuration issues.&#x20;

If you're still experiencing problems getting BlockAssist running after exhausting the options below, please make an issue in the repository [here](https://github.com/gensyn-ai/blockassist/issues).

#### Common Fixes

1. **Minecraft times out while starting**

Give it more time (first run can take 2–5 minutes):

```bash
MALMO_TIMEOUT=300 pyenv exec python run.py
# or, if calling Malmo directly:
python -m malmo.minecraft launch --timeout 300
```

Verify `logs/malmo.log` shows “Listening on port 10000” and both windows are open.

***

2. **Java is crashing, or "Bad CPU type" on Apple Silicon / ARM**

Install ARM64 Java 11 and set JAVA\_HOME:

```bash
brew install openjdk@11
echo 'export PATH="/opt/homebrew/opt/openjdk@11/bin:$PATH"' >> ~/.zshrc
export PATH="/opt/homebrew/opt/openjdk@11/bin:$PATH"
export JAVA_HOME=$(/usr/libexec/java_home -v 11)
sudo ln -sfn /opt/homebrew/opt/openjdk@11/libexec/openjdk.jdk /Library/Java/JavaVirtualMachines/zulu-8.jdk
java -version
```

***

3. **Port 10000 already in use or stuck processes**

Kill any outstanding processes, then relaunch BlockAssist then using the command.

```bash
lsof -i :10000
pgrep -fa 'java|minecraft|malmo|gradle'
pkill -f 'malmo|minecraft|gradle|java'
```

{% hint style="info" %}
Be sure to re-run the app after clearing processes.
{% endhint %}

***

4. **Node/Yarn version or permission errors**

Install the correct version of Yarn using `sudo` privileges. You may need to enter your account/device's password.&#x20;

```bash
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
source ~/.nvm/nvm.sh
nvm install 20.18.0 && nvm use 20.18.0
sudo npm install -g yarn
```

***

5. **`pyenv` using the wrong Python version**

Run the following command to install the correct version according to the README:

```bash
pyenv install 3.10.18
pyenv global 3.10.18
echo 'eval "$(pyenv init -)"' >> ~/.zshrc && source ~/.zshrc
pyenv exec pip install -U pip
pyenv exec pip install psutil readchar rich
pyenv exec python run.py
```

{% hint style="info" %}
You can also use this in the event that there are missing packages/dependencies.
{% endhint %}

***

6. **Minecraft application windows not opening**

Follow the sequence below in the event that the Minecraft instance windows are refusing to open:

* Approve macOS Accessibility for your terminal app.
* Ensure Java 11 ARM64 is active (see #2).
* Increase `MALMO_TIMEOUT` as in #1.
* Watch `logs/malmo.log` while launching.
* Clear straggler processes (see #3) and retry.

***

7. **Missing system utilities**

If certain build tools or command-line utilities are missing on your system, install them using the commands below.

```bash
xcode-select --install
brew install zip unzip
```

***

#### Helpful Diagnostics

Use the following diagnostic commands to confirm your BlockAssist environment is configured correctly. These checks verify Python, Java, and Node installations, confirm your system’s architecture, and help identify the most common “wrong version” or “missing dependency” issues.

{% tabs %}
{% tab title="Quick Checks" %}
Run this small set of commands first to make sure all major dependencies are recognized and properly configured.&#x20;

This will catch most “wrong version” or “wrong architecture” issues in seconds.

```bash
python -V  
pyenv versions  
java -version && /usr/libexec/java_home -V  
uname -m  
tail -f logs/malmo.log
```

{% endtab %}

{% tab title="Extended Diagnostics" %}
If you’re still seeing crashes or unexpected errors, run the extended set below.&#x20;

Copy and paste the full output when asking for help, as it’s the fastest way to catch version mismatches or architecture conflicts.

```bash
/usr/libexec/java_home -V
java -version
node -v && yarn -v
pyenv versions && pyenv which python && python -V
file "$(which java)"
```

{% endtab %}
{% endtabs %}

**Still Stuck?**

If the issue you're experiencing isn't fixable via the above steps, try this sequence of commands and modifications:

* Bump timeout to 420–600 on first run.
* Quit all Java/Minecraft/Gradle processes, then retry.
* Confirm Node 20.18.0 and ARM64 Java on Apple Silicon.
* Run `cd modal-login && yarn install && yarn dev` if you encounter a `/scripts/node_env.sh: line 14: logs/node_env.log: No such file or directory` error. Then, re-run BlockAssist using `python run.py` or `python3 run.py`.
* If you encounter an error stating "BlockAssist module not found" when attempting to check `blockassist-train.log` files, use `pip install -e .` then re-run.

{% hint style="success" %}
If you need additional support, you can [open a ticket](https://github.com/gensyn-ai/blockassist/issues) or [visit our Discord.](https://discord.com/invite/gensyn)
{% endhint %}


# Using BlockAssist

Use the platform-agnostic guide below to launch BlockAssist after installation, complete tasks, train your models, and upload them via Hugging Face.

## Overview

Use the step-by-step guide below to run BlockAssist, train models, and start contributing to Gensyn's Testnet.

### Logs

Use `tail -f logs/[specific log].log` to monitor progress, and `ls logs` to see options.&#x20;

{% hint style="info" %}
You might need to press ENTER a few times when prompted.
{% endhint %}

### Running with Python

The program will install various dependencies as required. Follow any instructions and approve all asks.

{% tabs %}
{% tab title="Windows (WSL 2)" %}
Use the following command to run the script on your Windows device:

```bash
python run.py
```

{% hint style="info" %}
You can optionally prefix it with `pyenv exec` if you’re using `pyenv` to manage your Python version.
{% endhint %}
{% endtab %}

{% tab title="Linux" %}
Use the following command to run the script on your Linux device/environment:

```bash
python run.py
```

{% hint style="info" %}
You can optionally prefix it with `pyenv exec` if you’re using `pyenv` to manage your Python version.
{% endhint %}
{% endtab %}

{% tab title="macOS" %}
Use the following command to run the script on your macOS device:

```bash
pyenv exec python run.py
```

{% endtab %}
{% endtabs %}

<figure><img src="/files/8wasD2P7yuvhhTM1FkR5" alt=""><figcaption></figcaption></figure>

#### HuggingFace Token

You will be asked to enter a [Hugging Face](https://huggingface.co) API token.&#x20;

Follow the instructions [in this guide](#huggingface-token), and make sure the token has **Write** access.

<figure><img src="/files/prnbP4dPK34P71iBETKd" alt=""><figcaption></figcaption></figure>

#### Logging into Gensyn Testnet

The terminal will show a **LOGIN** section where the system:

* Requests accessibility permissions (approve these if prompted)
* Waits for user authentication data to be created
* Confirms successful login setup

<figure><img src="/files/CygFTQwepOw0JCLazybF" alt=""><figcaption></figcaption></figure>

{% hint style="success" %}
If you have previously logged in, it will skip this step. Otherwise, log in using the browser window that just opened.
{% endhint %}

#### Play Minecraft

Next, the terminal will display a **START MINECRAFT** section:

1. Prompts you to wait for two Minecraft windows to open (up to 5 minutes)
2. Do not close either Minecraft window manually. The app manages them.

{% hint style="warning" %}
**Important:** If one or both windows close, restart the program.
{% endhint %}

3. Run `tail -f logs/malmo.log` in another terminal to monitor for errors.
4. Press `ENTER` when both Minecraft windows are open and ready.

<figure><img src="/files/1tkLMm5LNQGuyGv4LOIV" alt=""><figcaption></figcaption></figure>

### Game Instructions

The objective is to construct the structure in front of you by adding or removing blocks. Each attempt to build is referred to as an "episode." The AI player learns from your actions as you continue to play.

#### Game Controls

* Click on the Minecraft window and press **ENTER** to start playing
* Break red blocks and place blocks where indicated
* **Left click** to break blocks & **right click** to place blocks
* Select tools/blocks by pressing number keys **1-9**
* Use **WASD** keys to move around
* Press **ESC** when finished, then return to the terminal

<figure><img src="/files/T0GD16QgXVIKdGXwMnWd" alt=""><figcaption></figcaption></figure>

#### Record an Episode

The terminal will show a **STARTING EPISODE 0** section.&#x20;

At this stage, the program:

* Waits for the mission to load in Minecraft
* Begins recording your gameplay with a progress bar and timer
* Press `ENTER` when finished to stop recording

<figure><img src="/files/Ij8wXSROyD4OvgNDNM7e" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
**Note:** You may need to press `ENTER` multiple times to stop recording.
{% endhint %}

### Training Process

When the terminal displays the `MODEL TRAINING` section, BlockAssist begins training the AI model based on your recorded gameplay.&#x20;

This process can take some time depending on your hardware performance, so keep the terminal window open until training completes. You’ll see progress updates and status indicators as the model trains.

<figure><img src="/files/2pr1YtpRX3Go4yN9p7F8" alt=""><figcaption></figcaption></figure>

A model will now be trained and submitted to Hugging Face and Gensyn's smart contract.

#### Reviewing Logs

If you reach this stage in the logging window, and can see a transaction in the block explorer, then submissions have worked!

Logging Window:

```
[2025-07-28 05:03:48,955][blockassist.globals][INFO] - Successfully uploaded model to HuggingFace: h-grieve/blockassist-bc-bellowing_pouncing_horse_1753675374 with size 20.00 MB
```

You can see the details of the contract & transaction in the [Gensyn Testnet block explorer.](https://gensyn-testnet.explorer.alchemy.com/address/0xE2070109A0C1e8561274E59F024301a19581d45c?tab=logs)

```
huggingFaceID
string
false
h-grieve/blockassist-bc-bellowing_pouncing_horse_1753675374
```

The program will then end. Please close any Minecraft windows if they remain open, but only after you've confirmed the transaction and model upload, or you may lose your training progress.

### Testing & Contributing

Contributions to BlockAssist are welcome, whether through code improvements, testing, or documentation feedback.&#x20;

The following tools and options help you maintain a **\[1]** consistent and **\[2]** privacy-respecting development environment.

#### Telemetry

Running the following command disables **anonymous usage data** for your session. Paste this in the same terminal before starting the app:

```bash
export DISABLE_TELEMETRY=1
```

To make this change **permanent**, add the same line to your `~/.zshrc`.

{% hint style="danger" %}
Telemetry is completely optional. However, if you disable telemetry, your contributions may not be counted towards the [BlockAssist leaderboard](https://dashboard.gensyn.ai/).
{% endhint %}

#### Linting / Testing

This project uses [Ruff](https://github.com/astral-sh/ruff) to keep code tidy, which sorts imports and auto-fixes simple style issues.

How to run (from the project folder):

```bash
ruff check --select I --fix .
```

If you see `ruff: command not found`, install it once using this command:

```bash
pyenv exec pip install ruff
```

{% hint style="success" %}
If you need additional support, you can [open a ticket](https://github.com/gensyn-ai/blockassist/issues) or [visit our Discord.](https://discord.com/invite/gensyn)&#x20;
{% endhint %}


# Running BlockAssist with Cursor

This guide shows non-technical users how to set up and run BlockAssist on macOS using Cursor, an AI-powered code editor with an integrated chat assistant.

### Prerequisites

Make sure you have **essential deverloper tools** installed by using the commands below, depending on your operating system (OS).&#x20;

{% tabs %}
{% tab title="Windows (WSL 2)" %}
Run this command inside your WSL 2 terminal

```bash
sudo apt update && sudo apt install -y build-essential curl git zip unzip
```

{% endtab %}

{% tab title="Linux" %}
Run this command inside your Ubuntu terminal:

```bash
sudo apt update && sudo apt install -y build-essential curl git zip unzip
```

{% endtab %}

{% tab title="macOS" %}
Run this command inside your macOS terminal:

```bash
xcode-select --install
```

{% endtab %}
{% endtabs %}

### Step 1 — Install Cursor

Go to the [Cursor website](https://cursor.com/) and click Download.

### Step 2 — Set up your Workspace

Open the Cursor app and, on the welcome screen, click *"Clone repo".*

1. Select GitHub from the dropdown and paste `https://github.com/gensyn-ai/blockassist/`&#x20;
2. Pick a local folder where the code will be downloaded.

Once the download finishes, Cursor will open your `blockassist` local folder.

### Step 3 — Install Dependencies

{% hint style="info" %}
You only need to do this once. To record additional episodes, skip to [Running BlockAssist.](/testnet/blockassist/using-blockassist)
{% endhint %}

You should be able to see the "Chat" panel of Cursor on the right side of the screen. If you don’t see the Chat panel, press `ctrl+L` (Windows/Linux) or `cmd+L` (macOS).&#x20;

In the chat window, enter the following prompt:

```
help me install the right dependencies for my operating system according to README.md
```

Cursor will now guide you through the installation steps of various dependencies needed to run BlockAssist. At the end, you should see a message saying the installation is complete.

{% hint style="warning" %}
**macOS Users:** You will need to give Cursor permission to minimize the Minecraft AI assistant window while you play the game. To do this, go to `System Settings` > `Privacy & Security` > `Accessibility` and set the toggle next to Cursor to `ON`.
{% endhint %}

## Troubleshooting

If you see any errors while trying to install or run BlockAssist, Cursor may be able to help you fix the issue and get unblocked.

Otherwise, you can go to the **troubleshooting guides** for your respective operating system by clicking the cards below:

<table data-view="cards"><thead><tr><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td>Windows (WSL 2)</td><td><a href="/pages/IAgcnJEo2OIqC2aXMo8u#troubleshooting">/pages/IAgcnJEo2OIqC2aXMo8u#troubleshooting</a></td></tr><tr><td>Linux</td><td><a href="/pages/ZhMbKsjvcfc6MoR1Quvs#troubleshooting">/pages/ZhMbKsjvcfc6MoR1Quvs#troubleshooting</a></td></tr><tr><td>macOS</td><td><a href="/pages/K7RaUCXgt9PBYMIL7L5x#troubleshooting">/pages/K7RaUCXgt9PBYMIL7L5x#troubleshooting</a></td></tr></tbody></table>

#### Handling Errors in Cursor

To help you understand and fix an error you see in your Terminal, go to the Chat panel on the right and enter the following prompt:&#x20;

```
Help me fix this error
```

* Make sure that Cursor AI can see the error, by clicking on `Add Context` in the chat box and then selecting `Terminal(s)`
* Alternatively, you can also copy and paste the error you see to the chat next to the prompt above.

If you don't see an error but BlockAssist isn't working as expected, you can also ask Cursor to look at your log files. Try using this prompt:&#x20;

```
Look at my logs folder and see if there are any errors preventing BlockAssist from running as expected
```

You can then follow the recommendations from Cursor to help you fix any issues and get unblocked.&#x20;

{% hint style="success" %}
If you need additional support, you can [open a ticket](https://github.com/gensyn-ai/blockassist/issues) or [visit our Discord.](https://discord.com/invite/gensyn)&#x20;
{% endhint %}


# Hugging Face Guide

Follow this quick tutorial to sign up for Hugging Face and generate a private token for use with BlockAssist.

## Getting Tokens for BlockAssist

BlockAssist uses Hugging Face to securely host and share AI models, linking them to your Gensyn Testnet account. Hugging Face ensures models are accessible, auditable, and reusable within the AI ecosystem.

#### Step 1 — Sign Up&#x20;

Go to [Hugging Face](https://huggingface.co/login) and click **Sign Up** in the top right to create a free account.&#x20;

* You can sign up with email/password, or through Google or GitHub
* Already have an account? Click **Sign In.**&#x20;

{% hint style="success" %}
If you have trouble signing up, try a different browser or disable ad blockers.
{% endhint %}

#### Step 3 — Verify your Email (required)

After signing up, check your inbox for a Hugging Face verification email. Then, click the link in the email to verify your address.

This step is required before you can create tokens or upload anything.

{% hint style="warning" %}
Can't find it? Check your spam folder. or log in and click **“Resend Verification”.**
{% endhint %}

#### Step 3 — Generate a New Access Token

This token allows the game to upload a model to your Hugging Face account.

1. Once signed in, click your **profile icon** (top right corner).
2. Select **“Access Tokens”** from the dropdown.
3. Click **“New token”.**
   * **Name:** something like “BlockAssist”.
   * **Role:** choose **Write.**
4. Click **“Create”.**
5. **Copy the token immediately,** as you won’t be able to see it again.

{% hint style="info" %}
When prompted to paste the token, be aware that the token will be **invisible** when pasted, so you won't see it entered into the terminal. Simply paste, then hit `enter` (Windows/Linux) or `return` (macOS).
{% endhint %}

### Common Issues

Here's some common blockers and quick fixes if you encounter any problems regarding Hugging Face:

| Issue                                             | Solution                                                                                                                                                  |
| ------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Not seeing "Access Tokens" menu                   | Make sure you’re logged in and your email is verified.                                                                                                    |
| Copied the token, but didn't save it              | Delete the lost token and generate a new one. Be sure to save it!                                                                                         |
| 403 Client Error: Forbidden                       | Your token might not have *Write* permissions, or may have expired. Generate a new token with Write access.                                               |
| Uploaded model doesn't appear on Hugging Face     | Refresh your Hugging Face profile and check under Repositories → Models and confirm you’re logged into the same Hugging Face account that owns the token. |
| Multiple tokens created, not sure which is active | Delete unused tokens in Settings → Access Tokens. Keep only the one you use for BlockAssist to avoid confusion.                                           |

### Using your New Token with BlockAssist

You're ready to go!&#x20;

Paste your token during game setup, [which you can read about here](/testnet/blockassist/using-blockassist), and start training models and contributing to the Gensyn Testnet.&#x20;

{% hint style="success" %}
If you need additional support, you can [open a ticket](https://github.com/gensyn-ai/blockassist/issues) or [visit our Discord.](https://discord.com/invite/gensyn)&#x20;
{% endhint %}


# CodeAssist (Paused)

CodeAssist is an AI assistant that learns from every edit, keystroke, and solution, adapting to your style and training itself to become the perfect coding partner for you.

{% hint style="warning" %}
**CodeAssist has been sunset.**

As Gensyn prepares for Mainnet, we're consolidating focus around [Delphi](https://app.delphi.fyi/). CodeAssist demonstrated how ML models can train directly on human interactions to create personalized, privacy-preserving models that keep user data local.&#x20;

*These docs are preserved for reference but CodeAssist is no longer actively maintained.*

Alternatively, you can explore [Delphi](https://app.delphi.fyi/), a set of tools for creating information markets.
{% endhint %}

### What is CodeAssist?

CodeAssist opens locally in your browser and turns everyday coding into a learning experiment.

You solve short programming challenges based on LeetCode-style problems, while an on-device model observes your approach, refactors, and final solutions. Over time, the model begins to imitate your reasoning: how you structure loops, name variables, debug logic, and refine solutions.

Each coding session becomes a training “episode,” producing data the app uses to adapt its next set of suggestions.

{% hint style="info" %}
CodeAssist offers a simple, reproducible sandbox for learning. It uses lightweight, single-file challenges without external libraries or tools: just a prompt, code editor, and a test runner.
{% endhint %}

<div data-with-frame="true"><figure><img src="/files/Maoef6xq2tU8UksFg5fy" alt=""><figcaption></figcaption></figure></div>

### Why It Exists

Most AI coding tools are pre-trained on large static datasets. They either autocomplete or autosuggest code based on the context available to them, but they don't *learn* from you.&#x20;

CodeAssist is an interactive product that explores a new paradigm, being a code assistant that evolves from your own problem-solving style. It's built to demonstrate "assistance learning", a branch of RL where the user becomes the teacher.&#x20;

Much like BlockAssist, which learns Minecraft gameplay by mimicking user actions and receiving feedback through user intervention, CodeAssist models are trained to reinforce programming concepts and principles through editing, deleting, or retaining the assistant's output.

By grounding this in a lightweight, browser-based environment, CodeAssist provides a simple, auditable example of decentralized training and coordination in action.

{% hint style="info" %}
CodeAssist and [BlockAssist](/testnet/blockassist) demonstrate “assistance learning”, where AI that learns directly from human actions, not just static datasets while giving users a hands-on way to contribute to and experiment with decentralized AI training.
{% endhint %}

### How It Works

CodeAssist gives you a hands-on way to contribute to and experiment with decentralized AI training while improving your LeetCode skills.&#x20;

1. **Start Locally:** Launch CodeAssist in your browser. Each sessions spins up a contained coding environment.&#x20;
2. **Choose a Problem:**
3. **Code and Test:** CodeAssist tracks your edits and cursor movements, suggesting code additions like new lines, comments, and functions. It may also edit your code.
4. **Learn and Adapt:** After recording your "episode," the model reviews data from your coding session to learn your preferences and patterns.
5. **Iterate:** In the following sessions, CodeAssist continues fine-tuning the local model to seed new suggestions, like completions, refactors, and hints, based on the patterns it learned. The model will improve to code more like *you* over time.
6. **(Optional) Upload to Hugging Face:** Once you’re happy with your personal CodeAssist model, you can share it on Hugging Face and track your contribution to a decentralized, verifiable ledger of model improvements on the [Gensyn Testnet](https://www.gensyn.ai/testnet).

#### Why LeetCode?

All CodeAssist coding prompts are drawn from LeetCode-style problems.

We use them as a lightweight, well-understood medium for training because they strike a balance between simplicity and structure.&#x20;

They are:

1. **Self-contained:** These single-file challenges that run directly in your browser with no dependencies or setup.&#x20;
2. **Familiar:** Many developers already understand the format, which reduces friction when learning a new tool.&#x20;
3. **Measured and gradable:** Each problem has clear test cases and difficulty levels, which provides a natural way to track model progress.&#x20;
4. **Accessible:** CodeAssist leverages an existing public dataset of problems and test suites to ensure consistency across users.

{% hint style="success" %}
Using LeetCode as the sandbox keeps CodeAssist lightweight, fair, and approachable, so the focus stays on how *you* solve problems, not on configuring an environment.
{% endhint %}

#### Get Started

Ready to spin up CodeAssist and start training a local machine learning model (ML) to code like you today? Choose one of the installation guides below, or head directly to [this walkthrough guide.](/testnet/codeassist/using-codeassist)

<table data-view="cards"><thead><tr><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>Windows (WSL 2)</strong></td><td><a href="/pages/1auzmR4UE3dJLDHvgtCF">/pages/1auzmR4UE3dJLDHvgtCF</a></td></tr><tr><td><strong>Linux (Ubuntu 22.04+)</strong></td><td><a href="/pages/nVHDGxnVGE9Y5qMjIL3v">/pages/nVHDGxnVGE9Y5qMjIL3v</a></td></tr><tr><td><strong>macOS (Intel &#x26; ARM)</strong></td><td><a href="/pages/LTkb62eKBB1kiVr2IvsO">/pages/LTkb62eKBB1kiVr2IvsO</a></td></tr></tbody></table>


# Getting Started

Get up and running with CodeAssist and start training local models based to code like you.

{% embed url="<https://github.com/gensyn-ai/codeassist>" %}

{% hint style="warning" %}
CodeAssist has been sunset. Please see the [home page](/testnet/codeassist) for more information.
{% endhint %}

## Overview

This page helps you prepare your system and choose the correct installation path for CodeAssist.&#x20;

It provides a readiness checklist, supported platforms, and an overview of the setup process before you begin installing and running CodeAssist on your device.

<div data-with-frame="true"><figure><img src="/files/K1oX1xYEH5pcPJ4k9Kxh" alt=""><figcaption></figcaption></figure></div>

### Before you Begin

CodeAssist is available across several environments: [Windows (via WSL 2)](/testnet/codeassist/getting-started/windows-wsl-2), [Linux (Ubuntu 22.04+)](/testnet/codeassist/getting-started/linux), and [macOS (Intel and Apple Silicon).](/testnet/codeassist/getting-started/macos)

{% hint style="info" %}
A virtual private server (VPS) is **not** required to run CodeAssist.
{% endhint %}

Before you start, make sure you meet the basic requirements and have the necessary accounts.

#### System Requirements <a href="#system-requirements" id="system-requirements"></a>

* 8 GB RAM minimum (32 GB recommended)
* Stable internet connection
* At least 10 GB of available storage (for overhead)
* Modern multi-core CPU (Intel, AMD, or Apple Silicon)

#### Software Requirements

* [Docker](https://docs.docker.com/engine/install/)
* [Python 3.10+](https://www.python.org/downloads/)
* [Homebrew](mailto:undefined) (if installing on [macOS](/testnet/codeassist/getting-started/macos))
* [Git](https://git-scm.com/install) (for cloning the repo)

#### Accounts & Access

* **Hugging Face account:** You’ll need a Write-access API token to upload your model after training. See the [Hugging Face Guide](/testnet/codeassist/hugging-face-guide) for instructions.
* **Gensyn Testnet account:** Automatically created when you first log in through your browser during setup.

{% hint style="info" %}
When logging in, different types of External Object Identifiers (EOA) are assigned based on the authentication method used.&#x20;

Google authentication typically assigns an EOA linked to the user's Google account. On the other hand, logging in via OTP (One-Time Password) often results in an EOA tied to the mobile number or email address used for the OTP process.
{% endhint %}

#### Quickstart

You can find the quickstart commands for cloning the repository and installing dependencies below. If you take this route, it's recommended to use an IDE like Cursor in case you experience any initial issues.&#x20;

1. Run this sequence of commands in your terminal:

```bash
git clone https://github.com/gensyn-ai/codeassist
cd codeassist
uv run run.py
```

2. Open CodeAssist, load a LeetCode problem, and check that the container starts successfully.
3. You can also use the following commands to verify you've installed all the required dependencies correctly:

```bash
docker --version
python3 --version
uv --version
```

If you encounter any errors, head over to the [Troubleshooting](/testnet/rl-swarm/troubleshooting) page.

### Supported Platforms & Installation Paths

See platform-specific installation instructions below.

<table data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>Windows (WSL 2)</strong> </td><td>Install, run, and train models in a Linux-based Windows environment. </td><td><a href="/pages/1auzmR4UE3dJLDHvgtCF">/pages/1auzmR4UE3dJLDHvgtCF</a></td></tr><tr><td><strong>Linux (Ubuntu 22.04+)</strong></td><td>Install CodeAssist natively on Ubuntu or a compatible distribution for the most stable experience.</td><td><a href="/pages/nVHDGxnVGE9Y5qMjIL3v">/pages/nVHDGxnVGE9Y5qMjIL3v</a></td></tr><tr><td><strong>macOS (Intel &#x26; Apple Silicon)</strong></td><td>Install and run CodeAssist on macOS devices using <code>brew</code> or <code>curl</code> for dependency management. Both Intel and M-Series CPUs are supported. </td><td><a href="/pages/LTkb62eKBB1kiVr2IvsO">/pages/LTkb62eKBB1kiVr2IvsO</a></td></tr></tbody></table>


# Windows (WSL 2)

Get up and running with CodeAssist in your Windows (WSL 2) environment.

## Overview

This guide explains how to install and run CodeAssist on Windows using the Windows Subsystem for Linux 2 (WSL 2).

### Prerequisites

Before installing CodeAssist, make sure you have:

* Windows 10 or 11 with WSL 2 enabled and running.&#x20;
* A Linux distribution installed under WSL 2
* Administrator privileges on your device
* A [Hugging Face](https://huggingface.co/) account for authentication

### Dependencies

CodeAssist requires the following software components:

| Dependency                                        | Purpose                                                | Minimum Version |
| ------------------------------------------------- | ------------------------------------------------------ | --------------- |
| [Docker](https://docs.docker.com/engine/install/) | Runs the isolated CodeAssist container environment     | Latest stable   |
| [Python](https://www.python.org/downloads/)       | Executes the environment management and web UI Scripts | 3.10+           |
| UV                                                | Manages Python dependencies and virtual environments   | Latest stable   |

#### Docker & Python

Install [Docker](https://docs.docker.com/engine/install/) and [Python](https://www.python.org/downloads/) according to the installation steps for your platform.&#x20;

{% hint style="warning" %}
Make sure that Docker is open before trying to run CodeAssist. If this is your first time installing Docker, it should auto-open.

However, if you close or restart your system, **make sure to reopen the Docker desktop application,** or else you will encounter container connection failures.
{% endhint %}

#### UV

To install UV, a lightweight dependency manager used to handle the project's Python environment, use the following command inside your WSL 2 terminal:

```bash
curl -LsSf https://astral.sh/uv/install.sh | sh
```

You can then check if the installation was successful and check the version of UV installed with `uv --version`.

### Installation Steps

1. Open your WSL 2 terminal (Ubuntu or another distro).
2. Clone the CodeAssist repository:

```bash
git clone https://github.com/gensyn-ai/codeassist.git
cd codeassist
```

{% hint style="warning" %}
If you’re also running [RL Swarm](/testnet/rl-swarm) or another Docker-based Gensyn project, ensure that `port:3000` is free before launching CodeAssist.
{% endhint %}

#### Run CodeAssist

To open CodeAssist, run the following command in your terminal:

```bash
uv run run.py
```

The first run may take several minutes as Docker builds the environment and downloads required components.&#x20;

{% hint style="warning" %}
To ensure CodeAssist functions optimally, avoid modifying the `compose.yml` file. Editing this file undermines the run script's purpose and may prevent functionalities such as uploading trained models to Hugging Face, interacting with smart contracts, or earning Testnet participation points.
{% endhint %}

<div data-with-frame="true"><figure><img src="/files/0GrNQkloxcJazG0Kn9zZ" alt=""><figcaption></figcaption></figure></div>

Once running, CodeAssist automatically launches in your browser. If it doesn't, visit the following localhost URL and open it manually:

```url
http://localhost:3000
```

### Authentication&#x20;

CodeAssist uses Hugging Face tokens for authentication and model uploads.

1. Visit your **Hugging Face profile > Settings > Access Tokens.**
2. Generate a **New Token** with 'Write' access.
3. Copy the token string.
4. When starting CodeAssist, the application will prompt you for the token. Paste it into the terminal or web interface.

{% hint style="info" %}
Read the [Hugging Face Guide](/testnet/codeassist/hugging-face-guide) for help setting up a token, what it's used for, and basic troubleshooting.
{% endhint %}

### Next Steps

Once setup is complete, open CodeAssist, pick your first LeetCode-style problem, and start coding!&#x20;

You can view this [comprehensive walkthrough](/testnet/codeassist/using-codeassist) for instructions on how to use CodeAssist, any best practices and tips, and what to expect when training models, or visit the [Troubleshooting](/testnet/codeassist/troubleshooting) page if you need help setting up CodeAssist.

{% hint style="success" %}
If you need additional support, you can [open a ticket](https://github.com/gensyn-ai/codeassist/issues) or [visit our Discord.](https://discord.com/invite/gensyn)
{% endhint %}


# Linux

Get up and running with CodeAssist in your Linux (Ubuntu 22.04+) environment.

## Overview

This guide explains how to install and run CodeAssist on Linux.&#x20;

### Prerequisites

Before installing CodeAssist, make sure you have:

* A compatible Linux distribution (Ubuntu 22.04+ LTS recommended)&#x20;
* Administrator (`sudo`) privileges on your device
* A [Hugging Face](https://huggingface.co/) account for authentication

### Dependencies

CodeAssist requires the following software components:

| Dependency                                        | Purpose                                                | Minimum Version |
| ------------------------------------------------- | ------------------------------------------------------ | --------------- |
| [Docker](https://docs.docker.com/engine/install/) | Runs the isolated CodeAssist container environment     | Latest stable   |
| [Python](https://www.python.org/downloads/)       | Executes the environment management and web UI Scripts | 3.10+           |
| UV                                                | Manages Python dependencies and virtual environments   | Latest stable   |

#### Docker & Python

Install [Docker](https://docs.docker.com/engine/install/) and [Python](https://www.python.org/downloads/) according to the installation steps for your platform.&#x20;

{% hint style="warning" %}
Make sure that Docker is open before trying to run CodeAssist. If this is your first time installing Docker, it should auto-open.

However, if you close or restart your system, **make sure to reopen the Docker desktop application,** or else you will encounter container connection failures.
{% endhint %}

#### UV

To install UV, a lightweight dependency manager used to handle the project's Python environment, use the following command inside your terminal:

```bash
curl -LsSf https://astral.sh/uv/install.sh | sh
```

You can then check if the installation was successful and check the version of UV installed with `uv --version`.

### Installation Steps

1. Open your terminal
2. Clone the CodeAssist repository:

```bash
git clone https://github.com/gensyn-ai/codeassist.git
cd codeassist
```

{% hint style="warning" %}
If you’re also running [RL Swarm](/testnet/rl-swarm) or another Docker-based Gensyn project, ensure that `port:3000` is free before launching CodeAssist.
{% endhint %}

#### Run CodeAssist

To open CodeAssist, run the following command in your terminal:

```bash
uv run run.py
```

The first run may take several minutes as Docker builds the environment and downloads required components.&#x20;

{% hint style="warning" %}
To ensure CodeAssist functions optimally, avoid modifying the `compose.yml` file. Editing this file undermines the run script's purpose and may prevent functionalities such as uploading trained models to Hugging Face, interacting with smart contracts, or earning Testnet participation points.
{% endhint %}

<div data-with-frame="true"><figure><img src="/files/BR2E1t62G2WtTI3IcDtV" alt=""><figcaption></figcaption></figure></div>

Once running, CodeAssist automatically launches in your browser. If it doesn't, visit the following localhost URL and open it manually:

```url
http://localhost:3000
```

### Authentication&#x20;

CodeAssist uses Hugging Face tokens for authentication and model uploads.

1. Visit your **Hugging Face profile > Settings > Access Tokens.**
2. Generate a **New Token** with 'Write' access.
3. Copy the token string.
4. When starting CodeAssist, the application will prompt you for the token. Paste it into the terminal or web interface.

{% hint style="info" %}
Read the [Hugging Face Guide](/testnet/codeassist/hugging-face-guide) for help setting up a token, what it's used for, and basic troubleshooting.
{% endhint %}

### Next Steps

Once setup is complete, open CodeAssist, pick your first LeetCode-style problem, and start coding!&#x20;

You can view this [comprehensive walkthrough](/testnet/codeassist/using-codeassist) for instructions on how to use CodeAssist, any best practices and tips, and what to expect when training models, or visit the [Troubleshooting](/testnet/codeassist/troubleshooting) page if you need help setting up CodeAssist.

{% hint style="success" %}
If you need additional support, you can [open a ticket](https://github.com/gensyn-ai/codeassist/issues) or [visit our Discord.](https://discord.com/invite/gensyn)
{% endhint %}


# macOS

Get up and running with CodeAssist in your macOS environment.

## Overview

This guide explains how to install and run CodeAssist on macOS.

{% hint style="success" %}
This guide is compatible with both Intel and ARM (Apple Silicon, i.e., M1/M2/M3/M4) macOS devices.&#x20;
{% endhint %}

### Prerequisites

Before installing CodeAssist, make sure you have:

* macOS 12 (Monterey) or newer
* Administrator privileges on your device
* A [Hugging Face](https://huggingface.co/) account for authentication

### Dependencies

CodeAssist requires the following software components:

| Dependency                                        | Purpose                                                | Minimum Version |
| ------------------------------------------------- | ------------------------------------------------------ | --------------- |
| [Docker](https://docs.docker.com/engine/install/) | Runs the isolated CodeAssist container environment     | Latest stable   |
| [Python](https://www.python.org/downloads/)       | Executes the environment management and web UI Scripts | 3.10+           |
| UV                                                | Manages Python dependencies and virtual environments   | Latest stable   |

#### Docker & Python

Install [Docker](https://docs.docker.com/engine/install/) and [Python](https://www.python.org/downloads/) according to the installation steps for your platform.&#x20;

{% hint style="warning" %}
Make sure that Docker is open before trying to run CodeAssist. If this is your first time installing Docker, it should auto-open.

However, if you close or restart your system, **make sure to reopen the Docker desktop application,** or else you will encounter container connection failures.
{% endhint %}

#### UV

To install UV, a lightweight dependency manager used to handle the project's Python environment, use the following command inside your terminal:

```bash
brew install uv
```

Alternatively, you can install using a `curl` command if you don't have [Brew](https://brew.sh/) installed.&#x20;

```bash
curl -LsSf https://astral.sh/uv/install.sh | sh
```

You can then check if the installation was successful and check the version of UV installed with `uv --version`.

### Installation Steps

1. Open your terminal
2. Clone the CodeAssist repository:

```bash
git clone https://github.com/gensyn-ai/codeassist.git
cd codeassist
```

{% hint style="warning" %}
If you’re also running [RL Swarm](/testnet/rl-swarm) or another Docker-based Gensyn project, ensure that `port:3000` is free before launching CodeAssist.
{% endhint %}

#### Run CodeAssist

To open CodeAssist, run the following command in your terminal:

```bash
uv run run.py
```

The first run may take several minutes as Docker builds the environment and downloads required components.&#x20;

{% hint style="warning" %}
To ensure CodeAssist functions optimally, avoid modifying the `compose.yml` file. Editing this file undermines the run script's purpose and may prevent functionalities such as uploading trained models to Hugging Face, interacting with smart contracts, or earning Testnet participation points.
{% endhint %}

<div data-with-frame="true"><figure><img src="/files/qfrdf9m9UrkSZqBLYEzk" alt=""><figcaption></figcaption></figure></div>

Once running, CodeAssist automatically launches in your browser. If it doesn't, visit the following localhost URL and open it manually:

```url
http://localhost:3000
```

### Authentication&#x20;

CodeAssist uses Hugging Face tokens for authentication and model uploads.

1. Visit your **Hugging Face profile > Settings > Access Tokens.**
2. Generate a **New Token** with 'Write' access.
3. Copy the token string.
4. When starting CodeAssist, the application will prompt you for the token. Paste it into the terminal or web interface.

{% hint style="info" %}
Read the [Hugging Face Guide](/testnet/codeassist/hugging-face-guide) for help setting up a token, what it's used for, and basic troubleshooting.
{% endhint %}

### Next Steps

Once setup is complete, open CodeAssist, pick your first LeetCode-style problem, and start coding!&#x20;

You can view this [comprehensive walkthrough](/testnet/codeassist/using-codeassist) for instructions on how to use CodeAssist, any best practices and tips, and what to expect when training models, or visit the [Troubleshooting](/testnet/codeassist/troubleshooting) page if you need help setting up CodeAssist.

{% hint style="success" %}
If you need additional support, you can [open a ticket](https://github.com/gensyn-ai/codeassist/issues) or [visit our Discord.](https://discord.com/invite/gensyn)
{% endhint %}


# Using CodeAssist

Read the end-to-end CodeAssist user guide and start training your own personal coding model.

Overview

This guide walks you through every step of using CodeAssist, from the moment you launch it to the point you begin training your own personalized coding model, covering **setup, coding behavior, rewards, training** and **best practices.**&#x20;

## Video Walkthrough

If you're more of a visual learner, watch the video tutorial below for an end-to-end walkthrough on setting up and using CodeAssist, training models, and learn about best practices for improving model training.&#x20;

***

{% embed url="<https://youtu.be/ahfmHdNwYbk>" fullWidth="false" %}

***

### How does CodeAssist Work?

Unlike typical code assistants, CodeAssist doesn’t offer suggestions you *accept* or *reject*.

It writes directly into your editor in real time, and your actions, such as when you **type**, **fix**, **delete**, or **leave** its output untouched, become training signals that shape how it learns from you.

### Understanding the Assistant

CodeAssist runs two coordinated models:

* A frozen language model (Qwen2.5) that proposes code edits, comments, or reasoning steps.
* A trainable action-selection model that learns *how* to assist *you* based on your interactions and feedback.

> You are not using an agent or an autocomplete system: rather, *you* are training an *assistant!*

#### What This Means

The assistant watches your typing and timing. When you pause, it may generate code, refactor what’s there, or insert a comment.

How you respond to those actions, such as **accepting, modifying,** or **deleting** determines how the model learns. This is the foundation of CodeAssist's **reward vs. punishment** system and are later interpreted as reinforcement signals.

{% hint style="info" %}
Think of it as an 'apprentice' of sorts. It observes how you work, makes attempts, and improves once the episode training has completed.
{% endhint %}

### Launch & Login

To install CodeAssist, visit the [Getting Started](/testnet/codeassist/getting-started) page or use the platform-specific buttons below for detailed instructions on managing dependencies and installing CodeAssist.

<table data-view="cards"><thead><tr><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>Windows (WSL 2)</strong></td><td><a href="/pages/1auzmR4UE3dJLDHvgtCF">/pages/1auzmR4UE3dJLDHvgtCF</a></td></tr><tr><td><strong>Linux (Ubuntu 22.04+)</strong></td><td><a href="/pages/nVHDGxnVGE9Y5qMjIL3v">/pages/nVHDGxnVGE9Y5qMjIL3v</a></td></tr><tr><td><strong>macOS (Intel &#x26; ARM)</strong></td><td><a href="/pages/LTkb62eKBB1kiVr2IvsO">/pages/LTkb62eKBB1kiVr2IvsO</a></td></tr></tbody></table>

After installation, it's time to start CodeAssist from your terminal:

```bash
uv run run.py
```

This command spins up a local Docker environment and launches the web server at `localhost:3000` which automatically opens in your device's default browser.

<div data-with-frame="true"><figure><img src="/files/gEiq6b8yX3tgTjPqockZ" alt=""><figcaption></figcaption></figure></div>

When the web UI loads, you'll see the **Login Modal.**&#x20;

<div data-with-frame="true"><figure><img src="/files/71RplEuPRDsXZaF0aWuu" alt=""><figcaption></figcaption></figure></div>

Here, you can log in with email, or with Google. Logging in with email will send a one-time passcode (OTP) to your email.&#x20;

{% hint style="info" %}
Once you've logged in for the first time, a file called `persistent-data/auth/userKeyMap.json` will be generated, which stores your local credentials.&#x20;
{% endhint %}

#### Selecting a Problem

From the **Problems Sidebar** on the left-hand side, you can choose **Easy, Medium** or **Hard** problems.&#x20;

By default, you will have landed on a randomly-selected problem.&#x20;

If you want to change your problem, you can select the difficulty level from the dropdown to be assigned a new problem in that difficulty, or click the **Shuffle** button to get a *new* problem within your selected difficulty.&#x20;

<div data-with-frame="true"><figure><img src="/files/Maoef6xq2tU8UksFg5fy" alt=""><figcaption></figcaption></figure></div>

### Recording an Episode

Every time you run the launch command and open up CodeAssist in your browser, CodeAssist begins **recording an episode.**&#x20;

Each click, keyboard stroke, edit, acceptance, or deletion is logged as training feedback.&#x20;

> This is how the model trains once recording is finished: it examines *every action you took,* then trains in an attempt to emulate *you.*&#x20;

In that light, it is extremely important to work with the assistant patiently. Finishing solutions to LeetCode problems too quickly, or deleting everything the assistant adds to the `.txt` file immediately post-generation can neutralizing effects on the efficacy of that episode's training.&#x20;

{% hint style="danger" %}
In other words, rushing the model and aggressively correcting won't give it the chance to learn.&#x20;
{% endhint %}

### Coding with CodeAssist

When you stop typing, CodeAssist may begin typing for you. It doesn’t ask for confirmation. Instead, it acts directly in your file.

<div data-with-frame="true"><figure><img src="/files/5qCIatIG988hPet4ddLT" alt=""><figcaption></figcaption></figure></div>

At this point, when the assistant has generated code or made changes, you can:

* Let its code stay
* Edit or refine its generation
* Delete entire lines
* Rearrange code or fix indentation

Each of these choices then becomes a training signal post-recording.&#x20;

#### Rewards & Timing

| Your Action                            | Interpreted Signal         |
| -------------------------------------- | -------------------------- |
| Leave the assistant's code untouched   | *Positive* reward          |
| Edit it after a short delay            | *Moderate* positive reward |
| Delete it after working around it      | *Mild* negative reward     |
| Delete it immediately after it appears | *Harsh* negative penalty   |

If you delete everything it writes right away, you’re essentially teaching it to stop acting altogether.

{% hint style="warning" %}
Sometimes it’s better to let a generation live briefly, let it try one more move, and then delete or fix it to teach *gradual correction* and not *total rejection.*
{% endhint %}

#### Pausing

You can press `shift + space` or click the **Pause Assistant** button to temporarily stop the assistant. Typing anything (or even a space or cursor click) after pausing will **unpause it.**&#x20;

<div data-with-frame="true"><figure><img src="/files/yYacPRUdsx6IN0r5CE4q" alt=""><figcaption></figcaption></figure></div>

#### No-Ops

When the assistant produces a **No-Op**, as in it does *nothing,* it's waiting for you. This is intentional. **No-Op** means the assistant is not confident enough to act. Make an an edit or press a key to resume.

{% hint style="info" %}
This is not a bug, it's a feature signaling that it's *your turn.*&#x20;
{% endhint %}

#### Cursor Awareness

CodeAssist inserts code relative to your current cursor position. If your cursor sits at the bottom of the file and isn’t indented, new code may appear misaligned.

Keep your cursor near the section you’re working on. If something looks misplaced, re-indent with `tab` and `shift tab` or move your cursor before letting the assistant act.

#### Context&#x20;

Each LeetCode problem has the actual written problem on the left side, with the text field on the right.&#x20;

There's also a starter function. However, the starter function and imports are *masked* (read-only) to prevent the assistant from editing them.

<div data-with-frame="true"><figure><img src="/files/Jef2Mpd07vdPIKuUYoVW" alt=""><figcaption></figcaption></figure></div>

If you want to modify those lines, make a small manual edit, even a space, to unlock them.

{% hint style="warning" %}
Unlocking (unmasking) the initial solution shell *will* open up that starting function to the assistant, which means it will gain context to the problem's solution, but can also change that starter function.&#x20;
{% endhint %}

#### Keyboard Shortcuts & Controls

If you're relatively new to coding, there are several common keyboard shortcuts and controls commonly used when editing code in development tools that are handy to learn.

| Action                         | Shortcut                   |
| ------------------------------ | -------------------------- |
| Pause / Resume                 | `shift + space`            |
| Undo                           | `ctrl/command + z`         |
| Redo                           | `ctrl/command + shift + z` |
| Indent / Outdent selected code | `tab / shift + tab`        |
| Stop recording (end episode)   | `ctrl + c`                 |

#### Testing your Solution

When you're ready to test your code, click **Submit Solution.**&#x20;

* If your solution is incorrect, you will see a modal pop up that prompts you to return to the problem and try again.&#x20;

Then, you will also see the **Test Case** section, which is a solution tester, containing **Tests Passed, Error(s) Found In Case,** and **Cases Pending** section.&#x20;

This is a standardized solution tester which will contain `input`, `stdout`, and `output`, expected results, and any relevant errors (such as tracebacks) including the line the error was found on.

* If your solution is correct, you will be prompted with a different modal to return the problem *or* proceed to a new one. Congratulations!

{% columns %}
{% column %}

<figure><img src="/files/VqsjjAFmrp9k1sjPNoi8" alt=""><figcaption></figcaption></figure>
{% endcolumn %}

{% column %}

<figure><img src="/files/pY8kskNlJvDWRj0xL39P" alt=""><figcaption></figcaption></figure>
{% endcolumn %}
{% endcolumns %}

### Completing an Episode & Training your Model

Once you're done coding, you can complete the episode recording and train the model. To do this, return to your terminal (or IDE, if running CodeAssist from within a developer tool like Cursor or VS Code) and input `ctrl + c`.&#x20;

{% hint style="success" %}
You do **not** need to successfully solve a LeetCode problem to train the model. At any point, once the CodeAssist web UI is running in your browser, you can stop training with `ctrl + c`.&#x20;
{% endhint %}

During training, CodeAssist will:

* Compare your edits to the assistants actions
* Calculate rewards and penalties based on your reaction to the assistant's code generations&#x20;
* Updates your local model checkpoint
* Take a few minutes (depending on your system specifications) and store new model weights under `~/.codeassist/models`
* Upload your trained model to Hugging Face [using your previously-set Hugging Face token](/testnet/codeassist/hugging-face-guide)

<div data-with-frame="true"><figure><img src="/files/j4FXonZIUZLN9d6DfQmY" alt=""><figcaption></figcaption></figure></div>

At this point, you can <mark style="color:$success;">restart CodeAssist to use your updated model</mark> trained on your most recent episode.&#x20;

### Best Practices for Effective Training

Every user starts with a pre-trained baseline model tuned to generic behavior. As such, your first few episodes may feel inconsistent. This is normal.

#### Expectations

Early on, the model may feel 'too quiet' or 'too confident.' After 1-2 training runs, the model's performance can also *regress* as it begins calibrating to your coding habits.&#x20;

Improvement becomes more and more clear after a minimum of **4-5 episodes of training.**&#x20;

{% columns %}
{% column %}

#### Do

* Treat CodeAssist as a collaborator, not an agent or an autocomplete tool.&#x20;
* Keep coding normally and let it naturally interject code.&#x20;
* Reward 'good enough' behavior by keeping useful code around for a minute before editing or removing.&#x20;
* Relax! This is *experimental research,* not an interview environment.&#x20;
* Record multiple varied problems to diversify its learning signals.&#x20;
  {% endcolumn %}

{% column %}

#### Don't&#x20;

* Expect it to solve problems end-to-end.&#x20;
* Delete every generation instantly, even if its wrong, as this will encourage 'passivity.'
* Sit back and wait for it to code everything for you.&#x20;
* Panic when it begins typing unexpectedly or indenting pieces of code. Give it a moment to figure things out and patiently guide it towards outputting code that you want!
  {% endcolumn %}
  {% endcolumns %}

### Iterating & Improving

After you've finished training, you can restart and rerun CodeAssist using the command below:

```bash
uv run run.py
```

This will reopen the web UI, and you can select a new problem and begin coding again.&#x20;

At this point, especially after 4-5 training runs, notice subtle changes in how CodeAssist acts: timing, confidence, where it chooses the help, how much code it generates and where, and especially any stylistic peculiarities it has when generating code comments.&#x20;

Continue recording and training to refine your assistant over time!

***

### Next Steps

CodeAssist is designed to explore what *personalized assistance learning* looks like, and a machine learning (ML) model that adapts to individuals through the curation of a 'dataset' containing one user's training data, not a general, globally-available dataset.&#x20;

Visit the [Troubleshooting](/testnet/codeassist/troubleshooting) page if you're having any issues with running or installing CodeAssist, setting up dependencies (like Docker) or running into problems training your model.

{% hint style="success" %}
If you need additional support, you can [open a ticket](https://github.com/gensyn-ai/codeassist/issues) or [visit our Discord.](https://discord.com/invite/gensyn)
{% endhint %}


# Hugging Face Guide

Follow this quick tutorial to sign up for Hugging Face and generate a private token for use with CodeAssist.

## Getting Tokens for CodeAssist

CodeAssist uses Hugging Face to securely host and share AI models, linking them to your Gensyn Testnet account. Hugging Face ensures models are accessible, auditable, and reusable within the AI ecosystem.

#### Step 1 — Sign Up&#x20;

Go to [Hugging Face](https://huggingface.co/login) and click **Sign Up** in the top right to create a free account.&#x20;

* You can sign up with email/password, or through Google or GitHub
* Already have an account? Click **Sign In.**&#x20;

{% hint style="success" %}
If you have trouble signing up, try a different browser or disable ad blockers.
{% endhint %}

#### Step 3 — Verify your Email (required)

After signing up, check your inbox for a Hugging Face verification email. Then, click the link in the email to verify your address.

This step is required before you can create tokens or upload anything.

{% hint style="warning" %}
Can't find it? Check your spam folder. or log in and click **“Resend Verification”.**
{% endhint %}

#### Step 3 — Generate a New Access Token

This token allows the game to upload a model to your Hugging Face account.

1. Once signed in, click your **profile icon** (top right corner).
2. Select **“Access Tokens”** from the dropdown.
3. Click **“New token”.**
   * **Name:** something like “CodeAssist”.
   * **Role:** choose **Write.**
4. Click **“Create”.**
5. **Copy the token immediately,** as you won’t be able to see it again.

{% hint style="info" %}
When prompted to paste the token, be aware that the token will be **invisible** when pasted, so you won't see it entered into the terminal. Simply paste, then hit `enter` (Windows/Linux) or `return` (macOS).
{% endhint %}

### Common Issues

Here's some common blockers and quick fixes if you encounter any problems regarding Hugging Face:

| Issue                                             | Solution                                                                                                                                                  |
| ------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Not seeing "Access Tokens" menu                   | Make sure you’re logged in and your email is verified.                                                                                                    |
| Copied the token, but didn't save it              | Delete the lost token and generate a new one. Be sure to save it!                                                                                         |
| 403 Client Error: Forbidden                       | Your token might not have *Write* permissions, or may have expired. Generate a new token with Write access.                                               |
| Uploaded model doesn't appear on Hugging Face     | Refresh your Hugging Face profile and check under Repositories → Models and confirm you’re logged into the same Hugging Face account that owns the token. |
| Multiple tokens created, not sure which is active | Delete unused tokens in Settings → Access Tokens. Keep only the one you use for CodeAssist to avoid confusion.                                            |

### Using your New Token with CodeAssist

You're ready to go!&#x20;

Paste your token during CodeAssist setup, [which you can read about here](/testnet/blockassist/using-blockassist), and start training models and contributing to the Gensyn Testnet.&#x20;

{% hint style="success" %}
If you need additional support, you can [open a ticket](https://github.com/gensyn-ai/codeassist/issues) or [visit our Discord.](https://discord.com/invite/gensyn)&#x20;
{% endhint %}


# Troubleshooting

Stuck? Get unblocked with CodeAssist on Windows (WSL 2), Linux, or macOS, or reach out to support for more help.

## Overview

This page helps you diagnose and resolve common issues encountered while running or using CodeAssist. It covers both runtime behaviors (inside the CodeAssist UI) and system errors (Docker or environment-related).

### Environment & Docker Errors

These issues occur before or during CodeAssist startup.

#### Exception: Container is unhealthy

This can occur when a Docker container fails to start properly.&#x20;

1. Check container logs:

```bash
docker logs <container-name>
```

2. Review the output for startup errors.&#x20;
3. Restart Docker and rerun CodeAssist:

```bash
sudo systelctl restart docker
uv run run.py
```

#### Error connecting to Docker daemon

If Docker isn't running, or your user lacks permission to access it, you may encounter an error that looks much like this one:

```bash
2025-09-04 15:03:47,975 - ERROR - Error connecting to Docker daemon:
Error while fetching server API version: ('Connection aborted.', FileNotFoundError(2, 'No such file or directory'))
2025-09-04 15:03:47,976 - ERROR - Please ensure Docker is installed and running.
```

1. Ensure Docker desktop (macOS and Windows) or Docker Engine (Linux) is open and running.&#x20;
2. You may need to restart Docker. If so, use this command:

```bash
sudo systemctl restart docker
```

3. Then, test your connection to Docker:

```bash
docker ps
```

4. If you still see the error, verify your user is in the `docker` group using this command:

```bash
sudo usermod -aG docker $USER
```

5. Log out and log back in.

{% hint style="info" %}
If CodeAssist crashes and Docker containers aren't shutting down correctly, use `docker stop $(docker ps -q)` to kill and restart all containers.&#x20;
{% endhint %}

#### Bind for 0.0.0.0:3000 failed: port is already allocated

This is a common issue you might experience if already running other Gensyn products, like [BlockAssist](/testnet/blockassist) or [RL Swarm.](/testnet/rl-swarm)

If a container, such as another Gensyn service, is already using `port:3000`, then the Docker containers will refuse to open. \
\
You have two options:

1. Stop the other service that is using the port (e.g., if you're running RL Swarm)
2. Run CodeAssist on a different port using the following `--port` argument:

```bash
uv run run.py --port 3001
```

When choosing a new port, please avoid `8000`, `8080`, `8001`, `8008`, `3003`, and `11434`, as they are reserved for other CodeAssist services.

{% hint style="info" %}
To check what containers are currently running, you can use the `docker ps` command or use the Docker Desktop UI.&#x20;
{% endhint %}

***

### Common Runtime Behaviors

These are expected or semi-expected quirks of the current CodeAssist prototype. They are **not necessarily bugs**, but knowing what they mean can save you time.

#### No-Ops (Assistant Stops Typing)

Sometimes, the assistant can enter a “no-operation” state. It’s unsure what to do next.

To fix this, simply move your cursor, add a space, or make any small edit. This resumes generation immediately.

{% hint style="info" %}
A **No-Op** is intentional. It signals when it is 'your turn.'
{% endhint %}

#### Broken Constraints in Problems

Some imported LeetCode problems include invalid or computationally infeasible test cases. You may encounter test cases that hang or never complete, and inputs that do not match the problem's listed constraints.&#x20;

{% hint style="danger" %}
This is due to the publicly-available, 3rd party LeetCode problem/solution dataset used within CodeAssist.
{% endhint %}

To fix this, choose a new problem from the sidebar and continue training. The issue is dataset-specific, not user-specific.&#x20;

#### "Wandering" Behavior

Rarely, the assistant will overwrite the starter function or switch to solving a different problem.&#x20;

To fix this:

1. Pause with `shift + space` or the UI button
2. Save your work by copying & pasting it elsewhere (if needed)
3. Restart CodeAssist (`ctrl + c`) then rerun with `uv run run.py`

#### Non-Linear Learning

After your first or second training run, performance may actually *degrade* before it shows signs of improvement.&#x20;

* **Why:** The assistant starts from a baseline model and calibrates using your early episodes. Initial adjustments on the model's side can be dramatic.
* **How to fix:** Continue recording and training on at least *five episodes* before expecting stable improvements and a more accurate outputting from your model.&#x20;

***

### When to Report an Issue

If you’ve tried the above steps and the problem persists:

* Collect your terminal output and Docker logs
* Include the CodeAssist version (`git rev-parse HEAD` in your repo)
* [Open a GitHub issue here](https://github.com/gensyn-ai/codeassist/issues) or share logs in the `#codeassist-support` channel on the [Gensyn Discord](https://discord.gg/gensyn)

{% hint style="success" %}
If you need additional support, you can [open a ticket](https://github.com/gensyn-ai/codeassist/issues) or [visit our Discord.](https://discord.com/invite/gensyn)&#x20;
{% endhint %}


# Litepaper

The hyperscale, cost-efficient compute protocol for the world’s deep learning models

{% hint style="info" %}
***Published February 2022***

**Please note that this version of the Litepaper is out-of-date.** The Gensyn team have made multiple changes to the protocol design, including but not limited to:

1. Replacing the Substrate L1 chain build (and associated canarynet / mainnet functionality) with a custom Ethereum rollup, following significant advancements in our off-chain infrastructure. Note: we also no longer use Rust in our stack.
2. A more robust audit strategy for checking work
3. Introducing a cryptographic proof system to dynamically monitor training
4. Stronger game theoretic guarantees
5. A novel proof of availability system for proof guarantees
6. An ML compiler and reproducible ML runtime

This [research will be published separately](https://www.gensyn.ai/research), but please use this Litepaper as introduction to the problem + solution vectors.
{% endhint %}

## Background

The computational [complexity](https://arxiv.org/pdf/2007.05558.pdf) of state-of-the-art Artificial Intelligence (AI) systems is [doubling every 3 months](https://openai.com/blog/ai-and-compute/), vastly outstripping compute supply. As a founding team--whether we've been publishing research into the evolution of deep neural architectures or building hurricane damage prediction models--we've experienced these limits first hand.

GPT-3 175B, the largest GPT-3 model proposed by OpenAI in [Brown et al. (2020)](https://arxiv.org/abs/2005.14165) used a cluster of 1,000 NVIDIA Tesla V100 GPUs for training - roughly equivalent to 355 years of training on a single device. DALL-E from [Ramesh et al. (2021)](https://arxiv.org/abs/2102.12092), another Transformer model from OpenAI, has 12 billion parameters and was trained on over 400 million captioned images. OpenAI bore the cost of training DALL-E but controversially refused to open source the model, meaning that perhaps one of the most important state-of-the-art multimodal deep learning models remains inaccessible to all but a select few. The huge resource requirements for building these [foundation models](https://arxiv.org/abs/2108.07258) create significant barriers to access, and, without a method to pool resources whilst still capturing value, will likely cause stagnation in AI advancement. Many believe that these generalised models are the key to unlocking Artificial General Intelligence (AGI), making the current method of training in isolated, artificial silos seem absurd.

Current solutions which provide access to compute supply are either [oligopolistic and expensive](https://www.cnbc.com/2021/09/05/how-amazon-web-services-makes-money-estimated-margins-by-service.html#:~:text=Bernstein%27s%20analysts%20estimated%20that%20in,a%2061%25%20gross%20margin%20overall.) or simply [unworkable](https://people.cs.uchicago.edu/~teutsch/papers/truebit.pdf) given the complexity of compute required for large-scale AI. Meeting the ballooning demand requires a system which cost-efficiently leverages *all* available compute (as opposed to today’s \~40% global processor utilisation). Compounding this problem right now is the fact that the compute supply itself is hamstrung by [asymptotic](https://github.com/karlrupp/microprocessor-trend-data) advances in microprocessor performance - alongside [supply chain](https://www.theguardian.com/business/2021/mar/21/global-shortage-in-computer-chips-reaches-crisis-point) and [geopolitical](https://www.scmp.com/tech/big-tech/article/3129710/tsmc-chief-blames-geopolitical-tensions-chip-shortage-plays-down) chip shortages.

We’ve spoken with more than 150 CTOs, machine learning (ML) researchers, and ML engineers who consistently describe the painful trade-off between purchasing their own hardware and sacrificing scalability, or renting scalable cloud resources for vastly increased costs. They recognise that cloud costs are typically inflated by provider profit margins and often wonder why on-demand, serverless-style compute doesn’t exist for their ML work.

Voluntary grid computing services like [SETI@Home](https://setiathome.berkaeeley.edu), [Folding@Home](https://foldingathome.org/), and [BOINC](https://boinc.berkeley.edu/) demonstrate that trustless, voluntarily-networked, latent compute can be used to solve some of humanity’s biggest problems. However, they predominantly solve [embarrassingly parallel](https://books.google.co.uk/books?id=vfvPrSz7R7QC\&q=embarrasingly\&redir_esc=y#v=onepage\&q=embarrasingly\&f=false) problems such as 3D rendering, where computational work can be trivially split and verified owing to its state independence. ML problems (besides niche tasks like hyperparameter optimisation) are inherently state dependent, requiring new methods for both parallelisation and verification. Volunteer networks also function only by modelling participants as rational actors in a philanthropic system;  adding financial transactions drastically changes the incentive mechanisms and introduces the spectre of exploitation.

Decentralised blockchain protocols extend the concept of grid computing into financially-incentivised, trustless environments. Specifically, [Ethereum](https://ethereum.org/en/whitepaper/) moved the space beyond the transaction use-cases of [Bitcoin](https://bitcoin.org/en/bitcoin-paper) to more general on-chain computational work. This was achieved by incorporating a Turing-complete language (Solidity) and rewarding compute providers through variable gas fees.&#x20;

Ethereum, however, achieves trustless consensus only via extremely expensive on-chain replication of work. This is completely unsuitable for deep learning. Training a small MNIST neural network (\~400M processor operations) takes \~8 minutes on an average laptop but would take \~80 days on Ethereum at a cost of approximately $32m. To address this, [Truebit](https://arxiv.org/abs/1908.04756) showed that it's possible to perform simple computational work off-chain (and thus with less overhead) and prove to the chain that it was performed correctly. They achieved this by modelling participants as financially-rational actors and carefully constructing incentive structures. Specifically, they solved the [verifier's dilemma](https://dl.acm.org/doi/abs/10.1145/2810103.2813659) by intermittently requiring workers to produce incorrect work and awarding verifiers with a jackpot if they spot it.

Despite these improvements, the work must still be replicated off-chain. This is unsuitable for activities with extreme computational expense (e.g. deep learning), and a cost-efficient off-chain compute system must exist if deep learning work is to be serviced in a trustless way.

## Problem

A protocol which trustlessly connects and verifies off-chain deep learning work in a cost efficient way has five main challenges.

### Work verification

In order to build a truly trustless compute network, with economic incentives for participation, the network must have a way to verify that deep learning computational work has actually been performed as promised. Central to this problem is the state dependency of deep learning models; that is, each subsequent layer in a deep learning model takes as an input the output of the previous layer. Therefore, to validate work has been completed at a specific point, all work up to and including that point must be performed. We’ll cover this in more detail later but it’s a fundamental problem that until now has had no viable solutions.

### Market

A marketplace for compute is subject to the same supply and demand issues that any new marketplace faces, with a few unique challenges too. Principally there is a cold-start issue, where supply and demand liquidity need to roughly match from the beginning in order to grow successfully. In order to capture latent compute supply, there must be a clear reward for participants to pledge their compute time. Computational work must be tracked and proportional payments made to the providers in a timely manner. For more traditional marketplaces, this is performed using intermediaries which handle administration and onboarding, with minimum payouts to reduce overheads. Unfortunately, this approach becomes costly to scale and results in a threshold equilibrium where only a small portion of the supply can be economically captured.

### Ex-ante work estimation

Similar to Ethereum, ML computational work is subject to the [halting problem](https://arxiv.org/abs/1901.03429) - where it is at times impossible to quantify the amount of computational work required by a defined task and more specifically whether it will ever end (or halt). In the context of deep learning, this has become more significant relatively recently as models and frameworks have switched from static graph construction to dynamic construction and execution.

### Privacy

With the growth of stronger personal privacy regulations around the world (e.g. [GDPR](https://gdpr.eu/tag/gdpr/), [CCPA](https://leginfo.legislature.ca.gov/faces/codes_displayText.xhtml?division=3.\&part=4.\&lawCode=CIV\&title=1.81.5), [LGPD](https://iapp.org/media/pdf/resource_center/Brazilian_General_Data_Protection_Law.pdf)), privacy-conscious design and development has become an expected practice for organisations. Whilst large amounts of ML research can be performed on open datasets, final model fine-tuning often uses proprietary user data. More specifically, in our interviews with ML engineers and CTOs, they indicated that data privacy was orders of magnitude more important than model privacy.

### Parallelisation

State of the art deep learning models are typically trained in parallel over large clusters of hardware in order to access scale that is unachievable with a single device. The techniques required to achieve this parallelisation have improved drastically through recent research, with current state-of-the-art transformer models like Switch Transformers proposed by [Fedus, Zoph, and Shazeer (2021)](https://arxiv.org/abs/2101.03961) now inherently highly parallelised by nature. Combining the performance requirements of the ML work with the untrusted and unreliable nature of the compute sources means that a high degree of parallelisation is essential in any solution.

## Solution

### Gensyn Protocol

The Gensyn Protocol is a layer-1 trustless protocol for deep learning computation that directly and immediately rewards supply-side participants for pledging their compute time to the network and performing ML tasks. The protocol requires no administrative overseer or legal enforcement, rather facilitating task distribution and payments programmatically through smart contracts. As described above, the fundamental challenge in building this network is the verification of completed ML work. This is a highly complex problem that sits at the intersection of complexity theory, game theory, cryptography, and optimisation.

A simple solution is to check the honesty of workers by re-doing their work. At a bare minimum, this requires a doubling of the operations required ('single replication'); however, even with replication, the issue of trust remains unless the verifying party is the actual requestor of the work (in which case, they wouldn't request the work as they'd simply perform it themselves). Therefore, ensuring the honesty of the verifying party can generate an infinite chain of replication, where each new verifier is required to check the work of the previous verifier.

We solve this verification problem by interlocking three key concepts into a robust solution that is $$\gt 1,350 %$$more efficient than existing best-practice replication methods; in doing so, it solves the infinite-chain problem. The key concepts are:

#### Probabilistic proof-of-learning

Following [Jia et al. (2021)](https://arxiv.org/abs/2103.05633), we use the metadata from gradient-based optimisation processes to construct certificates of work performed, which can be verified quickly through replication of certain stages.

#### Graph-based pinpoint protocol

Following [Zheng et al. (2021)](https://arxiv.org/abs/2105.04919), we use a multi-granular, graph-based pinpoint protocol and cross-evaluator consistent execution to allow verification work to be re-run and compared for consistency, and ultimately confirmed by the chain itself.

#### Truebit-style incentive game

Following [Teutsch and Reitwießner (2019)](https://arxiv.org/abs/1908.04756), we use staking and slashing to construct an incentive game ensuring each financially-rational participant behaves honestly and performs their intended tasks.

### Participants

These concepts are used to construct a system with four main participants: Submitters, Solvers, Verifiers, and Whistleblowers.

#### Submitters

Submitters are the end-users of the system, providing tasks that will be computed and paying for units of work completed.

#### Solvers

Solvers are the main workers of the system, performing the model training and generating proofs to be checked by Verifiers.

#### Verifiers&#x20;

Verifiers are key to linking the non-deterministic training process to a deterministic linear computation, replicating portions of the Solvers’ proofs and comparing distances with expected thresholds.&#x20;

#### Whistleblowers

Whistleblowers are the final line of defence, checking Verifiers’ work and challenging in the hope of receiving a jackpot payout.

### Usage

Typical protocol usage will pass through eight stages, with the above roles performing specific tasks.

#### Task Submission&#x20;

Tasks take the form of three specific pieces of information:

1. Metadata describing the task and hyperparameters;
2. A model binary (or skeleton architecture); and
3. Publicly accessible, pre-processed training data.

In order to submit a task, Submitters specify the details of the task in a machine-readable format and submit these to the chain along with the publicly accessible locations of the model binary (or machine-readable architecture) and pre-processed training data. The publicly available data could be stored in a simple object store such as [Amazon’s S3](https://aws.amazon.com/s3/) or in a decentralised store like [IPFS](https://ipfs.io/), [Arweave](https://www.arweave.org/), or [Subspace](https://subspace.network/).

For privacy-preservation, models can be constructed using secure mapping layers (a form of functional encryption) as proposed by [Lan, Liu, and Li (2020)](https://arxiv.org/abs/2007.15145) and the publicly accessible training data encrypted. In this way, models can be trained on ciphertext with a small accuracy penalty ($$\lt0.5%$$).

When submitting a task, an estimate of required work is generated by constructing and unrolling a computational graph into the required operations. These operations are weighted using values similar to [Ethereum's Opcode gas values](https://ethereum.org/pt/developers/docs/evm/opcodes/) in order to calculate a rough sum of computational work to be performed. The transaction fee paid by the Submitter can then use this estimate, with any excess (e.g. due to pessimistic profiling) returned to the Submitter after computation. Crucially, unrolling the graph requires set limits to be placed on logic which can trigger the halting problem.&#x20;

Tasks form the smallest quantity of ML work that can be pushed to the protocol. Using parallelisation, larger computational workloads can be split into sets of tasks and pushed to the network asynchronously. Using this approach, large-scale language models and other state-of-the-art models can be built, as [Diskin et al. (2021)](https://arxiv.org/abs/2106.10207) demonstrated with volunteer compute.

#### Profiling

The profiling process establishes a baseline distance threshold for the proof-of-learning verification. Verifiers will periodically grab profiling tasks and generate variation thresholds for proof-of-learning comparisons. To generate a threshold, a Verifier will deterministically run and re-run portions of the training with different random seeds, generating and checking their own proofs. In doing this, the Verifier will build up an aggregate expected distance threshold that can later be used as a threshold to validate the non-deterministic work of the Solvers.

In order to ensure the honesty of the Verifiers when generating the distance thresholds, Whistleblowers are expected to re-run the profiling work and challenge Verifiers where appropriate, using the same graph-based pinpoint challenge and contract arbitration mechanisms described below.

#### Training

Following profiling, the task enters the common task pool (analogous to the Ethereum mempool). A single Solver is selected to perform the task and the task is removed from the task pool. The Solver performs the task according to the metadata submitted by the Submitter and using the model and training data supplied. Whilst performing the training task, the Solver also generates a [proof-of-learning](https://arxiv.org/abs/2103.05633) by checkpointing at a scheduled interval and storing metadata from the training process (including parameters) so that the following optimisation step can be replicated as accurately as possible by a Verifier.

#### Proof generation

Proof generation follows the process outlined in [Jia et al. (2021)](https://arxiv.org/abs/2103.05633), whereby Solvers periodically store the model weights or updates along with the corresponding indices from the training dataset identifying the samples that were used to generate the weight updates. The checkpoint frequency can be tuned to provide stronger guarantees or to save on storage space. Proofs can be “stacked”, meaning that a proof can start from the random distribution used to initialise the weights or from pre-trained weights generated with their own proof. This allows the protocol to build up a set of already-proven, pre-trained base models (i.e. [foundation models](https://arxiv.org/abs/2108.07258)) which can be fine-tuned for more specific tasks.

#### Verification of proof

Following task completion, Solvers register the completion of the task with the chain and present their proof-of-learning in a publicly accessible location for access by Verifiers. Verifiers pick up verification tasks from a common task pool (again analogous to the Ethereum mempool) and perform the computational work to re-run portions of the proof and perform distance calculations. The resulting distances are then used by the chain (along with the threshold calculated during the profiling stage) to determine whether the verification matches the proof.

#### Graph-based pinpoint challenge

Following verification of the proof-of-learning, Whistleblowers can replicate Verifier work in order to check that the verification work itself has been performed correctly. In the event that a Whistleblower believes that verification has been performed incorrectly (maliciously or not) they can challenge the Verifier to contract arbitration in order to receive a reward. This reward can come from Solver and Verifier deposits in the case of a true positive or from the jackpot treasury in the case of a false positive. The challenge process follows the procedure outlined in [Zheng et al. (2021)](https://arxiv.org/abs/2105.04919) and uses the chain itself to perform the arbitration.

Following [Teutsch and Reitwießner (2019)](https://arxiv.org/abs/1908.04756), Whistleblowers (in their case Verifiers) are only expected to verify and subsequently challenge work in the event that they expect to receive appropriate compensation. In practice, this means that Whistleblowers are expected to join and leave the network depending on the number of other active (i.e. with live deposits and challenging) Whistleblowers. Therefore, the expected default strategy for any Whistleblower is to join the network when there are a low number of other Whistleblowers, post a deposit, randomly choose an active task, and begin their verification process. Following the conclusion of the first task, they would grab another random active task and repeat until the number of Whistleblowers increases above their determined payout threshold, whereupon they would leave the network (or more likely, switch to performing another role in the network--Verifier or Solver--depending on their hardware capabilities) until the situation reverses again.

#### Contract arbitration

When a Verifier is challenged by a Whistleblower, they enter a process with the chain to whittle down the location of a disputed operation or input, culminating in the chain performing the final basic operation and determining whether the challenge was justified. In order to maintain the honesty of the Whistleblowers and overcome the [verifier’s dilemma](https://dl.acm.org/doi/abs/10.1145/2810103.2813659), the protocol introduces periodic forced errors with jackpot payouts, as proposed by [Teutsch and Reitwießner (2019)](https://arxiv.org/abs/1908.04756).

#### Settlement

In the settlement process, participants are paid according to the conclusions of the probabilistic and deterministic checks. Different payments are made in different scenarios depending on the outcome of the prior verification and challenges.

If the work is deemed to have been performed correctly and all checks have passed, the Solver and Verifier are both rewarded according to the operations performed.

### Scale and cost-efficiency

Building the marketplace as a Web3 protocol removes the centralised overheads on scaling and reduces the barriers-to-entry for new supply participants, allowing the network to potentially encompass every computing device in the world. Connecting all devices through a single decentralised network provides a level of scalability that is currently impossible to achieve through any existing provider, giving unprecedented on-demand access to the entirety of the world’s compute supply. For end-users, this completely dismantles the cost vs scale dilemma and provides a transparent, low, cost for potentially infinite scalability (up to worldwide physical hardware limits).

Creating a marketplace where prices are determined by market dynamics, and the market is open to all participants, allows the unit cost of ML compute to settle into its fair equilibrium. This sidesteps the usual moats that large providers enjoy, significantly drives down prices, and facilitates truly global competition at the resource level. Whilst current compute costs for end-users incorporate large margins for their oligopolistic suppliers, the Gensyn Protocol will ensure that the remaining margin, decreased by fair competition, is proportionally captured by every participant.

With Ethereum’s move from proof-of-work to proof-of-stake in [Eth2](https://ethereum.org/en/eth2/vision/), many miners with powerful GPUs (e.g. NVIDIA V100s) will be left without a yield. These miners can currently expect a return of around $0.20 to $0.35 per hour, which even now, when subtracting amortized capital purchase and electricity costs, provides a tight marginal return. The delta between the current yield expected by these miners with ML-capable hardware and the average hourly cost of the same hardware from the main providers, alongside the likely disappearance of Eth mining, forms a huge opportunity for the Gensyn Protocol; it also allows the hardware to generate returns on useful processor cycles - as opposed to merely calculating hashes in proof-of-work systems.  Capturing this mining supply, alongside other general sources of latent compute, leads to a projected hourly cost of around $0.40 per hour for NVIDIA V100-equivalent computation on the Gensyn Protocol, 80% cheaper than AWS on-demand.

<table><thead><tr><th width="253.08322463348168">Provider</th><th width="278.9348982913271">Approximate hourly cost for ML training work (V100-equivalent)</th><th>Scalability</th></tr></thead><tbody><tr><td>Ethereum</td><td>$15,700</td><td>Low</td></tr><tr><td>Truebit (+ Ethereum)</td><td>$12</td><td>Low</td></tr><tr><td>GCP on-demand</td><td>$2.50</td><td>Medium</td></tr><tr><td>AWS on-demand</td><td>$2</td><td>Medium</td></tr><tr><td>Golem Network</td><td>$1.20</td><td>Low</td></tr><tr><td>Vast.ai</td><td>$1.10</td><td>Low</td></tr><tr><td>AWS spot instances (unreliable)</td><td>$0.90</td><td>Medium</td></tr><tr><td>GCP spot instances (unreliable)</td><td>$0.75</td><td>Medium</td></tr><tr><td>Gensyn (projected)</td><td>$0.40</td><td>High</td></tr><tr><td>Single GPU in datacentre</td><td>$0.40</td><td>None</td></tr><tr><td>Single personal GPU</td><td>$0.28</td><td>None</td></tr></tbody></table>

### Protocol evaluation

We evaluate our solution through Python simulations in order to assess the magnitude of performance gains delivered by the Gensyn protocol. In this instance, we gauge performance as the aggregate time in seconds taken to complete a 100 epoch training job on a small MNIST image classification model. We test this on a 6-Core Intel Core i7 processor.&#x20;

We compare the protocol with 3 alternative approaches: running the model locally (as opposed to using any protocol), running the model using Truebit-inspired replication (with 7 verifiers), and running the model on Ethereum.

Despite the code lacking production-level optimisations, the results show that the Gensyn protocol adds a \~46% time overhead to model training representing a 1,350% performance gain versus Truebit-style replication and 2,522,477% gain versus Ethereum.

![Runtime comparison between Gensyn and Truebit-style replication for an MNIST image classification model](/files/2Ovh1XS26VyqEgSOZ6Ua) ![Runtime comparison between Gensyn and Ethereum (theoretical) for an MNIST image classification model](/files/VrF32ljgDB3WuFsht6wn)

## Decentralisation and governance

### Governance

Gensyn Limited is the initial entity that is developing the protocol, hiring the team, and managing the IP (prior to open source launch). Gensyn Limited is a fully remote company, hiring talent from all over the world. Following the Token Generation Event (TGE), Gensyn Limited will handle technical development and the Gensyn Foundation will represent the interests of the protocol.

Tokens will be issued at the TGE by the Gensyn Foundation, which will be governed in a decentralised manner by an elected council and make decisions based on on-chain proposals and referenda. Initially, members of the council will be tightly mapped to core members of Gensyn Limited and the early community in order to quickly develop the protocol. As time goes on, the council will become more decentralised.

The Gensyn Foundation will also control a treasury that will be directed by proposals to further the aims of the protocol by funding the continued development of the protocol itself and the overall ecosystem. The treasury will primarily be funded by taking a very small percentage of each task fee.

## Future development

### Research

We will continue our research into three main areas to improve the protocol: probabilistic verification of ML training using metadata from the optimisation process, pinpoint verification of deterministic ML work for on-chain proof, and parallelisation of ML models over heterogeneous hardware with latency constraints.

This research will strengthen the work verification guarantees and expand the utility of the protocol to include more model primitives and a wider variety of model types.

### Development

Development of the Gensyn protocol will follow three high-level phases: testnet, canarynet, mainnet.

#### Testnet

Initial development will focus on building a testnet implementation of the core technology. Tokens used by the testnet will be non-permanent, and users of the testnet will be early adopters and core members of the community who will be rewarded at the TGE.

#### Canarynet

Following successful testnet iteration, the protocol will launch as a canary network parachain on the [Kusama relay chain](https://kusama.network/). This phase will involve launching the canary utility token that will have real economic value. The canary network can be seen as a beta version of the protocol with access to the newest features and some risk associated with its use. Long-term, canary networks typically offer slightly lower prices and access to bleeding-edge R\&D functionality in exchange for this slight risk.

#### Mainnet

Following a successful parachain launch on the Kusama relay chain, the next phase will be to launch the final live parachain on the [Polkadot relay chain](https://polkadot.network/). This phase will include the launch of the mainnet utility token that will be the main utility token for the protocol. The mainnet will be the hardened, live protocol for full use by any organisation or individual. Features or changes will go through testnet and canarynet iteration before launching on the mainnet.

### Ecosystem

The Gensyn Protocol will be a foundational layer for ML compute, similar to Ethereum for smart contract execution. Going forward, we expect others to build on top of the protocol to provide rich user experiences and specific functionality in numerous niches. We expect this burgeoning ecosystem to start with expert-knowledge-based applications, allowing non-experts to build and deploy ML solutions using abstractions similar to existing Web2 solutions such as [Amazon’s SageMaker](https://aws.amazon.com/sagemaker/) and [DataRobot](https://www.datarobot.com/).

Besides human knowledge in model design, there are three fundamental problems slowing the progress of applied ML:

1. Access to compute power;
2. Access to data; and
3. Access to knowledge (ground-truth labelling).

Gensyn solves the first problem by providing on-demand access to globally scalable compute at its fair market price. The Gensyn Foundation will seek to encourage solutions to two and three through research, funding, and collaborations with other protocols.

### Long-term vision

The Gensyn Protocol will enable anyone to train ML models for any task using a self-organising network that encompasses every source of compute power in existence.

As Web3 Dapps increase in complexity and infrastructure requirements, they are forced to fall back onto Web2 where Web3 resources don't exist. By decentralising ML compute, the Gensyn Protocol brings a crucial infrastructure component natively to Web3 - reducing reliance on Web2 and further strengthening and decentralising the entire ecosystem.

Deep learning has shown incredible generalisation power and looks set to play a huge part in the future of ML. [Foundation models](https://arxiv.org/abs/2108.07258), trained on the Gensyn Protocol, will be decentralised and globally owned - allowing humanity to equally benefit from collaborative ML development and training. Building on these foundation models using fine-tuning will be as simple as defining a task and paying a fair market price for the fine-tuning work - removing the barriers that currently exist.

For decades, ML has progressed in silos, both academic and industrial. The Gensyn Protocol connects these silos through a common infrastructure with decentralised ownership, allowing all of humanity to quickly and collectively explore the future of artificial intelligence as equal pioneers. Combining this network with hierarchically-trained and collectively-owned foundation models provides a path towards a true realisation of AGI - the next step for humanity.

## Get involved

You can follow our progress on [Twitter](https://twitter.com/gensynai). If you're interested in contributing compute resources, using the network for ML tasks, or joining us then please send us a message. We'd love to chat.


