Skip to content

fix(terminus): parallel tool calls formatting - #3520

Open
cmunley1 wants to merge 4 commits into
mainfrom
cmunley/terminus-lineage
Open

cmunley1 wants to merge 4 commits into
mainfrom
cmunley/terminus-lineage

Conversation

@cmunley1

@cmunley1 cmunley1 commented Sep 18, 2026 •

Copy link
Copy Markdown
Contributor

What does this PR do?

Fixes how terminus_2_agent turns a trajectory step with parallel tool calls into Responses items.

When the model issues several commands in one step, the terminal runs them as one batch and returns a single combined observation. trajectory_to_responses emitted one function_call per command but only one function_call_output, paired with the first call, so the other calls had no output.

Each call is now kept. The terminal screen is captured after all of a step's calls run, so it pairs with the step's last call, and the earlier calls get an empty function_call_output. Every function_call then has a matching output, as in the other harness agents (Claude Code, Codex, OpenCode). Steps with no observation are unchanged.

Validation

  • trajectory_to_responses checked on 2 calls / 1 result, 1 / 1, 2 / 0 and 2 / 2. Only the first case changes.
  • test_shared_terminal_observation_pairs_every_call added. ruff check and format clean.

Rollouts

10 seeded SWE-bench Verified rows, anyswe running terminus_2, a self-hosted DeepSeek V4.1 Flash policy. The two arms differ only in terminus_2_agent/output.py (current main vs this branch):

main this PR
reward 7/10 7/10
function_call items 576 704
calls with no matching output 320 (all 10 rows) 0
empty outputs 0 379
masked rollouts 0 0

Three raw rollouts with 3- and 4-command steps read in order: N bash_command calls, then an empty output for each earlier call id, then the screen output for the last call id, one to one. No multi-call step ended with mark_task_complete (0 of 241).

Compatibility and benchmark impact

Only steps with several calls and one shared observation change: they gain empty outputs for the calls before the last. No config change. Rewards do not change, since grading reads the task's repo state. Training token capture happens on the model server and does not render response.output.

@copy-pr-bot

copy-pr-bot Bot commented Sep 18, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@yaoyu-33 yaoyu-33 added area:agent Agent harnesses and Responses API agent behavior bug Something isn't working complexity:low Localized change in one scope with a small, straightforward review surface needs-review PR is ready for code review and waiting on a reviewer labels Sep 18, 2026
@github-actions github-actions Bot added the sla:triage-overdue Review assignment is over the one-business-day SLA label Sep 21, 2026
@cmunley1

Copy link
Copy Markdown
Contributor Author

/ok to test 93c5387

@cmunley1

Copy link
Copy Markdown
Contributor Author

/review

@svcnvidia-nemo-ci svcnvidia-nemo-ci left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SHIP — LGTM — no reliability concerns.

Reviewed both changed files, including batch construction and observation pairing, the regression tests, and affected response serialization and training-metadata paths. No actionable BLOCKER, RISK, or NOTE findings.

Static review only: tests and model rollouts were not executed. Harbor’s upstream trajectory producer is an external dependency absent from the mounted trees.

Note: formal approval is not available for this request, so this review is posted as a comment only.

Review generated by codex. This was a full review. Request a full review with /review reset=true.

@github-actions github-actions Bot removed the sla:triage-overdue Review assignment is over the one-business-day SLA label Oct 26, 2026
@cmunley1

Copy link
Copy Markdown
Contributor Author

/ok to test 94e45ea

@cmunley1

Copy link
Copy Markdown
Contributor Author

/review

@svcnvidia-nemo-ci svcnvidia-nemo-ci left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SHIP — LGTM — no reliability concerns.

Follow-up to the prior clean review: compared the previous pairing logic with the current converter, inspected both changed files and the retained regression assertions, and traced affected response serialization and training-metadata paths. Shared-observation batching and ordinary positional pairing remain intact. No actionable findings were established.

Static review only: tests and model rollouts were not executed. Harbor’s pinned trajectory producer is external and absent from the mounted trees, so its emitted fields could not be independently confirmed. Two completed child report payloads were unavailable; their producer and downstream-integration topics were independently inspected by the parent.

Note: formal approval is not available for this request, so this review is posted as a comment only.

Review generated by codex. This was a findings-only review. Request a full review with /review reset=true.

@cmunley1

Copy link
Copy Markdown
Contributor Author

/ok to test 1600e4c

@cmunley1

Copy link
Copy Markdown
Contributor Author

/review

@svcnvidia-nemo-ci svcnvidia-nemo-ci left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SHIP — LGTM — no concerns found.

Follow-up to the prior clean review: compared the previous batching logic with the current converter, inspected both changed files and the replacement and retained regression assertions, and traced affected response serialization and metadata paths. Shared-observation steps retain individual calls with matching outputs; zero-result steps and complete positional pairing remain unchanged. No actionable findings were established.

Static review only: tests and model rollouts were not executed. Harbor’s pinned trajectory producer is external to the mounted trees, so its emitted field guarantees could not be independently verified.

Note: formal approval is not available for this request, so this review is posted as a comment only.

Review generated by codex. This was a findings-only review. Request a full review with /review reset=true.

@cmunley1

Copy link
Copy Markdown
Contributor Author

