examples: add swe-agent-harbor-daytona (Harbor sandboxes on Daytona) - #1919
Merged
Conversation
Adds a SWE-agent example whose task sandboxes run on Daytona cloud sandboxes instead of local Docker, so the trainer host needs no Docker daemon and no local task-image builds. The agent is terminus-2, which runs as a host process and appends both user and tool turns, so the session server needs --tito-allowed-append-roles user tool. That flag is the reason this needs its own launcher rather than reusing examples/swe-agent/run.py. generate.py and swe_agent_function.py are unchanged for Daytona-backed runs, so run.py puts the sibling example on PYTHONPATH instead of duplicating them.
Contributor
|
Caution The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased. |
Shi-Dong
commented
Jul 28, 2026
Shi-Dong
commented
Jul 28, 2026
Shi-Dong
commented
Jul 28, 2026
Shi-Dong
commented
Jul 28, 2026
- rename the example directory to swe-agent-harbor-daytona - name the harbor branch (harbor-miles-v0.20.0) in launch_agent_server.sh - trim the Daytona disk-quota discussion down to the sizing rule - refer to sibling files by their path from the repo root, not ../swe-agent - drop the troubleshooting row for a missing --tito-allowed-append-roles, which run.py always passes
- name the harbor branch (harbor-miles-v0.20.0) in launch_agent_server.sh - trim the Daytona disk-quota discussion down to the sizing rule - refer to sibling files by their path from the repo root, not ../swe-agent - drop the troubleshooting row for a missing --tito-allowed-append-roles, which run.py always passes - follow the directory rename through paths and default run names
Shi-Dong
commented
Jul 28, 2026
Shi-Dong
commented
Jul 28, 2026
- say up front that the example targets a single node of 8 H200 GPUs, and drop the now-duplicated hardware note from the launch section - reference examples/swe-agent as plain text rather than a relative link - spell out rollout/response_len/max instead of abbreviating it as .../max
nblintao
self-requested a review
August 3, 2026 23:13
nblintao
requested changes
Aug 4, 2026
| @@ -0,0 +1,284 @@ | |||
| """SWE-Agent launcher (GLM-4.7-Flash) for Harbor tasks on Daytona sandboxes. | |||
|
|
|||
| Same Miles <-> Harbor pipeline as examples/swe-agent, with two differences: | |||
Contributor
There was a problem hiding this comment.
Do you think we should rename swe-agent to something like swe-agent-harbor-docker? or should we should better keep the url slug unchanged?
Contributor
Author
There was a problem hiding this comment.
Good idea. Opened PR 2233 to handle the renaming.
| --host 0.0.0.0 \ | ||
| --port "$PORT" \ | ||
| --max-concurrent "$MAX_CONCURRENT" \ | ||
| --agent-timeout 5400 \ |
Contributor
There was a problem hiding this comment.
examples/swe-agent/swe_agent_function.py harcoded to
response = await asyncio.wait_for(
_post_agent_server(f"{agent_server_url}/run", request),
timeout=3600, # 1 hour max per trial
so the server will still be running after the agent function gives up.
Contributor
Author
There was a problem hiding this comment.
Opened a follow-up PR 2228 to address this comment.
…nt/run.py The launcher only existed because terminus-2 needed --tito-allowed-append-roles. #1818 removed that flag and added a test asserting it is rejected, so the launcher could no longer start a run. Nothing else in it was Daytona-specific: Daytona is selected entirely by the agent server's environment, which the trainer never sees. The four values it exposed as flags all defaulted to what examples/swe-agent/run.py already hardcodes, so reusing that launcher is behaviourally identical. Also corrects --router-external-host: it is substituted into the base URL handed to the agent and only has to resolve from the agent-server host, so a hostname is fine. The bind-time constraint belongs to --miles-host-ip.
4 tasks
nblintao
approved these changes
Aug 6, 2026
7 tasks
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.
Summary
Adds
examples/swe-agent-harbor-daytona, a variant ofexamples/swe-agentwhosetask sandboxes run on Daytona cloud sandboxes instead
of local Docker.
Two things differ from
examples/swe-agent:Docker daemon, no local image builds, and no local disk for task images. This
is the practical option when the trainer runs on a GPU node where you cannot
run Docker-in-Docker.
endpoint itself rather than from inside the sandbox. It appends both
userand
toolturns, so the session server needs--tito-allowed-append-roles user tool. Without it every append is rejected,trajectories collapse to a single turn, and the session server rolls them
back. That flag is the reason this needs its own launcher instead of a README
pointing at
examples/swe-agent/run.py.Everything else — TITO, the session server, GRPO, the reward path — is shared
with
examples/swe-agent, sorun.pyputs that example onPYTHONPATHandimports its
generate.pyandswe_agent_function.pyrather than keeping asecond copy in sync. Data prep also reuses
examples/swe-agent/download_and_process_data.py, with--agent-name terminus-2.Contents
README.mdrun.pylaunch_agent_server.shThe README also writes down the failure modes that cost the most time on a
multi-day run of this shape:
--rollout-max-response-lenandAGENT_MAX_OUTPUT_TOKENScap a singleturn, not the whole trajectory. Under
HARBOR_RESPONSE_LENGTH_POLICY=abortan over-cap turn ends the trial with none of that turn's tool calls performed,
so the trial scores 0 and dilutes its GRPO group.
rollout/raw_rewardfor the solve rate;rollout/rewardsis theGRPO-centered advantage and sits near zero by construction.
(the mtime of its
config.json), because writingexception.txtbumps thedirectory mtime and makes any mtime-sorted listing look like everything is
failing.
Two launcher settings that are hardcoded in
examples/swe-agent/run.pyareexposed as flags here, since they are the ones you actually end up tuning:
--rollout-max-response-lenand--max-tokens-per-gpu(plus--lrand--sglang-mem-fraction-static).--router-external-hostdefaults to the resolved local IP. sgl-router parsesthis into a Rust
SocketAddr, so it must be a numeric IP and a hostname failsto bind. The default is computed in a helper guarded against resolution
failure, so an unresolvable hostname cannot break module import.
Test plan
python -m py_compile examples/swe-agent-harbor-daytona/run.pybash -n examples/swe-agent-harbor-daytona/launch_agent_server.shruff check examples/swe-agent-harbor-daytona/run.pyof 8 H200 GPUs against Terminal-Bench 2 tasks, reaching non-zero
rollout/raw_rewardwith the agent server colocated on the trainer host.covers it.