Skip to content

feat(toolsandbox): add ToolSandbox multi-turn tool-use benchmark - #1949

Merged
ritaneves merged 18 commits into
NVIDIA-NeMo:mainfrom
pachmu:mbagdasarova/toolsandbox-integr
Jul 29, 2026
Merged

feat(toolsandbox): add ToolSandbox multi-turn tool-use benchmark#1949
ritaneves merged 18 commits into
NVIDIA-NeMo:mainfrom
pachmu:mbagdasarova/toolsandbox-integr

Conversation

@pachmu

@pachmu pachmu commented Jul 7, 2026

Copy link
Copy Markdown
Collaborator

Native gym port of apple/ToolSandbox — a stateful, conversational, tool-using benchmark — built on the aviary env pattern. The agent-under-test is the gym policy model driven by the toolsandbox_agent harness; the user simulator and the Python execution environment run inside the resources server; verify() is pure scoring. Reward is the milestone similarity in [0, 1] (0 if a minefield is hit).

  • resources_servers/toolsandbox — ToolSandboxResourcesServer with the aviary env lifecycle: seed_session -> obs + tools, /step(action) -> obs + done, /close (computes and caches the milestone/minefield breakdown), /verify (returns the cached reward). Each seed/step/close runs its role work inside its own asyncio.Task so concurrent episodes never share the vendored process-global ambient ExecutionContext.
  • responses_api_agents/toolsandbox_agent — thin fork of aviary_agent that forwards the whole model output (assistant text AND tool calls) to /step and lets the resources server decide done, so a natural-language turn routes to the user simulator instead of ending the rollout.
  • Vendored tool_sandbox/ (Apple custom source license) is used unchanged except for the conversation driver; scipy.optimize.linear_sum_assignment is replaced by a vendored dependency-free solver (scipy is excluded from the gym install), validated bit-identical to scipy. See tool_sandbox/VENDORING.md.
  • prepare_toolsandbox.py writes data/test.jsonl (one row per scenario index); committed example.jsonl is the 5-row smoke set.
  • toolsandbox.yaml wires the server + agent for local eval/training; toolsandbox_serve.yaml serves both for nemo-evaluator via the gym:// adapter.
  • Opt-in heavy deps live in requirements.txt (per-server .venv); ATTRIBUTIONS.md and pyproject ruff exclude cover the vendored tree.
  • Unit tests cover the scenario index, seed/step/close/verify, tool-call and natural-language routing, error observations, context isolation, the message cap, and user-sim extra_body flattening (19 tests).

@copy-pr-bot

copy-pr-bot Bot commented Jul 7, 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.

@pachmu
pachmu requested a review from a team as a code owner July 7, 2026 14:56
#
# NOTE: scipy is intentionally NOT listed. Upstream used
# scipy.optimize.linear_sum_assignment for milestone scoring, but scipy is in
# nemo-gym's [tool.uv] exclude-dependencies and uv strips it from any install

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.

This is no longer true - see PR #1832

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Removed