/ok to test fd67629

@cmunley1

Copy link
Copy Markdown
Contributor Author

/review

@svcnvidia-nemo-ci svcnvidia-nemo-ci left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SHIP — LGTM — no concerns found.

Follow-up to the latest clean review: compared the previous pairing logic with the current converter, inspected both changed files and the updated and retained regression assertions, and traced affected response serialization, training metadata, and verifier-consumer paths. Shared-observation steps retain matching call/output IDs and place the screen on the last call; single-call, zero-result, and complete positional-pairing paths remain unchanged. No qualifying introduced regressions were established.

Static review only: tests and model rollouts were not executed. Harbor’s pinned trajectory producer is external to the mounted trees, so its emitted-field guarantees could not be independently verified. All three delegated inspections completed; two report payloads were unavailable, and their converter and producer/test topics were independently inspected by the parent.

Note: formal approval is not available for this request, so this review is posted as a comment only.

Review generated by codex. This was a findings-only review. Request a full review with /review reset=true.

Signed-off-by: Christian Munley <cmunley@nvidia.com>
The pinned Harbor Terminus-2 never sets source_call_id, so the branch was dead,
and in a mixed result list it could pair two outputs with one call.

Signed-off-by: Christian Munley <cmunley@nvidia.com>
Terminus captures one terminal screen per step. Instead of batching the
step's calls into one synthetic call, keep each call and pad the
missing outputs with empty strings, so every function_call has a
matching function_call_output like the other harnesses.

Signed-off-by: Christian Munley <cmunley@nvidia.com>
The terminal screen is captured after all of a step's calls run, so it
belongs on the last call. The earlier calls get the empty output.

Signed-off-by: Christian Munley <cmunley@nvidia.com>
@cmunley1
cmunley1 force-pushed the cmunley/terminus-lineage branch from fd67629 to a724f0c Compare October 27, 2026 08:34
@cmunley1

Copy link
Copy Markdown
Contributor Author

/ok to test a724f0c

@cmunley1

cmunley1 commented Nov 5, 2026

Copy link
Copy Markdown
Contributor Author

/review

@svcnvidia-nemo-ci svcnvidia-nemo-ci left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SHIP — LGTM — no concerns found.

This follows the latest clean bot review, which had no unresolved findings. I inspected both changed files, including the converter’s pairing logic and the new and retained regression assertions. For calls with explicit IDs and one shared observation, the current code emits matching outputs, leaves earlier outputs empty, and places the screen on the last call. Zero-result, single-call, and complete positional-pairing paths remain unchanged. I also traced affected response serialization, training capture, and verifier consumers; no qualifying regression was established.

The previously reviewed tree at fd676291b898c2b3d671bed4931a2c4563fbbe3d is unavailable, so I couldn't independently establish the inter-review delta. Harbor’s pinned trajectory producer is external to the mounted trees, so its field and screen-timing guarantees remain unverified. Static review only; I didn't execute tests or rollouts.

All three delegated inspections completed. Two report payloads were unavailable; I independently inspected their converter and producer/test topics.

Review generated by codex. This was a findings-only review. Request a full review with /review reset=true.

yaoyu-33 added a commit that referenced this pull request Nov 5, 2026
Review fixes for the Terminus 2 agent-session adapter:

- A rollout stop during seed, or one that ends the runner before it saves
  a result, is reported as an empty wall_time run with ng_rollout_stop
  instead of failing the activation (which was retried).
- The run's budget starts once the run has a concurrency slot, so a
  provider transport timeout after a long queue stays a failure.
- Terminus's own tmux commands run from / when a task command removes
  or moves the workdir, instead of ending the run as a harness error.
- Request instructions join Terminus's instruction; tools, tool_choice
  and parallel_tool_calls stay out of its model calls; a field the
  converter cannot represent is refused with 422 before the activation
  starts.
- An owned sandbox carries the provider's default metadata and session
  labels, gets its workdir created at setup, and its default TTL
  reserves both setup steps.
- A runner result that does not validate becomes an
  observation_capture_failed gap instead of failing the activation or
  close.
- Setup refuses an image without bash.
- Add configs/profiles/benchmark.yaml, like the other session harnesses,
  and register it with the shared profile tests.
- README: capability level Evaluation until #3520 lands, supported
  pairings, request-field rules, terminal lifetime, scoped absolute IP,
  limits, and the relation to terminus_2_sandboxed_agent.
- Tests: the real SandboxSession lifecycle over an in-memory sandbox
  (stops, close during a run, activation after close), /run refusals,
  runner max_turns, moved workdir, background process and imports
  without nemo_gym, and a regression test for each fix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: yaoyu-33 <yaoyu.094@gmail.com>
@nemo-automation-bot
nemo-automation-bot Bot requested a review from a team November 6, 2026 22:07
@kajalj22
kajalj22 removed the request for review from a team November 6, 2026 22:52

This branch was previously deployed

1 inactive deployment
public — a724f0c5 Deployed Oct 27, 2026 by copy-pr-bot[bot] via release / finalize / notify #7546
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:agent Agent harnesses and Responses API agent behavior bug Something isn't working complexity:low Localized change in one scope with a small, straightforward review surface needs-review PR is ready for code review and waiting on a reviewer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants