diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index d5fc0fe..b943933 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -5,6 +5,18 @@ on:
pull_request:
jobs:
+ website:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-node@v4
+ with:
+ node-version: "22"
+ - name: Check project website and demo paths
+ run: |
+ node --check website/assets/app.js
+ node website/check.mjs
+
checks:
runs-on: ubuntu-latest
strategy:
diff --git a/.nojekyll b/.nojekyll
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/.nojekyll
@@ -0,0 +1 @@
+
diff --git a/README.md b/README.md
index 93087c2..cc0ad36 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@
**Receiver-conditioned latent communication for agents.**
Code for *Receiver-Conditioned Latent Communication gives 94% CacheBack*.
-**[Paper](https://arxiv.org/abs/2609.32046).** [Python API](https://github.com/maxr0ssi/rclc/blob/main/docs/api.md) · [Paper replication](https://github.com/maxr0ssi/rclc/blob/main/docs/replication.md)
+**[Website](https://maxr0ssi.github.io/rclc/)** · **[Paper](https://arxiv.org/abs/2609.32046)** · [Python API](https://github.com/maxr0ssi/rclc/blob/main/docs/api.md) · [Paper replication](https://github.com/maxr0ssi/rclc/blob/main/docs/replication.md)
Agents distribute large contexts across senders and receivers. Text messages
require decoding and can omit evidence. Full KV-cache messages accumulate every
@@ -18,18 +18,22 @@ that request to choose which sender positions enter the handoff.
with 50 concurrent tasks on eight H100 GPUs. Operating points differ by family.
Right: the receiver query guides which sender positions enter the handoff.*
-## Watch the handoff
+## Watch the demo
-**[▶ Try the demo in your browser](https://maxr0ssi.github.io/rclc/demo/)**
+**[▶ Watch the 36-second coding demo](https://maxr0ssi.github.io/rclc/#demo)**
-
+[](https://maxr0ssi.github.io/rclc/#demo)
-*Replayed at 2× from a recorded Qwen3-8B run on one A100.*
+Seven Qwen3-8B workers help a coordinator fix a Django bug. CacheBack completes
+this recorded case in **25.66 s**, versus **113.21 s** for text: **4.41× faster**.
+Both produce the same patch and subsequently pass all 88 tests. Startup and
+test grading are excluded from the clocks. The silent video reconstructs the
+interface from separate runs and varies playback speed. This is one case,
+not an aggregate benchmark. [Recorded results](demo/coding/evidence.json).
-The demo follows a booking through four agents and compares RCLC with a text
-relay. Latencies come from recorded runs, not a benchmark. The
-[demo guide](https://github.com/maxr0ssi/rclc/blob/main/demo/README.md) covers
-running it locally and recording your own.
+Also explore the [interactive booking relay](https://maxr0ssi.github.io/rclc/demo/)
+to inspect selected positions and text messages at each handoff. Its
+[demo guide](demo/README.md) covers recording your own.
## Install
diff --git a/demo/README.md b/demo/README.md
index a02f781..8b94c23 100644
--- a/demo/README.md
+++ b/demo/README.md
@@ -1,10 +1,15 @@
-# CacheBack demo
+# CacheBack booking relay
+
+The replay labels the method CacheBack; `rclc` remains its recording key.
Three agents pass evidence to a fourth. Maya's booking reference J7 leads to
Harbour Hub, whose passport requirement overrides the original desk's ID advice.
## Watch
+The [booking section](../index.html#booking-demo), below the main coding video, presents the recorded final answers
+and completion times before the replay. Selected positions use teal highlights.
+
Open and press **Run**. To serve it
locally, run this from the repository root and open :
@@ -22,8 +27,11 @@ intermediate messages, exact token origins and timings.
`collection-id-rules.txt`. Each shows the source document with RCLC highlights
and the generated text handoff. The last column shows both unedited answers
and their total times.
-- Text boxes follow the newest generated line. Documents and messages scroll; on
- a small screen, scroll the whole diagram horizontally.
+- Text boxes follow the newest generated line. Documents and messages scroll
+ within their compact panes. On smaller screens, agent cards form two columns,
+ then one on phones, with their agent labels repeated above the content.
+ An embedded replay resizes to its content, so its outer frame never needs
+ horizontal or vertical scrolling. Scroll the containing page normally.
- **Replay** restarts. **Clear** stops playback and resets the highlights,
messages and clocks.
- The reviewed 8B answer shows `✓ Harbour Hub · Passport` when it finishes. The
@@ -33,7 +41,8 @@ intermediate messages, exact token origins and timings.
Playback defaults to **1x**; **2x** and **4x** speed it up. Each method
progresses independently from its measured handoff durations and total
completion time, so the faster one finishes while the other keeps streaming, and
-the clocks show recorded time. Completion times are measured; streaming is
+the clocks show recorded time. Playback starts from the first animation-frame
+timestamp, keeping embedded-frame clock origins from producing negative time. Completion times are measured; streaming is
illustrative. Text streams at an estimated constant character rate within each
stage, because the recording has no per-token timestamps or separate
prefill/decode timings. Reduced-motion preferences disable the highlight
diff --git a/demo/coding/evidence.json b/demo/coding/evidence.json
new file mode 100644
index 0000000..47e5561
--- /dev/null
+++ b/demo/coding/evidence.json
@@ -0,0 +1,54 @@
+{
+ "run_id": "bughunt-16333-run-20261001T051520Z",
+ "source": "s3://lce-pr2789-paper/rclc-demo/bughunt-16333-run-20261001T051520Z/",
+ "model": "Qwen/Qwen3-8B",
+ "issue": "django__django-16333",
+ "arms": {
+ "text": {
+ "seconds": 113.20635836,
+ "worker_seconds": 100.612943677,
+ "worker_done": [
+ 100.612943677,
+ 38.252793639,
+ 25.637343035,
+ 33.867839988,
+ 22.492231897,
+ 78.432600727,
+ 29.442396709
+ ],
+ "status": "resolved",
+ "patch": "diff --git a/django/contrib/auth/forms.py b/django/contrib/auth/forms.py\n--- a/django/contrib/auth/forms.py\n+++ b/django/contrib/auth/forms.py\n@@ -141,6 +141,7 @@\n user.set_password(self.cleaned_data[\"password1\"])\n if commit:\n user.save()\n+ self.save_m2m()\n return user\n \n \n",
+ "new_tests_passed": 1,
+ "regression_tests_passed": 87,
+ "failed_tests": 0,
+ "handoff_bytes": 24969,
+ "handoff_rows": 0,
+ "coordinator_tokens": 1470,
+ "source_result": "s3://lce-pr2789-paper/rclc-demo/bughunt-16333-run-20261001T051520Z/text/result.json",
+ "source_grade": "s3://lce-pr2789-paper/rclc-demo/bughunt-16333-run-20261001T051520Z/grades/text.json"
+ },
+ "latent": {
+ "seconds": 25.66205141,
+ "worker_seconds": 6.196859804,
+ "worker_done": [
+ 6.196859804,
+ 6.093338203,
+ 6.146028218,
+ 6.18476604,
+ 6.18007457,
+ 5.908353919,
+ 6.053007381
+ ],
+ "status": "resolved",
+ "patch": "diff --git a/django/contrib/auth/forms.py b/django/contrib/auth/forms.py\n--- a/django/contrib/auth/forms.py\n+++ b/django/contrib/auth/forms.py\n@@ -141,6 +141,7 @@\n user.set_password(self.cleaned_data[\"password1\"])\n if commit:\n user.save()\n+ self.save_m2m()\n return user\n \n \n",
+ "new_tests_passed": 1,
+ "regression_tests_passed": 87,
+ "failed_tests": 0,
+ "handoff_bytes": 675872768,
+ "handoff_rows": 82504,
+ "coordinator_tokens": 921,
+ "source_result": "s3://lce-pr2789-paper/rclc-demo/bughunt-16333-run-20261001T051520Z/latent/result.json",
+ "source_grade": "s3://lce-pr2789-paper/rclc-demo/bughunt-16333-run-20261001T051520Z/grades/latent.json"
+ }
+ }
+}
diff --git a/demo/coding/poster.jpg b/demo/coding/poster.jpg
new file mode 100644
index 0000000..c6f47e9
Binary files /dev/null and b/demo/coding/poster.jpg differ
diff --git a/demo/coding/rclc-cacheback-4k.mp4 b/demo/coding/rclc-cacheback-4k.mp4
new file mode 100644
index 0000000..4eea1cc
Binary files /dev/null and b/demo/coding/rclc-cacheback-4k.mp4 differ
diff --git a/demo/index.html b/demo/index.html
index 6eb3de0..e412c8a 100644
--- a/demo/index.html
+++ b/demo/index.html
@@ -4,7 +4,7 @@
-
Written messages between agents can lose evidence; passing their entire internal state becomes expensive. Receiver-conditioning lets the receiver describe what it needs, so the sender can select what to pass on. CacheBack is our simplest, robust, training-free implementation.
+
On FanOutQA with Qwen 3 8B, CacheBack sends 75% fewer positions than full-state transfer. Compared with same-size text communication, strict accuracy improves by 14.7 percentage points and median completion is 3.2× faster.
+
+ Read the full abstract
+
+
Multi-agent systems distribute large contexts across agents that communicate to solve a task. Text messages are compact but require decoding and may omit evidence the receiving agent needs. Recent latent communication instead transfers KV caches. This avoids text generation and can improve accuracy and latency. However, a full KV cache grows linearly with both the context an individual agent processes, and the number of agents that coordinate together.
+
This raises memory and context costs, often far exceeding available GPU resources and context window sizes. Our key observation is that agents need only send what the receiving agent requires for its local task -- which we call receiver-conditioned communication. The receiver agent passes the sender a small description of its information needs, which serves to filter and compress the sender agent's KV cache.
+
CacheBack is a simple, robust, training-free instance of receiver conditioning based on the sender's attention weights. On FanOutQA, CacheBack with Qwen 3 removes 75% of the state the agent would otherwise receive, improving accuracy by 14.7 percentage points and reducing median task-completion latency by 3.2× relative to text communication. We show comparable improvements across model families that span dense Transformers, Mamba-attention hybrids, and sliding-window attention.
+
A KV cache stores intermediate state from the text a model has processed. Abstract from the published paper, by Rossi et al. CC BY 4.0; emphasis added.
+
+
+
+
+
+
+
How it works
+
The receiver describes what it needs for its next task. CacheBack uses that request to select part of the sender’s internal numerical state, or latent state, to send back.
+
+
+
+
Sender
Select state using the request
+
+
01 Request
+
02 Selected latent state
+
+
Receiver
Has the next task
+
+
+
CacheBack
+
Our simplest implementation. Robust and training-free.
+
Uses attention to the receiver’s request to score sender positions, then selects a subset within the message budget.
+
+
+ What crosses the handoff?
CacheBack selects positions using the sender’s attention to the receiver’s request. In the paper’s selected-embedding channel, the corresponding input vectors are sent and the receiver rebuilds its KV cache. A position is not an isolated fact, and an attention score is not a guarantee of relevance. The experiments use matching models; cross-model translation is outside this work. Read the method and limitations.
+
+
+
Results
On FanOutQA, three agents read separate sources and send state to one answering agent. These curves compare accuracy and completion time across message budgets and text-sender sizes.
+
+
Accuracy and completion time
Higher is more accurate. Further left is faster. Each point is a measured setting; lines join the best observed tradeoffs within each method. Text points vary sender size; CacheBack points vary compression or message budget. The receiver stays fixed.
Reading r4, r8, r16: rX means keeping about 1/X of the sender’s sequence positions. For example, r4 keeps 25%, r8 keeps 12.5%, and r16 keeps 6.25%. Larger numbers mean more compression and a smaller message.
+
● ━ CacheBack▲ ┄ Text communication× Question only
+
+ Qwen 3: r4 improves strict accuracy from 40.7% to 55.3% and median completion from 612 to 192 seconds.
+ Nemotron: the benefit also appears in a model combining Mamba and attention. A smaller text sender is faster, but less accurate.
+
+ Repeated handoffs: LongBench v2
On LongBench v2 Easy, four agents read successive sections of a long document. A final receiver answers from the last handoff. Evidence from the beginning must survive the chain.
A relative budget uses the rX fraction above, so message size grows with the sender’s context. A fixed budget caps the number of message positions, as in the labels “32K fixed” and “64K fixed”.
+ Qwen 3: both message-budget schemes improve the measured tradeoff. More aggressive compression eventually reduces accuracy.
+ Nemotron: a fixed budget caps message positions; a relative budget grows with the material read. Neither denotes total GPU memory.
+
+
+
Redrawn from the paper’s plotting data for Qwen and Nemotron. Each benchmark uses 50 tasks submitted together on eight H100s; completion includes queueing. Accuracy averages three receiver draws. Qwen uses a 0 to 1,000 s time axis, Nemotron 0 to 400 s; each model keeps its scale across benchmarks. Figures 5, 11, and 12 in the paper.
+
About “94% CacheBack”: r16 retains one sender position in sixteen, removing 93.75%. The selected Qwen result above uses r4, or 75% fewer positions. Position reduction is not total GPU memory saved.
+
+
+
+
+
Watch the demo
Seven workers help a coordinator fix a Django bug. Compare latent handoffs with written reports.
+
+
36 seconds · 4K · Recorded coding task
Fixing a Django bug with seven coding agents
Qwen3-8B produces the patch 4.41× faster with CacheBack than with written reports on this case. Both runs make the same one-line code change and pass all 88 tests.
+
+
One recorded case: CacheBack 25.66 s; text 113.21 s. Startup and test grading excluded. Silent video; playback speed varies. Open in full window
+ Recording details and text description
Seven Qwen3-8B workers pass information to a coordinator. The supplied bug report identifies a missing save_m2m() call in Django’s user creation form. Both runs add that call after saving the user. The CacheBack run finishes while the text workers are still generating reports.
The interface is reconstructed from separate recorded runs, aligned at their start. The final response and patch come from the recorded outputs. Both patches subsequently pass one new test and 87 regression tests; grading is outside the clocks. This is an individual demonstration, not an aggregate benchmark. Recorded results
+
+
+
+
Recorded model run
Where should Maya collect her pass on Friday, and what ID should she bring?
Three documents contain the booking, a change of location, and the new desk’s ID rules. The final agent must connect all three.
+
+
+
CacheBack
3.42 s
+
Maya should collect her pass at Harbour Hub on Friday, and she should bring a passport as her ID.
+ Evidence quoted by the model
Evidence:
+- "Reference J7 has moved to Harbour Hub."
+- "Harbour Hub requires a passport for replacement building pass collections."
+
+
+
Text messages
26.09 s
+
Maya should collect her pass at the assigned desk based on her reference J7, not at the Central Desk. She should check the Friday operations notice using her reference J7 to confirm the exact location. The ID she should bring depends on the desk where she collects her pass. If she is collecting at Harbour Hub, she must bring a passport, as a driving licence is not accepted. The name on the ID must match her booking, and the ID requirements for the specific desk apply.
+ Evidence quoted by the model
Evidence:
+- "Maya should collect her pass at the assigned desk based on her reference, not at the Central Desk."
+- "She should check the Friday operations notice using her reference J7 to confirm the exact location."
+- "If she is collecting at Harbour Hub, a passport is required, and a driving licence is not accepted."
+
+
+
Qwen3-8B · one A100 · r4 · one warm run per method. Times include three handoffs and final answer generation, excluding model loading, tokenization, and warmup. This recording is an example, not a benchmark. Raw recording · Setup
Bind a sender and receiver to matching models, then pass the receiver’s request to rcc.transfer. CacheBack is the default selector. Continue generation with your model’s native API.