feat: Switchyard OpenCode integration#2080
Open
drifold wants to merge 6 commits into
Open
Conversation
Adds opencode_source='opencode': runs upstream opencode headless with an opencode.json provider pointed at Switchyard (no fork), captures the session tree via opencode's native correlation headers (X-Session-Id / x-parent-session-id), and reconstructs root and subagent rollouts from the retrieved sessions. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: drifold <drifold@nvidia.com>
…mparison OpenCode re-serializes tool-call arguments differently across turns (compact vs. pretty-printed JSON), which failed the message-history extension check even though the tokens were contiguous. Canonicalize arguments for the comparison only; reconstructed training items keep the model's original arguments. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: drifold <drifold@nvidia.com>
…system-prompt instructions Signed-off-by: drifold <drifold@nvidia.com>
Adds switchyard_spawn_routing_profile: when set, each agent run spawns one dedicated token-capture Switchyard instance on a free port (stateful token injection requires all of a session's calls to reach one process), scopes records under the run's persistent_dir, and reaps the instance after trace retrieval in run(). Mutually exclusive with switchyard_base_url; behavior is unchanged when absent. The agent script is built after the instance URL is known, since it embeds the Switchyard routing. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: drifold <drifold@nvidia.com>
11 tasks
…nfigs as nv-opencode Signed-off-by: drifold <drifold@nvidia.com>
…ed context length Fetch the served model's max_model_len from Switchyard's /v1/models (surfaced there for token-capture routes) before building the opencode agent command, and declare limit.context/limit.output on the generated provider entry. Without limits, opencode requests a flat 32000 max_tokens and never compacts (limit.context defaults to 0); with them it budgets like any registry-known model. Output is reserved as min(32000, context // 4) so the compaction threshold (context - output) keeps most of the window for history. Fetch failure degrades to today's limit-less behavior with a warning. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: drifold <drifold@nvidia.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #2026 (base:
feature/switchyard-openhands-integration). Adds upstream opencode as a second harness for the Switchyard token-capture integration — same zero-fork principle as the OpenHands path — plus per-run Switchyard instance spawning for token injection.What
opencode run) with anopencode.jsonprovider pointed at Switchyard — no fork, no harness modification.X-Session-Idper (sub)agent session,x-parent-session-idlinking subagents to the root.subagent_trajectories.switchyard_spawn_routing_profilespawns one dedicated token-capture Switchyard instance per agent run on a free port — stateful token injection (feat: token-level capture for RL training (Switchyard ↔ NeMo Gym) Switchyard#63) requires all of a session's calls to reach one process — and reaps it after trace retrieval inrun().Zero-fork architecture
opencode.jsonprovider id is deliberately notopencode-prefixed — opencode only emits its native correlation headers for non-opencodeproviders; those headers are the whole capture contract.GET /v1/sessions(no harness logsread).
Activation and safety
opencode_source: nv-opencodeopencode_source: opencode, now default+ subagents reconstructswitchyard_trace_errorsetswitchyard_spawn_routing_profileabsentpersistent_dir, instance reaped after retrievalChanges
responses_api_agents/swe_agents/app.py—opencovider JSON), the opencode run command,_list_switchyard_sessions/_reconstruct_sessionssk_id steering via system-prompt instructions (worksaround an opencode quirk where it invents
task_ids).responses_api_agents/swe_agents/app.py—switchyard_spawn_routing_profile/switchyard_spawn_hostconfig (mutually exclusivewith
switchyard_base_url, validated fail-fast), specycle, agent-script build deferred until theinstance URL is known.responses_api_agents/swe_agents/app.py—openco toopencode` (upstream); config comment/docs updatedaccordingly.
responses_api_agents/swe_agents/configs/— splitnch_opencode.yaml/swebench_opencode_training.yamlnow target **upstream** opencode (opencode_source: gs move toswebench_nv_opencode.yaml/swebench_nv_opencode_training.yaml(`opencode_soured). Root README table regenerated.nemo_gym/switchyard_trace.py— canonicalize toolstory-extension comparison only (opencodere-serializes compact vs. pretty-printed JSON across turns); reconstructed items keep the model's original arguments.test_app.pyand`, plus 7 spawn-lifecycle tests (config conflicts,session minting + script rebuild, spawn/teardown with mocked subprocess, readiness-failure reaping).Dependencies
Requires the Switchyard side on NVIDIA-NeMo/Switchya
7b33c2c(native X-Session-Id capture),be0b2c5r the opencode capture path.7f20b2a,940b767,8307fd9(token-continuity ion use-case; spawn mode itself works withcapture-only).Testing
swe_agentsand `switchyardfidelity, 0% masked; with token injection enabled, buous across multi-turn reasoning + tool-calling
conversations (0 fallbacks), and an OpenHands-pattertiguity verification.
Changes from the live description are only: the openthe first two behavior-table rows (fork now keyed onnv-opencode; upstream noted as default), and two addault flip + config split). Everything else — including the - bullets, headings, dependency SHAs, and the vLs unchanged.