<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Agents | Randy Ardywibowo</title><link>https://ardywibowo.com/tag/agents/</link><atom:link href="https://ardywibowo.com/tag/agents/index.xml" rel="self" type="application/rss+xml"/><description>Agents</description><generator>Wowchemy (https://wowchemy.com)</generator><language>en-us</language><copyright>© Randy Ardywibowo</copyright><lastBuildDate>Mon, 27 Apr 2026 00:00:00 +0000</lastBuildDate><image><url>https://ardywibowo.com/media/icon_hu_d3bffc92642e4087.png</url><title>Agents</title><link>https://ardywibowo.com/tag/agents/</link></image><item><title>End-to-End Multi-Agent Reinforcement Learning</title><link>https://ardywibowo.com/post/end-to-end-multi-agent-reinforcement-learning-trace-view/</link><pubDate>Mon, 27 Apr 2026 00:00:00 +0000</pubDate><guid>https://ardywibowo.com/post/end-to-end-multi-agent-reinforcement-learning-trace-view/</guid><description>&lt;p&gt;Reinforcement Learning (RL) frameworks for language models often assume one rollout consists of one sequence. The model consecutively interacts with an environment by repeatedly receiving prompts and producing completions. Throughout this process, it receives a reward or rewards to update the model. This is the simplest possible interface, and for many RLHF or RLVR settings it is enough.&lt;/p&gt;
&lt;p&gt;But it is not the right abstraction for long-running tasks that involve multiple agents and compaction. Indeed, agents can interact with sub-agents, collaborate and debate with other agents, and compact continuations. In this setting, the rollout no longer involves a single sequence. Some of these sequences may share context. Others may be completely independent token streams. The final outcome is a property of the whole run.&lt;/p&gt;
&lt;p&gt;In the following, I will describe a good model for reasoning about these multi-agent trajectories, how to jointly train multiple agents, and why compaction is a special case of the same abstraction. I will then show that little needs to change to support this multi-agent joint training paradigm.&lt;/p&gt;
&lt;h2 id="sequences-and-traces"&gt;Sequences and Traces&lt;/h2&gt;
&lt;p&gt;A sequence is one model-generated stream of tokens. Write it as&lt;/p&gt;
&lt;div class="distill-math-block"&gt;\[s_i
=
(y_{i,1},\ldots,y_{i,T_i}).\]&lt;/div&gt;
&lt;p&gt;The sequence is generated under some local context \(h_i\):&lt;/p&gt;
&lt;div class="distill-math-block"&gt;\[y_{i,t}
\sim
\pi_\theta(\cdot \mid h_i, y_{i,&amp;lt;t}).\]&lt;/div&gt;
&lt;p&gt;In a simple chat setting, there may only be one such sequence. But in a real agent harness, there may be many:&lt;/p&gt;
&lt;div class="distill-math-block"&gt;\[\tau
=
\{s_1,\ldots,s_n\}.\]&lt;/div&gt;
&lt;p&gt;I will call this whole object a trace. The trace is the full execution of the harness: every model-generated sequence that contributed to the run, together with the environment state that connected them. Without loss of generality, we will assume outcome rewards \(R(\tau)\) are provided to the trace \(\tau\). The following formulations will hold for token-level rewards as well.&lt;/p&gt;
&lt;h2 id="policy-gradients-for-multiple-agents"&gt;Policy Gradients for Multiple Agents&lt;/h2&gt;
&lt;p&gt;The harness decides which agents are called, what tools they can use, when context is compacted, whether another agent is asked to critique the answer, and when the run terminates. It also decides what information is visible to each generated sequence. It is therefore useful to write the trace distribution as&lt;/p&gt;
&lt;div class="distill-math-block"&gt;\[\tau
\sim
H(\pi_\theta),\]&lt;/div&gt;
&lt;p&gt;where \(H\) is the harness. The harness may be a simple chat loop, but it may also be a large program involving many model calls, external tools, and state transitions. The Reinforcement Learning objective is thus:&lt;/p&gt;
&lt;div class="distill-math-block"&gt;\[\max_\theta
\;
\mathbb{E}_{\tau \sim H(\pi_\theta)}
\left[
R(\tau)
\right].\]&lt;/div&gt;
&lt;p&gt;The only difference is that the sample \(\tau\) is no longer assumed to be one contiguous sequence. It is the whole trace emitted by the harness.&lt;/p&gt;
&lt;p&gt;To see the gradient explicitly, first consider the case where every generated sequence comes from the same policy \(\pi_\theta\). If the trace contains generated sequences \(s_1,\ldots,s_n\), then the model-dependent part of the trace log-probability is the sum of the log-probabilities of the generated tokens:&lt;/p&gt;
&lt;div class="distill-math-block"&gt;\[\log \pi_\theta(\tau)
=
\sum_{i=1}^{n}
\sum_{t=1}^{T_i}
\log \pi_\theta
\left(
y_{i,t}
\mid
h_i, y_{i,&amp;lt;t}
\right)
&amp;#43; \text{terms independent of } \theta.\]&lt;/div&gt;
&lt;p&gt;So the policy-gradient update is&lt;/p&gt;
&lt;div class="distill-math-block"&gt;\[g
=
\mathbb{E}_{\tau}
\left[
A(\tau)
\sum_{i=1}^{n}
\sum_{t=1}^{T_i}
\nabla_\theta
\log \pi_\theta
\left(
y_{i,t}
\mid
h_i, y_{i,&amp;lt;t}
\right)
\right].\]&lt;/div&gt;
&lt;p&gt;This gives us a minimal algorithm implementation. Run the whole harness, collect every generated sequence in the trace, compute a trace-level reward or advantage, and apply that uniform reward to all trained tokens in the trace. This simple credit assignment method is unbiased. More careful credit assignment can come later, but note that it will only serve as variance reduction.&lt;/p&gt;
&lt;h2 id="compaction-as-a-special-case"&gt;Compaction as a Special Case&lt;/h2&gt;
&lt;p&gt;With this, we can see compaction as a special case of the above formulation. Before compaction, the model may have generated a long context:&lt;/p&gt;
&lt;div class="distill-math-block"&gt;\[s_1
=
(y_{1,1},\ldots,y_{1,T_1}).\]&lt;/div&gt;
&lt;p&gt;After compaction, the harness replaces the old context with a compressed state and continues:&lt;/p&gt;
&lt;div class="distill-math-block"&gt;\[h_2
=
C(h_1, s_1),
\qquad
s_2
\sim
\pi_\theta(\cdot \mid h_2).\]&lt;/div&gt;
&lt;p&gt;The second sequence may not share a token prefix with the first. In fact, it usually should not: the whole point of compaction is to replace the old transcript with a shorter representation. But this does not create a new RL problem. The pre-compaction sequence and the post-compaction sequence still belong to the same trace if the final outcome is assigned to the whole run:&lt;/p&gt;
&lt;div class="distill-math-block"&gt;\[\tau
=
\{s_1, s_2\}.\]&lt;/div&gt;
&lt;p&gt;So compaction is just a sequence boundary. It breaks the assumption that a rollout can be represented as one prefix-growing transcript, but it does not break trace-level training. Thus, we can view compaction as a special case of multi-agent training. A compacted continuation behaves like a new local agent invocation: it sees a different context, emits a new token stream, and contributes to the same final outcome.&lt;/p&gt;
&lt;h2 id="multi-turn-rl-and-shared-prefixes"&gt;Multi-Turn RL and Shared Prefixes&lt;/h2&gt;
&lt;p&gt;In ordinary multi-turn conversations, later model calls often contain earlier calls as exact token prefixes. For example:&lt;/p&gt;
&lt;div class="distill-math-block"&gt;\[\begin{aligned}
s_1
&amp;amp;=
\text{prompt} &amp;#43; \text{answer}_1,
\\
s_2
&amp;amp;=
\underbrace{\text{prompt} &amp;#43; \text{answer}_1}_{\text{shared prefix}}
&amp;#43;
\text{observation}_1
&amp;#43;
\text{answer}_2.
\end{aligned}\]&lt;/div&gt;
&lt;p&gt;If \(s_1\) is an exact prefix of \(s_2\), we can reuse the shared prefix computation and represent them as one longer training sequence while preserving labels for both generated spans. This avoids redundant computation on the shared prefix. In cases where the model&amp;rsquo;s sequence construction is not prefix stable, for example on models whose chat templates remove specific blocks such as thinking to preserve context length, one can fall back to the previous multi-agent formulation above and keep the sequences separate.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;We started by separating sequences from traces. A sequence is one model-generated token stream, while a trace is the full execution of the harness. The reward is attached to the trace, not necessarily to any single sequence. From this view, the policy gradient is still the usual policy gradient. The only change is that the score term sums over every trainable generated token in every sequence in the trace. This gives a simple unbiased estimator for multi-turn, multi-agent, tool-using, and compacted executions.&lt;/p&gt;</description></item></channel></rss>