# limitations under the License.
"""Agent harness for the ToolSandbox resources server.

A thin fork of ``aviary_agent``. The difference: ToolSandbox is a

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.

Would it be possible to extend the aviary_agent instead? I think it's worth consolidating the two for future maintenance cost.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

A fork here means mostly the structure. I've checked and their logic is way different and it's hard to find something to make it generic.

Comment thread resources_servers/toolsandbox/README.md Outdated
gym env start \
--config resources_servers/toolsandbox/configs/toolsandbox.yaml \
--model-type openai_model \
++policy_base_url=https://openrouter.ai/api/v1 \

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.

These overrides can be replaced with flags, see the mapping

Suggested change
++policy_base_url=https://openrouter.ai/api/v1 \
--model-url https://openrouter.ai/api/v1 \

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fixed

Comment thread resources_servers/toolsandbox/README.md Outdated
--config resources_servers/toolsandbox/configs/toolsandbox.yaml \
--model-type openai_model \
++policy_base_url=https://openrouter.ai/api/v1 \
++policy_api_key=$OPEN_ROUTER_KEY \

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.

Suggested change
++policy_api_key=$OPEN_ROUTER_KEY \
--model-api-key $OPEN_ROUTER_KEY \

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fixed

Comment thread resources_servers/toolsandbox/README.md Outdated
--model-type openai_model \
++policy_base_url=https://openrouter.ai/api/v1 \
++policy_api_key=$OPEN_ROUTER_KEY \
++policy_model_name=qwen/qwen3.5-9b

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.

Suggested change
++policy_model_name=qwen/qwen3.5-9b
--model qwen/qwen3.5-9b

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fixed

@@ -0,0 +1,320 @@
# For licensing see accompanying LICENSE file.

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.

Consider removing this directory. Based on the info in VENDORING.md (L44) I conclude that this dir is not needed by the server. The maintenance cost might outweigh the benefits of having the ability to run offline checks.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Deleted

return kwargs


class OpenAIAPIAgent(BaseRole):

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.

If you decide to remove the cli dir, this class is no longer needed (I think)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Removed.

@pachmu pachmu closed this Jul 21, 2026
@pachmu
pachmu deleted the mbagdasarova/toolsandbox-integr branch July 21, 2026 08:43
@pachmu pachmu reopened this Jul 24, 2026
pachmu added 7 commits July 24, 2026 13:20
Native gym port of apple/ToolSandbox — a stateful, conversational, tool-using
benchmark — built on the aviary env pattern. The agent-under-test is the gym
policy model driven by the toolsandbox_agent harness; the user simulator and
the Python execution environment run inside the resources server; verify() is
pure scoring. Reward is the milestone similarity in [0, 1] (0 if a minefield
is hit).

- resources_servers/toolsandbox — ToolSandboxResourcesServer with the aviary
  env lifecycle: seed_session -> obs + tools, /step(action) -> obs + done,
  /close (computes and caches the milestone/minefield breakdown), /verify
  (returns the cached reward). Each seed/step/close runs its role work inside
  its own asyncio.Task so concurrent episodes never share the vendored
  process-global ambient ExecutionContext.
- responses_api_agents/toolsandbox_agent — thin fork of aviary_agent that
  forwards the whole model output (assistant text AND tool calls) to /step and
  lets the resources server decide done, so a natural-language turn routes to
  the user simulator instead of ending the rollout.
- Vendored tool_sandbox/ (Apple custom source license) is used unchanged except
  for the conversation driver; scipy.optimize.linear_sum_assignment is replaced
  by a vendored dependency-free solver (scipy is excluded from the gym install),
  validated bit-identical to scipy. See tool_sandbox/VENDORING.md.
- prepare_toolsandbox.py writes data/test.jsonl (one row per scenario index);
  committed example.jsonl is the 5-row smoke set.
- toolsandbox.yaml wires the server + agent for local eval/training;
  toolsandbox_serve.yaml serves both for nemo-evaluator via the gym:// adapter.
- Opt-in heavy deps live in requirements.txt (per-server .venv); ATTRIBUTIONS.md
  and pyproject ruff exclude cover the vendored tree.
- Unit tests cover the scenario index, seed/step/close/verify, tool-call and
  natural-language routing, error observations, context isolation, the message
  cap, and user-sim extra_body flattening (19 tests).

Signed-off-by: mbagdasarova <mbagdasarova@nvidia.com>
Signed-off-by: mbagdasarova <mbagdasarova@nvidia.com>
…iguration

Signed-off-by: mbagdasarova <mbagdasarova@nvidia.com>
Signed-off-by: mbagdasarova <mbagdasarova@nvidia.com>
Signed-off-by: mbagdasarova <mbagdasarova@nvidia.com>
…uilders

Signed-off-by: mbagdasarova <mbagdasarova@nvidia.com>
Signed-off-by: mbagdasarova <mbagdasarova@nvidia.com>
Comment thread ATTRIBUTIONS.md
| Component | Type | License | Author / Copyright | URL |
|------------|------|----------|--------------------|-----|
| **ToolSandbox** | Tool-use benchmark (scenarios, tools, sandbox, scoring) | Original: Apple MIT License (see full text below). NVIDIA modifications: Apache-2.0 | Copyright (C) 2024 Apple Inc.; Modifications Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES | https://github.com/apple/ToolSandbox |

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

@ritaneves
ritaneves self-requested a review July 27, 2026 15:29
ritaneves
ritaneves previously approved these changes Jul 27, 2026
@ritaneves

Copy link
Copy Markdown
Contributor

/ok to test

@copy-pr-bot

copy-pr-bot Bot commented Jul 27, 2026

Copy link
Copy Markdown

/ok to test

@ritaneves, there was an error processing your request: E1

See the following link for more information: https://docs.gha-runners.nvidia.com/cpr/e/1/

@ritaneves

Copy link
Copy Markdown
Contributor

/ok to test 639483a

pachmu added 7 commits July 27, 2026 18:00
Signed-off-by: mbagdasarova <mbagdasarova@nvidia.com>
…PDX license information

Signed-off-by: mbagdasarova <mbagdasarova@nvidia.com>
… modifications

Signed-off-by: mbagdasarova <mbagdasarova@nvidia.com>
…ications

Signed-off-by: mbagdasarova <mbagdasarova@nvidia.com>
…nd tests

Signed-off-by: mbagdasarova <mbagdasarova@nvidia.com>
Signed-off-by: mbagdasarova <mbagdasarova@nvidia.com>
@pachmu
pachmu force-pushed the mbagdasarova/toolsandbox-integr branch from 639483a to 41d17f8 Compare July 27, 2026 16:05
@ritaneves
ritaneves self-requested a review July 27, 2026 16:14
@ritaneves
ritaneves merged commit 8bbcb6b into NVIDIA-NeMo:main Jul 29, 2026
15 checks passed
OlegSudakov pushed a commit to OlegSudakov/Gym that referenced this pull request Aug 7, 2026
…DIA-NeMo#1949)

Native gym port of apple/ToolSandbox — a stateful, conversational,
tool-using benchmark — built on the aviary env pattern. The
agent-under-test is the gym policy model driven by the toolsandbox_agent
harness; the user simulator and the Python execution environment run
inside the resources server; verify() is pure scoring. Reward is the
milestone similarity in [0, 1] (0 if a minefield is hit).

- resources_servers/toolsandbox — ToolSandboxResourcesServer with the
aviary env lifecycle: seed_session -> obs + tools, /step(action) -> obs
+ done, /close (computes and caches the milestone/minefield breakdown),
/verify (returns the cached reward). Each seed/step/close runs its role
work inside its own asyncio.Task so concurrent episodes never share the
vendored process-global ambient ExecutionContext.
- responses_api_agents/toolsandbox_agent — thin fork of aviary_agent
that forwards the whole model output (assistant text AND tool calls) to
/step and lets the resources server decide done, so a natural-language
turn routes to the user simulator instead of ending the rollout.
- Vendored tool_sandbox/ (Apple custom source license) is used unchanged
except for the conversation driver; scipy.optimize.linear_sum_assignment
is replaced by a vendored dependency-free solver (scipy is excluded from
the gym install), validated bit-identical to scipy. See
tool_sandbox/VENDORING.md.
- prepare_toolsandbox.py writes data/test.jsonl (one row per scenario
index); committed example.jsonl is the 5-row smoke set.
- toolsandbox.yaml wires the server + agent for local eval/training;
toolsandbox_serve.yaml serves both for nemo-evaluator via the gym://
adapter.
- Opt-in heavy deps live in requirements.txt (per-server .venv);
ATTRIBUTIONS.md and pyproject ruff exclude cover the vendored tree.
- Unit tests cover the scenario index, seed/step/close/verify, tool-call
and natural-language routing, error observations, context isolation, the
message cap, and user-sim extra_body flattening (19 tests).

---------

Signed-off-by: mbagdasarova <mbagdasarova@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants