<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Rakib</title>
    <description>The latest articles on DEV Community by Rakib (@rakib-nyc).</description>
    <link>https://dev.to/rakib-nyc</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4025741%2F3e1584ee-51a4-4cc7-ac2a-9172d91212b6.jpg</url>
      <title>DEV Community: Rakib</title>
      <link>https://dev.to/rakib-nyc</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rakib-nyc"/>
    <language>en</language>
    <item>
      <title>One channel decided whether my multi-agent RL agents learned at all</title>
      <dc:creator>Rakib</dc:creator>
      <pubDate>Sun, 12 Jul 2026 05:37:07 +0000</pubDate>
      <link>https://dev.to/rakib-nyc/one-channel-decided-whether-my-multi-agent-rl-agents-learned-at-all-4051</link>
      <guid>https://dev.to/rakib-nyc/one-channel-decided-whether-my-multi-agent-rl-agents-learned-at-all-4051</guid>
      <description>&lt;p&gt;I have a small cooperative multi-agent reinforcement-learning setup: eight agents on a 100×100 grid, learning to reach three goals while gathering resources and avoiding obstacles. Standard MAPPO — a shared actor, a centralized critic, per-agent advantages, the usual PPO machinery. Each agent sees the world through an 11×11 egocentric window.&lt;/p&gt;

&lt;p&gt;That window is the whole story, and it took an ablation to make me take it seriously.&lt;/p&gt;

&lt;h2&gt;
  
  
  The setup, and the thing that's easy to miss
&lt;/h2&gt;

&lt;p&gt;Look at the numbers for a second. The grid is 100×100. The agent sees an 11×11 patch centered on itself — reach ±5 in each direction. Goals are placed uniformly at random. So on any given step, what's the chance a goal is actually &lt;em&gt;inside&lt;/em&gt; the patch an agent can see?&lt;/p&gt;

&lt;p&gt;Almost never. A goal is a small target on a 10,000-cell map, and each agent perceives roughly 1% of that map at a time. For the overwhelming majority of steps, the agent's observation contains &lt;strong&gt;no signal about where it's supposed to go&lt;/strong&gt;. It's a partially observed task in the most literal sense: the objective is usually outside the sensory window entirely.&lt;/p&gt;

&lt;p&gt;There's a common fix for this, and my environment uses it: an &lt;strong&gt;objective beacon&lt;/strong&gt;. Instead of hoping the goal wanders into view, you project the &lt;em&gt;bearing&lt;/em&gt; to the nearest un-reached goal onto the border of the observation — a "go this way" arrow painted into the goal channel, always present, pointing toward the objective even when the objective itself is far outside the window. It's cheap, it's a handful of lines, and it turns an unobservable target into a directional gradient the policy can climb.&lt;/p&gt;

&lt;p&gt;I knew, abstractly, that this kind of thing helps. What I didn't have was a sense of &lt;em&gt;how much&lt;/em&gt; — whether the beacon was a nice-to-have that shaved some episodes off, or something more fundamental. So I ran the ablation: train with the beacon, train without it, change absolutely nothing else, and measure.&lt;/p&gt;

&lt;h2&gt;
  
  
  The ablation, kept honest
&lt;/h2&gt;

&lt;p&gt;The only thing that differs between the two conditions is a &lt;code&gt;beacon=True/False&lt;/code&gt; flag that wraps the beacon-drawing block. Same architecture, same hyperparameters (repo defaults — LR 1e-3, γ 0.99, GAE-λ 0.95, clip 0.2, entropy 0.005), same 250 training updates, same 64 parallel envs, same evaluation protocol, same four seeds for each condition. Greedy evaluation over 50 fixed-layout episodes, plus a random-policy baseline for reference.&lt;/p&gt;

&lt;p&gt;A quick sanity check that the toggle does what it says: summing the goal-channel activation across a batch at reset gives &lt;strong&gt;490.0 with the beacon on and 1.0 with it off&lt;/strong&gt;. With the beacon disabled, the goal channel is essentially empty — which is exactly the point. Without the beacon, the goal almost never appears in any agent's window, so the channel carries nearly no information.&lt;/p&gt;

&lt;h2&gt;
  
  
  The result
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Condition&lt;/th&gt;
&lt;th&gt;Success rate&lt;/th&gt;
&lt;th&gt;Reach rate&lt;/th&gt;
&lt;th&gt;Return&lt;/th&gt;
&lt;th&gt;Steps to solve&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Beacon ON&lt;/strong&gt; (mean ± std, 4 seeds)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.995 ± 0.010&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0.998 ± 0.003&lt;/td&gt;
&lt;td&gt;+9.05 ± 0.22&lt;/td&gt;
&lt;td&gt;43 / 200&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Beacon OFF&lt;/strong&gt; (mean ± std, 4 seeds)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.000 ± 0.000&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0.105 ± 0.053&lt;/td&gt;
&lt;td&gt;−75.4 ± 3.9&lt;/td&gt;
&lt;td&gt;200 (timeout)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Random policy&lt;/td&gt;
&lt;td&gt;0.00&lt;/td&gt;
&lt;td&gt;0.10&lt;/td&gt;
&lt;td&gt;−72.8&lt;/td&gt;
&lt;td&gt;200&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;"Success" means all three goals reached in an episode; the rate is the fraction of episodes fully solved.&lt;/p&gt;

&lt;p&gt;With the beacon, MAPPO solves the task: &lt;strong&gt;99.5% of episodes&lt;/strong&gt;, in about 43 of the allotted 200 steps, consistent across all four seeds (per-seed success: 1.0, 0.98, 1.0, 1.0). The training return climbs from about −10 and crosses into positive territory around update 45.&lt;/p&gt;

&lt;p&gt;Without the beacon — identical everything else — it &lt;strong&gt;does not learn at all&lt;/strong&gt;. Zero percent success on every seed. Its reach rate (0.105) is statistically indistinguishable from the random policy (0.10). The training curve never rises; it drifts slightly &lt;em&gt;more&lt;/em&gt; negative over time. This isn't "a bit worse." It's at chance.&lt;/p&gt;

&lt;p&gt;The gap between conditions is roughly &lt;strong&gt;100× the seed-to-seed noise&lt;/strong&gt; on success rate, so it's a real effect, not variance. The one-line version is honest: &lt;strong&gt;0% → 99.5%, from one channel's worth of directional signal.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this is the whole ballgame, not a tuning detail
&lt;/h2&gt;

&lt;p&gt;It's tempting to file "add a goal beacon" under reward shaping or feature engineering — a knob you turn to speed things up. This ablation reframed it for me. In a task where the objective is almost always outside the observation window, the beacon isn't accelerating learning; it's supplying the &lt;em&gt;only&lt;/em&gt; consistent signal about where to go. Take it away and there's nothing to climb — the policy is doing RL on observations that, most of the time, don't say anything about the goal. The agents don't learn slowly. They don't learn.&lt;/p&gt;

&lt;p&gt;The general lesson, which I think travels beyond this toy: in a partially observed task, &lt;strong&gt;what you put in the observation can matter more than the algorithm you run on it.&lt;/strong&gt; I could have spent that time tuning PPO clip ranges or critic architectures and gotten nowhere, because the bottleneck wasn't the optimizer — it was that the input didn't contain the answer. A single well-chosen feature — the bearing to the goal — was the difference between a policy that solves the map 99.5% of the time and one that never solves it at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  Honest boundaries
&lt;/h2&gt;

&lt;p&gt;A few things I want to be precise about, because the strong number invites over-reading:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This is &lt;strong&gt;one task configuration, one machine, four seeds, 250 updates.&lt;/strong&gt; The effect is large and dead-consistent across seeds, but it's a single setup, not a law.&lt;/li&gt;
&lt;li&gt;"Beacon-off can't learn" is shown &lt;strong&gt;within this fixed, fair budget.&lt;/strong&gt; I did not go hunting for a no-beacon recipe — much longer training, denser reward, bigger networks, different exploration — that might eventually crack it. The honest claim is narrow and specific: &lt;em&gt;under identical budget and hyperparameters, the beacon is required for learning here&lt;/em&gt;, not that the task is unlearnable without one in principle.&lt;/li&gt;
&lt;li&gt;Both conditions keep the dense distance-to-goal reward term, which is why the beacon-off return sits around −75 (a persistent distance penalty with no way to reduce it). The success and reach-rate columns — which don't depend on that shaping — are the ones carrying the real 0% vs 99.5% story.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The code
&lt;/h2&gt;

&lt;p&gt;This is from &lt;strong&gt;Kelvane&lt;/strong&gt;, a small open-source (Apache-2.0) toolkit I've been building: a WebAssembly runtime for running untrusted, hot-swappable neural policies under a per-call compute and authority budget, paired with this compact multi-agent RL reference that trains policies and exports them to ONNX to run inside that sandbox. The gridworld, the MAPPO/QMIX trainers, and the beacon are all in &lt;code&gt;kelvane-marl&lt;/code&gt;, and the ablation toggle is a few lines you can flip yourself.&lt;/p&gt;

&lt;p&gt;Repo: &lt;strong&gt;&lt;a href="https://github.com/rakib-nyc/kelvane" rel="noopener noreferrer"&gt;https://github.com/rakib-nyc/kelvane&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you're doing partially observed multi-agent RL and your agents stubbornly refuse to learn, the first question I'd now ask isn't about the algorithm. It's: &lt;em&gt;does the observation actually contain the objective?&lt;/em&gt; Mine didn't — until one channel said which way to go.&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>ai</category>
      <category>rust</category>
    </item>
  </channel>
</rss>
