Summary
This RFC focuses on the agent integration item in roadmap #1846.
A generator-owned proxy server exposes an OpenAI-compatible Chat Completions
endpoint to agent frameworks such as Harbor. Instead of forwarding chat messages
directly to vLLM, the proxy renders messages into token IDs, sends exact prompt
IDs to SkyRL's inference engine, records sampled completion IDs and logprobs, and
returns a compatible chat response to the agent.
For subsequent turns, the proxy preserves sampled token IDs and safely appends
new environment messages using a model-aware renderer. The recorded trace is
finally converted to GeneratorOutput.
Functional Requirements
- Provide a
/chat/completions-compatible endpoint that requires Harbor to
change only its endpoint URL.
- Transparently run token-in/token-out inference through the SkyRL router and
record tokens, masks, logprobs, and potentially R3 data efficiently.
- Handle compaction and expose branch and transition views.
Design
Trace Design
Trace is the bookkeeping object for one trial attempt.
- Trace maintains a message graph. Each node stores one canonical message, its
parent ID, and the token, mask, and logprob delta introduced by that message.
- Trace finds the longest message prefix with an in-memory
(parent_id, message_hash) -> node_id index.
- Before reusing a prefix, commit verifies that node token deltas exactly match
the prompt IDs sent to inference.
- Every root-to-leaf path is one exact trajectory. Shared prefixes are stored
once.
- Trace exposes branch and transition views without duplicating the underlying
message graph.
- Trace's underlying data structure is similar to Trie, Therefore the complexity for matching is $O(m)$ where $m$ is the number of messages. We do hope the branch will not happen often so we will also maintain the hash of the latest context for fast match.
Proxy Design
HarborGenerator.generate() starts one FastAPI proxy. Concurrent Harbor
trials share that proxy.
- Each trial attempt creates a Trace and registers it with the proxy. Harbor's
model endpoint is changed to the proxy endpoint.
- For the first call, the proxy renders the complete prompt. For later calls,
Trace finds the latest matching message node and returns the new message tail.
- The renderer safely extends the previous exact
(prompt_ids, completion_ids)
with the new tail.
- The proxy runs token-in inference, commits the exact result to Trace, and then
returns the Chat Completions response to the agent.
Example
The easiest way to illustrate this design is the following example.
Round 1
- Proxy receives initial messages $R_1$ and renders prompt IDs $P_1$.
- Inference returns completion IDs $C_1$ and logprobs $L_1$. Renderer parses
$C_1$ into assistant message $M_1$.
- Trace commits one node per message in $R_1$, followed by a sampled $M_1$ node.
- Proxy returns $M_1$ to the agent.
Round 2
- Agent runs an environment step and receives message $T_1$.
- Agent sends $R_1 \Vert [M_1, T_1]$.
- Trace matches $R_1 \Vert [M_1]$, recovers exact $(P_1, C_1)$, and identifies
$[T_1]$ as the new tail.
- Renderer constructs $P_2 = \mathrm{Bridge}(P_1, C_1, [T_1])$.
- Inference returns $(C_2, L_2)$ and renderer parses assistant message $M_2$.
- Trace commits a nonsampled $T_1$ node and a sampled $M_2$ node. The path
reconstructs $P_2 \Vert C_2$.
- Proxy returns $M_2$ to the agent.
Round 3
- Agent sends $R_1 \Vert [M_1, T_1, M_2, T_2]$.
- Trace matches through $M_2$ and identifies $[T_2]$ as the new tail.
- Renderer constructs $P_3 = \mathrm{Bridge}(P_2, C_2, [T_2])$.
- Inference returns $(C_3, L_3)$ and renderer parses $M_3$.
- Trace commits $T_2$ and $M_3$. The path reconstructs $P_3 \Vert C_3$.
- Proxy returns $M_3$ to the agent.
Branch Cases
- Linear extension: Message and token prefixes match. New nodes extend the
current leaf.
- Compaction or rewritten history: Matching stops at the last unchanged
message. New messages form a branch from that node or the dummy root.
- Unsafe renderer extension: Renderer returns
None. The proxy fully renders
the prompt, and exact token comparison selects the longest reusable node.
- Retry: An identical retry reuses the in-flight or cached response and does
not commit new nodes.
Summary
This RFC focuses on the agent integration item in roadmap #1846.
A generator-owned proxy server exposes an OpenAI-compatible Chat Completions
endpoint to agent frameworks such as Harbor. Instead of forwarding chat messages
directly to vLLM, the proxy renders messages into token IDs, sends exact prompt
IDs to SkyRL's inference engine, records sampled completion IDs and logprobs, and
returns a compatible chat response to the agent.
For subsequent turns, the proxy preserves sampled token IDs and safely appends
new environment messages using a model-aware renderer. The recorded trace is
finally converted to
GeneratorOutput.Functional Requirements
/chat/completions-compatible endpoint that requires Harbor tochange only its endpoint URL.
record tokens, masks, logprobs, and potentially R3 data efficiently.
Design
Trace Design
Traceis the bookkeeping object for one trial attempt.parent ID, and the token, mask, and logprob delta introduced by that message.
(parent_id, message_hash) -> node_idindex.the prompt IDs sent to inference.
once.
message graph.
Proxy Design
HarborGenerator.generate()starts one FastAPI proxy. Concurrent Harbortrials share that proxy.
model endpoint is changed to the proxy endpoint.
Trace finds the latest matching message node and returns the new message tail.
(prompt_ids, completion_ids)with the new tail.
returns the Chat Completions response to the agent.
Example
The easiest way to illustrate this design is the following example.
Round 1
Round 2
reconstructs
Round 3
Branch Cases
current leaf.
message. New messages form a branch from that node or the dummy root.
None. The proxy fully rendersthe prompt, and exact token comparison selects the longest reusable node.
not commit new nodes.